wined3d: Prevent crash in setup_light.
[wine] / dlls / kernel / comm.c
1 /*
2  * DEC 93 Erik Bos <erik@xs4all.nl>
3  *
4  * Copyright 1996 Marcus Meissner
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #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
58
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"
66
67 #include "wine/server.h"
68 #include "wine/unicode.h"
69
70 #include "wine/debug.h"
71
72 #ifdef HAVE_LINUX_SERIAL_H
73 #include <linux/serial.h>
74 #endif
75
76 WINE_DEFAULT_DEBUG_CHANNEL(comm);
77
78 /* retrieve the Unix handle corresponding to a comm handle */
79 static int get_comm_fd( HANDLE handle, DWORD access )
80 {
81     int fd, ret;
82
83     ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
84     if (ret) SetLastError( RtlNtStatusToDosError(ret) );
85     return fd;
86 }
87
88 /* release the Unix handle returned by get_comm_fd */
89 static inline void release_comm_fd( HANDLE handle, int fd )
90 {
91     wine_server_release_fd( handle, fd );
92 }
93
94 /*             serial_irq_info
95  * local structure holding the irq values we need for WaitCommEvent()
96  *
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
100  *
101  */
102 typedef struct serial_irq_info
103 {
104     int rx , tx, frame, overrun, parity, brk, buf_overrun;
105 }serial_irq_info;
106
107 /***********************************************************************
108  * Data needed by the thread polling for the changing CommEvent
109  */
110 typedef struct async_commio
111 {
112     HANDLE              handle;
113     char*               buffer;
114     HANDLE              hEvent;
115     DWORD               evtmask;
116     DWORD               mstat;
117     serial_irq_info     irq_info;
118 } async_commio;
119
120 /***********************************************************************/
121
122 #if !defined(TIOCINQ) && defined(FIONREAD)
123 #define TIOCINQ FIONREAD
124 #endif
125
126 /***********************************************************************
127  *   Get extended interrupt count info, needed for WaitCommEvent
128  */
129 static int COMM_GetEInfo(int fd, serial_irq_info *irq_info)
130 {
131 #ifdef TIOCGICOUNT
132     struct serial_icounter_struct einfo;
133     if (!ioctl(fd,TIOCGICOUNT, &einfo))
134     {
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;
143     }
144 #endif
145     memset(irq_info,0, sizeof(serial_irq_info));
146     return -1;
147 }
148
149 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
150 {
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
161 }
162
163 /***********************************************************************
164  *           COMM_Parse*   (Internal)
165  *
166  *  The following COMM_Parse* functions are used by the BuildCommDCB
167  *  functions to help parse the various parts of the device control string.
168  */
169 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
170 {
171         static const WCHAR comW[] = {'C','O','M',0};
172
173         /* The device control string may optionally start with "COMx" followed
174            by an optional ':' and spaces. */
175         if(!strncmpiW(ptr, comW, 3))
176         {
177                 ptr += 3;
178
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;
183                 
184                 /* Advance pointer past port number */
185                 while(*ptr >= '0' && *ptr <= '9') ptr++;
186                 
187                 /* The com port number must be followed by a ':' or ' ' */
188                 if(*ptr != ':' && *ptr != ' ')
189                         return NULL;
190
191                 /* Advance pointer to beginning of next parameter */
192                 while(*ptr == ' ') ptr++;
193                 if(*ptr == ':')
194                 {
195                         ptr++;
196                         while(*ptr == ' ') ptr++;
197                 }
198         }
199         /* The device control string must not start with a space. */
200         else if(*ptr == ' ')
201                 return NULL;
202         
203         return ptr;
204 }
205  
206 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
207 {
208         if(*ptr < '0' || *ptr > '9') return NULL;
209         *lpnumber = strtoulW(ptr, NULL, 10);
210         while(*ptr >= '0' && *ptr <= '9') ptr++;
211         return ptr;
212 }
213
214 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
215 {
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 */
219
220         switch(toupperW(*ptr++))
221         {
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;
239         }
240
241         return ptr;
242 }
243
244 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
245 {
246         DWORD temp;
247
248         if(!(ptr = COMM_ParseNumber(ptr, &temp)))
249                 return NULL;
250
251         if(temp >= 5 && temp <= 8)
252         {
253                 *lpbytesize = temp;
254                 return ptr;
255         }
256         else
257                 return NULL;
258 }
259
260 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
261 {
262         DWORD temp;
263         static const WCHAR stopbits15W[] = {'1','.','5',0};
264
265         if(!strncmpW(stopbits15W, ptr, 3))
266         {
267                 ptr += 3;
268                 *lpstopbits = ONE5STOPBITS;
269         }
270         else
271         {
272                 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
273                         return NULL;
274
275                 if(temp == 1)
276                         *lpstopbits = ONESTOPBIT;
277                 else if(temp == 2)
278                         *lpstopbits = TWOSTOPBITS;
279                 else
280                         return NULL;
281         }
282         
283         return ptr;
284 }
285
286 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
287 {
288         static const WCHAR onW[] = {'o','n',0};
289         static const WCHAR offW[] = {'o','f','f',0};
290
291         if(!strncmpiW(onW, ptr, 2))
292         {
293                 ptr += 2;
294                 *lponoff = 1;
295         }
296         else if(!strncmpiW(offW, ptr, 3))
297         {
298                 ptr += 3;
299                 *lponoff = 0;
300         }
301         else
302                 return NULL;
303
304         return ptr;
305 }
306
307 /***********************************************************************
308  *           COMM_BuildOldCommDCB   (Internal)
309  *
310  *  Build a DCB using the old style settings string eg: "96,n,8,1"
311  */
312 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
313 {
314         WCHAR last = 0;
315
316         if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
317                 return FALSE;
318         
319         switch(lpdcb->BaudRate)
320         {
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;
335         }
336
337         while(*device == ' ') device++;
338         if(*device++ != ',') return FALSE;
339         while(*device == ' ') device++;
340
341         if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
342                 return FALSE;
343
344         while(*device == ' ') device++;
345         if(*device++ != ',') return FALSE;
346         while(*device == ' ') device++;
347                 
348         if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
349                 return FALSE;
350
351         while(*device == ' ') device++;
352         if(*device++ != ',') return FALSE;
353         while(*device == ' ') device++;
354
355         if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
356                 return FALSE;
357
358         /* The last parameter for flow control is optional. */
359         while(*device == ' ') device++;
360         if(*device == ',')
361         {
362                 device++;
363                 while(*device == ' ') device++;
364                 if(*device) last = toupperW(*device++);
365                 while(*device == ' ') device++;
366         }
367
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)
371         {
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;
398         }
399
400         /* This should be the end of the string. */
401         if(*device) return FALSE;
402         
403         return TRUE;
404 }
405
406 /***********************************************************************
407  *           COMM_BuildNewCommDCB   (Internal)
408  *
409  *  Build a DCB using the new style settings string.
410  *   eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
411  */
412 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
413 {
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};
427
428         while(*device)
429         {
430                 while(*device == ' ') device++;
431
432                 if(!strncmpiW(baudW, device, 5))
433                 {
434                         baud = TRUE;
435                         
436                         if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
437                                 return FALSE;
438                 }
439                 else if(!strncmpiW(parityW, device, 7))
440                 {
441                         if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
442                                 return FALSE;
443                 }
444                 else if(!strncmpiW(dataW, device, 5))
445                 {
446                         if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
447                                 return FALSE;
448                 }
449                 else if(!strncmpiW(stopW, device, 5))
450                 {
451                         stop = TRUE;
452                         
453                         if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
454                                 return FALSE;
455                 }
456                 else if(!strncmpiW(toW, device, 3))
457                 {
458                         if(!(device = COMM_ParseOnOff(device + 3, &temp)))
459                                 return FALSE;
460
461                         lptimeouts->ReadIntervalTimeout = 0;
462                         lptimeouts->ReadTotalTimeoutMultiplier = 0;
463                         lptimeouts->ReadTotalTimeoutConstant = 0;
464                         lptimeouts->WriteTotalTimeoutMultiplier = 0;
465                         lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
466                 }
467                 else if(!strncmpiW(xonW, device, 4))
468                 {
469                         if(!(device = COMM_ParseOnOff(device + 4, &temp)))
470                                 return FALSE;
471
472                         lpdcb->fOutX = temp;
473                         lpdcb->fInX = temp;
474                 }
475                 else if(!strncmpiW(odsrW, device, 5))
476                 {
477                         if(!(device = COMM_ParseOnOff(device + 5, &temp)))
478                                 return FALSE;
479
480                         lpdcb->fOutxDsrFlow = temp;
481                 }
482                 else if(!strncmpiW(octsW, device, 5))
483                 {
484                         if(!(device = COMM_ParseOnOff(device + 5, &temp)))
485                                 return FALSE;
486
487                         lpdcb->fOutxCtsFlow = temp;
488                 }
489                 else if(!strncmpiW(dtrW, device, 4))
490                 {
491                         if(!(device = COMM_ParseOnOff(device + 4, &temp)))
492                                 return FALSE;
493
494                         lpdcb->fDtrControl = temp;
495                 }
496                 else if(!strncmpiW(rtsW, device, 4))
497                 {
498                         if(!(device = COMM_ParseOnOff(device + 4, &temp)))
499                                 return FALSE;
500
501                         lpdcb->fRtsControl = temp;
502                 }
503                 else if(!strncmpiW(idsrW, device, 5))
504                 {
505                         if(!(device = COMM_ParseOnOff(device + 5, &temp)))
506                                 return FALSE;
507
508                         /* Win NT sets the fDsrSensitivity member based on the
509                            idsr parameter.  Win 9x sets fOutxDsrFlow instead. */
510                         lpdcb->fDsrSensitivity = temp;
511                 }
512                 else
513                         return FALSE;
514
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;
519         }
520
521         /* If stop bits were not specified, a default is always supplied. */
522         if(!stop)
523         {
524                 if(baud && lpdcb->BaudRate == 110)
525                         lpdcb->StopBits = TWOSTOPBITS;
526                 else
527                         lpdcb->StopBits = ONESTOPBIT;
528         }
529
530         return TRUE;
531 }
532
533 /**************************************************************************
534  *         BuildCommDCBA                (KERNEL32.@)
535  *
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.
539  *
540  * RETURNS
541  *
542  *  True on success, false on a malformed control string.
543  */
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. */
547 {
548         return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
549 }
550
551 /**************************************************************************
552  *         BuildCommDCBAndTimeoutsA             (KERNEL32.@)
553  *
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.
557  *
558  * RETURNS
559  *
560  *  True on success, false bad handles etc.
561  */
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. */
566 {
567         BOOL ret = FALSE;
568         UNICODE_STRING deviceW;
569
570         TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
571         if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
572         else deviceW.Buffer = NULL;
573
574         if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
575
576         RtlFreeUnicodeString(&deviceW);
577         return ret;
578 }
579
580 /**************************************************************************
581  *         BuildCommDCBAndTimeoutsW     (KERNEL32.@)
582  *
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.
586  *
587  * RETURNS
588  *
589  *  True on success, false bad handles etc
590  */
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. */
595 {
596         DCB dcb;
597         COMMTIMEOUTS timeouts;
598         BOOL result;
599         LPCWSTR ptr = devid;
600         
601         TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
602
603         /* Set DCBlength. (Windows NT does not do this, but 9x does) */
604         lpdcb->DCBlength = sizeof(DCB);
605
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));
611
612         ptr = COMM_ParseStart(ptr);
613
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);
620
621         if(result)
622         {
623                 memcpy(lpdcb, &dcb, sizeof(DCB));
624                 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
625                 return TRUE;
626         }
627         else
628         {
629                 WARN("Invalid device control string: %s\n", debugstr_w(devid));
630                 SetLastError(ERROR_INVALID_PARAMETER);
631                 return FALSE;
632         }       
633 }
634
635 /**************************************************************************
636  *         BuildCommDCBW                (KERNEL32.@)
637  *
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.
641  *
642  * RETURNS
643  *
644  *  True on success, false on a malformed control string.
645  */
646 BOOL WINAPI BuildCommDCBW(
647     LPCWSTR devid, /* [in] The unicode device control string. */
648     LPDCB   lpdcb) /* [out] The device control block to be updated. */
649 {
650         return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
651 }
652
653 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
654 {
655     DWORD ret;
656
657     SERVER_START_REQ( set_serial_info )
658     {
659         req->handle = handle;
660         req->flags = SERIALINFO_SET_ERROR;
661         req->commerror = error;
662         ret = !wine_server_call_err( req );
663     }
664     SERVER_END_REQ;
665     return ret;
666 }
667
668 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
669 {
670     DWORD ret;
671
672     if(!lperror)
673         return FALSE;
674
675     SERVER_START_REQ( get_serial_info )
676     {
677         req->handle = handle;
678         ret = !wine_server_call_err( req );
679         *lperror = reply->commerror;
680     }
681     SERVER_END_REQ;
682
683     return ret;
684 }
685
686 /*****************************************************************************
687  *      SetCommBreak            (KERNEL32.@)
688  *
689  *  Halts the transmission of characters to a communications device.
690  *
691  * PARAMS
692  *      handle  [in] The communications device to suspend
693  *
694  * RETURNS
695  *
696  *  True on success, and false if the communications device could not be found,
697  *  the control is not supported.
698  *
699  * BUGS
700  *
701  *  Only TIOCSBRK and TIOCCBRK are supported.
702  */
703 BOOL WINAPI SetCommBreak(HANDLE handle)
704 {
705     return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, NULL, NULL);
706 }
707
708 /*****************************************************************************
709  *      ClearCommBreak          (KERNEL32.@)
710  *
711  *  Resumes character transmission from a communication device.
712  *
713  * PARAMS
714  *
715  *      handle [in] The halted communication device whose character transmission is to be resumed
716  *
717  * RETURNS
718  *
719  *  True on success and false if the communications device could not be found.
720  *
721  * BUGS
722  *
723  *  Only TIOCSBRK and TIOCCBRK are supported.
724  */
725 BOOL WINAPI ClearCommBreak(HANDLE handle)
726 {
727     return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, NULL, NULL);
728 }
729
730 /*****************************************************************************
731  *      EscapeCommFunction      (KERNEL32.@)
732  *
733  *  Directs a communication device to perform an extended function.
734  *
735  * RETURNS
736  *
737  *  True or requested data on successful completion of the command,
738  *  false if the device is not present cannot execute the command
739  *  or the command failed.
740  */
741 BOOL WINAPI EscapeCommFunction(
742     HANDLE handle,    /* [in] The communication device to perform the extended function. */
743     UINT   nFunction) /* [in] The extended function to be performed. */
744 {
745         int fd,direct=FALSE,result=FALSE;
746         struct termios  port;
747
748         TRACE("handle %p, function=%d\n", handle, nFunction);
749         fd = get_comm_fd( handle, FILE_READ_DATA );
750         if(fd<0) return FALSE;
751
752         if (tcgetattr(fd,&port) == -1) {
753                 COMM_SetCommError(handle,CE_IOE);
754                 release_comm_fd( handle, fd );
755                 return FALSE;
756         }
757
758         switch (nFunction) {
759                 case RESETDEV:
760                         TRACE("\n");
761                         break;
762
763                 case CLRDTR:
764                         TRACE("CLRDTR\n");
765 #ifdef TIOCM_DTR
766                         direct=TRUE;
767                         result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
768                         break;
769 #endif
770
771                 case CLRRTS:
772                         TRACE("CLRRTS\n");
773 #ifdef TIOCM_RTS
774                         direct=TRUE;
775                         result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
776                         break;
777 #endif
778
779                 case SETDTR:
780                         TRACE("SETDTR\n");
781 #ifdef TIOCM_DTR
782                         direct=TRUE;
783                         result= COMM_WhackModem(fd, 0, TIOCM_DTR);
784                         break;
785 #endif
786
787                 case SETRTS:
788                         TRACE("SETRTS\n");
789 #ifdef TIOCM_RTS
790                         direct=TRUE;
791                         result= COMM_WhackModem(fd, 0, TIOCM_RTS);
792                         break;
793 #endif
794
795                 case SETXOFF:
796                         TRACE("SETXOFF\n");
797                         port.c_iflag |= IXOFF;
798                         break;
799
800                 case SETXON:
801                         TRACE("SETXON\n");
802                         port.c_iflag |= IXON;
803                         break;
804                 case SETBREAK:
805                         TRACE("setbreak\n");
806 #ifdef  TIOCSBRK
807                         direct=TRUE;
808                         result = ioctl(fd,TIOCSBRK,0);
809                         break;
810 #endif
811                 case CLRBREAK:
812                         TRACE("clrbreak\n");
813 #ifdef  TIOCSBRK
814                         direct=TRUE;
815                         result = ioctl(fd,TIOCCBRK,0);
816                         break;
817 #endif
818                 default:
819                         WARN("(handle=%p,nFunction=%d): Unknown function\n",
820                         handle, nFunction);
821                         break;
822         }
823
824         if (!direct)
825           if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
826                 release_comm_fd( handle, fd );
827                 COMM_SetCommError(handle,CE_IOE);
828                 return FALSE;
829           } else
830                 result= TRUE;
831         else
832           {
833             if (result == -1)
834               {
835                 result= FALSE;
836                 COMM_SetCommError(handle,CE_IOE);
837               }
838             else
839               result = TRUE;
840           }
841         release_comm_fd( handle, fd );
842         return result;
843 }
844
845 /********************************************************************
846  *      PurgeComm        (KERNEL32.@)
847  *
848  *  Terminates pending operations and/or discards buffers on a
849  *  communication resource.
850  *
851  * PARAMS
852  *
853  *      handle  [in] The communication resource to be purged
854  *      flags   [in] Flags for clear pending/buffer on input/output
855  *
856  * RETURNS
857  *
858  *  True on success and false if the communications handle is bad.
859  */
860 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags)
861 {
862     return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags),
863                            NULL, 0, NULL, NULL);
864 }
865
866 /*****************************************************************************
867  *      ClearCommError  (KERNEL32.@)
868  *
869  *  Enables further I/O operations on a communications resource after
870  *  supplying error and current status information.
871  *
872  * RETURNS
873  *
874  *  True on success, false if the communication resource handle is bad.
875  */
876 BOOL WINAPI ClearCommError(
877     HANDLE    handle, /* [in] The communication resource with the error. */
878     LPDWORD   errors, /* [out] Flags indicating error the resource experienced. */
879     LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
880 {
881     int fd;
882
883     fd=get_comm_fd( handle, FILE_READ_DATA );
884     if(0>fd) return FALSE;
885
886     if (lpStat)
887     {
888         lpStat->fCtsHold = 0;
889         lpStat->fDsrHold = 0;
890         lpStat->fRlsdHold = 0;
891         lpStat->fXoffHold = 0;
892         lpStat->fXoffSent = 0;
893         lpStat->fEof = 0;
894         lpStat->fTxim = 0;
895         lpStat->fReserved = 0;
896
897 #ifdef TIOCOUTQ
898         if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
899             WARN("ioctl returned error\n");
900 #else
901         lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
902 #endif
903
904 #ifdef TIOCINQ
905         if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
906             WARN("ioctl returned error\n");
907 #endif
908
909         TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
910               handle, lpStat->cbInQue, lpStat->cbOutQue);
911     }
912
913     release_comm_fd( handle, fd );
914
915     COMM_GetCommError(handle, errors);
916     COMM_SetCommError(handle, 0);
917
918     return TRUE;
919 }
920
921 /*****************************************************************************
922  *      SetupComm       (KERNEL32.@)
923  *
924  *  Called after CreateFile to hint to the communication resource to use
925  *  specified sizes for input and output buffers rather than the default values.
926  *
927  * RETURNS
928  *
929  *  True if successful, false if the communications resource handle is bad.
930  *
931  * BUGS
932  *
933  *  Stub.
934  */
935 BOOL WINAPI SetupComm(
936     HANDLE handle,  /* [in] The just created communication resource handle. */
937     DWORD  insize,  /* [in] The suggested size of the communication resources input buffer in bytes. */
938     DWORD  outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
939 {
940     int fd;
941
942     FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
943     fd=get_comm_fd( handle, FILE_READ_DATA );
944     if(0>fd) return FALSE;
945     release_comm_fd( handle, fd );
946     return TRUE;
947 }
948
949 /*****************************************************************************
950  *      GetCommMask     (KERNEL32.@)
951  *
952  *  Obtain the events associated with a communication device that will cause
953  *  a call WaitCommEvent to return.
954  *
955  *  PARAMS
956  *
957  *      handle  [in]    The communications device
958  *      evtmask [out]   The events which cause WaitCommEvent to return
959  *
960  *  RETURNS
961  *
962  *   True on success, fail on bad device handle etc.
963  */
964 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask)
965 {
966     TRACE("handle %p, mask %p\n", handle, evtmask);
967     return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK,
968                            NULL, 0, evtmask, sizeof(*evtmask), NULL, NULL);
969 }
970
971 /*****************************************************************************
972  *      SetCommMask     (KERNEL32.@)
973  *
974  *  There be some things we need to hear about yon there communications device.
975  *  (Set which events associated with a communication device should cause
976  *  a call WaitCommEvent to return.)
977  *
978  * PARAMS
979  *
980  *      handle  [in]    The communications device
981  *      evtmask [in]    The events that are to be monitored
982  *
983  * RETURNS
984  *
985  *  True on success, false on bad handle etc.
986  */
987 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
988 {
989     TRACE("handle %p, mask %lx\n", handle, evtmask);
990     return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK,
991                            &evtmask, sizeof(evtmask), NULL, 0, NULL, NULL);
992 }
993
994 /*****************************************************************************
995  *      SetCommState    (KERNEL32.@)
996  *
997  *  Re-initializes all hardware and control settings of a communications device,
998  *  with values from a device control block without effecting the input and output
999  *  queues.
1000  *
1001  * RETURNS
1002  *
1003  *  True on success, false on failure eg if the XonChar is equal to the XoffChar.
1004  */
1005 BOOL WINAPI SetCommState(
1006     HANDLE handle, /* [in] The communications device. */
1007     LPDCB  lpdcb)  /* [out] The device control block. */
1008 {
1009      struct termios port;
1010      int fd, bytesize, stopbits;
1011      BOOL ret;
1012
1013      TRACE("handle %p, ptr %p\n", handle, lpdcb);
1014      TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1015            lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1016            (lpdcb->StopBits == ONESTOPBIT)?1:
1017            (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1018      TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1019            (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1020      TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1021              lpdcb->fRtsControl);
1022      TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1023              lpdcb->fDtrControl);
1024              
1025
1026      fd = get_comm_fd( handle, FILE_READ_DATA );
1027      if (fd < 0) return FALSE;
1028
1029      if ((tcgetattr(fd,&port)) == -1) {
1030          int save_error = errno;
1031          COMM_SetCommError(handle,CE_IOE);
1032          release_comm_fd( handle, fd );
1033          ERR("tcgetattr error '%s'\n", strerror(save_error));
1034          return FALSE;
1035      }
1036
1037         port.c_cc[VMIN] = 0;
1038         port.c_cc[VTIME] = 1;
1039
1040 #ifdef IMAXBEL
1041         port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK|IMAXBEL);
1042 #else
1043         port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK);
1044 #endif
1045         port.c_iflag |= (IGNBRK);
1046
1047         port.c_oflag &= ~(OPOST);
1048
1049         port.c_cflag &= ~(HUPCL);
1050         port.c_cflag |= CLOCAL | CREAD;
1051
1052         port.c_lflag &= ~(ICANON|ECHO|ISIG);
1053         port.c_lflag |= NOFLSH;
1054
1055 #ifdef CBAUD
1056         port.c_cflag &= ~CBAUD;
1057         switch (lpdcb->BaudRate) {
1058                 case 0:
1059                         port.c_cflag |= B0;
1060                         break;
1061                 case 50:
1062                         port.c_cflag |= B50;
1063                         break;
1064                 case 75:
1065                         port.c_cflag |= B75;
1066                         break;
1067                 case 110:
1068                 case CBR_110:
1069                         port.c_cflag |= B110;
1070                         break;
1071                 case 134:
1072                         port.c_cflag |= B134;
1073                         break;
1074                 case 150:
1075                         port.c_cflag |= B150;
1076                         break;
1077                 case 200:
1078                         port.c_cflag |= B200;
1079                         break;
1080                 case 300:
1081                 case CBR_300:
1082                         port.c_cflag |= B300;
1083                         break;
1084                 case 600:
1085                 case CBR_600:
1086                         port.c_cflag |= B600;
1087                         break;
1088                 case 1200:
1089                 case CBR_1200:
1090                         port.c_cflag |= B1200;
1091                         break;
1092                 case 1800:
1093                         port.c_cflag |= B1800;
1094                         break;
1095                 case 2400:
1096                 case CBR_2400:
1097                         port.c_cflag |= B2400;
1098                         break;
1099                 case 4800:
1100                 case CBR_4800:
1101                         port.c_cflag |= B4800;
1102                         break;
1103                 case 9600:
1104                 case CBR_9600:
1105                         port.c_cflag |= B9600;
1106                         break;
1107                 case 19200:
1108                 case CBR_19200:
1109                         port.c_cflag |= B19200;
1110                         break;
1111                 case 38400:
1112                 case CBR_38400:
1113                         port.c_cflag |= B38400;
1114                         break;
1115 #ifdef B57600
1116                 case 57600:
1117                         port.c_cflag |= B57600;
1118                         break;
1119 #endif
1120 #ifdef B115200
1121                 case 115200:
1122                         port.c_cflag |= B115200;
1123                         break;
1124 #endif
1125 #ifdef B230400
1126                 case 230400:
1127                         port.c_cflag |= B230400;
1128                         break;
1129 #endif
1130 #ifdef B460800
1131                 case 460800:
1132                         port.c_cflag |= B460800;
1133                         break;
1134 #endif
1135                 default:
1136 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1137                         {   struct serial_struct nuts;
1138                             int arby;
1139                             ioctl(fd, TIOCGSERIAL, &nuts);
1140                             nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1141                             if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1142                             arby = nuts.baud_base / nuts.custom_divisor;
1143                             nuts.flags &= ~ASYNC_SPD_MASK;
1144                             nuts.flags |= ASYNC_SPD_CUST;
1145                             WARN("You (or a program acting at your behest) have specified\n"
1146                                  "a non-standard baud rate %ld.  Wine will set the rate to %d,\n"
1147                                  "which is as close as we can get by our present understanding of your\n"
1148                                  "hardware. I hope you know what you are doing.  Any disruption Wine\n"
1149                                  "has caused to your linux system can be undone with setserial \n"
1150                                  "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1151                                  "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1152                             ioctl(fd, TIOCSSERIAL, &nuts);
1153                             port.c_cflag |= B38400;
1154                         }
1155                         break;
1156 #endif    /* Don't have linux/serial.h or lack TIOCSSERIAL */
1157
1158
1159                         COMM_SetCommError(handle,IE_BAUDRATE);
1160                         release_comm_fd( handle, fd );
1161                         ERR("baudrate %ld\n",lpdcb->BaudRate);
1162                         return FALSE;
1163         }
1164 #elif !defined(__EMX__)
1165         switch (lpdcb->BaudRate) {
1166                 case 0:
1167                         port.c_ospeed = B0;
1168                         break;
1169                 case 50:
1170                         port.c_ospeed = B50;
1171                         break;
1172                 case 75:
1173                         port.c_ospeed = B75;
1174                         break;
1175                 case 110:
1176                 case CBR_110:
1177                         port.c_ospeed = B110;
1178                         break;
1179                 case 134:
1180                         port.c_ospeed = B134;
1181                         break;
1182                 case 150:
1183                         port.c_ospeed = B150;
1184                         break;
1185                 case 200:
1186                         port.c_ospeed = B200;
1187                         break;
1188                 case 300:
1189                 case CBR_300:
1190                         port.c_ospeed = B300;
1191                         break;
1192                 case 600:
1193                 case CBR_600:
1194                         port.c_ospeed = B600;
1195                         break;
1196                 case 1200:
1197                 case CBR_1200:
1198                         port.c_ospeed = B1200;
1199                         break;
1200                 case 1800:
1201                         port.c_ospeed = B1800;
1202                         break;
1203                 case 2400:
1204                 case CBR_2400:
1205                         port.c_ospeed = B2400;
1206                         break;
1207                 case 4800:
1208                 case CBR_4800:
1209                         port.c_ospeed = B4800;
1210                         break;
1211                 case 9600:
1212                 case CBR_9600:
1213                         port.c_ospeed = B9600;
1214                         break;
1215                 case 19200:
1216                 case CBR_19200:
1217                         port.c_ospeed = B19200;
1218                         break;
1219                 case 38400:
1220                 case CBR_38400:
1221                         port.c_ospeed = B38400;
1222                         break;
1223 #ifdef B57600
1224                 case 57600:
1225                 case CBR_57600:
1226                         port.c_cflag |= B57600;
1227                         break;
1228 #endif
1229 #ifdef B115200
1230                 case 115200:
1231                 case CBR_115200:
1232                         port.c_cflag |= B115200;
1233                         break;
1234 #endif
1235 #ifdef B230400
1236                 case 230400:
1237                         port.c_cflag |= B230400;
1238                         break;
1239 #endif
1240 #ifdef B460800
1241                 case 460800:
1242                         port.c_cflag |= B460800;
1243                         break;
1244 #endif
1245                 default:
1246                         COMM_SetCommError(handle,IE_BAUDRATE);
1247                         release_comm_fd( handle, fd );
1248                         ERR("baudrate %ld\n",lpdcb->BaudRate);
1249                         return FALSE;
1250         }
1251         port.c_ispeed = port.c_ospeed;
1252 #endif
1253         bytesize=lpdcb->ByteSize;
1254         stopbits=lpdcb->StopBits;
1255
1256 #ifdef CMSPAR
1257         port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1258 #else
1259         port.c_cflag &= ~(PARENB | PARODD);
1260 #endif
1261         if (lpdcb->fParity)
1262             port.c_iflag |= INPCK;
1263         else
1264             port.c_iflag &= ~INPCK;
1265         switch (lpdcb->Parity) {
1266                 case NOPARITY:
1267                         break;
1268                 case ODDPARITY:
1269                         port.c_cflag |= (PARENB | PARODD);
1270                         break;
1271                 case EVENPARITY:
1272                         port.c_cflag |= PARENB;
1273                         break;
1274 #ifdef CMSPAR
1275                 /* Linux defines mark/space (stick) parity */
1276                 case MARKPARITY:
1277                         port.c_cflag |= (PARENB | CMSPAR);
1278                         break;
1279                 case SPACEPARITY:
1280                         port.c_cflag |= (PARENB | PARODD |  CMSPAR);
1281                         break;
1282 #else
1283                 /* try the POSIX way */
1284                 case MARKPARITY:
1285                         if( stopbits == ONESTOPBIT) {
1286                             stopbits = TWOSTOPBITS;
1287                             port.c_iflag &= ~INPCK;
1288                         } else {
1289                             COMM_SetCommError(handle,IE_BYTESIZE);
1290                             release_comm_fd( handle, fd );
1291                             ERR("Cannot set MARK Parity\n");
1292                             return FALSE;
1293                         }
1294                         break;
1295                 case SPACEPARITY:
1296                         if( bytesize < 8) {
1297                             bytesize +=1;
1298                             port.c_iflag &= ~INPCK;
1299                         } else {
1300                             COMM_SetCommError(handle,IE_BYTESIZE);
1301                             release_comm_fd( handle, fd );
1302                             ERR("Cannot set SPACE Parity\n");
1303                             return FALSE;
1304                         }
1305                         break;
1306 #endif
1307                default:
1308                         COMM_SetCommError(handle,IE_BYTESIZE);
1309                         release_comm_fd( handle, fd );
1310                         ERR("Parity\n");
1311                         return FALSE;
1312         }
1313
1314
1315         port.c_cflag &= ~CSIZE;
1316         switch (bytesize) {
1317                 case 5:
1318                         port.c_cflag |= CS5;
1319                         break;
1320                 case 6:
1321                         port.c_cflag |= CS6;
1322                         break;
1323                 case 7:
1324                         port.c_cflag |= CS7;
1325                         break;
1326                 case 8:
1327                         port.c_cflag |= CS8;
1328                         break;
1329                 default:
1330                         COMM_SetCommError(handle,IE_BYTESIZE);
1331                         release_comm_fd( handle, fd );
1332                         ERR("ByteSize\n");
1333                         return FALSE;
1334         }
1335
1336         switch (stopbits) {
1337                 case ONESTOPBIT:
1338                                 port.c_cflag &= ~CSTOPB;
1339                                 break;
1340                 case ONE5STOPBITS: /* will be selected if bytesize is 5 */
1341                 case TWOSTOPBITS:
1342                                 port.c_cflag |= CSTOPB;
1343                                 break;
1344                 default:
1345                         COMM_SetCommError(handle,IE_BYTESIZE);
1346                         release_comm_fd( handle, fd );
1347                         ERR("StopBits\n");
1348                         return FALSE;
1349         }
1350 #ifdef CRTSCTS
1351         if (    lpdcb->fOutxCtsFlow                     ||
1352                 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1353         )
1354           {
1355             port.c_cflag |= CRTSCTS;
1356             TRACE("CRTSCTS\n");
1357           }
1358 #endif
1359
1360         if (lpdcb->fInX)
1361                 port.c_iflag |= IXON;
1362         else
1363                 port.c_iflag &= ~IXON;
1364         if (lpdcb->fOutX)
1365                 port.c_iflag |= IXOFF;
1366         else
1367                 port.c_iflag &= ~IXOFF;
1368
1369         if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1370                 ERR("tcsetattr error '%s'\n", strerror(errno));
1371                 COMM_SetCommError(handle,CE_IOE);
1372                 ret = FALSE;
1373         } else {
1374                 COMM_SetCommError(handle,0);
1375                 ret = TRUE;
1376         }
1377
1378         /* note: change DTR/RTS lines after setting the comm attributes,
1379          * so flow control does not interfere. */
1380 #ifdef TIOCM_DTR
1381         if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1382         {
1383              WARN("DSR/DTR flow control not supported\n");
1384         } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1385             COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1386         else    
1387             COMM_WhackModem(fd, 0, TIOCM_DTR);
1388 #endif
1389 #ifdef TIOCM_RTS
1390         if(!lpdcb->fOutxCtsFlow )
1391         {
1392             if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1393                 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1394             else    
1395                 COMM_WhackModem(fd, 0, TIOCM_RTS);
1396         }
1397 #endif
1398         if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1399             FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1400         release_comm_fd( handle, fd );
1401         return ret;
1402
1403 }
1404
1405
1406 /*****************************************************************************
1407  *      GetCommState    (KERNEL32.@)
1408  *
1409  *  Fills in a device control block with information from a communications device.
1410  *
1411  * RETURNS
1412  *
1413  *  True on success, false if the communication device handle is bad etc
1414  *
1415  * BUGS
1416  *
1417  *  XonChar and XoffChar are not set.
1418  */
1419 BOOL WINAPI GetCommState(
1420     HANDLE handle, /* [in] The communications device. */
1421     LPDCB  lpdcb)  /* [out] The device control block. */
1422 {
1423      struct termios port;
1424      int fd,speed;
1425      int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1426
1427      TRACE("handle %p, ptr %p\n", handle, lpdcb);
1428
1429      fd = get_comm_fd( handle, FILE_READ_DATA );
1430      if (fd < 0) return FALSE;
1431      if (tcgetattr(fd, &port) == -1) {
1432                 int save_error=errno;
1433                 ERR("tcgetattr error '%s'\n", strerror(save_error));
1434                 COMM_SetCommError(handle,CE_IOE);
1435                 release_comm_fd( handle, fd );
1436                 return FALSE;
1437         }
1438         
1439 #ifdef TIOCMGET
1440      if (ioctl(fd, TIOCMGET, &stat) == -1)
1441      {
1442           int save_error=errno;
1443           WARN("ioctl error '%s'\n", strerror(save_error));
1444           stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1445      }
1446 #endif
1447      release_comm_fd( handle, fd );
1448 #ifndef __EMX__
1449 #ifdef CBAUD
1450      speed= (port.c_cflag & CBAUD);
1451 #else
1452      speed= (cfgetospeed(&port));
1453 #endif
1454      switch (speed) {
1455                 case B0:
1456                         lpdcb->BaudRate = 0;
1457                         break;
1458                 case B50:
1459                         lpdcb->BaudRate = 50;
1460                         break;
1461                 case B75:
1462                         lpdcb->BaudRate = 75;
1463                         break;
1464                 case B110:
1465                         lpdcb->BaudRate = 110;
1466                         break;
1467                 case B134:
1468                         lpdcb->BaudRate = 134;
1469                         break;
1470                 case B150:
1471                         lpdcb->BaudRate = 150;
1472                         break;
1473                 case B200:
1474                         lpdcb->BaudRate = 200;
1475                         break;
1476                 case B300:
1477                         lpdcb->BaudRate = 300;
1478                         break;
1479                 case B600:
1480                         lpdcb->BaudRate = 600;
1481                         break;
1482                 case B1200:
1483                         lpdcb->BaudRate = 1200;
1484                         break;
1485                 case B1800:
1486                         lpdcb->BaudRate = 1800;
1487                         break;
1488                 case B2400:
1489                         lpdcb->BaudRate = 2400;
1490                         break;
1491                 case B4800:
1492                         lpdcb->BaudRate = 4800;
1493                         break;
1494                 case B9600:
1495                         lpdcb->BaudRate = 9600;
1496                         break;
1497                 case B19200:
1498                         lpdcb->BaudRate = 19200;
1499                         break;
1500                 case B38400:
1501                         lpdcb->BaudRate = 38400;
1502                         break;
1503 #ifdef B57600
1504                 case B57600:
1505                         lpdcb->BaudRate = 57600;
1506                         break;
1507 #endif
1508 #ifdef B115200
1509                 case B115200:
1510                         lpdcb->BaudRate = 115200;
1511                         break;
1512 #endif
1513 #ifdef B230400
1514                 case B230400:
1515                         lpdcb->BaudRate = 230400;
1516                         break;
1517 #endif
1518 #ifdef B460800
1519                 case B460800:
1520                         lpdcb->BaudRate = 460800;
1521                         break;
1522 #endif
1523                 default:
1524                         ERR("unknown speed %x\n", speed);
1525         }
1526 #endif
1527         switch (port.c_cflag & CSIZE) {
1528                 case CS5:
1529                         lpdcb->ByteSize = 5;
1530                         break;
1531                 case CS6:
1532                         lpdcb->ByteSize = 6;
1533                         break;
1534                 case CS7:
1535                         lpdcb->ByteSize = 7;
1536                         break;
1537                 case CS8:
1538                         lpdcb->ByteSize = 8;
1539                         break;
1540                 default:
1541                         ERR("unknown size %x\n", port.c_cflag & CSIZE);
1542         }
1543
1544         if(port.c_iflag & INPCK)
1545             lpdcb->fParity = TRUE;
1546         else
1547             lpdcb->fParity = FALSE;
1548 #ifdef CMSPAR
1549         switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1550 #else
1551         switch (port.c_cflag & (PARENB | PARODD))
1552 #endif
1553         {
1554                 case 0:
1555                         lpdcb->Parity = NOPARITY;
1556                         break;
1557                 case PARENB:
1558                         lpdcb->Parity = EVENPARITY;
1559                         break;
1560                 case (PARENB | PARODD):
1561                         lpdcb->Parity = ODDPARITY;
1562                         break;
1563 #ifdef CMSPAR
1564                 case (PARENB | CMSPAR):
1565                         lpdcb->Parity = MARKPARITY;
1566                         break;
1567                 case (PARENB | PARODD | CMSPAR):
1568                         lpdcb->Parity = SPACEPARITY;
1569                         break;
1570 #endif
1571         }
1572
1573         if (port.c_cflag & CSTOPB)
1574             if(lpdcb->ByteSize == 5)
1575                 lpdcb->StopBits = ONE5STOPBITS;
1576             else
1577                 lpdcb->StopBits = TWOSTOPBITS;
1578         else
1579             lpdcb->StopBits = ONESTOPBIT;
1580
1581         lpdcb->fNull = 0;
1582         lpdcb->fBinary = 1;
1583
1584         /* termios does not support DTR/DSR flow control */
1585         lpdcb->fOutxDsrFlow = 0;
1586         lpdcb->fDtrControl =
1587 #ifdef TIOCM_DTR
1588             !(stat & TIOCM_DTR) ?  DTR_CONTROL_DISABLE:
1589 #endif
1590                 DTR_CONTROL_ENABLE  ;
1591
1592 #ifdef CRTSCTS
1593
1594         if (port.c_cflag & CRTSCTS) {
1595                 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1596                 lpdcb->fOutxCtsFlow = 1;
1597         } else
1598 #endif
1599         {
1600                 lpdcb->fRtsControl = 
1601 #ifdef TIOCM_RTS
1602                     !(stat & TIOCM_RTS) ?  RTS_CONTROL_DISABLE :
1603 #endif
1604                     RTS_CONTROL_ENABLE ;
1605                 lpdcb->fOutxCtsFlow = 0;
1606         }
1607         if (port.c_iflag & IXON)
1608                 lpdcb->fInX = 1;
1609         else
1610                 lpdcb->fInX = 0;
1611
1612         if (port.c_iflag & IXOFF)
1613                 lpdcb->fOutX = 1;
1614         else
1615                 lpdcb->fOutX = 0;
1616 /*
1617         lpdcb->XonChar =
1618         lpdcb->XoffChar =
1619  */
1620         lpdcb->XonLim = 10;
1621         lpdcb->XoffLim = 10;
1622
1623         COMM_SetCommError(handle,0);
1624
1625         TRACE("OK\n");
1626
1627         TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1628               lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1629               (lpdcb->StopBits == ONESTOPBIT)?1:
1630               (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1631         TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1632               (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1633          TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1634                  lpdcb->fRtsControl);
1635          TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1636                  lpdcb->fDtrControl);
1637 #ifdef CRTSCTS
1638         if (    lpdcb->fOutxCtsFlow                     ||
1639                 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1640                 )
1641           TRACE("CRTSCTS\n");
1642         else
1643
1644           TRACE("~CRTSCTS\n");
1645 #endif
1646         return TRUE;
1647 }
1648
1649 /*****************************************************************************
1650  *      TransmitCommChar        (KERNEL32.@)
1651  *
1652  *  Transmits a single character in front of any pending characters in the
1653  *  output buffer.  Usually used to send an interrupt character to a host.
1654  *
1655  * PARAMS
1656  *      hComm           [in]    The communication device in need of a command character
1657  *      chTransmit      [in]    The character to transmit
1658  *
1659  * RETURNS
1660  *
1661  *  True if the call succeeded, false if the previous command character to the
1662  *  same device has not been sent yet the handle is bad etc.
1663  *
1664  */
1665 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
1666 {
1667     return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR,
1668                            &chTransmit, sizeof(chTransmit), NULL, 0, NULL, NULL);
1669 }
1670
1671
1672 /*****************************************************************************
1673  *      GetCommTimeouts         (KERNEL32.@)
1674  *
1675  *  Obtains the request timeout values for the communications device.
1676  *
1677  * RETURNS
1678  *
1679  *  True on success, false if communications device handle is bad
1680  *  or the target structure is null.
1681  */
1682 BOOL WINAPI GetCommTimeouts(
1683     HANDLE         hComm,      /* [in] The communications device. */
1684     LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1685 {
1686     BOOL ret;
1687
1688     TRACE("(%p,%p)\n",hComm,lptimeouts);
1689
1690     if(!lptimeouts)
1691     {
1692         SetLastError(ERROR_INVALID_PARAMETER);
1693         return FALSE;
1694     }
1695
1696     SERVER_START_REQ( get_serial_info )
1697     {
1698         req->handle = hComm;
1699         if ((ret = !wine_server_call_err( req )))
1700         {
1701             lptimeouts->ReadIntervalTimeout         = reply->readinterval;
1702             lptimeouts->ReadTotalTimeoutMultiplier  = reply->readmult;
1703             lptimeouts->ReadTotalTimeoutConstant    = reply->readconst;
1704             lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1705             lptimeouts->WriteTotalTimeoutConstant   = reply->writeconst;
1706         }
1707     }
1708     SERVER_END_REQ;
1709     return ret;
1710 }
1711
1712 /*****************************************************************************
1713  *      SetCommTimeouts         (KERNEL32.@)
1714  *
1715  * Sets the timeouts used when reading and writing data to/from COMM ports.
1716  *
1717  * ReadIntervalTimeout
1718  *     - converted and passes to linux kernel as c_cc[VTIME]
1719  * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1720  *     - used in ReadFile to calculate GetOverlappedResult's timeout
1721  * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1722  *     - used in WriteFile to calculate GetOverlappedResult's timeout
1723  *
1724  * RETURNS
1725  *
1726  *  True if the timeouts were set, false otherwise.
1727  */
1728 BOOL WINAPI SetCommTimeouts(
1729     HANDLE hComm,              /* [in] handle of COMM device */
1730     LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1731 {
1732     BOOL ret;
1733     int fd;
1734     struct termios tios;
1735
1736     TRACE("(%p,%p)\n",hComm,lptimeouts);
1737
1738     if(!lptimeouts)
1739     {
1740         SetLastError(ERROR_INVALID_PARAMETER);
1741         return FALSE;
1742     }
1743
1744     SERVER_START_REQ( set_serial_info )
1745     {
1746         req->handle       = hComm;
1747         req->flags        = SERIALINFO_SET_TIMEOUTS;
1748         req->readinterval = lptimeouts->ReadIntervalTimeout ;
1749         req->readmult     = lptimeouts->ReadTotalTimeoutMultiplier ;
1750         req->readconst    = lptimeouts->ReadTotalTimeoutConstant ;
1751         req->writemult    = lptimeouts->WriteTotalTimeoutMultiplier ;
1752         req->writeconst   = lptimeouts->WriteTotalTimeoutConstant ;
1753         ret = !wine_server_call_err( req );
1754     }
1755     SERVER_END_REQ;
1756     if (!ret) return FALSE;
1757
1758     /* FIXME: move this stuff to the server */
1759     fd = get_comm_fd( hComm, FILE_READ_DATA );
1760     if (fd < 0) return FALSE;
1761
1762     if (-1==tcgetattr(fd,&tios)) {
1763         FIXME("tcgetattr on fd %d failed!\n",fd);
1764         release_comm_fd( hComm, fd );
1765         return FALSE;
1766     }
1767
1768     /* VTIME is in 1/10 seconds */
1769         {
1770                 unsigned int ux_timeout;
1771
1772                 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1773                 {
1774                         ux_timeout = 0;
1775                 }
1776                 else
1777                 {
1778                         ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1779                         if(ux_timeout == 0)
1780                         {
1781                                 ux_timeout = 1; /* must be at least some timeout */
1782                         }
1783                 }
1784                 tios.c_cc[VTIME] = ux_timeout;
1785         }
1786
1787     if (-1==tcsetattr(fd,0,&tios)) {
1788         FIXME("tcsetattr on fd %d failed!\n",fd);
1789         release_comm_fd( hComm, fd );
1790         return FALSE;
1791     }
1792     release_comm_fd( hComm, fd );
1793     return TRUE;
1794 }
1795
1796 /***********************************************************************
1797  *           GetCommModemStatus   (KERNEL32.@)
1798  *
1799  *  Obtains the four control register bits if supported by the hardware.
1800  *
1801  * PARAMS
1802  *
1803  *      hFile           [in]    The communications device
1804  *      lpModemStat     [out]   The control register bits
1805  *
1806  * RETURNS
1807  *
1808  *  True if the communications handle was good and for hardware that
1809  *  control register access, false otherwise.
1810  */
1811 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
1812 {
1813     return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
1814                            NULL, 0, lpModemStat, sizeof(DWORD), NULL, NULL);
1815 }
1816
1817 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1818 {
1819     DWORD ret = 0, queue;
1820
1821     TRACE("mask 0x%08lx\n", mask);
1822     TRACE("old->rx          0x%08x vs. new->rx          0x%08x\n", old->rx, new->rx);
1823     TRACE("old->tx          0x%08x vs. new->tx          0x%08x\n", old->tx, new->tx);
1824     TRACE("old->frame       0x%08x vs. new->frame       0x%08x\n", old->frame, new->frame);
1825     TRACE("old->overrun     0x%08x vs. new->overrun     0x%08x\n", old->overrun, new->overrun);
1826     TRACE("old->parity      0x%08x vs. new->parity      0x%08x\n", old->parity, new->parity);
1827     TRACE("old->brk         0x%08x vs. new->brk         0x%08x\n", old->brk, new->brk);
1828     TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x\n", old->buf_overrun, new->buf_overrun);
1829
1830     ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1831     ret |= ((mask & EV_CTS  ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS  :0;
1832     ret |= ((mask & EV_DSR  ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR  :0;
1833     ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1834     ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1835     ret |= ((mask & EV_ERR  ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1836                 || (old->parity != new->parity)) )?EV_ERR  :0;
1837     if (mask & EV_RXCHAR)
1838     {
1839         queue = 0;
1840 #ifdef TIOCINQ
1841         if(ioctl(fd, TIOCINQ, &queue))
1842             WARN("TIOCINQ returned error\n");
1843 #endif
1844         if (queue)
1845             ret |= EV_RXCHAR;
1846     }
1847     if (mask & EV_TXEMPTY)
1848     {
1849         queue = 0;
1850 /* We really want to know when all characters have gone out of the transmitter */
1851 #if defined(TIOCSERGETLSR) 
1852         if(ioctl(fd, TIOCSERGETLSR, &queue))
1853             WARN("TIOCSERGETLSR returned error\n");
1854         if (queue)
1855 /* TIOCINQ only checks for an empty buffer */
1856 #elif defined(TIOCINQ)
1857         if(ioctl(fd, TIOCOUTQ, &queue))
1858             WARN("TIOCOUTQ returned error\n");
1859         if (!queue)
1860 #endif
1861            ret |= EV_TXEMPTY;
1862     }
1863     TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1864     return ret;
1865     
1866 }
1867
1868 /***********************************************************************
1869  *             COMM_WaitCommEventService      (INTERNAL)
1870  *
1871  *  We need to poll for what is interesting
1872  *  TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1873  *
1874  */
1875 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1876 {
1877     async_commio *commio = (async_commio*) arg;
1878     int waitmask = 0;
1879     int rc, fd, abort;
1880     serial_irq_info new_irq_info;
1881     DWORD new_mstat, new_evtmask;
1882
1883     fd=get_comm_fd( commio->handle, FILE_READ_DATA );
1884
1885     TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n", 
1886           commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1887     do
1888     {
1889         /*
1890          * TIOCMIWAIT is not adequate
1891          *
1892          * FIXME:
1893          * We don't handle the EV_RXFLAG (the eventchar)
1894          */
1895         Sleep(1);
1896         rc= COMM_GetEInfo(fd,&new_irq_info);
1897         if (rc)
1898             TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1899         rc = GetCommModemStatus(commio->handle, &new_mstat);
1900         if (!rc)
1901             TRACE("GetCommModemStatus failed\n");
1902         rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
1903         GetCommMask(commio->handle, &new_evtmask);
1904         abort = (commio->evtmask != new_evtmask);
1905         TRACE("resulting Eventmask 0x%08x\n", rc);
1906     } while (!rc && ! abort);
1907     if (abort) rc = 0;
1908     release_comm_fd( commio->handle, fd );
1909     *commio->buffer = rc;
1910     if (commio->hEvent != INVALID_HANDLE_VALUE )
1911         NtSetEvent( commio->hEvent, NULL );
1912     HeapFree(GetProcessHeap(), 0, commio );
1913     return 0;
1914 }
1915
1916
1917 /***********************************************************************
1918  *             COMM_WaitCommEvent         (INTERNAL)
1919  *
1920  *  This function must have an lpOverlapped.
1921  */
1922 static BOOL COMM_WaitCommEvent(
1923     HANDLE hFile,              /* [in] handle of comm port to wait for */
1924     LPDWORD lpdwEvents,        /* [out] event(s) that were detected */
1925     LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1926 {
1927     int                 fd;
1928     async_commio*       commio;
1929     DWORD               result_mask;
1930     BOOL res;
1931
1932     if (!lpOverlapped)
1933     {
1934         SetLastError(ERROR_INVALID_PARAMETER);
1935         return FALSE;
1936     }
1937
1938     if (NtResetEvent(lpOverlapped->hEvent,NULL))
1939         return FALSE;
1940
1941     fd = get_comm_fd( hFile, FILE_WRITE_DATA );
1942     if (fd < 0) return FALSE;
1943
1944     commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1945     if (!commio)
1946     {
1947         release_comm_fd( hFile, fd );
1948         return FALSE;
1949     }
1950
1951     commio->handle = hFile;
1952     commio->buffer = (char *)lpdwEvents;
1953     commio->hEvent = lpOverlapped->hEvent;
1954     GetCommMask(hFile, &commio->evtmask);
1955
1956 /* We may never return, if some capabilities miss
1957  * Return error in that case
1958  */
1959 #if !defined(TIOCINQ)
1960     if(commio->evtmask & EV_RXCHAR)
1961         goto error;
1962 #endif
1963 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
1964     if(commio->evtmask & EV_TXEMPTY)
1965         goto error;
1966 #endif
1967 #if !defined(TIOCMGET)
1968     if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
1969         goto error;
1970 #endif
1971 #if !defined(TIOCM_CTS)
1972     if(commio->evtmask & EV_CTS)
1973         goto error;
1974 #endif
1975 #if !defined(TIOCM_DSR)
1976     if(commio->evtmask & EV_DSR)
1977         goto error;
1978 #endif
1979 #if !defined(TIOCM_RNG)
1980     if(commio->evtmask & EV_RING)
1981         goto error;
1982 #endif
1983 #if !defined(TIOCM_CAR)
1984     if(commio->evtmask & EV_RLSD)
1985         goto error;
1986 #endif
1987     if(commio->evtmask & EV_RXFLAG)
1988         FIXME("EV_RXFLAG not handled\n");
1989     COMM_GetEInfo(fd,&commio->irq_info);
1990     GetCommModemStatus(hFile, &commio->mstat);
1991     /* We might have received something or the TX bufffer is delivered*/
1992     result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
1993     if (result_mask) 
1994     {
1995         TRACE("Event already met\n");
1996         *lpdwEvents = result_mask;
1997         HeapFree(GetProcessHeap(), 0, commio );
1998         res = TRUE;
1999     }
2000     else
2001     {
2002         CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
2003         SetLastError(ERROR_IO_PENDING);
2004         res = FALSE;
2005     }
2006     release_comm_fd( hFile, fd );
2007     return res;
2008 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
2009  error:
2010     FIXME("Returning error because of missing capabilities\n");
2011     release_comm_fd( hFile, fd );
2012     HeapFree(GetProcessHeap(), 0, commio );
2013     SetLastError(ERROR_INVALID_PARAMETER);
2014     return FALSE;
2015 #endif
2016 }
2017 /***********************************************************************
2018  *           WaitCommEvent   (KERNEL32.@)
2019  *
2020  * Wait until something interesting happens on a COMM port.
2021  * Interesting things (events) are set by calling SetCommMask before
2022  * this function is called.
2023  *
2024  * RETURNS
2025  *   TRUE if successful
2026  *   FALSE if failure
2027  *
2028  *   The set of detected events will be written to *lpdwEventMask
2029  *   ERROR_IO_PENDING will be returned the overlapped structure was passed
2030  *
2031  * BUGS:
2032  *  Only supports EV_RXCHAR and EV_TXEMPTY
2033  */
2034 BOOL WINAPI WaitCommEvent(
2035     HANDLE hFile,              /* [in] handle of comm port to wait for */
2036     LPDWORD lpdwEvents,        /* [out] event(s) that were detected */
2037     LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2038 {
2039     OVERLAPPED ov;
2040     int ret = 0;
2041     DWORD res, err;
2042
2043     TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2044
2045     if(lpOverlapped)
2046         return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2047
2048     /* if there is no overlapped structure, create our own */
2049     ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
2050
2051     res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2052     err = GetLastError();
2053     if (!res)
2054     {
2055         if (err == ERROR_IO_PENDING)
2056         {
2057             do 
2058             {
2059                 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
2060             } while (res != WAIT_OBJECT_0);
2061             TRACE("Event met\n:");
2062             ret = TRUE;
2063         }
2064         else
2065         {
2066             FIXME("Unknown error 0x%08lx\n", err);
2067             ret = FALSE;
2068         }
2069     }
2070     else
2071         ret = TRUE;
2072     CloseHandle(ov.hEvent);
2073
2074     return ret;
2075 }
2076
2077 /***********************************************************************
2078  *           GetCommProperties   (KERNEL32.@)
2079  *
2080  * This function fills in a structure with the capabilities of the
2081  * communications port driver.
2082  *
2083  * RETURNS
2084  *
2085  *  TRUE on success, FALSE on failure
2086  *  If successful, the lpCommProp structure be filled in with
2087  *  properties of the comm port.
2088  */
2089 BOOL WINAPI GetCommProperties(
2090     HANDLE hFile,          /* [in] handle of the comm port */
2091     LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2092 {
2093     FIXME("(%p %p )\n",hFile,lpCommProp);
2094     if(!lpCommProp)
2095         return FALSE;
2096
2097     /*
2098      * These values should be valid for LINUX's serial driver
2099      * FIXME: Perhaps they deserve an #ifdef LINUX
2100      */
2101     memset(lpCommProp,0,sizeof(COMMPROP));
2102     lpCommProp->wPacketLength       = 1;
2103     lpCommProp->wPacketVersion      = 1;
2104     lpCommProp->dwServiceMask       = SP_SERIALCOMM;
2105     lpCommProp->dwReserved1         = 0;
2106     lpCommProp->dwMaxTxQueue        = 4096;
2107     lpCommProp->dwMaxRxQueue        = 4096;
2108     lpCommProp->dwMaxBaud           = BAUD_115200;
2109     lpCommProp->dwProvSubType       = PST_RS232;
2110     lpCommProp->dwProvCapabilities  = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2111     lpCommProp->dwSettableParams    = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2112                                       SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2113     lpCommProp->dwSettableBaud      = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2114                 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2115                 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2116     lpCommProp->wSettableData       = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2117     lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2118                 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2119     lpCommProp->dwCurrentTxQueue    = lpCommProp->dwMaxTxQueue;
2120     lpCommProp->dwCurrentRxQueue    = lpCommProp->dwMaxRxQueue;
2121
2122     return TRUE;
2123 }
2124
2125 /***********************************************************************
2126  * FIXME:
2127  * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2128  * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2129  * This is dependent on the type of COMM port, but since it is doubtful
2130  * anybody will get around to implementing support for fancy serial
2131  * ports in WINE, this is hardcoded for the time being.  The name of
2132  * this DLL should be stored in and read from the system registry in
2133  * the hive HKEY_LOCAL_MACHINE, key
2134  * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2135  * where ???? is the port number... that is determined by PNP
2136  * The DLL should be loaded when the COMM port is opened, and closed
2137  * when the COMM port is closed. - MJM 20 June 2000
2138  ***********************************************************************/
2139 static const WCHAR lpszSerialUI[] = { 
2140    's','e','r','i','a','l','u','i','.','d','l','l',0 };
2141
2142
2143 /***********************************************************************
2144  *           CommConfigDialogA   (KERNEL32.@)
2145  *
2146  * Raises a dialog that allows the user to configure a comm port.
2147  * Fills the COMMCONFIG struct with information specified by the user.
2148  * This function should call a similar routine in the COMM driver...
2149  *
2150  * RETURNS
2151  *
2152  *  TRUE on success, FALSE on failure
2153  *  If successful, the lpCommConfig structure will contain a new
2154  *  configuration for the comm port, as specified by the user.
2155  *
2156  * BUGS
2157  *  The library with the CommConfigDialog code is never unloaded.
2158  * Perhaps this should be done when the comm port is closed?
2159  */
2160 BOOL WINAPI CommConfigDialogA(
2161     LPCSTR lpszDevice,         /* [in] name of communications device */
2162     HWND hWnd,                 /* [in] parent window for the dialog */
2163     LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2164 {
2165     FARPROC lpfnCommDialog;
2166     HMODULE hConfigModule;
2167     BOOL r = FALSE;
2168
2169     TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2170
2171     hConfigModule = LoadLibraryW(lpszSerialUI);
2172     if(!hConfigModule)
2173         return FALSE;
2174
2175     lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2176
2177     if(lpfnCommDialog)
2178         r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2179
2180     FreeLibrary(hConfigModule);
2181
2182     return r;
2183 }
2184
2185 /***********************************************************************
2186  *           CommConfigDialogW   (KERNEL32.@)
2187  *
2188  * See CommConfigDialogA.
2189  */
2190 BOOL WINAPI CommConfigDialogW(
2191     LPCWSTR lpszDevice,        /* [in] name of communications device */
2192     HWND hWnd,                 /* [in] parent window for the dialog */
2193     LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2194 {
2195     FARPROC lpfnCommDialog;
2196     HMODULE hConfigModule;
2197     BOOL r = FALSE;
2198
2199     TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2200
2201     hConfigModule = LoadLibraryW(lpszSerialUI);
2202     if(!hConfigModule)
2203         return FALSE;
2204
2205     lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2206
2207     if(lpfnCommDialog)
2208         r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2209
2210     FreeLibrary(hConfigModule);
2211
2212     return r;
2213 }
2214
2215 /***********************************************************************
2216  *           GetCommConfig     (KERNEL32.@)
2217  *
2218  * Fill in the COMMCONFIG structure for the comm port hFile
2219  *
2220  * RETURNS
2221  *
2222  *  TRUE on success, FALSE on failure
2223  *  If successful, lpCommConfig contains the comm port configuration.
2224  *
2225  * BUGS
2226  *
2227  */
2228 BOOL WINAPI GetCommConfig(
2229     HANDLE       hFile,        /* [in] The communications device. */
2230     LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2231     LPDWORD      lpdwSize)     /* [in/out] Initially the size of the configuration buffer/structure,
2232                                   afterwards the number of bytes copied to the buffer or
2233                                   the needed size of the buffer. */
2234 {
2235     BOOL r;
2236
2237     TRACE("(%p %p)\n",hFile,lpCommConfig);
2238
2239     if(lpCommConfig == NULL)
2240         return FALSE;
2241     r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2242     *lpdwSize = sizeof(COMMCONFIG);
2243     if(r)
2244         return FALSE;
2245
2246     lpCommConfig->dwSize = sizeof(COMMCONFIG);
2247     lpCommConfig->wVersion = 1;
2248     lpCommConfig->wReserved = 0;
2249     r = GetCommState(hFile,&lpCommConfig->dcb);
2250     lpCommConfig->dwProviderSubType = PST_RS232;
2251     lpCommConfig->dwProviderOffset = 0;
2252     lpCommConfig->dwProviderSize = 0;
2253
2254     return r;
2255 }
2256
2257 /***********************************************************************
2258  *           SetCommConfig     (KERNEL32.@)
2259  *
2260  *  Sets the configuration of the communications device.
2261  *
2262  * RETURNS
2263  *
2264  *  True on success, false if the handle was bad is not a communications device.
2265  */
2266 BOOL WINAPI SetCommConfig(
2267     HANDLE       hFile,         /* [in] The communications device. */
2268     LPCOMMCONFIG lpCommConfig,  /* [in] The desired configuration. */
2269     DWORD dwSize)               /* [in] size of the lpCommConfig struct */
2270 {
2271     TRACE("(%p %p)\n",hFile,lpCommConfig);
2272     return SetCommState(hFile,&lpCommConfig->dcb);
2273 }
2274
2275 /***********************************************************************
2276  *           SetDefaultCommConfigA   (KERNEL32.@)
2277  *
2278  *  Initializes the default configuration for the specified communication
2279  *  device. (ascii)
2280  *
2281  * RETURNS
2282  *
2283  *  True if the device was found and the defaults set, false otherwise
2284  */
2285 BOOL WINAPI SetDefaultCommConfigW(
2286     LPCWSTR       lpszDevice,  /* [in] The ascii name of the device targeted for configuration. */
2287     LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2288     DWORD        dwSize)       /* [in] The number of bytes in the configuration structure. */
2289 {
2290     FARPROC lpfnSetDefaultCommConfig;
2291     HMODULE hConfigModule;
2292     BOOL r = FALSE;
2293
2294     TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2295
2296     hConfigModule = LoadLibraryW(lpszSerialUI);
2297     if(!hConfigModule)
2298         return r;
2299
2300     lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2301     if (lpfnSetDefaultCommConfig)
2302         r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2303
2304     FreeLibrary(hConfigModule);
2305
2306     return r;
2307 }
2308
2309
2310 /***********************************************************************
2311  *           SetDefaultCommConfigW     (KERNEL32.@)
2312  *
2313  *  Initializes the default configuration for the specified
2314  *  communication device. (unicode)
2315  *
2316  * RETURNS
2317  *
2318  */
2319 BOOL WINAPI SetDefaultCommConfigA(
2320     LPCSTR      lpszDevice,    /* [in] The unicode name of the device targeted for configuration. */
2321     LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2322     DWORD        dwSize)       /* [in] The number of bytes in the configuration structure. */
2323 {
2324     BOOL r;
2325     LPWSTR lpDeviceW = NULL;
2326     DWORD len;
2327
2328     TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2329
2330     if (lpszDevice)
2331     {
2332         len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2333         lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2334         MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2335     }
2336     r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2337     HeapFree( GetProcessHeap(), 0, lpDeviceW );
2338     return r;
2339 }
2340
2341
2342 /***********************************************************************
2343  *           GetDefaultCommConfigW   (KERNEL32.@)
2344  *
2345  *   Acquires the default configuration of the specified communication device. (unicode)
2346  *
2347  *  RETURNS
2348  *
2349  *   True on successful reading of the default configuration,
2350  *   if the device is not found or the buffer is too small.
2351  */
2352 BOOL WINAPI GetDefaultCommConfigW(
2353     LPCWSTR      lpszName, /* [in] The unicode name of the device targeted for configuration. */
2354     LPCOMMCONFIG lpCC,     /* [out] The default configuration for the device. */
2355     LPDWORD      lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2356                               afterwards the number of bytes copied to the buffer or
2357                               the needed size of the buffer. */
2358 {
2359      LPDCB lpdcb = &(lpCC->dcb);
2360      WCHAR temp[40];
2361      static const WCHAR comW[] = {'C','O','M',0};
2362      static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2363
2364      if (strncmpiW(lpszName,comW,3)) {
2365         ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2366         return FALSE;
2367      }
2368
2369      TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2370      if (*lpdwSize < sizeof(COMMCONFIG)) {
2371          *lpdwSize = sizeof(COMMCONFIG);
2372          return FALSE;
2373        }
2374
2375      *lpdwSize = sizeof(COMMCONFIG);
2376
2377      lpCC->dwSize = sizeof(COMMCONFIG);
2378      lpCC->wVersion = 1;
2379      lpCC->dwProviderSubType = PST_RS232;
2380      lpCC->dwProviderOffset = 0L;
2381      lpCC->dwProviderSize = 0L;
2382
2383      sprintfW( temp, formatW, lpszName[3]);
2384      FIXME("setting %s as default\n", debugstr_w(temp));
2385
2386      return BuildCommDCBW( temp, lpdcb);
2387 }
2388
2389 /**************************************************************************
2390  *         GetDefaultCommConfigA                (KERNEL32.@)
2391  *
2392  *   Acquires the default configuration of the specified communication device. (ascii)
2393  *
2394  *  RETURNS
2395  *
2396  *   True on successful reading of the default configuration,
2397  *   if the device is not found or the buffer is too small.
2398  */
2399 BOOL WINAPI GetDefaultCommConfigA(
2400     LPCSTR       lpszName, /* [in] The ascii name of the device targeted for configuration. */
2401     LPCOMMCONFIG lpCC,     /* [out] The default configuration for the device. */
2402     LPDWORD      lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2403                               afterwards the number of bytes copied to the buffer or
2404                               the needed size of the buffer. */
2405 {
2406         BOOL ret = FALSE;
2407         UNICODE_STRING lpszNameW;
2408
2409         TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2410         if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2411         else lpszNameW.Buffer = NULL;
2412
2413         if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2414
2415         RtlFreeUnicodeString(&lpszNameW);
2416         return ret;
2417 }