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