/* Copyright 2011-2013 The MathWorks, Inc. */ #include /* sprintf */ #include /* variable argument lists */ #include "xil_interface_common.h" #include "xil_data_stream.h" #include "xil_common.h" #include "target_io.h" #include "rtwtypes.h" /* test for ISO C99 or greater, which supports vsnprintf * * WARNING: if the compiler is ANSI C90 then we use vsprintf instead. * Therefore, it is possible to overrun the buffer so the * caller must take care not to exceed the buffer size! */ #if __STDC_VERSION__ >= 199901L #define VSNPRINTF_AVAILABLE #endif #ifndef TARGET_IO_BUFFER_SIZE /* default buffer size is large enough for most use cases */ #define TARGET_IO_BUFFER_SIZE 64 #endif #ifndef TARGET_IO_MAX_FILE_ID /* -1 avoids warning about the comparison that is done * in targetFopen * * note that MAX_uint16_T will be limited to uint16 max * even when portable word sizes maps uint16 to a larger * type such as uint32 on the SHARC */ #define TARGET_IO_MAX_FILE_ID (MAX_uint16_T - 1) #endif typedef enum {TARGET_IO_SUCCESS=0, TARGET_IO_BUFFER_TRUNC } TARGET_IO_ERROR_ID; static char targetStdioBuffer[TARGET_IO_BUFFER_SIZE]; #ifdef HOST_WORD_ADDRESSABLE_TESTING static MemUnit_T hostWordStdioBuffer[TARGET_IO_BUFFER_SIZE]; #endif /* fid is the file id on target and is limited to TARGET_IO_MAX_FILE_ID */ static uint16_T fid = 0; /* call xilWriteData and check for errors */ static void targetWriteDataWithErrorCheck(const MemUnit_T *, uint32_T); #ifdef HOST_WORD_ADDRESSABLE_TESTING static void targetWriteDataWithCharToMemUnitWidening(const char *, MemUnit_T *, uint16_T); #endif /* HOST_WORD_ADDRESSABLE_TESTING */ void targetWriteDataWithErrorCheck(const MemUnit_T * data, uint32_T size) { if (xilWriteData(data, size) != XIL_DATA_STREAM_SUCCESS) { for (;;) { /* fatal comms error */ } } } #ifdef HOST_WORD_ADDRESSABLE_TESTING static void targetWriteDataWithCharToMemUnitWidening(const char *pCharBuff, MemUnit_T *pMemUnitBuff, uint16_T buffSize) { uint16_T i; for(i=0;i= TARGET_IO_BUFFER_SIZE)) { /* set error id if error or buffer overruns */ errorId = TARGET_IO_BUFFER_TRUNC; /* do not send any data */ printSize = 0; } else { /* add one for the terminating null character */ printSize = (uint16_T) vsPrintSize + 1; } va_end(argptr); /* send response id */ targetWriteDataWithErrorCheck(&responseId, sizeof(responseId)); /* send error id */ targetWriteDataWithErrorCheck(&errorId, sizeof(errorId)); /* send printSize */ targetWriteDataWithErrorCheck((MemUnit_T *) &printSize, sizeof(printSize)); /* send data */ if (printSize > 0) { #ifdef HOST_WORD_ADDRESSABLE_TESTING targetWriteDataWithCharToMemUnitWidening(&targetStdioBuffer[0], &hostWordStdioBuffer[0], printSize); #else targetWriteDataWithErrorCheck((MemUnit_T *)&targetStdioBuffer[0], printSize); #endif } return; } /* Forward a fopen back to the host. * * fid is used on target to act as a valid * "file descriptor". */ unsigned short targetFopen(const char * fileName) { uint16_T fileNameSize; MemUnit_T responseId = XIL_RESPONSE_FOPEN; /* size of file name string */ fileNameSize = (uint16_T) strlen(fileName); /* add one for the terminating null character */ fileNameSize++; /* check bounds and reset to 0 if necessary which will trigger an error * on the host */ if(fid > TARGET_IO_MAX_FILE_ID) { fid = 0; } /* send response id */ targetWriteDataWithErrorCheck(&responseId, sizeof(responseId)); /* send file id */ targetWriteDataWithErrorCheck((MemUnit_T *)&fid, sizeof(fid)); /* send size of file name string */ targetWriteDataWithErrorCheck((MemUnit_T *)&fileNameSize, sizeof(fileNameSize)); #ifdef HOST_WORD_ADDRESSABLE_TESTING /* in case the total size is bigger than the hostWordStdioBuffer, send in * multiple chunks */ { while (fileNameSize > 0) { uint16_T transferSize = MIN(fileNameSize, TARGET_IO_BUFFER_SIZE); /* send file name string */ targetWriteDataWithCharToMemUnitWidening(fileName, &hostWordStdioBuffer[0], transferSize); fileNameSize -= transferSize; fileName += transferSize; } } #else /* send file name string */ targetWriteDataWithErrorCheck((const MemUnit_T *)fileName, fileNameSize); #endif /* return fid, THEN increment it */ return (unsigned short) (fid++); /* unsigned short is at least 16-bits * wide. See header file for more * information on why this cast is * required. */ } void targetFprintf(unsigned short targetFid, const char * fmt, ...) { va_list argptr; uint16_T fprintSize; int vsFprintSize; MemUnit_T responseId = XIL_RESPONSE_FPRINTF; MemUnit_T errorId = TARGET_IO_SUCCESS; const uint16_T targetFid16 = (uint16_T) targetFid; /* We only use the * lowermost 16 bits of * targetFid. unsigned * int is guaranteed to * be at least 16 bits * wide. See header file * for more information * on why this cast is * required. */ va_start(argptr, fmt); #ifdef VSNPRINTF_AVAILABLE /* size arg includes '\0', return value does not */ vsFprintSize = vsnprintf(&targetStdioBuffer[0], TARGET_IO_BUFFER_SIZE, fmt, argptr); #else vsFprintSize = vsprintf(&targetStdioBuffer[0], fmt, argptr); #endif if ((vsFprintSize < 0) || (vsFprintSize >= TARGET_IO_BUFFER_SIZE)) { /* set error id if error or buffer overruns */ errorId = TARGET_IO_BUFFER_TRUNC; /* do not send any data */ fprintSize = 0; } else { /* add one for the terminating null character */ fprintSize = (uint16_T) vsFprintSize + 1; } va_end(argptr); /* send response id */ targetWriteDataWithErrorCheck(&responseId, sizeof(responseId)); /* send error id */ targetWriteDataWithErrorCheck(&errorId, sizeof(errorId)); /* send file id*/ targetWriteDataWithErrorCheck((const MemUnit_T *)&targetFid16, sizeof(targetFid16)); /* send fprintSize */ targetWriteDataWithErrorCheck((MemUnit_T *)&fprintSize, sizeof(fprintSize)); if (fprintSize > 0) { #ifdef HOST_WORD_ADDRESSABLE_TESTING /* send data */ targetWriteDataWithCharToMemUnitWidening(&targetStdioBuffer[0], &hostWordStdioBuffer[0], fprintSize); #else /* send data */ targetWriteDataWithErrorCheck((MemUnit_T *)&targetStdioBuffer[0], fprintSize); #endif } return; }