Compile the kernel dll with -DSTRICT.
[wine/testsucceed.git] / dlls / kernel / comm.c
blob036e7860dd78444bf0c5e94e1aebe638311cf000
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
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.
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.
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
20 * History:
22 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
23 * - Fixed the modem control part of EscapeCommFunction16.
25 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
26 * - Implemented buffers and EnableCommNotification.
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.
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.
38 * July 6, 1998. Fixes and comments by Valentijn Sessink
39 * <vsessink@ic.uva.nl> [V]
41 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
42 * <lawson_whitney@juno.com>
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.
52 #include "config.h"
53 #include "wine/port.h"
55 #include <stdlib.h>
56 #include <stdio.h>
57 #ifdef HAVE_TERMIOS_H
58 #include <termios.h>
59 #endif
60 #include <fcntl.h>
61 #include <string.h>
62 #ifdef HAVE_STRINGS_H
63 # include <strings.h>
64 #endif
65 #include <errno.h>
66 #include <ctype.h>
67 #include <sys/stat.h>
68 #ifdef HAVE_SYS_FILIO_H
69 # include <sys/filio.h>
70 #endif
71 #ifdef HAVE_SYS_IOCTL_H
72 #include <sys/ioctl.h>
73 #endif
74 #ifdef HAVE_UNISTD_H
75 # include <unistd.h>
76 #endif
77 #ifdef HAVE_SYS_POLL_H
78 # include <sys/poll.h>
79 #endif
80 #ifdef HAVE_SYS_MODEM_H
81 # include <sys/modem.h>
82 #endif
83 #ifdef HAVE_SYS_STRTIO_H
84 # include <sys/strtio.h>
85 #endif
87 #include "winbase.h"
88 #include "winerror.h"
90 #include "wine/server.h"
91 #include "async.h"
92 #include "file.h"
93 #include "heap.h"
95 #include "wine/debug.h"
97 #ifdef HAVE_LINUX_SERIAL_H
98 #include <linux/serial.h>
99 #endif
101 WINE_DEFAULT_DEBUG_CHANNEL(comm);
103 /***********************************************************************
104 * Asynchronous I/O for asynchronous wait requests *
107 static DWORD commio_get_async_status (const async_private *ovp);
108 static DWORD commio_get_async_count (const async_private *ovp);
109 static void commio_set_async_status (async_private *ovp, const DWORD status);
110 static void commio_async_cleanup (async_private *ovp);
112 static async_ops commio_async_ops =
114 commio_get_async_status, /* get_status */
115 commio_set_async_status, /* set_status */
116 commio_get_async_count, /* get_count */
117 NULL, /* call_completion */
118 commio_async_cleanup /* cleanup */
121 typedef struct async_commio
123 struct async_private async;
124 LPOVERLAPPED lpOverlapped;
125 char *buffer;
126 } async_commio;
128 static DWORD commio_get_async_status (const struct async_private *ovp)
130 return ((async_commio*) ovp)->lpOverlapped->Internal;
133 static void commio_set_async_status (async_private *ovp, const DWORD status)
135 ((async_commio*) ovp)->lpOverlapped->Internal = status;
138 static DWORD commio_get_async_count (const struct async_private *ovp)
140 return 0;
143 static void commio_async_cleanup (async_private *ovp)
145 HeapFree(GetProcessHeap(), 0, ovp );
148 /***********************************************************************/
150 #if !defined(TIOCINQ) && defined(FIONREAD)
151 #define TIOCINQ FIONREAD
152 #endif
154 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
156 #ifdef TIOCMGET
157 unsigned int mstat, okay;
158 okay = ioctl(fd, TIOCMGET, &mstat);
159 if (okay) return okay;
160 if (andy) mstat &= andy;
161 mstat |= orrie;
162 return ioctl(fd, TIOCMSET, &mstat);
163 #else
164 return 0;
165 #endif
168 /***********************************************************************
169 * COMM_BuildOldCommDCB (Internal)
171 * Build a DCB using the old style settings string eg: "COMx:96,n,8,1"
172 * We ignore the COM port index, since we can support more than 4 ports.
174 BOOL WINAPI COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
176 /* "COM1:96,n,8,1" */
177 /* 012345 */
178 char *ptr, temp[256], last;
179 int rate;
181 TRACE("(%s), ptr %p\n", device, lpdcb);
183 /* Some applications call this function with "9600,n,8,1"
184 * not sending the "COM1:" parameter at left of string */
185 if (!strncasecmp(device,"COM",3))
187 if (!device[3]) return FALSE;
188 if (device[4] != ':' && device[4] != ' ') return FALSE;
189 strcpy(temp,device+5);
191 else strcpy(temp,device);
193 last=temp[strlen(temp)-1];
194 ptr = strtok(temp, ", ");
196 /* DOS/Windows only compares the first two numbers
197 * and assigns an appropriate baud rate.
198 * You can supply 961324245, it still returns 9600 ! */
199 if (strlen(ptr) < 2)
201 WARN("Unknown baudrate string '%s' !\n", ptr);
202 return FALSE; /* error: less than 2 chars */
204 ptr[2] = '\0';
205 rate = atoi(ptr);
207 switch (rate) {
208 case 11:
209 case 30:
210 case 60:
211 rate *= 10;
212 break;
213 case 12:
214 case 24:
215 case 48:
216 case 96:
217 rate *= 100;
218 break;
219 case 19:
220 rate = 19200;
221 break;
222 default:
223 WARN("Unknown baudrate indicator %d !\n", rate);
224 return FALSE;
227 lpdcb->BaudRate = rate;
228 TRACE("baudrate (%ld)\n", lpdcb->BaudRate);
230 ptr = strtok(NULL, ", ");
231 if (islower(*ptr))
232 *ptr = toupper(*ptr);
234 TRACE("parity (%c)\n", *ptr);
235 lpdcb->fParity = TRUE;
236 switch (*ptr) {
237 case 'N':
238 lpdcb->Parity = NOPARITY;
239 lpdcb->fParity = FALSE;
240 break;
241 case 'E':
242 lpdcb->Parity = EVENPARITY;
243 break;
244 case 'M':
245 lpdcb->Parity = MARKPARITY;
246 break;
247 case 'O':
248 lpdcb->Parity = ODDPARITY;
249 break;
250 case 'S':
251 lpdcb->Parity = SPACEPARITY;
252 break;
253 default:
254 WARN("Unknown parity `%c'!\n", *ptr);
255 return FALSE;
258 ptr = strtok(NULL, ", ");
259 TRACE("charsize (%c)\n", *ptr);
260 lpdcb->ByteSize = *ptr - '0';
262 ptr = strtok(NULL, ", ");
263 TRACE("stopbits (%c)\n", *ptr);
264 switch (*ptr) {
265 case '1':
266 lpdcb->StopBits = ONESTOPBIT;
267 break;
268 case '2':
269 lpdcb->StopBits = TWOSTOPBITS;
270 break;
271 default:
272 WARN("Unknown # of stopbits `%c'!\n", *ptr);
273 return FALSE;
276 if (last == 'x') {
277 lpdcb->fInX = TRUE;
278 lpdcb->fOutX = TRUE;
279 lpdcb->fOutxCtsFlow = FALSE;
280 lpdcb->fOutxDsrFlow = FALSE;
281 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
282 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
283 } else if (last=='p') {
284 lpdcb->fInX = FALSE;
285 lpdcb->fOutX = FALSE;
286 lpdcb->fOutxCtsFlow = TRUE;
287 lpdcb->fOutxDsrFlow = FALSE;
288 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
289 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
290 } else {
291 lpdcb->fInX = FALSE;
292 lpdcb->fOutX = FALSE;
293 lpdcb->fOutxCtsFlow = FALSE;
294 lpdcb->fOutxDsrFlow = FALSE;
295 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
296 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
299 return TRUE;
302 /**************************************************************************
303 * BuildCommDCBA (KERNEL32.@)
305 * Updates a device control block data structure with values from an
306 * ascii device control string. The device control string has two forms
307 * normal and extended, it must be exclusively in one or the other form.
309 * RETURNS
311 * True on success, false on a malformed control string.
313 BOOL WINAPI BuildCommDCBA(
314 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
315 LPDCB lpdcb) /* [out] The device control block to be updated. */
317 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
320 /**************************************************************************
321 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
323 * Updates a device control block data structure with values from an
324 * ascii device control string. Taking timeout values from a timeouts
325 * struct if desired by the control string.
327 * RETURNS
329 * True on success, false bad handles etc
331 BOOL WINAPI BuildCommDCBAndTimeoutsA(
332 LPCSTR device, /* [in] The ascii device control string. */
333 LPDCB lpdcb, /* [out] The device control block to be updated. */
334 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
336 int port;
337 char *ptr,*temp;
339 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
341 if (!strncasecmp(device,"COM",3)) {
342 port=device[3]-'0';
343 if (port--==0) {
344 ERR("BUG! COM0 can't exist!\n");
345 return FALSE;
347 if ((*(device+4)!=':') && (*(device+4)!=' '))
348 return FALSE;
349 temp=(LPSTR)(device+5);
350 } else
351 temp=(LPSTR)device;
353 memset(lpdcb,0,sizeof (DCB));
354 lpdcb->DCBlength = sizeof(DCB);
355 if (strchr(temp,',')) { /* old style */
357 return COMM_BuildOldCommDCB(device,lpdcb);
359 ptr=strtok(temp," ");
360 while (ptr) {
361 DWORD flag,x;
363 flag=0;
364 if (!strncasecmp("baud=",ptr,5)) {
365 if (!sscanf(ptr+5,"%ld",&x))
366 WARN("Couldn't parse %s\n",ptr);
367 lpdcb->BaudRate = x;
368 flag=1;
370 if (!strncasecmp("stop=",ptr,5)) {
371 if (!sscanf(ptr+5,"%ld",&x))
372 WARN("Couldn't parse %s\n",ptr);
373 lpdcb->StopBits = x;
374 flag=1;
376 if (!strncasecmp("data=",ptr,5)) {
377 if (!sscanf(ptr+5,"%ld",&x))
378 WARN("Couldn't parse %s\n",ptr);
379 lpdcb->ByteSize = x;
380 flag=1;
382 if (!strncasecmp("parity=",ptr,7)) {
383 lpdcb->fParity = TRUE;
384 switch (ptr[7]) {
385 case 'N':case 'n':
386 lpdcb->fParity = FALSE;
387 lpdcb->Parity = NOPARITY;
388 break;
389 case 'E':case 'e':
390 lpdcb->Parity = EVENPARITY;
391 break;
392 case 'O':case 'o':
393 lpdcb->Parity = ODDPARITY;
394 break;
395 case 'M':case 'm':
396 lpdcb->Parity = MARKPARITY;
397 break;
398 case 'S':case 's':
399 lpdcb->Parity = SPACEPARITY;
400 break;
402 flag=1;
404 if (!flag)
405 ERR("Unhandled specifier '%s', please report.\n",ptr);
406 ptr=strtok(NULL," ");
408 if (lpdcb->BaudRate==110)
409 lpdcb->StopBits = 2;
410 return TRUE;
413 /**************************************************************************
414 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
416 * Updates a device control block data structure with values from an
417 * unicode device control string. Taking timeout values from a timeouts
418 * struct if desired by the control string.
420 * RETURNS
422 * True on success, false bad handles etc.
424 BOOL WINAPI BuildCommDCBAndTimeoutsW(
425 LPCWSTR devid, /* [in] The unicode device control string. */
426 LPDCB lpdcb, /* [out] The device control block to be updated. */
427 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
429 BOOL ret = FALSE;
430 LPSTR devidA;
432 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
433 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
434 if (devidA)
436 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
437 HeapFree( GetProcessHeap(), 0, devidA );
439 return ret;
442 /**************************************************************************
443 * BuildCommDCBW (KERNEL32.@)
445 * Updates a device control block structure with values from an
446 * unicode device control string. The device control string has two forms
447 * normal and extended, it must be exclusively in one or the other form.
449 * RETURNS
451 * True on success, false on an malformed control string.
453 BOOL WINAPI BuildCommDCBW(
454 LPCWSTR devid, /* [in] The unicode device control string. */
455 LPDCB lpdcb) /* [out] The device control block to be updated. */
457 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
460 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
462 DWORD ret;
464 SERVER_START_REQ( set_serial_info )
466 req->handle = handle;
467 req->flags = SERIALINFO_SET_ERROR;
468 req->commerror = error;
469 ret = !wine_server_call_err( req );
471 SERVER_END_REQ;
472 return ret;
475 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
477 DWORD ret;
479 if(!lperror)
480 return FALSE;
482 SERVER_START_REQ( get_serial_info )
484 req->handle = handle;
485 ret = !wine_server_call_err( req );
486 *lperror = reply->commerror;
488 SERVER_END_REQ;
490 return ret;
493 /*****************************************************************************
494 * SetCommBreak (KERNEL32.@)
496 * Halts the transmission of characters to a communications device.
498 * RETURNS
500 * True on success, and false if the communications device could not be found,
501 * the control is not supported.
503 * BUGS
505 * Only TIOCSBRK and TIOCCBRK are supported.
507 BOOL WINAPI SetCommBreak(
508 HANDLE handle) /* [in] The communictions device to suspend. */
510 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
511 int fd,result;
513 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
514 if(fd<0) {
515 TRACE("FILE_GetUnixHandle failed\n");
516 return FALSE;
518 result = ioctl(fd,TIOCSBRK,0);
519 close(fd);
520 if (result ==-1)
522 TRACE("ioctl failed\n");
523 SetLastError(ERROR_NOT_SUPPORTED);
524 return FALSE;
526 return TRUE;
527 #else
528 FIXME("ioctl not available\n");
529 SetLastError(ERROR_NOT_SUPPORTED);
530 return FALSE;
531 #endif
534 /*****************************************************************************
535 * ClearCommBreak (KERNEL32.@)
537 * Resumes character transmission from a communication device.
539 * RETURNS
541 * True on success and false if the communications device could not be found.
543 * BUGS
545 * Only TIOCSBRK and TIOCCBRK are supported.
547 BOOL WINAPI ClearCommBreak(
548 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
550 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
551 int fd,result;
553 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
554 if(fd<0) {
555 TRACE("FILE_GetUnixHandle failed\n");
556 return FALSE;
558 result = ioctl(fd,TIOCCBRK,0);
559 close(fd);
560 if (result ==-1)
562 TRACE("ioctl failed\n");
563 SetLastError(ERROR_NOT_SUPPORTED);
564 return FALSE;
566 return TRUE;
567 #else
568 FIXME("ioctl not available\n");
569 SetLastError(ERROR_NOT_SUPPORTED);
570 return FALSE;
571 #endif
574 /*****************************************************************************
575 * EscapeCommFunction (KERNEL32.@)
577 * Directs a communication device to perform an extended function.
579 * RETURNS
581 * True or requested data on successful completion of the command,
582 * false if the device is not present cannot execute the command
583 * or the command failed.
585 BOOL WINAPI EscapeCommFunction(
586 HANDLE handle, /* [in] The communication device to perform the extended function. */
587 UINT nFunction) /* [in] The extended function to be performed. */
589 int fd,direct=FALSE,result=FALSE;
590 struct termios port;
592 TRACE("handle %p, function=%d\n", handle, nFunction);
593 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
594 if(fd<0) {
595 FIXME("handle %p not found.\n",handle);
596 return FALSE;
599 if (tcgetattr(fd,&port) == -1) {
600 COMM_SetCommError(handle,CE_IOE);
601 close(fd);
602 return FALSE;
605 switch (nFunction) {
606 case RESETDEV:
607 TRACE("\n");
608 break;
610 case CLRDTR:
611 TRACE("CLRDTR\n");
612 #ifdef TIOCM_DTR
613 direct=TRUE;
614 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
615 break;
616 #endif
618 case CLRRTS:
619 TRACE("CLRRTS\n");
620 #ifdef TIOCM_RTS
621 direct=TRUE;
622 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
623 break;
624 #endif
626 case SETDTR:
627 TRACE("SETDTR\n");
628 #ifdef TIOCM_DTR
629 direct=TRUE;
630 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
631 break;
632 #endif
634 case SETRTS:
635 TRACE("SETRTS\n");
636 #ifdef TIOCM_RTS
637 direct=TRUE;
638 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
639 break;
640 #endif
642 case SETXOFF:
643 TRACE("SETXOFF\n");
644 port.c_iflag |= IXOFF;
645 break;
647 case SETXON:
648 TRACE("SETXON\n");
649 port.c_iflag |= IXON;
650 break;
651 case SETBREAK:
652 TRACE("setbreak\n");
653 #ifdef TIOCSBRK
654 direct=TRUE;
655 result = ioctl(fd,TIOCSBRK,0);
656 break;
657 #endif
658 case CLRBREAK:
659 TRACE("clrbreak\n");
660 #ifdef TIOCSBRK
661 direct=TRUE;
662 result = ioctl(fd,TIOCCBRK,0);
663 break;
664 #endif
665 default:
666 WARN("(handle=%p,nFunction=%d): Unknown function\n",
667 handle, nFunction);
668 break;
671 if (!direct)
672 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
673 close(fd);
674 COMM_SetCommError(handle,CE_IOE);
675 return FALSE;
676 } else
677 result= TRUE;
678 else
680 if (result == -1)
682 result= FALSE;
683 COMM_SetCommError(handle,CE_IOE);
685 else
686 result = TRUE;
688 close(fd);
689 return result;
692 /********************************************************************
693 * PurgeComm (KERNEL32.@)
695 * Terminates pending operations and/or discards buffers on a
696 * communication resource.
698 * RETURNS
700 * True on success and false if the communications handle is bad.
702 BOOL WINAPI PurgeComm(
703 HANDLE handle, /* [in] The communication resource to be purged. */
704 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
706 int fd;
708 TRACE("handle %p, flags %lx\n", handle, flags);
710 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
711 if(fd<0) {
712 FIXME("no handle %p found\n",handle);
713 return FALSE;
717 ** not exactly sure how these are different
718 ** Perhaps if we had our own internal queues, one flushes them
719 ** and the other flushes the kernel's buffers.
721 if(flags&PURGE_TXABORT)
722 tcflush(fd,TCOFLUSH);
723 if(flags&PURGE_RXABORT)
724 tcflush(fd,TCIFLUSH);
725 if(flags&PURGE_TXCLEAR)
726 tcflush(fd,TCOFLUSH);
727 if(flags&PURGE_RXCLEAR)
728 tcflush(fd,TCIFLUSH);
729 close(fd);
731 return 1;
734 /*****************************************************************************
735 * ClearCommError (KERNEL32.@)
737 * Enables further I/O operations on a communications resource after
738 * supplying error and current status information.
740 * RETURNS
742 * True on success, false if the communication resource handle is bad.
744 BOOL WINAPI ClearCommError(
745 HANDLE handle, /* [in] The communication resource with the error. */
746 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
747 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
749 int fd;
751 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
752 if(0>fd)
754 FIXME("no handle %p found\n",handle);
755 return FALSE;
758 if (lpStat)
760 lpStat->fCtsHold = 0;
761 lpStat->fDsrHold = 0;
762 lpStat->fRlsdHold = 0;
763 lpStat->fXoffHold = 0;
764 lpStat->fXoffSent = 0;
765 lpStat->fEof = 0;
766 lpStat->fTxim = 0;
767 lpStat->fReserved = 0;
769 #ifdef TIOCOUTQ
770 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
771 WARN("ioctl returned error\n");
772 #else
773 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
774 #endif
776 #ifdef TIOCINQ
777 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
778 WARN("ioctl returned error\n");
779 #endif
781 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
782 handle, lpStat->cbInQue, lpStat->cbOutQue);
785 close(fd);
787 COMM_GetCommError(handle, errors);
788 COMM_SetCommError(handle, 0);
790 return TRUE;
793 /*****************************************************************************
794 * SetupComm (KERNEL32.@)
796 * Called after CreateFile to hint to the communication resource to use
797 * specified sizes for input and output buffers rather than the default values.
799 * RETURNS
801 * True if successful, false if the communications resource handle is bad.
803 * BUGS
805 * Stub.
807 BOOL WINAPI SetupComm(
808 HANDLE handle, /* [in] The just created communication resource handle. */
809 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
810 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
812 int fd;
814 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
815 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
816 if(0>fd) {
817 FIXME("handle %p not found?\n",handle);
818 return FALSE;
820 close(fd);
821 return TRUE;
824 /*****************************************************************************
825 * GetCommMask (KERNEL32.@)
827 * Obtain the events associated with a communication device that will cause
828 * a call WaitCommEvent to return.
830 * RETURNS
832 * True on success, fail on bad device handle etc.
834 BOOL WINAPI GetCommMask(
835 HANDLE handle, /* [in] The communications device. */
836 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
838 BOOL ret;
840 TRACE("handle %p, mask %p\n", handle, evtmask);
842 SERVER_START_REQ( get_serial_info )
844 req->handle = handle;
845 if ((ret = !wine_server_call_err( req )))
847 if (evtmask) *evtmask = reply->eventmask;
850 SERVER_END_REQ;
851 return ret;
854 /*****************************************************************************
855 * SetCommMask (KERNEL32.@)
857 * There be some things we need to hear about yon there communications device.
858 * (Set which events associated with a communication device should cause
859 * a call WaitCommEvent to return.)
861 * RETURNS
863 * True on success, false on bad handle etc.
865 BOOL WINAPI SetCommMask(
866 HANDLE handle, /* [in] The communications device. */
867 DWORD evtmask) /* [in] The events that are to be monitored. */
869 BOOL ret;
871 TRACE("handle %p, mask %lx\n", handle, evtmask);
873 SERVER_START_REQ( set_serial_info )
875 req->handle = handle;
876 req->flags = SERIALINFO_SET_MASK;
877 req->eventmask = evtmask;
878 ret = !wine_server_call_err( req );
880 SERVER_END_REQ;
881 return ret;
884 /*****************************************************************************
885 * SetCommState (KERNEL32.@)
887 * Re-initializes all hardware and control settings of a communications device,
888 * with values from a device control block without effecting the input and output
889 * queues.
891 * RETURNS
893 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
895 BOOL WINAPI SetCommState(
896 HANDLE handle, /* [in] The communications device. */
897 LPDCB lpdcb) /* [out] The device control block. */
899 struct termios port;
900 int fd, bytesize, stopbits;
902 TRACE("handle %p, ptr %p\n", handle, lpdcb);
903 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
904 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
905 (lpdcb->StopBits == ONESTOPBIT)?1:
906 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
907 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
908 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
910 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
911 if (fd < 0) {
912 FIXME("no handle %p found\n",handle);
913 return FALSE;
916 if ((tcgetattr(fd,&port)) == -1) {
917 int save_error = errno;
918 COMM_SetCommError(handle,CE_IOE);
919 close( fd );
920 ERR("tcgetattr error '%s'\n", strerror(save_error));
921 return FALSE;
924 port.c_cc[VMIN] = 0;
925 port.c_cc[VTIME] = 1;
927 #ifdef IMAXBEL
928 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
929 #else
930 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
931 #endif
932 port.c_iflag |= (IGNBRK);
934 port.c_oflag &= ~(OPOST);
936 port.c_cflag &= ~(HUPCL);
937 port.c_cflag |= CLOCAL | CREAD;
939 port.c_lflag &= ~(ICANON|ECHO|ISIG);
940 port.c_lflag |= NOFLSH;
942 #ifdef CBAUD
943 port.c_cflag &= ~CBAUD;
944 switch (lpdcb->BaudRate) {
945 case 110:
946 case CBR_110:
947 port.c_cflag |= B110;
948 break;
949 case 300:
950 case CBR_300:
951 port.c_cflag |= B300;
952 break;
953 case 600:
954 case CBR_600:
955 port.c_cflag |= B600;
956 break;
957 case 1200:
958 case CBR_1200:
959 port.c_cflag |= B1200;
960 break;
961 case 2400:
962 case CBR_2400:
963 port.c_cflag |= B2400;
964 break;
965 case 4800:
966 case CBR_4800:
967 port.c_cflag |= B4800;
968 break;
969 case 9600:
970 case CBR_9600:
971 port.c_cflag |= B9600;
972 break;
973 case 19200:
974 case CBR_19200:
975 port.c_cflag |= B19200;
976 break;
977 case 38400:
978 case CBR_38400:
979 port.c_cflag |= B38400;
980 break;
981 #ifdef B57600
982 case 57600:
983 port.c_cflag |= B57600;
984 break;
985 #endif
986 #ifdef B115200
987 case 115200:
988 port.c_cflag |= B115200;
989 break;
990 #endif
991 #ifdef B230400
992 case 230400:
993 port.c_cflag |= B230400;
994 break;
995 #endif
996 #ifdef B460800
997 case 460800:
998 port.c_cflag |= B460800;
999 break;
1000 #endif
1001 default:
1002 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1003 { struct serial_struct nuts;
1004 int arby;
1005 ioctl(fd, TIOCGSERIAL, &nuts);
1006 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1007 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1008 arby = nuts.baud_base / nuts.custom_divisor;
1009 nuts.flags &= ~ASYNC_SPD_MASK;
1010 nuts.flags |= ASYNC_SPD_CUST;
1011 WARN("You (or a program acting at your behest) have specified\n"
1012 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1013 "which is as close as we can get by our present understanding of your\n"
1014 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1015 "has caused to your linux system can be undone with setserial \n"
1016 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1017 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1018 ioctl(fd, TIOCSSERIAL, &nuts);
1019 port.c_cflag |= B38400;
1021 break;
1022 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1025 COMM_SetCommError(handle,IE_BAUDRATE);
1026 close( fd );
1027 ERR("baudrate %ld\n",lpdcb->BaudRate);
1028 return FALSE;
1030 #elif !defined(__EMX__)
1031 switch (lpdcb->BaudRate) {
1032 case 110:
1033 case CBR_110:
1034 port.c_ospeed = B110;
1035 break;
1036 case 300:
1037 case CBR_300:
1038 port.c_ospeed = B300;
1039 break;
1040 case 600:
1041 case CBR_600:
1042 port.c_ospeed = B600;
1043 break;
1044 case 1200:
1045 case CBR_1200:
1046 port.c_ospeed = B1200;
1047 break;
1048 case 2400:
1049 case CBR_2400:
1050 port.c_ospeed = B2400;
1051 break;
1052 case 4800:
1053 case CBR_4800:
1054 port.c_ospeed = B4800;
1055 break;
1056 case 9600:
1057 case CBR_9600:
1058 port.c_ospeed = B9600;
1059 break;
1060 case 19200:
1061 case CBR_19200:
1062 port.c_ospeed = B19200;
1063 break;
1064 case 38400:
1065 case CBR_38400:
1066 port.c_ospeed = B38400;
1067 break;
1068 #ifdef B57600
1069 case 57600:
1070 case CBR_57600:
1071 port.c_cflag |= B57600;
1072 break;
1073 #endif
1074 #ifdef B115200
1075 case 115200:
1076 case CBR_115200:
1077 port.c_cflag |= B115200;
1078 break;
1079 #endif
1080 #ifdef B230400
1081 case 230400:
1082 port.c_cflag |= B230400;
1083 break;
1084 #endif
1085 #ifdef B460800
1086 case 460800:
1087 port.c_cflag |= B460800;
1088 break;
1089 #endif
1090 default:
1091 COMM_SetCommError(handle,IE_BAUDRATE);
1092 close( fd );
1093 ERR("baudrate %ld\n",lpdcb->BaudRate);
1094 return FALSE;
1096 port.c_ispeed = port.c_ospeed;
1097 #endif
1098 bytesize=lpdcb->ByteSize;
1099 stopbits=lpdcb->StopBits;
1101 #ifdef CMSPAR
1102 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1103 #else
1104 port.c_cflag &= ~(PARENB | PARODD);
1105 #endif
1106 if (lpdcb->fParity)
1107 port.c_iflag |= INPCK;
1108 else
1109 port.c_iflag &= ~INPCK;
1110 switch (lpdcb->Parity) {
1111 case NOPARITY:
1112 break;
1113 case ODDPARITY:
1114 port.c_cflag |= (PARENB | PARODD);
1115 break;
1116 case EVENPARITY:
1117 port.c_cflag |= PARENB;
1118 break;
1119 #ifdef CMSPAR
1120 /* Linux defines mark/space (stick) parity */
1121 case MARKPARITY:
1122 port.c_cflag |= (PARENB | CMSPAR);
1123 break;
1124 case SPACEPARITY:
1125 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1126 break;
1127 #else
1128 /* try the POSIX way */
1129 case MARKPARITY:
1130 if( stopbits == ONESTOPBIT) {
1131 stopbits = TWOSTOPBITS;
1132 port.c_iflag &= ~INPCK;
1133 } else {
1134 COMM_SetCommError(handle,IE_BYTESIZE);
1135 close( fd );
1136 ERR("Cannot set MARK Parity\n");
1137 return FALSE;
1139 break;
1140 case SPACEPARITY:
1141 if( bytesize < 8) {
1142 bytesize +=1;
1143 port.c_iflag &= ~INPCK;
1144 } else {
1145 COMM_SetCommError(handle,IE_BYTESIZE);
1146 close( fd );
1147 ERR("Cannot set SPACE Parity\n");
1148 return FALSE;
1150 break;
1151 #endif
1152 default:
1153 COMM_SetCommError(handle,IE_BYTESIZE);
1154 close( fd );
1155 ERR("Parity\n");
1156 return FALSE;
1160 port.c_cflag &= ~CSIZE;
1161 switch (bytesize) {
1162 case 5:
1163 port.c_cflag |= CS5;
1164 break;
1165 case 6:
1166 port.c_cflag |= CS6;
1167 break;
1168 case 7:
1169 port.c_cflag |= CS7;
1170 break;
1171 case 8:
1172 port.c_cflag |= CS8;
1173 break;
1174 default:
1175 COMM_SetCommError(handle,IE_BYTESIZE);
1176 close( fd );
1177 ERR("ByteSize\n");
1178 return FALSE;
1181 switch (stopbits) {
1182 case ONESTOPBIT:
1183 port.c_cflag &= ~CSTOPB;
1184 break;
1185 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1186 case TWOSTOPBITS:
1187 port.c_cflag |= CSTOPB;
1188 break;
1189 default:
1190 COMM_SetCommError(handle,IE_BYTESIZE);
1191 close( fd );
1192 ERR("StopBits\n");
1193 return FALSE;
1195 #ifdef CRTSCTS
1196 if ( lpdcb->fOutxCtsFlow ||
1197 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1200 port.c_cflag |= CRTSCTS;
1201 TRACE("CRTSCTS\n");
1203 #endif
1205 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1207 WARN("DSR/DTR flow control not supported\n");
1210 if (lpdcb->fInX)
1211 port.c_iflag |= IXON;
1212 else
1213 port.c_iflag &= ~IXON;
1214 if (lpdcb->fOutX)
1215 port.c_iflag |= IXOFF;
1216 else
1217 port.c_iflag &= ~IXOFF;
1219 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1220 int save_error=errno;
1221 COMM_SetCommError(handle,CE_IOE);
1222 close( fd );
1223 ERR("tcsetattr error '%s'\n", strerror(save_error));
1224 return FALSE;
1225 } else {
1226 COMM_SetCommError(handle,0);
1227 close( fd );
1228 return TRUE;
1233 /*****************************************************************************
1234 * GetCommState (KERNEL32.@)
1236 * Fills in a device control block with information from a communications device.
1238 * RETURNS
1240 * True on success, false if the communication device handle is bad etc
1242 * BUGS
1244 * XonChar and XoffChar are not set.
1246 BOOL WINAPI GetCommState(
1247 HANDLE handle, /* [in] The communications device. */
1248 LPDCB lpdcb) /* [out] The device control block. */
1250 struct termios port;
1251 int fd,speed;
1253 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1255 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1256 if (fd < 0)
1258 ERR("FILE_GetUnixHandle failed\n");
1259 return FALSE;
1261 if (tcgetattr(fd, &port) == -1) {
1262 int save_error=errno;
1263 ERR("tcgetattr error '%s'\n", strerror(save_error));
1264 COMM_SetCommError(handle,CE_IOE);
1265 close( fd );
1266 return FALSE;
1268 close( fd );
1269 #ifndef __EMX__
1270 #ifdef CBAUD
1271 speed= (port.c_cflag & CBAUD);
1272 #else
1273 speed= (cfgetospeed(&port));
1274 #endif
1275 switch (speed) {
1276 case B110:
1277 lpdcb->BaudRate = 110;
1278 break;
1279 case B300:
1280 lpdcb->BaudRate = 300;
1281 break;
1282 case B600:
1283 lpdcb->BaudRate = 600;
1284 break;
1285 case B1200:
1286 lpdcb->BaudRate = 1200;
1287 break;
1288 case B2400:
1289 lpdcb->BaudRate = 2400;
1290 break;
1291 case B4800:
1292 lpdcb->BaudRate = 4800;
1293 break;
1294 case B9600:
1295 lpdcb->BaudRate = 9600;
1296 break;
1297 case B19200:
1298 lpdcb->BaudRate = 19200;
1299 break;
1300 case B38400:
1301 lpdcb->BaudRate = 38400;
1302 break;
1303 #ifdef B57600
1304 case B57600:
1305 lpdcb->BaudRate = 57600;
1306 break;
1307 #endif
1308 #ifdef B115200
1309 case B115200:
1310 lpdcb->BaudRate = 115200;
1311 break;
1312 #endif
1313 #ifdef B230400
1314 case B230400:
1315 lpdcb->BaudRate = 230400;
1316 break;
1317 #endif
1318 #ifdef B460800
1319 case B460800:
1320 lpdcb->BaudRate = 460800;
1321 break;
1322 #endif
1323 default:
1324 ERR("unknown speed %x \n",speed);
1326 #endif
1327 switch (port.c_cflag & CSIZE) {
1328 case CS5:
1329 lpdcb->ByteSize = 5;
1330 break;
1331 case CS6:
1332 lpdcb->ByteSize = 6;
1333 break;
1334 case CS7:
1335 lpdcb->ByteSize = 7;
1336 break;
1337 case CS8:
1338 lpdcb->ByteSize = 8;
1339 break;
1340 default:
1341 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1344 if(port.c_iflag & INPCK)
1345 lpdcb->fParity = TRUE;
1346 else
1347 lpdcb->fParity = FALSE;
1348 #ifdef CMSPAR
1349 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1350 #else
1351 switch (port.c_cflag & (PARENB | PARODD))
1352 #endif
1354 case 0:
1355 lpdcb->Parity = NOPARITY;
1356 break;
1357 case PARENB:
1358 lpdcb->Parity = EVENPARITY;
1359 break;
1360 case (PARENB | PARODD):
1361 lpdcb->Parity = ODDPARITY;
1362 break;
1363 #ifdef CMSPAR
1364 case (PARENB | CMSPAR):
1365 lpdcb->Parity = MARKPARITY;
1366 break;
1367 case (PARENB | PARODD | CMSPAR):
1368 lpdcb->Parity = SPACEPARITY;
1369 break;
1370 #endif
1373 if (port.c_cflag & CSTOPB)
1374 if(lpdcb->ByteSize == 5)
1375 lpdcb->StopBits = ONE5STOPBITS;
1376 else
1377 lpdcb->StopBits = TWOSTOPBITS;
1378 else
1379 lpdcb->StopBits = ONESTOPBIT;
1381 lpdcb->fNull = 0;
1382 lpdcb->fBinary = 1;
1384 /* termios does not support DTR/DSR flow control */
1385 lpdcb->fOutxDsrFlow = 0;
1386 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1388 #ifdef CRTSCTS
1390 if (port.c_cflag & CRTSCTS) {
1391 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1392 lpdcb->fOutxCtsFlow = 1;
1393 } else
1394 #endif
1396 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1397 lpdcb->fOutxCtsFlow = 0;
1399 if (port.c_iflag & IXON)
1400 lpdcb->fInX = 1;
1401 else
1402 lpdcb->fInX = 0;
1404 if (port.c_iflag & IXOFF)
1405 lpdcb->fOutX = 1;
1406 else
1407 lpdcb->fOutX = 0;
1409 lpdcb->XonChar =
1410 lpdcb->XoffChar =
1412 lpdcb->XonLim = 10;
1413 lpdcb->XoffLim = 10;
1415 COMM_SetCommError(handle,0);
1417 TRACE("OK\n");
1419 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1420 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1421 (lpdcb->StopBits == ONESTOPBIT)?1:
1422 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1423 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1424 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1425 #ifdef CRTSCTS
1426 if ( lpdcb->fOutxCtsFlow ||
1427 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1429 TRACE("CRTSCTS\n");
1430 else
1432 TRACE("~CRTSCTS\n");
1434 #endif
1435 return TRUE;
1438 /*****************************************************************************
1439 * TransmitCommChar (KERNEL32.@)
1441 * Transmits a single character in front of any pending characters in the
1442 * output buffer. Usually used to send an interrupt character to a host.
1444 * RETURNS
1446 * True if the call succeeded, false if the previous command character to the
1447 * same device has not been sent yet the handle is bad etc.
1449 * BUGS
1451 * Stub.
1453 BOOL WINAPI TransmitCommChar(
1454 HANDLE hComm, /* [in] The communication device in need of a command character. */
1455 CHAR chTransmit) /* [in] The character to transmit. */
1457 BOOL r = FALSE;
1458 int fd;
1460 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1462 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1463 if ( fd < 0 )
1464 SetLastError ( ERROR_INVALID_PARAMETER );
1465 else
1467 r = (1 == write(fd, &chTransmit, 1));
1468 close(fd);
1471 return r;
1475 /*****************************************************************************
1476 * GetCommTimeouts (KERNEL32.@)
1478 * Obtains the request timeout values for the communications device.
1480 * RETURNS
1482 * True on success, false if communications device handle is bad
1483 * or the target structure is null.
1485 BOOL WINAPI GetCommTimeouts(
1486 HANDLE hComm, /* [in] The communications device. */
1487 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1489 BOOL ret;
1491 TRACE("(%p,%p)\n",hComm,lptimeouts);
1493 if(!lptimeouts)
1495 SetLastError(ERROR_INVALID_PARAMETER);
1496 return FALSE;
1499 SERVER_START_REQ( get_serial_info )
1501 req->handle = hComm;
1502 if ((ret = !wine_server_call_err( req )))
1504 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1505 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1506 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1507 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1508 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1511 SERVER_END_REQ;
1512 return ret;
1515 /*****************************************************************************
1516 * SetCommTimeouts (KERNEL32.@)
1518 * Sets the timeouts used when reading and writing data to/from COMM ports.
1520 * ReadIntervalTimeout
1521 * - converted and passes to linux kernel as c_cc[VTIME]
1522 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1523 * - used in ReadFile to calculate GetOverlappedResult's timeout
1524 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1525 * - used in WriteFile to calculate GetOverlappedResult's timeout
1527 * RETURNS
1529 * True if the timeouts were set, false otherwise.
1531 BOOL WINAPI SetCommTimeouts(
1532 HANDLE hComm, /* [in] handle of COMM device */
1533 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1535 BOOL ret;
1536 int fd;
1537 struct termios tios;
1539 TRACE("(%p,%p)\n",hComm,lptimeouts);
1541 if(!lptimeouts)
1543 SetLastError(ERROR_INVALID_PARAMETER);
1544 return FALSE;
1547 SERVER_START_REQ( set_serial_info )
1549 req->handle = hComm;
1550 req->flags = SERIALINFO_SET_TIMEOUTS;
1551 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1552 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1553 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1554 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1555 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1556 ret = !wine_server_call_err( req );
1558 SERVER_END_REQ;
1559 if (!ret) return FALSE;
1561 /* FIXME: move this stuff to the server */
1562 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1563 if (fd < 0) {
1564 FIXME("no fd for handle = %p!.\n",hComm);
1565 return FALSE;
1568 if (-1==tcgetattr(fd,&tios)) {
1569 FIXME("tcgetattr on fd %d failed!\n",fd);
1570 return FALSE;
1573 /* VTIME is in 1/10 seconds */
1575 unsigned int ux_timeout;
1577 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1579 ux_timeout = 0;
1581 else
1583 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1584 if(ux_timeout == 0)
1586 ux_timeout = 1; /* must be at least some timeout */
1589 tios.c_cc[VTIME] = ux_timeout;
1592 if (-1==tcsetattr(fd,0,&tios)) {
1593 FIXME("tcsetattr on fd %d failed!\n",fd);
1594 return FALSE;
1596 close(fd);
1597 return TRUE;
1600 /***********************************************************************
1601 * GetCommModemStatus (KERNEL32.@)
1603 * Obtains the four control register bits if supported by the hardware.
1605 * RETURNS
1607 * True if the communications handle was good and for hardware that
1608 * control register access, false otherwise.
1610 BOOL WINAPI GetCommModemStatus(
1611 HANDLE hFile, /* [in] The communications device. */
1612 LPDWORD lpModemStat) /* [out] The control register bits. */
1614 int fd,mstat, result=FALSE;
1616 *lpModemStat=0;
1617 #ifdef TIOCMGET
1618 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
1619 if(fd<0)
1620 return FALSE;
1621 result = ioctl(fd, TIOCMGET, &mstat);
1622 close(fd);
1623 if (result == -1)
1625 WARN("ioctl failed\n");
1626 return FALSE;
1628 #ifdef TIOCM_CTS
1629 if (mstat & TIOCM_CTS)
1630 *lpModemStat |= MS_CTS_ON;
1631 #endif
1632 #ifdef TIOCM_DSR
1633 if (mstat & TIOCM_DSR)
1634 *lpModemStat |= MS_DSR_ON;
1635 #endif
1636 #ifdef TIOCM_RNG
1637 if (mstat & TIOCM_RNG)
1638 *lpModemStat |= MS_RING_ON;
1639 #endif
1640 #ifdef TIOCM_CAR
1641 /*FIXME: Not really sure about RLSD UB 990810*/
1642 if (mstat & TIOCM_CAR)
1643 *lpModemStat |= MS_RLSD_ON;
1644 #endif
1645 TRACE("%04x -> %s%s%s%s\n", mstat,
1646 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1647 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1648 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1649 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1650 return TRUE;
1651 #else
1652 return FALSE;
1653 #endif
1656 /***********************************************************************
1657 * COMM_WaitCommEventService (INTERNAL)
1659 * This function is called while the client is waiting on the
1660 * server, so we can't make any server calls here.
1662 static void COMM_WaitCommEventService(async_private *ovp)
1664 async_commio *commio = (async_commio*) ovp;
1665 LPOVERLAPPED lpOverlapped = commio->lpOverlapped;
1667 TRACE("overlapped %p\n",lpOverlapped);
1669 /* FIXME: detect other events */
1670 *commio->buffer = EV_RXCHAR;
1672 lpOverlapped->Internal = STATUS_SUCCESS;
1676 /***********************************************************************
1677 * COMM_WaitCommEvent (INTERNAL)
1679 * This function must have an lpOverlapped.
1681 static BOOL COMM_WaitCommEvent(
1682 HANDLE hFile, /* [in] handle of comm port to wait for */
1683 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1684 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1686 int fd;
1687 async_commio *ovp;
1689 if(!lpOverlapped)
1691 SetLastError(ERROR_INVALID_PARAMETER);
1692 return FALSE;
1695 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1696 return FALSE;
1698 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
1699 if(fd<0)
1700 return FALSE;
1702 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1703 if(!ovp)
1705 close(fd);
1706 return FALSE;
1709 ovp->async.ops = &commio_async_ops;
1710 ovp->async.handle = hFile;
1711 ovp->async.fd = fd;
1712 ovp->async.type = ASYNC_TYPE_WAIT;
1713 ovp->async.func = COMM_WaitCommEventService;
1714 ovp->async.event = lpOverlapped->hEvent;
1715 ovp->lpOverlapped = lpOverlapped;
1716 ovp->buffer = (char *)lpdwEvents;
1718 lpOverlapped->InternalHigh = 0;
1719 lpOverlapped->Offset = 0;
1720 lpOverlapped->OffsetHigh = 0;
1722 if ( !register_new_async (&ovp->async) )
1723 SetLastError( ERROR_IO_PENDING );
1725 return FALSE;
1728 /***********************************************************************
1729 * WaitCommEvent (KERNEL32.@)
1731 * Wait until something interesting happens on a COMM port.
1732 * Interesting things (events) are set by calling SetCommMask before
1733 * this function is called.
1735 * RETURNS:
1736 * TRUE if successful
1737 * FALSE if failure
1739 * The set of detected events will be written to *lpdwEventMask
1740 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1742 * BUGS:
1743 * Only supports EV_RXCHAR and EV_TXEMPTY
1745 BOOL WINAPI WaitCommEvent(
1746 HANDLE hFile, /* [in] handle of comm port to wait for */
1747 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1748 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1750 OVERLAPPED ov;
1751 int ret;
1753 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1755 if(lpOverlapped)
1756 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1758 /* if there is no overlapped structure, create our own */
1759 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1761 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1763 if(GetLastError()!=STATUS_PENDING)
1765 CloseHandle(ov.hEvent);
1766 return FALSE;
1769 /* wait for the overlapped to complete */
1770 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1771 CloseHandle(ov.hEvent);
1773 return ret;
1776 /***********************************************************************
1777 * GetCommProperties (KERNEL32.@)
1779 * This function fills in a structure with the capabilities of the
1780 * communications port driver.
1782 * RETURNS
1784 * TRUE on success, FALSE on failure
1785 * If successful, the lpCommProp structure be filled in with
1786 * properties of the comm port.
1788 BOOL WINAPI GetCommProperties(
1789 HANDLE hFile, /* [in] handle of the comm port */
1790 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1792 FIXME("(%p %p )\n",hFile,lpCommProp);
1793 if(!lpCommProp)
1794 return FALSE;
1797 * These values should be valid for LINUX's serial driver
1798 * FIXME: Perhaps they deserve an #ifdef LINUX
1800 memset(lpCommProp,0,sizeof(COMMPROP));
1801 lpCommProp->wPacketLength = 1;
1802 lpCommProp->wPacketVersion = 1;
1803 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1804 lpCommProp->dwReserved1 = 0;
1805 lpCommProp->dwMaxTxQueue = 4096;
1806 lpCommProp->dwMaxRxQueue = 4096;
1807 lpCommProp->dwMaxBaud = BAUD_115200;
1808 lpCommProp->dwProvSubType = PST_RS232;
1809 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1810 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1811 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1812 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1813 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1814 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1815 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1816 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1817 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1818 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1819 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1821 return TRUE;
1824 /***********************************************************************
1825 * FIXME:
1826 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1827 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1828 * This is dependent on the type of COMM port, but since it is doubtful
1829 * anybody will get around to implementing support for fancy serial
1830 * ports in WINE, this is hardcoded for the time being. The name of
1831 * this DLL should be stored in and read from the system registry in
1832 * the hive HKEY_LOCAL_MACHINE, key
1833 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1834 * where ???? is the port number... that is determined by PNP
1835 * The DLL should be loaded when the COMM port is opened, and closed
1836 * when the COMM port is closed. - MJM 20 June 2000
1837 ***********************************************************************/
1838 static CHAR lpszSerialUI[] = "serialui.dll";
1841 /***********************************************************************
1842 * CommConfigDialogA (KERNEL32.@)
1844 * Raises a dialog that allows the user to configure a comm port.
1845 * Fills the COMMCONFIG struct with information specified by the user.
1846 * This function should call a similar routine in the COMM driver...
1848 * RETURNS
1850 * TRUE on success, FALSE on failure
1851 * If successful, the lpCommConfig structure will contain a new
1852 * configuration for the comm port, as specified by the user.
1854 * BUGS
1855 * The library with the CommConfigDialog code is never unloaded.
1856 * Perhaps this should be done when the comm port is closed?
1858 BOOL WINAPI CommConfigDialogA(
1859 LPCSTR lpszDevice, /* [in] name of communications device */
1860 HANDLE hWnd, /* [in] parent window for the dialog */
1861 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1863 FARPROC lpfnCommDialog;
1864 HMODULE hConfigModule;
1865 BOOL r;
1867 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
1869 hConfigModule = LoadLibraryA(lpszSerialUI);
1870 if(!hConfigModule)
1871 return FALSE;
1873 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
1875 if(!lpfnCommDialog)
1876 return FALSE;
1878 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1880 /* UnloadLibrary(hConfigModule); */
1882 return r;
1885 /***********************************************************************
1886 * CommConfigDialogW (KERNEL32.@)
1888 * see CommConfigDialogA for more info
1890 BOOL WINAPI CommConfigDialogW(
1891 LPCWSTR lpszDevice, /* [in] name of communications device */
1892 HANDLE hWnd, /* [in] parent window for the dialog */
1893 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1895 BOOL r;
1896 LPSTR lpDeviceA;
1898 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1899 if(lpDeviceA)
1900 return FALSE;
1901 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
1902 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1903 return r;
1906 /***********************************************************************
1907 * GetCommConfig (KERNEL32.@)
1909 * Fill in the COMMCONFIG structure for the comm port hFile
1911 * RETURNS
1913 * TRUE on success, FALSE on failure
1914 * If successful, lpCommConfig contains the comm port configuration.
1916 * BUGS
1919 BOOL WINAPI GetCommConfig(
1920 HANDLE hFile, /* [in] The communications device. */
1921 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1922 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1923 afterwards the number of bytes copied to the buffer or
1924 the needed size of the buffer. */
1926 BOOL r;
1928 TRACE("(%p %p)\n",hFile,lpCommConfig);
1930 if(lpCommConfig == NULL)
1931 return FALSE;
1933 r = *lpdwSize < sizeof(COMMCONFIG);
1934 *lpdwSize = sizeof(COMMCONFIG);
1935 if(!r)
1936 return FALSE;
1938 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1939 lpCommConfig->wVersion = 1;
1940 lpCommConfig->wReserved = 0;
1941 r = GetCommState(hFile,&lpCommConfig->dcb);
1942 lpCommConfig->dwProviderSubType = PST_RS232;
1943 lpCommConfig->dwProviderOffset = 0;
1944 lpCommConfig->dwProviderSize = 0;
1946 return r;
1949 /***********************************************************************
1950 * SetCommConfig (KERNEL32.@)
1952 * Sets the configuration of the communications device.
1954 * RETURNS
1956 * True on success, false if the handle was bad is not a communications device.
1958 BOOL WINAPI SetCommConfig(
1959 HANDLE hFile, /* [in] The communications device. */
1960 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1961 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1963 TRACE("(%p %p)\n",hFile,lpCommConfig);
1964 return SetCommState(hFile,&lpCommConfig->dcb);
1967 /***********************************************************************
1968 * SetDefaultCommConfigA (KERNEL32.@)
1970 * Initializes the default configuration for the specified communication
1971 * device. (ascii)
1973 * RETURNS
1975 * True if the device was found and the defaults set, false otherwise
1977 BOOL WINAPI SetDefaultCommConfigA(
1978 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1979 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1980 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1982 FARPROC lpfnSetDefaultCommConfig;
1983 HMODULE hConfigModule;
1984 BOOL r;
1986 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1988 hConfigModule = LoadLibraryA(lpszSerialUI);
1989 if(!hConfigModule)
1990 return FALSE;
1992 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
1994 if(! lpfnSetDefaultCommConfig)
1995 return TRUE;
1997 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1999 /* UnloadLibrary(hConfigModule); */
2001 return r;
2005 /***********************************************************************
2006 * SetDefaultCommConfigW (KERNEL32.@)
2008 * Initializes the default configuration for the specified
2009 * communication device. (unicode)
2011 * RETURNS
2014 BOOL WINAPI SetDefaultCommConfigW(
2015 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2016 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2017 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2019 BOOL r;
2020 LPSTR lpDeviceA;
2022 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2024 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2025 if(lpDeviceA)
2026 return FALSE;
2027 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2028 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2029 return r;
2033 /***********************************************************************
2034 * GetDefaultCommConfigA (KERNEL32.@)
2036 * Acquires the default configuration of the specified communication device. (unicode)
2038 * RETURNS
2040 * True on successful reading of the default configuration,
2041 * if the device is not found or the buffer is too small.
2043 BOOL WINAPI GetDefaultCommConfigA(
2044 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2045 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2046 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2047 afterwards the number of bytes copied to the buffer or
2048 the needed size of the buffer. */
2050 LPDCB lpdcb = &(lpCC->dcb);
2051 char temp[40];
2053 if (strncasecmp(lpszName,"COM",3)) {
2054 ERR("not implemented for <%s>\n", lpszName);
2055 return FALSE;
2058 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2059 if (*lpdwSize < sizeof(COMMCONFIG)) {
2060 *lpdwSize = sizeof(COMMCONFIG);
2061 return FALSE;
2064 *lpdwSize = sizeof(COMMCONFIG);
2066 lpCC->dwSize = sizeof(COMMCONFIG);
2067 lpCC->wVersion = 1;
2068 lpCC->dwProviderSubType = PST_RS232;
2069 lpCC->dwProviderOffset = 0L;
2070 lpCC->dwProviderSize = 0L;
2072 sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2073 FIXME("setting %s as default\n", temp);
2075 return BuildCommDCBA( temp, lpdcb);
2078 /**************************************************************************
2079 * GetDefaultCommConfigW (KERNEL32.@)
2081 * Acquires the default configuration of the specified communication device. (unicode)
2083 * RETURNS
2085 * True on successful reading of the default configuration,
2086 * if the device is not found or the buffer is too small.
2088 BOOL WINAPI GetDefaultCommConfigW(
2089 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2090 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2091 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2092 afterwards the number of bytes copied to the buffer or
2093 the needed size of the buffer. */
2095 BOOL ret = FALSE;
2096 LPSTR lpszNameA;
2098 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2099 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2100 if (lpszNameA)
2102 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2103 HeapFree( GetProcessHeap(), 0, lpszNameA );
2105 return ret;