Changeset 7457 for trunk/src/kernel32/hmcomm.cpp
- Timestamp:
- Nov 26, 2001, 3:54:03 PM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/hmcomm.cpp
r7301 r7457 1 /* $Id: hmcomm.cpp,v 1.1 3 2001-11-08 15:38:42 phallerExp $ */1 /* $Id: hmcomm.cpp,v 1.14 2001-11-26 14:53:59 sandervl Exp $ */ 2 2 3 3 /* … … 7 7 * 8 8 * 1999 Achim Hasenmueller <achimha@innotek.de> 9 * 2001 Sander van Leeuwen <sandervl@xs4all.nl> 10 * 11 * TODO: Overlapped IO only supports one request at a time 9 12 * 10 13 */ … … 23 26 #include "dbglocal.h" 24 27 25 #define MAGIC_COM 0x12abcd34 26 27 #define IOCTL_ASYNC 0x01 28 #define ASYNC_GETDCBINFO 0x73 29 #define ASYNC_SETDCBINFO 0x53 30 #define ASYNC_SETLINECTRL 0x42 31 #define ASYNC_GETCOMMEVENT 0x72 32 #define ASYNC_EXTGETBAUDRATE 0x63 33 #define ASYNC_EXTSETBAUDRATE 0x43 34 #define ASYNC_GETCOMMERROR 0x6D 35 #define ASYNC_GETCOMMSTATUS 0x65 36 #define ASYNC_GETINQUECOUNT 0x68 37 #define ASYNC_GETOUTQUECOUNT 0x69 38 #define ASYNC_GETMODEMINPUT 0x67 39 #define ASYNC_TRANSMITIMM 0x44 40 #define ASYNC_SETBREAKON 0x4B 41 #define ASYNC_SETBREAKOFF 0x45 42 #define ASYNC_SETMODEMCTRL 0x46 43 #define ASYNC_STARTTRANSMIT 0x48 44 #define ASYNC_STOPTRANSMIT 0x47 45 #define ASYNC_GETMODEMOUTPUT 0x66 46 47 48 #pragma pack(1) 49 typedef struct _DCBINFO 50 { 51 USHORT usWriteTimeout; /* Time period used for Write Timeout processing. */ 52 USHORT usReadTimeout; /* Time period used for Read Timeout processing. */ 53 BYTE fbCtlHndShake; /* HandShake Control flag. */ 54 BYTE fbFlowReplace; /* Flow Control flag. */ 55 BYTE fbTimeOut; /* Timeout flag. */ 56 BYTE bErrorReplacementChar; /* Error Replacement Character. */ 57 BYTE bBreakReplacementChar; /* Break Replacement Character. */ 58 BYTE bXONChar; /* Character XON. */ 59 BYTE bXOFFChar; /* Character XOFF. */ 60 } DCBINFO; 61 typedef DCBINFO *PDCBINFO; 62 63 64 typedef struct _RXQUEUE 65 { 66 USHORT cch; /* Number of characters in the queue. */ 67 USHORT cb; /* Size of receive/transmit queue. */ 68 } RXQUEUE; 69 70 typedef RXQUEUE *PRXQUEUE; 71 72 73 typedef struct _MODEMSTATUS 74 { 75 BYTE fbModemOn; /* Modem Control Signals ON Mask. */ 76 BYTE fbModemOff; /* Modem Control Signals OFF Mask. */ 77 } MODEMSTATUS; 78 79 typedef MODEMSTATUS *PMODEMSTATUS; 80 81 82 #pragma pack() 83 84 85 86 87 88 typedef struct _HMDEVCOMDATA 89 { 90 ULONG ulMagic; 91 // Win32 Device Control Block 92 COMMCONFIG CommCfg; 93 COMMTIMEOUTS CommTOuts; 94 DWORD dwInBuffer, dwOutBuffer; 95 DWORD dwEventMask; 96 //OS/2 Device Control Block 97 DCBINFO dcbOS2; 98 } HMDEVCOMDATA, *PHMDEVCOMDATA; 99 28 29 BAUDTABLEENTRY BaudTable[] = 30 { 31 {75,BAUD_075}, 32 {110,BAUD_110}, 33 {134,BAUD_134_5}, 34 {150,BAUD_150}, 35 {300,BAUD_300}, 36 {600,BAUD_600}, 37 {1200,BAUD_1200}, 38 {1800,BAUD_1800}, 39 {2400,BAUD_2400}, 40 {4800,BAUD_4800}, 41 {7200,BAUD_7200}, 42 {9600,BAUD_9600}, 43 {14400,BAUD_14400}, 44 {19200,BAUD_19200}, 45 {38400,BAUD_38400}, 46 {56000,BAUD_56K}, 47 {57600,BAUD_57600}, 48 {115200,BAUD_115200}, 49 {128000,BAUD_128K} 50 }; 51 52 #define BaudTableSize (sizeof(BaudTable)/sizeof(BAUDTABLEENTRY)) 53 54 DWORD CALLBACK SerialCommThread(LPVOID lpThreadParam); 55 56 //****************************************************************************** 57 //****************************************************************************** 100 58 static VOID *CreateDevData() 101 59 { … … 119 77 return pData; 120 78 } 121 79 //****************************************************************************** 80 //****************************************************************************** 122 81 HMDeviceCommClass::HMDeviceCommClass(LPCSTR lpDeviceName) : HMDeviceHandler(lpDeviceName) 123 82 { … … 168 127 return FALSE; 169 128 } 170 171 DWORD HMDeviceCommClass::CreateFile(LPCSTR lpFileName, 129 //****************************************************************************** 130 //****************************************************************************** 131 DWORD HMDeviceCommClass::CreateFile(HANDLE hComm, 132 LPCSTR lpFileName, 172 133 PHMHANDLEDATA pHMHandleData, 173 134 PVOID lpSecurityAttributes, … … 179 140 180 141 if(strlen(lpFileName) > 5) { 181 return -1; //safety check (unnecessary..)142 return ERROR_INVALID_PARAMETER; //safety check (unnecessary..) 182 143 } 183 144 pHMHandleData->hHMHandle = 0; … … 233 194 if(rc) 234 195 { 235 return -1; 196 delete pHMHandleData->lpHandlerData; 197 return rc; 236 198 } 237 199 rc = SetBaud(pHMHandleData,9600); … … 239 201 rc = SetLine(pHMHandleData,8,0,0); 240 202 dprintf(("Set Line to 8/N/1 rc = %d",rc)); 241 return 0; 203 204 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) 205 { 206 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData; 207 DWORD dwThreadId; 208 209 pDevData->hEventSem = ::CreateEventA(NULL, TRUE, FALSE, NULL); 210 pDevData->hThread = ::CreateThread(NULL, 32*1024, SerialCommThread, (LPVOID)hComm, 0, &dwThreadId); 211 212 if(!pDevData->hEventSem || !pDevData->hThread) 213 { 214 DebugInt3(); 215 if(pDevData->hEventSem) ::CloseHandle(pDevData->hEventSem); 216 delete pHMHandleData->lpHandlerData; 217 return ERROR_NOT_ENOUGH_MEMORY; 218 } 219 } 220 return ERROR_SUCCESS; 242 221 } 243 222 else 244 return -1; 245 } 246 247 248 /* this is a handler method for calls to CloseHandle() */ 223 return ERROR_ACCESS_DENIED; 224 } 225 //****************************************************************************** 226 //****************************************************************************** 249 227 BOOL HMDeviceCommClass::CloseHandle(PHMHANDLEDATA pHMHandleData) 250 228 { 251 dprintf(("HMComm: Serial communication port close request\n")); 229 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData; 230 dprintf(("HMComm: Serial communication port close request")); 231 232 if(pDevData && pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) 233 { 234 pDevData->fClosing = TRUE; 235 dprintf(("signalling serial thread")); 236 ::SetEvent(pDevData->hEventSem); 237 ::ResetEvent(pDevData->hEventSem); 238 239 //Wait for thread to clean up 240 dprintf(("waiting for serial thread")); 241 DWORD ret = ::WaitForSingleObject(pDevData->hEventSem, 200); 242 dprintf(("waiting for serial thread done -> %x", ret)); 243 ::CloseHandle(pDevData->hEventSem); 244 } 252 245 delete pHMHandleData->lpHandlerData; 253 246 return OSLibDosClose(pHMHandleData->hHMHandle); 254 247 } 255 248 /***************************************************************************** 249 * Name : BOOL HMDeviceCommClass::WriteFile 250 * Purpose : write data to handle / device 251 * Parameters: PHMHANDLEDATA pHMHandleData, 252 * LPCVOID lpBuffer, 253 * DWORD nNumberOfBytesToWrite, 254 * LPDWORD lpNumberOfBytesWritten, 255 * LPOVERLAPPED lpOverlapped 256 * Variables : 257 * Result : Boolean 258 * Remark : 259 * Status : 260 * 261 * Author : SvL 262 *****************************************************************************/ 263 BOOL HMDeviceCommClass::WriteFile(PHMHANDLEDATA pHMHandleData, 264 LPCVOID lpBuffer, 265 DWORD nNumberOfBytesToWrite, 266 LPDWORD lpNumberOfBytesWritten, 267 LPOVERLAPPED lpOverlapped) 268 { 269 dprintf(("KERNEL32:HMDeviceCommClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)", 270 lpHMDeviceName, 271 pHMHandleData->hHMHandle, 272 lpBuffer, 273 nNumberOfBytesToWrite, 274 lpNumberOfBytesWritten, 275 lpOverlapped)); 276 277 BOOL ret; 278 ULONG ulBytesWritten; 279 280 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) { 281 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!")); 282 SetLastError(ERROR_INVALID_PARAMETER); 283 return FALSE; 284 } 285 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) { 286 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation")); 287 } 288 289 ret = OSLibDosWrite(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToWrite, 290 &ulBytesWritten); 291 292 if(lpNumberOfBytesWritten) { 293 *lpNumberOfBytesWritten = (ret) ? ulBytesWritten : 0; 294 } 295 if(ret == FALSE) { 296 dprintf(("!ERROR!: WriteFile failed with rc %d", GetLastError())); 297 } 298 299 return ret; 300 } 301 /***************************************************************************** 302 * Name : BOOL WriteFileEx 303 * Purpose : The WriteFileEx function writes data to a file. It is designed 304 * solely for asynchronous operation, unlike WriteFile, which is 305 * designed for both synchronous and asynchronous operation. 306 * WriteFileEx reports its completion status asynchronously, 307 * calling a specified completion routine when writing is completed 308 * and the calling thread is in an alertable wait state. 309 * Parameters: HANDLE hFile handle of file to write 310 * LPVOID lpBuffer address of buffer 311 * DWORD nNumberOfBytesToRead number of bytes to write 312 * LPOVERLAPPED lpOverlapped address of offset 313 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine 314 * Variables : 315 * Result : TRUE / FALSE 316 * Remark : 317 * Status : UNTESTED STUB 318 * 319 * Author : SvL 320 *****************************************************************************/ 321 322 BOOL HMDeviceCommClass::WriteFileEx(PHMHANDLEDATA pHMHandleData, 323 LPVOID lpBuffer, 324 DWORD nNumberOfBytesToWrite, 325 LPOVERLAPPED lpOverlapped, 326 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 327 { 328 dprintf(("!ERROR!: WriteFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n", 329 lpHMDeviceName, 330 pHMHandleData->hHMHandle, 331 lpBuffer, 332 nNumberOfBytesToWrite, 333 lpOverlapped, 334 lpCompletionRoutine)); 335 336 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) { 337 dprintf(("!WARNING!: Handle not created with FILE_FLAG_OVERLAPPED!")); 338 SetLastError(ERROR_ACCESS_DENIED); //todo: right error? 339 return FALSE; 340 } 341 342 SetLastError(ERROR_INVALID_FUNCTION); 343 return FALSE; 344 } 345 /***************************************************************************** 346 * Name : BOOL HMDeviceCommClass::ReadFile 347 * Purpose : read data from handle / device 348 * Parameters: PHMHANDLEDATA pHMHandleData, 349 * LPCVOID lpBuffer, 350 * DWORD nNumberOfBytesToRead, 351 * LPDWORD lpNumberOfBytesRead, 352 * LPOVERLAPPED lpOverlapped 353 * Variables : 354 * Result : Boolean 355 * Remark : 356 * Status : 357 * 358 * Author : SvL 359 *****************************************************************************/ 360 361 BOOL HMDeviceCommClass::ReadFile(PHMHANDLEDATA pHMHandleData, 362 LPCVOID lpBuffer, 363 DWORD nNumberOfBytesToRead, 364 LPDWORD lpNumberOfBytesRead, 365 LPOVERLAPPED lpOverlapped) 366 { 367 dprintf(("KERNEL32:HMDeviceCommClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)", 368 lpHMDeviceName, 369 pHMHandleData->hHMHandle, 370 lpBuffer, 371 nNumberOfBytesToRead, 372 lpNumberOfBytesRead, 373 lpOverlapped)); 374 375 BOOL ret; 376 ULONG ulBytesRead; 377 378 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) { 379 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!")); 380 SetLastError(ERROR_INVALID_PARAMETER); 381 return FALSE; 382 } 383 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) { 384 dprintf(("!WARNING!: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation")); 385 } 386 387 ret = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToRead, 388 &ulBytesRead); 389 390 if(lpNumberOfBytesRead) { 391 *lpNumberOfBytesRead = (ret) ? ulBytesRead : 0; 392 } 393 if(ret == FALSE) { 394 dprintf(("!ERROR!: ReadFile failed with rc %d", GetLastError())); 395 } 396 return ret; 397 } 398 399 /***************************************************************************** 400 * Name : BOOL ReadFileEx 401 * Purpose : The ReadFileEx function reads data from a file asynchronously. 402 * It is designed solely for asynchronous operation, unlike the 403 * ReadFile function, which is designed for both synchronous and 404 * asynchronous operation. ReadFileEx lets an application perform 405 * other processing during a file read operation. 406 * The ReadFileEx function reports its completion status asynchronously, 407 * calling a specified completion routine when reading is completed 408 * and the calling thread is in an alertable wait state. 409 * Parameters: HANDLE hFile handle of file to read 410 * LPVOID lpBuffer address of buffer 411 * DWORD nNumberOfBytesToRead number of bytes to read 412 * LPOVERLAPPED lpOverlapped address of offset 413 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine 414 * Variables : 415 * Result : TRUE / FALSE 416 * Remark : 417 * Status : UNTESTED STUB 418 * 419 * Author : SvL 420 *****************************************************************************/ 421 BOOL HMDeviceCommClass::ReadFileEx(PHMHANDLEDATA pHMHandleData, 422 LPVOID lpBuffer, 423 DWORD nNumberOfBytesToRead, 424 LPOVERLAPPED lpOverlapped, 425 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 426 { 427 dprintf(("!ERROR!: ReadFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n", 428 lpHMDeviceName, 429 pHMHandleData->hHMHandle, 430 lpBuffer, 431 nNumberOfBytesToRead, 432 lpOverlapped, 433 lpCompletionRoutine)); 434 435 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) { 436 dprintf(("!WARNING!: Handle not created with FILE_FLAG_OVERLAPPED!")); 437 SetLastError(ERROR_ACCESS_DENIED); //todo: right error? 438 return FALSE; 439 } 440 441 SetLastError(ERROR_INVALID_FUNCTION); 442 return FALSE; 443 } 256 444 /***************************************************************************** 257 445 * Name : DWORD HMDeviceHandler::SetupComm … … 273 461 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) ) 274 462 { 275 SetLastError(ERROR_INVALID_HANDLE);276 return FALSE;463 SetLastError(ERROR_INVALID_HANDLE); 464 return FALSE; 277 465 } 278 466 pDevData->dwInBuffer = dwInQueue; … … 281 469 return(TRUE); 282 470 } 283 471 //****************************************************************************** 472 #define TIMEOUT_COMM 50 473 //****************************************************************************** 474 DWORD CALLBACK SerialCommThread(LPVOID lpThreadParam) 475 { 476 HANDLE hComm = (HANDLE)lpThreadParam; 477 PHMHANDLEDATA pHMHandleData; 478 PHMDEVCOMDATA pDevData; 479 DWORD ret; 480 APIRET rc; 481 ULONG ulLen; 482 USHORT COMEvt; 483 DWORD dwEvent,dwMask; 484 485 dprintf(("SerialCommThread %x entered", hComm)); 486 pHMHandleData = HMQueryHandleData(hComm); 487 if(!pHMHandleData) { 488 dprintf(("!ERROR!: Invalid handle -> aborting")); 489 return 0; 490 } 491 492 pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData; 493 if(!pDevData) { 494 DebugInt3(); 495 return 0; 496 } 497 HANDLE hEvent = pDevData->hEventSem; 498 HANDLE hCommOS2 = pHMHandleData->hHMHandle; 499 if(!hCommOS2 || !hEvent) { 500 DebugInt3(); 501 return 0; 502 } 503 504 while(TRUE) 505 { 506 //validate handle 507 pHMHandleData = HMQueryHandleData(hComm); 508 if(!pHMHandleData) { 509 dprintf(("!ERROR!: Invalid handle -> aborting")); 510 return 0; 511 } 512 if(pDevData->fClosing) { 513 dprintf(("Cleaning up async comm thread")); 514 SetEvent(hEvent); //signal to CloseHandle that we're done 515 return 0; 516 } 517 518 //Wait for the app to call WaitCommEvent 519 dprintf(("SerialCommThread: wait for WaitCommEvent")); 520 ret = WaitForSingleObject(hEvent, INFINITE); 521 ResetEvent(hEvent); 522 dprintf(("SerialCommThread: wait for WaitCommEvent done %x", ret)); 523 524 //validate handle first 525 pHMHandleData = HMQueryHandleData(hComm); 526 if(!pHMHandleData) { 527 dprintf(("!ERROR!: Invalid handle -> aborting")); 528 return 0; 529 } 530 531 if(pDevData->fClosing) { 532 dprintf(("Cleaning up async comm thread")); 533 SetEvent(hEvent); //signal to CloseHandle that we're done 534 return 0; 535 } 536 537 HANDLE hOverlappedEvent = pDevData->overlapped.hEvent; 538 if(!hOverlappedEvent) { 539 DebugInt3(); 540 return 0; 541 } 542 543 ulLen = sizeof(CHAR); 544 dwEvent = 0; 545 rc = 0; 546 ulLen = sizeof(COMEvt); 547 dwMask = pDevData->dwEventMask; 548 549 while( (0==rc) && 550 !(dwEvent & dwMask) && 551 (dwMask == pDevData->dwEventMask) && 552 !(pDevData->fCancelIo) && !(pDevData->fClosing) ) // Exit if the Mask gets changed 553 { 554 rc = OSLibDosDevIOCtl(hCommOS2, 555 IOCTL_ASYNC, 556 ASYNC_GETCOMMEVENT, 557 0,0,0, 558 &COMEvt,ulLen,&ulLen); 559 if(!rc) 560 { 561 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0; 562 //dwEvent |= (COMEvt&0x0002)? 0:0; 563 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0; 564 dwEvent |= (COMEvt&0x0008)? EV_CTS:0; 565 dwEvent |= (COMEvt&0x0010)? EV_DSR:0; 566 //dwEvent |= (COMEvt&0x0020)? 0:0; DCS = RLSD? 567 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0; 568 dwEvent |= (COMEvt&0x0080)? EV_ERR:0; 569 dwEvent |= (COMEvt&0x0100)? EV_RING:0; 570 if((dwEvent & dwMask)) break; 571 } 572 else break; 573 574 DosSleep(TIMEOUT_COMM); 575 } 576 if((dwEvent & dwMask) && (dwMask == pDevData->dwEventMask)) { 577 pDevData->overlapped.Internal |= (rc==0) ? (dwEvent & dwMask) : 0; 578 pDevData->dwLastError = rc; 579 dprintf(("Overlapped: WaitCommEvent returned %x", pDevData->overlapped.Internal)); 580 581 //signal to app that a comm event has occurred 582 SetEvent(hOverlappedEvent); 583 } 584 } 585 return 0; 586 } 587 //****************************************************************************** 588 //****************************************************************************** 284 589 BOOL HMDeviceCommClass::WaitCommEvent( PHMHANDLEDATA pHMHandleData, 285 590 LPDWORD lpfdwEvtMask, … … 293 598 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData; 294 599 295 dprintf(("HMDeviceCommClass::WaitCommEvent")); 600 dprintf2(("HMDeviceCommClass::WaitCommEvent %x", pHMHandleData->hHMHandle)); 601 602 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo) { 603 dprintf(("!WARNING! pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo")); 604 SetLastError(ERROR_INVALID_PARAMETER); 605 return FALSE; 606 } 607 296 608 ulLen = sizeof(CHAR); 297 609 … … 304 616 (dwMask ==pDevData->dwEventMask) ) // Exit if the Mask gets changed 305 617 { 306 rc = OSLibDosDevIOCtl( 307 IOCTL_ASYNC,308 ASYNC_GETCOMMEVENT,309 0,0,0,310 &COMEvt,ulLen,&ulLen);618 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 619 IOCTL_ASYNC, 620 ASYNC_GETCOMMEVENT, 621 0,0,0, 622 &COMEvt,ulLen,&ulLen); 311 623 if(!rc) 312 624 { 313 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0; 314 //dwEvent |= (COMEvt&0x0002)? 0:0; 315 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0; 316 dwEvent |= (COMEvt&0x0008)? EV_CTS:0; 317 dwEvent |= (COMEvt&0x0010)? EV_DSR:0; 318 //dwEvent |= (COMEvt&0x0020)? 0:0; DCS = RLSD? 319 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0; 320 dwEvent |= (COMEvt&0x0080)? EV_ERR:0; 321 dwEvent |= (COMEvt&0x0100)? EV_RING:0; 625 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0; 626 //dwEvent |= (COMEvt&0x0002)? 0:0; 627 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0; 628 dwEvent |= (COMEvt&0x0008)? EV_CTS:0; 629 dwEvent |= (COMEvt&0x0010)? EV_DSR:0; 630 //dwEvent |= (COMEvt&0x0020)? 0:0; DCS = RLSD? 631 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0; 632 dwEvent |= (COMEvt&0x0080)? EV_ERR:0; 633 dwEvent |= (COMEvt&0x0100)? EV_RING:0; 634 if((dwEvent & dwMask)) break; 322 635 } 323 DosSleep(100); 324 } 325 *lpfdwEvtMask = rc==0?dwEvent:0; 326 return(rc==0); 327 } 328 329 330 #pragma pack(1) 331 typedef struct 332 { 333 ULONG ulCurrBaud; 334 UCHAR ucCurrFrac; 335 ULONG ulMinBaud; 336 UCHAR ucMinFrac; 337 ULONG ulMaxBaud; 338 UCHAR ucMaxFrac; 339 } EXTBAUDGET, *PEXTBAUDGET; 340 341 typedef struct 342 { 343 ULONG ulBaud; 344 UCHAR ucFrac; 345 } EXTBAUDSET, *PEXTBAUDSET; 346 #pragma pack() 347 348 BAUDTABLEENTRY BaudTable[] = 349 { 350 {75,BAUD_075}, 351 {110,BAUD_110}, 352 {134,BAUD_134_5}, 353 {150,BAUD_150}, 354 {300,BAUD_300}, 355 {600,BAUD_600}, 356 {1200,BAUD_1200}, 357 {1800,BAUD_1800}, 358 {2400,BAUD_2400}, 359 {4800,BAUD_4800}, 360 {7200,BAUD_7200}, 361 {9600,BAUD_9600}, 362 {14400,BAUD_14400}, 363 {19200,BAUD_19200}, 364 {38400,BAUD_38400}, 365 {56000,BAUD_56K}, 366 {57600,BAUD_57600}, 367 {115200,BAUD_115200}, 368 {128000,BAUD_128K} 369 }; 370 371 #define BaudTableSize (sizeof(BaudTable)/sizeof(BAUDTABLEENTRY)) 372 636 else break; 637 638 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) 639 { 640 memcpy(&pDevData->overlapped, lpo, sizeof(pDevData->overlapped)); 641 pDevData->overlapped.Internal = 0; 642 pDevData->overlapped.InternalHigh = 0; 643 pDevData->overlapped.Offset = 0; 644 pDevData->overlapped.OffsetHigh = 0; 645 //signal async comm thread to start polling comm status 646 ::SetEvent(pDevData->hEventSem); 647 SetLastError(ERROR_IO_PENDING); 648 return FALSE; 649 } 650 DosSleep(TIMEOUT_COMM); 651 } 652 if(dwMask == pDevData->dwEventMask) { 653 *lpfdwEvtMask = (rc==0) ? (dwEvent & dwMask) : 0; 654 dprintf(("WaitCommEvent returned %x", *lpfdwEvtMask)); 655 } 656 else *lpfdwEvtMask = 0; 657 658 return (rc==0); 659 } 660 /***************************************************************************** 661 * Name : DWORD HMDeviceCommClass::CancelIo 662 * Purpose : cancel pending IO operation 663 * Variables : 664 * Result : 665 * Remark : 666 * Status : 667 * 668 * Author : SvL 669 *****************************************************************************/ 670 BOOL HMDeviceCommClass::CancelIo(PHMHANDLEDATA pHMHandleData) 671 { 672 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData; 673 674 dprintf(("HMDeviceCommClass::CancelIo")); 675 if(pDevData == NULL || !(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) { 676 SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error? 677 return FALSE; 678 } 679 680 //signal serial thread to cancel pending IO operation 681 pDevData->fCancelIo = TRUE; 682 ::SetEvent(pDevData->hEventSem); 683 684 SetLastError(ERROR_SUCCESS); 685 return(TRUE); 686 } 687 /***************************************************************************** 688 * Name : DWORD HMDeviceFileClass::GetOverlappedResult 689 * Purpose : asynchronus I/O 690 * Parameters: PHMHANDLEDATA pHMHandleData 691 * LPOVERLAPPED arg2 692 * LPDWORD arg3 693 * BOOL arg4 694 * Variables : 695 * Result : API returncode 696 * Remark : 697 * Status : 698 * 699 * Author : SvL 700 *****************************************************************************/ 701 BOOL HMDeviceCommClass::GetOverlappedResult(PHMHANDLEDATA pHMHandleData, 702 LPOVERLAPPED lpoOverlapped, 703 LPDWORD lpcbTransfer, 704 BOOL fWait) 705 { 706 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData; 707 708 dprintf(("KERNEL32-WARNING: HMDeviceCommClass::GetOverlappedResult(%08xh,%08xh,%08xh,%08xh) STUB!!", 709 pHMHandleData->hHMHandle, 710 lpoOverlapped, 711 lpcbTransfer, 712 fWait)); 713 714 if(pDevData == NULL || !(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) { 715 SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error? 716 return FALSE; 717 } 718 if(!lpoOverlapped) { 719 SetLastError(ERROR_INVALID_PARAMETER); 720 return FALSE; 721 } 722 if(lpoOverlapped->hEvent != pDevData->overlapped.hEvent) { 723 dprintf(("!WARNING!: GetOverlappedResult called for unknown operation")); 724 SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error? 725 return FALSE; 726 } 727 if(pDevData->overlapped.Internal) { 728 lpoOverlapped->Internal = pDevData->overlapped.Internal; 729 pDevData->overlapped.Internal = 0; //not entirely safe 730 pDevData->dwLastError = 0; 731 SetLastError(pDevData->dwLastError); 732 return lpoOverlapped->Internal; 733 } 734 if(fWait) { 735 ::WaitForSingleObject(pDevData->overlapped.hEvent, INFINITE); 736 ::ResetEvent(pDevData->overlapped.hEvent); 737 lpoOverlapped->Internal = pDevData->overlapped.Internal; 738 pDevData->overlapped.Internal = 0; //not entirely safe 739 SetLastError(ERROR_SUCCESS); 740 return lpoOverlapped->Internal; 741 } 742 else { 743 SetLastError(ERROR_IO_PENDING); 744 return FALSE; 745 } 746 } 747 //****************************************************************************** 748 //****************************************************************************** 373 749 BOOL HMDeviceCommClass::GetCommProperties( PHMHANDLEDATA pHMHandleData, 374 750 LPCOMMPROP lpcmmp) … … 414 790 return(rc==0); 415 791 } 416 792 //****************************************************************************** 793 //****************************************************************************** 417 794 BOOL HMDeviceCommClass::GetCommMask( PHMHANDLEDATA pHMHandleData, 418 795 LPDWORD lpfdwEvtMask) … … 425 802 return(TRUE); 426 803 } 427 804 //****************************************************************************** 805 //****************************************************************************** 428 806 BOOL HMDeviceCommClass::SetCommMask( PHMHANDLEDATA pHMHandleData, 429 807 DWORD fdwEvtMask) 430 808 { 431 809 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData; 432 dprintf(("HMDeviceCommClass::SetCommMask")); 810 dprintf(("HMDeviceCommClass::SetCommMask %x", fdwEvtMask)); 811 812 if(fdwEvtMask & (EV_RLSD|EV_RXFLAG)) { 813 dprintf(("!WARNING! SetCommMask: unsupported flags EV_RLSD and/or EV_RXFLAG!!")); 814 } 433 815 434 816 pDevData->dwEventMask = fdwEvtMask & ~(EV_RLSD|EV_RXFLAG); // Clear the 2 not supported Flags. 435 817 return(TRUE); 436 818 } 437 819 //****************************************************************************** 820 //****************************************************************************** 438 821 BOOL HMDeviceCommClass::PurgeComm( PHMHANDLEDATA pHMHandleData, 439 822 DWORD fdwAction) … … 445 828 return(TRUE); 446 829 } 830 //****************************************************************************** 831 //****************************************************************************** 447 832 BOOL HMDeviceCommClass::ClearCommError( PHMHANDLEDATA pHMHandleData, 448 833 LPDWORD lpdwErrors, … … 509 894 return(rc==0); 510 895 } 896 //****************************************************************************** 897 //****************************************************************************** 511 898 BOOL HMDeviceCommClass::SetCommState( PHMHANDLEDATA pHMHandleData, 512 899 LPDCB lpDCB) … … 561 948 return(rc==0); 562 949 } 950 //****************************************************************************** 951 //****************************************************************************** 563 952 BOOL HMDeviceCommClass::GetCommState( PHMHANDLEDATA pHMHandleData, 564 953 LPDCB lpdcb) … … 571 960 return(TRUE); 572 961 } 962 //****************************************************************************** 963 //****************************************************************************** 573 964 BOOL HMDeviceCommClass::GetCommModemStatus( PHMHANDLEDATA pHMHandleData, 574 965 LPDWORD lpModemStat ) … … 579 970 UCHAR ucStatus; 580 971 581 dprintf(("HMDeviceCommClass:: TransmitCommChar partly implemented"));972 dprintf(("HMDeviceCommClass::GetCommModemStatus %x", lpModemStat)); 582 973 ulLen = sizeof(CHAR); 583 974 … … 600 991 return(rc==0); 601 992 } 602 993 //****************************************************************************** 994 //****************************************************************************** 603 995 BOOL HMDeviceCommClass::GetCommTimeouts( PHMHANDLEDATA pHMHandleData, 604 996 LPCOMMTIMEOUTS lpctmo) … … 612 1004 return(TRUE); 613 1005 } 1006 //****************************************************************************** 1007 //****************************************************************************** 614 1008 BOOL HMDeviceCommClass::SetCommTimeouts( PHMHANDLEDATA pHMHandleData, 615 1009 LPCOMMTIMEOUTS lpctmo) … … 690 1084 return(0==rc); 691 1085 } 1086 //****************************************************************************** 1087 //****************************************************************************** 692 1088 BOOL HMDeviceCommClass::TransmitCommChar( PHMHANDLEDATA pHMHandleData, 693 1089 CHAR cChar ) … … 708 1104 return(rc==0); 709 1105 } 710 711 /***************************************************************************** 712 * Name : BOOL HMDeviceCommClass::WriteFile 713 * Purpose : write data to handle / device 714 * Parameters: PHMHANDLEDATA pHMHandleData, 715 * LPCVOID lpBuffer, 716 * DWORD nNumberOfBytesToWrite, 717 * LPDWORD lpNumberOfBytesWritten, 718 * LPOVERLAPPED lpOverlapped 719 * Variables : 720 * Result : Boolean 721 * Remark : 722 * Status : 723 * 724 * Author : SvL 725 *****************************************************************************/ 726 727 BOOL HMDeviceCommClass::WriteFile(PHMHANDLEDATA pHMHandleData, 728 LPCVOID lpBuffer, 729 DWORD nNumberOfBytesToWrite, 730 LPDWORD lpNumberOfBytesWritten, 731 LPOVERLAPPED lpOverlapped) 732 { 733 dprintf(("KERNEL32:HMDeviceCommClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)", 734 lpHMDeviceName, 735 pHMHandleData->hHMHandle, 736 lpBuffer, 737 nNumberOfBytesToWrite, 738 lpNumberOfBytesWritten, 739 lpOverlapped)); 740 741 BOOL ret; 742 ULONG ulBytesWritten; 743 744 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) { 745 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!")); 746 SetLastError(ERROR_INVALID_PARAMETER); 747 return FALSE; 748 } 749 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) { 750 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation")); 751 } 752 753 ret = OSLibDosWrite(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToWrite, 754 &ulBytesWritten); 755 756 if(lpNumberOfBytesWritten) { 757 *lpNumberOfBytesWritten = (ret) ? ulBytesWritten : 0; 758 } 759 if(ret == FALSE) { 760 dprintf(("ERROR: WriteFile failed with rc %d", GetLastError())); 761 } 762 763 return ret; 764 } 765 766 /***************************************************************************** 767 * Name : BOOL WriteFileEx 768 * Purpose : The WriteFileEx function writes data to a file. It is designed 769 * solely for asynchronous operation, unlike WriteFile, which is 770 * designed for both synchronous and asynchronous operation. 771 * WriteFileEx reports its completion status asynchronously, 772 * calling a specified completion routine when writing is completed 773 * and the calling thread is in an alertable wait state. 774 * Parameters: HANDLE hFile handle of file to write 775 * LPVOID lpBuffer address of buffer 776 * DWORD nNumberOfBytesToRead number of bytes to write 777 * LPOVERLAPPED lpOverlapped address of offset 778 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine 779 * Variables : 780 * Result : TRUE / FALSE 781 * Remark : 782 * Status : UNTESTED STUB 783 * 784 * Author : Patrick Haller [Mon, 1998/06/15 08:00] 785 *****************************************************************************/ 786 787 BOOL HMDeviceCommClass::WriteFileEx(PHMHANDLEDATA pHMHandleData, 788 LPVOID lpBuffer, 789 DWORD nNumberOfBytesToWrite, 790 LPOVERLAPPED lpOverlapped, 791 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 792 { 793 dprintf(("ERROR: WriteFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n", 794 lpHMDeviceName, 795 pHMHandleData->hHMHandle, 796 lpBuffer, 797 nNumberOfBytesToWrite, 798 lpOverlapped, 799 lpCompletionRoutine)); 800 801 SetLastError(ERROR_INVALID_FUNCTION); 802 return FALSE; 803 } 804 805 /***************************************************************************** 806 * Name : BOOL HMDeviceCommClass::ReadFile 807 * Purpose : read data from handle / device 808 * Parameters: PHMHANDLEDATA pHMHandleData, 809 * LPCVOID lpBuffer, 810 * DWORD nNumberOfBytesToRead, 811 * LPDWORD lpNumberOfBytesRead, 812 * LPOVERLAPPED lpOverlapped 813 * Variables : 814 * Result : Boolean 815 * Remark : 816 * Status : 817 * 818 * Author : SvL 819 *****************************************************************************/ 820 821 BOOL HMDeviceCommClass::ReadFile(PHMHANDLEDATA pHMHandleData, 822 LPCVOID lpBuffer, 823 DWORD nNumberOfBytesToRead, 824 LPDWORD lpNumberOfBytesRead, 825 LPOVERLAPPED lpOverlapped) 826 { 827 dprintf(("KERNEL32:HMDeviceCommClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)", 828 lpHMDeviceName, 829 pHMHandleData->hHMHandle, 830 lpBuffer, 831 nNumberOfBytesToRead, 832 lpNumberOfBytesRead, 833 lpOverlapped)); 834 835 BOOL ret; 836 ULONG ulBytesRead; 837 838 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) { 839 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!")); 840 SetLastError(ERROR_INVALID_PARAMETER); 841 return FALSE; 842 } 843 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) { 844 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation")); 845 } 846 847 ret = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToRead, 848 &ulBytesRead); 849 850 if(lpNumberOfBytesRead) { 851 *lpNumberOfBytesRead = (ret) ? ulBytesRead : 0; 852 } 853 if(ret == FALSE) { 854 dprintf(("ERROR: ReadFile failed with rc %d", GetLastError())); 855 } 856 return ret; 857 } 858 859 /***************************************************************************** 860 * Name : BOOL ReadFileEx 861 * Purpose : The ReadFileEx function reads data from a file asynchronously. 862 * It is designed solely for asynchronous operation, unlike the 863 * ReadFile function, which is designed for both synchronous and 864 * asynchronous operation. ReadFileEx lets an application perform 865 * other processing during a file read operation. 866 * The ReadFileEx function reports its completion status asynchronously, 867 * calling a specified completion routine when reading is completed 868 * and the calling thread is in an alertable wait state. 869 * Parameters: HANDLE hFile handle of file to read 870 * LPVOID lpBuffer address of buffer 871 * DWORD nNumberOfBytesToRead number of bytes to read 872 * LPOVERLAPPED lpOverlapped address of offset 873 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine 874 * Variables : 875 * Result : TRUE / FALSE 876 * Remark : 877 * Status : UNTESTED STUB 878 * 879 * Author : Patrick Haller [Mon, 1998/06/15 08:00] 880 *****************************************************************************/ 881 BOOL HMDeviceCommClass::ReadFileEx(PHMHANDLEDATA pHMHandleData, 882 LPVOID lpBuffer, 883 DWORD nNumberOfBytesToRead, 884 LPOVERLAPPED lpOverlapped, 885 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 886 { 887 dprintf(("ERROR: ReadFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n", 888 lpHMDeviceName, 889 pHMHandleData->hHMHandle, 890 lpBuffer, 891 nNumberOfBytesToRead, 892 lpOverlapped, 893 lpCompletionRoutine)); 894 895 SetLastError(ERROR_INVALID_FUNCTION); 896 return FALSE; 897 } 898 1106 //****************************************************************************** 1107 //****************************************************************************** 899 1108 BOOL HMDeviceCommClass::SetCommBreak( PHMHANDLEDATA pHMHandleData ) 900 1109 { … … 914 1123 return(rc==0); 915 1124 } 916 1125 //****************************************************************************** 1126 //****************************************************************************** 917 1127 BOOL HMDeviceCommClass::ClearCommBreak( PHMHANDLEDATA pHMHandleData) 918 1128 { … … 932 1142 return(rc==0); 933 1143 } 934 1144 //****************************************************************************** 1145 //****************************************************************************** 935 1146 BOOL HMDeviceCommClass::SetCommConfig( PHMHANDLEDATA pHMHandleData, 936 1147 LPCOMMCONFIG lpCC, 937 1148 DWORD dwSize ) 938 1149 { 939 dprintf(("HMDeviceCommClass::SetCommConfig")); 940 1150 dprintf(("HMDeviceCommClass::SetCommConfig NOT IMPLEMENTED")); 941 1151 942 1152 return(TRUE); 943 1153 } 944 1154 //****************************************************************************** 1155 //****************************************************************************** 945 1156 BOOL HMDeviceCommClass::GetCommConfig( PHMHANDLEDATA pHMHandleData, 946 1157 LPCOMMCONFIG lpCC, … … 969 1180 return(TRUE); 970 1181 } 971 1182 //****************************************************************************** 1183 //****************************************************************************** 972 1184 BOOL HMDeviceCommClass::EscapeCommFunction( PHMHANDLEDATA pHMHandleData, 973 1185 UINT dwFunc ) … … 978 1190 MODEMSTATUS mdm; 979 1191 980 dprintf(("HMDeviceCommClass::EscapeCommFunction "));1192 dprintf(("HMDeviceCommClass::EscapeCommFunction %x", dwFunc)); 981 1193 982 1194 ulDLen = sizeof(USHORT); … … 1049 1261 break; 1050 1262 default: 1263 dprintf(("!ERROR!: EscapeCommFunction: unknown function")); 1051 1264 SetLastError(ERROR_INVALID_PARAMETER); 1052 1265 return(FALSE); … … 1055 1268 return(rc==0); 1056 1269 } 1057 1270 //****************************************************************************** 1271 //****************************************************************************** 1058 1272 BOOL HMDeviceCommClass::SetDefaultCommConfig( PHMHANDLEDATA pHMHandleData, 1059 1273 LPCOMMCONFIG lpCC, … … 1071 1285 return(TRUE); 1072 1286 } 1287 //****************************************************************************** 1288 //****************************************************************************** 1073 1289 BOOL HMDeviceCommClass::GetDefaultCommConfig( PHMHANDLEDATA pHMHandleData, 1074 1290 LPCOMMCONFIG lpCC, … … 1095 1311 return(TRUE); 1096 1312 } 1313 //****************************************************************************** 1314 //****************************************************************************** 1097 1315 APIRET HMDeviceCommClass::SetLine( PHMHANDLEDATA pHMHandleData, 1098 1316 UCHAR ucSize, … … 1132 1350 return rc; 1133 1351 } 1134 1352 //****************************************************************************** 1353 //****************************************************************************** 1135 1354 APIRET HMDeviceCommClass::SetOS2DCB( PHMHANDLEDATA pHMHandleData, 1136 1355 BOOL fOutxCtsFlow, BOOL fOutxDsrFlow, … … 1213 1432 1214 1433 } 1215 1434 //****************************************************************************** 1435 //****************************************************************************** 1216 1436 APIRET HMDeviceCommClass::SetBaud( PHMHANDLEDATA pHMHandleData, 1217 1437 DWORD dwNewBaud) … … 1249 1469 return rc; 1250 1470 } 1251 1252 1471 //****************************************************************************** 1472 //****************************************************************************** 1473 1474
Note:
See TracChangeset
for help on using the changeset viewer.