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