advpack: Forward GetVersionFromFileA/ExA to their Unicode counterparts.
[wine/wine-kai.git] / dlls / kernel / comm.c
blobcd25666c9dcfb9f2a206552e42b3a3f3e8aec857
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #ifdef HAVE_TERMIOS_H
28 #include <termios.h>
29 #endif
30 #include <fcntl.h>
31 #include <string.h>
32 #ifdef HAVE_STRINGS_H
33 # include <strings.h>
34 #endif
35 #include <errno.h>
36 #include <ctype.h>
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
39 #endif
40 #ifdef HAVE_SYS_FILIO_H
41 # include <sys/filio.h>
42 #endif
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
45 #endif
46 #ifdef HAVE_UNISTD_H
47 # include <unistd.h>
48 #endif
49 #ifdef HAVE_SYS_POLL_H
50 # include <sys/poll.h>
51 #endif
52 #ifdef HAVE_SYS_MODEM_H
53 # include <sys/modem.h>
54 #endif
55 #ifdef HAVE_SYS_STRTIO_H
56 # include <sys/strtio.h>
57 #endif
59 #define NONAMELESSUNION
60 #define NONAMELESSSTRUCT
61 #include "windef.h"
62 #include "winbase.h"
63 #include "winerror.h"
64 #include "winioctl.h"
65 #include "ddk/ntddser.h"
67 #include "wine/server.h"
68 #include "wine/unicode.h"
70 #include "wine/debug.h"
72 #ifdef HAVE_LINUX_SERIAL_H
73 #include <linux/serial.h>
74 #endif
76 WINE_DEFAULT_DEBUG_CHANNEL(comm);
78 /* retrieve the Unix handle corresponding to a comm handle */
79 static int get_comm_fd( HANDLE handle, DWORD access )
81 int fd, ret;
83 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
84 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
85 return fd;
88 /* release the Unix handle returned by get_comm_fd */
89 static inline void release_comm_fd( HANDLE handle, int fd )
91 wine_server_release_fd( handle, fd );
94 /* serial_irq_info
95 * local structure holding the irq values we need for WaitCommEvent()
97 * Stripped down from struct serial_icounter_struct, which may not be available on some systems
98 * As the modem line interrupts (cts, dsr, rng, dcd) only get updated with TIOCMIWAIT active,
99 * no need to carry them in the internal structure
102 typedef struct serial_irq_info
104 int rx , tx, frame, overrun, parity, brk, buf_overrun;
105 }serial_irq_info;
107 /***********************************************************************
108 * Data needed by the thread polling for the changing CommEvent
110 typedef struct async_commio
112 HANDLE handle;
113 char* buffer;
114 HANDLE hEvent;
115 DWORD evtmask;
116 DWORD mstat;
117 serial_irq_info irq_info;
118 } async_commio;
120 /***********************************************************************/
122 #if !defined(TIOCINQ) && defined(FIONREAD)
123 #define TIOCINQ FIONREAD
124 #endif
126 /***********************************************************************
127 * Get extended interrupt count info, needed for WaitCommEvent
129 static int COMM_GetEInfo(int fd, serial_irq_info *irq_info)
131 #ifdef TIOCGICOUNT
132 struct serial_icounter_struct einfo;
133 if (!ioctl(fd,TIOCGICOUNT, &einfo))
135 irq_info->rx = einfo.rx;
136 irq_info->tx = einfo.tx;
137 irq_info->frame = einfo.frame;
138 irq_info->overrun = einfo.overrun;
139 irq_info->parity = einfo.parity;
140 irq_info->brk = einfo.brk;
141 irq_info->buf_overrun = einfo.buf_overrun;
142 return 0;
144 #endif
145 memset(irq_info,0, sizeof(serial_irq_info));
146 return -1;
149 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
151 #ifdef TIOCMGET
152 unsigned int mstat, okay;
153 okay = ioctl(fd, TIOCMGET, &mstat);
154 if (okay) return okay;
155 if (andy) mstat &= andy;
156 mstat |= orrie;
157 return ioctl(fd, TIOCMSET, &mstat);
158 #else
159 return 0;
160 #endif
163 /***********************************************************************
164 * COMM_Parse* (Internal)
166 * The following COMM_Parse* functions are used by the BuildCommDCB
167 * functions to help parse the various parts of the device control string.
169 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
171 static const WCHAR comW[] = {'C','O','M',0};
173 /* The device control string may optionally start with "COMx" followed
174 by an optional ':' and spaces. */
175 if(!strncmpiW(ptr, comW, 3))
177 ptr += 3;
179 /* Allow any com port above 0 as Win 9x does (NT only allows
180 values for com ports which are actually present) */
181 if(*ptr < '1' || *ptr > '9')
182 return NULL;
184 /* Advance pointer past port number */
185 while(*ptr >= '0' && *ptr <= '9') ptr++;
187 /* The com port number must be followed by a ':' or ' ' */
188 if(*ptr != ':' && *ptr != ' ')
189 return NULL;
191 /* Advance pointer to beginning of next parameter */
192 while(*ptr == ' ') ptr++;
193 if(*ptr == ':')
195 ptr++;
196 while(*ptr == ' ') ptr++;
199 /* The device control string must not start with a space. */
200 else if(*ptr == ' ')
201 return NULL;
203 return ptr;
206 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
208 if(*ptr < '0' || *ptr > '9') return NULL;
209 *lpnumber = strtoulW(ptr, NULL, 10);
210 while(*ptr >= '0' && *ptr <= '9') ptr++;
211 return ptr;
214 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
216 /* Contrary to what you might expect, Windows only sets the Parity
217 member of DCB and not fParity even when parity is specified in the
218 device control string */
220 switch(toupperW(*ptr++))
222 case 'E':
223 *lpparity = EVENPARITY;
224 break;
225 case 'M':
226 *lpparity = MARKPARITY;
227 break;
228 case 'N':
229 *lpparity = NOPARITY;
230 break;
231 case 'O':
232 *lpparity = ODDPARITY;
233 break;
234 case 'S':
235 *lpparity = SPACEPARITY;
236 break;
237 default:
238 return NULL;
241 return ptr;
244 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
246 DWORD temp;
248 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
249 return NULL;
251 if(temp >= 5 && temp <= 8)
253 *lpbytesize = temp;
254 return ptr;
256 else
257 return NULL;
260 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
262 DWORD temp;
263 static const WCHAR stopbits15W[] = {'1','.','5',0};
265 if(!strncmpW(stopbits15W, ptr, 3))
267 ptr += 3;
268 *lpstopbits = ONE5STOPBITS;
270 else
272 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
273 return NULL;
275 if(temp == 1)
276 *lpstopbits = ONESTOPBIT;
277 else if(temp == 2)
278 *lpstopbits = TWOSTOPBITS;
279 else
280 return NULL;
283 return ptr;
286 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
288 static const WCHAR onW[] = {'o','n',0};
289 static const WCHAR offW[] = {'o','f','f',0};
291 if(!strncmpiW(onW, ptr, 2))
293 ptr += 2;
294 *lponoff = 1;
296 else if(!strncmpiW(offW, ptr, 3))
298 ptr += 3;
299 *lponoff = 0;
301 else
302 return NULL;
304 return ptr;
307 /***********************************************************************
308 * COMM_BuildOldCommDCB (Internal)
310 * Build a DCB using the old style settings string eg: "96,n,8,1"
312 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
314 WCHAR last = 0;
316 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
317 return FALSE;
319 switch(lpdcb->BaudRate)
321 case 11:
322 case 30:
323 case 60:
324 lpdcb->BaudRate *= 10;
325 break;
326 case 12:
327 case 24:
328 case 48:
329 case 96:
330 lpdcb->BaudRate *= 100;
331 break;
332 case 19:
333 lpdcb->BaudRate = 19200;
334 break;
337 while(*device == ' ') device++;
338 if(*device++ != ',') return FALSE;
339 while(*device == ' ') device++;
341 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
342 return FALSE;
344 while(*device == ' ') device++;
345 if(*device++ != ',') return FALSE;
346 while(*device == ' ') device++;
348 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
349 return FALSE;
351 while(*device == ' ') device++;
352 if(*device++ != ',') return FALSE;
353 while(*device == ' ') device++;
355 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
356 return FALSE;
358 /* The last parameter for flow control is optional. */
359 while(*device == ' ') device++;
360 if(*device == ',')
362 device++;
363 while(*device == ' ') device++;
364 if(*device) last = toupperW(*device++);
365 while(*device == ' ') device++;
368 /* Win NT sets the flow control members based on (or lack of) the last
369 parameter. Win 9x does not set these members. */
370 switch(last)
372 case 0:
373 lpdcb->fInX = FALSE;
374 lpdcb->fOutX = FALSE;
375 lpdcb->fOutxCtsFlow = FALSE;
376 lpdcb->fOutxDsrFlow = FALSE;
377 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
378 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
379 break;
380 case 'X':
381 lpdcb->fInX = TRUE;
382 lpdcb->fOutX = TRUE;
383 lpdcb->fOutxCtsFlow = FALSE;
384 lpdcb->fOutxDsrFlow = FALSE;
385 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
386 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
387 break;
388 case 'P':
389 lpdcb->fInX = FALSE;
390 lpdcb->fOutX = FALSE;
391 lpdcb->fOutxCtsFlow = TRUE;
392 lpdcb->fOutxDsrFlow = TRUE;
393 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
394 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
395 break;
396 default:
397 return FALSE;
400 /* This should be the end of the string. */
401 if(*device) return FALSE;
403 return TRUE;
406 /***********************************************************************
407 * COMM_BuildNewCommDCB (Internal)
409 * Build a DCB using the new style settings string.
410 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
412 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
414 DWORD temp;
415 BOOL baud = FALSE, stop = FALSE;
416 static const WCHAR baudW[] = {'b','a','u','d','=',0};
417 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
418 static const WCHAR dataW[] = {'d','a','t','a','=',0};
419 static const WCHAR stopW[] = {'s','t','o','p','=',0};
420 static const WCHAR toW[] = {'t','o','=',0};
421 static const WCHAR xonW[] = {'x','o','n','=',0};
422 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
423 static const WCHAR octsW[] = {'o','c','t','s','=',0};
424 static const WCHAR dtrW[] = {'d','t','r','=',0};
425 static const WCHAR rtsW[] = {'r','t','s','=',0};
426 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
428 while(*device)
430 while(*device == ' ') device++;
432 if(!strncmpiW(baudW, device, 5))
434 baud = TRUE;
436 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
437 return FALSE;
439 else if(!strncmpiW(parityW, device, 7))
441 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
442 return FALSE;
444 else if(!strncmpiW(dataW, device, 5))
446 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
447 return FALSE;
449 else if(!strncmpiW(stopW, device, 5))
451 stop = TRUE;
453 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
454 return FALSE;
456 else if(!strncmpiW(toW, device, 3))
458 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
459 return FALSE;
461 lptimeouts->ReadIntervalTimeout = 0;
462 lptimeouts->ReadTotalTimeoutMultiplier = 0;
463 lptimeouts->ReadTotalTimeoutConstant = 0;
464 lptimeouts->WriteTotalTimeoutMultiplier = 0;
465 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
467 else if(!strncmpiW(xonW, device, 4))
469 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
470 return FALSE;
472 lpdcb->fOutX = temp;
473 lpdcb->fInX = temp;
475 else if(!strncmpiW(odsrW, device, 5))
477 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
478 return FALSE;
480 lpdcb->fOutxDsrFlow = temp;
482 else if(!strncmpiW(octsW, device, 5))
484 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
485 return FALSE;
487 lpdcb->fOutxCtsFlow = temp;
489 else if(!strncmpiW(dtrW, device, 4))
491 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
492 return FALSE;
494 lpdcb->fDtrControl = temp;
496 else if(!strncmpiW(rtsW, device, 4))
498 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
499 return FALSE;
501 lpdcb->fRtsControl = temp;
503 else if(!strncmpiW(idsrW, device, 5))
505 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
506 return FALSE;
508 /* Win NT sets the fDsrSensitivity member based on the
509 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
510 lpdcb->fDsrSensitivity = temp;
512 else
513 return FALSE;
515 /* After the above parsing, the next character (if not the end of
516 the string) should be a space */
517 if(*device && *device != ' ')
518 return FALSE;
521 /* If stop bits were not specified, a default is always supplied. */
522 if(!stop)
524 if(baud && lpdcb->BaudRate == 110)
525 lpdcb->StopBits = TWOSTOPBITS;
526 else
527 lpdcb->StopBits = ONESTOPBIT;
530 return TRUE;
533 /**************************************************************************
534 * BuildCommDCBA (KERNEL32.@)
536 * Updates a device control block data structure with values from an
537 * ascii device control string. The device control string has two forms
538 * normal and extended, it must be exclusively in one or the other form.
540 * RETURNS
542 * True on success, false on a malformed control string.
544 BOOL WINAPI BuildCommDCBA(
545 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
546 LPDCB lpdcb) /* [out] The device control block to be updated. */
548 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
551 /**************************************************************************
552 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
554 * Updates a device control block data structure with values from an
555 * ascii device control string. Taking timeout values from a timeouts
556 * struct if desired by the control string.
558 * RETURNS
560 * True on success, false bad handles etc.
562 BOOL WINAPI BuildCommDCBAndTimeoutsA(
563 LPCSTR device, /* [in] The ascii device control string. */
564 LPDCB lpdcb, /* [out] The device control block to be updated. */
565 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
567 BOOL ret = FALSE;
568 UNICODE_STRING deviceW;
570 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
571 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
572 else deviceW.Buffer = NULL;
574 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
576 RtlFreeUnicodeString(&deviceW);
577 return ret;
580 /**************************************************************************
581 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
583 * Updates a device control block data structure with values from a
584 * unicode device control string. Taking timeout values from a timeouts
585 * struct if desired by the control string.
587 * RETURNS
589 * True on success, false bad handles etc
591 BOOL WINAPI BuildCommDCBAndTimeoutsW(
592 LPCWSTR devid, /* [in] The unicode device control string. */
593 LPDCB lpdcb, /* [out] The device control block to be updated. */
594 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
596 DCB dcb;
597 COMMTIMEOUTS timeouts;
598 BOOL result;
599 LPCWSTR ptr = devid;
601 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
603 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
604 lpdcb->DCBlength = sizeof(DCB);
606 /* Make a copy of the original data structures to work with since if
607 if there is an error in the device control string the originals
608 should not be modified (except possibly DCBlength) */
609 memcpy(&dcb, lpdcb, sizeof(DCB));
610 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
612 ptr = COMM_ParseStart(ptr);
614 if(ptr == NULL)
615 result = FALSE;
616 else if(strchrW(ptr, ','))
617 result = COMM_BuildOldCommDCB(ptr, &dcb);
618 else
619 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
621 if(result)
623 memcpy(lpdcb, &dcb, sizeof(DCB));
624 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
625 return TRUE;
627 else
629 WARN("Invalid device control string: %s\n", debugstr_w(devid));
630 SetLastError(ERROR_INVALID_PARAMETER);
631 return FALSE;
635 /**************************************************************************
636 * BuildCommDCBW (KERNEL32.@)
638 * Updates a device control block structure with values from an
639 * unicode device control string. The device control string has two forms
640 * normal and extended, it must be exclusively in one or the other form.
642 * RETURNS
644 * True on success, false on a malformed control string.
646 BOOL WINAPI BuildCommDCBW(
647 LPCWSTR devid, /* [in] The unicode device control string. */
648 LPDCB lpdcb) /* [out] The device control block to be updated. */
650 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
653 /*****************************************************************************
654 * SetCommBreak (KERNEL32.@)
656 * Halts the transmission of characters to a communications device.
658 * PARAMS
659 * handle [in] The communications device to suspend
661 * RETURNS
663 * True on success, and false if the communications device could not be found,
664 * the control is not supported.
666 * BUGS
668 * Only TIOCSBRK and TIOCCBRK are supported.
670 BOOL WINAPI SetCommBreak(HANDLE handle)
672 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, NULL, NULL);
675 /*****************************************************************************
676 * ClearCommBreak (KERNEL32.@)
678 * Resumes character transmission from a communication device.
680 * PARAMS
682 * handle [in] The halted communication device whose character transmission is to be resumed
684 * RETURNS
686 * True on success and false if the communications device could not be found.
688 * BUGS
690 * Only TIOCSBRK and TIOCCBRK are supported.
692 BOOL WINAPI ClearCommBreak(HANDLE handle)
694 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, NULL, NULL);
697 /*****************************************************************************
698 * EscapeCommFunction (KERNEL32.@)
700 * Directs a communication device to perform an extended function.
702 * RETURNS
704 * True or requested data on successful completion of the command,
705 * false if the device is not present cannot execute the command
706 * or the command failed.
708 BOOL WINAPI EscapeCommFunction(
709 HANDLE handle, /* [in] The communication device to perform the extended function. */
710 UINT nFunction) /* [in] The extended function to be performed. */
712 int fd,direct=FALSE,result=FALSE;
713 struct termios port;
715 TRACE("handle %p, function=%d\n", handle, nFunction);
716 fd = get_comm_fd( handle, FILE_READ_DATA );
717 if(fd<0) return FALSE;
719 if (tcgetattr(fd,&port) == -1) {
720 release_comm_fd( handle, fd );
721 return FALSE;
724 switch (nFunction) {
725 case RESETDEV:
726 TRACE("\n");
727 break;
729 case CLRDTR:
730 TRACE("CLRDTR\n");
731 #ifdef TIOCM_DTR
732 direct=TRUE;
733 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
734 break;
735 #endif
737 case CLRRTS:
738 TRACE("CLRRTS\n");
739 #ifdef TIOCM_RTS
740 direct=TRUE;
741 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
742 break;
743 #endif
745 case SETDTR:
746 TRACE("SETDTR\n");
747 #ifdef TIOCM_DTR
748 direct=TRUE;
749 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
750 break;
751 #endif
753 case SETRTS:
754 TRACE("SETRTS\n");
755 #ifdef TIOCM_RTS
756 direct=TRUE;
757 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
758 break;
759 #endif
761 case SETXOFF:
762 TRACE("SETXOFF\n");
763 port.c_iflag |= IXOFF;
764 break;
766 case SETXON:
767 TRACE("SETXON\n");
768 port.c_iflag |= IXON;
769 break;
770 case SETBREAK:
771 TRACE("setbreak\n");
772 #ifdef TIOCSBRK
773 direct=TRUE;
774 result = ioctl(fd,TIOCSBRK,0);
775 break;
776 #endif
777 case CLRBREAK:
778 TRACE("clrbreak\n");
779 #ifdef TIOCSBRK
780 direct=TRUE;
781 result = ioctl(fd,TIOCCBRK,0);
782 break;
783 #endif
784 default:
785 WARN("(handle=%p,nFunction=%d): Unknown function\n",
786 handle, nFunction);
787 break;
790 if (!direct)
791 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
792 release_comm_fd( handle, fd );
793 return FALSE;
794 } else
795 result= TRUE;
796 else
798 if (result == -1)
800 result= FALSE;
802 else
803 result = TRUE;
805 release_comm_fd( handle, fd );
806 return result;
809 /********************************************************************
810 * PurgeComm (KERNEL32.@)
812 * Terminates pending operations and/or discards buffers on a
813 * communication resource.
815 * PARAMS
817 * handle [in] The communication resource to be purged
818 * flags [in] Flags for clear pending/buffer on input/output
820 * RETURNS
822 * True on success and false if the communications handle is bad.
824 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags)
826 return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags),
827 NULL, 0, NULL, NULL);
830 /*****************************************************************************
831 * ClearCommError (KERNEL32.@)
833 * Enables further I/O operations on a communications resource after
834 * supplying error and current status information.
836 * PARAMS
838 * handle [in] The communication resource with the error
839 * errors [out] Flags indicating error the resource experienced
840 * lpStat [out] The status of the communication resource
841 * RETURNS
843 * True on success, false if the communication resource handle is bad.
845 BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat)
847 SERIAL_STATUS ss;
849 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0,
850 &ss, sizeof(ss), NULL, NULL))
851 return FALSE;
853 if (errors)
855 *errors = 0;
856 if (ss.Errors & SERIAL_ERROR_BREAK) *errors |= CE_BREAK;
857 if (ss.Errors & SERIAL_ERROR_FRAMING) *errors |= CE_FRAME;
858 if (ss.Errors & SERIAL_ERROR_OVERRUN) *errors |= CE_OVERRUN;
859 if (ss.Errors & SERIAL_ERROR_QUEUEOVERRUN) *errors |= CE_RXOVER;
860 if (ss.Errors & SERIAL_ERROR_PARITY) *errors |= CE_RXPARITY;
863 if (lpStat)
865 memset(lpStat, 0, sizeof(*lpStat));
867 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) lpStat->fCtsHold = TRUE;
868 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) lpStat->fDsrHold = TRUE;
869 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) lpStat->fRlsdHold = TRUE;
870 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_XON) lpStat->fXoffHold = TRUE;
871 if (ss.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) lpStat->fXoffSent = TRUE;
872 if (ss.EofReceived) lpStat->fEof = TRUE;
873 if (ss.WaitForImmediate) lpStat->fTxim = TRUE;
874 lpStat->cbInQue = ss.AmountInInQueue;
875 lpStat->cbOutQue = ss.AmountInOutQueue;
877 return TRUE;
880 /*****************************************************************************
881 * SetupComm (KERNEL32.@)
883 * Called after CreateFile to hint to the communication resource to use
884 * specified sizes for input and output buffers rather than the default values.
886 * RETURNS
888 * True if successful, false if the communications resource handle is bad.
890 * BUGS
892 * Stub.
894 BOOL WINAPI SetupComm(
895 HANDLE handle, /* [in] The just created communication resource handle. */
896 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
897 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
899 int fd;
901 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
902 fd=get_comm_fd( handle, FILE_READ_DATA );
903 if(0>fd) return FALSE;
904 release_comm_fd( handle, fd );
905 return TRUE;
908 /*****************************************************************************
909 * GetCommMask (KERNEL32.@)
911 * Obtain the events associated with a communication device that will cause
912 * a call WaitCommEvent to return.
914 * PARAMS
916 * handle [in] The communications device
917 * evtmask [out] The events which cause WaitCommEvent to return
919 * RETURNS
921 * True on success, fail on bad device handle etc.
923 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask)
925 TRACE("handle %p, mask %p\n", handle, evtmask);
926 return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK,
927 NULL, 0, evtmask, sizeof(*evtmask), NULL, NULL);
930 /*****************************************************************************
931 * SetCommMask (KERNEL32.@)
933 * There be some things we need to hear about yon there communications device.
934 * (Set which events associated with a communication device should cause
935 * a call WaitCommEvent to return.)
937 * PARAMS
939 * handle [in] The communications device
940 * evtmask [in] The events that are to be monitored
942 * RETURNS
944 * True on success, false on bad handle etc.
946 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
948 TRACE("handle %p, mask %lx\n", handle, evtmask);
949 return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK,
950 &evtmask, sizeof(evtmask), NULL, 0, NULL, NULL);
953 /*****************************************************************************
954 * SetCommState (KERNEL32.@)
956 * Re-initializes all hardware and control settings of a communications device,
957 * with values from a device control block without effecting the input and output
958 * queues.
960 * RETURNS
962 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
964 BOOL WINAPI SetCommState(
965 HANDLE handle, /* [in] The communications device. */
966 LPDCB lpdcb) /* [out] The device control block. */
968 struct termios port;
969 int fd, bytesize, stopbits;
970 BOOL ret;
972 TRACE("handle %p, ptr %p\n", handle, lpdcb);
973 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
974 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
975 (lpdcb->StopBits == ONESTOPBIT)?1:
976 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
977 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
978 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
979 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
980 lpdcb->fRtsControl);
981 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
982 lpdcb->fDtrControl);
985 fd = get_comm_fd( handle, FILE_READ_DATA );
986 if (fd < 0) return FALSE;
988 if ((tcgetattr(fd,&port)) == -1) {
989 int save_error = errno;
990 release_comm_fd( handle, fd );
991 ERR("tcgetattr error '%s'\n", strerror(save_error));
992 return FALSE;
995 port.c_cc[VMIN] = 0;
996 port.c_cc[VTIME] = 1;
998 #ifdef IMAXBEL
999 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK|IMAXBEL);
1000 #else
1001 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK);
1002 #endif
1003 port.c_iflag |= (IGNBRK);
1005 port.c_oflag &= ~(OPOST);
1007 port.c_cflag &= ~(HUPCL);
1008 port.c_cflag |= CLOCAL | CREAD;
1010 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1011 port.c_lflag |= NOFLSH;
1013 #ifdef CBAUD
1014 port.c_cflag &= ~CBAUD;
1015 switch (lpdcb->BaudRate) {
1016 case 0:
1017 port.c_cflag |= B0;
1018 break;
1019 case 50:
1020 port.c_cflag |= B50;
1021 break;
1022 case 75:
1023 port.c_cflag |= B75;
1024 break;
1025 case 110:
1026 case CBR_110:
1027 port.c_cflag |= B110;
1028 break;
1029 case 134:
1030 port.c_cflag |= B134;
1031 break;
1032 case 150:
1033 port.c_cflag |= B150;
1034 break;
1035 case 200:
1036 port.c_cflag |= B200;
1037 break;
1038 case 300:
1039 case CBR_300:
1040 port.c_cflag |= B300;
1041 break;
1042 case 600:
1043 case CBR_600:
1044 port.c_cflag |= B600;
1045 break;
1046 case 1200:
1047 case CBR_1200:
1048 port.c_cflag |= B1200;
1049 break;
1050 case 1800:
1051 port.c_cflag |= B1800;
1052 break;
1053 case 2400:
1054 case CBR_2400:
1055 port.c_cflag |= B2400;
1056 break;
1057 case 4800:
1058 case CBR_4800:
1059 port.c_cflag |= B4800;
1060 break;
1061 case 9600:
1062 case CBR_9600:
1063 port.c_cflag |= B9600;
1064 break;
1065 case 19200:
1066 case CBR_19200:
1067 port.c_cflag |= B19200;
1068 break;
1069 case 38400:
1070 case CBR_38400:
1071 port.c_cflag |= B38400;
1072 break;
1073 #ifdef B57600
1074 case 57600:
1075 port.c_cflag |= B57600;
1076 break;
1077 #endif
1078 #ifdef B115200
1079 case 115200:
1080 port.c_cflag |= B115200;
1081 break;
1082 #endif
1083 #ifdef B230400
1084 case 230400:
1085 port.c_cflag |= B230400;
1086 break;
1087 #endif
1088 #ifdef B460800
1089 case 460800:
1090 port.c_cflag |= B460800;
1091 break;
1092 #endif
1093 default:
1094 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1095 { struct serial_struct nuts;
1096 int arby;
1097 ioctl(fd, TIOCGSERIAL, &nuts);
1098 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1099 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1100 arby = nuts.baud_base / nuts.custom_divisor;
1101 nuts.flags &= ~ASYNC_SPD_MASK;
1102 nuts.flags |= ASYNC_SPD_CUST;
1103 WARN("You (or a program acting at your behest) have specified\n"
1104 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1105 "which is as close as we can get by our present understanding of your\n"
1106 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1107 "has caused to your linux system can be undone with setserial \n"
1108 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1109 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1110 ioctl(fd, TIOCSSERIAL, &nuts);
1111 port.c_cflag |= B38400;
1113 break;
1114 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1117 release_comm_fd( handle, fd );
1118 ERR("baudrate %ld\n",lpdcb->BaudRate);
1119 return FALSE;
1121 #elif !defined(__EMX__)
1122 switch (lpdcb->BaudRate) {
1123 case 0:
1124 port.c_ospeed = B0;
1125 break;
1126 case 50:
1127 port.c_ospeed = B50;
1128 break;
1129 case 75:
1130 port.c_ospeed = B75;
1131 break;
1132 case 110:
1133 case CBR_110:
1134 port.c_ospeed = B110;
1135 break;
1136 case 134:
1137 port.c_ospeed = B134;
1138 break;
1139 case 150:
1140 port.c_ospeed = B150;
1141 break;
1142 case 200:
1143 port.c_ospeed = B200;
1144 break;
1145 case 300:
1146 case CBR_300:
1147 port.c_ospeed = B300;
1148 break;
1149 case 600:
1150 case CBR_600:
1151 port.c_ospeed = B600;
1152 break;
1153 case 1200:
1154 case CBR_1200:
1155 port.c_ospeed = B1200;
1156 break;
1157 case 1800:
1158 port.c_ospeed = B1800;
1159 break;
1160 case 2400:
1161 case CBR_2400:
1162 port.c_ospeed = B2400;
1163 break;
1164 case 4800:
1165 case CBR_4800:
1166 port.c_ospeed = B4800;
1167 break;
1168 case 9600:
1169 case CBR_9600:
1170 port.c_ospeed = B9600;
1171 break;
1172 case 19200:
1173 case CBR_19200:
1174 port.c_ospeed = B19200;
1175 break;
1176 case 38400:
1177 case CBR_38400:
1178 port.c_ospeed = B38400;
1179 break;
1180 #ifdef B57600
1181 case 57600:
1182 case CBR_57600:
1183 port.c_cflag |= B57600;
1184 break;
1185 #endif
1186 #ifdef B115200
1187 case 115200:
1188 case CBR_115200:
1189 port.c_cflag |= B115200;
1190 break;
1191 #endif
1192 #ifdef B230400
1193 case 230400:
1194 port.c_cflag |= B230400;
1195 break;
1196 #endif
1197 #ifdef B460800
1198 case 460800:
1199 port.c_cflag |= B460800;
1200 break;
1201 #endif
1202 default:
1203 release_comm_fd( handle, fd );
1204 ERR("baudrate %ld\n",lpdcb->BaudRate);
1205 return FALSE;
1207 port.c_ispeed = port.c_ospeed;
1208 #endif
1209 bytesize=lpdcb->ByteSize;
1210 stopbits=lpdcb->StopBits;
1212 #ifdef CMSPAR
1213 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1214 #else
1215 port.c_cflag &= ~(PARENB | PARODD);
1216 #endif
1217 if (lpdcb->fParity)
1218 port.c_iflag |= INPCK;
1219 else
1220 port.c_iflag &= ~INPCK;
1221 switch (lpdcb->Parity) {
1222 case NOPARITY:
1223 break;
1224 case ODDPARITY:
1225 port.c_cflag |= (PARENB | PARODD);
1226 break;
1227 case EVENPARITY:
1228 port.c_cflag |= PARENB;
1229 break;
1230 #ifdef CMSPAR
1231 /* Linux defines mark/space (stick) parity */
1232 case MARKPARITY:
1233 port.c_cflag |= (PARENB | CMSPAR);
1234 break;
1235 case SPACEPARITY:
1236 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1237 break;
1238 #else
1239 /* try the POSIX way */
1240 case MARKPARITY:
1241 if( stopbits == ONESTOPBIT) {
1242 stopbits = TWOSTOPBITS;
1243 port.c_iflag &= ~INPCK;
1244 } else {
1245 release_comm_fd( handle, fd );
1246 ERR("Cannot set MARK Parity\n");
1247 return FALSE;
1249 break;
1250 case SPACEPARITY:
1251 if( bytesize < 8) {
1252 bytesize +=1;
1253 port.c_iflag &= ~INPCK;
1254 } else {
1255 release_comm_fd( handle, fd );
1256 ERR("Cannot set SPACE Parity\n");
1257 return FALSE;
1259 break;
1260 #endif
1261 default:
1262 release_comm_fd( handle, fd );
1263 ERR("Parity\n");
1264 return FALSE;
1268 port.c_cflag &= ~CSIZE;
1269 switch (bytesize) {
1270 case 5:
1271 port.c_cflag |= CS5;
1272 break;
1273 case 6:
1274 port.c_cflag |= CS6;
1275 break;
1276 case 7:
1277 port.c_cflag |= CS7;
1278 break;
1279 case 8:
1280 port.c_cflag |= CS8;
1281 break;
1282 default:
1283 release_comm_fd( handle, fd );
1284 ERR("ByteSize\n");
1285 return FALSE;
1288 switch (stopbits) {
1289 case ONESTOPBIT:
1290 port.c_cflag &= ~CSTOPB;
1291 break;
1292 case ONE5STOPBITS: /* will be selected if bytesize is 5 */
1293 case TWOSTOPBITS:
1294 port.c_cflag |= CSTOPB;
1295 break;
1296 default:
1297 release_comm_fd( handle, fd );
1298 ERR("StopBits\n");
1299 return FALSE;
1301 #ifdef CRTSCTS
1302 if ( lpdcb->fOutxCtsFlow ||
1303 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1306 port.c_cflag |= CRTSCTS;
1307 TRACE("CRTSCTS\n");
1309 #endif
1311 if (lpdcb->fInX)
1312 port.c_iflag |= IXON;
1313 else
1314 port.c_iflag &= ~IXON;
1315 if (lpdcb->fOutX)
1316 port.c_iflag |= IXOFF;
1317 else
1318 port.c_iflag &= ~IXOFF;
1320 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1321 ERR("tcsetattr error '%s'\n", strerror(errno));
1322 ret = FALSE;
1323 } else {
1324 ClearCommError(handle, NULL, NULL);
1325 ret = TRUE;
1328 /* note: change DTR/RTS lines after setting the comm attributes,
1329 * so flow control does not interfere. */
1330 #ifdef TIOCM_DTR
1331 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1333 WARN("DSR/DTR flow control not supported\n");
1334 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1335 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1336 else
1337 COMM_WhackModem(fd, 0, TIOCM_DTR);
1338 #endif
1339 #ifdef TIOCM_RTS
1340 if(!lpdcb->fOutxCtsFlow )
1342 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1343 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1344 else
1345 COMM_WhackModem(fd, 0, TIOCM_RTS);
1347 #endif
1348 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1349 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1350 release_comm_fd( handle, fd );
1351 return ret;
1356 /*****************************************************************************
1357 * GetCommState (KERNEL32.@)
1359 * Fills in a device control block with information from a communications device.
1361 * RETURNS
1363 * True on success, false if the communication device handle is bad etc
1365 * BUGS
1367 * XonChar and XoffChar are not set.
1369 BOOL WINAPI GetCommState(
1370 HANDLE handle, /* [in] The communications device. */
1371 LPDCB lpdcb) /* [out] The device control block. */
1373 struct termios port;
1374 int fd,speed;
1375 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1377 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1379 fd = get_comm_fd( handle, FILE_READ_DATA );
1380 if (fd < 0) return FALSE;
1381 if (tcgetattr(fd, &port) == -1) {
1382 int save_error=errno;
1383 ERR("tcgetattr error '%s'\n", strerror(save_error));
1384 release_comm_fd( handle, fd );
1385 return FALSE;
1388 #ifdef TIOCMGET
1389 if (ioctl(fd, TIOCMGET, &stat) == -1)
1391 int save_error=errno;
1392 WARN("ioctl error '%s'\n", strerror(save_error));
1393 stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1395 #endif
1396 release_comm_fd( handle, fd );
1397 #ifndef __EMX__
1398 #ifdef CBAUD
1399 speed= (port.c_cflag & CBAUD);
1400 #else
1401 speed= (cfgetospeed(&port));
1402 #endif
1403 switch (speed) {
1404 case B0:
1405 lpdcb->BaudRate = 0;
1406 break;
1407 case B50:
1408 lpdcb->BaudRate = 50;
1409 break;
1410 case B75:
1411 lpdcb->BaudRate = 75;
1412 break;
1413 case B110:
1414 lpdcb->BaudRate = 110;
1415 break;
1416 case B134:
1417 lpdcb->BaudRate = 134;
1418 break;
1419 case B150:
1420 lpdcb->BaudRate = 150;
1421 break;
1422 case B200:
1423 lpdcb->BaudRate = 200;
1424 break;
1425 case B300:
1426 lpdcb->BaudRate = 300;
1427 break;
1428 case B600:
1429 lpdcb->BaudRate = 600;
1430 break;
1431 case B1200:
1432 lpdcb->BaudRate = 1200;
1433 break;
1434 case B1800:
1435 lpdcb->BaudRate = 1800;
1436 break;
1437 case B2400:
1438 lpdcb->BaudRate = 2400;
1439 break;
1440 case B4800:
1441 lpdcb->BaudRate = 4800;
1442 break;
1443 case B9600:
1444 lpdcb->BaudRate = 9600;
1445 break;
1446 case B19200:
1447 lpdcb->BaudRate = 19200;
1448 break;
1449 case B38400:
1450 lpdcb->BaudRate = 38400;
1451 break;
1452 #ifdef B57600
1453 case B57600:
1454 lpdcb->BaudRate = 57600;
1455 break;
1456 #endif
1457 #ifdef B115200
1458 case B115200:
1459 lpdcb->BaudRate = 115200;
1460 break;
1461 #endif
1462 #ifdef B230400
1463 case B230400:
1464 lpdcb->BaudRate = 230400;
1465 break;
1466 #endif
1467 #ifdef B460800
1468 case B460800:
1469 lpdcb->BaudRate = 460800;
1470 break;
1471 #endif
1472 default:
1473 ERR("unknown speed %x\n", speed);
1475 #endif
1476 switch (port.c_cflag & CSIZE) {
1477 case CS5:
1478 lpdcb->ByteSize = 5;
1479 break;
1480 case CS6:
1481 lpdcb->ByteSize = 6;
1482 break;
1483 case CS7:
1484 lpdcb->ByteSize = 7;
1485 break;
1486 case CS8:
1487 lpdcb->ByteSize = 8;
1488 break;
1489 default:
1490 ERR("unknown size %x\n", port.c_cflag & CSIZE);
1493 if(port.c_iflag & INPCK)
1494 lpdcb->fParity = TRUE;
1495 else
1496 lpdcb->fParity = FALSE;
1497 #ifdef CMSPAR
1498 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1499 #else
1500 switch (port.c_cflag & (PARENB | PARODD))
1501 #endif
1503 case 0:
1504 lpdcb->Parity = NOPARITY;
1505 break;
1506 case PARENB:
1507 lpdcb->Parity = EVENPARITY;
1508 break;
1509 case (PARENB | PARODD):
1510 lpdcb->Parity = ODDPARITY;
1511 break;
1512 #ifdef CMSPAR
1513 case (PARENB | CMSPAR):
1514 lpdcb->Parity = MARKPARITY;
1515 break;
1516 case (PARENB | PARODD | CMSPAR):
1517 lpdcb->Parity = SPACEPARITY;
1518 break;
1519 #endif
1522 if (port.c_cflag & CSTOPB)
1523 if(lpdcb->ByteSize == 5)
1524 lpdcb->StopBits = ONE5STOPBITS;
1525 else
1526 lpdcb->StopBits = TWOSTOPBITS;
1527 else
1528 lpdcb->StopBits = ONESTOPBIT;
1530 lpdcb->fNull = 0;
1531 lpdcb->fBinary = 1;
1533 /* termios does not support DTR/DSR flow control */
1534 lpdcb->fOutxDsrFlow = 0;
1535 lpdcb->fDtrControl =
1536 #ifdef TIOCM_DTR
1537 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1538 #endif
1539 DTR_CONTROL_ENABLE ;
1541 #ifdef CRTSCTS
1543 if (port.c_cflag & CRTSCTS) {
1544 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1545 lpdcb->fOutxCtsFlow = 1;
1546 } else
1547 #endif
1549 lpdcb->fRtsControl =
1550 #ifdef TIOCM_RTS
1551 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1552 #endif
1553 RTS_CONTROL_ENABLE ;
1554 lpdcb->fOutxCtsFlow = 0;
1556 if (port.c_iflag & IXON)
1557 lpdcb->fInX = 1;
1558 else
1559 lpdcb->fInX = 0;
1561 if (port.c_iflag & IXOFF)
1562 lpdcb->fOutX = 1;
1563 else
1564 lpdcb->fOutX = 0;
1566 lpdcb->XonChar =
1567 lpdcb->XoffChar =
1569 lpdcb->XonLim = 10;
1570 lpdcb->XoffLim = 10;
1572 TRACE("OK\n");
1574 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1575 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1576 (lpdcb->StopBits == ONESTOPBIT)?1:
1577 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1578 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1579 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1580 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1581 lpdcb->fRtsControl);
1582 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1583 lpdcb->fDtrControl);
1584 #ifdef CRTSCTS
1585 if ( lpdcb->fOutxCtsFlow ||
1586 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1588 TRACE("CRTSCTS\n");
1589 else
1591 TRACE("~CRTSCTS\n");
1592 #endif
1593 return TRUE;
1596 /*****************************************************************************
1597 * TransmitCommChar (KERNEL32.@)
1599 * Transmits a single character in front of any pending characters in the
1600 * output buffer. Usually used to send an interrupt character to a host.
1602 * PARAMS
1603 * hComm [in] The communication device in need of a command character
1604 * chTransmit [in] The character to transmit
1606 * RETURNS
1608 * True if the call succeeded, false if the previous command character to the
1609 * same device has not been sent yet the handle is bad etc.
1612 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
1614 return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR,
1615 &chTransmit, sizeof(chTransmit), NULL, 0, NULL, NULL);
1619 /*****************************************************************************
1620 * GetCommTimeouts (KERNEL32.@)
1622 * Obtains the request timeout values for the communications device.
1624 * RETURNS
1626 * True on success, false if communications device handle is bad
1627 * or the target structure is null.
1629 BOOL WINAPI GetCommTimeouts(
1630 HANDLE hComm, /* [in] The communications device. */
1631 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1633 BOOL ret;
1635 TRACE("(%p,%p)\n",hComm,lptimeouts);
1637 if(!lptimeouts)
1639 SetLastError(ERROR_INVALID_PARAMETER);
1640 return FALSE;
1643 SERVER_START_REQ( get_serial_info )
1645 req->handle = hComm;
1646 if ((ret = !wine_server_call_err( req )))
1648 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1649 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1650 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1651 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1652 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1655 SERVER_END_REQ;
1656 return ret;
1659 /*****************************************************************************
1660 * SetCommTimeouts (KERNEL32.@)
1662 * Sets the timeouts used when reading and writing data to/from COMM ports.
1664 * ReadIntervalTimeout
1665 * - converted and passes to linux kernel as c_cc[VTIME]
1666 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1667 * - used in ReadFile to calculate GetOverlappedResult's timeout
1668 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1669 * - used in WriteFile to calculate GetOverlappedResult's timeout
1671 * RETURNS
1673 * True if the timeouts were set, false otherwise.
1675 BOOL WINAPI SetCommTimeouts(
1676 HANDLE hComm, /* [in] handle of COMM device */
1677 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1679 BOOL ret;
1680 int fd;
1681 struct termios tios;
1683 TRACE("(%p,%p)\n",hComm,lptimeouts);
1685 if(!lptimeouts)
1687 SetLastError(ERROR_INVALID_PARAMETER);
1688 return FALSE;
1691 SERVER_START_REQ( set_serial_info )
1693 req->handle = hComm;
1694 req->flags = SERIALINFO_SET_TIMEOUTS;
1695 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1696 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1697 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1698 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1699 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1700 ret = !wine_server_call_err( req );
1702 SERVER_END_REQ;
1703 if (!ret) return FALSE;
1705 /* FIXME: move this stuff to the server */
1706 fd = get_comm_fd( hComm, FILE_READ_DATA );
1707 if (fd < 0) return FALSE;
1709 if (-1==tcgetattr(fd,&tios)) {
1710 FIXME("tcgetattr on fd %d failed!\n",fd);
1711 release_comm_fd( hComm, fd );
1712 return FALSE;
1715 /* VTIME is in 1/10 seconds */
1717 unsigned int ux_timeout;
1719 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1721 ux_timeout = 0;
1723 else
1725 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1726 if(ux_timeout == 0)
1728 ux_timeout = 1; /* must be at least some timeout */
1731 tios.c_cc[VTIME] = ux_timeout;
1734 if (-1==tcsetattr(fd,0,&tios)) {
1735 FIXME("tcsetattr on fd %d failed!\n",fd);
1736 release_comm_fd( hComm, fd );
1737 return FALSE;
1739 release_comm_fd( hComm, fd );
1740 return TRUE;
1743 /***********************************************************************
1744 * GetCommModemStatus (KERNEL32.@)
1746 * Obtains the four control register bits if supported by the hardware.
1748 * PARAMS
1750 * hFile [in] The communications device
1751 * lpModemStat [out] The control register bits
1753 * RETURNS
1755 * True if the communications handle was good and for hardware that
1756 * control register access, false otherwise.
1758 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
1760 return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
1761 NULL, 0, lpModemStat, sizeof(DWORD), NULL, NULL);
1764 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1766 DWORD ret = 0, queue;
1768 TRACE("mask 0x%08lx\n", mask);
1769 TRACE("old->rx 0x%08x vs. new->rx 0x%08x\n", old->rx, new->rx);
1770 TRACE("old->tx 0x%08x vs. new->tx 0x%08x\n", old->tx, new->tx);
1771 TRACE("old->frame 0x%08x vs. new->frame 0x%08x\n", old->frame, new->frame);
1772 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x\n", old->overrun, new->overrun);
1773 TRACE("old->parity 0x%08x vs. new->parity 0x%08x\n", old->parity, new->parity);
1774 TRACE("old->brk 0x%08x vs. new->brk 0x%08x\n", old->brk, new->brk);
1775 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x\n", old->buf_overrun, new->buf_overrun);
1777 ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1778 ret |= ((mask & EV_CTS ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS :0;
1779 ret |= ((mask & EV_DSR ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR :0;
1780 ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1781 ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1782 ret |= ((mask & EV_ERR ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1783 || (old->parity != new->parity)) )?EV_ERR :0;
1784 if (mask & EV_RXCHAR)
1786 queue = 0;
1787 #ifdef TIOCINQ
1788 if(ioctl(fd, TIOCINQ, &queue))
1789 WARN("TIOCINQ returned error\n");
1790 #endif
1791 if (queue)
1792 ret |= EV_RXCHAR;
1794 if (mask & EV_TXEMPTY)
1796 queue = 0;
1797 /* We really want to know when all characters have gone out of the transmitter */
1798 #if defined(TIOCSERGETLSR)
1799 if(ioctl(fd, TIOCSERGETLSR, &queue))
1800 WARN("TIOCSERGETLSR returned error\n");
1801 if (queue)
1802 /* TIOCINQ only checks for an empty buffer */
1803 #elif defined(TIOCINQ)
1804 if(ioctl(fd, TIOCOUTQ, &queue))
1805 WARN("TIOCOUTQ returned error\n");
1806 if (!queue)
1807 #endif
1808 ret |= EV_TXEMPTY;
1810 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1811 return ret;
1815 /***********************************************************************
1816 * COMM_WaitCommEventService (INTERNAL)
1818 * We need to poll for what is interesting
1819 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1822 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1824 async_commio *commio = (async_commio*) arg;
1825 int waitmask = 0;
1826 int rc, fd, abort;
1827 serial_irq_info new_irq_info;
1828 DWORD new_mstat, new_evtmask;
1830 fd=get_comm_fd( commio->handle, FILE_READ_DATA );
1832 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1833 commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1837 * TIOCMIWAIT is not adequate
1839 * FIXME:
1840 * We don't handle the EV_RXFLAG (the eventchar)
1842 Sleep(1);
1843 rc= COMM_GetEInfo(fd,&new_irq_info);
1844 if (rc)
1845 TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1846 rc = GetCommModemStatus(commio->handle, &new_mstat);
1847 if (!rc)
1848 TRACE("GetCommModemStatus failed\n");
1849 rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
1850 GetCommMask(commio->handle, &new_evtmask);
1851 abort = (commio->evtmask != new_evtmask);
1852 TRACE("resulting Eventmask 0x%08x\n", rc);
1853 } while (!rc && ! abort);
1854 if (abort) rc = 0;
1855 release_comm_fd( commio->handle, fd );
1856 *commio->buffer = rc;
1857 if (commio->hEvent != INVALID_HANDLE_VALUE )
1858 NtSetEvent( commio->hEvent, NULL );
1859 HeapFree(GetProcessHeap(), 0, commio );
1860 return 0;
1864 /***********************************************************************
1865 * COMM_WaitCommEvent (INTERNAL)
1867 * This function must have an lpOverlapped.
1869 static BOOL COMM_WaitCommEvent(
1870 HANDLE hFile, /* [in] handle of comm port to wait for */
1871 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1872 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1874 int fd;
1875 async_commio* commio;
1876 DWORD result_mask;
1877 BOOL res;
1879 if (!lpOverlapped)
1881 SetLastError(ERROR_INVALID_PARAMETER);
1882 return FALSE;
1885 if (NtResetEvent(lpOverlapped->hEvent,NULL))
1886 return FALSE;
1888 fd = get_comm_fd( hFile, FILE_WRITE_DATA );
1889 if (fd < 0) return FALSE;
1891 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1892 if (!commio)
1894 release_comm_fd( hFile, fd );
1895 return FALSE;
1898 commio->handle = hFile;
1899 commio->buffer = (char *)lpdwEvents;
1900 commio->hEvent = lpOverlapped->hEvent;
1901 GetCommMask(hFile, &commio->evtmask);
1903 /* We may never return, if some capabilities miss
1904 * Return error in that case
1906 #if !defined(TIOCINQ)
1907 if(commio->evtmask & EV_RXCHAR)
1908 goto error;
1909 #endif
1910 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
1911 if(commio->evtmask & EV_TXEMPTY)
1912 goto error;
1913 #endif
1914 #if !defined(TIOCMGET)
1915 if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
1916 goto error;
1917 #endif
1918 #if !defined(TIOCM_CTS)
1919 if(commio->evtmask & EV_CTS)
1920 goto error;
1921 #endif
1922 #if !defined(TIOCM_DSR)
1923 if(commio->evtmask & EV_DSR)
1924 goto error;
1925 #endif
1926 #if !defined(TIOCM_RNG)
1927 if(commio->evtmask & EV_RING)
1928 goto error;
1929 #endif
1930 #if !defined(TIOCM_CAR)
1931 if(commio->evtmask & EV_RLSD)
1932 goto error;
1933 #endif
1934 if(commio->evtmask & EV_RXFLAG)
1935 FIXME("EV_RXFLAG not handled\n");
1936 COMM_GetEInfo(fd,&commio->irq_info);
1937 GetCommModemStatus(hFile, &commio->mstat);
1938 /* We might have received something or the TX bufffer is delivered*/
1939 result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
1940 if (result_mask)
1942 TRACE("Event already met\n");
1943 *lpdwEvents = result_mask;
1944 HeapFree(GetProcessHeap(), 0, commio );
1945 res = TRUE;
1947 else
1949 CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
1950 SetLastError(ERROR_IO_PENDING);
1951 res = FALSE;
1953 release_comm_fd( hFile, fd );
1954 return res;
1955 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
1956 error:
1957 FIXME("Returning error because of missing capabilities\n");
1958 release_comm_fd( hFile, fd );
1959 HeapFree(GetProcessHeap(), 0, commio );
1960 SetLastError(ERROR_INVALID_PARAMETER);
1961 return FALSE;
1962 #endif
1964 /***********************************************************************
1965 * WaitCommEvent (KERNEL32.@)
1967 * Wait until something interesting happens on a COMM port.
1968 * Interesting things (events) are set by calling SetCommMask before
1969 * this function is called.
1971 * RETURNS
1972 * TRUE if successful
1973 * FALSE if failure
1975 * The set of detected events will be written to *lpdwEventMask
1976 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1978 * BUGS:
1979 * Only supports EV_RXCHAR and EV_TXEMPTY
1981 BOOL WINAPI WaitCommEvent(
1982 HANDLE hFile, /* [in] handle of comm port to wait for */
1983 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1984 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1986 OVERLAPPED ov;
1987 int ret = 0;
1988 DWORD res, err;
1990 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1992 if(lpOverlapped)
1993 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1995 /* if there is no overlapped structure, create our own */
1996 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
1998 res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1999 err = GetLastError();
2000 if (!res)
2002 if (err == ERROR_IO_PENDING)
2006 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
2007 } while (res != WAIT_OBJECT_0);
2008 TRACE("Event met\n:");
2009 ret = TRUE;
2011 else
2013 FIXME("Unknown error 0x%08lx\n", err);
2014 ret = FALSE;
2017 else
2018 ret = TRUE;
2019 CloseHandle(ov.hEvent);
2021 return ret;
2024 /***********************************************************************
2025 * GetCommProperties (KERNEL32.@)
2027 * This function fills in a structure with the capabilities of the
2028 * communications port driver.
2030 * RETURNS
2032 * TRUE on success, FALSE on failure
2033 * If successful, the lpCommProp structure be filled in with
2034 * properties of the comm port.
2036 BOOL WINAPI GetCommProperties(
2037 HANDLE hFile, /* [in] handle of the comm port */
2038 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2040 FIXME("(%p %p )\n",hFile,lpCommProp);
2041 if(!lpCommProp)
2042 return FALSE;
2045 * These values should be valid for LINUX's serial driver
2046 * FIXME: Perhaps they deserve an #ifdef LINUX
2048 memset(lpCommProp,0,sizeof(COMMPROP));
2049 lpCommProp->wPacketLength = 1;
2050 lpCommProp->wPacketVersion = 1;
2051 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2052 lpCommProp->dwReserved1 = 0;
2053 lpCommProp->dwMaxTxQueue = 4096;
2054 lpCommProp->dwMaxRxQueue = 4096;
2055 lpCommProp->dwMaxBaud = BAUD_115200;
2056 lpCommProp->dwProvSubType = PST_RS232;
2057 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2058 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2059 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2060 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2061 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2062 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2063 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2064 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2065 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2066 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2067 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2069 return TRUE;
2072 /***********************************************************************
2073 * FIXME:
2074 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2075 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2076 * This is dependent on the type of COMM port, but since it is doubtful
2077 * anybody will get around to implementing support for fancy serial
2078 * ports in WINE, this is hardcoded for the time being. The name of
2079 * this DLL should be stored in and read from the system registry in
2080 * the hive HKEY_LOCAL_MACHINE, key
2081 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2082 * where ???? is the port number... that is determined by PNP
2083 * The DLL should be loaded when the COMM port is opened, and closed
2084 * when the COMM port is closed. - MJM 20 June 2000
2085 ***********************************************************************/
2086 static const WCHAR lpszSerialUI[] = {
2087 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2090 /***********************************************************************
2091 * CommConfigDialogA (KERNEL32.@)
2093 * Raises a dialog that allows the user to configure a comm port.
2094 * Fills the COMMCONFIG struct with information specified by the user.
2095 * This function should call a similar routine in the COMM driver...
2097 * RETURNS
2099 * TRUE on success, FALSE on failure
2100 * If successful, the lpCommConfig structure will contain a new
2101 * configuration for the comm port, as specified by the user.
2103 * BUGS
2104 * The library with the CommConfigDialog code is never unloaded.
2105 * Perhaps this should be done when the comm port is closed?
2107 BOOL WINAPI CommConfigDialogA(
2108 LPCSTR lpszDevice, /* [in] name of communications device */
2109 HWND hWnd, /* [in] parent window for the dialog */
2110 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2112 FARPROC lpfnCommDialog;
2113 HMODULE hConfigModule;
2114 BOOL r = FALSE;
2116 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2118 hConfigModule = LoadLibraryW(lpszSerialUI);
2119 if(!hConfigModule)
2120 return FALSE;
2122 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2124 if(lpfnCommDialog)
2125 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2127 FreeLibrary(hConfigModule);
2129 return r;
2132 /***********************************************************************
2133 * CommConfigDialogW (KERNEL32.@)
2135 * See CommConfigDialogA.
2137 BOOL WINAPI CommConfigDialogW(
2138 LPCWSTR lpszDevice, /* [in] name of communications device */
2139 HWND hWnd, /* [in] parent window for the dialog */
2140 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2142 FARPROC lpfnCommDialog;
2143 HMODULE hConfigModule;
2144 BOOL r = FALSE;
2146 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2148 hConfigModule = LoadLibraryW(lpszSerialUI);
2149 if(!hConfigModule)
2150 return FALSE;
2152 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2154 if(lpfnCommDialog)
2155 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2157 FreeLibrary(hConfigModule);
2159 return r;
2162 /***********************************************************************
2163 * GetCommConfig (KERNEL32.@)
2165 * Fill in the COMMCONFIG structure for the comm port hFile
2167 * RETURNS
2169 * TRUE on success, FALSE on failure
2170 * If successful, lpCommConfig contains the comm port configuration.
2172 * BUGS
2175 BOOL WINAPI GetCommConfig(
2176 HANDLE hFile, /* [in] The communications device. */
2177 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2178 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2179 afterwards the number of bytes copied to the buffer or
2180 the needed size of the buffer. */
2182 BOOL r;
2184 TRACE("(%p %p)\n",hFile,lpCommConfig);
2186 if(lpCommConfig == NULL)
2187 return FALSE;
2188 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2189 *lpdwSize = sizeof(COMMCONFIG);
2190 if(r)
2191 return FALSE;
2193 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2194 lpCommConfig->wVersion = 1;
2195 lpCommConfig->wReserved = 0;
2196 r = GetCommState(hFile,&lpCommConfig->dcb);
2197 lpCommConfig->dwProviderSubType = PST_RS232;
2198 lpCommConfig->dwProviderOffset = 0;
2199 lpCommConfig->dwProviderSize = 0;
2201 return r;
2204 /***********************************************************************
2205 * SetCommConfig (KERNEL32.@)
2207 * Sets the configuration of the communications device.
2209 * RETURNS
2211 * True on success, false if the handle was bad is not a communications device.
2213 BOOL WINAPI SetCommConfig(
2214 HANDLE hFile, /* [in] The communications device. */
2215 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2216 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2218 TRACE("(%p %p)\n",hFile,lpCommConfig);
2219 return SetCommState(hFile,&lpCommConfig->dcb);
2222 /***********************************************************************
2223 * SetDefaultCommConfigA (KERNEL32.@)
2225 * Initializes the default configuration for the specified communication
2226 * device. (ascii)
2228 * RETURNS
2230 * True if the device was found and the defaults set, false otherwise
2232 BOOL WINAPI SetDefaultCommConfigW(
2233 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2234 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2235 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2237 FARPROC lpfnSetDefaultCommConfig;
2238 HMODULE hConfigModule;
2239 BOOL r = FALSE;
2241 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2243 hConfigModule = LoadLibraryW(lpszSerialUI);
2244 if(!hConfigModule)
2245 return r;
2247 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2248 if (lpfnSetDefaultCommConfig)
2249 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2251 FreeLibrary(hConfigModule);
2253 return r;
2257 /***********************************************************************
2258 * SetDefaultCommConfigW (KERNEL32.@)
2260 * Initializes the default configuration for the specified
2261 * communication device. (unicode)
2263 * RETURNS
2266 BOOL WINAPI SetDefaultCommConfigA(
2267 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2268 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2269 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2271 BOOL r;
2272 LPWSTR lpDeviceW = NULL;
2273 DWORD len;
2275 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2277 if (lpszDevice)
2279 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2280 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2281 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2283 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2284 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2285 return r;
2289 /***********************************************************************
2290 * GetDefaultCommConfigW (KERNEL32.@)
2292 * Acquires the default configuration of the specified communication device. (unicode)
2294 * RETURNS
2296 * True on successful reading of the default configuration,
2297 * if the device is not found or the buffer is too small.
2299 BOOL WINAPI GetDefaultCommConfigW(
2300 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2301 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2302 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2303 afterwards the number of bytes copied to the buffer or
2304 the needed size of the buffer. */
2306 LPDCB lpdcb = &(lpCC->dcb);
2307 WCHAR temp[40];
2308 static const WCHAR comW[] = {'C','O','M',0};
2309 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2311 if (strncmpiW(lpszName,comW,3)) {
2312 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2313 return FALSE;
2316 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2317 if (*lpdwSize < sizeof(COMMCONFIG)) {
2318 *lpdwSize = sizeof(COMMCONFIG);
2319 return FALSE;
2322 *lpdwSize = sizeof(COMMCONFIG);
2324 lpCC->dwSize = sizeof(COMMCONFIG);
2325 lpCC->wVersion = 1;
2326 lpCC->dwProviderSubType = PST_RS232;
2327 lpCC->dwProviderOffset = 0L;
2328 lpCC->dwProviderSize = 0L;
2330 sprintfW( temp, formatW, lpszName[3]);
2331 FIXME("setting %s as default\n", debugstr_w(temp));
2333 return BuildCommDCBW( temp, lpdcb);
2336 /**************************************************************************
2337 * GetDefaultCommConfigA (KERNEL32.@)
2339 * Acquires the default configuration of the specified communication device. (ascii)
2341 * RETURNS
2343 * True on successful reading of the default configuration,
2344 * if the device is not found or the buffer is too small.
2346 BOOL WINAPI GetDefaultCommConfigA(
2347 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2348 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2349 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2350 afterwards the number of bytes copied to the buffer or
2351 the needed size of the buffer. */
2353 BOOL ret = FALSE;
2354 UNICODE_STRING lpszNameW;
2356 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2357 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2358 else lpszNameW.Buffer = NULL;
2360 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2362 RtlFreeUnicodeString(&lpszNameW);
2363 return ret;