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