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