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