00001
00002 #ifndef __SERIAL_WIN32_PAL_HPP__
00003 #define __SERIAL_WIN32_PAL_HPP__
00004
00005
00006 #include <assert.h>
00007 #include <ctype.h>
00008 #include <stdio.h>
00009 #include <windows.h>
00010
00011 namespace lfc
00012 {
00013 namespace win32PAL
00014 {
00015
00017
00021 namespace serial
00022 {
00023
00024 const int MAX_ERROR_CODE = 2;
00025
00026 enum ErrorCodes
00027 {
00028 errOk,
00029 errGeneric,
00030 errNotSupported,
00031 };
00032
00033 extern const char *messagesTable[MAX_ERROR_CODE + 1];
00034
00035
00037 typedef ::HANDLE Handle;
00038
00040 const Handle NULL_HANDLE = INVALID_HANDLE_VALUE;
00041
00042
00044 struct PortSettings
00045 {
00046 DCB dcb;
00047 COMMTIMEOUTS commTimeouts;
00048 };
00049
00050
00052 const int
00053 purgeInput = 0x0001,
00054 purgeOutput = 0x0002;
00055
00057 const int
00058 mstatusDSR = 0x0001,
00059 mstatusDTR = 0x0002,
00060 mstatusRTS = 0x0004,
00061 mstatusCTS = 0x0008,
00062 mstatusDCD = 0x0010,
00063 mstatusRNG = 0x0020;
00064
00065
00067
00070 inline int init()
00071 {
00072 return errOk;
00073 }
00074
00075
00077
00080 inline int cleanup()
00081 {
00082 return errOk;
00083 }
00084
00085
00087
00092 inline int open(Handle &handle, const char *name)
00093 {
00094 assert(handle == NULL_HANDLE);
00095
00096 HANDLE h = ::CreateFile(name, GENERIC_READ | GENERIC_WRITE,
00097 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00098 if(h != INVALID_HANDLE_VALUE)
00099 {
00100 handle = h;
00101 return errOk;
00102 }
00103 else
00104 return errGeneric;
00105 }
00106
00107
00109
00113 inline int close(Handle handle)
00114 {
00115 assert(handle != NULL_HANDLE);
00116 return ::CloseHandle(handle) ? errOk : errGeneric;
00117 }
00118
00119
00121
00128 inline int write(Handle handle, const void *buff, long count, long &writtenCount)
00129 {
00130 assert(handle != NULL_HANDLE);
00131
00132 DWORD dwCount = static_cast<DWORD>(count);
00133 DWORD dwWritten = 0;
00134
00135 if(::WriteFile(handle, buff, dwCount, &dwWritten, NULL))
00136 {
00137 writtenCount = static_cast<long>(dwWritten);
00138 return errOk;
00139 }
00140 else
00141 return errGeneric;
00142 }
00143
00145
00152 inline int read(Handle handle, void *buff, long count, long &readCount)
00153 {
00154 assert(handle != NULL_HANDLE);
00155
00156 DWORD dwCount = static_cast<DWORD>(count);
00157 DWORD dwRead = 0;
00158
00159 if(::ReadFile(handle, buff, dwCount, &dwRead, NULL))
00160 {
00161 readCount = static_cast<long>(dwRead);
00162 return errOk;
00163 }
00164 else
00165 return errGeneric;
00166 }
00167
00168
00170
00174 inline int flush(Handle handle)
00175 {
00176 assert(handle != NULL_HANDLE);
00177 return ::FlushFileBuffers(handle) ? errOk : errGeneric;
00178 }
00179
00180
00182
00194 inline int setup(Handle handle, const char *portSettings)
00195 {
00196 assert(handle != NULL_HANDLE);
00197 assert(portSettings != NULL);
00198
00199 const char *p = portSettings;
00200 long baud = 0;
00201 long byteSize = 0;
00202 long stopBits = 0;
00203 char parity = '#';
00204
00205
00206 while( isdigit(*p) )
00207 baud = baud * 10 + *p++ - '0';
00208 if(*p++ != ',')
00209 return errGeneric;
00210 byteSize = *p++ - '0';
00211 if(byteSize < 5 || byteSize > 8)
00212 return errGeneric;
00213 parity = toupper(*p++);
00214 if(::strchr("NOES", parity) == NULL)
00215 return errGeneric;
00216 stopBits = *p++ - '0';
00217 if(stopBits != 1 && stopBits != 2)
00218 return errGeneric;
00219 if(*p != 0)
00220 return errGeneric;
00221
00222
00223 char buff[1024];
00224 ::sprintf(buff, "%ld,%c,%ld,%ld", baud, parity, byteSize, stopBits);
00225
00226 DCB dcb = {0};
00227 dcb.DCBlength = sizeof(DCB);
00228
00229
00230 if(!::BuildCommDCB(buff, &dcb))
00231 return errGeneric;
00232
00233 return ::SetCommState(handle, &dcb) ? errOk : errGeneric;
00234 }
00235
00236
00238
00244 inline int availableCount(Handle handle, long &count)
00245 {
00246 assert(handle != NULL_HANDLE);
00247
00248 DWORD dwErrors;
00249 COMSTAT comStat = {0};
00250
00251 ::ClearCommError(handle, &dwErrors, &comStat);
00252 assert(dwErrors == 0);
00253
00254 count = static_cast<long>(comStat.cbInQue);
00255 return errOk;
00256 }
00257
00258
00260
00265 inline int setHardwareFlowControl(Handle handle, bool bEnable)
00266 {
00267 assert(handle != NULL_HANDLE);
00268
00269 DCB dcb = {0};
00270 dcb.DCBlength = sizeof(DCB);
00271
00272 if(!::GetCommState(handle, &dcb))
00273 return errGeneric;
00274
00275 if(bEnable)
00276 {
00277 dcb.fOutxCtsFlow = true;
00278 dcb.fOutxDsrFlow = true;
00279 dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
00280 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
00281 }
00282 else
00283 {
00284 dcb.fOutxCtsFlow = false;
00285 dcb.fOutxDsrFlow = false;
00286 dcb.fDtrControl = DTR_CONTROL_ENABLE;
00287 dcb.fRtsControl = RTS_CONTROL_ENABLE;
00288 }
00289
00290 return ::SetCommState(handle, &dcb) ? errOk : errGeneric;
00291 }
00292
00293
00295
00302 inline int setSoftwareFlowControl(Handle handle, bool bEnable, char Xon, char Xoff)
00303 {
00304 assert(handle != NULL_HANDLE);
00305
00306 DCB dcb = {0};
00307 dcb.DCBlength = sizeof(DCB);
00308
00309 if(!::GetCommState(handle, &dcb))
00310 return errGeneric;
00311
00312 if(bEnable)
00313 {
00314 dcb.fOutX = true;
00315 dcb.fInX = true;
00316 dcb.fTXContinueOnXoff = false;
00317 dcb.XonLim = 256;
00318 dcb.XoffLim = 512;
00319 }
00320 else
00321 {
00322 dcb.fOutX = false;
00323 dcb.fInX = false;
00324 }
00325
00326 return ::SetCommState(handle, &dcb) ? errOk : errGeneric;
00327 }
00328
00329
00331
00336 inline int setReadTimeouts(Handle handle, long timeout)
00337 {
00338 assert(handle != NULL_HANDLE);
00339
00340 COMMTIMEOUTS to = {0};
00341
00342 if(!::GetCommTimeouts(handle, &to))
00343 return errGeneric;
00344
00345 to.ReadIntervalTimeout = MAXDWORD;
00346 to.ReadTotalTimeoutMultiplier = MAXDWORD;
00347 to.ReadTotalTimeoutConstant = timeout;
00348
00349 return ::SetCommTimeouts(handle, &to) ? errOk : errGeneric;
00350 }
00351
00352
00354
00361 inline int setBlockingRead(Handle handle, bool bBlocking)
00362 {
00363 assert(handle != NULL_HANDLE);
00364
00365 COMMTIMEOUTS to = {0};
00366
00367 if(!::GetCommTimeouts(handle, &to))
00368 return errGeneric;
00369
00370 if(bBlocking)
00371 {
00372 to.ReadIntervalTimeout = 0;
00373 to.ReadTotalTimeoutMultiplier = 0;
00374 to.ReadTotalTimeoutConstant = 0;
00375 }
00376 else
00377 {
00378 to.ReadIntervalTimeout = MAXDWORD;
00379 to.ReadTotalTimeoutMultiplier = 0;
00380 to.ReadTotalTimeoutConstant = 0;
00381 }
00382
00383 return ::SetCommTimeouts(handle, &to) ? errOk : errGeneric;
00384 }
00385
00386
00388
00395 inline int purgeBuffer(Handle handle, int flags)
00396 {
00397 assert(handle != NULL_HANDLE);
00398
00399 DWORD win32flags = 0;
00400 win32flags |= flags & purgeInput ? PURGE_RXCLEAR : 0;
00401 win32flags |= flags & purgeOutput ? PURGE_TXCLEAR : 0;
00402
00403 return ::PurgeComm(handle, win32flags) ? errOk : errGeneric;
00404 }
00405
00406
00408
00412 inline int sendBreak(Handle handle)
00413 {
00414 assert(handle != NULL_HANDLE);
00415
00416 if(!::SetCommBreak(handle))
00417 return errGeneric;
00418 ::Sleep(500);
00419 if(!::ClearCommBreak(handle))
00420 return errGeneric;
00421
00422 return errOk;
00423 }
00424
00425
00427
00437 inline int getModemStatus(Handle handle, int &status)
00438 {
00439 assert(handle != NULL_HANDLE);
00440
00441 DWORD win32status = 0;
00442
00443 if(!::GetCommModemStatus(handle, &win32status))
00444 return errGeneric;
00445
00446 status = 0;
00447 status |= win32status & MS_CTS_ON ? mstatusCTS : 0;
00448 status |= win32status & MS_DSR_ON ? mstatusDSR : 0;
00449 status |= win32status & MS_RING_ON ? mstatusRNG : 0;
00450 status |= win32status & MS_RLSD_ON ? mstatusDCD : 0;
00451
00452 return errOk;
00453 }
00454
00455
00457
00463 inline int setDTR(Handle handle, bool bEnable)
00464 {
00465 assert(handle != NULL_HANDLE);
00466 return ::EscapeCommFunction(handle, bEnable ? SETDTR : CLRDTR) ?
00467 errOk : errGeneric;
00468 }
00469
00470
00472
00478 inline int setRTS(Handle handle, bool bEnable)
00479 {
00480 assert(handle != NULL_HANDLE);
00481 return ::EscapeCommFunction(handle, bEnable ? SETRTS : CLRRTS) ?
00482 errOk : errGeneric;
00483 }
00484
00485
00487
00492 inline int saveSettings(Handle handle, PortSettings &settings)
00493 {
00494 assert(handle != NULL_HANDLE);
00495
00496
00497 DCB dcb = {0};
00498 dcb.DCBlength = sizeof(DCB);
00499 if(!::GetCommState(handle, &dcb))
00500 return errGeneric;
00501
00502
00503 COMMTIMEOUTS to = {0};
00504 if(!::GetCommTimeouts(handle, &to))
00505 return errGeneric;
00506
00507 settings.dcb = dcb;
00508 settings.commTimeouts = to;
00509 return errOk;
00510 }
00511
00512
00514
00519 inline int restoreSettings(Handle handle, const PortSettings &settings)
00520 {
00521 assert(handle != NULL_HANDLE);
00522
00523 DCB dcb = settings.dcb;
00524 COMMTIMEOUTS commTimeouts = settings.commTimeouts;
00525
00526
00527 if(!::SetCommState(handle, &dcb))
00528 return errGeneric;
00529
00530
00531 if(!::SetCommTimeouts(handle, &commTimeouts))
00532 return errGeneric;
00533
00534 return errOk;
00535 }
00536
00537
00539
00542 inline const char *message(int index)
00543 {
00544 assert(index >= 0 && index <= MAX_ERROR_CODE);
00545 return messagesTable[index];
00546 }
00547
00548
00549 }
00550 }
00551
00552 namespace pal = win32PAL;
00553
00554 }
00555
00556
00557 #endif // __SERIAL_WIN32_PAL_HPP__
00558