FreeCalypso > hg > freecalypso-sw
view gsm-fw/gpf/tst_drv/usart.c @ 871:a5c8f48003cd
rvinterf: client programs can now selectively stop receiving packets of a
particular RVTMUX type
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Fri, 29 May 2015 06:29:38 +0000 |
parents | 5d1e22505446 |
children |
line wrap: on
line source
/* +------------------------------------------------------------------------------ | File: usart.c +------------------------------------------------------------------------------ | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This Modul defines functions for actual or simulated | USART comunication between two PS-Frames. | Use US_set_mode() to select actual USART under windows95 or | under windowsNT, or to select simulated USART under win95/NT +----------------------------------------------------------------------------- */ #ifndef __USART_C__ #define __USART_C__ #endif /*==== INCLUDES ===================================================*/ #include <windows.h> #ifndef _VXWORKS_ #include <stdarg.h> #endif #include <stdio.h> #include "typedefs.h" #include "usart.h" #include "printtofile.h" /*==== CONSTANTS ==================================================*/ #define COM_ERROR (CE_FRAME | CE_IOE | CE_OVERRUN) #define XON 0x11 #define XOFF 0x13 #define READER_THREAD_EXIT_CODE 4711 #define USART_BUFFER_SIZE 0x10000 /* 65536 */ #define FILE_MAX_CHUNK 0x0ffff #define FILE_SLOW_DOWN 0x01 #ifdef _TOOLS_ #define USART_SEND_TIMEOUT 60000 #define USART_RCV_TIMEOUT 120000 #else /* _TOOLS_ */ #define USART_SEND_TIMEOUT INFINITE #define USART_RCV_TIMEOUT INFINITE #endif /* _TOOLS_ */ /*==== TYPES ======================================================*/ typedef struct { UBYTE Connects; UBYTE Type; USHORT CH1_numOfBytes; USHORT CH2_numOfBytes; UBYTE CH1_CTS; UBYTE CH2_CTS; UBYTE CH1_data[USART_BUFFER_SIZE]; UBYTE CH2_data[USART_BUFFER_SIZE]; } T_USARTStream; /*==== EXPORT =====================================================*/ /*==== PRIVATE ====================================================*/ /*==== VARIABLES ==================================================*/ static int m_mode=UT_MODE_NT; static long int m_send_timeout=(long int)USART_SEND_TIMEOUT; static long int m_rcv_timeout =(long int)USART_RCV_TIMEOUT; static int first_ut_init = 1; static FILE* m_file=NULL; static OVERLAPPED gWriteOverLap; static OVERLAPPED gReadOverLap; static int ReaderThreadExitRequest = FALSE; LOCAL void (*ReceiveCallback)(void) = NULL; static int initialized = FALSE; #ifdef COM_AUTOSEARCH static int P = 0; #endif #ifdef DEBUG_USART static int usart_in, usart_out; #endif T_USARTStream *Stream; HANDLE SemCH1_full; HANDLE SemCH2_full; HANDLE SemCH1_empty; HANDLE SemCH2_empty; HANDLE USARTMemHandle; HANDLE *semRCVFull=0, *semRCVEmpty=0; HANDLE *semSNDFull=0, *semSNDEmpty=0; HANDLE ut_sema_handle; UBYTE *InBuffer, *OutBuffer, *readPointer; USHORT *InCounter, *OutCounter; UBYTE *CTS = NULL; static HANDLE hComDev = INVALID_HANDLE_VALUE; static HANDLE hThread = INVALID_HANDLE_VALUE; static int mem_closed = TRUE; static int cls_cnt = 0; static int snd_cnt = 0; /*==== FUNCTIONS ==================================================*/ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : US_set_mode | +--------------------------------------------------------------------+ PURPOSE : With this function you can select the UART mode #define US_MODE_95 1 #define US_MODE_NT 2 #define US_MODE_SIM 3 #define US_MODE_FILE 4 */ void US_set_mode(int mode) { m_mode=mode; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : US_set_mode | +--------------------------------------------------------------------+ PURPOSE : With this function get the seleced UART mode #define US_MODE_95 1 #define US_MODE_NT 2 #define US_MODE_SIM 3 #define US_MODE_FILE 4 */ int US_get_mode() { return m_mode; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USARTSIM | | STATE : code ROUTINE : unlockUSARTMemory | +--------------------------------------------------------------------+ PURPOSE : unlocks the previously locked shared memory area. */ LOCAL void markRCVBufferEmpty (void) { ReleaseSemaphore (*semRCVEmpty, 1, NULL); } LOCAL void markSNDBufferFull (void) { ReleaseSemaphore (*semSNDFull, 1, NULL); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USARTSIM | | STATE : code ROUTINE : waitForSNDBufferEmpty | +--------------------------------------------------------------------+ PURPOSE : waits for send buffer becoming empty RETURNS : 0 .. send buffer is empty -1 .. given up */ LOCAL int waitForSNDBufferEmpty (void) { if (WaitForSingleObject (*semSNDEmpty, m_send_timeout) NEQ WAIT_OBJECT_0) { int err = GetLastError(); PrintToFile("USART: error code %d\n", err); PrintToFile("USART: giving up sending with %d ms timeout :-(\n", m_send_timeout); return -1; /* give up */ } return 0; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USARTSIM | | STATE : code ROUTINE : createUSARTMemory | +--------------------------------------------------------------------+ PURPOSE : Create two pipes for byte oriented data exchange between two win32 processes */ LOCAL void *createUSARTMemory (char *name, ULONG size) { char newname[40]; /* * create two Semaphores pairs to protect the send data to be * overwritten before they have read by the receiver */ sprintf (newname, "%s_CH1empty", name); SemCH1_empty = CreateSemaphore (NULL, 1, 1, newname); if (SemCH1_empty EQ NULL) return NULL; sprintf (newname, "%s_CH1full", name); SemCH1_full = CreateSemaphore (NULL, 0, 1, newname); if (SemCH1_full EQ NULL) return NULL; sprintf (newname, "%s_CH2empty", name); SemCH2_empty = CreateSemaphore (NULL, 1, 1, newname); if (SemCH2_empty EQ NULL) return NULL; sprintf (newname, "%s_CH2full", name); SemCH2_full = CreateSemaphore (NULL, 0, 1, newname); if (SemCH2_full EQ NULL) return NULL; /* * create a shared memory area */ sprintf (newname, "UT_Mem_%s", name); USARTMemHandle = CreateFileMapping ( (HANDLE) 0xffffffff, /* memory-mapped */ NULL, /* no security */ PAGE_READWRITE, /* read/write access */ (DWORD) 0, /* memory size */ (DWORD) size, newname /* name of sh. mem */ ); if (USARTMemHandle EQ NULL) return NULL; /* * map the shared memory area into the address space of the process * and return the startaddress. */ return MapViewOfFile (USARTMemHandle, FILE_MAP_WRITE, 0, 0, 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USARTSIM | | STATE : code ROUTINE : openUSARTMemory | +--------------------------------------------------------------------+ PURPOSE : open a shared memory area for character exchange between two WIN32 processes */ LOCAL void *openUSARTMemory (char *name, ULONG size) { char newname[30]; /* * open the Semaphores */ sprintf (newname, "%s_CH1empty", name); SemCH1_empty = OpenSemaphore (SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, FALSE, newname); if (SemCH1_empty EQ NULL) return NULL; sprintf (newname, "%s_CH1full", name); SemCH1_full = OpenSemaphore (SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, FALSE, newname); if (SemCH1_full EQ NULL) return NULL; sprintf (newname, "%s_CH2empty", name); SemCH2_empty = OpenSemaphore (SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, FALSE, newname); if (SemCH2_empty EQ NULL) return NULL; sprintf (newname, "%s_CH2full", name); SemCH2_full = OpenSemaphore (SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, FALSE, newname); if (SemCH2_full EQ NULL) return NULL; /* * open the shared memory area */ sprintf (newname, "UT_Mem_%s", name); USARTMemHandle = OpenFileMapping (FILE_MAP_WRITE, FALSE, newname); /* name of sh. mem */ if (USARTMemHandle EQ NULL) return NULL; /* * map the shared memory area into the address space of the process * and return the startaddress. */ return MapViewOfFile (USARTMemHandle, FILE_MAP_WRITE, 0, 0, 0); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : waitForRCVBufferFull | +--------------------------------------------------------------------+ PURPOSE : This function waits until an incoming character is signaled with the EV_RXCHAR Event */ LOCAL void waitForRCVBufferFull (void) { switch (m_mode) { case US_MODE_95: { static COMSTAT stComStat; static DWORD dwErrors; static DWORD EvtMask = 0; BOOL validReceive = FALSE; do { SetCommMask (hComDev, EV_RXCHAR) ; WaitCommEvent (hComDev, &EvtMask, NULL); ClearCommError (hComDev, &dwErrors, &stComStat); if (dwErrors & COM_ERROR) PurgeComm (hComDev, PURGE_RXCLEAR|PURGE_RXABORT); else validReceive = TRUE; } while (!validReceive); break; } case US_MODE_NT: { static COMSTAT stComStat; static DWORD dwErrors; static DWORD EvtMask = 0; BOOL validReceive = FALSE; do { SetCommMask (hComDev, EV_RXCHAR) ; WaitCommEvent (hComDev, &EvtMask, NULL); ClearCommError (hComDev, &dwErrors, &stComStat); if (dwErrors & COM_ERROR) PurgeComm (hComDev, PURGE_RXCLEAR|PURGE_RXABORT); else validReceive = TRUE; } while (!validReceive && !ReaderThreadExitRequest); break; } case US_MODE_SIM: { if (WaitForSingleObject (*semRCVFull, m_rcv_timeout) NEQ WAIT_OBJECT_0) { PrintToFile("USART: no stack connected\n"); } break; } default: break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : _readerThread | +--------------------------------------------------------------------+ PURPOSE : This function is the central signal handling function. It is installed as a thread and waits for the occurance of an event and then calls the installed callback function of the application. */ LOCAL void _readerThread (void) { while (ReaderThreadExitRequest == FALSE) { waitForRCVBufferFull (); ReceiveCallback (); } ReaderThreadExitRequest = FALSE; ExitThread(READER_THREAD_EXIT_CODE); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : convertBaudrate | +--------------------------------------------------------------------+ PURPOSE : This function convert the constants for the baudrates in usart.h into the equvalent constants for WIN32 comm. */ LOCAL DWORD convertBaudrate (DWORD br) { switch (br) { case US_BAUD_256000: return CBR_256000; case US_BAUD_128000: return CBR_128000; case US_BAUD_115200: return CBR_115200; case US_BAUD_57600: return CBR_57600; case US_BAUD_38400: return CBR_38400; case US_BAUD_19200: return CBR_19200; case US_BAUD_14400: return CBR_14400; case US_BAUD_9600: return CBR_9600; case US_BAUD_4800: return CBR_4800; case US_BAUD_2400: return CBR_2400; case US_BAUD_1200: return CBR_1200; case US_BAUD_600: return CBR_600; case US_BAUD_300: return CBR_300; default: /* no CBR_xxx constant found -> return value itsself */ return br; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : sioInit | +--------------------------------------------------------------------+ PURPOSE : This function opens the given comm port and initiializes the DCB with baudrate and flowcontrol parameters. */ LOCAL BOOL sioInit (int portNr, unsigned int baudrate, unsigned int bufSize, char flowCtrl) { char szPort[10]; DCB stDCB; COMMTIMEOUTS stTimeout ; DWORD dwErrorFlags; COMSTAT stComStat; sprintf (szPort, "\\\\.\\COM%d", portNr) ; // ------------------------------------ // open the communication device // ------------------------------------ if (m_mode==UT_MODE_NT) { hComDev = CreateFile ( szPort, GENERIC_READ | GENERIC_WRITE, 0, /* exclusive access */ NULL, /* no security attrs */ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); } else { hComDev = CreateFile ( szPort, GENERIC_READ | GENERIC_WRITE, 0, // exclusive access NULL, // no security attrs OPEN_EXISTING, 0, NULL ); } if (hComDev EQ INVALID_HANDLE_VALUE) return FALSE; // device not available if (m_mode==UT_MODE_NT) { gReadOverLap.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if (!gReadOverLap.hEvent) return ( FALSE ); gReadOverLap.Offset = 0; gReadOverLap.OffsetHigh = 0; gWriteOverLap.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if (!(gWriteOverLap.hEvent)) return ( FALSE ); gWriteOverLap.Offset = 0; gWriteOverLap.OffsetHigh = 0; } // ------------------------------------ // get any early notifications // ------------------------------------ SetCommMask (hComDev, EV_RXCHAR); // ------------------------------------ // setup device buffers // ------------------------------------ SetupComm (hComDev, bufSize, bufSize ); // ------------------------------------ // purge any information in the buffer // ------------------------------------ PurgeComm (hComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); // ------------------------------------ // setup up and enable communication // device. If not possible close // communication and abort function. // ------------------------------------ if (!GetCommState (hComDev, &stDCB)) { SetCommMask (hComDev, 0); CloseHandle (hComDev); return FALSE; } stDCB.DCBlength = sizeof (stDCB); // sizeof(DCB) switch (flowCtrl) { case 'N': stDCB.fOutxCtsFlow = FALSE; stDCB.fOutxDsrFlow = FALSE; stDCB.fDtrControl = DTR_CONTROL_DISABLE; stDCB.fRtsControl = RTS_CONTROL_DISABLE; break; case 'D': stDCB.fOutxCtsFlow = FALSE; stDCB.fOutxDsrFlow = TRUE; stDCB.fDtrControl = DTR_CONTROL_HANDSHAKE; stDCB.fRtsControl = RTS_CONTROL_DISABLE; stDCB.XonLim = 0; stDCB.XoffLim = 50; break; case 'R': stDCB.fOutxCtsFlow = TRUE; stDCB.fOutxDsrFlow = FALSE; stDCB.fDtrControl = DTR_CONTROL_DISABLE; stDCB.fRtsControl = RTS_CONTROL_HANDSHAKE; stDCB.XonLim = 0; stDCB.XoffLim = 50; break; case 'P': stDCB.fOutxCtsFlow = FALSE; stDCB.fOutxDsrFlow = FALSE; stDCB.fDtrControl = DTR_CONTROL_ENABLE; stDCB.fRtsControl = RTS_CONTROL_DISABLE; break; case 'V': if (m_mode==US_MODE_NT) { stDCB.fOutxCtsFlow = FALSE; stDCB.fOutxDsrFlow = FALSE; stDCB.fDtrControl = DTR_CONTROL_ENABLE; stDCB.fRtsControl = RTS_CONTROL_ENABLE; break; } /*lint -fallthrough*/ /* go on if not US_MODE_NT */ default: return FALSE; } fprintf (stdout,"flow control: %c ...", flowCtrl); stDCB.BaudRate = baudrate; // current baud rate stDCB.fBinary = TRUE; // binary mode, no EOF check stDCB.fParity = FALSE; // enable parity checking stDCB.fDsrSensitivity = FALSE; // DSR sensitivity stDCB.fTXContinueOnXoff = FALSE; // XOFF continues Tx stDCB.fOutX = FALSE; // XON/XOFF out flow control stDCB.fInX = FALSE; // XON/XOFF in flow control stDCB.fErrorChar = FALSE; // enable error replacement stDCB.fNull = FALSE; // enable null stripping stDCB.fAbortOnError = FALSE; // abort reads/writes on error stDCB.ByteSize = 8; // number of bits/byte, 4-8 stDCB.Parity = NOPARITY; // 0-4=no,odd,even,mark,space stDCB.StopBits = ONESTOPBIT;// 0,1,2 = 1, 1.5, 2 stDCB.XonChar = 0; // Tx and Rx XON character stDCB.XoffChar = 0; // Tx and Rx XOFF character stDCB.ErrorChar = 0; // error replacement character stDCB.EofChar = 0; // end of input character stDCB.EvtChar = 0; // received event character if (!SetCommState (hComDev, &stDCB)) { SetCommMask (hComDev, 0); CloseHandle (hComDev); return FALSE; } if (!GetCommTimeouts (hComDev, &stTimeout)) return FALSE; stTimeout.WriteTotalTimeoutConstant = 0xffff; stTimeout.WriteTotalTimeoutMultiplier = 0xffff; stTimeout.ReadTotalTimeoutConstant = 0xffff; stTimeout.ReadIntervalTimeout = 0; stTimeout.ReadTotalTimeoutMultiplier = 0xffff; if (!SetCommTimeouts (hComDev, &stTimeout)) return FALSE; PurgeComm (hComDev, PURGE_RXCLEAR |PURGE_TXCLEAR |PURGE_TXABORT |PURGE_RXABORT); ClearCommError (hComDev, &dwErrorFlags, &stComStat); return TRUE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : sioRead | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL BOOL sioRead (BYTE *bpRXBuffer, // RX Buffer DWORD *pdwLength) // IN: Bytes to read { DWORD dwBytesToRead = *pdwLength ; DWORD dwErrorFlags; COMSTAT stComStat; if (hComDev == INVALID_HANDLE_VALUE OR *pdwLength == 0) return FALSE; // device not available if (m_mode==US_MODE_NT) { if (!ReadFile (hComDev, bpRXBuffer, dwBytesToRead, pdwLength, &gReadOverLap)) { // if there was a problem if (GetLastError() == ERROR_IO_PENDING) { /* asynchronous i/o is still in progress */ /* do something else for a while */ /* check on the results of the asynchronous read */ if (GetOverlappedResult(gReadOverLap.hEvent, &gReadOverLap, pdwLength, TRUE)) return TRUE; } ClearCommError(hComDev, &dwErrorFlags, &stComStat); return FALSE; } else { ClearCommError(hComDev, &dwErrorFlags, &stComStat); } } else { if (!ReadFile (hComDev, bpRXBuffer, dwBytesToRead, pdwLength, NULL)) { // if there was a problem ClearCommError(hComDev, &dwErrorFlags, &stComStat); return FALSE; } } #ifdef DEBUG_USART { char traceBuf[255]; unsigned int i; traceBuf[0] = '\0'; if (bpRXBuffer[0] EQ 0xff) { Sleep(1); } for (i=0; i<*pdwLength; i++) { if (!isprint (bpRXBuffer[i])) { sprintf (traceBuf+strlen(traceBuf), "[%02x]%c", (USHORT) bpRXBuffer[i], ((bpRXBuffer[i] EQ '\n') ? '\n' : ' ') ); } else sprintf (traceBuf+strlen(traceBuf), "%c", bpRXBuffer[i]); if (strlen (traceBuf) > 200) { write (usart_in, traceBuf, strlen (traceBuf)); traceBuf[0] = '\0'; } } /* * write the string to the tracefile */ write (usart_in, traceBuf, strlen (traceBuf)); } #endif return TRUE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : sioWrite | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL BOOL sioWrite (BYTE *bpTXBuffer, // TX Buffer DWORD *pdwLength) // IN: Bytes to read { DWORD dwBytesToSend = *pdwLength, toSend, realySend; int ret; DWORD dwErrorFlags; COMSTAT stComStat; DWORD dwNumberOfBytesTransferred; /* Windows 95: */ /* The number of transferred bytes returned by the */ /* GetOverlappedResult function is always zero, also */ /* if there are bytes received by the communication */ /* partner via the serial line. */ if (hComDev EQ INVALID_HANDLE_VALUE OR !bpTXBuffer OR *pdwLength ==0) return FALSE; // device not available realySend = 0; toSend = dwBytesToSend; while (toSend > 0) { if (m_mode==US_MODE_NT) { if (toSend > 20) { ret = WriteFile (hComDev, bpTXBuffer+realySend, 20, pdwLength, &gWriteOverLap); dwNumberOfBytesTransferred = 20; } else { ret = WriteFile (hComDev, bpTXBuffer+realySend, toSend, pdwLength, &gWriteOverLap); dwNumberOfBytesTransferred = toSend; } /* if there was a problem, or the async. operation's still pending ... */ if (!ret) { /* deal with the error code */ if (GetLastError() == ERROR_IO_PENDING) { /* asynchronous i/o is still in progress */ /* do something else for a while */ /* check on the results of the asynchronous read */ while (!GetOverlappedResult(gWriteOverLap.hEvent, &gWriteOverLap, pdwLength, TRUE)) { if(GetLastError() == ERROR_IO_INCOMPLETE) { continue; } else { break ; } } } else { ClearCommError(hComDev, &dwErrorFlags, &stComStat); return FALSE; } } } else { if (toSend > 20) { ret = WriteFile (hComDev, bpTXBuffer+realySend, 20, pdwLength, NULL); dwNumberOfBytesTransferred = 20; /* US_MODE_NT */ } else { ret = WriteFile (hComDev, bpTXBuffer+realySend, toSend, pdwLength, NULL); dwNumberOfBytesTransferred = toSend; /* US_MODE_NT */ } } #ifdef DEBUG_USART { char traceBuf[255]; unsigned int i; traceBuf[0] = '\0'; for (i=0; i<*pdwLength; i++) { if (!isprint (bpTXBuffer[realySend+i])) { sprintf (traceBuf+strlen(traceBuf), "[%02x]%c", (USHORT) bpTXBuffer[realySend+i], ((bpTXBuffer[realySend+i] EQ '\n') ? '\n': ' ') ); } else sprintf (traceBuf+strlen(traceBuf), "%c", bpTXBuffer[realySend+i]); if (strlen (traceBuf) > 200) { write (usart_out, traceBuf, strlen (traceBuf)); traceBuf[0] = '\0'; } } /* * write the string to the tracefile */ write (usart_out, traceBuf, strlen (traceBuf)); } #endif switch (m_mode) { case US_MODE_NT: realySend += dwNumberOfBytesTransferred; toSend -= dwNumberOfBytesTransferred; break; case US_MODE_95: realySend += *pdwLength; toSend -= *pdwLength; break; default: break; } } *pdwLength = dwBytesToSend; return TRUE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : UT_Init | +--------------------------------------------------------------------+ PURPOSE : initializes the USART driver RETURNS : 0 ... initialization succeeded -1 ... error */ int UT_Init (unsigned int baudRate, int fifoSize, char flow_ctrl, void (func(void)), const char* fname ) { if (initialized == TRUE) { return 0; } switch (m_mode) { case US_MODE_FILE: if (!fname || !strlen(fname) || (m_file=fopen(fname,"rb"))==NULL) { fprintf (stdout, "USART: failed to open %s :-(\n",fname); return -1; } fprintf (stdout, "USART: \"%s\" opened\n",fname); break; case US_MODE_95: case US_MODE_NT: { BOOL ret; DWORD dwThreadID; #ifdef COM_AUTOSEARCH int from, to; int portNr; #else EXTERN int extPort; #endif ReceiveCallback = func; #ifdef COM_AUTOSEARCH if (P NEQ 0) { from = to = P; } else { from = 1; to = 4; } /* * try COMn: to COMm: where n is from and m is to */ for (portNr = from; portNr <= to; portNr++) { fprintf (stdout,"USART: Trying COM%d ... ", portNr); if ((ret = sioInit (portNr, convertBaudrate (baudRate), 10000 /*fifoSize*/, flow_ctrl)) EQ FALSE) { fprintf (stdout, "fail\n"); } else { fprintf (stdout, "success!\n"); break; } } #else fprintf (stdout, "USART: Trying COM%d ... ", extPort); if ((ret = sioInit (extPort, convertBaudrate (baudRate), 10000 /*fifoSize*/, flow_ctrl)) EQ FALSE) { fprintf (stdout, "fail\n"); } #endif if (ret) { fprintf (stdout, "success!\n"); if (ReceiveCallback NEQ NULL) { hThread = CreateThread ((LPSECURITY_ATTRIBUTES) NULL, 0, (LPTHREAD_START_ROUTINE) _readerThread, (LPVOID) NULL, 0, &dwThreadID ); } initialized = TRUE; } else { fprintf (stdout, "USART: COM-port not free or baudrate not supported !\n"); return -1; } break; } case US_MODE_SIM: { int i; if ( first_ut_init ) { if ( (ut_sema_handle = OpenSemaphore (SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, FALSE, "UT_SIM_SEMA")) == NULL ) { ut_sema_handle = CreateSemaphore (NULL, 1, 1, "UT_SIM_SEMA"); } first_ut_init = 0; } WaitForSingleObject (ut_sema_handle, INFINITE); if ((Stream = (T_USARTStream *) openUSARTMemory ( (char*)"GSM", sizeof (T_USARTStream) )) EQ NULL) { if ((Stream = (T_USARTStream *) createUSARTMemory ( (char*)"GSM", sizeof (T_USARTStream) )) EQ NULL) { PrintToFile ("USART: simulation could not create a shared memory area\n"); return -1; } PrintToFile ("USART: shared memory area created\n"); Stream->CH1_numOfBytes = 0; Stream->CH2_numOfBytes = 0; Stream->CH1_CTS = 0; Stream->CH2_CTS = 0; for (i=0; i<USART_BUFFER_SIZE; i++) { Stream->CH1_data[i] = 0; Stream->CH2_data[i] = 0; } Stream->Connects = 0; /* init connection counter (!! CURRENTLY NOT USED !!) */ Stream->Type=1; /* signaling new type */ } else { PrintToFile ("USART: shared memory area opened\n"); } /* set pointers to semaphores and data buffers */ #ifdef _TOOLS_ if (Stream->Type==0) // shared mem created by old stack { PrintToFile ("USART: connecting to old stack !\n"); Stream->CH1_CTS = 1; // (baudRate NEQ -1); removed because baudrate never negative InBuffer = Stream->CH1_data; OutBuffer = Stream->CH2_data; InCounter = &Stream->CH1_numOfBytes; OutCounter = &Stream->CH2_numOfBytes; semRCVFull = &SemCH1_full; semRCVEmpty = &SemCH1_empty; semSNDFull = &SemCH2_full; semSNDEmpty = &SemCH2_empty; CTS = &Stream->CH2_CTS; } else // shared mem created by us or new stack { Stream->CH2_CTS = 1; // (baudRate NEQ -1); removed because baudrate never negative InBuffer = Stream->CH2_data; OutBuffer = Stream->CH1_data; InCounter = &Stream->CH2_numOfBytes; OutCounter = &Stream->CH1_numOfBytes; semRCVFull = &SemCH2_full; semRCVEmpty = &SemCH2_empty; semSNDFull = &SemCH1_full; semSNDEmpty = &SemCH1_empty; CTS = &Stream->CH1_CTS; } #else /* _TOOLS_ */ Stream->CH1_CTS = 1; // (baudRate NEQ -1); removed because baudrate never negative InBuffer = Stream->CH1_data; OutBuffer = Stream->CH2_data; InCounter = &Stream->CH1_numOfBytes; OutCounter = &Stream->CH2_numOfBytes; semRCVFull = &SemCH1_full; semRCVEmpty = &SemCH1_empty; semSNDFull = &SemCH2_full; semSNDEmpty = &SemCH2_empty; CTS = &Stream->CH2_CTS; #endif /* _TOOLS_ */ readPointer = InBuffer; ReceiveCallback = func; Stream->Connects++; /* mark connection (!! CURRENTLY NOT USED !!) */ } ReleaseSemaphore (ut_sema_handle, 1, NULL); break; default: break; } initialized = TRUE; mem_closed = FALSE; #ifdef DEBUG_USART /* * Open protocol file and initialize */ usart_in = open ("USART.IN", O_WRONLY| O_TEXT| O_TRUNC| O_CREAT, 0666); usart_out = open ("USART.OUT", O_WRONLY| O_TEXT| O_TRUNC| O_CREAT, 0666); #endif return 0; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USARTSIM | | STATE : code ROUTINE : UT_Close | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL BOOL UT_Close(void) { if (initialized == FALSE) return FALSE; switch (m_mode) { case US_MODE_FILE: if (m_file) { fclose(m_file); m_file=NULL; } break; case US_MODE_95: case US_MODE_NT: { DWORD ExitCode; if (ReceiveCallback != NULL) { /* Initialize stop _readerThread */ ReaderThreadExitRequest = TRUE; while (ReaderThreadExitRequest == TRUE) SetCommMask (hComDev, 0); } /* Close Communication port. */ PurgeComm (hComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ; if (m_mode==UT_MODE_NT) { CloseHandle (gReadOverLap.hEvent); gReadOverLap.hEvent = INVALID_HANDLE_VALUE ; CloseHandle (gWriteOverLap.hEvent); gWriteOverLap.hEvent = INVALID_HANDLE_VALUE ; } CloseHandle (hComDev); hComDev = INVALID_HANDLE_VALUE; if (ReceiveCallback != NULL) { /* Stop _readerThread */ do { GetExitCodeThread(hThread, (LPDWORD) &ExitCode); } while (ExitCode == STILL_ACTIVE); CloseHandle (hThread); hThread = INVALID_HANDLE_VALUE; } break; } case US_MODE_SIM: { PrintToFile("USART: shared memory closed (%d)\n",cls_cnt); mem_closed = TRUE; /* mark disconnection */ Stream->Connects=(Stream->Connects>1) ? 1 : 0; /* (!! CURRENTLY NOT USED !!) */ #ifdef _TOOLS_ if (Stream->Type==0) /* shared mem created by old stack */ { fprintf (stdout, "USART: disconnecting from old stack !\n"); Stream->CH1_CTS = 0; } else /* shared mem created by us or new stack */ { Stream->CH2_CTS = 0; } #else /* _TOOLS_ */ Stream->CH1_CTS = 0; #endif /* _TOOLS_ */ CTS = NULL; /* close all handles */ UnmapViewOfFile((void*)Stream); CloseHandle(USARTMemHandle); CloseHandle(SemCH1_full); CloseHandle(SemCH2_full); CloseHandle(SemCH1_empty); CloseHandle(SemCH2_empty); cls_cnt++; break; default: break; } } #ifdef DEBUG_USART /* close tracefiles for usart-in and out */ close(usart_in); close(usart_out); #endif /* Deinitialize */ ReceiveCallback = NULL; initialized = FALSE; return TRUE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : UT_InitBlk | +--------------------------------------------------------------------+ PURPOSE : Initialize the USART for reading blocks */ int UT_InitBlk ( unsigned int baudRate, int fifoSize, char flow_ctrl, void *hP) { return UT_Init (baudRate, fifoSize, flow_ctrl, NULL, NULL); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : UT_IsChar | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL int UT_IsChar (void) { int ret; switch (m_mode) { case US_MODE_FILE: Sleep(FILE_SLOW_DOWN); while (feof(m_file)) { Sleep(1000); fseek(m_file,0,SEEK_CUR); } ret=1; break; case US_MODE_95: case US_MODE_NT: { static COMSTAT stComStat; static DWORD dwErrors; if (!initialized) return FALSE; waitForRCVBufferFull (); ClearCommError (hComDev, &dwErrors, &stComStat); ret= (stComStat.cbInQue > 0); break; } case US_MODE_SIM: { waitForRCVBufferFull (); ret = (*InCounter NEQ 0); if (ret EQ 0) readPointer = InBuffer; break; default: ret = 0; break; } } return ret; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : UT_ReadChar | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL BYTE UT_ReadChar (void) { BYTE ret=0; switch (m_mode) { case US_MODE_95: case US_MODE_NT: { BYTE buffer[1]; ULONG bytesRead; if (!initialized) return 0; sioRead (buffer, &bytesRead); if (!bytesRead) buffer[0] = 0xff; ret=buffer[0]; break; } case US_MODE_SIM: { if (*InCounter NEQ 0) { ret = *readPointer++; #ifdef DEBUG_USART { BYTE buf[20]; sprintf (buf, "R[1 of %d]: ", *InCounter); write (usart_in, buf, strlen (buf)); if (isprint (ret)) { sprintf (buf, "%c\n", ret); } else { sprintf (buf, "(%02X)\n", ret); } write (usart_in, buf, strlen (buf)); } #endif (*InCounter)--; if (*InCounter EQ 0) { readPointer = InBuffer; markRCVBufferEmpty (); } } break; default: break; } } return ret; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : UT_ReadNChars | +--------------------------------------------------------------------+ PURPOSE : Called from the HISR - Reads a block of characters Parameters : buffer for holding received characters, max. size of buffer Returns the number of characters read */ GLOBAL ULONG UT_ReadNChars (int usart_id, BYTE *buffer, ULONG bufferSize) { ULONG bytes; switch (m_mode) { case US_MODE_FILE: if (bufferSize>FILE_MAX_CHUNK) { bufferSize=FILE_MAX_CHUNK; } bytes=fread(buffer,1,bufferSize,m_file); break; case US_MODE_95: case US_MODE_NT: { COMSTAT stComStat; DWORD dwErrors; if (!initialized) return 0L; ClearCommError (hComDev, &dwErrors, &stComStat); bytes = MINIMUM (stComStat.cbInQue, bufferSize); if (bytes EQ 0) return 0L; sioRead (buffer, &bytes); break; } case US_MODE_SIM: { if ((bytes = MINIMUM (*InCounter, bufferSize)) NEQ 0) { #ifdef DEBUG_USART unsigned int i; char buf[50]; #endif memcpy (buffer, readPointer, bytes); #ifdef DEBUG_USART sprintf (buf, "R[%d of %d]: ", bytes, *InCounter); write (usart_in, buf, strlen (buf)); for (i=0; i<bytes; i++) { if (isprint (buffer[i])) sprintf (buf, "%c", buffer[i]); else sprintf (buf, "(%02X)", buffer[i]); write (usart_in, buf, strlen (buf)); } write (usart_in, "\n", 1); #endif (*InCounter) -= (USHORT)bytes; if (*InCounter EQ 0) { readPointer = InBuffer; markRCVBufferEmpty (); } else { readPointer += bytes; } } else { markRCVBufferEmpty (); } break; default: bytes = 0; break; } } return bytes; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : UT_WriteChar | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void UT_WriteChar (int usart_id, char ch) { switch (m_mode) { case US_MODE_95: case US_MODE_NT: { BYTE buffer[1]; ULONG bytesWritten = 1; if (!initialized) return; buffer[0] = (BYTE)ch; sioWrite (buffer, &bytesWritten); break; } case US_MODE_SIM: { #ifdef DEBUG_USART char buf[50]; #endif if ( CTS == NULL || !*CTS) /* no testtools connected */ { return; } if (waitForSNDBufferEmpty () != 0) { markSNDBufferFull (); return; /* we gave up sending to avoid dead lock */ } #ifdef DEBUG_USART sprintf (buf, "W[1]: %02X", ch); write (usart_out, buf, strlen (buf)); #endif *OutBuffer = (UBYTE)ch; *OutCounter = 1; markSNDBufferFull (); break; default: break; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : UT_WriteString | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void UT_WriteString (int usart_id, char *s) { switch (m_mode) { case US_MODE_95: case US_MODE_NT: { ULONG bytesWritten = strlen (s); if (!initialized) return; sioWrite ((BYTE *) s, &bytesWritten); break; } case US_MODE_SIM: { unsigned int numOfChars; #ifdef DEBUG_USART int i; char buf[50]; #endif if ( CTS == NULL || !*CTS) /* no testtools connected */ { return; } if (waitForSNDBufferEmpty () != 0) { markSNDBufferFull (); return; /* we gave up sending to avoid dead lock */ } numOfChars = strlen (s); memcpy (OutBuffer, s, numOfChars); *OutCounter = numOfChars; #ifdef DEBUG_USART sprintf (buf, "W[%d]:", numOfChars); write (usart_out, buf, strlen (buf)); for (i=0; i<numOfChars; i++) { if (isprint (OutBuffer[i])) sprintf (buf, "%c", OutBuffer[i]); else sprintf (buf, "(%02X)", OutBuffer[i]); write (usart_out, buf, strlen (buf)); } write (usart_out,"\n", 1); #endif markSNDBufferFull (); break; default: break; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : UT_WriteNChars | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void UT_WriteNChars (int usart_id, BYTE *s, unsigned int n) { switch (m_mode) { case US_MODE_95: case US_MODE_NT: { ULONG bytesWritten = (ULONG) n; if (!initialized) return; if (!sioWrite ((BYTE *) s, &bytesWritten)) fprintf (stderr, "USART: Error1\n"); if (bytesWritten NEQ (ULONG) n) fprintf (stderr, "USART: Error2\n"); break; } case US_MODE_SIM: { #ifdef DEBUG_USART int i; char buf[50]; #endif if ( CTS == NULL || !*CTS) /* no testtools connected */ { #ifdef DEBUG_USART printf("-"); #endif snd_cnt++; return; } if ( mem_closed == TRUE ) { PrintToFile("USART:tried to write on closed memory (%d)\n",snd_cnt); return; } if (waitForSNDBufferEmpty () != 0) { markSNDBufferFull (); PrintToFile("USART: gave up sending\n"); snd_cnt++; return; /* we gave up sending to avoid dead lock */ } memcpy (OutBuffer, s, n); *OutCounter = n; #ifdef DEBUG_USART sprintf (buf, "W[%d]:", n); write (usart_out, buf, strlen (buf)); for (i=0; i<n; i++) { if (isprint (OutBuffer[i])) sprintf (buf, "%c", OutBuffer[i]); else sprintf (buf, "(%02X)", OutBuffer[i]); write (usart_out, buf, strlen (buf)); } write (usart_out,"\n", 1); #endif if ( mem_closed == TRUE ) { PrintToFile("USART: written on closed memory (%d)\n",snd_cnt); snd_cnt++; return; } #ifdef DEBUG_USART printf("+"); #endif markSNDBufferFull (); snd_cnt++; break; default: break; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : USART | | STATE : code ROUTINE : UT_SetFlowCtrl | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void UT_SetFlowCtrl (char flowCtrl) { switch (m_mode) { case US_MODE_95: case US_MODE_NT: { DCB stDCB; if (!GetCommState (hComDev, &stDCB)) return; stDCB.DCBlength = sizeof (stDCB); // sizeof(DCB) switch (flowCtrl) { case 'N': stDCB.fOutxCtsFlow = FALSE; stDCB.fOutxDsrFlow = FALSE; stDCB.fDtrControl = DTR_CONTROL_DISABLE; stDCB.fRtsControl = RTS_CONTROL_DISABLE; break; case 'D': stDCB.fOutxCtsFlow = FALSE; stDCB.fOutxDsrFlow = TRUE; stDCB.fDtrControl = DTR_CONTROL_HANDSHAKE; stDCB.fRtsControl = RTS_CONTROL_DISABLE; stDCB.XonLim = 0; stDCB.XoffLim = 50; break; case 'R': stDCB.fOutxCtsFlow = TRUE; stDCB.fOutxDsrFlow = FALSE; stDCB.fDtrControl = DTR_CONTROL_DISABLE; stDCB.fRtsControl = RTS_CONTROL_HANDSHAKE; stDCB.XonLim = 0; stDCB.XoffLim = 50; break; case 'P': stDCB.fOutxCtsFlow = FALSE; stDCB.fOutxDsrFlow = FALSE; stDCB.fDtrControl = DTR_CONTROL_ENABLE; stDCB.fRtsControl = RTS_CONTROL_DISABLE; break; default: break; } SetCommState (hComDev, &stDCB); break; } case US_MODE_SIM: break; default: break; } }