FreeCalypso > hg > fc-magnetite
view src/gpf2/tst/drv/usart.c @ 597:f18b29e27be5
First attempt at MCSI voice path automatic switching
The function is implemented at the ACI level in both aci2 and aci3,
successfully avoids triggering the DSP bug on the first call,
but the shutdown of MCSI upon call completion is not working properly yet
in either version.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 27 Mar 2019 22:18:35 +0000 |
parents | cd37d228dae0 |
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; } }