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;

}