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