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