1 /* 2 * DEC 93 Erik Bos <erik@xs4all.nl> 3 * 4 * Copyright 1996 Marcus Meissner 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <k32.h> 22 23 typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; 24 #undef SERIAL_LSRMST_ESCAPE 25 #undef SERIAL_LSRMST_LSR_DATA 26 #undef SERIAL_LSRMST_LSR_NODATA 27 #undef SERIAL_LSRMST_MST 28 #undef SERIAL_IOC_FCR_FIFO_ENABLE 29 #undef SERIAL_IOC_FCR_RCVR_RESET 30 #undef SERIAL_IOC_FCR_XMIT_RESET 31 #undef SERIAL_IOC_FCR_DMA_MODE 32 #undef SERIAL_IOC_FCR_RES1 33 #undef SERIAL_IOC_FCR_RES2 34 #undef SERIAL_IOC_FCR_RCVR_TRIGGER_LSB 35 #undef SERIAL_IOC_FCR_RCVR_TRIGGER_MSB 36 #undef SERIAL_IOC_MCR_DTR 37 #undef SERIAL_IOC_MCR_RTS 38 #undef SERIAL_IOC_MCR_OUT1 39 #undef SERIAL_IOC_MCR_OUT2 40 #undef SERIAL_IOC_MCR_LOOP 41 #undef IOCTL_SERIAL_LSRMST_INSERT 42 #include <ntddser.h> 43 44 #define NDEBUG 45 #include <debug.h> 46 DEBUG_CHANNEL(comm); 47 48 /*********************************************************************** 49 * COMM_Parse* (Internal) 50 * 51 * The following COMM_Parse* functions are used by the BuildCommDCB 52 * functions to help parse the various parts of the device control string. 53 */ 54 static LPCWSTR COMM_ParseStart(LPCWSTR ptr) 55 { 56 static const WCHAR comW[] = {'C','O','M',0}; 57 58 /* The device control string may optionally start with "COMx" followed 59 by an optional ':' and spaces. */ 60 if(!strncmpiW(ptr, comW, 3)) 61 { 62 ptr += 3; 63 64 /* Allow any com port above 0 as Win 9x does (NT only allows 65 values for com ports which are actually present) */ 66 if(*ptr < '1' || *ptr > '9') 67 return NULL; 68 69 /* Advance pointer past port number */ 70 while(*ptr >= '0' && *ptr <= '9') ptr++; 71 72 /* The com port number must be followed by a ':' or ' ' */ 73 if(*ptr != ':' && *ptr != ' ') 74 return NULL; 75 76 /* Advance pointer to beginning of next parameter */ 77 while(*ptr == ' ') ptr++; 78 if(*ptr == ':') 79 { 80 ptr++; 81 while(*ptr == ' ') ptr++; 82 } 83 } 84 /* The device control string must not start with a space. */ 85 else if(*ptr == ' ') 86 return NULL; 87 88 return ptr; 89 } 90 91 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber) 92 { 93 if(*ptr < '0' || *ptr > '9') return NULL; 94 *lpnumber = strtoulW(ptr, NULL, 10); 95 while(*ptr >= '0' && *ptr <= '9') ptr++; 96 return ptr; 97 } 98 99 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity) 100 { 101 /* Contrary to what you might expect, Windows only sets the Parity 102 member of DCB and not fParity even when parity is specified in the 103 device control string */ 104 105 switch(toupperW(*ptr++)) 106 { 107 case 'E': 108 *lpparity = EVENPARITY; 109 break; 110 case 'M': 111 *lpparity = MARKPARITY; 112 break; 113 case 'N': 114 *lpparity = NOPARITY; 115 break; 116 case 'O': 117 *lpparity = ODDPARITY; 118 break; 119 case 'S': 120 *lpparity = SPACEPARITY; 121 break; 122 default: 123 return NULL; 124 } 125 126 return ptr; 127 } 128 129 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize) 130 { 131 DWORD temp; 132 133 if(!(ptr = COMM_ParseNumber(ptr, &temp))) 134 return NULL; 135 136 if(temp >= 5 && temp <= 8) 137 { 138 *lpbytesize = temp; 139 return ptr; 140 } 141 else 142 return NULL; 143 } 144 145 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits) 146 { 147 DWORD temp; 148 static const WCHAR stopbits15W[] = {'1','.','5',0}; 149 150 if(!strncmpW(stopbits15W, ptr, 3)) 151 { 152 ptr += 3; 153 *lpstopbits = ONE5STOPBITS; 154 } 155 else 156 { 157 if(!(ptr = COMM_ParseNumber(ptr, &temp))) 158 return NULL; 159 160 if(temp == 1) 161 *lpstopbits = ONESTOPBIT; 162 else if(temp == 2) 163 *lpstopbits = TWOSTOPBITS; 164 else 165 return NULL; 166 } 167 168 return ptr; 169 } 170 171 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff) 172 { 173 static const WCHAR onW[] = {'o','n',0}; 174 static const WCHAR offW[] = {'o','f','f',0}; 175 176 if(!strncmpiW(onW, ptr, 2)) 177 { 178 ptr += 2; 179 *lponoff = 1; 180 } 181 else if(!strncmpiW(offW, ptr, 3)) 182 { 183 ptr += 3; 184 *lponoff = 0; 185 } 186 else 187 return NULL; 188 189 return ptr; 190 } 191 192 /*********************************************************************** 193 * COMM_BuildOldCommDCB (Internal) 194 * 195 * Build a DCB using the old style settings string eg: "96,n,8,1" 196 */ 197 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb) 198 { 199 WCHAR last = 0; 200 201 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate))) 202 return FALSE; 203 204 switch(lpdcb->BaudRate) 205 { 206 case 11: 207 case 30: 208 case 60: 209 lpdcb->BaudRate *= 10; 210 break; 211 case 12: 212 case 24: 213 case 48: 214 case 96: 215 lpdcb->BaudRate *= 100; 216 break; 217 case 19: 218 lpdcb->BaudRate = 19200; 219 break; 220 } 221 222 while(*device == ' ') device++; 223 if(*device++ != ',') return FALSE; 224 while(*device == ' ') device++; 225 226 if(!(device = COMM_ParseParity(device, &lpdcb->Parity))) 227 return FALSE; 228 229 while(*device == ' ') device++; 230 if(*device++ != ',') return FALSE; 231 while(*device == ' ') device++; 232 233 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize))) 234 return FALSE; 235 236 while(*device == ' ') device++; 237 if(*device++ != ',') return FALSE; 238 while(*device == ' ') device++; 239 240 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits))) 241 return FALSE; 242 243 /* The last parameter for flow control is optional. */ 244 while(*device == ' ') device++; 245 if(*device == ',') 246 { 247 device++; 248 while(*device == ' ') device++; 249 if(*device) last = toupperW(*device++); 250 while(*device == ' ') device++; 251 } 252 253 /* Win NT sets the flow control members based on (or lack of) the last 254 parameter. Win 9x does not set these members. */ 255 switch(last) 256 { 257 case 0: 258 lpdcb->fInX = FALSE; 259 lpdcb->fOutX = FALSE; 260 lpdcb->fOutxCtsFlow = FALSE; 261 lpdcb->fOutxDsrFlow = FALSE; 262 lpdcb->fDtrControl = DTR_CONTROL_ENABLE; 263 lpdcb->fRtsControl = RTS_CONTROL_ENABLE; 264 break; 265 case 'X': 266 lpdcb->fInX = TRUE; 267 lpdcb->fOutX = TRUE; 268 lpdcb->fOutxCtsFlow = FALSE; 269 lpdcb->fOutxDsrFlow = FALSE; 270 lpdcb->fDtrControl = DTR_CONTROL_ENABLE; 271 lpdcb->fRtsControl = RTS_CONTROL_ENABLE; 272 break; 273 case 'P': 274 lpdcb->fInX = FALSE; 275 lpdcb->fOutX = FALSE; 276 lpdcb->fOutxCtsFlow = TRUE; 277 lpdcb->fOutxDsrFlow = TRUE; 278 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; 279 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; 280 break; 281 default: 282 return FALSE; 283 } 284 285 /* This should be the end of the string. */ 286 if(*device) return FALSE; 287 288 return TRUE; 289 } 290 291 /*********************************************************************** 292 * COMM_BuildNewCommDCB (Internal) 293 * 294 * Build a DCB using the new style settings string. 295 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on" 296 */ 297 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts) 298 { 299 DWORD temp; 300 BOOL baud = FALSE, stop = FALSE; 301 static const WCHAR baudW[] = {'b','a','u','d','=',0}; 302 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0}; 303 static const WCHAR dataW[] = {'d','a','t','a','=',0}; 304 static const WCHAR stopW[] = {'s','t','o','p','=',0}; 305 static const WCHAR toW[] = {'t','o','=',0}; 306 static const WCHAR xonW[] = {'x','o','n','=',0}; 307 static const WCHAR odsrW[] = {'o','d','s','r','=',0}; 308 static const WCHAR octsW[] = {'o','c','t','s','=',0}; 309 static const WCHAR dtrW[] = {'d','t','r','=',0}; 310 static const WCHAR rtsW[] = {'r','t','s','=',0}; 311 static const WCHAR idsrW[] = {'i','d','s','r','=',0}; 312 313 while(*device) 314 { 315 while(*device == ' ') device++; 316 317 if(!strncmpiW(baudW, device, 5)) 318 { 319 baud = TRUE; 320 321 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate))) 322 return FALSE; 323 } 324 else if(!strncmpiW(parityW, device, 7)) 325 { 326 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity))) 327 return FALSE; 328 } 329 else if(!strncmpiW(dataW, device, 5)) 330 { 331 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize))) 332 return FALSE; 333 } 334 else if(!strncmpiW(stopW, device, 5)) 335 { 336 stop = TRUE; 337 338 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits))) 339 return FALSE; 340 } 341 else if(!strncmpiW(toW, device, 3)) 342 { 343 if(!(device = COMM_ParseOnOff(device + 3, &temp))) 344 return FALSE; 345 346 lptimeouts->ReadIntervalTimeout = 0; 347 lptimeouts->ReadTotalTimeoutMultiplier = 0; 348 lptimeouts->ReadTotalTimeoutConstant = 0; 349 lptimeouts->WriteTotalTimeoutMultiplier = 0; 350 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0; 351 } 352 else if(!strncmpiW(xonW, device, 4)) 353 { 354 if(!(device = COMM_ParseOnOff(device + 4, &temp))) 355 return FALSE; 356 357 lpdcb->fOutX = temp; 358 lpdcb->fInX = temp; 359 } 360 else if(!strncmpiW(odsrW, device, 5)) 361 { 362 if(!(device = COMM_ParseOnOff(device + 5, &temp))) 363 return FALSE; 364 365 lpdcb->fOutxDsrFlow = temp; 366 } 367 else if(!strncmpiW(octsW, device, 5)) 368 { 369 if(!(device = COMM_ParseOnOff(device + 5, &temp))) 370 return FALSE; 371 372 lpdcb->fOutxCtsFlow = temp; 373 } 374 else if(!strncmpiW(dtrW, device, 4)) 375 { 376 if(!(device = COMM_ParseOnOff(device + 4, &temp))) 377 return FALSE; 378 379 lpdcb->fDtrControl = temp; 380 } 381 else if(!strncmpiW(rtsW, device, 4)) 382 { 383 if(!(device = COMM_ParseOnOff(device + 4, &temp))) 384 return FALSE; 385 386 lpdcb->fRtsControl = temp; 387 } 388 else if(!strncmpiW(idsrW, device, 5)) 389 { 390 if(!(device = COMM_ParseOnOff(device + 5, &temp))) 391 return FALSE; 392 393 /* Win NT sets the fDsrSensitivity member based on the 394 idsr parameter. Win 9x sets fOutxDsrFlow instead. */ 395 lpdcb->fDsrSensitivity = temp; 396 } 397 else 398 return FALSE; 399 400 /* After the above parsing, the next character (if not the end of 401 the string) should be a space */ 402 if(*device && *device != ' ') 403 return FALSE; 404 } 405 406 /* If stop bits were not specified, a default is always supplied. */ 407 if(!stop) 408 { 409 if(baud && lpdcb->BaudRate == 110) 410 lpdcb->StopBits = TWOSTOPBITS; 411 else 412 lpdcb->StopBits = ONESTOPBIT; 413 } 414 415 return TRUE; 416 } 417 418 /************************************************************************** 419 * BuildCommDCBA (KERNEL32.@) 420 * 421 * Updates a device control block data structure with values from an 422 * ascii device control string. The device control string has two forms 423 * normal and extended, it must be exclusively in one or the other form. 424 * 425 * RETURNS 426 * 427 * True on success, false on a malformed control string. 428 */ 429 BOOL WINAPI BuildCommDCBA( 430 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */ 431 LPDCB lpdcb) /* [out] The device control block to be updated. */ 432 { 433 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL); 434 } 435 436 /************************************************************************** 437 * BuildCommDCBAndTimeoutsA (KERNEL32.@) 438 * 439 * Updates a device control block data structure with values from an 440 * ascii device control string. Taking timeout values from a timeouts 441 * struct if desired by the control string. 442 * 443 * RETURNS 444 * 445 * True on success, false bad handles etc. 446 */ 447 BOOL WINAPI BuildCommDCBAndTimeoutsA( 448 LPCSTR device, /* [in] The ascii device control string. */ 449 LPDCB lpdcb, /* [out] The device control block to be updated. */ 450 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */ 451 { 452 BOOL ret = FALSE; 453 UNICODE_STRING deviceW; 454 455 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts); 456 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device); 457 else deviceW.Buffer = NULL; 458 459 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts); 460 461 RtlFreeUnicodeString(&deviceW); 462 return ret; 463 } 464 465 /************************************************************************** 466 * BuildCommDCBAndTimeoutsW (KERNEL32.@) 467 * 468 * Updates a device control block data structure with values from a 469 * unicode device control string. Taking timeout values from a timeouts 470 * struct if desired by the control string. 471 * 472 * RETURNS 473 * 474 * True on success, false bad handles etc 475 */ 476 BOOL WINAPI BuildCommDCBAndTimeoutsW( 477 LPCWSTR devid, /* [in] The unicode device control string. */ 478 LPDCB lpdcb, /* [out] The device control block to be updated. */ 479 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */ 480 { 481 DCB dcb; 482 COMMTIMEOUTS timeouts; 483 BOOL result; 484 LPCWSTR ptr = devid; 485 486 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts); 487 488 memset(&timeouts, 0, sizeof timeouts); 489 490 /* Set DCBlength. (Windows NT does not do this, but 9x does) */ 491 lpdcb->DCBlength = sizeof(DCB); 492 493 /* Make a copy of the original data structures to work with since if 494 if there is an error in the device control string the originals 495 should not be modified (except possibly DCBlength) */ 496 dcb = *lpdcb; 497 if(lptimeouts) timeouts = *lptimeouts; 498 499 ptr = COMM_ParseStart(ptr); 500 501 if(ptr == NULL) 502 result = FALSE; 503 else if(strchrW(ptr, ',')) 504 result = COMM_BuildOldCommDCB(ptr, &dcb); 505 else 506 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts); 507 508 if(result) 509 { 510 *lpdcb = dcb; 511 if(lptimeouts) *lptimeouts = timeouts; 512 return TRUE; 513 } 514 else 515 { 516 WARN("Invalid device control string: %s\n", debugstr_w(devid)); 517 SetLastError(ERROR_INVALID_PARAMETER); 518 return FALSE; 519 } 520 } 521 522 /************************************************************************** 523 * BuildCommDCBW (KERNEL32.@) 524 * 525 * Updates a device control block structure with values from an 526 * unicode device control string. The device control string has two forms 527 * normal and extended, it must be exclusively in one or the other form. 528 * 529 * RETURNS 530 * 531 * True on success, false on a malformed control string. 532 */ 533 BOOL WINAPI BuildCommDCBW( 534 LPCWSTR devid, /* [in] The unicode device control string. */ 535 LPDCB lpdcb) /* [out] The device control block to be updated. */ 536 { 537 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL); 538 } 539 540 /***************************************************************************** 541 * SetCommBreak (KERNEL32.@) 542 * 543 * Halts the transmission of characters to a communications device. 544 * 545 * PARAMS 546 * handle [in] The communications device to suspend 547 * 548 * RETURNS 549 * 550 * True on success, and false if the communications device could not be found, 551 * the control is not supported. 552 * 553 * BUGS 554 * 555 * Only TIOCSBRK and TIOCCBRK are supported. 556 */ 557 BOOL WINAPI SetCommBreak(HANDLE handle) 558 { 559 DWORD dwBytesReturned; 560 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL); 561 } 562 563 /***************************************************************************** 564 * ClearCommBreak (KERNEL32.@) 565 * 566 * Resumes character transmission from a communication device. 567 * 568 * PARAMS 569 * 570 * handle [in] The halted communication device whose character transmission is to be resumed 571 * 572 * RETURNS 573 * 574 * True on success and false if the communications device could not be found. 575 * 576 * BUGS 577 * 578 * Only TIOCSBRK and TIOCCBRK are supported. 579 */ 580 BOOL WINAPI ClearCommBreak(HANDLE handle) 581 { 582 DWORD dwBytesReturned; 583 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL); 584 } 585 586 /***************************************************************************** 587 * EscapeCommFunction (KERNEL32.@) 588 * 589 * Directs a communication device to perform an extended function. 590 * 591 * PARAMS 592 * 593 * handle [in] The communication device to perform the extended function 594 * nFunction [in] The extended function to be performed 595 * 596 * RETURNS 597 * 598 * True or requested data on successful completion of the command, 599 * false if the device is not present cannot execute the command 600 * or the command failed. 601 */ 602 BOOL WINAPI EscapeCommFunction(HANDLE handle, DWORD func) 603 { 604 DWORD ioc; 605 DWORD dwBytesReturned; 606 607 switch (func) 608 { 609 case CLRDTR: ioc = IOCTL_SERIAL_CLR_DTR; break; 610 case CLRRTS: ioc = IOCTL_SERIAL_CLR_RTS; break; 611 case SETDTR: ioc = IOCTL_SERIAL_SET_DTR; break; 612 case SETRTS: ioc = IOCTL_SERIAL_SET_RTS; break; 613 case SETXOFF: ioc = IOCTL_SERIAL_SET_XOFF; break; 614 case SETXON: ioc = IOCTL_SERIAL_SET_XON; break; 615 case SETBREAK: ioc = IOCTL_SERIAL_SET_BREAK_ON; break; 616 case CLRBREAK: ioc = IOCTL_SERIAL_SET_BREAK_OFF; break; 617 case RESETDEV: ioc = IOCTL_SERIAL_RESET_DEVICE; break; 618 default: 619 ERR("Unknown function code (%u)\n", func); 620 SetLastError(ERROR_INVALID_PARAMETER); 621 return FALSE; 622 } 623 return DeviceIoControl(handle, ioc, NULL, 0, NULL, 0, &dwBytesReturned, NULL); 624 } 625 626 /******************************************************************** 627 * PurgeComm (KERNEL32.@) 628 * 629 * Terminates pending operations and/or discards buffers on a 630 * communication resource. 631 * 632 * PARAMS 633 * 634 * handle [in] The communication resource to be purged 635 * flags [in] Flags for clear pending/buffer on input/output 636 * 637 * RETURNS 638 * 639 * True on success and false if the communications handle is bad. 640 */ 641 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags) 642 { 643 DWORD dwBytesReturned; 644 return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags), 645 NULL, 0, &dwBytesReturned, NULL); 646 } 647 648 /***************************************************************************** 649 * ClearCommError (KERNEL32.@) 650 * 651 * Enables further I/O operations on a communications resource after 652 * supplying error and current status information. 653 * 654 * PARAMS 655 * 656 * handle [in] The communication resource with the error 657 * errors [out] Flags indicating error the resource experienced 658 * lpStat [out] The status of the communication resource 659 * RETURNS 660 * 661 * True on success, false if the communication resource handle is bad. 662 */ 663 BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat) 664 { 665 SERIAL_STATUS ss; 666 DWORD dwBytesReturned; 667 668 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0, 669 &ss, sizeof(ss), &dwBytesReturned, NULL)) 670 return FALSE; 671 672 if (errors) 673 { 674 *errors = 0; 675 if (ss.Errors & SERIAL_ERROR_BREAK) *errors |= CE_BREAK; 676 if (ss.Errors & SERIAL_ERROR_FRAMING) *errors |= CE_FRAME; 677 if (ss.Errors & SERIAL_ERROR_OVERRUN) *errors |= CE_OVERRUN; 678 if (ss.Errors & SERIAL_ERROR_QUEUEOVERRUN) *errors |= CE_RXOVER; 679 if (ss.Errors & SERIAL_ERROR_PARITY) *errors |= CE_RXPARITY; 680 } 681 682 if (lpStat) 683 { 684 memset(lpStat, 0, sizeof(*lpStat)); 685 686 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) lpStat->fCtsHold = TRUE; 687 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) lpStat->fDsrHold = TRUE; 688 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) lpStat->fRlsdHold = TRUE; 689 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_XON) lpStat->fXoffHold = TRUE; 690 if (ss.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) lpStat->fXoffSent = TRUE; 691 if (ss.EofReceived) lpStat->fEof = TRUE; 692 if (ss.WaitForImmediate) lpStat->fTxim = TRUE; 693 lpStat->cbInQue = ss.AmountInInQueue; 694 lpStat->cbOutQue = ss.AmountInOutQueue; 695 } 696 return TRUE; 697 } 698 699 /***************************************************************************** 700 * SetupComm (KERNEL32.@) 701 * 702 * Called after CreateFile to hint to the communication resource to use 703 * specified sizes for input and output buffers rather than the default values. 704 * 705 * PARAMS 706 * handle [in] The just created communication resource handle 707 * insize [in] The suggested size of the communication resources input buffer in bytes 708 * outsize [in] The suggested size of the communication resources output buffer in bytes 709 * 710 * RETURNS 711 * 712 * True if successful, false if the communications resource handle is bad. 713 * 714 * BUGS 715 * 716 * Stub. 717 */ 718 BOOL WINAPI SetupComm(HANDLE handle, DWORD insize, DWORD outsize) 719 { 720 SERIAL_QUEUE_SIZE sqs; 721 DWORD dwBytesReturned; 722 723 sqs.InSize = insize; 724 sqs.OutSize = outsize; 725 return DeviceIoControl(handle, IOCTL_SERIAL_SET_QUEUE_SIZE, 726 &sqs, sizeof(sqs), NULL, 0, &dwBytesReturned, NULL); 727 } 728 729 /***************************************************************************** 730 * GetCommMask (KERNEL32.@) 731 * 732 * Obtain the events associated with a communication device that will cause 733 * a call WaitCommEvent to return. 734 * 735 * PARAMS 736 * 737 * handle [in] The communications device 738 * evtmask [out] The events which cause WaitCommEvent to return 739 * 740 * RETURNS 741 * 742 * True on success, fail on bad device handle etc. 743 */ 744 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask) 745 { 746 DWORD dwBytesReturned; 747 TRACE("handle %p, mask %p\n", handle, evtmask); 748 return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK, 749 NULL, 0, evtmask, sizeof(*evtmask), &dwBytesReturned, NULL); 750 } 751 752 /***************************************************************************** 753 * SetCommMask (KERNEL32.@) 754 * 755 * There be some things we need to hear about yon there communications device. 756 * (Set which events associated with a communication device should cause 757 * a call WaitCommEvent to return.) 758 * 759 * PARAMS 760 * 761 * handle [in] The communications device 762 * evtmask [in] The events that are to be monitored 763 * 764 * RETURNS 765 * 766 * True on success, false on bad handle etc. 767 */ 768 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask) 769 { 770 DWORD dwBytesReturned; 771 TRACE("handle %p, mask %x\n", handle, evtmask); 772 return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK, 773 &evtmask, sizeof(evtmask), NULL, 0, &dwBytesReturned, NULL); 774 } 775 776 static void dump_dcb(const DCB* lpdcb) 777 { 778 TRACE("bytesize=%d baudrate=%d fParity=%d Parity=%d stopbits=%d\n", 779 lpdcb->ByteSize, lpdcb->BaudRate, lpdcb->fParity, lpdcb->Parity, 780 (lpdcb->StopBits == ONESTOPBIT) ? 1 : 781 (lpdcb->StopBits == TWOSTOPBITS) ? 2 : 0); 782 TRACE("%sIXON %sIXOFF\n", (lpdcb->fOutX) ? "" : "~", (lpdcb->fInX) ? "" : "~"); 783 TRACE("fOutxCtsFlow=%d fRtsControl=%d\n", lpdcb->fOutxCtsFlow, lpdcb->fRtsControl); 784 TRACE("fOutxDsrFlow=%d fDtrControl=%d\n", lpdcb->fOutxDsrFlow, lpdcb->fDtrControl); 785 if (lpdcb->fOutxCtsFlow || lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE) 786 TRACE("CRTSCTS\n"); 787 else 788 TRACE("~CRTSCTS\n"); 789 } 790 791 /***************************************************************************** 792 * SetCommState (KERNEL32.@) 793 * 794 * Re-initializes all hardware and control settings of a communications device, 795 * with values from a device control block without affecting the input and output 796 * queues. 797 * 798 * PARAMS 799 * 800 * handle [in] The communications device 801 * lpdcb [out] The device control block 802 * 803 * RETURNS 804 * 805 * True on success, false on failure, e.g., if the XonChar is equal to the XoffChar. 806 */ 807 BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb) 808 { 809 SERIAL_BAUD_RATE sbr; 810 SERIAL_LINE_CONTROL slc; 811 SERIAL_HANDFLOW shf; 812 SERIAL_CHARS sc; 813 DWORD dwBytesReturned; 814 815 TRACE("handle %p, ptr %p\n", handle, lpdcb); 816 817 if (lpdcb == NULL) 818 { 819 SetLastError(ERROR_INVALID_PARAMETER); 820 return FALSE; 821 } 822 dump_dcb(lpdcb); 823 824 sbr.BaudRate = lpdcb->BaudRate; 825 826 slc.StopBits = lpdcb->StopBits; 827 slc.Parity = lpdcb->Parity; 828 slc.WordLength = lpdcb->ByteSize; 829 830 shf.ControlHandShake = 0; 831 shf.FlowReplace = 0; 832 if (lpdcb->fOutxCtsFlow) shf.ControlHandShake |= SERIAL_CTS_HANDSHAKE; 833 if (lpdcb->fOutxDsrFlow) shf.ControlHandShake |= SERIAL_DSR_HANDSHAKE; 834 switch (lpdcb->fDtrControl) 835 { 836 case DTR_CONTROL_DISABLE: break; 837 case DTR_CONTROL_ENABLE: shf.ControlHandShake |= SERIAL_DTR_CONTROL; break; 838 case DTR_CONTROL_HANDSHAKE: shf.ControlHandShake |= SERIAL_DTR_HANDSHAKE;break; 839 default: 840 SetLastError(ERROR_INVALID_PARAMETER); 841 return FALSE; 842 } 843 switch (lpdcb->fRtsControl) 844 { 845 case RTS_CONTROL_DISABLE: break; 846 case RTS_CONTROL_ENABLE: shf.FlowReplace |= SERIAL_RTS_CONTROL; break; 847 case RTS_CONTROL_HANDSHAKE: shf.FlowReplace |= SERIAL_RTS_HANDSHAKE; break; 848 case RTS_CONTROL_TOGGLE: shf.FlowReplace |= SERIAL_RTS_CONTROL | 849 SERIAL_RTS_HANDSHAKE; break; 850 default: 851 SetLastError(ERROR_INVALID_PARAMETER); 852 return FALSE; 853 } 854 if (lpdcb->fDsrSensitivity) shf.ControlHandShake |= SERIAL_DSR_SENSITIVITY; 855 if (lpdcb->fAbortOnError) shf.ControlHandShake |= SERIAL_ERROR_ABORT; 856 857 if (lpdcb->fErrorChar) shf.FlowReplace |= SERIAL_ERROR_CHAR; 858 if (lpdcb->fNull) shf.FlowReplace |= SERIAL_NULL_STRIPPING; 859 if (lpdcb->fTXContinueOnXoff) shf.FlowReplace |= SERIAL_XOFF_CONTINUE; 860 if (lpdcb->fOutX) shf.FlowReplace |= SERIAL_AUTO_TRANSMIT; 861 if (lpdcb->fInX) shf.FlowReplace |= SERIAL_AUTO_RECEIVE; 862 863 shf.XonLimit = lpdcb->XonLim; 864 shf.XoffLimit = lpdcb->XoffLim; 865 866 sc.EofChar = lpdcb->EofChar; 867 sc.ErrorChar = lpdcb->ErrorChar; 868 sc.BreakChar = 0; 869 sc.EventChar = lpdcb->EvtChar; 870 sc.XonChar = lpdcb->XonChar; 871 sc.XoffChar = lpdcb->XoffChar; 872 873 /* note: change DTR/RTS lines after setting the comm attributes, 874 * so flow control does not interfere. 875 */ 876 return (DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE, 877 &sbr, sizeof(sbr), NULL, 0, &dwBytesReturned, NULL) && 878 DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL, 879 &slc, sizeof(slc), NULL, 0, &dwBytesReturned, NULL) && 880 DeviceIoControl(handle, IOCTL_SERIAL_SET_HANDFLOW, 881 &shf, sizeof(shf), NULL, 0, &dwBytesReturned, NULL) && 882 DeviceIoControl(handle, IOCTL_SERIAL_SET_CHARS, 883 &sc, sizeof(sc), NULL, 0, &dwBytesReturned, NULL)); 884 } 885 886 887 /***************************************************************************** 888 * GetCommState (KERNEL32.@) 889 * 890 * Fills in a device control block with information from a communications device. 891 * 892 * PARAMS 893 * handle [in] The communications device 894 * lpdcb [out] The device control block 895 * 896 * RETURNS 897 * 898 * True on success, false if the communication device handle is bad etc 899 * 900 * BUGS 901 * 902 * XonChar and XoffChar are not set. 903 */ 904 BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb) 905 { 906 SERIAL_BAUD_RATE sbr; 907 SERIAL_LINE_CONTROL slc; 908 SERIAL_HANDFLOW shf; 909 SERIAL_CHARS sc; 910 DWORD dwBytesReturned; 911 912 TRACE("handle %p, ptr %p\n", handle, lpdcb); 913 914 if (!lpdcb) 915 { 916 SetLastError(ERROR_INVALID_PARAMETER); 917 return FALSE; 918 } 919 920 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE, 921 NULL, 0, &sbr, sizeof(sbr), &dwBytesReturned, NULL) || 922 !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL, 923 NULL, 0, &slc, sizeof(slc), &dwBytesReturned, NULL) || 924 !DeviceIoControl(handle, IOCTL_SERIAL_GET_HANDFLOW, 925 NULL, 0, &shf, sizeof(shf), &dwBytesReturned, NULL) || 926 !DeviceIoControl(handle, IOCTL_SERIAL_GET_CHARS, 927 NULL, 0, &sc, sizeof(sc), &dwBytesReturned, NULL)) 928 return FALSE; 929 930 memset(lpdcb, 0, sizeof(*lpdcb)); 931 lpdcb->DCBlength = sizeof(*lpdcb); 932 933 /* yes, they seem no never be (re)set on NT */ 934 lpdcb->fBinary = 1; 935 lpdcb->fParity = 0; 936 937 lpdcb->BaudRate = sbr.BaudRate; 938 939 lpdcb->StopBits = slc.StopBits; 940 lpdcb->Parity = slc.Parity; 941 lpdcb->ByteSize = slc.WordLength; 942 943 if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE) lpdcb->fOutxCtsFlow = 1; 944 if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE) lpdcb->fOutxDsrFlow = 1; 945 switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE)) 946 { 947 case 0: lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break; 948 case SERIAL_DTR_CONTROL: lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break; 949 case SERIAL_DTR_HANDSHAKE: lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break; 950 } 951 switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE)) 952 { 953 case 0: lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break; 954 case SERIAL_RTS_CONTROL: lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break; 955 case SERIAL_RTS_HANDSHAKE: lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break; 956 case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE: 957 lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break; 958 } 959 if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY) lpdcb->fDsrSensitivity = 1; 960 if (shf.ControlHandShake & SERIAL_ERROR_ABORT) lpdcb->fAbortOnError = 1; 961 if (shf.FlowReplace & SERIAL_ERROR_CHAR) lpdcb->fErrorChar = 1; 962 if (shf.FlowReplace & SERIAL_NULL_STRIPPING) lpdcb->fNull = 1; 963 if (shf.FlowReplace & SERIAL_XOFF_CONTINUE) lpdcb->fTXContinueOnXoff = 1; 964 lpdcb->XonLim = shf.XonLimit; 965 lpdcb->XoffLim = shf.XoffLimit; 966 967 if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1; 968 if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1; 969 970 lpdcb->EofChar = sc.EofChar; 971 lpdcb->ErrorChar = sc.ErrorChar; 972 lpdcb->EvtChar = sc.EventChar; 973 lpdcb->XonChar = sc.XonChar; 974 lpdcb->XoffChar = sc.XoffChar; 975 976 TRACE("OK\n"); 977 dump_dcb(lpdcb); 978 979 return TRUE; 980 } 981 982 /***************************************************************************** 983 * TransmitCommChar (KERNEL32.@) 984 * 985 * Transmits a single character in front of any pending characters in the 986 * output buffer. Usually used to send an interrupt character to a host. 987 * 988 * PARAMS 989 * hComm [in] The communication device in need of a command character 990 * chTransmit [in] The character to transmit 991 * 992 * RETURNS 993 * 994 * True if the call succeeded, false if the previous command character to the 995 * same device has not been sent yet the handle is bad etc. 996 * 997 */ 998 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit) 999 { 1000 DWORD dwBytesReturned; 1001 return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR, 1002 &chTransmit, sizeof(chTransmit), NULL, 0, &dwBytesReturned, NULL); 1003 } 1004 1005 1006 /***************************************************************************** 1007 * GetCommTimeouts (KERNEL32.@) 1008 * 1009 * Obtains the request timeout values for the communications device. 1010 * 1011 * PARAMS 1012 * hComm [in] The communications device 1013 * lptimeouts [out] The struct of request timeouts 1014 * 1015 * RETURNS 1016 * 1017 * True on success, false if communications device handle is bad 1018 * or the target structure is null. 1019 */ 1020 BOOL WINAPI GetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts) 1021 { 1022 SERIAL_TIMEOUTS st; 1023 DWORD dwBytesReturned; 1024 1025 TRACE("(%p, %p)\n", hComm, lptimeouts); 1026 if (!lptimeouts) 1027 { 1028 SetLastError(ERROR_INVALID_PARAMETER); 1029 return FALSE; 1030 } 1031 if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS, 1032 NULL, 0, &st, sizeof(st), &dwBytesReturned, NULL)) 1033 return FALSE; 1034 lptimeouts->ReadIntervalTimeout = st.ReadIntervalTimeout; 1035 lptimeouts->ReadTotalTimeoutMultiplier = st.ReadTotalTimeoutMultiplier; 1036 lptimeouts->ReadTotalTimeoutConstant = st.ReadTotalTimeoutConstant; 1037 lptimeouts->WriteTotalTimeoutMultiplier = st.WriteTotalTimeoutMultiplier; 1038 lptimeouts->WriteTotalTimeoutConstant = st.WriteTotalTimeoutConstant; 1039 return TRUE; 1040 } 1041 1042 /***************************************************************************** 1043 * SetCommTimeouts (KERNEL32.@) 1044 * 1045 * Sets the timeouts used when reading and writing data to/from COMM ports. 1046 * 1047 * PARAMS 1048 * hComm [in] handle of COMM device 1049 * lptimeouts [in] pointer to COMMTIMEOUTS structure 1050 * 1051 * ReadIntervalTimeout 1052 * - converted and passes to linux kernel as c_cc[VTIME] 1053 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant 1054 * - used in ReadFile to calculate GetOverlappedResult's timeout 1055 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant 1056 * - used in WriteFile to calculate GetOverlappedResult's timeout 1057 * 1058 * RETURNS 1059 * 1060 * True if the timeouts were set, false otherwise. 1061 */ 1062 BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts) 1063 { 1064 SERIAL_TIMEOUTS st; 1065 DWORD dwBytesReturned; 1066 1067 TRACE("(%p, %p)\n", hComm, lptimeouts); 1068 1069 if (lptimeouts == NULL) 1070 { 1071 SetLastError(ERROR_INVALID_PARAMETER); 1072 return FALSE; 1073 } 1074 st.ReadIntervalTimeout = lptimeouts->ReadIntervalTimeout; 1075 st.ReadTotalTimeoutMultiplier = lptimeouts->ReadTotalTimeoutMultiplier; 1076 st.ReadTotalTimeoutConstant = lptimeouts->ReadTotalTimeoutConstant; 1077 st.WriteTotalTimeoutMultiplier = lptimeouts->WriteTotalTimeoutMultiplier; 1078 st.WriteTotalTimeoutConstant = lptimeouts->WriteTotalTimeoutConstant; 1079 1080 return DeviceIoControl(hComm, IOCTL_SERIAL_SET_TIMEOUTS, 1081 &st, sizeof(st), NULL, 0, &dwBytesReturned, NULL); 1082 } 1083 1084 /*********************************************************************** 1085 * GetCommModemStatus (KERNEL32.@) 1086 * 1087 * Obtains the four control register bits if supported by the hardware. 1088 * 1089 * PARAMS 1090 * 1091 * hFile [in] The communications device 1092 * lpModemStat [out] The control register bits 1093 * 1094 * RETURNS 1095 * 1096 * True if the communications handle was good and for hardware that 1097 * control register access, false otherwise. 1098 */ 1099 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat) 1100 { 1101 DWORD dwBytesReturned; 1102 return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS, 1103 NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL); 1104 } 1105 1106 /*********************************************************************** 1107 * WaitCommEvent (KERNEL32.@) 1108 * 1109 * Wait until something interesting happens on a COMM port. 1110 * Interesting things (events) are set by calling SetCommMask before 1111 * this function is called. 1112 * 1113 * RETURNS 1114 * TRUE if successful 1115 * FALSE if failure 1116 * 1117 * The set of detected events will be written to *lpdwEventMask 1118 * ERROR_IO_PENDING will be returned the overlapped structure was passed 1119 * 1120 * BUGS: 1121 * Only supports EV_RXCHAR and EV_TXEMPTY 1122 */ 1123 BOOL WINAPI WaitCommEvent( 1124 HANDLE hFile, /* [in] handle of comm port to wait for */ 1125 LPDWORD lpdwEvents, /* [out] event(s) that were detected */ 1126 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */ 1127 { 1128 return DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK, NULL, 0, 1129 lpdwEvents, sizeof(DWORD), NULL, lpOverlapped); 1130 } 1131 1132 /*********************************************************************** 1133 * GetCommProperties (KERNEL32.@) 1134 * 1135 * This function fills in a structure with the capabilities of the 1136 * communications port driver. 1137 * 1138 * RETURNS 1139 * 1140 * TRUE on success, FALSE on failure 1141 * If successful, the lpCommProp structure be filled in with 1142 * properties of the comm port. 1143 */ 1144 BOOL WINAPI GetCommProperties( 1145 HANDLE hFile, /* [in] handle of the comm port */ 1146 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */ 1147 { 1148 TRACE("(%p %p)\n",hFile,lpCommProp); 1149 if(!lpCommProp) 1150 return FALSE; 1151 1152 /* 1153 * These values should be valid for LINUX's serial driver 1154 * FIXME: Perhaps they deserve an #ifdef LINUX 1155 */ 1156 memset(lpCommProp,0,sizeof(COMMPROP)); 1157 lpCommProp->wPacketLength = 1; 1158 lpCommProp->wPacketVersion = 1; 1159 lpCommProp->dwServiceMask = SP_SERIALCOMM; 1160 lpCommProp->dwMaxTxQueue = 4096; 1161 lpCommProp->dwMaxRxQueue = 4096; 1162 lpCommProp->dwMaxBaud = BAUD_115200; 1163 lpCommProp->dwProvSubType = PST_RS232; 1164 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS; 1165 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING | 1166 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ; 1167 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 | 1168 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 | 1169 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ; 1170 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ; 1171 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 | 1172 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE; 1173 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue; 1174 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue; 1175 1176 return TRUE; 1177 } 1178 1179 /*********************************************************************** 1180 * FIXME: 1181 * The functionality of CommConfigDialogA, GetDefaultCommConfig and 1182 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL). 1183 * This is dependent on the type of COMM port, but since it is doubtful 1184 * anybody will get around to implementing support for fancy serial 1185 * ports in WINE, this is hardcoded for the time being. The name of 1186 * this DLL should be stored in and read from the system registry in 1187 * the hive HKEY_LOCAL_MACHINE, key 1188 * System\\CurrentControlSet\\Services\\Class\\Ports\\???? 1189 * where ???? is the port number... that is determined by PNP 1190 * The DLL should be loaded when the COMM port is opened, and closed 1191 * when the COMM port is closed. - MJM 20 June 2000 1192 ***********************************************************************/ 1193 static const WCHAR lpszSerialUI[] = { 1194 's','e','r','i','a','l','u','i','.','d','l','l',0 }; 1195 1196 1197 /*********************************************************************** 1198 * CommConfigDialogA (KERNEL32.@) 1199 * 1200 * Raises a dialog that allows the user to configure a comm port. 1201 * Fills the COMMCONFIG struct with information specified by the user. 1202 * This function should call a similar routine in the COMM driver... 1203 * 1204 * RETURNS 1205 * 1206 * TRUE on success, FALSE on failure 1207 * If successful, the lpCommConfig structure will contain a new 1208 * configuration for the comm port, as specified by the user. 1209 * 1210 * BUGS 1211 * The library with the CommConfigDialog code is never unloaded. 1212 * Perhaps this should be done when the comm port is closed? 1213 */ 1214 BOOL WINAPI CommConfigDialogA( 1215 LPCSTR lpszDevice, /* [in] name of communications device */ 1216 HWND hWnd, /* [in] parent window for the dialog */ 1217 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */ 1218 { 1219 LPWSTR lpDeviceW = NULL; 1220 DWORD len; 1221 BOOL r; 1222 1223 TRACE("(%s, %p, %p)\n", debugstr_a(lpszDevice), hWnd, lpCommConfig); 1224 1225 if (lpszDevice) 1226 { 1227 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 ); 1228 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); 1229 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len ); 1230 } 1231 r = CommConfigDialogW(lpDeviceW, hWnd, lpCommConfig); 1232 HeapFree( GetProcessHeap(), 0, lpDeviceW ); 1233 return r; 1234 } 1235 1236 /*********************************************************************** 1237 * CommConfigDialogW (KERNEL32.@) 1238 * 1239 * See CommConfigDialogA. 1240 */ 1241 BOOL WINAPI CommConfigDialogW( 1242 LPCWSTR lpszDevice, /* [in] name of communications device */ 1243 HWND hWnd, /* [in] parent window for the dialog */ 1244 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */ 1245 { 1246 DWORD (WINAPI *pCommConfigDialog)(LPCWSTR, HWND, LPCOMMCONFIG); 1247 HMODULE hConfigModule; 1248 DWORD res = ERROR_INVALID_PARAMETER; 1249 1250 TRACE("(%s, %p, %p)\n", debugstr_w(lpszDevice), hWnd, lpCommConfig); 1251 hConfigModule = LoadLibraryW(lpszSerialUI); 1252 1253 if (hConfigModule) { 1254 pCommConfigDialog = (void *)GetProcAddress(hConfigModule, "drvCommConfigDialogW"); 1255 if (pCommConfigDialog) { 1256 res = pCommConfigDialog(lpszDevice, hWnd, lpCommConfig); 1257 } 1258 FreeLibrary(hConfigModule); 1259 } 1260 1261 if (res) SetLastError(res); 1262 return (res == ERROR_SUCCESS); 1263 } 1264 1265 /*********************************************************************** 1266 * GetCommConfig (KERNEL32.@) 1267 * 1268 * Fill in the COMMCONFIG structure for the comm port hFile 1269 * 1270 * RETURNS 1271 * 1272 * TRUE on success, FALSE on failure 1273 * If successful, lpCommConfig contains the comm port configuration. 1274 * 1275 * BUGS 1276 * 1277 */ 1278 BOOL WINAPI GetCommConfig( 1279 HANDLE hFile, /* [in] The communications device. */ 1280 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */ 1281 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure, 1282 afterwards the number of bytes copied to the buffer or 1283 the needed size of the buffer. */ 1284 { 1285 BOOL r; 1286 1287 TRACE("(%p, %p, %p) *lpdwSize: %u\n", hFile, lpCommConfig, lpdwSize, lpdwSize ? *lpdwSize : 0 ); 1288 1289 if(lpCommConfig == NULL) 1290 return FALSE; 1291 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */ 1292 *lpdwSize = sizeof(COMMCONFIG); 1293 if(r) 1294 return FALSE; 1295 1296 lpCommConfig->dwSize = sizeof(COMMCONFIG); 1297 lpCommConfig->wVersion = 1; 1298 lpCommConfig->wReserved = 0; 1299 r = GetCommState(hFile,&lpCommConfig->dcb); 1300 lpCommConfig->dwProviderSubType = PST_RS232; 1301 lpCommConfig->dwProviderOffset = 0; 1302 lpCommConfig->dwProviderSize = 0; 1303 1304 return r; 1305 } 1306 1307 /*********************************************************************** 1308 * SetCommConfig (KERNEL32.@) 1309 * 1310 * Sets the configuration of the communications device. 1311 * 1312 * RETURNS 1313 * 1314 * True on success, false if the handle was bad is not a communications device. 1315 */ 1316 BOOL WINAPI SetCommConfig( 1317 HANDLE hFile, /* [in] The communications device. */ 1318 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */ 1319 DWORD dwSize) /* [in] size of the lpCommConfig struct */ 1320 { 1321 TRACE("(%p, %p, %u)\n", hFile, lpCommConfig, dwSize); 1322 return SetCommState(hFile,&lpCommConfig->dcb); 1323 } 1324 1325 /*********************************************************************** 1326 * SetDefaultCommConfigW (KERNEL32.@) 1327 * 1328 * Initializes the default configuration for a communication device. 1329 * 1330 * PARAMS 1331 * lpszDevice [I] Name of the device targeted for configuration 1332 * lpCommConfig [I] PTR to a buffer with the configuration for the device 1333 * dwSize [I] Number of bytes in the buffer 1334 * 1335 * RETURNS 1336 * Failure: FALSE 1337 * Success: TRUE, and default configuration saved 1338 * 1339 */ 1340 BOOL WINAPI SetDefaultCommConfigW(LPCWSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize) 1341 { 1342 BOOL (WINAPI *lpfnSetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, DWORD); 1343 HMODULE hConfigModule; 1344 BOOL r = FALSE; 1345 1346 TRACE("(%s, %p, %u)\n", debugstr_w(lpszDevice), lpCommConfig, dwSize); 1347 1348 hConfigModule = LoadLibraryW(lpszSerialUI); 1349 if(!hConfigModule) 1350 return r; 1351 1352 lpfnSetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW"); 1353 if (lpfnSetDefaultCommConfig) 1354 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize); 1355 1356 FreeLibrary(hConfigModule); 1357 1358 return r; 1359 } 1360 1361 1362 /*********************************************************************** 1363 * SetDefaultCommConfigA (KERNEL32.@) 1364 * 1365 * Initializes the default configuration for a communication device. 1366 * 1367 * See SetDefaultCommConfigW. 1368 * 1369 */ 1370 BOOL WINAPI SetDefaultCommConfigA(LPCSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize) 1371 { 1372 BOOL r; 1373 LPWSTR lpDeviceW = NULL; 1374 DWORD len; 1375 1376 TRACE("(%s, %p, %u)\n", debugstr_a(lpszDevice), lpCommConfig, dwSize); 1377 1378 if (lpszDevice) 1379 { 1380 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 ); 1381 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); 1382 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len ); 1383 } 1384 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize); 1385 HeapFree( GetProcessHeap(), 0, lpDeviceW ); 1386 return r; 1387 } 1388 1389 1390 /*********************************************************************** 1391 * GetDefaultCommConfigW (KERNEL32.@) 1392 * 1393 * Acquires the default configuration of the specified communication device. (unicode) 1394 * 1395 * RETURNS 1396 * 1397 * True on successful reading of the default configuration, 1398 * if the device is not found or the buffer is too small. 1399 */ 1400 BOOL WINAPI GetDefaultCommConfigW( 1401 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */ 1402 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */ 1403 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer, 1404 afterwards the number of bytes copied to the buffer or 1405 the needed size of the buffer. */ 1406 { 1407 DWORD (WINAPI *pGetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, LPDWORD); 1408 HMODULE hConfigModule; 1409 DWORD res = ERROR_INVALID_PARAMETER; 1410 1411 TRACE("(%s, %p, %p) *lpdwSize: %u\n", debugstr_w(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 ); 1412 hConfigModule = LoadLibraryW(lpszSerialUI); 1413 1414 if (hConfigModule) { 1415 pGetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvGetDefaultCommConfigW"); 1416 if (pGetDefaultCommConfig) { 1417 res = pGetDefaultCommConfig(lpszName, lpCC, lpdwSize); 1418 } 1419 FreeLibrary(hConfigModule); 1420 } 1421 1422 if (res) SetLastError(res); 1423 return (res == ERROR_SUCCESS); 1424 } 1425 1426 /************************************************************************** 1427 * GetDefaultCommConfigA (KERNEL32.@) 1428 * 1429 * Acquires the default configuration of the specified communication device. (ascii) 1430 * 1431 * RETURNS 1432 * 1433 * True on successful reading of the default configuration, 1434 * if the device is not found or the buffer is too small. 1435 */ 1436 BOOL WINAPI GetDefaultCommConfigA( 1437 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */ 1438 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */ 1439 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer, 1440 afterwards the number of bytes copied to the buffer or 1441 the needed size of the buffer. */ 1442 { 1443 BOOL ret = FALSE; 1444 UNICODE_STRING lpszNameW; 1445 1446 TRACE("(%s, %p, %p) *lpdwSize: %u\n", debugstr_a(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 ); 1447 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName); 1448 else lpszNameW.Buffer = NULL; 1449 1450 ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize); 1451 1452 RtlFreeUnicodeString(&lpszNameW); 1453 return ret; 1454 } 1455