Add support for the 'title' command.
[wine/gsoc_dplay.git] / dlls / kernel / comm.c
blobef2c257079244dab1cce849929b4e168bbd1f30b
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 /* Some applications call this function with "9600,n,8,1"
172 * not sending the "COM1:" parameter at left of string */
173 if (!strncasecmp(device,"COM",3))
175 if (!device[3]) return FALSE;
176 if (device[4] != ':' && device[4] != ' ') return FALSE;
177 strcpy(temp,device+5);
179 else strcpy(temp,device);
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 #ifdef B57600
1050 case 57600:
1051 case CBR_57600:
1052 port.c_cflag |= B57600;
1053 break;
1054 #endif
1055 #ifdef B115200
1056 case 115200:
1057 case CBR_115200:
1058 port.c_cflag |= B115200;
1059 break;
1060 #endif
1061 #ifdef B230400
1062 case 230400:
1063 port.c_cflag |= B230400;
1064 break;
1065 #endif
1066 #ifdef B460800
1067 case 460800:
1068 port.c_cflag |= B460800;
1069 break;
1070 #endif
1071 default:
1072 COMM_SetCommError(handle,IE_BAUDRATE);
1073 close( fd );
1074 ERR("baudrate %ld\n",lpdcb->BaudRate);
1075 return FALSE;
1077 port.c_ispeed = port.c_ospeed;
1078 #endif
1079 bytesize=lpdcb->ByteSize;
1080 stopbits=lpdcb->StopBits;
1082 #ifdef CMSPAR
1083 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1084 #else
1085 port.c_cflag &= ~(PARENB | PARODD);
1086 #endif
1087 if (lpdcb->fParity)
1088 port.c_iflag |= INPCK;
1089 else
1090 port.c_iflag &= ~INPCK;
1091 switch (lpdcb->Parity) {
1092 case NOPARITY:
1093 break;
1094 case ODDPARITY:
1095 port.c_cflag |= (PARENB | PARODD);
1096 break;
1097 case EVENPARITY:
1098 port.c_cflag |= PARENB;
1099 break;
1100 #ifdef CMSPAR
1101 /* Linux defines mark/space (stick) parity */
1102 case MARKPARITY:
1103 port.c_cflag |= (PARENB | CMSPAR);
1104 break;
1105 case SPACEPARITY:
1106 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1107 break;
1108 #else
1109 /* try the POSIX way */
1110 case MARKPARITY:
1111 if( stopbits == ONESTOPBIT) {
1112 stopbits = TWOSTOPBITS;
1113 port.c_iflag &= ~INPCK;
1114 } else {
1115 COMM_SetCommError(handle,IE_BYTESIZE);
1116 close( fd );
1117 ERR("Cannot set MARK Parity\n");
1118 return FALSE;
1120 break;
1121 case SPACEPARITY:
1122 if( bytesize < 8) {
1123 bytesize +=1;
1124 port.c_iflag &= ~INPCK;
1125 } else {
1126 COMM_SetCommError(handle,IE_BYTESIZE);
1127 close( fd );
1128 ERR("Cannot set SPACE Parity\n");
1129 return FALSE;
1131 break;
1132 #endif
1133 default:
1134 COMM_SetCommError(handle,IE_BYTESIZE);
1135 close( fd );
1136 ERR("Parity\n");
1137 return FALSE;
1141 port.c_cflag &= ~CSIZE;
1142 switch (bytesize) {
1143 case 5:
1144 port.c_cflag |= CS5;
1145 break;
1146 case 6:
1147 port.c_cflag |= CS6;
1148 break;
1149 case 7:
1150 port.c_cflag |= CS7;
1151 break;
1152 case 8:
1153 port.c_cflag |= CS8;
1154 break;
1155 default:
1156 COMM_SetCommError(handle,IE_BYTESIZE);
1157 close( fd );
1158 ERR("ByteSize\n");
1159 return FALSE;
1162 switch (stopbits) {
1163 case ONESTOPBIT:
1164 port.c_cflag &= ~CSTOPB;
1165 break;
1166 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1167 case TWOSTOPBITS:
1168 port.c_cflag |= CSTOPB;
1169 break;
1170 default:
1171 COMM_SetCommError(handle,IE_BYTESIZE);
1172 close( fd );
1173 ERR("StopBits\n");
1174 return FALSE;
1176 #ifdef CRTSCTS
1177 if ( lpdcb->fOutxCtsFlow ||
1178 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1181 port.c_cflag |= CRTSCTS;
1182 TRACE("CRTSCTS\n");
1184 #endif
1186 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1188 WARN("DSR/DTR flow control not supported\n");
1191 if (lpdcb->fInX)
1192 port.c_iflag |= IXON;
1193 else
1194 port.c_iflag &= ~IXON;
1195 if (lpdcb->fOutX)
1196 port.c_iflag |= IXOFF;
1197 else
1198 port.c_iflag &= ~IXOFF;
1200 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1201 int save_error=errno;
1202 COMM_SetCommError(handle,CE_IOE);
1203 close( fd );
1204 ERR("tcsetattr error '%s'\n", strerror(save_error));
1205 return FALSE;
1206 } else {
1207 COMM_SetCommError(handle,0);
1208 close( fd );
1209 return TRUE;
1214 /*****************************************************************************
1215 * GetCommState (KERNEL32.@)
1217 * Fills in a device control block with information from a communications device.
1219 * RETURNS
1221 * True on success, false if the communication device handle is bad etc
1223 * BUGS
1225 * XonChar and XoffChar are not set.
1227 BOOL WINAPI GetCommState(
1228 HANDLE handle, /* [in] The communications device. */
1229 LPDCB lpdcb) /* [out] The device control block. */
1231 struct termios port;
1232 int fd,speed;
1234 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1236 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1237 if (fd < 0)
1239 ERR("FILE_GetUnixHandle failed\n");
1240 return FALSE;
1242 if (tcgetattr(fd, &port) == -1) {
1243 int save_error=errno;
1244 ERR("tcgetattr error '%s'\n", strerror(save_error));
1245 COMM_SetCommError(handle,CE_IOE);
1246 close( fd );
1247 return FALSE;
1249 close( fd );
1250 #ifndef __EMX__
1251 #ifdef CBAUD
1252 speed= (port.c_cflag & CBAUD);
1253 #else
1254 speed= (cfgetospeed(&port));
1255 #endif
1256 switch (speed) {
1257 case B110:
1258 lpdcb->BaudRate = 110;
1259 break;
1260 case B300:
1261 lpdcb->BaudRate = 300;
1262 break;
1263 case B600:
1264 lpdcb->BaudRate = 600;
1265 break;
1266 case B1200:
1267 lpdcb->BaudRate = 1200;
1268 break;
1269 case B2400:
1270 lpdcb->BaudRate = 2400;
1271 break;
1272 case B4800:
1273 lpdcb->BaudRate = 4800;
1274 break;
1275 case B9600:
1276 lpdcb->BaudRate = 9600;
1277 break;
1278 case B19200:
1279 lpdcb->BaudRate = 19200;
1280 break;
1281 case B38400:
1282 lpdcb->BaudRate = 38400;
1283 break;
1284 #ifdef B57600
1285 case B57600:
1286 lpdcb->BaudRate = 57600;
1287 break;
1288 #endif
1289 #ifdef B115200
1290 case B115200:
1291 lpdcb->BaudRate = 115200;
1292 break;
1293 #endif
1294 #ifdef B230400
1295 case B230400:
1296 lpdcb->BaudRate = 230400;
1297 break;
1298 #endif
1299 #ifdef B460800
1300 case B460800:
1301 lpdcb->BaudRate = 460800;
1302 break;
1303 #endif
1304 default:
1305 ERR("unknown speed %x \n",speed);
1307 #endif
1308 switch (port.c_cflag & CSIZE) {
1309 case CS5:
1310 lpdcb->ByteSize = 5;
1311 break;
1312 case CS6:
1313 lpdcb->ByteSize = 6;
1314 break;
1315 case CS7:
1316 lpdcb->ByteSize = 7;
1317 break;
1318 case CS8:
1319 lpdcb->ByteSize = 8;
1320 break;
1321 default:
1322 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1325 if(port.c_iflag & INPCK)
1326 lpdcb->fParity = TRUE;
1327 else
1328 lpdcb->fParity = FALSE;
1329 #ifdef CMSPAR
1330 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1331 #else
1332 switch (port.c_cflag & (PARENB | PARODD))
1333 #endif
1335 case 0:
1336 lpdcb->Parity = NOPARITY;
1337 break;
1338 case PARENB:
1339 lpdcb->Parity = EVENPARITY;
1340 break;
1341 case (PARENB | PARODD):
1342 lpdcb->Parity = ODDPARITY;
1343 break;
1344 #ifdef CMSPAR
1345 case (PARENB | CMSPAR):
1346 lpdcb->Parity = MARKPARITY;
1347 break;
1348 case (PARENB | PARODD | CMSPAR):
1349 lpdcb->Parity = SPACEPARITY;
1350 break;
1351 #endif
1354 if (port.c_cflag & CSTOPB)
1355 if(lpdcb->ByteSize == 5)
1356 lpdcb->StopBits = ONE5STOPBITS;
1357 else
1358 lpdcb->StopBits = TWOSTOPBITS;
1359 else
1360 lpdcb->StopBits = ONESTOPBIT;
1362 lpdcb->fNull = 0;
1363 lpdcb->fBinary = 1;
1365 /* termios does not support DTR/DSR flow control */
1366 lpdcb->fOutxDsrFlow = 0;
1367 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1369 #ifdef CRTSCTS
1371 if (port.c_cflag & CRTSCTS) {
1372 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1373 lpdcb->fOutxCtsFlow = 1;
1374 } else
1375 #endif
1377 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1378 lpdcb->fOutxCtsFlow = 0;
1380 if (port.c_iflag & IXON)
1381 lpdcb->fInX = 1;
1382 else
1383 lpdcb->fInX = 0;
1385 if (port.c_iflag & IXOFF)
1386 lpdcb->fOutX = 1;
1387 else
1388 lpdcb->fOutX = 0;
1390 lpdcb->XonChar =
1391 lpdcb->XoffChar =
1393 lpdcb->XonLim = 10;
1394 lpdcb->XoffLim = 10;
1396 COMM_SetCommError(handle,0);
1398 TRACE("OK\n");
1400 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1401 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1402 (lpdcb->StopBits == ONESTOPBIT)?1:
1403 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1404 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1405 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1406 #ifdef CRTSCTS
1407 if ( lpdcb->fOutxCtsFlow ||
1408 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1410 TRACE("CRTSCTS\n");
1411 else
1413 TRACE("~CRTSCTS\n");
1415 #endif
1416 return TRUE;
1419 /*****************************************************************************
1420 * TransmitCommChar (KERNEL32.@)
1422 * Transmits a single character in front of any pending characters in the
1423 * output buffer. Usually used to send an interrupt character to a host.
1425 * RETURNS
1427 * True if the call succeeded, false if the previous command character to the
1428 * same device has not been sent yet the handle is bad etc.
1430 * BUGS
1432 * Stub.
1434 BOOL WINAPI TransmitCommChar(
1435 HANDLE hComm, /* [in] The communication device in need of a command character. */
1436 CHAR chTransmit) /* [in] The character to transmit. */
1438 BOOL r = FALSE;
1439 int fd;
1441 WARN("(%x,'%c') not perfect!\n",hComm,chTransmit);
1443 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1444 if ( fd < 0 )
1445 SetLastError ( ERROR_INVALID_PARAMETER );
1446 else
1448 r = (1 == write(fd, &chTransmit, 1));
1449 close(fd);
1452 return r;
1456 /*****************************************************************************
1457 * GetCommTimeouts (KERNEL32.@)
1459 * Obtains the request timeout values for the communications device.
1461 * RETURNS
1463 * True on success, false if communications device handle is bad
1464 * or the target structure is null.
1466 BOOL WINAPI GetCommTimeouts(
1467 HANDLE hComm, /* [in] The communications device. */
1468 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1470 BOOL ret;
1472 TRACE("(%x,%p)\n",hComm,lptimeouts);
1474 if(!lptimeouts)
1476 SetLastError(ERROR_INVALID_PARAMETER);
1477 return FALSE;
1480 SERVER_START_REQ( get_serial_info )
1482 req->handle = hComm;
1483 if ((ret = !wine_server_call_err( req )))
1485 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1486 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1487 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1488 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1489 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1492 SERVER_END_REQ;
1493 return ret;
1496 /*****************************************************************************
1497 * SetCommTimeouts (KERNEL32.@)
1499 * Sets the timeouts used when reading and writing data to/from COMM ports.
1501 * ReadIntervalTimeout
1502 * - converted and passes to linux kernel as c_cc[VTIME]
1503 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1504 * - used in ReadFile to calculate GetOverlappedResult's timeout
1505 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1506 * - used in WriteFile to calculate GetOverlappedResult's timeout
1508 * RETURNS
1510 * True if the timeouts were set, false otherwise.
1512 BOOL WINAPI SetCommTimeouts(
1513 HANDLE hComm, /* [in] handle of COMM device */
1514 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1516 BOOL ret;
1517 int fd;
1518 struct termios tios;
1520 TRACE("(%x,%p)\n",hComm,lptimeouts);
1522 if(!lptimeouts)
1524 SetLastError(ERROR_INVALID_PARAMETER);
1525 return FALSE;
1528 SERVER_START_REQ( set_serial_info )
1530 req->handle = hComm;
1531 req->flags = SERIALINFO_SET_TIMEOUTS;
1532 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1533 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1534 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1535 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1536 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1537 ret = !wine_server_call_err( req );
1539 SERVER_END_REQ;
1540 if (!ret) return FALSE;
1542 /* FIXME: move this stuff to the server */
1543 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1544 if (fd < 0) {
1545 FIXME("no fd for handle = %0x!.\n",hComm);
1546 return FALSE;
1549 if (-1==tcgetattr(fd,&tios)) {
1550 FIXME("tcgetattr on fd %d failed!\n",fd);
1551 return FALSE;
1554 /* VTIME is in 1/10 seconds */
1556 unsigned int ux_timeout;
1558 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1560 ux_timeout = 0;
1562 else
1564 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1565 if(ux_timeout == 0)
1567 ux_timeout = 1; /* must be at least some timeout */
1570 tios.c_cc[VTIME] = ux_timeout;
1573 if (-1==tcsetattr(fd,0,&tios)) {
1574 FIXME("tcsetattr on fd %d failed!\n",fd);
1575 return FALSE;
1577 close(fd);
1578 return TRUE;
1581 /***********************************************************************
1582 * GetCommModemStatus (KERNEL32.@)
1584 * Obtains the four control register bits if supported by the hardware.
1586 * RETURNS
1588 * True if the communications handle was good and for hardware that
1589 * control register access, false otherwise.
1591 BOOL WINAPI GetCommModemStatus(
1592 HANDLE hFile, /* [in] The communications device. */
1593 LPDWORD lpModemStat) /* [out] The control register bits. */
1595 int fd,mstat, result=FALSE;
1597 *lpModemStat=0;
1598 #ifdef TIOCMGET
1599 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
1600 if(fd<0)
1601 return FALSE;
1602 result = ioctl(fd, TIOCMGET, &mstat);
1603 close(fd);
1604 if (result == -1)
1606 WARN("ioctl failed\n");
1607 return FALSE;
1609 #ifdef TIOCM_CTS
1610 if (mstat & TIOCM_CTS)
1611 *lpModemStat |= MS_CTS_ON;
1612 #endif
1613 #ifdef TIOCM_DSR
1614 if (mstat & TIOCM_DSR)
1615 *lpModemStat |= MS_DSR_ON;
1616 #endif
1617 #ifdef TIOCM_RNG
1618 if (mstat & TIOCM_RNG)
1619 *lpModemStat |= MS_RING_ON;
1620 #endif
1621 #ifdef TIOCM_CAR
1622 /*FIXME: Not really sure about RLSD UB 990810*/
1623 if (mstat & TIOCM_CAR)
1624 *lpModemStat |= MS_RLSD_ON;
1625 #endif
1626 TRACE("%04x -> %s%s%s%s\n", mstat,
1627 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1628 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1629 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1630 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1631 return TRUE;
1632 #else
1633 return FALSE;
1634 #endif
1637 /***********************************************************************
1638 * COMM_WaitCommEventService (INTERNAL)
1640 * This function is called while the client is waiting on the
1641 * server, so we can't make any server calls here.
1643 static void COMM_WaitCommEventService(async_private *ovp)
1645 async_commio *commio = (async_commio*) ovp;
1646 LPOVERLAPPED lpOverlapped = commio->lpOverlapped;
1648 TRACE("overlapped %p\n",lpOverlapped);
1650 /* FIXME: detect other events */
1651 *commio->buffer = EV_RXCHAR;
1653 lpOverlapped->Internal = STATUS_SUCCESS;
1657 /***********************************************************************
1658 * COMM_WaitCommEvent (INTERNAL)
1660 * This function must have an lpOverlapped.
1662 static BOOL COMM_WaitCommEvent(
1663 HANDLE hFile, /* [in] handle of comm port to wait for */
1664 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1665 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1667 int fd;
1668 async_commio *ovp;
1670 if(!lpOverlapped)
1672 SetLastError(ERROR_INVALID_PARAMETER);
1673 return FALSE;
1676 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1677 return FALSE;
1679 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
1680 if(fd<0)
1681 return FALSE;
1683 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1684 if(!ovp)
1686 close(fd);
1687 return FALSE;
1690 ovp->async.ops = &commio_async_ops;
1691 ovp->async.handle = hFile;
1692 ovp->async.fd = fd;
1693 ovp->async.type = ASYNC_TYPE_WAIT;
1694 ovp->async.func = COMM_WaitCommEventService;
1695 ovp->async.event = lpOverlapped->hEvent;
1696 ovp->lpOverlapped = lpOverlapped;
1697 ovp->buffer = (char *)lpdwEvents;
1699 lpOverlapped->InternalHigh = 0;
1700 lpOverlapped->Offset = 0;
1701 lpOverlapped->OffsetHigh = 0;
1703 if ( !register_new_async (&ovp->async) )
1704 SetLastError( ERROR_IO_PENDING );
1706 return FALSE;
1709 /***********************************************************************
1710 * WaitCommEvent (KERNEL32.@)
1712 * Wait until something interesting happens on a COMM port.
1713 * Interesting things (events) are set by calling SetCommMask before
1714 * this function is called.
1716 * RETURNS:
1717 * TRUE if successful
1718 * FALSE if failure
1720 * The set of detected events will be written to *lpdwEventMask
1721 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1723 * BUGS:
1724 * Only supports EV_RXCHAR and EV_TXEMPTY
1726 BOOL WINAPI WaitCommEvent(
1727 HANDLE hFile, /* [in] handle of comm port to wait for */
1728 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1729 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1731 OVERLAPPED ov;
1732 int ret;
1734 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1736 if(lpOverlapped)
1737 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1739 /* if there is no overlapped structure, create our own */
1740 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1742 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1744 if(GetLastError()!=STATUS_PENDING)
1746 CloseHandle(ov.hEvent);
1747 return FALSE;
1750 /* wait for the overlapped to complete */
1751 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1752 CloseHandle(ov.hEvent);
1754 return ret;
1757 /***********************************************************************
1758 * GetCommProperties (KERNEL32.@)
1760 * This function fills in a structure with the capabilities of the
1761 * communications port driver.
1763 * RETURNS
1765 * TRUE on success, FALSE on failure
1766 * If successful, the lpCommProp structure be filled in with
1767 * properties of the comm port.
1769 BOOL WINAPI GetCommProperties(
1770 HANDLE hFile, /* [in] handle of the comm port */
1771 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1773 FIXME("(%d %p )\n",hFile,lpCommProp);
1774 if(!lpCommProp)
1775 return FALSE;
1778 * These values should be valid for LINUX's serial driver
1779 * FIXME: Perhaps they deserve an #ifdef LINUX
1781 memset(lpCommProp,0,sizeof(COMMPROP));
1782 lpCommProp->wPacketLength = 1;
1783 lpCommProp->wPacketVersion = 1;
1784 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1785 lpCommProp->dwReserved1 = 0;
1786 lpCommProp->dwMaxTxQueue = 4096;
1787 lpCommProp->dwMaxRxQueue = 4096;
1788 lpCommProp->dwMaxBaud = BAUD_115200;
1789 lpCommProp->dwProvSubType = PST_RS232;
1790 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
1791 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1792 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1793 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1794 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1795 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1796 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1797 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1798 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1799 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1800 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1802 return TRUE;
1805 /***********************************************************************
1806 * FIXME:
1807 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1808 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1809 * This is dependent on the type of COMM port, but since it is doubtful
1810 * anybody will get around to implementing support for fancy serial
1811 * ports in WINE, this is hardcoded for the time being. The name of
1812 * this DLL should be stored in and read from the system registry in
1813 * the hive HKEY_LOCAL_MACHINE, key
1814 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1815 * where ???? is the port number... that is determined by PNP
1816 * The DLL should be loaded when the COMM port is opened, and closed
1817 * when the COMM port is closed. - MJM 20 June 2000
1818 ***********************************************************************/
1819 static CHAR lpszSerialUI[] = "serialui.dll";
1822 /***********************************************************************
1823 * CommConfigDialogA (KERNEL32.@)
1825 * Raises a dialog that allows the user to configure a comm port.
1826 * Fills the COMMCONFIG struct with information specified by the user.
1827 * This function should call a similar routine in the COMM driver...
1829 * RETURNS
1831 * TRUE on success, FALSE on failure
1832 * If successful, the lpCommConfig structure will contain a new
1833 * configuration for the comm port, as specified by the user.
1835 * BUGS
1836 * The library with the CommConfigDialog code is never unloaded.
1837 * Perhaps this should be done when the comm port is closed?
1839 BOOL WINAPI CommConfigDialogA(
1840 LPCSTR lpszDevice, /* [in] name of communications device */
1841 HANDLE hWnd, /* [in] parent window for the dialog */
1842 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1844 FARPROC lpfnCommDialog;
1845 HMODULE hConfigModule;
1846 BOOL r;
1848 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
1850 hConfigModule = LoadLibraryA(lpszSerialUI);
1851 if(!hConfigModule)
1852 return FALSE;
1854 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
1856 if(!lpfnCommDialog)
1857 return FALSE;
1859 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1861 /* UnloadLibrary(hConfigModule); */
1863 return r;
1866 /***********************************************************************
1867 * CommConfigDialogW (KERNEL32.@)
1869 * see CommConfigDialogA for more info
1871 BOOL WINAPI CommConfigDialogW(
1872 LPCWSTR lpszDevice, /* [in] name of communications device */
1873 HANDLE hWnd, /* [in] parent window for the dialog */
1874 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1876 BOOL r;
1877 LPSTR lpDeviceA;
1879 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1880 if(lpDeviceA)
1881 return FALSE;
1882 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
1883 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1884 return r;
1887 /***********************************************************************
1888 * GetCommConfig (KERNEL32.@)
1890 * Fill in the COMMCONFIG structure for the comm port hFile
1892 * RETURNS
1894 * TRUE on success, FALSE on failure
1895 * If successful, lpCommConfig contains the comm port configuration.
1897 * BUGS
1900 BOOL WINAPI GetCommConfig(
1901 HANDLE hFile, /* [in] The communications device. */
1902 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1903 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1904 afterwards the number of bytes copied to the buffer or
1905 the needed size of the buffer. */
1907 BOOL r;
1909 TRACE("(%x %p)\n",hFile,lpCommConfig);
1911 if(lpCommConfig == NULL)
1912 return FALSE;
1914 r = *lpdwSize < sizeof(COMMCONFIG);
1915 *lpdwSize = sizeof(COMMCONFIG);
1916 if(!r)
1917 return FALSE;
1919 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1920 lpCommConfig->wVersion = 1;
1921 lpCommConfig->wReserved = 0;
1922 r = GetCommState(hFile,&lpCommConfig->dcb);
1923 lpCommConfig->dwProviderSubType = PST_RS232;
1924 lpCommConfig->dwProviderOffset = 0;
1925 lpCommConfig->dwProviderSize = 0;
1927 return r;
1930 /***********************************************************************
1931 * SetCommConfig (KERNEL32.@)
1933 * Sets the configuration of the communications device.
1935 * RETURNS
1937 * True on success, false if the handle was bad is not a communications device.
1939 BOOL WINAPI SetCommConfig(
1940 HANDLE hFile, /* [in] The communications device. */
1941 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1942 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1944 TRACE("(%x %p)\n",hFile,lpCommConfig);
1945 return SetCommState(hFile,&lpCommConfig->dcb);
1948 /***********************************************************************
1949 * SetDefaultCommConfigA (KERNEL32.@)
1951 * Initializes the default configuration for the specified communication
1952 * device. (ascii)
1954 * RETURNS
1956 * True if the device was found and the defaults set, false otherwise
1958 BOOL WINAPI SetDefaultCommConfigA(
1959 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1960 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1961 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1963 FARPROC lpfnSetDefaultCommConfig;
1964 HMODULE hConfigModule;
1965 BOOL r;
1967 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1969 hConfigModule = LoadLibraryA(lpszSerialUI);
1970 if(!hConfigModule)
1971 return FALSE;
1973 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
1975 if(! lpfnSetDefaultCommConfig)
1976 return TRUE;
1978 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1980 /* UnloadLibrary(hConfigModule); */
1982 return r;
1986 /***********************************************************************
1987 * SetDefaultCommConfigW (KERNEL32.@)
1989 * Initializes the default configuration for the specified
1990 * communication device. (unicode)
1992 * RETURNS
1995 BOOL WINAPI SetDefaultCommConfigW(
1996 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
1997 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1998 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2000 BOOL r;
2001 LPSTR lpDeviceA;
2003 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2005 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2006 if(lpDeviceA)
2007 return FALSE;
2008 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2009 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2010 return r;
2014 /***********************************************************************
2015 * GetDefaultCommConfigA (KERNEL32.@)
2017 * Acquires the default configuration of the specified communication device. (unicode)
2019 * RETURNS
2021 * True on successful reading of the default configuration,
2022 * if the device is not found or the buffer is too small.
2024 BOOL WINAPI GetDefaultCommConfigA(
2025 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2026 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2027 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2028 afterwards the number of bytes copied to the buffer or
2029 the needed size of the buffer. */
2031 LPDCB lpdcb = &(lpCC->dcb);
2032 char temp[40];
2034 if (strncasecmp(lpszName,"COM",3)) {
2035 ERR("not implemented for <%s>\n", lpszName);
2036 return FALSE;
2039 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2040 if (*lpdwSize < sizeof(COMMCONFIG)) {
2041 *lpdwSize = sizeof(COMMCONFIG);
2042 return FALSE;
2045 *lpdwSize = sizeof(COMMCONFIG);
2047 lpCC->dwSize = sizeof(COMMCONFIG);
2048 lpCC->wVersion = 1;
2049 lpCC->dwProviderSubType = PST_RS232;
2050 lpCC->dwProviderOffset = 0L;
2051 lpCC->dwProviderSize = 0L;
2053 sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2054 FIXME("setting %s as default\n", temp);
2056 return BuildCommDCBA( temp, lpdcb);
2059 /**************************************************************************
2060 * GetDefaultCommConfigW (KERNEL32.@)
2062 * Acquires the default configuration of the specified communication device. (unicode)
2064 * RETURNS
2066 * True on successful reading of the default configuration,
2067 * if the device is not found or the buffer is too small.
2069 BOOL WINAPI GetDefaultCommConfigW(
2070 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2071 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2072 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2073 afterwards the number of bytes copied to the buffer or
2074 the needed size of the buffer. */
2076 BOOL ret = FALSE;
2077 LPSTR lpszNameA;
2079 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2080 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2081 if (lpszNameA)
2083 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2084 HeapFree( GetProcessHeap(), 0, lpszNameA );
2086 return ret;