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