- Need a "cleanup" method.
[wine/testsucceed.git] / dlls / kernel / comm.c
blobac477e9340322ebbf19e3a8e3a21dc8c17face3a
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 #include <termios.h>
58 #include <fcntl.h>
59 #include <string.h>
60 #ifdef HAVE_STRINGS_H
61 # include <strings.h>
62 #endif
63 #include <errno.h>
64 #include <ctype.h>
65 #include <sys/stat.h>
66 #ifdef HAVE_SYS_FILIO_H
67 # include <sys/filio.h>
68 #endif
69 #include <sys/ioctl.h>
70 #include <unistd.h>
71 #include <sys/poll.h>
72 #ifdef HAVE_SYS_MODEM_H
73 # include <sys/modem.h>
74 #endif
75 #ifdef HAVE_SYS_STRTIO_H
76 # include <sys/strtio.h>
77 #endif
79 #include "winbase.h"
80 #include "winerror.h"
82 #include "wine/server.h"
83 #include "async.h"
84 #include "file.h"
85 #include "heap.h"
87 #include "wine/debug.h"
89 #ifdef HAVE_LINUX_SERIAL_H
90 #include <linux/serial.h>
91 #endif
93 WINE_DEFAULT_DEBUG_CHANNEL(comm);
95 /***********************************************************************
96 * Asynchronous I/O for asynchronous wait requests *
99 static DWORD commio_get_async_status (const async_private *ovp);
100 static DWORD commio_get_async_count (const async_private *ovp);
101 static void commio_set_async_status (async_private *ovp, const DWORD status);
102 static void commio_async_cleanup (async_private *ovp);
104 static async_ops commio_async_ops =
106 commio_get_async_status, /* get_status */
107 commio_set_async_status, /* set_status */
108 commio_get_async_count, /* get_count */
109 NULL, /* call_completion */
110 commio_async_cleanup /* cleanup */
113 typedef struct async_commio
115 struct async_private async;
116 LPOVERLAPPED lpOverlapped;
117 char *buffer;
118 } async_commio;
120 static DWORD commio_get_async_status (const struct async_private *ovp)
122 return ((async_commio*) ovp)->lpOverlapped->Internal;
125 static void commio_set_async_status (async_private *ovp, const DWORD status)
127 ((async_commio*) ovp)->lpOverlapped->Internal = status;
130 static DWORD commio_get_async_count (const struct async_private *ovp)
132 return 0;
135 static void commio_async_cleanup (async_private *ovp)
137 HeapFree(GetProcessHeap(), 0, ovp );
140 /***********************************************************************/
142 #if !defined(TIOCINQ) && defined(FIONREAD)
143 #define TIOCINQ FIONREAD
144 #endif
146 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
148 unsigned int mstat, okay;
149 okay = ioctl(fd, TIOCMGET, &mstat);
150 if (okay) return okay;
151 if (andy) mstat &= andy;
152 mstat |= orrie;
153 return ioctl(fd, TIOCMSET, &mstat);
156 /***********************************************************************
157 * COMM_BuildOldCommDCB (Internal)
159 * Build a DCB using the old style settings string eg: "COMx:96,n,8,1"
160 * We ignore the COM port index, since we can support more than 4 ports.
162 BOOL WINAPI COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
164 /* "COM1:96,n,8,1" */
165 /* 012345 */
166 char *ptr, temp[256], last;
167 int rate;
169 TRACE("(%s), ptr %p\n", device, lpdcb);
171 if (strncasecmp(device,"COM",3))
172 return FALSE;
174 if (!*(device+4))
175 return FALSE;
177 if ((*(device+4) != ':') && (*(device+4) != ' '))
178 return FALSE;
180 strcpy(temp,device+5);
181 last=temp[strlen(temp)-1];
182 ptr = strtok(temp, ", ");
184 /* DOS/Windows only compares the first two numbers
185 * and assigns an appropriate baud rate.
186 * You can supply 961324245, it still returns 9600 ! */
187 if (strlen(ptr) < 2)
189 WARN("Unknown baudrate string '%s' !\n", ptr);
190 return FALSE; /* error: less than 2 chars */
192 ptr[2] = '\0';
193 rate = atoi(ptr);
195 switch (rate) {
196 case 11:
197 case 30:
198 case 60:
199 rate *= 10;
200 break;
201 case 12:
202 case 24:
203 case 48:
204 case 96:
205 rate *= 100;
206 break;
207 case 19:
208 rate = 19200;
209 break;
210 default:
211 WARN("Unknown baudrate indicator %d !\n", rate);
212 return FALSE;
215 lpdcb->BaudRate = rate;
216 TRACE("baudrate (%ld)\n", lpdcb->BaudRate);
218 ptr = strtok(NULL, ", ");
219 if (islower(*ptr))
220 *ptr = toupper(*ptr);
222 TRACE("parity (%c)\n", *ptr);
223 lpdcb->fParity = TRUE;
224 switch (*ptr) {
225 case 'N':
226 lpdcb->Parity = NOPARITY;
227 lpdcb->fParity = FALSE;
228 break;
229 case 'E':
230 lpdcb->Parity = EVENPARITY;
231 break;
232 case 'M':
233 lpdcb->Parity = MARKPARITY;
234 break;
235 case 'O':
236 lpdcb->Parity = ODDPARITY;
237 break;
238 case 'S':
239 lpdcb->Parity = SPACEPARITY;
240 break;
241 default:
242 WARN("Unknown parity `%c'!\n", *ptr);
243 return FALSE;
246 ptr = strtok(NULL, ", ");
247 TRACE("charsize (%c)\n", *ptr);
248 lpdcb->ByteSize = *ptr - '0';
250 ptr = strtok(NULL, ", ");
251 TRACE("stopbits (%c)\n", *ptr);
252 switch (*ptr) {
253 case '1':
254 lpdcb->StopBits = ONESTOPBIT;
255 break;
256 case '2':
257 lpdcb->StopBits = TWOSTOPBITS;
258 break;
259 default:
260 WARN("Unknown # of stopbits `%c'!\n", *ptr);
261 return FALSE;
264 if (last == 'x') {
265 lpdcb->fInX = TRUE;
266 lpdcb->fOutX = TRUE;
267 lpdcb->fOutxCtsFlow = FALSE;
268 lpdcb->fOutxDsrFlow = FALSE;
269 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
270 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
271 } else if (last=='p') {
272 lpdcb->fInX = FALSE;
273 lpdcb->fOutX = FALSE;
274 lpdcb->fOutxCtsFlow = TRUE;
275 lpdcb->fOutxDsrFlow = FALSE;
276 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
277 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
278 } else {
279 lpdcb->fInX = FALSE;
280 lpdcb->fOutX = FALSE;
281 lpdcb->fOutxCtsFlow = FALSE;
282 lpdcb->fOutxDsrFlow = FALSE;
283 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
284 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
287 return TRUE;
290 /**************************************************************************
291 * BuildCommDCBA (KERNEL32.@)
293 * Updates a device control block data structure with values from an
294 * ascii device control string. The device control string has two forms
295 * normal and extended, it must be exclusively in one or the other form.
297 * RETURNS
299 * True on success, false on a malformed control string.
301 BOOL WINAPI BuildCommDCBA(
302 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
303 LPDCB lpdcb) /* [out] The device control block to be updated. */
305 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
308 /**************************************************************************
309 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
311 * Updates a device control block data structure with values from an
312 * ascii device control string. Taking timeout values from a timeouts
313 * struct if desired by the control string.
315 * RETURNS
317 * True on success, false bad handles etc
319 BOOL WINAPI BuildCommDCBAndTimeoutsA(
320 LPCSTR device, /* [in] The ascii device control string. */
321 LPDCB lpdcb, /* [out] The device control block to be updated. */
322 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
324 int port;
325 char *ptr,*temp;
327 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
329 if (!strncasecmp(device,"COM",3)) {
330 port=device[3]-'0';
331 if (port--==0) {
332 ERR("BUG! COM0 can't exist!\n");
333 return FALSE;
335 if ((*(device+4)!=':') && (*(device+4)!=' '))
336 return FALSE;
337 temp=(LPSTR)(device+5);
338 } else
339 temp=(LPSTR)device;
341 memset(lpdcb,0,sizeof (DCB));
342 lpdcb->DCBlength = sizeof(DCB);
343 if (strchr(temp,',')) { /* old style */
345 return COMM_BuildOldCommDCB(device,lpdcb);
347 ptr=strtok(temp," ");
348 while (ptr) {
349 DWORD flag,x;
351 flag=0;
352 if (!strncmp("baud=",ptr,5)) {
353 if (!sscanf(ptr+5,"%ld",&x))
354 WARN("Couldn't parse %s\n",ptr);
355 lpdcb->BaudRate = x;
356 flag=1;
358 if (!strncmp("stop=",ptr,5)) {
359 if (!sscanf(ptr+5,"%ld",&x))
360 WARN("Couldn't parse %s\n",ptr);
361 lpdcb->StopBits = x;
362 flag=1;
364 if (!strncmp("data=",ptr,5)) {
365 if (!sscanf(ptr+5,"%ld",&x))
366 WARN("Couldn't parse %s\n",ptr);
367 lpdcb->ByteSize = x;
368 flag=1;
370 if (!strncmp("parity=",ptr,7)) {
371 lpdcb->fParity = TRUE;
372 switch (ptr[7]) {
373 case 'N':case 'n':
374 lpdcb->fParity = FALSE;
375 lpdcb->Parity = NOPARITY;
376 break;
377 case 'E':case 'e':
378 lpdcb->Parity = EVENPARITY;
379 break;
380 case 'O':case 'o':
381 lpdcb->Parity = ODDPARITY;
382 break;
383 case 'M':case 'm':
384 lpdcb->Parity = MARKPARITY;
385 break;
386 case 'S':case 's':
387 lpdcb->Parity = SPACEPARITY;
388 break;
390 flag=1;
392 if (!flag)
393 ERR("Unhandled specifier '%s', please report.\n",ptr);
394 ptr=strtok(NULL," ");
396 if (lpdcb->BaudRate==110)
397 lpdcb->StopBits = 2;
398 return TRUE;
401 /**************************************************************************
402 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
404 * Updates a device control block data structure with values from an
405 * unicode device control string. Taking timeout values from a timeouts
406 * struct if desired by the control string.
408 * RETURNS
410 * True on success, false bad handles etc.
412 BOOL WINAPI BuildCommDCBAndTimeoutsW(
413 LPCWSTR devid, /* [in] The unicode device control string. */
414 LPDCB lpdcb, /* [out] The device control block to be updated. */
415 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
417 BOOL ret = FALSE;
418 LPSTR devidA;
420 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
421 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
422 if (devidA)
424 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
425 HeapFree( GetProcessHeap(), 0, devidA );
427 return ret;
430 /**************************************************************************
431 * BuildCommDCBW (KERNEL32.@)
433 * Updates a device control block structure with values from an
434 * unicode device control string. The device control string has two forms
435 * normal and extended, it must be exclusively in one or the other form.
437 * RETURNS
439 * True on success, false on an malformed control string.
441 BOOL WINAPI BuildCommDCBW(
442 LPCWSTR devid, /* [in] The unicode device control string. */
443 LPDCB lpdcb) /* [out] The device control block to be updated. */
445 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
448 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
450 DWORD ret;
452 SERVER_START_REQ( set_serial_info )
454 req->handle = handle;
455 req->flags = SERIALINFO_SET_ERROR;
456 req->commerror = error;
457 ret = !wine_server_call_err( req );
459 SERVER_END_REQ;
460 return ret;
463 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
465 DWORD ret;
467 if(!lperror)
468 return FALSE;
470 SERVER_START_REQ( get_serial_info )
472 req->handle = handle;
473 ret = !wine_server_call_err( req );
474 *lperror = reply->commerror;
476 SERVER_END_REQ;
478 return ret;
481 /*****************************************************************************
482 * SetCommBreak (KERNEL32.@)
484 * Halts the transmission of characters to a communications device.
486 * RETURNS
488 * True on success, and false if the communications device could not be found,
489 * the control is not supported.
491 * BUGS
493 * Only TIOCSBRK and TIOCCBRK are supported.
495 BOOL WINAPI SetCommBreak(
496 HANDLE handle) /* [in] The communictions device to suspend. */
498 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
499 int fd,result;
501 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
502 if(fd<0) {
503 TRACE("FILE_GetUnixHandle failed\n");
504 return FALSE;
506 result = ioctl(fd,TIOCSBRK,0);
507 close(fd);
508 if (result ==-1)
510 TRACE("ioctl failed\n");
511 SetLastError(ERROR_NOT_SUPPORTED);
512 return FALSE;
514 return TRUE;
515 #else
516 FIXME("ioctl not available\n");
517 SetLastError(ERROR_NOT_SUPPORTED);
518 return FALSE;
519 #endif
522 /*****************************************************************************
523 * ClearCommBreak (KERNEL32.@)
525 * Resumes character transmission from a communication device.
527 * RETURNS
529 * True on success and false if the communications device could not be found.
531 * BUGS
533 * Only TIOCSBRK and TIOCCBRK are supported.
535 BOOL WINAPI ClearCommBreak(
536 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
538 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
539 int fd,result;
541 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
542 if(fd<0) {
543 TRACE("FILE_GetUnixHandle failed\n");
544 return FALSE;
546 result = ioctl(fd,TIOCCBRK,0);
547 close(fd);
548 if (result ==-1)
550 TRACE("ioctl failed\n");
551 SetLastError(ERROR_NOT_SUPPORTED);
552 return FALSE;
554 return TRUE;
555 #else
556 FIXME("ioctl not available\n");
557 SetLastError(ERROR_NOT_SUPPORTED);
558 return FALSE;
559 #endif
562 /*****************************************************************************
563 * EscapeCommFunction (KERNEL32.@)
565 * Directs a communication device to perform an extended function.
567 * RETURNS
569 * True or requested data on successful completion of the command,
570 * false if the device is not present cannot execute the command
571 * or the command failed.
573 BOOL WINAPI EscapeCommFunction(
574 HANDLE handle, /* [in] The communication device to perform the extended function. */
575 UINT nFunction) /* [in] The extended function to be performed. */
577 int fd,direct=FALSE,result=FALSE;
578 struct termios port;
580 TRACE("handle %d, function=%d\n", handle, nFunction);
581 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
582 if(fd<0) {
583 FIXME("handle %d not found.\n",handle);
584 return FALSE;
587 if (tcgetattr(fd,&port) == -1) {
588 COMM_SetCommError(handle,CE_IOE);
589 close(fd);
590 return FALSE;
593 switch (nFunction) {
594 case RESETDEV:
595 TRACE("\n");
596 break;
598 case CLRDTR:
599 TRACE("CLRDTR\n");
600 #ifdef TIOCM_DTR
601 direct=TRUE;
602 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
603 break;
604 #endif
606 case CLRRTS:
607 TRACE("CLRRTS\n");
608 #ifdef TIOCM_RTS
609 direct=TRUE;
610 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
611 break;
612 #endif
614 case SETDTR:
615 TRACE("SETDTR\n");
616 #ifdef TIOCM_DTR
617 direct=TRUE;
618 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
619 break;
620 #endif
622 case SETRTS:
623 TRACE("SETRTS\n");
624 #ifdef TIOCM_RTS
625 direct=TRUE;
626 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
627 break;
628 #endif
630 case SETXOFF:
631 TRACE("SETXOFF\n");
632 port.c_iflag |= IXOFF;
633 break;
635 case SETXON:
636 TRACE("SETXON\n");
637 port.c_iflag |= IXON;
638 break;
639 case SETBREAK:
640 TRACE("setbreak\n");
641 #ifdef TIOCSBRK
642 direct=TRUE;
643 result = ioctl(fd,TIOCSBRK,0);
644 break;
645 #endif
646 case CLRBREAK:
647 TRACE("clrbreak\n");
648 #ifdef TIOCSBRK
649 direct=TRUE;
650 result = ioctl(fd,TIOCCBRK,0);
651 break;
652 #endif
653 default:
654 WARN("(handle=%d,nFunction=%d): Unknown function\n",
655 handle, nFunction);
656 break;
659 if (!direct)
660 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
661 close(fd);
662 COMM_SetCommError(handle,CE_IOE);
663 return FALSE;
664 } else
665 result= TRUE;
666 else
668 if (result == -1)
670 result= FALSE;
671 COMM_SetCommError(handle,CE_IOE);
673 else
674 result = TRUE;
676 close(fd);
677 return result;
680 /********************************************************************
681 * PurgeComm (KERNEL32.@)
683 * Terminates pending operations and/or discards buffers on a
684 * communication resource.
686 * RETURNS
688 * True on success and false if the communications handle is bad.
690 BOOL WINAPI PurgeComm(
691 HANDLE handle, /* [in] The communication resource to be purged. */
692 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
694 int fd;
696 TRACE("handle %d, flags %lx\n", handle, flags);
698 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
699 if(fd<0) {
700 FIXME("no handle %d found\n",handle);
701 return FALSE;
705 ** not exactly sure how these are different
706 ** Perhaps if we had our own internal queues, one flushes them
707 ** and the other flushes the kernel's buffers.
709 if(flags&PURGE_TXABORT)
710 tcflush(fd,TCOFLUSH);
711 if(flags&PURGE_RXABORT)
712 tcflush(fd,TCIFLUSH);
713 if(flags&PURGE_TXCLEAR)
714 tcflush(fd,TCOFLUSH);
715 if(flags&PURGE_RXCLEAR)
716 tcflush(fd,TCIFLUSH);
717 close(fd);
719 return 1;
722 /*****************************************************************************
723 * ClearCommError (KERNEL32.@)
725 * Enables further I/O operations on a communications resource after
726 * supplying error and current status information.
728 * RETURNS
730 * True on success, false if the communication resource handle is bad.
732 BOOL WINAPI ClearCommError(
733 HANDLE handle, /* [in] The communication resource with the error. */
734 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
735 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
737 int fd;
739 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
740 if(0>fd)
742 FIXME("no handle %d found\n",handle);
743 return FALSE;
746 if (lpStat)
748 lpStat->status = 0;
750 #ifdef TIOCOUTQ
751 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
752 WARN("ioctl returned error\n");
753 #else
754 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
755 #endif
757 #ifdef TIOCINQ
758 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
759 WARN("ioctl returned error\n");
760 #endif
762 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
763 handle, lpStat->cbInQue, lpStat->cbOutQue);
766 close(fd);
768 COMM_GetCommError(handle, errors);
769 COMM_SetCommError(handle, 0);
771 return TRUE;
774 /*****************************************************************************
775 * SetupComm (KERNEL32.@)
777 * Called after CreateFile to hint to the communication resource to use
778 * specified sizes for input and output buffers rather than the default values.
780 * RETURNS
782 * True if successful, false if the communications resource handle is bad.
784 * BUGS
786 * Stub.
788 BOOL WINAPI SetupComm(
789 HANDLE handle, /* [in] The just created communication resource handle. */
790 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
791 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
793 int fd;
795 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
796 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
797 if(0>fd) {
798 FIXME("handle %d not found?\n",handle);
799 return FALSE;
801 close(fd);
802 return TRUE;
805 /*****************************************************************************
806 * GetCommMask (KERNEL32.@)
808 * Obtain the events associated with a communication device that will cause
809 * a call WaitCommEvent to return.
811 * RETURNS
813 * True on success, fail on bad device handle etc.
815 BOOL WINAPI GetCommMask(
816 HANDLE handle, /* [in] The communications device. */
817 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
819 BOOL ret;
821 TRACE("handle %d, mask %p\n", handle, evtmask);
823 SERVER_START_REQ( get_serial_info )
825 req->handle = handle;
826 if ((ret = !wine_server_call_err( req )))
828 if (evtmask) *evtmask = reply->eventmask;
831 SERVER_END_REQ;
832 return ret;
835 /*****************************************************************************
836 * SetCommMask (KERNEL32.@)
838 * There be some things we need to hear about yon there communications device.
839 * (Set which events associated with a communication device should cause
840 * a call WaitCommEvent to return.)
842 * RETURNS
844 * True on success, false on bad handle etc.
846 BOOL WINAPI SetCommMask(
847 HANDLE handle, /* [in] The communications device. */
848 DWORD evtmask) /* [in] The events that are to be monitored. */
850 BOOL ret;
852 TRACE("handle %d, mask %lx\n", handle, evtmask);
854 SERVER_START_REQ( set_serial_info )
856 req->handle = handle;
857 req->flags = SERIALINFO_SET_MASK;
858 req->eventmask = evtmask;
859 ret = !wine_server_call_err( req );
861 SERVER_END_REQ;
862 return ret;
865 /*****************************************************************************
866 * SetCommState (KERNEL32.@)
868 * Re-initializes all hardware and control settings of a communications device,
869 * with values from a device control block without effecting the input and output
870 * queues.
872 * RETURNS
874 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
876 BOOL WINAPI SetCommState(
877 HANDLE handle, /* [in] The communications device. */
878 LPDCB lpdcb) /* [out] The device control block. */
880 struct termios port;
881 int fd, bytesize, stopbits;
883 TRACE("handle %d, ptr %p\n", handle, lpdcb);
884 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
885 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
886 (lpdcb->StopBits == ONESTOPBIT)?1:
887 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
888 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
889 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
891 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
892 if (fd < 0) {
893 FIXME("no handle %d found\n",handle);
894 return FALSE;
897 if ((tcgetattr(fd,&port)) == -1) {
898 int save_error = errno;
899 COMM_SetCommError(handle,CE_IOE);
900 close( fd );
901 ERR("tcgetattr error '%s'\n", strerror(save_error));
902 return FALSE;
905 port.c_cc[VMIN] = 0;
906 port.c_cc[VTIME] = 1;
908 #ifdef IMAXBEL
909 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
910 #else
911 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
912 #endif
913 port.c_iflag |= (IGNBRK);
915 port.c_oflag &= ~(OPOST);
917 port.c_cflag &= ~(HUPCL);
918 port.c_cflag |= CLOCAL | CREAD;
920 port.c_lflag &= ~(ICANON|ECHO|ISIG);
921 port.c_lflag |= NOFLSH;
923 #ifdef CBAUD
924 port.c_cflag &= ~CBAUD;
925 switch (lpdcb->BaudRate) {
926 case 110:
927 case CBR_110:
928 port.c_cflag |= B110;
929 break;
930 case 300:
931 case CBR_300:
932 port.c_cflag |= B300;
933 break;
934 case 600:
935 case CBR_600:
936 port.c_cflag |= B600;
937 break;
938 case 1200:
939 case CBR_1200:
940 port.c_cflag |= B1200;
941 break;
942 case 2400:
943 case CBR_2400:
944 port.c_cflag |= B2400;
945 break;
946 case 4800:
947 case CBR_4800:
948 port.c_cflag |= B4800;
949 break;
950 case 9600:
951 case CBR_9600:
952 port.c_cflag |= B9600;
953 break;
954 case 19200:
955 case CBR_19200:
956 port.c_cflag |= B19200;
957 break;
958 case 38400:
959 case CBR_38400:
960 port.c_cflag |= B38400;
961 break;
962 #ifdef B57600
963 case 57600:
964 port.c_cflag |= B57600;
965 break;
966 #endif
967 #ifdef B115200
968 case 115200:
969 port.c_cflag |= B115200;
970 break;
971 #endif
972 #ifdef B230400
973 case 230400:
974 port.c_cflag |= B230400;
975 break;
976 #endif
977 #ifdef B460800
978 case 460800:
979 port.c_cflag |= B460800;
980 break;
981 #endif
982 default:
983 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
984 { struct serial_struct nuts;
985 int arby;
986 ioctl(fd, TIOCGSERIAL, &nuts);
987 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
988 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
989 arby = nuts.baud_base / nuts.custom_divisor;
990 nuts.flags &= ~ASYNC_SPD_MASK;
991 nuts.flags |= ASYNC_SPD_CUST;
992 WARN("You (or a program acting at your behest) have specified\n"
993 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
994 "which is as close as we can get by our present understanding of your\n"
995 "hardware. I hope you know what you are doing. Any disruption Wine\n"
996 "has caused to your linux system can be undone with setserial \n"
997 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
998 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
999 ioctl(fd, TIOCSSERIAL, &nuts);
1000 port.c_cflag |= B38400;
1002 break;
1003 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1006 COMM_SetCommError(handle,IE_BAUDRATE);
1007 close( fd );
1008 ERR("baudrate %ld\n",lpdcb->BaudRate);
1009 return FALSE;
1011 #elif !defined(__EMX__)
1012 switch (lpdcb->BaudRate) {
1013 case 110:
1014 case CBR_110:
1015 port.c_ospeed = B110;
1016 break;
1017 case 300:
1018 case CBR_300:
1019 port.c_ospeed = B300;
1020 break;
1021 case 600:
1022 case CBR_600:
1023 port.c_ospeed = B600;
1024 break;
1025 case 1200:
1026 case CBR_1200:
1027 port.c_ospeed = B1200;
1028 break;
1029 case 2400:
1030 case CBR_2400:
1031 port.c_ospeed = B2400;
1032 break;
1033 case 4800:
1034 case CBR_4800:
1035 port.c_ospeed = B4800;
1036 break;
1037 case 9600:
1038 case CBR_9600:
1039 port.c_ospeed = B9600;
1040 break;
1041 case 19200:
1042 case CBR_19200:
1043 port.c_ospeed = B19200;
1044 break;
1045 case 38400:
1046 case CBR_38400:
1047 port.c_ospeed = B38400;
1048 break;
1049 default:
1050 COMM_SetCommError(handle,IE_BAUDRATE);
1051 close( fd );
1052 ERR("baudrate %ld\n",lpdcb->BaudRate);
1053 return FALSE;
1055 port.c_ispeed = port.c_ospeed;
1056 #endif
1057 bytesize=lpdcb->ByteSize;
1058 stopbits=lpdcb->StopBits;
1060 #ifdef CMSPAR
1061 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1062 #else
1063 port.c_cflag &= ~(PARENB | PARODD);
1064 #endif
1065 if (lpdcb->fParity)
1066 port.c_iflag |= INPCK;
1067 else
1068 port.c_iflag &= ~INPCK;
1069 switch (lpdcb->Parity) {
1070 case NOPARITY:
1071 break;
1072 case ODDPARITY:
1073 port.c_cflag |= (PARENB | PARODD);
1074 break;
1075 case EVENPARITY:
1076 port.c_cflag |= PARENB;
1077 break;
1078 #ifdef CMSPAR
1079 /* Linux defines mark/space (stick) parity */
1080 case MARKPARITY:
1081 port.c_cflag |= (PARENB | CMSPAR);
1082 break;
1083 case SPACEPARITY:
1084 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1085 break;
1086 #else
1087 /* try the POSIX way */
1088 case MARKPARITY:
1089 if( stopbits == ONESTOPBIT) {
1090 stopbits = TWOSTOPBITS;
1091 port.c_iflag &= ~INPCK;
1092 } else {
1093 COMM_SetCommError(handle,IE_BYTESIZE);
1094 close( fd );
1095 ERR("Cannot set MARK Parity\n");
1096 return FALSE;
1098 break;
1099 case SPACEPARITY:
1100 if( bytesize < 8) {
1101 bytesize +=1;
1102 port.c_iflag &= ~INPCK;
1103 } else {
1104 COMM_SetCommError(handle,IE_BYTESIZE);
1105 close( fd );
1106 ERR("Cannot set SPACE Parity\n");
1107 return FALSE;
1109 break;
1110 #endif
1111 default:
1112 COMM_SetCommError(handle,IE_BYTESIZE);
1113 close( fd );
1114 ERR("Parity\n");
1115 return FALSE;
1119 port.c_cflag &= ~CSIZE;
1120 switch (bytesize) {
1121 case 5:
1122 port.c_cflag |= CS5;
1123 break;
1124 case 6:
1125 port.c_cflag |= CS6;
1126 break;
1127 case 7:
1128 port.c_cflag |= CS7;
1129 break;
1130 case 8:
1131 port.c_cflag |= CS8;
1132 break;
1133 default:
1134 COMM_SetCommError(handle,IE_BYTESIZE);
1135 close( fd );
1136 ERR("ByteSize\n");
1137 return FALSE;
1140 switch (stopbits) {
1141 case ONESTOPBIT:
1142 port.c_cflag &= ~CSTOPB;
1143 break;
1144 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1145 case TWOSTOPBITS:
1146 port.c_cflag |= CSTOPB;
1147 break;
1148 default:
1149 COMM_SetCommError(handle,IE_BYTESIZE);
1150 close( fd );
1151 ERR("StopBits\n");
1152 return FALSE;
1154 #ifdef CRTSCTS
1155 if ( lpdcb->fOutxCtsFlow ||
1156 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1159 port.c_cflag |= CRTSCTS;
1160 TRACE("CRTSCTS\n");
1162 #endif
1164 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1166 WARN("DSR/DTR flow control not supported\n");
1169 if (lpdcb->fInX)
1170 port.c_iflag |= IXON;
1171 else
1172 port.c_iflag &= ~IXON;
1173 if (lpdcb->fOutX)
1174 port.c_iflag |= IXOFF;
1175 else
1176 port.c_iflag &= ~IXOFF;
1178 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1179 int save_error=errno;
1180 COMM_SetCommError(handle,CE_IOE);
1181 close( fd );
1182 ERR("tcsetattr error '%s'\n", strerror(save_error));
1183 return FALSE;
1184 } else {
1185 COMM_SetCommError(handle,0);
1186 close( fd );
1187 return TRUE;
1192 /*****************************************************************************
1193 * GetCommState (KERNEL32.@)
1195 * Fills in a device control block with information from a communications device.
1197 * RETURNS
1199 * True on success, false if the communication device handle is bad etc
1201 * BUGS
1203 * XonChar and XoffChar are not set.
1205 BOOL WINAPI GetCommState(
1206 HANDLE handle, /* [in] The communications device. */
1207 LPDCB lpdcb) /* [out] The device control block. */
1209 struct termios port;
1210 int fd,speed;
1212 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1214 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1215 if (fd < 0)
1217 ERR("FILE_GetUnixHandle failed\n");
1218 return FALSE;
1220 if (tcgetattr(fd, &port) == -1) {
1221 int save_error=errno;
1222 ERR("tcgetattr error '%s'\n", strerror(save_error));
1223 COMM_SetCommError(handle,CE_IOE);
1224 close( fd );
1225 return FALSE;
1227 close( fd );
1228 #ifndef __EMX__
1229 #ifdef CBAUD
1230 speed= (port.c_cflag & CBAUD);
1231 #else
1232 speed= (cfgetospeed(&port));
1233 #endif
1234 switch (speed) {
1235 case B110:
1236 lpdcb->BaudRate = 110;
1237 break;
1238 case B300:
1239 lpdcb->BaudRate = 300;
1240 break;
1241 case B600:
1242 lpdcb->BaudRate = 600;
1243 break;
1244 case B1200:
1245 lpdcb->BaudRate = 1200;
1246 break;
1247 case B2400:
1248 lpdcb->BaudRate = 2400;
1249 break;
1250 case B4800:
1251 lpdcb->BaudRate = 4800;
1252 break;
1253 case B9600:
1254 lpdcb->BaudRate = 9600;
1255 break;
1256 case B19200:
1257 lpdcb->BaudRate = 19200;
1258 break;
1259 case B38400:
1260 lpdcb->BaudRate = 38400;
1261 break;
1262 #ifdef B57600
1263 case B57600:
1264 lpdcb->BaudRate = 57600;
1265 break;
1266 #endif
1267 #ifdef B115200
1268 case B115200:
1269 lpdcb->BaudRate = 115200;
1270 break;
1271 #endif
1272 #ifdef B230400
1273 case B230400:
1274 lpdcb->BaudRate = 230400;
1275 break;
1276 #endif
1277 #ifdef B460800
1278 case B460800:
1279 lpdcb->BaudRate = 460800;
1280 break;
1281 #endif
1282 default:
1283 ERR("unknown speed %x \n",speed);
1285 #endif
1286 switch (port.c_cflag & CSIZE) {
1287 case CS5:
1288 lpdcb->ByteSize = 5;
1289 break;
1290 case CS6:
1291 lpdcb->ByteSize = 6;
1292 break;
1293 case CS7:
1294 lpdcb->ByteSize = 7;
1295 break;
1296 case CS8:
1297 lpdcb->ByteSize = 8;
1298 break;
1299 default:
1300 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1303 if(port.c_iflag & INPCK)
1304 lpdcb->fParity = TRUE;
1305 else
1306 lpdcb->fParity = FALSE;
1307 #ifdef CMSPAR
1308 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1309 #else
1310 switch (port.c_cflag & (PARENB | PARODD))
1311 #endif
1313 case 0:
1314 lpdcb->Parity = NOPARITY;
1315 break;
1316 case PARENB:
1317 lpdcb->Parity = EVENPARITY;
1318 break;
1319 case (PARENB | PARODD):
1320 lpdcb->Parity = ODDPARITY;
1321 break;
1322 #ifdef CMSPAR
1323 case (PARENB | CMSPAR):
1324 lpdcb->Parity = MARKPARITY;
1325 break;
1326 case (PARENB | PARODD | CMSPAR):
1327 lpdcb->Parity = SPACEPARITY;
1328 break;
1329 #endif
1332 if (port.c_cflag & CSTOPB)
1333 if(lpdcb->ByteSize == 5)
1334 lpdcb->StopBits = ONE5STOPBITS;
1335 else
1336 lpdcb->StopBits = TWOSTOPBITS;
1337 else
1338 lpdcb->StopBits = ONESTOPBIT;
1340 lpdcb->fNull = 0;
1341 lpdcb->fBinary = 1;
1343 /* termios does not support DTR/DSR flow control */
1344 lpdcb->fOutxDsrFlow = 0;
1345 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1347 #ifdef CRTSCTS
1349 if (port.c_cflag & CRTSCTS) {
1350 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1351 lpdcb->fOutxCtsFlow = 1;
1352 } else
1353 #endif
1355 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1356 lpdcb->fOutxCtsFlow = 0;
1358 if (port.c_iflag & IXON)
1359 lpdcb->fInX = 1;
1360 else
1361 lpdcb->fInX = 0;
1363 if (port.c_iflag & IXOFF)
1364 lpdcb->fOutX = 1;
1365 else
1366 lpdcb->fOutX = 0;
1368 lpdcb->XonChar =
1369 lpdcb->XoffChar =
1371 lpdcb->XonLim = 10;
1372 lpdcb->XoffLim = 10;
1374 COMM_SetCommError(handle,0);
1376 TRACE("OK\n");
1378 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1379 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1380 (lpdcb->StopBits == ONESTOPBIT)?1:
1381 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1382 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1383 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1384 #ifdef CRTSCTS
1385 if ( lpdcb->fOutxCtsFlow ||
1386 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1388 TRACE("CRTSCTS\n");
1389 else
1391 TRACE("~CRTSCTS\n");
1393 #endif
1394 return TRUE;
1397 /*****************************************************************************
1398 * TransmitCommChar (KERNEL32.@)
1400 * Transmits a single character in front of any pending characters in the
1401 * output buffer. Usually used to send an interrupt character to a host.
1403 * RETURNS
1405 * True if the call succeeded, false if the previous command character to the
1406 * same device has not been sent yet the handle is bad etc.
1408 * BUGS
1410 * Stub.
1412 BOOL WINAPI TransmitCommChar(
1413 HANDLE hComm, /* [in] The communication device in need of a command character. */
1414 CHAR chTransmit) /* [in] The character to transmit. */
1416 FIXME("(%x,'%c'), stub ! Use win32 handle!\n",hComm,chTransmit);
1417 return TRUE;
1420 /*****************************************************************************
1421 * GetCommTimeouts (KERNEL32.@)
1423 * Obtains the request timeout values for the communications device.
1425 * RETURNS
1427 * True on success, false if communications device handle is bad
1428 * or the target structure is null.
1430 BOOL WINAPI GetCommTimeouts(
1431 HANDLE hComm, /* [in] The communications device. */
1432 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1434 BOOL ret;
1436 TRACE("(%x,%p)\n",hComm,lptimeouts);
1438 if(!lptimeouts)
1440 SetLastError(ERROR_INVALID_PARAMETER);
1441 return FALSE;
1444 SERVER_START_REQ( get_serial_info )
1446 req->handle = hComm;
1447 if ((ret = !wine_server_call_err( req )))
1449 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1450 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1451 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1452 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1453 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1456 SERVER_END_REQ;
1457 return ret;
1460 /*****************************************************************************
1461 * SetCommTimeouts (KERNEL32.@)
1463 * Sets the timeouts used when reading and writing data to/from COMM ports.
1465 * ReadIntervalTimeout
1466 * - converted and passes to linux kernel as c_cc[VTIME]
1467 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1468 * - used in ReadFile to calculate GetOverlappedResult's timeout
1469 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1470 * - used in WriteFile to calculate GetOverlappedResult's timeout
1472 * RETURNS
1474 * True if the timeouts were set, false otherwise.
1476 BOOL WINAPI SetCommTimeouts(
1477 HANDLE hComm, /* [in] handle of COMM device */
1478 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1480 BOOL ret;
1481 int fd;
1482 struct termios tios;
1484 TRACE("(%x,%p)\n",hComm,lptimeouts);
1486 if(!lptimeouts)
1488 SetLastError(ERROR_INVALID_PARAMETER);
1489 return FALSE;
1492 SERVER_START_REQ( set_serial_info )
1494 req->handle = hComm;
1495 req->flags = SERIALINFO_SET_TIMEOUTS;
1496 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1497 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1498 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1499 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1500 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1501 ret = !wine_server_call_err( req );
1503 SERVER_END_REQ;
1504 if (!ret) return FALSE;
1506 /* FIXME: move this stuff to the server */
1507 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1508 if (fd < 0) {
1509 FIXME("no fd for handle = %0x!.\n",hComm);
1510 return FALSE;
1513 if (-1==tcgetattr(fd,&tios)) {
1514 FIXME("tcgetattr on fd %d failed!\n",fd);
1515 return FALSE;
1518 /* VTIME is in 1/10 seconds */
1520 unsigned int ux_timeout;
1522 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1524 ux_timeout = 0;
1526 else
1528 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1529 if(ux_timeout == 0)
1531 ux_timeout = 1; /* must be at least some timeout */
1534 tios.c_cc[VTIME] = ux_timeout;
1537 if (-1==tcsetattr(fd,0,&tios)) {
1538 FIXME("tcsetattr on fd %d failed!\n",fd);
1539 return FALSE;
1541 close(fd);
1542 return TRUE;
1545 /***********************************************************************
1546 * GetCommModemStatus (KERNEL32.@)
1548 * Obtains the four control register bits if supported by the hardware.
1550 * RETURNS
1552 * True if the communications handle was good and for hardware that
1553 * control register access, false otherwise.
1555 BOOL WINAPI GetCommModemStatus(
1556 HANDLE hFile, /* [in] The communications device. */
1557 LPDWORD lpModemStat) /* [out] The control register bits. */
1559 int fd,mstat, result=FALSE;
1561 *lpModemStat=0;
1562 #ifdef TIOCMGET
1563 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
1564 if(fd<0)
1565 return FALSE;
1566 result = ioctl(fd, TIOCMGET, &mstat);
1567 close(fd);
1568 if (result == -1)
1570 WARN("ioctl failed\n");
1571 return FALSE;
1573 #ifdef TIOCM_CTS
1574 if (mstat & TIOCM_CTS)
1575 *lpModemStat |= MS_CTS_ON;
1576 #endif
1577 #ifdef TIOCM_DSR
1578 if (mstat & TIOCM_DSR)
1579 *lpModemStat |= MS_DSR_ON;
1580 #endif
1581 #ifdef TIOCM_RNG
1582 if (mstat & TIOCM_RNG)
1583 *lpModemStat |= MS_RING_ON;
1584 #endif
1585 #ifdef TIOCM_CAR
1586 /*FIXME: Not really sure about RLSD UB 990810*/
1587 if (mstat & TIOCM_CAR)
1588 *lpModemStat |= MS_RLSD_ON;
1589 #endif
1590 TRACE("%04x -> %s%s%s%s\n", mstat,
1591 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1592 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1593 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1594 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1595 return TRUE;
1596 #else
1597 return FALSE;
1598 #endif
1601 /***********************************************************************
1602 * COMM_WaitCommEventService (INTERNAL)
1604 * This function is called while the client is waiting on the
1605 * server, so we can't make any server calls here.
1607 static void COMM_WaitCommEventService(async_private *ovp)
1609 async_commio *commio = (async_commio*) ovp;
1610 LPOVERLAPPED lpOverlapped = commio->lpOverlapped;
1612 TRACE("overlapped %p\n",lpOverlapped);
1614 /* FIXME: detect other events */
1615 *commio->buffer = EV_RXCHAR;
1617 lpOverlapped->Internal = STATUS_SUCCESS;
1621 /***********************************************************************
1622 * COMM_WaitCommEvent (INTERNAL)
1624 * This function must have an lpOverlapped.
1626 static BOOL COMM_WaitCommEvent(
1627 HANDLE hFile, /* [in] handle of comm port to wait for */
1628 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1629 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1631 int fd;
1632 async_commio *ovp;
1634 if(!lpOverlapped)
1636 SetLastError(ERROR_INVALID_PARAMETER);
1637 return FALSE;
1640 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1641 return FALSE;
1643 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
1644 if(fd<0)
1645 return FALSE;
1647 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1648 if(!ovp)
1650 close(fd);
1651 return FALSE;
1654 ovp->async.ops = &commio_async_ops;
1655 ovp->async.handle = hFile;
1656 ovp->async.fd = fd;
1657 ovp->async.type = ASYNC_TYPE_WAIT;
1658 ovp->async.func = COMM_WaitCommEventService;
1659 ovp->async.event = lpOverlapped->hEvent;
1660 ovp->lpOverlapped = lpOverlapped;
1661 ovp->buffer = (char *)lpdwEvents;
1663 lpOverlapped->InternalHigh = 0;
1664 lpOverlapped->Offset = 0;
1665 lpOverlapped->OffsetHigh = 0;
1667 if ( !register_new_async (&ovp->async) )
1668 SetLastError( ERROR_IO_PENDING );
1670 return FALSE;
1673 /***********************************************************************
1674 * WaitCommEvent (KERNEL32.@)
1676 * Wait until something interesting happens on a COMM port.
1677 * Interesting things (events) are set by calling SetCommMask before
1678 * this function is called.
1680 * RETURNS:
1681 * TRUE if successful
1682 * FALSE if failure
1684 * The set of detected events will be written to *lpdwEventMask
1685 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1687 * BUGS:
1688 * Only supports EV_RXCHAR and EV_TXEMPTY
1690 BOOL WINAPI WaitCommEvent(
1691 HANDLE hFile, /* [in] handle of comm port to wait for */
1692 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1693 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1695 OVERLAPPED ov;
1696 int ret;
1698 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1700 if(lpOverlapped)
1701 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1703 /* if there is no overlapped structure, create our own */
1704 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1706 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1708 if(GetLastError()!=STATUS_PENDING)
1710 CloseHandle(ov.hEvent);
1711 return FALSE;
1714 /* wait for the overlapped to complete */
1715 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1716 CloseHandle(ov.hEvent);
1718 return ret;
1721 /***********************************************************************
1722 * GetCommProperties (KERNEL32.@)
1724 * This function fills in a structure with the capabilities of the
1725 * communications port driver.
1727 * RETURNS
1729 * TRUE on success, FALSE on failure
1730 * If successful, the lpCommProp structure be filled in with
1731 * properties of the comm port.
1733 BOOL WINAPI GetCommProperties(
1734 HANDLE hFile, /* [in] handle of the comm port */
1735 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1737 FIXME("(%d %p )\n",hFile,lpCommProp);
1738 if(!lpCommProp)
1739 return FALSE;
1742 * These values should be valid for LINUX's serial driver
1743 * FIXME: Perhaps they deserve an #ifdef LINUX
1745 memset(lpCommProp,0,sizeof(COMMPROP));
1746 lpCommProp->wPacketLength = 1;
1747 lpCommProp->wPacketVersion = 1;
1748 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1749 lpCommProp->dwReserved1 = 0;
1750 lpCommProp->dwMaxTxQueue = 4096;
1751 lpCommProp->dwMaxRxQueue = 4096;
1752 lpCommProp->dwMaxBaud = BAUD_115200;
1753 lpCommProp->dwProvSubType = PST_RS232;
1754 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
1755 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1756 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1757 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1758 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1759 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1760 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1761 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1762 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1763 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1764 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1766 return TRUE;
1769 /***********************************************************************
1770 * FIXME:
1771 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1772 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1773 * This is dependent on the type of COMM port, but since it is doubtful
1774 * anybody will get around to implementing support for fancy serial
1775 * ports in WINE, this is hardcoded for the time being. The name of
1776 * this DLL should be stored in and read from the system registry in
1777 * the hive HKEY_LOCAL_MACHINE, key
1778 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1779 * where ???? is the port number... that is determined by PNP
1780 * The DLL should be loaded when the COMM port is opened, and closed
1781 * when the COMM port is closed. - MJM 20 June 2000
1782 ***********************************************************************/
1783 static CHAR lpszSerialUI[] = "serialui.dll";
1786 /***********************************************************************
1787 * CommConfigDialogA (KERNEL32.@)
1789 * Raises a dialog that allows the user to configure a comm port.
1790 * Fills the COMMCONFIG struct with information specified by the user.
1791 * This function should call a similar routine in the COMM driver...
1793 * RETURNS
1795 * TRUE on success, FALSE on failure
1796 * If successful, the lpCommConfig structure will contain a new
1797 * configuration for the comm port, as specified by the user.
1799 * BUGS
1800 * The library with the CommConfigDialog code is never unloaded.
1801 * Perhaps this should be done when the comm port is closed?
1803 BOOL WINAPI CommConfigDialogA(
1804 LPCSTR lpszDevice, /* [in] name of communications device */
1805 HANDLE hWnd, /* [in] parent window for the dialog */
1806 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1808 FARPROC lpfnCommDialog;
1809 HMODULE hConfigModule;
1810 BOOL r;
1812 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
1814 hConfigModule = LoadLibraryA(lpszSerialUI);
1815 if(!hConfigModule)
1816 return FALSE;
1818 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
1820 if(!lpfnCommDialog)
1821 return FALSE;
1823 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1825 /* UnloadLibrary(hConfigModule); */
1827 return r;
1830 /***********************************************************************
1831 * CommConfigDialogW (KERNEL32.@)
1833 * see CommConfigDialogA for more info
1835 BOOL WINAPI CommConfigDialogW(
1836 LPCWSTR lpszDevice, /* [in] name of communications device */
1837 HANDLE hWnd, /* [in] parent window for the dialog */
1838 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1840 BOOL r;
1841 LPSTR lpDeviceA;
1843 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1844 if(lpDeviceA)
1845 return FALSE;
1846 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
1847 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1848 return r;
1851 /***********************************************************************
1852 * GetCommConfig (KERNEL32.@)
1854 * Fill in the COMMCONFIG structure for the comm port hFile
1856 * RETURNS
1858 * TRUE on success, FALSE on failure
1859 * If successful, lpCommConfig contains the comm port configuration.
1861 * BUGS
1864 BOOL WINAPI GetCommConfig(
1865 HANDLE hFile, /* [in] The communications device. */
1866 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1867 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1868 afterwards the number of bytes copied to the buffer or
1869 the needed size of the buffer. */
1871 BOOL r;
1873 TRACE("(%x %p)\n",hFile,lpCommConfig);
1875 if(lpCommConfig == NULL)
1876 return FALSE;
1878 r = *lpdwSize < sizeof(COMMCONFIG);
1879 *lpdwSize = sizeof(COMMCONFIG);
1880 if(!r)
1881 return FALSE;
1883 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1884 lpCommConfig->wVersion = 1;
1885 lpCommConfig->wReserved = 0;
1886 r = GetCommState(hFile,&lpCommConfig->dcb);
1887 lpCommConfig->dwProviderSubType = PST_RS232;
1888 lpCommConfig->dwProviderOffset = 0;
1889 lpCommConfig->dwProviderSize = 0;
1891 return r;
1894 /***********************************************************************
1895 * SetCommConfig (KERNEL32.@)
1897 * Sets the configuration of the communications device.
1899 * RETURNS
1901 * True on success, false if the handle was bad is not a communications device.
1903 BOOL WINAPI SetCommConfig(
1904 HANDLE hFile, /* [in] The communications device. */
1905 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1906 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1908 TRACE("(%x %p)\n",hFile,lpCommConfig);
1909 return SetCommState(hFile,&lpCommConfig->dcb);
1912 /***********************************************************************
1913 * SetDefaultCommConfigA (KERNEL32.@)
1915 * Initializes the default configuration for the specified communication
1916 * device. (ascii)
1918 * RETURNS
1920 * True if the device was found and the defaults set, false otherwise
1922 BOOL WINAPI SetDefaultCommConfigA(
1923 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1924 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1925 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1927 FARPROC lpfnSetDefaultCommConfig;
1928 HMODULE hConfigModule;
1929 BOOL r;
1931 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1933 hConfigModule = LoadLibraryA(lpszSerialUI);
1934 if(!hConfigModule)
1935 return FALSE;
1937 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
1939 if(! lpfnSetDefaultCommConfig)
1940 return TRUE;
1942 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1944 /* UnloadLibrary(hConfigModule); */
1946 return r;
1950 /***********************************************************************
1951 * SetDefaultCommConfigW (KERNEL32.@)
1953 * Initializes the default configuration for the specified
1954 * communication device. (unicode)
1956 * RETURNS
1959 BOOL WINAPI SetDefaultCommConfigW(
1960 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
1961 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1962 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1964 BOOL r;
1965 LPSTR lpDeviceA;
1967 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
1969 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1970 if(lpDeviceA)
1971 return FALSE;
1972 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
1973 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1974 return r;
1978 /***********************************************************************
1979 * GetDefaultCommConfigA (KERNEL32.@)
1981 * Acquires the default configuration of the specified communication device. (unicode)
1983 * RETURNS
1985 * True on successful reading of the default configuration,
1986 * if the device is not found or the buffer is too small.
1988 BOOL WINAPI GetDefaultCommConfigA(
1989 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
1990 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
1991 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
1992 afterwards the number of bytes copied to the buffer or
1993 the needed size of the buffer. */
1995 LPDCB lpdcb = &(lpCC->dcb);
1996 char temp[40];
1998 if (strncasecmp(lpszName,"COM",3)) {
1999 ERR("not implemented for <%s>\n", lpszName);
2000 return FALSE;
2003 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2004 if (*lpdwSize < sizeof(COMMCONFIG)) {
2005 *lpdwSize = sizeof(COMMCONFIG);
2006 return FALSE;
2009 *lpdwSize = sizeof(COMMCONFIG);
2011 lpCC->dwSize = sizeof(COMMCONFIG);
2012 lpCC->wVersion = 1;
2013 lpCC->dwProviderSubType = PST_RS232;
2014 lpCC->dwProviderOffset = 0L;
2015 lpCC->dwProviderSize = 0L;
2017 sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2018 FIXME("setting %s as default\n", temp);
2020 return BuildCommDCBA( temp, lpdcb);
2023 /**************************************************************************
2024 * GetDefaultCommConfigW (KERNEL32.@)
2026 * Acquires the default configuration of the specified communication device. (unicode)
2028 * RETURNS
2030 * True on successful reading of the default configuration,
2031 * if the device is not found or the buffer is too small.
2033 BOOL WINAPI GetDefaultCommConfigW(
2034 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2035 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2036 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2037 afterwards the number of bytes copied to the buffer or
2038 the needed size of the buffer. */
2040 BOOL ret = FALSE;
2041 LPSTR lpszNameA;
2043 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2044 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2045 if (lpszNameA)
2047 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2048 HeapFree( GetProcessHeap(), 0, lpszNameA );
2050 return ret;