User implemented serial driver example |
// Defines the entry point for the DLL application.
// Make sure that shdata is a shared section (e.g. for Microsoft linker you should use: /SECTION:shdata,RWS) // This way the s_nInstances variable will be globally visible to all applications using this DLL
#pragma data_seg("shdata") static int s_nInstances = 0;
#pragma data_seg()
HANDLE g_hSerialPort = INVALID_HANDLE_VALUE; DWORD g_nBaudRate = 0;
BOOL APIENTRY DllMain( HANDLE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/ ) { switch (ul_reason_for_call)
case DLL_PROCESS_ATTACH: if (s_nInstances == 0)
g_hSerialPort = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, // exclusive access NULL, // no security attrs OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (g_hSerialPort == INVALID_HANDLE_VALUE) return false;
//Initialize serial parameters DCB dcb; if (!GetCommState(g_hSerialPort, &dcb)) return false; dcb.BaudRate = g_nBaudRate = CBR_9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = TWOSTOPBITS; // Standard flow control // setup no hardware flow control dcb.fOutxDsrFlow = 0; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fOutxCtsFlow = 0; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fDsrSensitivity = false;
// setup no software flow control dcb.fInX = dcb.fOutX = 0; dcb.fBinary = true ; if (!SetCommState(g_hSerialPort, &dcb)) return false;
//Set serial timeouts. ReadData and WriteData must return //in a determined period of time COMMTIMEOUTS CommTimeOuts; CommTimeOuts.ReadIntervalTimeout = 1000; CommTimeOuts.WriteTotalTimeoutMultiplier = CommTimeOuts.ReadTotalTimeoutMultiplier = 700 ; CommTimeOuts.WriteTotalTimeoutConstant = CommTimeOuts.ReadTotalTimeoutConstant = 500 ; if(!SetCommTimeouts(g_hSerialPort, &CommTimeOuts)) return false; } else
//This library does not support connection sharing between applications //If you need it, you must duplicate file handler from one process to another return false; } s_nInstances++; break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: s_nInstances--; if (s_nInstances == 0)
CloseHandle(g_hSerialPort); g_hSerialPort = INVALID_HANDLE_VALUE; } break; } return true; }
//must have a timeout bool __stdcall ReadData(BYTE* pData, DWORD dwBufSize, DWORD* pdwBytesRead)
return ReadFile(g_hSerialPort, pData, dwBufSize, pdwBytesRead, NULL) ? true : false; }
//must have a timeout bool __stdcall WriteData(const BYTE* pData, DWORD dwBufSize, DWORD* pdwBytesWritten)
return WriteFile(g_hSerialPort, pData, dwBufSize, pdwBytesWritten, NULL) ? true : false; }
int __stdcall GetBytesCountInQueue() // should be non-blocking, < 0 means error
COMSTAT comStat; DWORD dwComErrors; if (!ClearCommError(g_hSerialPort, &dwComErrors, &comStat)) return -1; return comStat.cbInQue; }
void __stdcall PurgeQueues()
PurgeComm(g_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); }
DWORD __stdcall GetCommBaudRate()
return g_nBaudRate; }
bool __stdcall SetCommBaudRate(DWORD nNewBaudRate)
if(nNewBaudRate != g_nBaudRate)
DCB dcb; if (!GetCommState(g_hSerialPort, &dcb)) return false; dcb.BaudRate = g_nBaudRate = nNewBaudRate; if (!SetCommState(g_hSerialPort, &dcb)) return false; } return true; } |