00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <string.h>
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include "serialport.h"
00041
00042 #define SERIALPORT_SETUPCOMM_INTERNAL_BUFFER_SIZE (8192)
00043
00044
00045
00046 static BOOL SERIALPORT_static_ReportLastError();
00047
00048
00049
00050 BOOL SERIALPORT_Initialize( SERIALPORT_structObject* serialport )
00051 {
00052 if( serialport == NULL )
00053 {
00054 SERIALPORT_ERROR_MSG( "if( serialport == NULL )" );
00055 return FALSE;
00056 }
00057 serialport->baudrate = SERIALPORT_BAUD_9600;
00058 serialport->parity = SERIALPORT_PARITY_NONE;
00059 serialport->databits = SERIALPORT_DATABITS_8;
00060 serialport->stopbits = SERIALPORT_STOPBITS_1;
00061 serialport->flowcontrol = SERIALPORT_FLOWCONTROL_NONE;
00062 serialport->isPortOpen = FALSE;
00063
00064 serialport->port = 0;
00065 serialport->timeout = 0;
00066 serialport->handle = NULL;
00067
00068 serialport->behaviour = SERIALPORT_BEHAVIOUR_RETURN_IMMEDIATELY;
00069
00070 memset( &serialport->control_setting, 0, sizeof(serialport->control_setting) );
00071
00072 return TRUE;
00073 }
00074
00075
00076
00077
00078 BOOL SERIALPORT_Open( SERIALPORT_structObject* serialport )
00079 {
00080 char msg[128];
00081 char comName[8];
00082 COMMTIMEOUTS CommTimeouts;
00083 WCHAR comStr[8];
00084 unsigned i = 0;
00085
00086 if( serialport == NULL )
00087 {
00088 SERIALPORT_ERROR_MSG( "if( serialport == NULL )" );
00089 return FALSE;
00090 }
00091
00092
00093 if( serialport->isPortOpen )
00094 {
00095 sprintf( msg, "Serial port %d is already open.", serialport->port );
00096 SERIALPORT_ERROR_MSG( msg );
00097 return FALSE;
00098 }
00099
00100 sprintf( comName, "COM%d", serialport->port );
00101
00102 for( i = 0; i < 8; i++ )
00103 {
00104 comStr[i] = comName[i];
00105 }
00106
00107
00108
00109 serialport->handle = CreateFile(
00110 comStr,
00111 GENERIC_READ | GENERIC_WRITE,
00112 0,
00113 NULL,
00114 OPEN_EXISTING,
00115 0,
00116 NULL
00117 );
00118
00119
00120 if( serialport->handle == INVALID_HANDLE_VALUE )
00121 {
00122 SERIALPORT_ERROR_MSG( "CreateFile returned an invalid handle.\nGetLastError() reports:\n" );
00123 SERIALPORT_static_ReportLastError();
00124 return FALSE;
00125 }
00126
00127
00128
00129 if( !SetupComm( serialport->handle, SERIALPORT_SETUPCOMM_INTERNAL_BUFFER_SIZE, SERIALPORT_SETUPCOMM_INTERNAL_BUFFER_SIZE ) )
00130 {
00131 SERIALPORT_ERROR_MSG( "SetupComm returned error condition.\nGetLastError() reports:\n" );
00132 SERIALPORT_static_ReportLastError();
00133 SERIALPORT_Close( serialport );
00134 return FALSE;
00135 }
00136
00137 if( !GetCommState(serialport->handle, &serialport->control_setting) )
00138 {
00139 SERIALPORT_ERROR_MSG( "GetCommState returned error condition.\nGetLastError() reports:\n" );
00140 SERIALPORT_static_ReportLastError();
00141 SERIALPORT_Close( serialport );
00142 return FALSE;
00143 }
00144
00145
00146 serialport->control_setting.BaudRate = serialport->baudrate;
00147 serialport->control_setting.ByteSize = serialport->databits;
00148 serialport->control_setting.Parity = serialport->parity;
00149 serialport->control_setting.StopBits = serialport->stopbits;
00150 if( serialport->parity != SERIALPORT_PARITY_NONE )
00151 {
00152 serialport->control_setting.fParity = TRUE;
00153 }
00154 else
00155 {
00156 serialport->control_setting.fParity = FALSE;
00157 }
00158
00159 if( serialport->flowcontrol == SERIALPORT_FLOWCONTROL_NONE )
00160 {
00161 serialport->control_setting.fOutxCtsFlow = 0;
00162 serialport->control_setting.fOutxDsrFlow = 0;
00163 serialport->control_setting.fDtrControl = DTR_CONTROL_DISABLE;
00164 serialport->control_setting.fOutX = 0;
00165 serialport->control_setting.fInX = 0;
00166 serialport->control_setting.fRtsControl = RTS_CONTROL_DISABLE;
00167 }
00168 else if( serialport->flowcontrol == SERIALPORT_FLOWCONTROL_HARDWARE )
00169 {
00170 serialport->control_setting.fOutxCtsFlow = 1;
00171 serialport->control_setting.fOutxDsrFlow = 1;
00172 serialport->control_setting.fDtrControl = DTR_CONTROL_HANDSHAKE;
00173 serialport->control_setting.fOutX = 0;
00174 serialport->control_setting.fInX = 0;
00175 serialport->control_setting.fRtsControl = RTS_CONTROL_HANDSHAKE;
00176 }
00177 else if( serialport->flowcontrol == SERIALPORT_FLOWCONTROL_XONXOFF )
00178 {
00179 serialport->control_setting.fOutxCtsFlow = 0;
00180 serialport->control_setting.fOutxDsrFlow = 0;
00181 serialport->control_setting.fDtrControl = DTR_CONTROL_ENABLE;
00182 serialport->control_setting.fOutX = 1;
00183 serialport->control_setting.fInX = 1;
00184 serialport->control_setting.fRtsControl = RTS_CONTROL_ENABLE;
00185 }
00186 else
00187 {
00188 SERIALPORT_ERROR_MSG( "Unexpected" );
00189 return FALSE;
00190 }
00191
00192
00193
00194 if( !SetCommState( serialport->handle, &serialport->control_setting ) )
00195 {
00196 SERIALPORT_ERROR_MSG( "SetCommState returned error condition.\nGetLastError() reports:\n" );
00197 SERIALPORT_static_ReportLastError();
00198 SERIALPORT_Close( serialport );
00199 return FALSE;
00200 }
00201
00202
00203
00204 if( !GetCommTimeouts( serialport->handle, &CommTimeouts ) )
00205 {
00206 SERIALPORT_ERROR_MSG( "GetCommTimeouts returned error condition.\nGetLastError() reports:\n" );
00207 SERIALPORT_static_ReportLastError();
00208 SERIALPORT_Close( serialport );
00209 return FALSE;
00210 }
00211
00212 if( serialport->behaviour == SERIALPORT_BEHAVIOUR_WAIT_UNTIL_BYTES_DETECTED )
00213 {
00214 CommTimeouts.ReadIntervalTimeout = MAXDWORD;
00215 CommTimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
00216 CommTimeouts.ReadTotalTimeoutConstant = serialport->timeout;
00217 }
00218 else if( serialport->behaviour == SERIALPORT_BEHAVIOUR_RETURN_IMMEDIATELY )
00219 {
00220 CommTimeouts.ReadIntervalTimeout = MAXDWORD;
00221 CommTimeouts.ReadTotalTimeoutMultiplier = 0;
00222 CommTimeouts.ReadTotalTimeoutConstant = 0;
00223 serialport->timeout = 0;
00224 }
00225 else
00226 {
00227 SERIALPORT_ERROR_MSG("Unexpected.");
00228 return FALSE;
00229 }
00230
00231 if( !SetCommTimeouts( serialport->handle, &CommTimeouts ) )
00232 {
00233 SERIALPORT_ERROR_MSG( "SetCommTimeouts returned FALSE.\nGetLastError() reports:\n" );
00234 SERIALPORT_static_ReportLastError();
00235 SERIALPORT_Close( serialport );
00236 return FALSE;
00237 }
00238
00239 serialport->isPortOpen = TRUE;
00240
00241 return TRUE;
00242 }
00243
00244 BOOL SERIALPORT_Close( SERIALPORT_structObject* serialport )
00245 {
00246 if( serialport == NULL )
00247 {
00248 SERIALPORT_ERROR_MSG( "if( serialport == NULL )" );
00249 return FALSE;
00250 }
00251 if( serialport->isPortOpen )
00252 {
00253 if( !CloseHandle( serialport->handle ) )
00254 {
00255 SERIALPORT_ERROR_MSG( "CloseHandle returned FALSE.\nGetLastError() reports:\n" );
00256 SERIALPORT_static_ReportLastError();
00257 return FALSE;
00258 }
00259 serialport->isPortOpen = FALSE;
00260 serialport->handle = NULL;
00261 return TRUE;
00262 }
00263 else
00264 {
00265 SERIALPORT_ERROR_MSG( "The serial port is not open." );
00266 return FALSE;
00267 }
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 BOOL SERIALPORT_Read(
00311 SERIALPORT_structObject* serialport,
00312 unsigned char* buffer,
00313 const unsigned int bytesAvailableInBuffer,
00314 unsigned int *bytesRead
00315 )
00316 {
00317 BOOL result;
00318 DWORD dwbytesRead = 0;
00319 *bytesRead = 0;
00320
00321 if( serialport == NULL )
00322 {
00323 SERIALPORT_ERROR_MSG( "if( serialport == NULL )" );
00324 return FALSE;
00325 }
00326 if( serialport->isPortOpen )
00327 {
00328 result = ReadFile(
00329 serialport->handle,
00330 buffer,
00331 bytesAvailableInBuffer,
00332 (LPDWORD)&dwbytesRead,
00333 NULL );
00334
00335 *bytesRead = dwbytesRead;
00336
00337 if( GetLastError() == ERROR_IO_PENDING )
00338 {
00339
00340 return TRUE;
00341 }
00342 if( !result )
00343 {
00344 SERIALPORT_ERROR_MSG( "ReadFile returned FALSE.\nGetLastError() reports:\n" );
00345 SERIALPORT_static_ReportLastError();
00346 SERIALPORT_Close( serialport );
00347 return FALSE;
00348 }
00349 else
00350 {
00351 return TRUE;
00352 }
00353 }
00354 else
00355 {
00356 SERIALPORT_ERROR_MSG( "The serial port is not open." );
00357 return FALSE;
00358 }
00359 }
00360
00361 BOOL SERIALPORT_Write(
00362 SERIALPORT_structObject* serialport,
00363 const unsigned char* buffer,
00364 const unsigned int numberOfBytesToWrite
00365 )
00366 {
00367
00368 BOOL result;
00369 DWORD dwbytesWritten = 0;
00370
00371 if( serialport == NULL )
00372 {
00373 SERIALPORT_ERROR_MSG( "if( serialport == NULL )" );
00374 return FALSE;
00375 }
00376 if( serialport->isPortOpen )
00377 {
00378
00379 result = WriteFile(
00380 serialport->handle,
00381 buffer,
00382 numberOfBytesToWrite,
00383 (LPDWORD)&dwbytesWritten,
00384 NULL
00385 );
00386
00387 if( GetLastError() == ERROR_IO_PENDING )
00388 {
00389
00390 return TRUE;
00391 }
00392 if( !result )
00393 {
00394 SERIALPORT_ERROR_MSG( "WriteFile returned FALSE.\nGetLastError() reports:\n" );
00395 SERIALPORT_static_ReportLastError();
00396 SERIALPORT_Close( serialport );
00397 return FALSE;
00398 }
00399 else
00400 {
00401 if( dwbytesWritten != numberOfBytesToWrite )
00402 {
00403 SERIALPORT_ERROR_MSG( "if( dwbytesWritten != numberOfBytesToWrite )" );
00404 return FALSE;
00405 }
00406 return TRUE;
00407 }
00408 }
00409 else
00410 {
00411 SERIALPORT_ERROR_MSG( "The serial port is not open." );
00412 return FALSE;
00413 }
00414 }
00415
00416
00417
00418 BOOL SERIALPORT_static_ReportLastError()
00419 {
00420 unsigned i = 0;
00421 char msg[8192];
00422 LPTSTR pszMessage;
00423 DWORD dwLastError = GetLastError();
00424 FormatMessage(
00425 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00426 FORMAT_MESSAGE_FROM_SYSTEM |
00427 FORMAT_MESSAGE_IGNORE_INSERTS,
00428 NULL,
00429 dwLastError,
00430 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00431 (LPTSTR)&pszMessage,
00432 0,
00433 NULL
00434 );
00435 for( i = 0; i < 8192; i++ )
00436 {
00437 msg[i] = (char)pszMessage[i];
00438 if( pszMessage[i] == '\0' )
00439 {
00440 break;
00441 }
00442 }
00443 SERIALPORT_ERROR_MSG( msg );
00444
00445 return TRUE;
00446 }
00447
00448
00449 BOOL SERIALPORT_WaitOnRingIndicatorEvent(
00450 SERIALPORT_structObject* serialport,
00451 unsigned short timeout_ms,
00452 BOOL *ring_detected
00453 )
00454 {
00455 BOOL result;
00456 DWORD EvtMask;
00457 SERIALPORT_enumBehaviour prev_behaviour;
00458 SERIALPORT_enumBehaviour prev_timeout;
00459 COMMTIMEOUTS CommTimeouts;
00460
00461 if( serialport == NULL )
00462 {
00463 SERIALPORT_ERROR_MSG( "if( serialport == NULL )" );
00464 return FALSE;
00465 }
00466 if( !serialport->isPortOpen )
00467 {
00468 SERIALPORT_ERROR_MSG( "if( !serialport->isPortOpen )" );
00469 return FALSE;
00470 }
00471
00472 result = GetCommMask( serialport->handle, &EvtMask );
00473 if( !result )
00474 {
00475 SERIALPORT_ERROR_MSG( "GetCommMask returned FALSE.\nGetLastError() reports:\n" );
00476 SERIALPORT_static_ReportLastError();
00477 SERIALPORT_Close( serialport );
00478 return FALSE;
00479 }
00480 EvtMask |= EV_RING;
00481
00482 result = SetCommMask( serialport->handle, EvtMask );
00483 if( !result )
00484 {
00485 SERIALPORT_ERROR_MSG( "SetCommMask returned FALSE.\nGetLastError() reports:\n" );
00486 SERIALPORT_static_ReportLastError();
00487 SERIALPORT_Close( serialport );
00488 return FALSE;
00489 }
00490
00491
00492 prev_behaviour = serialport->behaviour;
00493 prev_timeout = serialport->timeout;
00494 serialport->behaviour = SERIALPORT_BEHAVIOUR_WAIT_UNTIL_BYTES_DETECTED;
00495
00496
00497
00498 if( !GetCommTimeouts( serialport->handle, &CommTimeouts ) )
00499 {
00500 SERIALPORT_ERROR_MSG( "GetCommTimeouts returned error condition.\nGetLastError() reports:\n" );
00501 SERIALPORT_static_ReportLastError();
00502 SERIALPORT_Close( serialport );
00503 return FALSE;
00504 }
00505
00506 CommTimeouts.ReadIntervalTimeout = MAXDWORD;
00507 CommTimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
00508 CommTimeouts.ReadTotalTimeoutConstant = timeout_ms;
00509
00510 if( !SetCommTimeouts( serialport->handle, &CommTimeouts ) )
00511 {
00512 SERIALPORT_ERROR_MSG( "SetCommTimeouts returned FALSE.\nGetLastError() reports:\n" );
00513 SERIALPORT_static_ReportLastError();
00514 SERIALPORT_Close( serialport );
00515 return FALSE;
00516 }
00517
00518 EvtMask = 0;
00519 result = WaitCommEvent(
00520 serialport->handle,
00521 &EvtMask,
00522 NULL
00523 );
00524 if( !result )
00525 {
00526 SERIALPORT_ERROR_MSG( "WaitCommEvent returned FALSE.\nGetLastError() reports:\n" );
00527 SERIALPORT_static_ReportLastError();
00528 SERIALPORT_Close( serialport );
00529 return FALSE;
00530 }
00531
00532 if( EvtMask == EV_RING )
00533 {
00534 *ring_detected = TRUE;
00535 }
00536
00537 serialport->behaviour = prev_behaviour;
00538 serialport->timeout = prev_timeout;
00539
00540 if( serialport->behaviour == SERIALPORT_BEHAVIOUR_WAIT_UNTIL_BYTES_DETECTED )
00541 {
00542 CommTimeouts.ReadIntervalTimeout = MAXDWORD;
00543 CommTimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
00544 CommTimeouts.ReadTotalTimeoutConstant = serialport->timeout;
00545 }
00546 else if( serialport->behaviour == SERIALPORT_BEHAVIOUR_RETURN_IMMEDIATELY )
00547 {
00548 CommTimeouts.ReadIntervalTimeout = MAXDWORD;
00549 CommTimeouts.ReadTotalTimeoutMultiplier = 0;
00550 CommTimeouts.ReadTotalTimeoutConstant = 0;
00551 serialport->timeout = 0;
00552 }
00553 else
00554 {
00555 SERIALPORT_ERROR_MSG("Unexpected.");
00556 return FALSE;
00557 }
00558 if( !SetCommTimeouts( serialport->handle, &CommTimeouts ) )
00559 {
00560 SERIALPORT_ERROR_MSG( "SetCommTimeouts returned FALSE.\nGetLastError() reports:\n" );
00561 SERIALPORT_static_ReportLastError();
00562 SERIALPORT_Close( serialport );
00563 return FALSE;
00564 }
00565
00566 return TRUE;
00567 }
00568