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