Portability fixes.
[wine/gsoc_dplay.git] / dlls / kernel / comm.c
blobfc98f98635dd3b5e334d43a0e8608924f85076e6
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 #include <unistd.h>
75 #include <sys/poll.h>
76 #ifdef HAVE_SYS_MODEM_H
77 # include <sys/modem.h>
78 #endif
79 #ifdef HAVE_SYS_STRTIO_H
80 # include <sys/strtio.h>
81 #endif
83 #include "winbase.h"
84 #include "winerror.h"
86 #include "wine/server.h"
87 #include "async.h"
88 #include "file.h"
89 #include "heap.h"
91 #include "wine/debug.h"
93 #ifdef HAVE_LINUX_SERIAL_H
94 #include <linux/serial.h>
95 #endif
97 WINE_DEFAULT_DEBUG_CHANNEL(comm);
99 /***********************************************************************
100 * Asynchronous I/O for asynchronous wait requests *
103 static DWORD commio_get_async_status (const async_private *ovp);
104 static DWORD commio_get_async_count (const async_private *ovp);
105 static void commio_set_async_status (async_private *ovp, const DWORD status);
106 static void commio_async_cleanup (async_private *ovp);
108 static async_ops commio_async_ops =
110 commio_get_async_status, /* get_status */
111 commio_set_async_status, /* set_status */
112 commio_get_async_count, /* get_count */
113 NULL, /* call_completion */
114 commio_async_cleanup /* cleanup */
117 typedef struct async_commio
119 struct async_private async;
120 LPOVERLAPPED lpOverlapped;
121 char *buffer;
122 } async_commio;
124 static DWORD commio_get_async_status (const struct async_private *ovp)
126 return ((async_commio*) ovp)->lpOverlapped->Internal;
129 static void commio_set_async_status (async_private *ovp, const DWORD status)
131 ((async_commio*) ovp)->lpOverlapped->Internal = status;
134 static DWORD commio_get_async_count (const struct async_private *ovp)
136 return 0;
139 static void commio_async_cleanup (async_private *ovp)
141 HeapFree(GetProcessHeap(), 0, ovp );
144 /***********************************************************************/
146 #if !defined(TIOCINQ) && defined(FIONREAD)
147 #define TIOCINQ FIONREAD
148 #endif
150 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
152 #ifdef TIOCMGET
153 unsigned int mstat, okay;
154 okay = ioctl(fd, TIOCMGET, &mstat);
155 if (okay) return okay;
156 if (andy) mstat &= andy;
157 mstat |= orrie;
158 return ioctl(fd, TIOCMSET, &mstat);
159 #else
160 return 0;
161 #endif
164 /***********************************************************************
165 * COMM_BuildOldCommDCB (Internal)
167 * Build a DCB using the old style settings string eg: "COMx:96,n,8,1"
168 * We ignore the COM port index, since we can support more than 4 ports.
170 BOOL WINAPI COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
172 /* "COM1:96,n,8,1" */
173 /* 012345 */
174 char *ptr, temp[256], last;
175 int rate;
177 TRACE("(%s), ptr %p\n", device, lpdcb);
179 /* Some applications call this function with "9600,n,8,1"
180 * not sending the "COM1:" parameter at left of string */
181 if (!strncasecmp(device,"COM",3))
183 if (!device[3]) return FALSE;
184 if (device[4] != ':' && device[4] != ' ') return FALSE;
185 strcpy(temp,device+5);
187 else strcpy(temp,device);
189 last=temp[strlen(temp)-1];
190 ptr = strtok(temp, ", ");
192 /* DOS/Windows only compares the first two numbers
193 * and assigns an appropriate baud rate.
194 * You can supply 961324245, it still returns 9600 ! */
195 if (strlen(ptr) < 2)
197 WARN("Unknown baudrate string '%s' !\n", ptr);
198 return FALSE; /* error: less than 2 chars */
200 ptr[2] = '\0';
201 rate = atoi(ptr);
203 switch (rate) {
204 case 11:
205 case 30:
206 case 60:
207 rate *= 10;
208 break;
209 case 12:
210 case 24:
211 case 48:
212 case 96:
213 rate *= 100;
214 break;
215 case 19:
216 rate = 19200;
217 break;
218 default:
219 WARN("Unknown baudrate indicator %d !\n", rate);
220 return FALSE;
223 lpdcb->BaudRate = rate;
224 TRACE("baudrate (%ld)\n", lpdcb->BaudRate);
226 ptr = strtok(NULL, ", ");
227 if (islower(*ptr))
228 *ptr = toupper(*ptr);
230 TRACE("parity (%c)\n", *ptr);
231 lpdcb->fParity = TRUE;
232 switch (*ptr) {
233 case 'N':
234 lpdcb->Parity = NOPARITY;
235 lpdcb->fParity = FALSE;
236 break;
237 case 'E':
238 lpdcb->Parity = EVENPARITY;
239 break;
240 case 'M':
241 lpdcb->Parity = MARKPARITY;
242 break;
243 case 'O':
244 lpdcb->Parity = ODDPARITY;
245 break;
246 case 'S':
247 lpdcb->Parity = SPACEPARITY;
248 break;
249 default:
250 WARN("Unknown parity `%c'!\n", *ptr);
251 return FALSE;
254 ptr = strtok(NULL, ", ");
255 TRACE("charsize (%c)\n", *ptr);
256 lpdcb->ByteSize = *ptr - '0';
258 ptr = strtok(NULL, ", ");
259 TRACE("stopbits (%c)\n", *ptr);
260 switch (*ptr) {
261 case '1':
262 lpdcb->StopBits = ONESTOPBIT;
263 break;
264 case '2':
265 lpdcb->StopBits = TWOSTOPBITS;
266 break;
267 default:
268 WARN("Unknown # of stopbits `%c'!\n", *ptr);
269 return FALSE;
272 if (last == 'x') {
273 lpdcb->fInX = TRUE;
274 lpdcb->fOutX = TRUE;
275 lpdcb->fOutxCtsFlow = FALSE;
276 lpdcb->fOutxDsrFlow = FALSE;
277 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
278 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
279 } else if (last=='p') {
280 lpdcb->fInX = FALSE;
281 lpdcb->fOutX = FALSE;
282 lpdcb->fOutxCtsFlow = TRUE;
283 lpdcb->fOutxDsrFlow = FALSE;
284 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
285 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
286 } else {
287 lpdcb->fInX = FALSE;
288 lpdcb->fOutX = FALSE;
289 lpdcb->fOutxCtsFlow = FALSE;
290 lpdcb->fOutxDsrFlow = FALSE;
291 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
292 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
295 return TRUE;
298 /**************************************************************************
299 * BuildCommDCBA (KERNEL32.@)
301 * Updates a device control block data structure with values from an
302 * ascii device control string. The device control string has two forms
303 * normal and extended, it must be exclusively in one or the other form.
305 * RETURNS
307 * True on success, false on a malformed control string.
309 BOOL WINAPI BuildCommDCBA(
310 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
311 LPDCB lpdcb) /* [out] The device control block to be updated. */
313 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
316 /**************************************************************************
317 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
319 * Updates a device control block data structure with values from an
320 * ascii device control string. Taking timeout values from a timeouts
321 * struct if desired by the control string.
323 * RETURNS
325 * True on success, false bad handles etc
327 BOOL WINAPI BuildCommDCBAndTimeoutsA(
328 LPCSTR device, /* [in] The ascii device control string. */
329 LPDCB lpdcb, /* [out] The device control block to be updated. */
330 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
332 int port;
333 char *ptr,*temp;
335 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
337 if (!strncasecmp(device,"COM",3)) {
338 port=device[3]-'0';
339 if (port--==0) {
340 ERR("BUG! COM0 can't exist!\n");
341 return FALSE;
343 if ((*(device+4)!=':') && (*(device+4)!=' '))
344 return FALSE;
345 temp=(LPSTR)(device+5);
346 } else
347 temp=(LPSTR)device;
349 memset(lpdcb,0,sizeof (DCB));
350 lpdcb->DCBlength = sizeof(DCB);
351 if (strchr(temp,',')) { /* old style */
353 return COMM_BuildOldCommDCB(device,lpdcb);
355 ptr=strtok(temp," ");
356 while (ptr) {
357 DWORD flag,x;
359 flag=0;
360 if (!strncmp("baud=",ptr,5)) {
361 if (!sscanf(ptr+5,"%ld",&x))
362 WARN("Couldn't parse %s\n",ptr);
363 lpdcb->BaudRate = x;
364 flag=1;
366 if (!strncmp("stop=",ptr,5)) {
367 if (!sscanf(ptr+5,"%ld",&x))
368 WARN("Couldn't parse %s\n",ptr);
369 lpdcb->StopBits = x;
370 flag=1;
372 if (!strncmp("data=",ptr,5)) {
373 if (!sscanf(ptr+5,"%ld",&x))
374 WARN("Couldn't parse %s\n",ptr);
375 lpdcb->ByteSize = x;
376 flag=1;
378 if (!strncmp("parity=",ptr,7)) {
379 lpdcb->fParity = TRUE;
380 switch (ptr[7]) {
381 case 'N':case 'n':
382 lpdcb->fParity = FALSE;
383 lpdcb->Parity = NOPARITY;
384 break;
385 case 'E':case 'e':
386 lpdcb->Parity = EVENPARITY;
387 break;
388 case 'O':case 'o':
389 lpdcb->Parity = ODDPARITY;
390 break;
391 case 'M':case 'm':
392 lpdcb->Parity = MARKPARITY;
393 break;
394 case 'S':case 's':
395 lpdcb->Parity = SPACEPARITY;
396 break;
398 flag=1;
400 if (!flag)
401 ERR("Unhandled specifier '%s', please report.\n",ptr);
402 ptr=strtok(NULL," ");
404 if (lpdcb->BaudRate==110)
405 lpdcb->StopBits = 2;
406 return TRUE;
409 /**************************************************************************
410 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
412 * Updates a device control block data structure with values from an
413 * unicode device control string. Taking timeout values from a timeouts
414 * struct if desired by the control string.
416 * RETURNS
418 * True on success, false bad handles etc.
420 BOOL WINAPI BuildCommDCBAndTimeoutsW(
421 LPCWSTR devid, /* [in] The unicode device control string. */
422 LPDCB lpdcb, /* [out] The device control block to be updated. */
423 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
425 BOOL ret = FALSE;
426 LPSTR devidA;
428 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
429 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
430 if (devidA)
432 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
433 HeapFree( GetProcessHeap(), 0, devidA );
435 return ret;
438 /**************************************************************************
439 * BuildCommDCBW (KERNEL32.@)
441 * Updates a device control block structure with values from an
442 * unicode device control string. The device control string has two forms
443 * normal and extended, it must be exclusively in one or the other form.
445 * RETURNS
447 * True on success, false on an malformed control string.
449 BOOL WINAPI BuildCommDCBW(
450 LPCWSTR devid, /* [in] The unicode device control string. */
451 LPDCB lpdcb) /* [out] The device control block to be updated. */
453 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
456 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
458 DWORD ret;
460 SERVER_START_REQ( set_serial_info )
462 req->handle = handle;
463 req->flags = SERIALINFO_SET_ERROR;
464 req->commerror = error;
465 ret = !wine_server_call_err( req );
467 SERVER_END_REQ;
468 return ret;
471 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
473 DWORD ret;
475 if(!lperror)
476 return FALSE;
478 SERVER_START_REQ( get_serial_info )
480 req->handle = handle;
481 ret = !wine_server_call_err( req );
482 *lperror = reply->commerror;
484 SERVER_END_REQ;
486 return ret;
489 /*****************************************************************************
490 * SetCommBreak (KERNEL32.@)
492 * Halts the transmission of characters to a communications device.
494 * RETURNS
496 * True on success, and false if the communications device could not be found,
497 * the control is not supported.
499 * BUGS
501 * Only TIOCSBRK and TIOCCBRK are supported.
503 BOOL WINAPI SetCommBreak(
504 HANDLE handle) /* [in] The communictions device to suspend. */
506 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
507 int fd,result;
509 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
510 if(fd<0) {
511 TRACE("FILE_GetUnixHandle failed\n");
512 return FALSE;
514 result = ioctl(fd,TIOCSBRK,0);
515 close(fd);
516 if (result ==-1)
518 TRACE("ioctl failed\n");
519 SetLastError(ERROR_NOT_SUPPORTED);
520 return FALSE;
522 return TRUE;
523 #else
524 FIXME("ioctl not available\n");
525 SetLastError(ERROR_NOT_SUPPORTED);
526 return FALSE;
527 #endif
530 /*****************************************************************************
531 * ClearCommBreak (KERNEL32.@)
533 * Resumes character transmission from a communication device.
535 * RETURNS
537 * True on success and false if the communications device could not be found.
539 * BUGS
541 * Only TIOCSBRK and TIOCCBRK are supported.
543 BOOL WINAPI ClearCommBreak(
544 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
546 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
547 int fd,result;
549 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
550 if(fd<0) {
551 TRACE("FILE_GetUnixHandle failed\n");
552 return FALSE;
554 result = ioctl(fd,TIOCCBRK,0);
555 close(fd);
556 if (result ==-1)
558 TRACE("ioctl failed\n");
559 SetLastError(ERROR_NOT_SUPPORTED);
560 return FALSE;
562 return TRUE;
563 #else
564 FIXME("ioctl not available\n");
565 SetLastError(ERROR_NOT_SUPPORTED);
566 return FALSE;
567 #endif
570 /*****************************************************************************
571 * EscapeCommFunction (KERNEL32.@)
573 * Directs a communication device to perform an extended function.
575 * RETURNS
577 * True or requested data on successful completion of the command,
578 * false if the device is not present cannot execute the command
579 * or the command failed.
581 BOOL WINAPI EscapeCommFunction(
582 HANDLE handle, /* [in] The communication device to perform the extended function. */
583 UINT nFunction) /* [in] The extended function to be performed. */
585 int fd,direct=FALSE,result=FALSE;
586 struct termios port;
588 TRACE("handle %d, function=%d\n", handle, nFunction);
589 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
590 if(fd<0) {
591 FIXME("handle %d not found.\n",handle);
592 return FALSE;
595 if (tcgetattr(fd,&port) == -1) {
596 COMM_SetCommError(handle,CE_IOE);
597 close(fd);
598 return FALSE;
601 switch (nFunction) {
602 case RESETDEV:
603 TRACE("\n");
604 break;
606 case CLRDTR:
607 TRACE("CLRDTR\n");
608 #ifdef TIOCM_DTR
609 direct=TRUE;
610 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
611 break;
612 #endif
614 case CLRRTS:
615 TRACE("CLRRTS\n");
616 #ifdef TIOCM_RTS
617 direct=TRUE;
618 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
619 break;
620 #endif
622 case SETDTR:
623 TRACE("SETDTR\n");
624 #ifdef TIOCM_DTR
625 direct=TRUE;
626 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
627 break;
628 #endif
630 case SETRTS:
631 TRACE("SETRTS\n");
632 #ifdef TIOCM_RTS
633 direct=TRUE;
634 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
635 break;
636 #endif
638 case SETXOFF:
639 TRACE("SETXOFF\n");
640 port.c_iflag |= IXOFF;
641 break;
643 case SETXON:
644 TRACE("SETXON\n");
645 port.c_iflag |= IXON;
646 break;
647 case SETBREAK:
648 TRACE("setbreak\n");
649 #ifdef TIOCSBRK
650 direct=TRUE;
651 result = ioctl(fd,TIOCSBRK,0);
652 break;
653 #endif
654 case CLRBREAK:
655 TRACE("clrbreak\n");
656 #ifdef TIOCSBRK
657 direct=TRUE;
658 result = ioctl(fd,TIOCCBRK,0);
659 break;
660 #endif
661 default:
662 WARN("(handle=%d,nFunction=%d): Unknown function\n",
663 handle, nFunction);
664 break;
667 if (!direct)
668 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
669 close(fd);
670 COMM_SetCommError(handle,CE_IOE);
671 return FALSE;
672 } else
673 result= TRUE;
674 else
676 if (result == -1)
678 result= FALSE;
679 COMM_SetCommError(handle,CE_IOE);
681 else
682 result = TRUE;
684 close(fd);
685 return result;
688 /********************************************************************
689 * PurgeComm (KERNEL32.@)
691 * Terminates pending operations and/or discards buffers on a
692 * communication resource.
694 * RETURNS
696 * True on success and false if the communications handle is bad.
698 BOOL WINAPI PurgeComm(
699 HANDLE handle, /* [in] The communication resource to be purged. */
700 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
702 int fd;
704 TRACE("handle %d, flags %lx\n", handle, flags);
706 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
707 if(fd<0) {
708 FIXME("no handle %d found\n",handle);
709 return FALSE;
713 ** not exactly sure how these are different
714 ** Perhaps if we had our own internal queues, one flushes them
715 ** and the other flushes the kernel's buffers.
717 if(flags&PURGE_TXABORT)
718 tcflush(fd,TCOFLUSH);
719 if(flags&PURGE_RXABORT)
720 tcflush(fd,TCIFLUSH);
721 if(flags&PURGE_TXCLEAR)
722 tcflush(fd,TCOFLUSH);
723 if(flags&PURGE_RXCLEAR)
724 tcflush(fd,TCIFLUSH);
725 close(fd);
727 return 1;
730 /*****************************************************************************
731 * ClearCommError (KERNEL32.@)
733 * Enables further I/O operations on a communications resource after
734 * supplying error and current status information.
736 * RETURNS
738 * True on success, false if the communication resource handle is bad.
740 BOOL WINAPI ClearCommError(
741 HANDLE handle, /* [in] The communication resource with the error. */
742 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
743 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
745 int fd;
747 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
748 if(0>fd)
750 FIXME("no handle %d found\n",handle);
751 return FALSE;
754 if (lpStat)
756 lpStat->status = 0;
758 #ifdef TIOCOUTQ
759 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
760 WARN("ioctl returned error\n");
761 #else
762 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
763 #endif
765 #ifdef TIOCINQ
766 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
767 WARN("ioctl returned error\n");
768 #endif
770 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
771 handle, lpStat->cbInQue, lpStat->cbOutQue);
774 close(fd);
776 COMM_GetCommError(handle, errors);
777 COMM_SetCommError(handle, 0);
779 return TRUE;
782 /*****************************************************************************
783 * SetupComm (KERNEL32.@)
785 * Called after CreateFile to hint to the communication resource to use
786 * specified sizes for input and output buffers rather than the default values.
788 * RETURNS
790 * True if successful, false if the communications resource handle is bad.
792 * BUGS
794 * Stub.
796 BOOL WINAPI SetupComm(
797 HANDLE handle, /* [in] The just created communication resource handle. */
798 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
799 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
801 int fd;
803 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
804 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
805 if(0>fd) {
806 FIXME("handle %d not found?\n",handle);
807 return FALSE;
809 close(fd);
810 return TRUE;
813 /*****************************************************************************
814 * GetCommMask (KERNEL32.@)
816 * Obtain the events associated with a communication device that will cause
817 * a call WaitCommEvent to return.
819 * RETURNS
821 * True on success, fail on bad device handle etc.
823 BOOL WINAPI GetCommMask(
824 HANDLE handle, /* [in] The communications device. */
825 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
827 BOOL ret;
829 TRACE("handle %d, mask %p\n", handle, evtmask);
831 SERVER_START_REQ( get_serial_info )
833 req->handle = handle;
834 if ((ret = !wine_server_call_err( req )))
836 if (evtmask) *evtmask = reply->eventmask;
839 SERVER_END_REQ;
840 return ret;
843 /*****************************************************************************
844 * SetCommMask (KERNEL32.@)
846 * There be some things we need to hear about yon there communications device.
847 * (Set which events associated with a communication device should cause
848 * a call WaitCommEvent to return.)
850 * RETURNS
852 * True on success, false on bad handle etc.
854 BOOL WINAPI SetCommMask(
855 HANDLE handle, /* [in] The communications device. */
856 DWORD evtmask) /* [in] The events that are to be monitored. */
858 BOOL ret;
860 TRACE("handle %d, mask %lx\n", handle, evtmask);
862 SERVER_START_REQ( set_serial_info )
864 req->handle = handle;
865 req->flags = SERIALINFO_SET_MASK;
866 req->eventmask = evtmask;
867 ret = !wine_server_call_err( req );
869 SERVER_END_REQ;
870 return ret;
873 /*****************************************************************************
874 * SetCommState (KERNEL32.@)
876 * Re-initializes all hardware and control settings of a communications device,
877 * with values from a device control block without effecting the input and output
878 * queues.
880 * RETURNS
882 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
884 BOOL WINAPI SetCommState(
885 HANDLE handle, /* [in] The communications device. */
886 LPDCB lpdcb) /* [out] The device control block. */
888 struct termios port;
889 int fd, bytesize, stopbits;
891 TRACE("handle %d, ptr %p\n", handle, lpdcb);
892 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
893 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
894 (lpdcb->StopBits == ONESTOPBIT)?1:
895 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
896 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
897 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
899 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
900 if (fd < 0) {
901 FIXME("no handle %d found\n",handle);
902 return FALSE;
905 if ((tcgetattr(fd,&port)) == -1) {
906 int save_error = errno;
907 COMM_SetCommError(handle,CE_IOE);
908 close( fd );
909 ERR("tcgetattr error '%s'\n", strerror(save_error));
910 return FALSE;
913 port.c_cc[VMIN] = 0;
914 port.c_cc[VTIME] = 1;
916 #ifdef IMAXBEL
917 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
918 #else
919 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
920 #endif
921 port.c_iflag |= (IGNBRK);
923 port.c_oflag &= ~(OPOST);
925 port.c_cflag &= ~(HUPCL);
926 port.c_cflag |= CLOCAL | CREAD;
928 port.c_lflag &= ~(ICANON|ECHO|ISIG);
929 port.c_lflag |= NOFLSH;
931 #ifdef CBAUD
932 port.c_cflag &= ~CBAUD;
933 switch (lpdcb->BaudRate) {
934 case 110:
935 case CBR_110:
936 port.c_cflag |= B110;
937 break;
938 case 300:
939 case CBR_300:
940 port.c_cflag |= B300;
941 break;
942 case 600:
943 case CBR_600:
944 port.c_cflag |= B600;
945 break;
946 case 1200:
947 case CBR_1200:
948 port.c_cflag |= B1200;
949 break;
950 case 2400:
951 case CBR_2400:
952 port.c_cflag |= B2400;
953 break;
954 case 4800:
955 case CBR_4800:
956 port.c_cflag |= B4800;
957 break;
958 case 9600:
959 case CBR_9600:
960 port.c_cflag |= B9600;
961 break;
962 case 19200:
963 case CBR_19200:
964 port.c_cflag |= B19200;
965 break;
966 case 38400:
967 case CBR_38400:
968 port.c_cflag |= B38400;
969 break;
970 #ifdef B57600
971 case 57600:
972 port.c_cflag |= B57600;
973 break;
974 #endif
975 #ifdef B115200
976 case 115200:
977 port.c_cflag |= B115200;
978 break;
979 #endif
980 #ifdef B230400
981 case 230400:
982 port.c_cflag |= B230400;
983 break;
984 #endif
985 #ifdef B460800
986 case 460800:
987 port.c_cflag |= B460800;
988 break;
989 #endif
990 default:
991 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
992 { struct serial_struct nuts;
993 int arby;
994 ioctl(fd, TIOCGSERIAL, &nuts);
995 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
996 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
997 arby = nuts.baud_base / nuts.custom_divisor;
998 nuts.flags &= ~ASYNC_SPD_MASK;
999 nuts.flags |= ASYNC_SPD_CUST;
1000 WARN("You (or a program acting at your behest) have specified\n"
1001 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1002 "which is as close as we can get by our present understanding of your\n"
1003 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1004 "has caused to your linux system can be undone with setserial \n"
1005 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1006 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1007 ioctl(fd, TIOCSSERIAL, &nuts);
1008 port.c_cflag |= B38400;
1010 break;
1011 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1014 COMM_SetCommError(handle,IE_BAUDRATE);
1015 close( fd );
1016 ERR("baudrate %ld\n",lpdcb->BaudRate);
1017 return FALSE;
1019 #elif !defined(__EMX__)
1020 switch (lpdcb->BaudRate) {
1021 case 110:
1022 case CBR_110:
1023 port.c_ospeed = B110;
1024 break;
1025 case 300:
1026 case CBR_300:
1027 port.c_ospeed = B300;
1028 break;
1029 case 600:
1030 case CBR_600:
1031 port.c_ospeed = B600;
1032 break;
1033 case 1200:
1034 case CBR_1200:
1035 port.c_ospeed = B1200;
1036 break;
1037 case 2400:
1038 case CBR_2400:
1039 port.c_ospeed = B2400;
1040 break;
1041 case 4800:
1042 case CBR_4800:
1043 port.c_ospeed = B4800;
1044 break;
1045 case 9600:
1046 case CBR_9600:
1047 port.c_ospeed = B9600;
1048 break;
1049 case 19200:
1050 case CBR_19200:
1051 port.c_ospeed = B19200;
1052 break;
1053 case 38400:
1054 case CBR_38400:
1055 port.c_ospeed = B38400;
1056 break;
1057 #ifdef B57600
1058 case 57600:
1059 case CBR_57600:
1060 port.c_cflag |= B57600;
1061 break;
1062 #endif
1063 #ifdef B115200
1064 case 115200:
1065 case CBR_115200:
1066 port.c_cflag |= B115200;
1067 break;
1068 #endif
1069 #ifdef B230400
1070 case 230400:
1071 port.c_cflag |= B230400;
1072 break;
1073 #endif
1074 #ifdef B460800
1075 case 460800:
1076 port.c_cflag |= B460800;
1077 break;
1078 #endif
1079 default:
1080 COMM_SetCommError(handle,IE_BAUDRATE);
1081 close( fd );
1082 ERR("baudrate %ld\n",lpdcb->BaudRate);
1083 return FALSE;
1085 port.c_ispeed = port.c_ospeed;
1086 #endif
1087 bytesize=lpdcb->ByteSize;
1088 stopbits=lpdcb->StopBits;
1090 #ifdef CMSPAR
1091 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1092 #else
1093 port.c_cflag &= ~(PARENB | PARODD);
1094 #endif
1095 if (lpdcb->fParity)
1096 port.c_iflag |= INPCK;
1097 else
1098 port.c_iflag &= ~INPCK;
1099 switch (lpdcb->Parity) {
1100 case NOPARITY:
1101 break;
1102 case ODDPARITY:
1103 port.c_cflag |= (PARENB | PARODD);
1104 break;
1105 case EVENPARITY:
1106 port.c_cflag |= PARENB;
1107 break;
1108 #ifdef CMSPAR
1109 /* Linux defines mark/space (stick) parity */
1110 case MARKPARITY:
1111 port.c_cflag |= (PARENB | CMSPAR);
1112 break;
1113 case SPACEPARITY:
1114 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1115 break;
1116 #else
1117 /* try the POSIX way */
1118 case MARKPARITY:
1119 if( stopbits == ONESTOPBIT) {
1120 stopbits = TWOSTOPBITS;
1121 port.c_iflag &= ~INPCK;
1122 } else {
1123 COMM_SetCommError(handle,IE_BYTESIZE);
1124 close( fd );
1125 ERR("Cannot set MARK Parity\n");
1126 return FALSE;
1128 break;
1129 case SPACEPARITY:
1130 if( bytesize < 8) {
1131 bytesize +=1;
1132 port.c_iflag &= ~INPCK;
1133 } else {
1134 COMM_SetCommError(handle,IE_BYTESIZE);
1135 close( fd );
1136 ERR("Cannot set SPACE Parity\n");
1137 return FALSE;
1139 break;
1140 #endif
1141 default:
1142 COMM_SetCommError(handle,IE_BYTESIZE);
1143 close( fd );
1144 ERR("Parity\n");
1145 return FALSE;
1149 port.c_cflag &= ~CSIZE;
1150 switch (bytesize) {
1151 case 5:
1152 port.c_cflag |= CS5;
1153 break;
1154 case 6:
1155 port.c_cflag |= CS6;
1156 break;
1157 case 7:
1158 port.c_cflag |= CS7;
1159 break;
1160 case 8:
1161 port.c_cflag |= CS8;
1162 break;
1163 default:
1164 COMM_SetCommError(handle,IE_BYTESIZE);
1165 close( fd );
1166 ERR("ByteSize\n");
1167 return FALSE;
1170 switch (stopbits) {
1171 case ONESTOPBIT:
1172 port.c_cflag &= ~CSTOPB;
1173 break;
1174 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1175 case TWOSTOPBITS:
1176 port.c_cflag |= CSTOPB;
1177 break;
1178 default:
1179 COMM_SetCommError(handle,IE_BYTESIZE);
1180 close( fd );
1181 ERR("StopBits\n");
1182 return FALSE;
1184 #ifdef CRTSCTS
1185 if ( lpdcb->fOutxCtsFlow ||
1186 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1189 port.c_cflag |= CRTSCTS;
1190 TRACE("CRTSCTS\n");
1192 #endif
1194 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1196 WARN("DSR/DTR flow control not supported\n");
1199 if (lpdcb->fInX)
1200 port.c_iflag |= IXON;
1201 else
1202 port.c_iflag &= ~IXON;
1203 if (lpdcb->fOutX)
1204 port.c_iflag |= IXOFF;
1205 else
1206 port.c_iflag &= ~IXOFF;
1208 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1209 int save_error=errno;
1210 COMM_SetCommError(handle,CE_IOE);
1211 close( fd );
1212 ERR("tcsetattr error '%s'\n", strerror(save_error));
1213 return FALSE;
1214 } else {
1215 COMM_SetCommError(handle,0);
1216 close( fd );
1217 return TRUE;
1222 /*****************************************************************************
1223 * GetCommState (KERNEL32.@)
1225 * Fills in a device control block with information from a communications device.
1227 * RETURNS
1229 * True on success, false if the communication device handle is bad etc
1231 * BUGS
1233 * XonChar and XoffChar are not set.
1235 BOOL WINAPI GetCommState(
1236 HANDLE handle, /* [in] The communications device. */
1237 LPDCB lpdcb) /* [out] The device control block. */
1239 struct termios port;
1240 int fd,speed;
1242 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1244 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1245 if (fd < 0)
1247 ERR("FILE_GetUnixHandle failed\n");
1248 return FALSE;
1250 if (tcgetattr(fd, &port) == -1) {
1251 int save_error=errno;
1252 ERR("tcgetattr error '%s'\n", strerror(save_error));
1253 COMM_SetCommError(handle,CE_IOE);
1254 close( fd );
1255 return FALSE;
1257 close( fd );
1258 #ifndef __EMX__
1259 #ifdef CBAUD
1260 speed= (port.c_cflag & CBAUD);
1261 #else
1262 speed= (cfgetospeed(&port));
1263 #endif
1264 switch (speed) {
1265 case B110:
1266 lpdcb->BaudRate = 110;
1267 break;
1268 case B300:
1269 lpdcb->BaudRate = 300;
1270 break;
1271 case B600:
1272 lpdcb->BaudRate = 600;
1273 break;
1274 case B1200:
1275 lpdcb->BaudRate = 1200;
1276 break;
1277 case B2400:
1278 lpdcb->BaudRate = 2400;
1279 break;
1280 case B4800:
1281 lpdcb->BaudRate = 4800;
1282 break;
1283 case B9600:
1284 lpdcb->BaudRate = 9600;
1285 break;
1286 case B19200:
1287 lpdcb->BaudRate = 19200;
1288 break;
1289 case B38400:
1290 lpdcb->BaudRate = 38400;
1291 break;
1292 #ifdef B57600
1293 case B57600:
1294 lpdcb->BaudRate = 57600;
1295 break;
1296 #endif
1297 #ifdef B115200
1298 case B115200:
1299 lpdcb->BaudRate = 115200;
1300 break;
1301 #endif
1302 #ifdef B230400
1303 case B230400:
1304 lpdcb->BaudRate = 230400;
1305 break;
1306 #endif
1307 #ifdef B460800
1308 case B460800:
1309 lpdcb->BaudRate = 460800;
1310 break;
1311 #endif
1312 default:
1313 ERR("unknown speed %x \n",speed);
1315 #endif
1316 switch (port.c_cflag & CSIZE) {
1317 case CS5:
1318 lpdcb->ByteSize = 5;
1319 break;
1320 case CS6:
1321 lpdcb->ByteSize = 6;
1322 break;
1323 case CS7:
1324 lpdcb->ByteSize = 7;
1325 break;
1326 case CS8:
1327 lpdcb->ByteSize = 8;
1328 break;
1329 default:
1330 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1333 if(port.c_iflag & INPCK)
1334 lpdcb->fParity = TRUE;
1335 else
1336 lpdcb->fParity = FALSE;
1337 #ifdef CMSPAR
1338 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1339 #else
1340 switch (port.c_cflag & (PARENB | PARODD))
1341 #endif
1343 case 0:
1344 lpdcb->Parity = NOPARITY;
1345 break;
1346 case PARENB:
1347 lpdcb->Parity = EVENPARITY;
1348 break;
1349 case (PARENB | PARODD):
1350 lpdcb->Parity = ODDPARITY;
1351 break;
1352 #ifdef CMSPAR
1353 case (PARENB | CMSPAR):
1354 lpdcb->Parity = MARKPARITY;
1355 break;
1356 case (PARENB | PARODD | CMSPAR):
1357 lpdcb->Parity = SPACEPARITY;
1358 break;
1359 #endif
1362 if (port.c_cflag & CSTOPB)
1363 if(lpdcb->ByteSize == 5)
1364 lpdcb->StopBits = ONE5STOPBITS;
1365 else
1366 lpdcb->StopBits = TWOSTOPBITS;
1367 else
1368 lpdcb->StopBits = ONESTOPBIT;
1370 lpdcb->fNull = 0;
1371 lpdcb->fBinary = 1;
1373 /* termios does not support DTR/DSR flow control */
1374 lpdcb->fOutxDsrFlow = 0;
1375 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1377 #ifdef CRTSCTS
1379 if (port.c_cflag & CRTSCTS) {
1380 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1381 lpdcb->fOutxCtsFlow = 1;
1382 } else
1383 #endif
1385 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1386 lpdcb->fOutxCtsFlow = 0;
1388 if (port.c_iflag & IXON)
1389 lpdcb->fInX = 1;
1390 else
1391 lpdcb->fInX = 0;
1393 if (port.c_iflag & IXOFF)
1394 lpdcb->fOutX = 1;
1395 else
1396 lpdcb->fOutX = 0;
1398 lpdcb->XonChar =
1399 lpdcb->XoffChar =
1401 lpdcb->XonLim = 10;
1402 lpdcb->XoffLim = 10;
1404 COMM_SetCommError(handle,0);
1406 TRACE("OK\n");
1408 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1409 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1410 (lpdcb->StopBits == ONESTOPBIT)?1:
1411 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1412 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1413 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1414 #ifdef CRTSCTS
1415 if ( lpdcb->fOutxCtsFlow ||
1416 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1418 TRACE("CRTSCTS\n");
1419 else
1421 TRACE("~CRTSCTS\n");
1423 #endif
1424 return TRUE;
1427 /*****************************************************************************
1428 * TransmitCommChar (KERNEL32.@)
1430 * Transmits a single character in front of any pending characters in the
1431 * output buffer. Usually used to send an interrupt character to a host.
1433 * RETURNS
1435 * True if the call succeeded, false if the previous command character to the
1436 * same device has not been sent yet the handle is bad etc.
1438 * BUGS
1440 * Stub.
1442 BOOL WINAPI TransmitCommChar(
1443 HANDLE hComm, /* [in] The communication device in need of a command character. */
1444 CHAR chTransmit) /* [in] The character to transmit. */
1446 BOOL r = FALSE;
1447 int fd;
1449 WARN("(%x,'%c') not perfect!\n",hComm,chTransmit);
1451 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1452 if ( fd < 0 )
1453 SetLastError ( ERROR_INVALID_PARAMETER );
1454 else
1456 r = (1 == write(fd, &chTransmit, 1));
1457 close(fd);
1460 return r;
1464 /*****************************************************************************
1465 * GetCommTimeouts (KERNEL32.@)
1467 * Obtains the request timeout values for the communications device.
1469 * RETURNS
1471 * True on success, false if communications device handle is bad
1472 * or the target structure is null.
1474 BOOL WINAPI GetCommTimeouts(
1475 HANDLE hComm, /* [in] The communications device. */
1476 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1478 BOOL ret;
1480 TRACE("(%x,%p)\n",hComm,lptimeouts);
1482 if(!lptimeouts)
1484 SetLastError(ERROR_INVALID_PARAMETER);
1485 return FALSE;
1488 SERVER_START_REQ( get_serial_info )
1490 req->handle = hComm;
1491 if ((ret = !wine_server_call_err( req )))
1493 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1494 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1495 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1496 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1497 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1500 SERVER_END_REQ;
1501 return ret;
1504 /*****************************************************************************
1505 * SetCommTimeouts (KERNEL32.@)
1507 * Sets the timeouts used when reading and writing data to/from COMM ports.
1509 * ReadIntervalTimeout
1510 * - converted and passes to linux kernel as c_cc[VTIME]
1511 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1512 * - used in ReadFile to calculate GetOverlappedResult's timeout
1513 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1514 * - used in WriteFile to calculate GetOverlappedResult's timeout
1516 * RETURNS
1518 * True if the timeouts were set, false otherwise.
1520 BOOL WINAPI SetCommTimeouts(
1521 HANDLE hComm, /* [in] handle of COMM device */
1522 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1524 BOOL ret;
1525 int fd;
1526 struct termios tios;
1528 TRACE("(%x,%p)\n",hComm,lptimeouts);
1530 if(!lptimeouts)
1532 SetLastError(ERROR_INVALID_PARAMETER);
1533 return FALSE;
1536 SERVER_START_REQ( set_serial_info )
1538 req->handle = hComm;
1539 req->flags = SERIALINFO_SET_TIMEOUTS;
1540 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1541 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1542 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1543 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1544 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1545 ret = !wine_server_call_err( req );
1547 SERVER_END_REQ;
1548 if (!ret) return FALSE;
1550 /* FIXME: move this stuff to the server */
1551 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1552 if (fd < 0) {
1553 FIXME("no fd for handle = %0x!.\n",hComm);
1554 return FALSE;
1557 if (-1==tcgetattr(fd,&tios)) {
1558 FIXME("tcgetattr on fd %d failed!\n",fd);
1559 return FALSE;
1562 /* VTIME is in 1/10 seconds */
1564 unsigned int ux_timeout;
1566 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1568 ux_timeout = 0;
1570 else
1572 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1573 if(ux_timeout == 0)
1575 ux_timeout = 1; /* must be at least some timeout */
1578 tios.c_cc[VTIME] = ux_timeout;
1581 if (-1==tcsetattr(fd,0,&tios)) {
1582 FIXME("tcsetattr on fd %d failed!\n",fd);
1583 return FALSE;
1585 close(fd);
1586 return TRUE;
1589 /***********************************************************************
1590 * GetCommModemStatus (KERNEL32.@)
1592 * Obtains the four control register bits if supported by the hardware.
1594 * RETURNS
1596 * True if the communications handle was good and for hardware that
1597 * control register access, false otherwise.
1599 BOOL WINAPI GetCommModemStatus(
1600 HANDLE hFile, /* [in] The communications device. */
1601 LPDWORD lpModemStat) /* [out] The control register bits. */
1603 int fd,mstat, result=FALSE;
1605 *lpModemStat=0;
1606 #ifdef TIOCMGET
1607 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
1608 if(fd<0)
1609 return FALSE;
1610 result = ioctl(fd, TIOCMGET, &mstat);
1611 close(fd);
1612 if (result == -1)
1614 WARN("ioctl failed\n");
1615 return FALSE;
1617 #ifdef TIOCM_CTS
1618 if (mstat & TIOCM_CTS)
1619 *lpModemStat |= MS_CTS_ON;
1620 #endif
1621 #ifdef TIOCM_DSR
1622 if (mstat & TIOCM_DSR)
1623 *lpModemStat |= MS_DSR_ON;
1624 #endif
1625 #ifdef TIOCM_RNG
1626 if (mstat & TIOCM_RNG)
1627 *lpModemStat |= MS_RING_ON;
1628 #endif
1629 #ifdef TIOCM_CAR
1630 /*FIXME: Not really sure about RLSD UB 990810*/
1631 if (mstat & TIOCM_CAR)
1632 *lpModemStat |= MS_RLSD_ON;
1633 #endif
1634 TRACE("%04x -> %s%s%s%s\n", mstat,
1635 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1636 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1637 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1638 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1639 return TRUE;
1640 #else
1641 return FALSE;
1642 #endif
1645 /***********************************************************************
1646 * COMM_WaitCommEventService (INTERNAL)
1648 * This function is called while the client is waiting on the
1649 * server, so we can't make any server calls here.
1651 static void COMM_WaitCommEventService(async_private *ovp)
1653 async_commio *commio = (async_commio*) ovp;
1654 LPOVERLAPPED lpOverlapped = commio->lpOverlapped;
1656 TRACE("overlapped %p\n",lpOverlapped);
1658 /* FIXME: detect other events */
1659 *commio->buffer = EV_RXCHAR;
1661 lpOverlapped->Internal = STATUS_SUCCESS;
1665 /***********************************************************************
1666 * COMM_WaitCommEvent (INTERNAL)
1668 * This function must have an lpOverlapped.
1670 static BOOL COMM_WaitCommEvent(
1671 HANDLE hFile, /* [in] handle of comm port to wait for */
1672 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1673 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1675 int fd;
1676 async_commio *ovp;
1678 if(!lpOverlapped)
1680 SetLastError(ERROR_INVALID_PARAMETER);
1681 return FALSE;
1684 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1685 return FALSE;
1687 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
1688 if(fd<0)
1689 return FALSE;
1691 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1692 if(!ovp)
1694 close(fd);
1695 return FALSE;
1698 ovp->async.ops = &commio_async_ops;
1699 ovp->async.handle = hFile;
1700 ovp->async.fd = fd;
1701 ovp->async.type = ASYNC_TYPE_WAIT;
1702 ovp->async.func = COMM_WaitCommEventService;
1703 ovp->async.event = lpOverlapped->hEvent;
1704 ovp->lpOverlapped = lpOverlapped;
1705 ovp->buffer = (char *)lpdwEvents;
1707 lpOverlapped->InternalHigh = 0;
1708 lpOverlapped->Offset = 0;
1709 lpOverlapped->OffsetHigh = 0;
1711 if ( !register_new_async (&ovp->async) )
1712 SetLastError( ERROR_IO_PENDING );
1714 return FALSE;
1717 /***********************************************************************
1718 * WaitCommEvent (KERNEL32.@)
1720 * Wait until something interesting happens on a COMM port.
1721 * Interesting things (events) are set by calling SetCommMask before
1722 * this function is called.
1724 * RETURNS:
1725 * TRUE if successful
1726 * FALSE if failure
1728 * The set of detected events will be written to *lpdwEventMask
1729 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1731 * BUGS:
1732 * Only supports EV_RXCHAR and EV_TXEMPTY
1734 BOOL WINAPI WaitCommEvent(
1735 HANDLE hFile, /* [in] handle of comm port to wait for */
1736 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1737 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1739 OVERLAPPED ov;
1740 int ret;
1742 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1744 if(lpOverlapped)
1745 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1747 /* if there is no overlapped structure, create our own */
1748 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1750 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1752 if(GetLastError()!=STATUS_PENDING)
1754 CloseHandle(ov.hEvent);
1755 return FALSE;
1758 /* wait for the overlapped to complete */
1759 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1760 CloseHandle(ov.hEvent);
1762 return ret;
1765 /***********************************************************************
1766 * GetCommProperties (KERNEL32.@)
1768 * This function fills in a structure with the capabilities of the
1769 * communications port driver.
1771 * RETURNS
1773 * TRUE on success, FALSE on failure
1774 * If successful, the lpCommProp structure be filled in with
1775 * properties of the comm port.
1777 BOOL WINAPI GetCommProperties(
1778 HANDLE hFile, /* [in] handle of the comm port */
1779 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1781 FIXME("(%d %p )\n",hFile,lpCommProp);
1782 if(!lpCommProp)
1783 return FALSE;
1786 * These values should be valid for LINUX's serial driver
1787 * FIXME: Perhaps they deserve an #ifdef LINUX
1789 memset(lpCommProp,0,sizeof(COMMPROP));
1790 lpCommProp->wPacketLength = 1;
1791 lpCommProp->wPacketVersion = 1;
1792 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1793 lpCommProp->dwReserved1 = 0;
1794 lpCommProp->dwMaxTxQueue = 4096;
1795 lpCommProp->dwMaxRxQueue = 4096;
1796 lpCommProp->dwMaxBaud = BAUD_115200;
1797 lpCommProp->dwProvSubType = PST_RS232;
1798 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
1799 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1800 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1801 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1802 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1803 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1804 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1805 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1806 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1807 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1808 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1810 return TRUE;
1813 /***********************************************************************
1814 * FIXME:
1815 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1816 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1817 * This is dependent on the type of COMM port, but since it is doubtful
1818 * anybody will get around to implementing support for fancy serial
1819 * ports in WINE, this is hardcoded for the time being. The name of
1820 * this DLL should be stored in and read from the system registry in
1821 * the hive HKEY_LOCAL_MACHINE, key
1822 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1823 * where ???? is the port number... that is determined by PNP
1824 * The DLL should be loaded when the COMM port is opened, and closed
1825 * when the COMM port is closed. - MJM 20 June 2000
1826 ***********************************************************************/
1827 static CHAR lpszSerialUI[] = "serialui.dll";
1830 /***********************************************************************
1831 * CommConfigDialogA (KERNEL32.@)
1833 * Raises a dialog that allows the user to configure a comm port.
1834 * Fills the COMMCONFIG struct with information specified by the user.
1835 * This function should call a similar routine in the COMM driver...
1837 * RETURNS
1839 * TRUE on success, FALSE on failure
1840 * If successful, the lpCommConfig structure will contain a new
1841 * configuration for the comm port, as specified by the user.
1843 * BUGS
1844 * The library with the CommConfigDialog code is never unloaded.
1845 * Perhaps this should be done when the comm port is closed?
1847 BOOL WINAPI CommConfigDialogA(
1848 LPCSTR lpszDevice, /* [in] name of communications device */
1849 HANDLE hWnd, /* [in] parent window for the dialog */
1850 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1852 FARPROC lpfnCommDialog;
1853 HMODULE hConfigModule;
1854 BOOL r;
1856 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
1858 hConfigModule = LoadLibraryA(lpszSerialUI);
1859 if(!hConfigModule)
1860 return FALSE;
1862 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
1864 if(!lpfnCommDialog)
1865 return FALSE;
1867 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1869 /* UnloadLibrary(hConfigModule); */
1871 return r;
1874 /***********************************************************************
1875 * CommConfigDialogW (KERNEL32.@)
1877 * see CommConfigDialogA for more info
1879 BOOL WINAPI CommConfigDialogW(
1880 LPCWSTR lpszDevice, /* [in] name of communications device */
1881 HANDLE hWnd, /* [in] parent window for the dialog */
1882 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1884 BOOL r;
1885 LPSTR lpDeviceA;
1887 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1888 if(lpDeviceA)
1889 return FALSE;
1890 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
1891 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1892 return r;
1895 /***********************************************************************
1896 * GetCommConfig (KERNEL32.@)
1898 * Fill in the COMMCONFIG structure for the comm port hFile
1900 * RETURNS
1902 * TRUE on success, FALSE on failure
1903 * If successful, lpCommConfig contains the comm port configuration.
1905 * BUGS
1908 BOOL WINAPI GetCommConfig(
1909 HANDLE hFile, /* [in] The communications device. */
1910 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1911 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1912 afterwards the number of bytes copied to the buffer or
1913 the needed size of the buffer. */
1915 BOOL r;
1917 TRACE("(%x %p)\n",hFile,lpCommConfig);
1919 if(lpCommConfig == NULL)
1920 return FALSE;
1922 r = *lpdwSize < sizeof(COMMCONFIG);
1923 *lpdwSize = sizeof(COMMCONFIG);
1924 if(!r)
1925 return FALSE;
1927 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1928 lpCommConfig->wVersion = 1;
1929 lpCommConfig->wReserved = 0;
1930 r = GetCommState(hFile,&lpCommConfig->dcb);
1931 lpCommConfig->dwProviderSubType = PST_RS232;
1932 lpCommConfig->dwProviderOffset = 0;
1933 lpCommConfig->dwProviderSize = 0;
1935 return r;
1938 /***********************************************************************
1939 * SetCommConfig (KERNEL32.@)
1941 * Sets the configuration of the communications device.
1943 * RETURNS
1945 * True on success, false if the handle was bad is not a communications device.
1947 BOOL WINAPI SetCommConfig(
1948 HANDLE hFile, /* [in] The communications device. */
1949 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1950 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1952 TRACE("(%x %p)\n",hFile,lpCommConfig);
1953 return SetCommState(hFile,&lpCommConfig->dcb);
1956 /***********************************************************************
1957 * SetDefaultCommConfigA (KERNEL32.@)
1959 * Initializes the default configuration for the specified communication
1960 * device. (ascii)
1962 * RETURNS
1964 * True if the device was found and the defaults set, false otherwise
1966 BOOL WINAPI SetDefaultCommConfigA(
1967 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1968 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1969 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1971 FARPROC lpfnSetDefaultCommConfig;
1972 HMODULE hConfigModule;
1973 BOOL r;
1975 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1977 hConfigModule = LoadLibraryA(lpszSerialUI);
1978 if(!hConfigModule)
1979 return FALSE;
1981 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
1983 if(! lpfnSetDefaultCommConfig)
1984 return TRUE;
1986 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1988 /* UnloadLibrary(hConfigModule); */
1990 return r;
1994 /***********************************************************************
1995 * SetDefaultCommConfigW (KERNEL32.@)
1997 * Initializes the default configuration for the specified
1998 * communication device. (unicode)
2000 * RETURNS
2003 BOOL WINAPI SetDefaultCommConfigW(
2004 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2005 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2006 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2008 BOOL r;
2009 LPSTR lpDeviceA;
2011 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2013 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2014 if(lpDeviceA)
2015 return FALSE;
2016 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2017 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2018 return r;
2022 /***********************************************************************
2023 * GetDefaultCommConfigA (KERNEL32.@)
2025 * Acquires the default configuration of the specified communication device. (unicode)
2027 * RETURNS
2029 * True on successful reading of the default configuration,
2030 * if the device is not found or the buffer is too small.
2032 BOOL WINAPI GetDefaultCommConfigA(
2033 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2034 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2035 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2036 afterwards the number of bytes copied to the buffer or
2037 the needed size of the buffer. */
2039 LPDCB lpdcb = &(lpCC->dcb);
2040 char temp[40];
2042 if (strncasecmp(lpszName,"COM",3)) {
2043 ERR("not implemented for <%s>\n", lpszName);
2044 return FALSE;
2047 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2048 if (*lpdwSize < sizeof(COMMCONFIG)) {
2049 *lpdwSize = sizeof(COMMCONFIG);
2050 return FALSE;
2053 *lpdwSize = sizeof(COMMCONFIG);
2055 lpCC->dwSize = sizeof(COMMCONFIG);
2056 lpCC->wVersion = 1;
2057 lpCC->dwProviderSubType = PST_RS232;
2058 lpCC->dwProviderOffset = 0L;
2059 lpCC->dwProviderSize = 0L;
2061 sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2062 FIXME("setting %s as default\n", temp);
2064 return BuildCommDCBA( temp, lpdcb);
2067 /**************************************************************************
2068 * GetDefaultCommConfigW (KERNEL32.@)
2070 * Acquires the default configuration of the specified communication device. (unicode)
2072 * RETURNS
2074 * True on successful reading of the default configuration,
2075 * if the device is not found or the buffer is too small.
2077 BOOL WINAPI GetDefaultCommConfigW(
2078 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2079 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2080 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2081 afterwards the number of bytes copied to the buffer or
2082 the needed size of the buffer. */
2084 BOOL ret = FALSE;
2085 LPSTR lpszNameA;
2087 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2088 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2089 if (lpszNameA)
2091 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2092 HeapFree( GetProcessHeap(), 0, lpszNameA );
2094 return ret;