Tolerate ioctl failure in GetCommState() in order to be capable to use
[wine/multimedia.git] / dlls / kernel / comm.c
blob2f75e2fb9b7ed0b59f9d8650ca037dbc78c12a12
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 "ntstatus.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winerror.h"
66 #include "wine/server.h"
67 #include "wine/unicode.h"
69 #include "wine/debug.h"
71 #ifdef HAVE_LINUX_SERIAL_H
72 #include <linux/serial.h>
73 #endif
75 WINE_DEFAULT_DEBUG_CHANNEL(comm);
77 /* retrieve the Unix handle corresponding to a comm handle */
78 static int get_comm_fd( HANDLE handle, DWORD access )
80 int fd, ret;
82 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
83 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
84 return fd;
87 /* release the Unix handle returned by get_comm_fd */
88 static inline void release_comm_fd( HANDLE handle, int fd )
90 wine_server_release_fd( handle, fd );
93 /* serial_irq_info
94 * local structure holding the irq values we need for WaitCommEvent()
96 * Stripped down from struct serial_icounter_struct, which may not be available on some systems
97 * As the modem line interrupts (cts, dsr, rng, dcd) only get updated with TIOCMIWAIT active,
98 * no need to carry them in the internal structure
101 typedef struct serial_irq_info
103 int rx , tx, frame, overrun, parity, brk, buf_overrun;
104 }serial_irq_info;
106 /***********************************************************************
107 * Data needed by the thread polling for the changing CommEvent
109 typedef struct async_commio
111 HANDLE handle;
112 char* buffer;
113 HANDLE hEvent;
114 DWORD evtmask;
115 DWORD mstat;
116 serial_irq_info irq_info;
117 } async_commio;
119 /***********************************************************************/
121 #if !defined(TIOCINQ) && defined(FIONREAD)
122 #define TIOCINQ FIONREAD
123 #endif
125 /***********************************************************************
126 * Get extended interrupt count info, needed for WaitCommEvent
128 static int COMM_GetEInfo(int fd, serial_irq_info *irq_info)
130 #ifdef TIOCGICOUNT
131 struct serial_icounter_struct einfo;
132 if (!ioctl(fd,TIOCGICOUNT, &einfo))
134 irq_info->rx = einfo.rx;
135 irq_info->tx = einfo.tx;
136 irq_info->frame = einfo.frame;
137 irq_info->overrun = einfo.overrun;
138 irq_info->parity = einfo.parity;
139 irq_info->brk = einfo.brk;
140 irq_info->buf_overrun = einfo.buf_overrun;
141 return 0;
143 #endif
144 memset(irq_info,0, sizeof(serial_irq_info));
145 return -1;
148 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
150 #ifdef TIOCMGET
151 unsigned int mstat, okay;
152 okay = ioctl(fd, TIOCMGET, &mstat);
153 if (okay) return okay;
154 if (andy) mstat &= andy;
155 mstat |= orrie;
156 return ioctl(fd, TIOCMSET, &mstat);
157 #else
158 return 0;
159 #endif
162 /***********************************************************************
163 * COMM_Parse* (Internal)
165 * The following COMM_Parse* functions are used by the BuildCommDCB
166 * functions to help parse the various parts of the device control string.
168 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
170 static const WCHAR comW[] = {'C','O','M',0};
172 /* The device control string may optionally start with "COMx" followed
173 by an optional ':' and spaces. */
174 if(!strncmpiW(ptr, comW, 3))
176 ptr += 3;
178 /* Allow any com port above 0 as Win 9x does (NT only allows
179 values for com ports which are actually present) */
180 if(*ptr < '1' || *ptr > '9')
181 return NULL;
183 /* Advance pointer past port number */
184 while(*ptr >= '0' && *ptr <= '9') ptr++;
186 /* The com port number must be followed by a ':' or ' ' */
187 if(*ptr != ':' && *ptr != ' ')
188 return NULL;
190 /* Advance pointer to beginning of next parameter */
191 while(*ptr == ' ') ptr++;
192 if(*ptr == ':')
194 ptr++;
195 while(*ptr == ' ') ptr++;
198 /* The device control string must not start with a space. */
199 else if(*ptr == ' ')
200 return NULL;
202 return ptr;
205 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
207 if(*ptr < '0' || *ptr > '9') return NULL;
208 *lpnumber = strtoulW(ptr, NULL, 10);
209 while(*ptr >= '0' && *ptr <= '9') ptr++;
210 return ptr;
213 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
215 /* Contrary to what you might expect, Windows only sets the Parity
216 member of DCB and not fParity even when parity is specified in the
217 device control string */
219 switch(toupperW(*ptr++))
221 case 'E':
222 *lpparity = EVENPARITY;
223 break;
224 case 'M':
225 *lpparity = MARKPARITY;
226 break;
227 case 'N':
228 *lpparity = NOPARITY;
229 break;
230 case 'O':
231 *lpparity = ODDPARITY;
232 break;
233 case 'S':
234 *lpparity = SPACEPARITY;
235 break;
236 default:
237 return NULL;
240 return ptr;
243 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
245 DWORD temp;
247 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
248 return NULL;
250 if(temp >= 5 && temp <= 8)
252 *lpbytesize = temp;
253 return ptr;
255 else
256 return NULL;
259 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
261 DWORD temp;
262 static const WCHAR stopbits15W[] = {'1','.','5',0};
264 if(!strncmpW(stopbits15W, ptr, 3))
266 ptr += 3;
267 *lpstopbits = ONE5STOPBITS;
269 else
271 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
272 return NULL;
274 if(temp == 1)
275 *lpstopbits = ONESTOPBIT;
276 else if(temp == 2)
277 *lpstopbits = TWOSTOPBITS;
278 else
279 return NULL;
282 return ptr;
285 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
287 static const WCHAR onW[] = {'o','n',0};
288 static const WCHAR offW[] = {'o','f','f',0};
290 if(!strncmpiW(onW, ptr, 2))
292 ptr += 2;
293 *lponoff = 1;
295 else if(!strncmpiW(offW, ptr, 3))
297 ptr += 3;
298 *lponoff = 0;
300 else
301 return NULL;
303 return ptr;
306 /***********************************************************************
307 * COMM_BuildOldCommDCB (Internal)
309 * Build a DCB using the old style settings string eg: "96,n,8,1"
311 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
313 WCHAR last = 0;
315 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
316 return FALSE;
318 switch(lpdcb->BaudRate)
320 case 11:
321 case 30:
322 case 60:
323 lpdcb->BaudRate *= 10;
324 break;
325 case 12:
326 case 24:
327 case 48:
328 case 96:
329 lpdcb->BaudRate *= 100;
330 break;
331 case 19:
332 lpdcb->BaudRate = 19200;
333 break;
336 while(*device == ' ') device++;
337 if(*device++ != ',') return FALSE;
338 while(*device == ' ') device++;
340 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
341 return FALSE;
343 while(*device == ' ') device++;
344 if(*device++ != ',') return FALSE;
345 while(*device == ' ') device++;
347 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
348 return FALSE;
350 while(*device == ' ') device++;
351 if(*device++ != ',') return FALSE;
352 while(*device == ' ') device++;
354 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
355 return FALSE;
357 /* The last parameter for flow control is optional. */
358 while(*device == ' ') device++;
359 if(*device == ',')
361 device++;
362 while(*device == ' ') device++;
363 if(*device) last = toupperW(*device++);
364 while(*device == ' ') device++;
367 /* Win NT sets the flow control members based on (or lack of) the last
368 parameter. Win 9x does not set these members. */
369 switch(last)
371 case 0:
372 lpdcb->fInX = FALSE;
373 lpdcb->fOutX = FALSE;
374 lpdcb->fOutxCtsFlow = FALSE;
375 lpdcb->fOutxDsrFlow = FALSE;
376 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
377 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
378 break;
379 case 'X':
380 lpdcb->fInX = TRUE;
381 lpdcb->fOutX = TRUE;
382 lpdcb->fOutxCtsFlow = FALSE;
383 lpdcb->fOutxDsrFlow = FALSE;
384 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
385 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
386 break;
387 case 'P':
388 lpdcb->fInX = FALSE;
389 lpdcb->fOutX = FALSE;
390 lpdcb->fOutxCtsFlow = TRUE;
391 lpdcb->fOutxDsrFlow = TRUE;
392 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
393 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
394 break;
395 default:
396 return FALSE;
399 /* This should be the end of the string. */
400 if(*device) return FALSE;
402 return TRUE;
405 /***********************************************************************
406 * COMM_BuildNewCommDCB (Internal)
408 * Build a DCB using the new style settings string.
409 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
411 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
413 DWORD temp;
414 BOOL baud = FALSE, stop = FALSE;
415 static const WCHAR baudW[] = {'b','a','u','d','=',0};
416 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
417 static const WCHAR dataW[] = {'d','a','t','a','=',0};
418 static const WCHAR stopW[] = {'s','t','o','p','=',0};
419 static const WCHAR toW[] = {'t','o','=',0};
420 static const WCHAR xonW[] = {'x','o','n','=',0};
421 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
422 static const WCHAR octsW[] = {'o','c','t','s','=',0};
423 static const WCHAR dtrW[] = {'d','t','r','=',0};
424 static const WCHAR rtsW[] = {'r','t','s','=',0};
425 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
427 while(*device)
429 while(*device == ' ') device++;
431 if(!strncmpiW(baudW, device, 5))
433 baud = TRUE;
435 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
436 return FALSE;
438 else if(!strncmpiW(parityW, device, 7))
440 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
441 return FALSE;
443 else if(!strncmpiW(dataW, device, 5))
445 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
446 return FALSE;
448 else if(!strncmpiW(stopW, device, 5))
450 stop = TRUE;
452 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
453 return FALSE;
455 else if(!strncmpiW(toW, device, 3))
457 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
458 return FALSE;
460 lptimeouts->ReadIntervalTimeout = 0;
461 lptimeouts->ReadTotalTimeoutMultiplier = 0;
462 lptimeouts->ReadTotalTimeoutConstant = 0;
463 lptimeouts->WriteTotalTimeoutMultiplier = 0;
464 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
466 else if(!strncmpiW(xonW, device, 4))
468 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
469 return FALSE;
471 lpdcb->fOutX = temp;
472 lpdcb->fInX = temp;
474 else if(!strncmpiW(odsrW, device, 5))
476 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
477 return FALSE;
479 lpdcb->fOutxDsrFlow = temp;
481 else if(!strncmpiW(octsW, device, 5))
483 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
484 return FALSE;
486 lpdcb->fOutxCtsFlow = temp;
488 else if(!strncmpiW(dtrW, device, 4))
490 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
491 return FALSE;
493 lpdcb->fDtrControl = temp;
495 else if(!strncmpiW(rtsW, device, 4))
497 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
498 return FALSE;
500 lpdcb->fRtsControl = temp;
502 else if(!strncmpiW(idsrW, device, 5))
504 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
505 return FALSE;
507 /* Win NT sets the fDsrSensitivity member based on the
508 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
509 lpdcb->fDsrSensitivity = temp;
511 else
512 return FALSE;
514 /* After the above parsing, the next character (if not the end of
515 the string) should be a space */
516 if(*device && *device != ' ')
517 return FALSE;
520 /* If stop bits were not specified, a default is always supplied. */
521 if(!stop)
523 if(baud && lpdcb->BaudRate == 110)
524 lpdcb->StopBits = TWOSTOPBITS;
525 else
526 lpdcb->StopBits = ONESTOPBIT;
529 return TRUE;
532 /**************************************************************************
533 * BuildCommDCBA (KERNEL32.@)
535 * Updates a device control block data structure with values from an
536 * ascii device control string. The device control string has two forms
537 * normal and extended, it must be exclusively in one or the other form.
539 * RETURNS
541 * True on success, false on a malformed control string.
543 BOOL WINAPI BuildCommDCBA(
544 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
545 LPDCB lpdcb) /* [out] The device control block to be updated. */
547 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
550 /**************************************************************************
551 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
553 * Updates a device control block data structure with values from an
554 * ascii device control string. Taking timeout values from a timeouts
555 * struct if desired by the control string.
557 * RETURNS
559 * True on success, false bad handles etc.
561 BOOL WINAPI BuildCommDCBAndTimeoutsA(
562 LPCSTR device, /* [in] The ascii device control string. */
563 LPDCB lpdcb, /* [out] The device control block to be updated. */
564 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
566 BOOL ret = FALSE;
567 UNICODE_STRING deviceW;
569 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
570 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
571 else deviceW.Buffer = NULL;
573 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
575 RtlFreeUnicodeString(&deviceW);
576 return ret;
579 /**************************************************************************
580 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
582 * Updates a device control block data structure with values from a
583 * unicode device control string. Taking timeout values from a timeouts
584 * struct if desired by the control string.
586 * RETURNS
588 * True on success, false bad handles etc
590 BOOL WINAPI BuildCommDCBAndTimeoutsW(
591 LPCWSTR devid, /* [in] The unicode device control string. */
592 LPDCB lpdcb, /* [out] The device control block to be updated. */
593 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
595 DCB dcb;
596 COMMTIMEOUTS timeouts;
597 BOOL result;
598 LPCWSTR ptr = devid;
600 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
602 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
603 lpdcb->DCBlength = sizeof(DCB);
605 /* Make a copy of the original data structures to work with since if
606 if there is an error in the device control string the originals
607 should not be modified (except possibly DCBlength) */
608 memcpy(&dcb, lpdcb, sizeof(DCB));
609 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
611 ptr = COMM_ParseStart(ptr);
613 if(ptr == NULL)
614 result = FALSE;
615 else if(strchrW(ptr, ','))
616 result = COMM_BuildOldCommDCB(ptr, &dcb);
617 else
618 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
620 if(result)
622 memcpy(lpdcb, &dcb, sizeof(DCB));
623 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
624 return TRUE;
626 else
628 WARN("Invalid device control string: %s\n", debugstr_w(devid));
629 SetLastError(ERROR_INVALID_PARAMETER);
630 return FALSE;
634 /**************************************************************************
635 * BuildCommDCBW (KERNEL32.@)
637 * Updates a device control block structure with values from an
638 * unicode device control string. The device control string has two forms
639 * normal and extended, it must be exclusively in one or the other form.
641 * RETURNS
643 * True on success, false on a malformed control string.
645 BOOL WINAPI BuildCommDCBW(
646 LPCWSTR devid, /* [in] The unicode device control string. */
647 LPDCB lpdcb) /* [out] The device control block to be updated. */
649 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
652 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
654 DWORD ret;
656 SERVER_START_REQ( set_serial_info )
658 req->handle = handle;
659 req->flags = SERIALINFO_SET_ERROR;
660 req->commerror = error;
661 ret = !wine_server_call_err( req );
663 SERVER_END_REQ;
664 return ret;
667 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
669 DWORD ret;
671 if(!lperror)
672 return FALSE;
674 SERVER_START_REQ( get_serial_info )
676 req->handle = handle;
677 ret = !wine_server_call_err( req );
678 *lperror = reply->commerror;
680 SERVER_END_REQ;
682 return ret;
685 /*****************************************************************************
686 * SetCommBreak (KERNEL32.@)
688 * Halts the transmission of characters to a communications device.
690 * RETURNS
692 * True on success, and false if the communications device could not be found,
693 * the control is not supported.
695 * BUGS
697 * Only TIOCSBRK and TIOCCBRK are supported.
699 BOOL WINAPI SetCommBreak(
700 HANDLE handle) /* [in] The communications device to suspend. */
702 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
703 int fd,result;
705 fd = get_comm_fd( handle, GENERIC_READ );
706 if(fd<0) return FALSE;
707 result = ioctl(fd,TIOCSBRK,0);
708 release_comm_fd( handle, fd );
709 if (result ==-1)
711 TRACE("ioctl failed\n");
712 SetLastError(ERROR_NOT_SUPPORTED);
713 return FALSE;
715 return TRUE;
716 #else
717 FIXME("ioctl not available\n");
718 SetLastError(ERROR_NOT_SUPPORTED);
719 return FALSE;
720 #endif
723 /*****************************************************************************
724 * ClearCommBreak (KERNEL32.@)
726 * Resumes character transmission from a communication device.
728 * RETURNS
730 * True on success and false if the communications device could not be found.
732 * BUGS
734 * Only TIOCSBRK and TIOCCBRK are supported.
736 BOOL WINAPI ClearCommBreak(
737 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
739 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
740 int fd,result;
742 fd = get_comm_fd( handle, GENERIC_READ );
743 if(fd<0) return FALSE;
744 result = ioctl(fd,TIOCCBRK,0);
745 release_comm_fd( handle, fd );
746 if (result ==-1)
748 TRACE("ioctl failed\n");
749 SetLastError(ERROR_NOT_SUPPORTED);
750 return FALSE;
752 return TRUE;
753 #else
754 FIXME("ioctl not available\n");
755 SetLastError(ERROR_NOT_SUPPORTED);
756 return FALSE;
757 #endif
760 /*****************************************************************************
761 * EscapeCommFunction (KERNEL32.@)
763 * Directs a communication device to perform an extended function.
765 * RETURNS
767 * True or requested data on successful completion of the command,
768 * false if the device is not present cannot execute the command
769 * or the command failed.
771 BOOL WINAPI EscapeCommFunction(
772 HANDLE handle, /* [in] The communication device to perform the extended function. */
773 UINT nFunction) /* [in] The extended function to be performed. */
775 int fd,direct=FALSE,result=FALSE;
776 struct termios port;
778 TRACE("handle %p, function=%d\n", handle, nFunction);
779 fd = get_comm_fd( handle, GENERIC_READ );
780 if(fd<0) return FALSE;
782 if (tcgetattr(fd,&port) == -1) {
783 COMM_SetCommError(handle,CE_IOE);
784 release_comm_fd( handle, fd );
785 return FALSE;
788 switch (nFunction) {
789 case RESETDEV:
790 TRACE("\n");
791 break;
793 case CLRDTR:
794 TRACE("CLRDTR\n");
795 #ifdef TIOCM_DTR
796 direct=TRUE;
797 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
798 break;
799 #endif
801 case CLRRTS:
802 TRACE("CLRRTS\n");
803 #ifdef TIOCM_RTS
804 direct=TRUE;
805 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
806 break;
807 #endif
809 case SETDTR:
810 TRACE("SETDTR\n");
811 #ifdef TIOCM_DTR
812 direct=TRUE;
813 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
814 break;
815 #endif
817 case SETRTS:
818 TRACE("SETRTS\n");
819 #ifdef TIOCM_RTS
820 direct=TRUE;
821 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
822 break;
823 #endif
825 case SETXOFF:
826 TRACE("SETXOFF\n");
827 port.c_iflag |= IXOFF;
828 break;
830 case SETXON:
831 TRACE("SETXON\n");
832 port.c_iflag |= IXON;
833 break;
834 case SETBREAK:
835 TRACE("setbreak\n");
836 #ifdef TIOCSBRK
837 direct=TRUE;
838 result = ioctl(fd,TIOCSBRK,0);
839 break;
840 #endif
841 case CLRBREAK:
842 TRACE("clrbreak\n");
843 #ifdef TIOCSBRK
844 direct=TRUE;
845 result = ioctl(fd,TIOCCBRK,0);
846 break;
847 #endif
848 default:
849 WARN("(handle=%p,nFunction=%d): Unknown function\n",
850 handle, nFunction);
851 break;
854 if (!direct)
855 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
856 release_comm_fd( handle, fd );
857 COMM_SetCommError(handle,CE_IOE);
858 return FALSE;
859 } else
860 result= TRUE;
861 else
863 if (result == -1)
865 result= FALSE;
866 COMM_SetCommError(handle,CE_IOE);
868 else
869 result = TRUE;
871 release_comm_fd( handle, fd );
872 return result;
875 /********************************************************************
876 * PurgeComm (KERNEL32.@)
878 * Terminates pending operations and/or discards buffers on a
879 * communication resource.
881 * RETURNS
883 * True on success and false if the communications handle is bad.
885 BOOL WINAPI PurgeComm(
886 HANDLE handle, /* [in] The communication resource to be purged. */
887 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
889 int fd;
891 TRACE("handle %p, flags %lx\n", handle, flags);
893 fd = get_comm_fd( handle, GENERIC_READ );
894 if(fd<0) return FALSE;
897 ** not exactly sure how these are different
898 ** Perhaps if we had our own internal queues, one flushes them
899 ** and the other flushes the kernel's buffers.
901 if(flags&PURGE_TXABORT)
902 tcflush(fd,TCOFLUSH);
903 if(flags&PURGE_RXABORT)
904 tcflush(fd,TCIFLUSH);
905 if(flags&PURGE_TXCLEAR)
906 tcflush(fd,TCOFLUSH);
907 if(flags&PURGE_RXCLEAR)
908 tcflush(fd,TCIFLUSH);
909 release_comm_fd( handle, fd );
911 return 1;
914 /*****************************************************************************
915 * ClearCommError (KERNEL32.@)
917 * Enables further I/O operations on a communications resource after
918 * supplying error and current status information.
920 * RETURNS
922 * True on success, false if the communication resource handle is bad.
924 BOOL WINAPI ClearCommError(
925 HANDLE handle, /* [in] The communication resource with the error. */
926 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
927 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
929 int fd;
931 fd=get_comm_fd( handle, GENERIC_READ );
932 if(0>fd) return FALSE;
934 if (lpStat)
936 lpStat->fCtsHold = 0;
937 lpStat->fDsrHold = 0;
938 lpStat->fRlsdHold = 0;
939 lpStat->fXoffHold = 0;
940 lpStat->fXoffSent = 0;
941 lpStat->fEof = 0;
942 lpStat->fTxim = 0;
943 lpStat->fReserved = 0;
945 #ifdef TIOCOUTQ
946 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
947 WARN("ioctl returned error\n");
948 #else
949 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
950 #endif
952 #ifdef TIOCINQ
953 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
954 WARN("ioctl returned error\n");
955 #endif
957 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
958 handle, lpStat->cbInQue, lpStat->cbOutQue);
961 release_comm_fd( handle, fd );
963 COMM_GetCommError(handle, errors);
964 COMM_SetCommError(handle, 0);
966 return TRUE;
969 /*****************************************************************************
970 * SetupComm (KERNEL32.@)
972 * Called after CreateFile to hint to the communication resource to use
973 * specified sizes for input and output buffers rather than the default values.
975 * RETURNS
977 * True if successful, false if the communications resource handle is bad.
979 * BUGS
981 * Stub.
983 BOOL WINAPI SetupComm(
984 HANDLE handle, /* [in] The just created communication resource handle. */
985 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
986 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
988 int fd;
990 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
991 fd=get_comm_fd( handle, GENERIC_READ );
992 if(0>fd) return FALSE;
993 release_comm_fd( handle, fd );
994 return TRUE;
997 /*****************************************************************************
998 * GetCommMask (KERNEL32.@)
1000 * Obtain the events associated with a communication device that will cause
1001 * a call WaitCommEvent to return.
1003 * RETURNS
1005 * True on success, fail on bad device handle etc.
1007 BOOL WINAPI GetCommMask(
1008 HANDLE handle, /* [in] The communications device. */
1009 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1011 BOOL ret;
1013 TRACE("handle %p, mask %p\n", handle, evtmask);
1015 SERVER_START_REQ( get_serial_info )
1017 req->handle = handle;
1018 if ((ret = !wine_server_call_err( req )))
1020 if (evtmask) *evtmask = reply->eventmask;
1023 SERVER_END_REQ;
1024 return ret;
1027 /*****************************************************************************
1028 * SetCommMask (KERNEL32.@)
1030 * There be some things we need to hear about yon there communications device.
1031 * (Set which events associated with a communication device should cause
1032 * a call WaitCommEvent to return.)
1034 * RETURNS
1036 * True on success, false on bad handle etc.
1038 BOOL WINAPI SetCommMask(
1039 HANDLE handle, /* [in] The communications device. */
1040 DWORD evtmask) /* [in] The events that are to be monitored. */
1042 BOOL ret;
1044 TRACE("handle %p, mask %lx\n", handle, evtmask);
1046 SERVER_START_REQ( set_serial_info )
1048 req->handle = handle;
1049 req->flags = SERIALINFO_SET_MASK;
1050 req->eventmask = evtmask;
1051 ret = !wine_server_call_err( req );
1053 SERVER_END_REQ;
1054 return ret;
1057 /*****************************************************************************
1058 * SetCommState (KERNEL32.@)
1060 * Re-initializes all hardware and control settings of a communications device,
1061 * with values from a device control block without effecting the input and output
1062 * queues.
1064 * RETURNS
1066 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1068 BOOL WINAPI SetCommState(
1069 HANDLE handle, /* [in] The communications device. */
1070 LPDCB lpdcb) /* [out] The device control block. */
1072 struct termios port;
1073 int fd, bytesize, stopbits;
1074 BOOL ret;
1076 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1077 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1078 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1079 (lpdcb->StopBits == ONESTOPBIT)?1:
1080 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1081 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1082 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1083 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1084 lpdcb->fRtsControl);
1085 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1086 lpdcb->fDtrControl);
1089 fd = get_comm_fd( handle, GENERIC_READ );
1090 if (fd < 0) return FALSE;
1092 if ((tcgetattr(fd,&port)) == -1) {
1093 int save_error = errno;
1094 COMM_SetCommError(handle,CE_IOE);
1095 release_comm_fd( handle, fd );
1096 ERR("tcgetattr error '%s'\n", strerror(save_error));
1097 return FALSE;
1100 port.c_cc[VMIN] = 0;
1101 port.c_cc[VTIME] = 1;
1103 #ifdef IMAXBEL
1104 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1105 #else
1106 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1107 #endif
1108 port.c_iflag |= (IGNBRK);
1110 port.c_oflag &= ~(OPOST);
1112 port.c_cflag &= ~(HUPCL);
1113 port.c_cflag |= CLOCAL | CREAD;
1115 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1116 port.c_lflag |= NOFLSH;
1118 #ifdef CBAUD
1119 port.c_cflag &= ~CBAUD;
1120 switch (lpdcb->BaudRate) {
1121 case 0:
1122 port.c_cflag |= B0;
1123 break;
1124 case 50:
1125 port.c_cflag |= B50;
1126 break;
1127 case 75:
1128 port.c_cflag |= B75;
1129 break;
1130 case 110:
1131 case CBR_110:
1132 port.c_cflag |= B110;
1133 break;
1134 case 134:
1135 port.c_cflag |= B134;
1136 break;
1137 case 150:
1138 port.c_cflag |= B150;
1139 break;
1140 case 200:
1141 port.c_cflag |= B200;
1142 break;
1143 case 300:
1144 case CBR_300:
1145 port.c_cflag |= B300;
1146 break;
1147 case 600:
1148 case CBR_600:
1149 port.c_cflag |= B600;
1150 break;
1151 case 1200:
1152 case CBR_1200:
1153 port.c_cflag |= B1200;
1154 break;
1155 case 1800:
1156 port.c_cflag |= B1800;
1157 break;
1158 case 2400:
1159 case CBR_2400:
1160 port.c_cflag |= B2400;
1161 break;
1162 case 4800:
1163 case CBR_4800:
1164 port.c_cflag |= B4800;
1165 break;
1166 case 9600:
1167 case CBR_9600:
1168 port.c_cflag |= B9600;
1169 break;
1170 case 19200:
1171 case CBR_19200:
1172 port.c_cflag |= B19200;
1173 break;
1174 case 38400:
1175 case CBR_38400:
1176 port.c_cflag |= B38400;
1177 break;
1178 #ifdef B57600
1179 case 57600:
1180 port.c_cflag |= B57600;
1181 break;
1182 #endif
1183 #ifdef B115200
1184 case 115200:
1185 port.c_cflag |= B115200;
1186 break;
1187 #endif
1188 #ifdef B230400
1189 case 230400:
1190 port.c_cflag |= B230400;
1191 break;
1192 #endif
1193 #ifdef B460800
1194 case 460800:
1195 port.c_cflag |= B460800;
1196 break;
1197 #endif
1198 default:
1199 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1200 { struct serial_struct nuts;
1201 int arby;
1202 ioctl(fd, TIOCGSERIAL, &nuts);
1203 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1204 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1205 arby = nuts.baud_base / nuts.custom_divisor;
1206 nuts.flags &= ~ASYNC_SPD_MASK;
1207 nuts.flags |= ASYNC_SPD_CUST;
1208 WARN("You (or a program acting at your behest) have specified\n"
1209 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1210 "which is as close as we can get by our present understanding of your\n"
1211 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1212 "has caused to your linux system can be undone with setserial \n"
1213 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1214 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1215 ioctl(fd, TIOCSSERIAL, &nuts);
1216 port.c_cflag |= B38400;
1218 break;
1219 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1222 COMM_SetCommError(handle,IE_BAUDRATE);
1223 release_comm_fd( handle, fd );
1224 ERR("baudrate %ld\n",lpdcb->BaudRate);
1225 return FALSE;
1227 #elif !defined(__EMX__)
1228 switch (lpdcb->BaudRate) {
1229 case 0:
1230 port.c_ospeed = B0;
1231 break;
1232 case 50:
1233 port.c_ospeed = B50;
1234 break;
1235 case 75:
1236 port.c_ospeed = B75;
1237 break;
1238 case 110:
1239 case CBR_110:
1240 port.c_ospeed = B110;
1241 break;
1242 case 134:
1243 port.c_ospeed = B134;
1244 break;
1245 case 150:
1246 port.c_ospeed = B150;
1247 break;
1248 case 200:
1249 port.c_ospeed = B200;
1250 break;
1251 case 300:
1252 case CBR_300:
1253 port.c_ospeed = B300;
1254 break;
1255 case 600:
1256 case CBR_600:
1257 port.c_ospeed = B600;
1258 break;
1259 case 1200:
1260 case CBR_1200:
1261 port.c_ospeed = B1200;
1262 break;
1263 case 1800:
1264 port.c_ospeed = B1800;
1265 break;
1266 case 2400:
1267 case CBR_2400:
1268 port.c_ospeed = B2400;
1269 break;
1270 case 4800:
1271 case CBR_4800:
1272 port.c_ospeed = B4800;
1273 break;
1274 case 9600:
1275 case CBR_9600:
1276 port.c_ospeed = B9600;
1277 break;
1278 case 19200:
1279 case CBR_19200:
1280 port.c_ospeed = B19200;
1281 break;
1282 case 38400:
1283 case CBR_38400:
1284 port.c_ospeed = B38400;
1285 break;
1286 #ifdef B57600
1287 case 57600:
1288 case CBR_57600:
1289 port.c_cflag |= B57600;
1290 break;
1291 #endif
1292 #ifdef B115200
1293 case 115200:
1294 case CBR_115200:
1295 port.c_cflag |= B115200;
1296 break;
1297 #endif
1298 #ifdef B230400
1299 case 230400:
1300 port.c_cflag |= B230400;
1301 break;
1302 #endif
1303 #ifdef B460800
1304 case 460800:
1305 port.c_cflag |= B460800;
1306 break;
1307 #endif
1308 default:
1309 COMM_SetCommError(handle,IE_BAUDRATE);
1310 release_comm_fd( handle, fd );
1311 ERR("baudrate %ld\n",lpdcb->BaudRate);
1312 return FALSE;
1314 port.c_ispeed = port.c_ospeed;
1315 #endif
1316 bytesize=lpdcb->ByteSize;
1317 stopbits=lpdcb->StopBits;
1319 #ifdef CMSPAR
1320 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1321 #else
1322 port.c_cflag &= ~(PARENB | PARODD);
1323 #endif
1324 if (lpdcb->fParity)
1325 port.c_iflag |= INPCK;
1326 else
1327 port.c_iflag &= ~INPCK;
1328 switch (lpdcb->Parity) {
1329 case NOPARITY:
1330 break;
1331 case ODDPARITY:
1332 port.c_cflag |= (PARENB | PARODD);
1333 break;
1334 case EVENPARITY:
1335 port.c_cflag |= PARENB;
1336 break;
1337 #ifdef CMSPAR
1338 /* Linux defines mark/space (stick) parity */
1339 case MARKPARITY:
1340 port.c_cflag |= (PARENB | CMSPAR);
1341 break;
1342 case SPACEPARITY:
1343 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1344 break;
1345 #else
1346 /* try the POSIX way */
1347 case MARKPARITY:
1348 if( stopbits == ONESTOPBIT) {
1349 stopbits = TWOSTOPBITS;
1350 port.c_iflag &= ~INPCK;
1351 } else {
1352 COMM_SetCommError(handle,IE_BYTESIZE);
1353 release_comm_fd( handle, fd );
1354 ERR("Cannot set MARK Parity\n");
1355 return FALSE;
1357 break;
1358 case SPACEPARITY:
1359 if( bytesize < 8) {
1360 bytesize +=1;
1361 port.c_iflag &= ~INPCK;
1362 } else {
1363 COMM_SetCommError(handle,IE_BYTESIZE);
1364 release_comm_fd( handle, fd );
1365 ERR("Cannot set SPACE Parity\n");
1366 return FALSE;
1368 break;
1369 #endif
1370 default:
1371 COMM_SetCommError(handle,IE_BYTESIZE);
1372 release_comm_fd( handle, fd );
1373 ERR("Parity\n");
1374 return FALSE;
1378 port.c_cflag &= ~CSIZE;
1379 switch (bytesize) {
1380 case 5:
1381 port.c_cflag |= CS5;
1382 break;
1383 case 6:
1384 port.c_cflag |= CS6;
1385 break;
1386 case 7:
1387 port.c_cflag |= CS7;
1388 break;
1389 case 8:
1390 port.c_cflag |= CS8;
1391 break;
1392 default:
1393 COMM_SetCommError(handle,IE_BYTESIZE);
1394 release_comm_fd( handle, fd );
1395 ERR("ByteSize\n");
1396 return FALSE;
1399 switch (stopbits) {
1400 case ONESTOPBIT:
1401 port.c_cflag &= ~CSTOPB;
1402 break;
1403 case ONE5STOPBITS: /* will be selected if bytesize is 5 */
1404 case TWOSTOPBITS:
1405 port.c_cflag |= CSTOPB;
1406 break;
1407 default:
1408 COMM_SetCommError(handle,IE_BYTESIZE);
1409 release_comm_fd( handle, fd );
1410 ERR("StopBits\n");
1411 return FALSE;
1413 #ifdef CRTSCTS
1414 if ( lpdcb->fOutxCtsFlow ||
1415 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1418 port.c_cflag |= CRTSCTS;
1419 TRACE("CRTSCTS\n");
1421 #endif
1423 if (lpdcb->fInX)
1424 port.c_iflag |= IXON;
1425 else
1426 port.c_iflag &= ~IXON;
1427 if (lpdcb->fOutX)
1428 port.c_iflag |= IXOFF;
1429 else
1430 port.c_iflag &= ~IXOFF;
1432 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1433 ERR("tcsetattr error '%s'\n", strerror(errno));
1434 COMM_SetCommError(handle,CE_IOE);
1435 ret = FALSE;
1436 } else {
1437 COMM_SetCommError(handle,0);
1438 ret = TRUE;
1441 /* note: change DTR/RTS lines after setting the comm attributes,
1442 * so flow control does not interfere. */
1443 #ifdef TIOCM_DTR
1444 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1446 WARN("DSR/DTR flow control not supported\n");
1447 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1448 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1449 else
1450 COMM_WhackModem(fd, 0, TIOCM_DTR);
1451 #endif
1452 #ifdef TIOCM_RTS
1453 if(!lpdcb->fOutxCtsFlow )
1455 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1456 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1457 else
1458 COMM_WhackModem(fd, 0, TIOCM_RTS);
1460 #endif
1461 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1462 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1463 release_comm_fd( handle, fd );
1464 return ret;
1469 /*****************************************************************************
1470 * GetCommState (KERNEL32.@)
1472 * Fills in a device control block with information from a communications device.
1474 * RETURNS
1476 * True on success, false if the communication device handle is bad etc
1478 * BUGS
1480 * XonChar and XoffChar are not set.
1482 BOOL WINAPI GetCommState(
1483 HANDLE handle, /* [in] The communications device. */
1484 LPDCB lpdcb) /* [out] The device control block. */
1486 struct termios port;
1487 int fd,speed;
1488 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1490 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1492 fd = get_comm_fd( handle, GENERIC_READ );
1493 if (fd < 0) return FALSE;
1494 if (tcgetattr(fd, &port) == -1) {
1495 int save_error=errno;
1496 ERR("tcgetattr error '%s'\n", strerror(save_error));
1497 COMM_SetCommError(handle,CE_IOE);
1498 release_comm_fd( handle, fd );
1499 return FALSE;
1502 #ifdef TIOCMGET
1503 if (ioctl(fd, TIOCMGET, &stat) == -1)
1505 int save_error=errno;
1506 WARN("ioctl error '%s'\n", strerror(save_error));
1507 stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1509 #endif
1510 release_comm_fd( handle, fd );
1511 #ifndef __EMX__
1512 #ifdef CBAUD
1513 speed= (port.c_cflag & CBAUD);
1514 #else
1515 speed= (cfgetospeed(&port));
1516 #endif
1517 switch (speed) {
1518 case B0:
1519 lpdcb->BaudRate = 0;
1520 break;
1521 case B50:
1522 lpdcb->BaudRate = 50;
1523 break;
1524 case B75:
1525 lpdcb->BaudRate = 75;
1526 break;
1527 case B110:
1528 lpdcb->BaudRate = 110;
1529 break;
1530 case B134:
1531 lpdcb->BaudRate = 134;
1532 break;
1533 case B150:
1534 lpdcb->BaudRate = 150;
1535 break;
1536 case B200:
1537 lpdcb->BaudRate = 200;
1538 break;
1539 case B300:
1540 lpdcb->BaudRate = 300;
1541 break;
1542 case B600:
1543 lpdcb->BaudRate = 600;
1544 break;
1545 case B1200:
1546 lpdcb->BaudRate = 1200;
1547 break;
1548 case B1800:
1549 lpdcb->BaudRate = 1800;
1550 break;
1551 case B2400:
1552 lpdcb->BaudRate = 2400;
1553 break;
1554 case B4800:
1555 lpdcb->BaudRate = 4800;
1556 break;
1557 case B9600:
1558 lpdcb->BaudRate = 9600;
1559 break;
1560 case B19200:
1561 lpdcb->BaudRate = 19200;
1562 break;
1563 case B38400:
1564 lpdcb->BaudRate = 38400;
1565 break;
1566 #ifdef B57600
1567 case B57600:
1568 lpdcb->BaudRate = 57600;
1569 break;
1570 #endif
1571 #ifdef B115200
1572 case B115200:
1573 lpdcb->BaudRate = 115200;
1574 break;
1575 #endif
1576 #ifdef B230400
1577 case B230400:
1578 lpdcb->BaudRate = 230400;
1579 break;
1580 #endif
1581 #ifdef B460800
1582 case B460800:
1583 lpdcb->BaudRate = 460800;
1584 break;
1585 #endif
1586 default:
1587 ERR("unknown speed %x \n",speed);
1589 #endif
1590 switch (port.c_cflag & CSIZE) {
1591 case CS5:
1592 lpdcb->ByteSize = 5;
1593 break;
1594 case CS6:
1595 lpdcb->ByteSize = 6;
1596 break;
1597 case CS7:
1598 lpdcb->ByteSize = 7;
1599 break;
1600 case CS8:
1601 lpdcb->ByteSize = 8;
1602 break;
1603 default:
1604 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1607 if(port.c_iflag & INPCK)
1608 lpdcb->fParity = TRUE;
1609 else
1610 lpdcb->fParity = FALSE;
1611 #ifdef CMSPAR
1612 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1613 #else
1614 switch (port.c_cflag & (PARENB | PARODD))
1615 #endif
1617 case 0:
1618 lpdcb->Parity = NOPARITY;
1619 break;
1620 case PARENB:
1621 lpdcb->Parity = EVENPARITY;
1622 break;
1623 case (PARENB | PARODD):
1624 lpdcb->Parity = ODDPARITY;
1625 break;
1626 #ifdef CMSPAR
1627 case (PARENB | CMSPAR):
1628 lpdcb->Parity = MARKPARITY;
1629 break;
1630 case (PARENB | PARODD | CMSPAR):
1631 lpdcb->Parity = SPACEPARITY;
1632 break;
1633 #endif
1636 if (port.c_cflag & CSTOPB)
1637 if(lpdcb->ByteSize == 5)
1638 lpdcb->StopBits = ONE5STOPBITS;
1639 else
1640 lpdcb->StopBits = TWOSTOPBITS;
1641 else
1642 lpdcb->StopBits = ONESTOPBIT;
1644 lpdcb->fNull = 0;
1645 lpdcb->fBinary = 1;
1647 /* termios does not support DTR/DSR flow control */
1648 lpdcb->fOutxDsrFlow = 0;
1649 lpdcb->fDtrControl =
1650 #ifdef TIOCM_DTR
1651 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1652 #endif
1653 DTR_CONTROL_ENABLE ;
1655 #ifdef CRTSCTS
1657 if (port.c_cflag & CRTSCTS) {
1658 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1659 lpdcb->fOutxCtsFlow = 1;
1660 } else
1661 #endif
1663 lpdcb->fRtsControl =
1664 #ifdef TIOCM_RTS
1665 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1666 #endif
1667 RTS_CONTROL_ENABLE ;
1668 lpdcb->fOutxCtsFlow = 0;
1670 if (port.c_iflag & IXON)
1671 lpdcb->fInX = 1;
1672 else
1673 lpdcb->fInX = 0;
1675 if (port.c_iflag & IXOFF)
1676 lpdcb->fOutX = 1;
1677 else
1678 lpdcb->fOutX = 0;
1680 lpdcb->XonChar =
1681 lpdcb->XoffChar =
1683 lpdcb->XonLim = 10;
1684 lpdcb->XoffLim = 10;
1686 COMM_SetCommError(handle,0);
1688 TRACE("OK\n");
1690 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1691 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1692 (lpdcb->StopBits == ONESTOPBIT)?1:
1693 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1694 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1695 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1696 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1697 lpdcb->fRtsControl);
1698 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1699 lpdcb->fDtrControl);
1700 #ifdef CRTSCTS
1701 if ( lpdcb->fOutxCtsFlow ||
1702 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1704 TRACE("CRTSCTS\n");
1705 else
1707 TRACE("~CRTSCTS\n");
1708 #endif
1709 return TRUE;
1712 /*****************************************************************************
1713 * TransmitCommChar (KERNEL32.@)
1715 * Transmits a single character in front of any pending characters in the
1716 * output buffer. Usually used to send an interrupt character to a host.
1718 * RETURNS
1720 * True if the call succeeded, false if the previous command character to the
1721 * same device has not been sent yet the handle is bad etc.
1723 * BUGS
1725 * Stub.
1727 BOOL WINAPI TransmitCommChar(
1728 HANDLE hComm, /* [in] The communication device in need of a command character. */
1729 CHAR chTransmit) /* [in] The character to transmit. */
1731 DWORD w;
1732 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1734 return WriteFile( hComm, &chTransmit, 1, &w, NULL );
1738 /*****************************************************************************
1739 * GetCommTimeouts (KERNEL32.@)
1741 * Obtains the request timeout values for the communications device.
1743 * RETURNS
1745 * True on success, false if communications device handle is bad
1746 * or the target structure is null.
1748 BOOL WINAPI GetCommTimeouts(
1749 HANDLE hComm, /* [in] The communications device. */
1750 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1752 BOOL ret;
1754 TRACE("(%p,%p)\n",hComm,lptimeouts);
1756 if(!lptimeouts)
1758 SetLastError(ERROR_INVALID_PARAMETER);
1759 return FALSE;
1762 SERVER_START_REQ( get_serial_info )
1764 req->handle = hComm;
1765 if ((ret = !wine_server_call_err( req )))
1767 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1768 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1769 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1770 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1771 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1774 SERVER_END_REQ;
1775 return ret;
1778 /*****************************************************************************
1779 * SetCommTimeouts (KERNEL32.@)
1781 * Sets the timeouts used when reading and writing data to/from COMM ports.
1783 * ReadIntervalTimeout
1784 * - converted and passes to linux kernel as c_cc[VTIME]
1785 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1786 * - used in ReadFile to calculate GetOverlappedResult's timeout
1787 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1788 * - used in WriteFile to calculate GetOverlappedResult's timeout
1790 * RETURNS
1792 * True if the timeouts were set, false otherwise.
1794 BOOL WINAPI SetCommTimeouts(
1795 HANDLE hComm, /* [in] handle of COMM device */
1796 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1798 BOOL ret;
1799 int fd;
1800 struct termios tios;
1802 TRACE("(%p,%p)\n",hComm,lptimeouts);
1804 if(!lptimeouts)
1806 SetLastError(ERROR_INVALID_PARAMETER);
1807 return FALSE;
1810 SERVER_START_REQ( set_serial_info )
1812 req->handle = hComm;
1813 req->flags = SERIALINFO_SET_TIMEOUTS;
1814 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1815 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1816 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1817 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1818 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1819 ret = !wine_server_call_err( req );
1821 SERVER_END_REQ;
1822 if (!ret) return FALSE;
1824 /* FIXME: move this stuff to the server */
1825 fd = get_comm_fd( hComm, GENERIC_READ );
1826 if (fd < 0) return FALSE;
1828 if (-1==tcgetattr(fd,&tios)) {
1829 FIXME("tcgetattr on fd %d failed!\n",fd);
1830 release_comm_fd( hComm, fd );
1831 return FALSE;
1834 /* VTIME is in 1/10 seconds */
1836 unsigned int ux_timeout;
1838 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1840 ux_timeout = 0;
1842 else
1844 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1845 if(ux_timeout == 0)
1847 ux_timeout = 1; /* must be at least some timeout */
1850 tios.c_cc[VTIME] = ux_timeout;
1853 if (-1==tcsetattr(fd,0,&tios)) {
1854 FIXME("tcsetattr on fd %d failed!\n",fd);
1855 release_comm_fd( hComm, fd );
1856 return FALSE;
1858 release_comm_fd( hComm, fd );
1859 return TRUE;
1862 /***********************************************************************
1863 * GetCommModemStatus (KERNEL32.@)
1865 * Obtains the four control register bits if supported by the hardware.
1867 * RETURNS
1869 * True if the communications handle was good and for hardware that
1870 * control register access, false otherwise.
1872 BOOL WINAPI GetCommModemStatus(
1873 HANDLE hFile, /* [in] The communications device. */
1874 LPDWORD lpModemStat) /* [out] The control register bits. */
1876 int fd,mstat, result=FALSE;
1878 *lpModemStat=0;
1879 #ifdef TIOCMGET
1880 fd = get_comm_fd( hFile, GENERIC_READ );
1881 if(fd<0)
1882 return FALSE;
1883 result = ioctl(fd, TIOCMGET, &mstat);
1884 release_comm_fd( hFile, fd );
1885 if (result == -1)
1887 WARN("ioctl failed\n");
1888 return FALSE;
1890 #ifdef TIOCM_CTS
1891 if (mstat & TIOCM_CTS)
1892 *lpModemStat |= MS_CTS_ON;
1893 #endif
1894 #ifdef TIOCM_DSR
1895 if (mstat & TIOCM_DSR)
1896 *lpModemStat |= MS_DSR_ON;
1897 #endif
1898 #ifdef TIOCM_RNG
1899 if (mstat & TIOCM_RNG)
1900 *lpModemStat |= MS_RING_ON;
1901 #endif
1902 #ifdef TIOCM_CAR
1903 /*FIXME: Not really sure about RLSD UB 990810*/
1904 if (mstat & TIOCM_CAR)
1905 *lpModemStat |= MS_RLSD_ON;
1906 #endif
1907 TRACE("%04x -> %s%s%s%s\n", mstat,
1908 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1909 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1910 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1911 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1912 return TRUE;
1913 #else
1914 return FALSE;
1915 #endif
1918 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1920 DWORD ret = 0, queue;
1922 TRACE("mask 0x%08lx\n", mask);
1923 TRACE("old->rx 0x%08x vs. new->rx 0x%08x \n", old->rx, new->rx);
1924 TRACE("old->tx 0x%08x vs. new->tx 0x%08x \n", old->tx, new->tx);
1925 TRACE("old->frame 0x%08x vs. new->frame 0x%08x \n", old->frame, new->frame);
1926 TRACE("old->overrun 0x%08x vs. new->overrun 0x%08x \n", old->overrun, new->overrun);
1927 TRACE("old->parity 0x%08x vs. new->parity 0x%08x \n", old->parity, new->parity);
1928 TRACE("old->brk 0x%08x vs. new->brk 0x%08x \n", old->brk, new->brk);
1929 TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x \n", old->buf_overrun, new->buf_overrun);
1931 ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1932 ret |= ((mask & EV_CTS ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS :0;
1933 ret |= ((mask & EV_DSR ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR :0;
1934 ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1935 ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1936 ret |= ((mask & EV_ERR ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1937 || (old->parity != new->parity)) )?EV_ERR :0;
1938 if (mask & EV_RXCHAR)
1940 queue = 0;
1941 #ifdef TIOCINQ
1942 if(ioctl(fd, TIOCINQ, &queue))
1943 WARN("TIOCINQ returned error\n");
1944 #endif
1945 if (queue)
1946 ret |= EV_RXCHAR;
1948 if (mask & EV_TXEMPTY)
1950 queue = 0;
1951 /* We really want to know when all characters have gone out of the transmitter */
1952 #if defined(TIOCSERGETLSR)
1953 if(ioctl(fd, TIOCSERGETLSR, &queue))
1954 WARN("TIOCSERGETLSR returned error\n");
1955 if (queue)
1956 /* TIOCINQ only checks for an empty buffer */
1957 #elif defined(TIOCINQ)
1958 if(ioctl(fd, TIOCOUTQ, &queue))
1959 WARN("TIOCOUTQ returned error\n");
1960 if (!queue)
1961 #endif
1962 ret |= EV_TXEMPTY;
1964 TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1965 return ret;
1969 /***********************************************************************
1970 * COMM_WaitCommEventService (INTERNAL)
1972 * We need to poll for what is interesting
1973 * TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1976 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1978 async_commio *commio = (async_commio*) arg;
1979 int waitmask = 0;
1980 int rc, fd, abort;
1981 serial_irq_info new_irq_info;
1982 DWORD new_mstat, new_evtmask;
1984 fd=get_comm_fd( commio->handle, GENERIC_READ );
1986 TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n",
1987 commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1991 * TIOCMIWAIT is not adequate
1993 * FIXME:
1994 * We don't handle the EV_RXFLAG (the eventchar)
1996 Sleep(1);
1997 rc= COMM_GetEInfo(fd,&new_irq_info);
1998 if (rc)
1999 TRACE("TIOCGICOUNT err %s\n", strerror(errno));
2000 rc = GetCommModemStatus(commio->handle, &new_mstat);
2001 if (!rc)
2002 TRACE("GetCommModemStatus failed\n");
2003 rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
2004 GetCommMask(commio->handle, &new_evtmask);
2005 abort = (commio->evtmask != new_evtmask);
2006 TRACE("resulting Eventmask 0x%08x\n", rc);
2007 } while (!rc && ! abort);
2008 if (abort) rc = 0;
2009 release_comm_fd( commio->handle, fd );
2010 *commio->buffer = rc;
2011 if (commio->hEvent != INVALID_HANDLE_VALUE )
2012 NtSetEvent( commio->hEvent, NULL );
2013 HeapFree(GetProcessHeap(), 0, commio );
2014 return 0;
2018 /***********************************************************************
2019 * COMM_WaitCommEvent (INTERNAL)
2021 * This function must have an lpOverlapped.
2023 static BOOL COMM_WaitCommEvent(
2024 HANDLE hFile, /* [in] handle of comm port to wait for */
2025 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2026 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2028 int fd;
2029 async_commio* commio;
2030 DWORD result_mask;
2031 BOOL res;
2033 if (!lpOverlapped)
2035 SetLastError(ERROR_INVALID_PARAMETER);
2036 return FALSE;
2039 if (NtResetEvent(lpOverlapped->hEvent,NULL))
2040 return FALSE;
2042 fd = get_comm_fd( hFile, GENERIC_WRITE );
2043 if (fd < 0) return FALSE;
2045 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
2046 if (!commio)
2048 release_comm_fd( hFile, fd );
2049 return FALSE;
2052 commio->handle = hFile;
2053 commio->buffer = (char *)lpdwEvents;
2054 commio->hEvent = lpOverlapped->hEvent;
2055 GetCommMask(hFile, &commio->evtmask);
2057 /* We may never return, if some capabilities miss
2058 * Return error in that case
2060 #if !defined(TIOCINQ)
2061 if(commio->evtmask & EV_RXCHAR)
2062 goto error;
2063 #endif
2064 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
2065 if(commio->evtmask & EV_TXEMPTY)
2066 goto error;
2067 #endif
2068 #if !defined(TIOCMGET)
2069 if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
2070 goto error;
2071 #endif
2072 #if !defined(TIOCM_CTS)
2073 if(commio->evtmask & EV_CTS)
2074 goto error;
2075 #endif
2076 #if !defined(TIOCM_DSR)
2077 if(commio->evtmask & EV_DSR)
2078 goto error;
2079 #endif
2080 #if !defined(TIOCM_RNG)
2081 if(commio->evtmask & EV_RING)
2082 goto error;
2083 #endif
2084 #if !defined(TIOCM_CAR)
2085 if(commio->evtmask & EV_RLSD)
2086 goto error;
2087 #endif
2088 if(commio->evtmask & EV_RXFLAG)
2089 FIXME("EV_RXFLAG not handled\n");
2090 COMM_GetEInfo(fd,&commio->irq_info);
2091 GetCommModemStatus(hFile, &commio->mstat);
2092 /* We might have received something or the TX bufffer is delivered*/
2093 result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
2094 if (result_mask)
2096 TRACE("Event already met\n");
2097 *lpdwEvents = result_mask;
2098 release_comm_fd( commio->handle, fd );
2099 HeapFree(GetProcessHeap(), 0, commio );
2100 res = TRUE;
2102 else
2104 CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
2105 SetLastError(ERROR_IO_PENDING);
2106 res = FALSE;
2108 return res;
2109 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
2110 error:
2111 FIXME("Returning error because of missing capabilities\n");
2112 HeapFree(GetProcessHeap(), 0, commio );
2113 SetLastError(ERROR_INVALID_PARAMETER);
2114 return FALSE;
2115 #endif
2117 /***********************************************************************
2118 * WaitCommEvent (KERNEL32.@)
2120 * Wait until something interesting happens on a COMM port.
2121 * Interesting things (events) are set by calling SetCommMask before
2122 * this function is called.
2124 * RETURNS:
2125 * TRUE if successful
2126 * FALSE if failure
2128 * The set of detected events will be written to *lpdwEventMask
2129 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2131 * BUGS:
2132 * Only supports EV_RXCHAR and EV_TXEMPTY
2134 BOOL WINAPI WaitCommEvent(
2135 HANDLE hFile, /* [in] handle of comm port to wait for */
2136 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2137 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2139 OVERLAPPED ov;
2140 int ret = 0;
2141 DWORD res, err;
2143 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2145 if(lpOverlapped)
2146 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2148 /* if there is no overlapped structure, create our own */
2149 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
2151 res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2152 err = GetLastError();
2153 if (!res)
2155 if (err == ERROR_IO_PENDING)
2159 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
2160 } while (res != WAIT_OBJECT_0);
2161 TRACE("Event met\n:");
2162 ret = TRUE;
2164 else
2166 FIXME("Unknown error 0x%08lx\n", err);
2167 ret = FALSE;
2170 else
2171 ret = TRUE;
2172 CloseHandle(ov.hEvent);
2174 return ret;
2177 /***********************************************************************
2178 * GetCommProperties (KERNEL32.@)
2180 * This function fills in a structure with the capabilities of the
2181 * communications port driver.
2183 * RETURNS
2185 * TRUE on success, FALSE on failure
2186 * If successful, the lpCommProp structure be filled in with
2187 * properties of the comm port.
2189 BOOL WINAPI GetCommProperties(
2190 HANDLE hFile, /* [in] handle of the comm port */
2191 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2193 FIXME("(%p %p )\n",hFile,lpCommProp);
2194 if(!lpCommProp)
2195 return FALSE;
2198 * These values should be valid for LINUX's serial driver
2199 * FIXME: Perhaps they deserve an #ifdef LINUX
2201 memset(lpCommProp,0,sizeof(COMMPROP));
2202 lpCommProp->wPacketLength = 1;
2203 lpCommProp->wPacketVersion = 1;
2204 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2205 lpCommProp->dwReserved1 = 0;
2206 lpCommProp->dwMaxTxQueue = 4096;
2207 lpCommProp->dwMaxRxQueue = 4096;
2208 lpCommProp->dwMaxBaud = BAUD_115200;
2209 lpCommProp->dwProvSubType = PST_RS232;
2210 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2211 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2212 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2213 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2214 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2215 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2216 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2217 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2218 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2219 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2220 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2222 return TRUE;
2225 /***********************************************************************
2226 * FIXME:
2227 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2228 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2229 * This is dependent on the type of COMM port, but since it is doubtful
2230 * anybody will get around to implementing support for fancy serial
2231 * ports in WINE, this is hardcoded for the time being. The name of
2232 * this DLL should be stored in and read from the system registry in
2233 * the hive HKEY_LOCAL_MACHINE, key
2234 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2235 * where ???? is the port number... that is determined by PNP
2236 * The DLL should be loaded when the COMM port is opened, and closed
2237 * when the COMM port is closed. - MJM 20 June 2000
2238 ***********************************************************************/
2239 static WCHAR lpszSerialUI[] = {
2240 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2243 /***********************************************************************
2244 * CommConfigDialogA (KERNEL32.@)
2246 * Raises a dialog that allows the user to configure a comm port.
2247 * Fills the COMMCONFIG struct with information specified by the user.
2248 * This function should call a similar routine in the COMM driver...
2250 * RETURNS
2252 * TRUE on success, FALSE on failure
2253 * If successful, the lpCommConfig structure will contain a new
2254 * configuration for the comm port, as specified by the user.
2256 * BUGS
2257 * The library with the CommConfigDialog code is never unloaded.
2258 * Perhaps this should be done when the comm port is closed?
2260 BOOL WINAPI CommConfigDialogA(
2261 LPCSTR lpszDevice, /* [in] name of communications device */
2262 HWND hWnd, /* [in] parent window for the dialog */
2263 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2265 FARPROC lpfnCommDialog;
2266 HMODULE hConfigModule;
2267 BOOL r = FALSE;
2269 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2271 hConfigModule = LoadLibraryW(lpszSerialUI);
2272 if(!hConfigModule)
2273 return FALSE;
2275 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2277 if(lpfnCommDialog)
2278 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2280 FreeLibrary(hConfigModule);
2282 return r;
2285 /***********************************************************************
2286 * CommConfigDialogW (KERNEL32.@)
2288 * see CommConfigDialogA for more info
2290 BOOL WINAPI CommConfigDialogW(
2291 LPCWSTR lpszDevice, /* [in] name of communications device */
2292 HWND hWnd, /* [in] parent window for the dialog */
2293 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2295 FARPROC lpfnCommDialog;
2296 HMODULE hConfigModule;
2297 BOOL r = FALSE;
2299 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2301 hConfigModule = LoadLibraryW(lpszSerialUI);
2302 if(!hConfigModule)
2303 return FALSE;
2305 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2307 if(lpfnCommDialog)
2308 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2310 FreeLibrary(hConfigModule);
2312 return r;
2315 /***********************************************************************
2316 * GetCommConfig (KERNEL32.@)
2318 * Fill in the COMMCONFIG structure for the comm port hFile
2320 * RETURNS
2322 * TRUE on success, FALSE on failure
2323 * If successful, lpCommConfig contains the comm port configuration.
2325 * BUGS
2328 BOOL WINAPI GetCommConfig(
2329 HANDLE hFile, /* [in] The communications device. */
2330 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2331 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2332 afterwards the number of bytes copied to the buffer or
2333 the needed size of the buffer. */
2335 BOOL r;
2337 TRACE("(%p %p)\n",hFile,lpCommConfig);
2339 if(lpCommConfig == NULL)
2340 return FALSE;
2341 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2342 *lpdwSize = sizeof(COMMCONFIG);
2343 if(r)
2344 return FALSE;
2346 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2347 lpCommConfig->wVersion = 1;
2348 lpCommConfig->wReserved = 0;
2349 r = GetCommState(hFile,&lpCommConfig->dcb);
2350 lpCommConfig->dwProviderSubType = PST_RS232;
2351 lpCommConfig->dwProviderOffset = 0;
2352 lpCommConfig->dwProviderSize = 0;
2354 return r;
2357 /***********************************************************************
2358 * SetCommConfig (KERNEL32.@)
2360 * Sets the configuration of the communications device.
2362 * RETURNS
2364 * True on success, false if the handle was bad is not a communications device.
2366 BOOL WINAPI SetCommConfig(
2367 HANDLE hFile, /* [in] The communications device. */
2368 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2369 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2371 TRACE("(%p %p)\n",hFile,lpCommConfig);
2372 return SetCommState(hFile,&lpCommConfig->dcb);
2375 /***********************************************************************
2376 * SetDefaultCommConfigA (KERNEL32.@)
2378 * Initializes the default configuration for the specified communication
2379 * device. (ascii)
2381 * RETURNS
2383 * True if the device was found and the defaults set, false otherwise
2385 BOOL WINAPI SetDefaultCommConfigW(
2386 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2387 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2388 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2390 FARPROC lpfnSetDefaultCommConfig;
2391 HMODULE hConfigModule;
2392 BOOL r = FALSE;
2394 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2396 hConfigModule = LoadLibraryW(lpszSerialUI);
2397 if(!hConfigModule)
2398 return r;
2400 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2401 if (lpfnSetDefaultCommConfig)
2402 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2404 FreeLibrary(hConfigModule);
2406 return r;
2410 /***********************************************************************
2411 * SetDefaultCommConfigW (KERNEL32.@)
2413 * Initializes the default configuration for the specified
2414 * communication device. (unicode)
2416 * RETURNS
2419 BOOL WINAPI SetDefaultCommConfigA(
2420 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2421 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2422 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2424 BOOL r;
2425 LPWSTR lpDeviceW = NULL;
2426 DWORD len;
2428 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2430 if (lpszDevice)
2432 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2433 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2434 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2436 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2437 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2438 return r;
2442 /***********************************************************************
2443 * GetDefaultCommConfigW (KERNEL32.@)
2445 * Acquires the default configuration of the specified communication device. (unicode)
2447 * RETURNS
2449 * True on successful reading of the default configuration,
2450 * if the device is not found or the buffer is too small.
2452 BOOL WINAPI GetDefaultCommConfigW(
2453 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2454 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2455 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2456 afterwards the number of bytes copied to the buffer or
2457 the needed size of the buffer. */
2459 LPDCB lpdcb = &(lpCC->dcb);
2460 WCHAR temp[40];
2461 static const WCHAR comW[] = {'C','O','M',0};
2462 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2464 if (strncmpiW(lpszName,comW,3)) {
2465 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2466 return FALSE;
2469 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2470 if (*lpdwSize < sizeof(COMMCONFIG)) {
2471 *lpdwSize = sizeof(COMMCONFIG);
2472 return FALSE;
2475 *lpdwSize = sizeof(COMMCONFIG);
2477 lpCC->dwSize = sizeof(COMMCONFIG);
2478 lpCC->wVersion = 1;
2479 lpCC->dwProviderSubType = PST_RS232;
2480 lpCC->dwProviderOffset = 0L;
2481 lpCC->dwProviderSize = 0L;
2483 sprintfW( temp, formatW, lpszName[3]);
2484 FIXME("setting %s as default\n", debugstr_w(temp));
2486 return BuildCommDCBW( temp, lpdcb);
2489 /**************************************************************************
2490 * GetDefaultCommConfigA (KERNEL32.@)
2492 * Acquires the default configuration of the specified communication device. (ascii)
2494 * RETURNS
2496 * True on successful reading of the default configuration,
2497 * if the device is not found or the buffer is too small.
2499 BOOL WINAPI GetDefaultCommConfigA(
2500 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2501 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2502 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2503 afterwards the number of bytes copied to the buffer or
2504 the needed size of the buffer. */
2506 BOOL ret = FALSE;
2507 UNICODE_STRING lpszNameW;
2509 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2510 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2511 else lpszNameW.Buffer = NULL;
2513 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2515 RtlFreeUnicodeString(&lpszNameW);
2516 return ret;