FreeCalypso > hg > freecalypso-sw
diff gsm-fw/gpf/tst_drv/usart.c @ 322:5d1e22505446
GPF: tif library sources imported from Leonardo version
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 13 Apr 2014 07:21:57 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/gpf/tst_drv/usart.c Sun Apr 13 07:21:57 2014 +0000 @@ -0,0 +1,1843 @@ +/* ++------------------------------------------------------------------------------ +| 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; + } +}