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