Don't fail in CoRegisterClassObject if the class already exists and
[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|IMAXBEL);
1105 #else
1106         port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
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 #ifdef TIOCMGET
1496              || ioctl(fd, TIOCMGET, &stat) == -1
1497 #endif
1498              ) {
1499                 int save_error=errno;
1500                 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
1501                 COMM_SetCommError(handle,CE_IOE);
1502                 release_comm_fd( handle, fd );
1503                 return FALSE;
1504         }
1505      release_comm_fd( handle, fd );
1506 #ifndef __EMX__
1507 #ifdef CBAUD
1508      speed= (port.c_cflag & CBAUD);
1509 #else
1510      speed= (cfgetospeed(&port));
1511 #endif
1512      switch (speed) {
1513                 case B0:
1514                         lpdcb->BaudRate = 0;
1515                         break;
1516                 case B50:
1517                         lpdcb->BaudRate = 50;
1518                         break;
1519                 case B75:
1520                         lpdcb->BaudRate = 75;
1521                         break;
1522                 case B110:
1523                         lpdcb->BaudRate = 110;
1524                         break;
1525                 case B134:
1526                         lpdcb->BaudRate = 134;
1527                         break;
1528                 case B150:
1529                         lpdcb->BaudRate = 150;
1530                         break;
1531                 case B200:
1532                         lpdcb->BaudRate = 200;
1533                         break;
1534                 case B300:
1535                         lpdcb->BaudRate = 300;
1536                         break;
1537                 case B600:
1538                         lpdcb->BaudRate = 600;
1539                         break;
1540                 case B1200:
1541                         lpdcb->BaudRate = 1200;
1542                         break;
1543                 case B1800:
1544                         lpdcb->BaudRate = 1800;
1545                         break;
1546                 case B2400:
1547                         lpdcb->BaudRate = 2400;
1548                         break;
1549                 case B4800:
1550                         lpdcb->BaudRate = 4800;
1551                         break;
1552                 case B9600:
1553                         lpdcb->BaudRate = 9600;
1554                         break;
1555                 case B19200:
1556                         lpdcb->BaudRate = 19200;
1557                         break;
1558                 case B38400:
1559                         lpdcb->BaudRate = 38400;
1560                         break;
1561 #ifdef B57600
1562                 case B57600:
1563                         lpdcb->BaudRate = 57600;
1564                         break;
1565 #endif
1566 #ifdef B115200
1567                 case B115200:
1568                         lpdcb->BaudRate = 115200;
1569                         break;
1570 #endif
1571 #ifdef B230400
1572                 case B230400:
1573                         lpdcb->BaudRate = 230400;
1574                         break;
1575 #endif
1576 #ifdef B460800
1577                 case B460800:
1578                         lpdcb->BaudRate = 460800;
1579                         break;
1580 #endif
1581                 default:
1582                         ERR("unknown speed %x \n",speed);
1583         }
1584 #endif
1585         switch (port.c_cflag & CSIZE) {
1586                 case CS5:
1587                         lpdcb->ByteSize = 5;
1588                         break;
1589                 case CS6:
1590                         lpdcb->ByteSize = 6;
1591                         break;
1592                 case CS7:
1593                         lpdcb->ByteSize = 7;
1594                         break;
1595                 case CS8:
1596                         lpdcb->ByteSize = 8;
1597                         break;
1598                 default:
1599                         ERR("unknown size %x \n",port.c_cflag & CSIZE);
1600         }
1601
1602         if(port.c_iflag & INPCK)
1603             lpdcb->fParity = TRUE;
1604         else
1605             lpdcb->fParity = FALSE;
1606 #ifdef CMSPAR
1607         switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1608 #else
1609         switch (port.c_cflag & (PARENB | PARODD))
1610 #endif
1611         {
1612                 case 0:
1613                         lpdcb->Parity = NOPARITY;
1614                         break;
1615                 case PARENB:
1616                         lpdcb->Parity = EVENPARITY;
1617                         break;
1618                 case (PARENB | PARODD):
1619                         lpdcb->Parity = ODDPARITY;
1620                         break;
1621 #ifdef CMSPAR
1622                 case (PARENB | CMSPAR):
1623                         lpdcb->Parity = MARKPARITY;
1624                         break;
1625                 case (PARENB | PARODD | CMSPAR):
1626                         lpdcb->Parity = SPACEPARITY;
1627                         break;
1628 #endif
1629         }
1630
1631         if (port.c_cflag & CSTOPB)
1632             if(lpdcb->ByteSize == 5)
1633                 lpdcb->StopBits = ONE5STOPBITS;
1634             else
1635                 lpdcb->StopBits = TWOSTOPBITS;
1636         else
1637             lpdcb->StopBits = ONESTOPBIT;
1638
1639         lpdcb->fNull = 0;
1640         lpdcb->fBinary = 1;
1641
1642         /* termios does not support DTR/DSR flow control */
1643         lpdcb->fOutxDsrFlow = 0;
1644         lpdcb->fDtrControl =
1645 #ifdef TIOCM_DTR
1646             !(stat & TIOCM_DTR) ?  DTR_CONTROL_DISABLE:
1647 #endif
1648                 DTR_CONTROL_ENABLE  ;
1649
1650 #ifdef CRTSCTS
1651
1652         if (port.c_cflag & CRTSCTS) {
1653                 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1654                 lpdcb->fOutxCtsFlow = 1;
1655         } else
1656 #endif
1657         {
1658                 lpdcb->fRtsControl = 
1659 #ifdef TIOCM_RTS
1660                     !(stat & TIOCM_RTS) ?  RTS_CONTROL_DISABLE :
1661 #endif
1662                     RTS_CONTROL_ENABLE ;
1663                 lpdcb->fOutxCtsFlow = 0;
1664         }
1665         if (port.c_iflag & IXON)
1666                 lpdcb->fInX = 1;
1667         else
1668                 lpdcb->fInX = 0;
1669
1670         if (port.c_iflag & IXOFF)
1671                 lpdcb->fOutX = 1;
1672         else
1673                 lpdcb->fOutX = 0;
1674 /*
1675         lpdcb->XonChar =
1676         lpdcb->XoffChar =
1677  */
1678         lpdcb->XonLim = 10;
1679         lpdcb->XoffLim = 10;
1680
1681         COMM_SetCommError(handle,0);
1682
1683         TRACE("OK\n");
1684
1685         TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1686               lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1687               (lpdcb->StopBits == ONESTOPBIT)?1:
1688               (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1689         TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1690               (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1691          TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1692                  lpdcb->fRtsControl);
1693          TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1694                  lpdcb->fDtrControl);
1695 #ifdef CRTSCTS
1696         if (    lpdcb->fOutxCtsFlow                     ||
1697                 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1698                 )
1699           TRACE("CRTSCTS\n");
1700         else
1701
1702           TRACE("~CRTSCTS\n");
1703 #endif
1704         return TRUE;
1705 }
1706
1707 /*****************************************************************************
1708  *      TransmitCommChar        (KERNEL32.@)
1709  *
1710  *  Transmits a single character in front of any pending characters in the
1711  *  output buffer.  Usually used to send an interrupt character to a host.
1712  *
1713  * RETURNS
1714  *
1715  *  True if the call succeeded, false if the previous command character to the
1716  *  same device has not been sent yet the handle is bad etc.
1717  *
1718  * BUGS
1719  *
1720  *  Stub.
1721  */
1722 BOOL WINAPI TransmitCommChar(
1723     HANDLE hComm,      /* [in] The communication device in need of a command character. */
1724     CHAR   chTransmit) /* [in] The character to transmit. */
1725 {
1726     DWORD w;
1727     WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1728
1729     return WriteFile( hComm, &chTransmit, 1, &w, NULL );
1730 }
1731
1732
1733 /*****************************************************************************
1734  *      GetCommTimeouts         (KERNEL32.@)
1735  *
1736  *  Obtains the request timeout values for the communications device.
1737  *
1738  * RETURNS
1739  *
1740  *  True on success, false if communications device handle is bad
1741  *  or the target structure is null.
1742  */
1743 BOOL WINAPI GetCommTimeouts(
1744     HANDLE         hComm,      /* [in] The communications device. */
1745     LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1746 {
1747     BOOL ret;
1748
1749     TRACE("(%p,%p)\n",hComm,lptimeouts);
1750
1751     if(!lptimeouts)
1752     {
1753         SetLastError(ERROR_INVALID_PARAMETER);
1754         return FALSE;
1755     }
1756
1757     SERVER_START_REQ( get_serial_info )
1758     {
1759         req->handle = hComm;
1760         if ((ret = !wine_server_call_err( req )))
1761         {
1762             lptimeouts->ReadIntervalTimeout         = reply->readinterval;
1763             lptimeouts->ReadTotalTimeoutMultiplier  = reply->readmult;
1764             lptimeouts->ReadTotalTimeoutConstant    = reply->readconst;
1765             lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1766             lptimeouts->WriteTotalTimeoutConstant   = reply->writeconst;
1767         }
1768     }
1769     SERVER_END_REQ;
1770     return ret;
1771 }
1772
1773 /*****************************************************************************
1774  *      SetCommTimeouts         (KERNEL32.@)
1775  *
1776  * Sets the timeouts used when reading and writing data to/from COMM ports.
1777  *
1778  * ReadIntervalTimeout
1779  *     - converted and passes to linux kernel as c_cc[VTIME]
1780  * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1781  *     - used in ReadFile to calculate GetOverlappedResult's timeout
1782  * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1783  *     - used in WriteFile to calculate GetOverlappedResult's timeout
1784  *
1785  * RETURNS
1786  *
1787  *  True if the timeouts were set, false otherwise.
1788  */
1789 BOOL WINAPI SetCommTimeouts(
1790     HANDLE hComm,              /* [in] handle of COMM device */
1791     LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1792 {
1793     BOOL ret;
1794     int fd;
1795     struct termios tios;
1796
1797     TRACE("(%p,%p)\n",hComm,lptimeouts);
1798
1799     if(!lptimeouts)
1800     {
1801         SetLastError(ERROR_INVALID_PARAMETER);
1802         return FALSE;
1803     }
1804
1805     SERVER_START_REQ( set_serial_info )
1806     {
1807         req->handle       = hComm;
1808         req->flags        = SERIALINFO_SET_TIMEOUTS;
1809         req->readinterval = lptimeouts->ReadIntervalTimeout ;
1810         req->readmult     = lptimeouts->ReadTotalTimeoutMultiplier ;
1811         req->readconst    = lptimeouts->ReadTotalTimeoutConstant ;
1812         req->writemult    = lptimeouts->WriteTotalTimeoutMultiplier ;
1813         req->writeconst   = lptimeouts->WriteTotalTimeoutConstant ;
1814         ret = !wine_server_call_err( req );
1815     }
1816     SERVER_END_REQ;
1817     if (!ret) return FALSE;
1818
1819     /* FIXME: move this stuff to the server */
1820     fd = get_comm_fd( hComm, GENERIC_READ );
1821     if (fd < 0) return FALSE;
1822
1823     if (-1==tcgetattr(fd,&tios)) {
1824         FIXME("tcgetattr on fd %d failed!\n",fd);
1825         release_comm_fd( hComm, fd );
1826         return FALSE;
1827     }
1828
1829     /* VTIME is in 1/10 seconds */
1830         {
1831                 unsigned int ux_timeout;
1832
1833                 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1834                 {
1835                         ux_timeout = 0;
1836                 }
1837                 else
1838                 {
1839                         ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1840                         if(ux_timeout == 0)
1841                         {
1842                                 ux_timeout = 1; /* must be at least some timeout */
1843                         }
1844                 }
1845                 tios.c_cc[VTIME] = ux_timeout;
1846         }
1847
1848     if (-1==tcsetattr(fd,0,&tios)) {
1849         FIXME("tcsetattr on fd %d failed!\n",fd);
1850         release_comm_fd( hComm, fd );
1851         return FALSE;
1852     }
1853     release_comm_fd( hComm, fd );
1854     return TRUE;
1855 }
1856
1857 /***********************************************************************
1858  *           GetCommModemStatus   (KERNEL32.@)
1859  *
1860  *  Obtains the four control register bits if supported by the hardware.
1861  *
1862  * RETURNS
1863  *
1864  *  True if the communications handle was good and for hardware that
1865  *  control register access, false otherwise.
1866  */
1867 BOOL WINAPI GetCommModemStatus(
1868     HANDLE  hFile,       /* [in] The communications device. */
1869     LPDWORD lpModemStat) /* [out] The control register bits. */
1870 {
1871         int fd,mstat, result=FALSE;
1872
1873         *lpModemStat=0;
1874 #ifdef TIOCMGET
1875         fd = get_comm_fd( hFile, GENERIC_READ );
1876         if(fd<0)
1877                 return FALSE;
1878         result = ioctl(fd, TIOCMGET, &mstat);
1879         release_comm_fd( hFile, fd );
1880         if (result == -1)
1881           {
1882             WARN("ioctl failed\n");
1883             return FALSE;
1884           }
1885 #ifdef TIOCM_CTS
1886         if (mstat & TIOCM_CTS)
1887             *lpModemStat |= MS_CTS_ON;
1888 #endif
1889 #ifdef TIOCM_DSR
1890         if (mstat & TIOCM_DSR)
1891           *lpModemStat |= MS_DSR_ON;
1892 #endif
1893 #ifdef TIOCM_RNG
1894         if (mstat & TIOCM_RNG)
1895           *lpModemStat |= MS_RING_ON;
1896 #endif
1897 #ifdef TIOCM_CAR
1898         /*FIXME:  Not really sure about RLSD  UB 990810*/
1899         if (mstat & TIOCM_CAR)
1900           *lpModemStat |= MS_RLSD_ON;
1901 #endif
1902         TRACE("%04x -> %s%s%s%s\n", mstat,
1903               (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1904               (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1905               (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1906               (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1907         return TRUE;
1908 #else
1909         return FALSE;
1910 #endif
1911 }
1912
1913 static DWORD WINAPI Comm_CheckEvents(int fd, DWORD mask, serial_irq_info *new, serial_irq_info *old, DWORD new_mstat, DWORD old_mstat)
1914 {
1915     DWORD ret = 0, queue;
1916
1917     TRACE("mask 0x%08lx\n", mask);
1918     TRACE("old->rx          0x%08x vs. new->rx          0x%08x \n", old->rx, new->rx);
1919     TRACE("old->tx          0x%08x vs. new->tx          0x%08x \n", old->tx, new->tx);
1920     TRACE("old->frame       0x%08x vs. new->frame       0x%08x \n", old->frame, new->frame);
1921     TRACE("old->overrun     0x%08x vs. new->overrun     0x%08x \n", old->overrun, new->overrun);
1922     TRACE("old->parity      0x%08x vs. new->parity      0x%08x \n", old->parity, new->parity);
1923     TRACE("old->brk         0x%08x vs. new->brk         0x%08x \n", old->brk, new->brk);
1924     TRACE("old->buf_overrun 0x%08x vs. new->buf_overrun 0x%08x \n", old->buf_overrun, new->buf_overrun);
1925
1926     ret |= ((mask & EV_BREAK) && ( old->brk != new->brk))?EV_BREAK:0;
1927     ret |= ((mask & EV_CTS  ) && ((old_mstat&MS_CTS_ON )!=(new_mstat&MS_CTS_ON )))?EV_CTS  :0;
1928     ret |= ((mask & EV_DSR  ) && ((old_mstat&MS_DSR_ON )!=(new_mstat&MS_DSR_ON )))?EV_DSR  :0;
1929     ret |= ((mask & EV_RING ) && ((old_mstat&MS_RING_ON)!=(new_mstat&MS_RING_ON)))?EV_RING :0;
1930     ret |= ((mask & EV_RLSD ) && ((old_mstat&MS_RLSD_ON)!=(new_mstat&MS_RLSD_ON)))?EV_RLSD :0;
1931     ret |= ((mask & EV_ERR  ) && (( old->frame != new->frame) ||(old->overrun != new->overrun)
1932                 || (old->parity != new->parity)) )?EV_ERR  :0;
1933     if (mask & EV_RXCHAR)
1934     {
1935         queue = 0;
1936 #ifdef TIOCINQ
1937         if(ioctl(fd, TIOCINQ, &queue))
1938             WARN("TIOCINQ returned error\n");
1939 #endif
1940         if (queue)
1941             ret |= EV_RXCHAR;
1942     }
1943     if (mask & EV_TXEMPTY)
1944     {
1945         queue = 0;
1946 /* We really want to know when all characters have gone out of the transmitter */
1947 #if defined(TIOCSERGETLSR) 
1948         if(ioctl(fd, TIOCSERGETLSR, &queue))
1949             WARN("TIOCSERGETLSR returned error\n");
1950         if (queue)
1951 /* TIOCINQ only checks for an empty buffer */
1952 #elif defined(TIOCINQ)
1953         if(ioctl(fd, TIOCOUTQ, &queue))
1954             WARN("TIOCOUTQ returned error\n");
1955         if (!queue)
1956 #endif
1957            ret |= EV_TXEMPTY;
1958     }
1959     TRACE("OUTQUEUE %ld, Transmitter %sempty\n", queue, (ret & EV_TXEMPTY)?"":"not ");
1960     return ret;
1961     
1962 }
1963
1964 /***********************************************************************
1965  *             COMM_WaitCommEventService      (INTERNAL)
1966  *
1967  *  We need to poll for what is interesting
1968  *  TIOCMIWAIT only checks modem status line and may not be aborted by a changing mask
1969  *
1970  */
1971 static DWORD WINAPI COMM_WaitCommEventService(LPVOID arg)
1972 {
1973     async_commio *commio = (async_commio*) arg;
1974     int waitmask = 0;
1975     int rc, fd, abort;
1976     serial_irq_info new_irq_info;
1977     DWORD new_mstat, new_evtmask;
1978
1979     fd=get_comm_fd( commio->handle, GENERIC_READ );
1980
1981     TRACE("handle %p fd 0x%08x, mask 0x%08lx buffer %p event %p irq_info %p waitmask 0x%08x\n", 
1982           commio->handle, fd, commio->evtmask, commio->buffer, commio->hEvent, &commio->irq_info, waitmask);
1983     do
1984     {
1985         /*
1986          * TIOCMIWAIT is not adequate
1987          *
1988          * FIXME:
1989          * We don't handle the EV_RXFLAG (the eventchar)
1990          */
1991         Sleep(1);
1992         rc= COMM_GetEInfo(fd,&new_irq_info);
1993         if (rc)
1994             TRACE("TIOCGICOUNT err %s\n", strerror(errno));
1995         rc = GetCommModemStatus(commio->handle, &new_mstat);
1996         if (!rc)
1997             TRACE("GetCommModemStatus failed\n");
1998         rc = Comm_CheckEvents(fd, commio->evtmask,&new_irq_info,&commio->irq_info, new_mstat, commio->mstat);
1999         GetCommMask(commio->handle, &new_evtmask);
2000         abort = (commio->evtmask != new_evtmask);
2001         TRACE("resulting Eventmask 0x%08x\n", rc);
2002     } while (!rc && ! abort);
2003     if (abort) rc = 0;
2004     release_comm_fd( commio->handle, fd );
2005     *commio->buffer = rc;
2006     if (commio->hEvent != INVALID_HANDLE_VALUE )
2007         NtSetEvent( commio->hEvent, NULL );
2008     HeapFree(GetProcessHeap(), 0, commio );
2009     return 0;
2010 }
2011
2012
2013 /***********************************************************************
2014  *             COMM_WaitCommEvent         (INTERNAL)
2015  *
2016  *  This function must have an lpOverlapped.
2017  */
2018 static BOOL COMM_WaitCommEvent(
2019     HANDLE hFile,              /* [in] handle of comm port to wait for */
2020     LPDWORD lpdwEvents,        /* [out] event(s) that were detected */
2021     LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2022 {
2023     int                 fd;
2024     async_commio*       commio;
2025     DWORD               result_mask;
2026     BOOL res;
2027
2028     if (!lpOverlapped)
2029     {
2030         SetLastError(ERROR_INVALID_PARAMETER);
2031         return FALSE;
2032     }
2033
2034     if (NtResetEvent(lpOverlapped->hEvent,NULL))
2035         return FALSE;
2036
2037     fd = get_comm_fd( hFile, GENERIC_WRITE );
2038     if (fd < 0) return FALSE;
2039
2040     commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
2041     if (!commio)
2042     {
2043         release_comm_fd( hFile, fd );
2044         return FALSE;
2045     }
2046
2047     commio->handle = hFile;
2048     commio->buffer = (char *)lpdwEvents;
2049     commio->hEvent = lpOverlapped->hEvent;
2050     GetCommMask(hFile, &commio->evtmask);
2051
2052 /* We may never return, if some capabilities miss
2053  * Return error in that case
2054  */
2055 #if !defined(TIOCINQ)
2056     if(commio->evtmask & EV_RXCHAR)
2057         goto error;
2058 #endif
2059 #if !(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)
2060     if(commio->evtmask & EV_TXEMPTY)
2061         goto error;
2062 #endif
2063 #if !defined(TIOCMGET)
2064     if(commio->evtmask & (EV_CTS | EV_DSR| EV_RING| EV_RLSD))
2065         goto error;
2066 #endif
2067 #if !defined(TIOCM_CTS)
2068     if(commio->evtmask & EV_CTS)
2069         goto error;
2070 #endif
2071 #if !defined(TIOCM_DSR)
2072     if(commio->evtmask & EV_DSR)
2073         goto error;
2074 #endif
2075 #if !defined(TIOCM_RNG)
2076     if(commio->evtmask & EV_RING)
2077         goto error;
2078 #endif
2079 #if !defined(TIOCM_CAR)
2080     if(commio->evtmask & EV_RLSD)
2081         goto error;
2082 #endif
2083     if(commio->evtmask & EV_RXFLAG)
2084         FIXME("EV_RXFLAG not handled\n");
2085     COMM_GetEInfo(fd,&commio->irq_info);
2086     GetCommModemStatus(hFile, &commio->mstat);
2087     /* We might have received something or the TX bufffer is delivered*/
2088     result_mask = Comm_CheckEvents( fd, commio->evtmask, &commio->irq_info, &commio->irq_info,commio->mstat,commio->mstat);
2089     if (result_mask) 
2090     {
2091         TRACE("Event already met\n");
2092         *lpdwEvents = result_mask;
2093         release_comm_fd( commio->handle, fd );
2094         HeapFree(GetProcessHeap(), 0, commio );
2095         res = TRUE;
2096     }
2097     else
2098     {
2099         CreateThread(NULL, 0, COMM_WaitCommEventService, (LPVOID)commio, 0, NULL);
2100         SetLastError(ERROR_IO_PENDING);
2101         res = FALSE;
2102     }
2103     return res;
2104 #if !defined(TIOCINQ) || (!(defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)) || !defined(TIOCINQ)) || !defined(TIOCMGET) || !defined(TIOCM_CTS) ||!defined(TIOCM_DSR) || !defined(TIOCM_RNG) || !defined(TIOCM_CAR)
2105  error:
2106     FIXME("Returning error because of missing capabilities\n");
2107     HeapFree(GetProcessHeap(), 0, commio );
2108     SetLastError(ERROR_INVALID_PARAMETER);
2109     return FALSE;
2110 #endif
2111 }
2112 /***********************************************************************
2113  *           WaitCommEvent   (KERNEL32.@)
2114  *
2115  * Wait until something interesting happens on a COMM port.
2116  * Interesting things (events) are set by calling SetCommMask before
2117  * this function is called.
2118  *
2119  * RETURNS:
2120  *   TRUE if successful
2121  *   FALSE if failure
2122  *
2123  *   The set of detected events will be written to *lpdwEventMask
2124  *   ERROR_IO_PENDING will be returned the overlapped structure was passed
2125  *
2126  * BUGS:
2127  *  Only supports EV_RXCHAR and EV_TXEMPTY
2128  */
2129 BOOL WINAPI WaitCommEvent(
2130     HANDLE hFile,              /* [in] handle of comm port to wait for */
2131     LPDWORD lpdwEvents,        /* [out] event(s) that were detected */
2132     LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2133 {
2134     OVERLAPPED ov;
2135     int ret = 0;
2136     DWORD res, err;
2137
2138     TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2139
2140     if(lpOverlapped)
2141         return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2142
2143     /* if there is no overlapped structure, create our own */
2144     ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
2145
2146     res = COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2147     err = GetLastError();
2148     if (!res)
2149     {
2150         if (err == ERROR_IO_PENDING)
2151         {
2152             do 
2153             {
2154                 res = WaitForSingleObjectEx(ov.hEvent, INFINITE, FALSE);
2155             } while (res != WAIT_OBJECT_0);
2156             TRACE("Event met\n:");
2157             ret = TRUE;
2158         }
2159         else
2160         {
2161             FIXME("Unknown error 0x%08lx\n", err);
2162             ret = FALSE;
2163         }
2164     }
2165     else
2166         ret = TRUE;
2167     CloseHandle(ov.hEvent);
2168
2169     return ret;
2170 }
2171
2172 /***********************************************************************
2173  *           GetCommProperties   (KERNEL32.@)
2174  *
2175  * This function fills in a structure with the capabilities of the
2176  * communications port driver.
2177  *
2178  * RETURNS
2179  *
2180  *  TRUE on success, FALSE on failure
2181  *  If successful, the lpCommProp structure be filled in with
2182  *  properties of the comm port.
2183  */
2184 BOOL WINAPI GetCommProperties(
2185     HANDLE hFile,          /* [in] handle of the comm port */
2186     LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2187 {
2188     FIXME("(%p %p )\n",hFile,lpCommProp);
2189     if(!lpCommProp)
2190         return FALSE;
2191
2192     /*
2193      * These values should be valid for LINUX's serial driver
2194      * FIXME: Perhaps they deserve an #ifdef LINUX
2195      */
2196     memset(lpCommProp,0,sizeof(COMMPROP));
2197     lpCommProp->wPacketLength       = 1;
2198     lpCommProp->wPacketVersion      = 1;
2199     lpCommProp->dwServiceMask       = SP_SERIALCOMM;
2200     lpCommProp->dwReserved1         = 0;
2201     lpCommProp->dwMaxTxQueue        = 4096;
2202     lpCommProp->dwMaxRxQueue        = 4096;
2203     lpCommProp->dwMaxBaud           = BAUD_115200;
2204     lpCommProp->dwProvSubType       = PST_RS232;
2205     lpCommProp->dwProvCapabilities  = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2206     lpCommProp->dwSettableParams    = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2207                                       SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2208     lpCommProp->dwSettableBaud      = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2209                 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2210                 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2211     lpCommProp->wSettableData       = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2212     lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2213                 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2214     lpCommProp->dwCurrentTxQueue    = lpCommProp->dwMaxTxQueue;
2215     lpCommProp->dwCurrentRxQueue    = lpCommProp->dwMaxRxQueue;
2216
2217     return TRUE;
2218 }
2219
2220 /***********************************************************************
2221  * FIXME:
2222  * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2223  * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2224  * This is dependent on the type of COMM port, but since it is doubtful
2225  * anybody will get around to implementing support for fancy serial
2226  * ports in WINE, this is hardcoded for the time being.  The name of
2227  * this DLL should be stored in and read from the system registry in
2228  * the hive HKEY_LOCAL_MACHINE, key
2229  * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2230  * where ???? is the port number... that is determined by PNP
2231  * The DLL should be loaded when the COMM port is opened, and closed
2232  * when the COMM port is closed. - MJM 20 June 2000
2233  ***********************************************************************/
2234 static WCHAR lpszSerialUI[] = { 
2235    's','e','r','i','a','l','u','i','.','d','l','l',0 };
2236
2237
2238 /***********************************************************************
2239  *           CommConfigDialogA   (KERNEL32.@)
2240  *
2241  * Raises a dialog that allows the user to configure a comm port.
2242  * Fills the COMMCONFIG struct with information specified by the user.
2243  * This function should call a similar routine in the COMM driver...
2244  *
2245  * RETURNS
2246  *
2247  *  TRUE on success, FALSE on failure
2248  *  If successful, the lpCommConfig structure will contain a new
2249  *  configuration for the comm port, as specified by the user.
2250  *
2251  * BUGS
2252  *  The library with the CommConfigDialog code is never unloaded.
2253  * Perhaps this should be done when the comm port is closed?
2254  */
2255 BOOL WINAPI CommConfigDialogA(
2256     LPCSTR lpszDevice,         /* [in] name of communications device */
2257     HWND hWnd,                 /* [in] parent window for the dialog */
2258     LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2259 {
2260     FARPROC lpfnCommDialog;
2261     HMODULE hConfigModule;
2262     BOOL r = FALSE;
2263
2264     TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2265
2266     hConfigModule = LoadLibraryW(lpszSerialUI);
2267     if(!hConfigModule)
2268         return FALSE;
2269
2270     lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2271
2272     if(lpfnCommDialog)
2273         r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2274
2275     FreeLibrary(hConfigModule);
2276
2277     return r;
2278 }
2279
2280 /***********************************************************************
2281  *           CommConfigDialogW   (KERNEL32.@)
2282  *
2283  * see CommConfigDialogA for more info
2284  */
2285 BOOL WINAPI CommConfigDialogW(
2286     LPCWSTR lpszDevice,        /* [in] name of communications device */
2287     HWND hWnd,                 /* [in] parent window for the dialog */
2288     LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2289 {
2290     FARPROC lpfnCommDialog;
2291     HMODULE hConfigModule;
2292     BOOL r = FALSE;
2293
2294     TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2295
2296     hConfigModule = LoadLibraryW(lpszSerialUI);
2297     if(!hConfigModule)
2298         return FALSE;
2299
2300     lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2301
2302     if(lpfnCommDialog)
2303         r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2304
2305     FreeLibrary(hConfigModule);
2306
2307     return r;
2308 }
2309
2310 /***********************************************************************
2311  *           GetCommConfig     (KERNEL32.@)
2312  *
2313  * Fill in the COMMCONFIG structure for the comm port hFile
2314  *
2315  * RETURNS
2316  *
2317  *  TRUE on success, FALSE on failure
2318  *  If successful, lpCommConfig contains the comm port configuration.
2319  *
2320  * BUGS
2321  *
2322  */
2323 BOOL WINAPI GetCommConfig(
2324     HANDLE       hFile,        /* [in] The communications device. */
2325     LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2326     LPDWORD      lpdwSize)     /* [in/out] Initially the size of the configuration buffer/structure,
2327                                   afterwards the number of bytes copied to the buffer or
2328                                   the needed size of the buffer. */
2329 {
2330     BOOL r;
2331
2332     TRACE("(%p %p)\n",hFile,lpCommConfig);
2333
2334     if(lpCommConfig == NULL)
2335         return FALSE;
2336     r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2337     *lpdwSize = sizeof(COMMCONFIG);
2338     if(r)
2339         return FALSE;
2340
2341     lpCommConfig->dwSize = sizeof(COMMCONFIG);
2342     lpCommConfig->wVersion = 1;
2343     lpCommConfig->wReserved = 0;
2344     r = GetCommState(hFile,&lpCommConfig->dcb);
2345     lpCommConfig->dwProviderSubType = PST_RS232;
2346     lpCommConfig->dwProviderOffset = 0;
2347     lpCommConfig->dwProviderSize = 0;
2348
2349     return r;
2350 }
2351
2352 /***********************************************************************
2353  *           SetCommConfig     (KERNEL32.@)
2354  *
2355  *  Sets the configuration of the communications device.
2356  *
2357  * RETURNS
2358  *
2359  *  True on success, false if the handle was bad is not a communications device.
2360  */
2361 BOOL WINAPI SetCommConfig(
2362     HANDLE       hFile,         /* [in] The communications device. */
2363     LPCOMMCONFIG lpCommConfig,  /* [in] The desired configuration. */
2364     DWORD dwSize)               /* [in] size of the lpCommConfig struct */
2365 {
2366     TRACE("(%p %p)\n",hFile,lpCommConfig);
2367     return SetCommState(hFile,&lpCommConfig->dcb);
2368 }
2369
2370 /***********************************************************************
2371  *           SetDefaultCommConfigA   (KERNEL32.@)
2372  *
2373  *  Initializes the default configuration for the specified communication
2374  *  device. (ascii)
2375  *
2376  * RETURNS
2377  *
2378  *  True if the device was found and the defaults set, false otherwise
2379  */
2380 BOOL WINAPI SetDefaultCommConfigW(
2381     LPCWSTR       lpszDevice,  /* [in] The ascii name of the device targeted for configuration. */
2382     LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2383     DWORD        dwSize)       /* [in] The number of bytes in the configuration structure. */
2384 {
2385     FARPROC lpfnSetDefaultCommConfig;
2386     HMODULE hConfigModule;
2387     BOOL r = FALSE;
2388
2389     TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2390
2391     hConfigModule = LoadLibraryW(lpszSerialUI);
2392     if(!hConfigModule)
2393         return r;
2394
2395     lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2396     if (lpfnSetDefaultCommConfig)
2397         r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2398
2399     FreeLibrary(hConfigModule);
2400
2401     return r;
2402 }
2403
2404
2405 /***********************************************************************
2406  *           SetDefaultCommConfigW     (KERNEL32.@)
2407  *
2408  *  Initializes the default configuration for the specified
2409  *  communication device. (unicode)
2410  *
2411  * RETURNS
2412  *
2413  */
2414 BOOL WINAPI SetDefaultCommConfigA(
2415     LPCSTR      lpszDevice,    /* [in] The unicode name of the device targeted for configuration. */
2416     LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2417     DWORD        dwSize)       /* [in] The number of bytes in the configuration structure. */
2418 {
2419     BOOL r;
2420     LPWSTR lpDeviceW = NULL;
2421     DWORD len;
2422
2423     TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2424
2425     if (lpszDevice)
2426     {
2427         len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2428         lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2429         MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2430     }
2431     r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2432     HeapFree( GetProcessHeap(), 0, lpDeviceW );
2433     return r;
2434 }
2435
2436
2437 /***********************************************************************
2438  *           GetDefaultCommConfigW   (KERNEL32.@)
2439  *
2440  *   Acquires the default configuration of the specified communication device. (unicode)
2441  *
2442  *  RETURNS
2443  *
2444  *   True on successful reading of the default configuration,
2445  *   if the device is not found or the buffer is too small.
2446  */
2447 BOOL WINAPI GetDefaultCommConfigW(
2448     LPCWSTR      lpszName, /* [in] The unicode name of the device targeted for configuration. */
2449     LPCOMMCONFIG lpCC,     /* [out] The default configuration for the device. */
2450     LPDWORD      lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2451                               afterwards the number of bytes copied to the buffer or
2452                               the needed size of the buffer. */
2453 {
2454      LPDCB lpdcb = &(lpCC->dcb);
2455      WCHAR temp[40];
2456      static const WCHAR comW[] = {'C','O','M',0};
2457      static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2458
2459      if (strncmpiW(lpszName,comW,3)) {
2460         ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2461         return FALSE;
2462      }
2463
2464      TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2465      if (*lpdwSize < sizeof(COMMCONFIG)) {
2466          *lpdwSize = sizeof(COMMCONFIG);
2467          return FALSE;
2468        }
2469
2470      *lpdwSize = sizeof(COMMCONFIG);
2471
2472      lpCC->dwSize = sizeof(COMMCONFIG);
2473      lpCC->wVersion = 1;
2474      lpCC->dwProviderSubType = PST_RS232;
2475      lpCC->dwProviderOffset = 0L;
2476      lpCC->dwProviderSize = 0L;
2477
2478      sprintfW( temp, formatW, lpszName[3]);
2479      FIXME("setting %s as default\n", debugstr_w(temp));
2480
2481      return BuildCommDCBW( temp, lpdcb);
2482 }
2483
2484 /**************************************************************************
2485  *         GetDefaultCommConfigA                (KERNEL32.@)
2486  *
2487  *   Acquires the default configuration of the specified communication device. (ascii)
2488  *
2489  *  RETURNS
2490  *
2491  *   True on successful reading of the default configuration,
2492  *   if the device is not found or the buffer is too small.
2493  */
2494 BOOL WINAPI GetDefaultCommConfigA(
2495     LPCSTR       lpszName, /* [in] The ascii name of the device targeted for configuration. */
2496     LPCOMMCONFIG lpCC,     /* [out] The default configuration for the device. */
2497     LPDWORD      lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2498                               afterwards the number of bytes copied to the buffer or
2499                               the needed size of the buffer. */
2500 {
2501         BOOL ret = FALSE;
2502         UNICODE_STRING lpszNameW;
2503
2504         TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2505         if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2506         else lpszNameW.Buffer = NULL;
2507
2508         if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2509
2510         RtlFreeUnicodeString(&lpszNameW);
2511         return ret;
2512 }