Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / kernel / comm.c
blobdb31aba5215f20df60d975d1f7df47ace1e8a7cb
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 <stdarg.h>
57 #include <stdio.h>
58 #ifdef HAVE_TERMIOS_H
59 #include <termios.h>
60 #endif
61 #include <fcntl.h>
62 #include <string.h>
63 #ifdef HAVE_STRINGS_H
64 # include <strings.h>
65 #endif
66 #include <errno.h>
67 #include <ctype.h>
68 #include <sys/stat.h>
69 #ifdef HAVE_SYS_FILIO_H
70 # include <sys/filio.h>
71 #endif
72 #ifdef HAVE_SYS_IOCTL_H
73 #include <sys/ioctl.h>
74 #endif
75 #ifdef HAVE_UNISTD_H
76 # include <unistd.h>
77 #endif
78 #ifdef HAVE_SYS_POLL_H
79 # include <sys/poll.h>
80 #endif
81 #ifdef HAVE_SYS_MODEM_H
82 # include <sys/modem.h>
83 #endif
84 #ifdef HAVE_SYS_STRTIO_H
85 # include <sys/strtio.h>
86 #endif
88 #define NONAMELESSUNION
89 #define NONAMELESSSTRUCT
90 #include "ntstatus.h"
91 #include "windef.h"
92 #include "winbase.h"
93 #include "winerror.h"
95 #include "wine/server.h"
96 #include "async.h"
97 #include "file.h"
98 #include "heap.h"
100 #include "wine/debug.h"
102 #ifdef HAVE_LINUX_SERIAL_H
103 #include <linux/serial.h>
104 #endif
106 WINE_DEFAULT_DEBUG_CHANNEL(comm);
108 /***********************************************************************
109 * Asynchronous I/O for asynchronous wait requests *
112 static DWORD commio_get_async_count (const async_private *ovp);
113 static void commio_async_cleanup (async_private *ovp);
115 static async_ops commio_async_ops =
117 commio_get_async_count, /* get_count */
118 NULL, /* call_completion */
119 commio_async_cleanup /* cleanup */
122 typedef struct async_commio
124 struct async_private async;
125 char *buffer;
126 } async_commio;
128 static DWORD commio_get_async_count (const struct async_private *ovp)
130 return 0;
133 static void commio_async_cleanup (async_private *ovp)
135 HeapFree(GetProcessHeap(), 0, ovp );
138 /***********************************************************************/
140 #if !defined(TIOCINQ) && defined(FIONREAD)
141 #define TIOCINQ FIONREAD
142 #endif
144 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
146 #ifdef TIOCMGET
147 unsigned int mstat, okay;
148 okay = ioctl(fd, TIOCMGET, &mstat);
149 if (okay) return okay;
150 if (andy) mstat &= andy;
151 mstat |= orrie;
152 return ioctl(fd, TIOCMSET, &mstat);
153 #else
154 return 0;
155 #endif
158 /***********************************************************************
159 * COMM_BuildOldCommDCB (Internal)
161 * Build a DCB using the old style settings string eg: "COMx:96,n,8,1"
162 * We ignore the COM port index, since we can support more than 4 ports.
164 BOOL WINAPI COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
166 /* "COM1:96,n,8,1" */
167 /* 012345 */
168 char *ptr, temp[256], last;
169 int rate;
171 TRACE("(%s), ptr %p\n", device, lpdcb);
173 /* Some applications call this function with "9600,n,8,1"
174 * not sending the "COM1:" parameter at left of string */
175 if (!strncasecmp(device,"COM",3))
177 if (!device[3]) return FALSE;
178 if (device[4] != ':' && device[4] != ' ') return FALSE;
179 strcpy(temp,device+5);
181 else strcpy(temp,device);
183 last=temp[strlen(temp)-1];
184 ptr = strtok(temp, ", ");
186 /* DOS/Windows only compares the first two numbers
187 * and assigns an appropriate baud rate.
188 * You can supply 961324245, it still returns 9600 ! */
189 if (strlen(ptr) < 2)
191 WARN("Unknown baudrate string '%s' !\n", ptr);
192 return FALSE; /* error: less than 2 chars */
194 ptr[2] = '\0';
195 rate = atoi(ptr);
197 switch (rate) {
198 case 11:
199 case 30:
200 case 60:
201 rate *= 10;
202 break;
203 case 12:
204 case 24:
205 case 48:
206 case 96:
207 rate *= 100;
208 break;
209 case 19:
210 rate = 19200;
211 break;
212 default:
213 WARN("Unknown baudrate indicator %d !\n", rate);
214 return FALSE;
217 lpdcb->BaudRate = rate;
218 TRACE("baudrate (%ld)\n", lpdcb->BaudRate);
220 ptr = strtok(NULL, ", ");
221 if (islower(*ptr))
222 *ptr = toupper(*ptr);
224 TRACE("parity (%c)\n", *ptr);
225 lpdcb->fParity = TRUE;
226 switch (*ptr) {
227 case 'N':
228 lpdcb->Parity = NOPARITY;
229 lpdcb->fParity = FALSE;
230 break;
231 case 'E':
232 lpdcb->Parity = EVENPARITY;
233 break;
234 case 'M':
235 lpdcb->Parity = MARKPARITY;
236 break;
237 case 'O':
238 lpdcb->Parity = ODDPARITY;
239 break;
240 case 'S':
241 lpdcb->Parity = SPACEPARITY;
242 break;
243 default:
244 WARN("Unknown parity `%c'!\n", *ptr);
245 return FALSE;
248 ptr = strtok(NULL, ", ");
249 TRACE("charsize (%c)\n", *ptr);
250 lpdcb->ByteSize = *ptr - '0';
252 ptr = strtok(NULL, ", ");
253 TRACE("stopbits (%c)\n", *ptr);
254 switch (*ptr) {
255 case '1':
256 lpdcb->StopBits = ONESTOPBIT;
257 break;
258 case '2':
259 lpdcb->StopBits = TWOSTOPBITS;
260 break;
261 default:
262 WARN("Unknown # of stopbits `%c'!\n", *ptr);
263 return FALSE;
266 if (last == 'x') {
267 lpdcb->fInX = TRUE;
268 lpdcb->fOutX = TRUE;
269 lpdcb->fOutxCtsFlow = FALSE;
270 lpdcb->fOutxDsrFlow = FALSE;
271 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
272 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
273 } else if (last=='p') {
274 lpdcb->fInX = FALSE;
275 lpdcb->fOutX = FALSE;
276 lpdcb->fOutxCtsFlow = TRUE;
277 lpdcb->fOutxDsrFlow = FALSE;
278 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
279 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
280 } else {
281 lpdcb->fInX = FALSE;
282 lpdcb->fOutX = FALSE;
283 lpdcb->fOutxCtsFlow = FALSE;
284 lpdcb->fOutxDsrFlow = FALSE;
285 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
286 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
289 return TRUE;
292 /**************************************************************************
293 * BuildCommDCBA (KERNEL32.@)
295 * Updates a device control block data structure with values from an
296 * ascii device control string. The device control string has two forms
297 * normal and extended, it must be exclusively in one or the other form.
299 * RETURNS
301 * True on success, false on a malformed control string.
303 BOOL WINAPI BuildCommDCBA(
304 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
305 LPDCB lpdcb) /* [out] The device control block to be updated. */
307 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
310 /**************************************************************************
311 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
313 * Updates a device control block data structure with values from an
314 * ascii device control string. Taking timeout values from a timeouts
315 * struct if desired by the control string.
317 * RETURNS
319 * True on success, false bad handles etc
321 BOOL WINAPI BuildCommDCBAndTimeoutsA(
322 LPCSTR device, /* [in] The ascii device control string. */
323 LPDCB lpdcb, /* [out] The device control block to be updated. */
324 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
326 int port;
327 char *ptr,*temp;
329 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
331 if (!strncasecmp(device,"COM",3)) {
332 port=device[3]-'0';
333 if (port--==0) {
334 ERR("BUG! COM0 can't exist!\n");
335 return FALSE;
337 if ((*(device+4)!=':') && (*(device+4)!=' '))
338 return FALSE;
339 temp=(LPSTR)(device+5);
340 } else
341 temp=(LPSTR)device;
343 memset(lpdcb,0,sizeof (DCB));
344 lpdcb->DCBlength = sizeof(DCB);
345 if (strchr(temp,',')) { /* old style */
347 return COMM_BuildOldCommDCB(device,lpdcb);
349 ptr=strtok(temp," ");
350 while (ptr) {
351 DWORD flag,x;
353 flag=0;
354 if (!strncasecmp("baud=",ptr,5)) {
355 if (!sscanf(ptr+5,"%ld",&x))
356 WARN("Couldn't parse %s\n",ptr);
357 lpdcb->BaudRate = x;
358 flag=1;
360 if (!strncasecmp("stop=",ptr,5)) {
361 if (!sscanf(ptr+5,"%ld",&x))
362 WARN("Couldn't parse %s\n",ptr);
363 lpdcb->StopBits = x;
364 flag=1;
366 if (!strncasecmp("data=",ptr,5)) {
367 if (!sscanf(ptr+5,"%ld",&x))
368 WARN("Couldn't parse %s\n",ptr);
369 lpdcb->ByteSize = x;
370 flag=1;
372 if (!strncasecmp("parity=",ptr,7)) {
373 lpdcb->fParity = TRUE;
374 switch (ptr[7]) {
375 case 'N':case 'n':
376 lpdcb->fParity = FALSE;
377 lpdcb->Parity = NOPARITY;
378 break;
379 case 'E':case 'e':
380 lpdcb->Parity = EVENPARITY;
381 break;
382 case 'O':case 'o':
383 lpdcb->Parity = ODDPARITY;
384 break;
385 case 'M':case 'm':
386 lpdcb->Parity = MARKPARITY;
387 break;
388 case 'S':case 's':
389 lpdcb->Parity = SPACEPARITY;
390 break;
392 flag=1;
394 if (!flag)
395 ERR("Unhandled specifier '%s', please report.\n",ptr);
396 ptr=strtok(NULL," ");
398 if (lpdcb->BaudRate==110)
399 lpdcb->StopBits = 2;
400 return TRUE;
403 /**************************************************************************
404 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
406 * Updates a device control block data structure with values from an
407 * unicode device control string. Taking timeout values from a timeouts
408 * struct if desired by the control string.
410 * RETURNS
412 * True on success, false bad handles etc.
414 BOOL WINAPI BuildCommDCBAndTimeoutsW(
415 LPCWSTR devid, /* [in] The unicode device control string. */
416 LPDCB lpdcb, /* [out] The device control block to be updated. */
417 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
419 BOOL ret = FALSE;
420 LPSTR devidA;
422 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
423 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
424 if (devidA)
426 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
427 HeapFree( GetProcessHeap(), 0, devidA );
429 return ret;
432 /**************************************************************************
433 * BuildCommDCBW (KERNEL32.@)
435 * Updates a device control block structure with values from an
436 * unicode device control string. The device control string has two forms
437 * normal and extended, it must be exclusively in one or the other form.
439 * RETURNS
441 * True on success, false on an malformed control string.
443 BOOL WINAPI BuildCommDCBW(
444 LPCWSTR devid, /* [in] The unicode device control string. */
445 LPDCB lpdcb) /* [out] The device control block to be updated. */
447 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
450 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
452 DWORD ret;
454 SERVER_START_REQ( set_serial_info )
456 req->handle = handle;
457 req->flags = SERIALINFO_SET_ERROR;
458 req->commerror = error;
459 ret = !wine_server_call_err( req );
461 SERVER_END_REQ;
462 return ret;
465 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
467 DWORD ret;
469 if(!lperror)
470 return FALSE;
472 SERVER_START_REQ( get_serial_info )
474 req->handle = handle;
475 ret = !wine_server_call_err( req );
476 *lperror = reply->commerror;
478 SERVER_END_REQ;
480 return ret;
483 /*****************************************************************************
484 * SetCommBreak (KERNEL32.@)
486 * Halts the transmission of characters to a communications device.
488 * RETURNS
490 * True on success, and false if the communications device could not be found,
491 * the control is not supported.
493 * BUGS
495 * Only TIOCSBRK and TIOCCBRK are supported.
497 BOOL WINAPI SetCommBreak(
498 HANDLE handle) /* [in] The communictions device to suspend. */
500 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
501 int fd,result;
503 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
504 if(fd<0) {
505 TRACE("FILE_GetUnixHandle failed\n");
506 return FALSE;
508 result = ioctl(fd,TIOCSBRK,0);
509 close(fd);
510 if (result ==-1)
512 TRACE("ioctl failed\n");
513 SetLastError(ERROR_NOT_SUPPORTED);
514 return FALSE;
516 return TRUE;
517 #else
518 FIXME("ioctl not available\n");
519 SetLastError(ERROR_NOT_SUPPORTED);
520 return FALSE;
521 #endif
524 /*****************************************************************************
525 * ClearCommBreak (KERNEL32.@)
527 * Resumes character transmission from a communication device.
529 * RETURNS
531 * True on success and false if the communications device could not be found.
533 * BUGS
535 * Only TIOCSBRK and TIOCCBRK are supported.
537 BOOL WINAPI ClearCommBreak(
538 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
540 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
541 int fd,result;
543 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
544 if(fd<0) {
545 TRACE("FILE_GetUnixHandle failed\n");
546 return FALSE;
548 result = ioctl(fd,TIOCCBRK,0);
549 close(fd);
550 if (result ==-1)
552 TRACE("ioctl failed\n");
553 SetLastError(ERROR_NOT_SUPPORTED);
554 return FALSE;
556 return TRUE;
557 #else
558 FIXME("ioctl not available\n");
559 SetLastError(ERROR_NOT_SUPPORTED);
560 return FALSE;
561 #endif
564 /*****************************************************************************
565 * EscapeCommFunction (KERNEL32.@)
567 * Directs a communication device to perform an extended function.
569 * RETURNS
571 * True or requested data on successful completion of the command,
572 * false if the device is not present cannot execute the command
573 * or the command failed.
575 BOOL WINAPI EscapeCommFunction(
576 HANDLE handle, /* [in] The communication device to perform the extended function. */
577 UINT nFunction) /* [in] The extended function to be performed. */
579 int fd,direct=FALSE,result=FALSE;
580 struct termios port;
582 TRACE("handle %p, function=%d\n", handle, nFunction);
583 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
584 if(fd<0) {
585 FIXME("handle %p not found.\n",handle);
586 return FALSE;
589 if (tcgetattr(fd,&port) == -1) {
590 COMM_SetCommError(handle,CE_IOE);
591 close(fd);
592 return FALSE;
595 switch (nFunction) {
596 case RESETDEV:
597 TRACE("\n");
598 break;
600 case CLRDTR:
601 TRACE("CLRDTR\n");
602 #ifdef TIOCM_DTR
603 direct=TRUE;
604 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
605 break;
606 #endif
608 case CLRRTS:
609 TRACE("CLRRTS\n");
610 #ifdef TIOCM_RTS
611 direct=TRUE;
612 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
613 break;
614 #endif
616 case SETDTR:
617 TRACE("SETDTR\n");
618 #ifdef TIOCM_DTR
619 direct=TRUE;
620 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
621 break;
622 #endif
624 case SETRTS:
625 TRACE("SETRTS\n");
626 #ifdef TIOCM_RTS
627 direct=TRUE;
628 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
629 break;
630 #endif
632 case SETXOFF:
633 TRACE("SETXOFF\n");
634 port.c_iflag |= IXOFF;
635 break;
637 case SETXON:
638 TRACE("SETXON\n");
639 port.c_iflag |= IXON;
640 break;
641 case SETBREAK:
642 TRACE("setbreak\n");
643 #ifdef TIOCSBRK
644 direct=TRUE;
645 result = ioctl(fd,TIOCSBRK,0);
646 break;
647 #endif
648 case CLRBREAK:
649 TRACE("clrbreak\n");
650 #ifdef TIOCSBRK
651 direct=TRUE;
652 result = ioctl(fd,TIOCCBRK,0);
653 break;
654 #endif
655 default:
656 WARN("(handle=%p,nFunction=%d): Unknown function\n",
657 handle, nFunction);
658 break;
661 if (!direct)
662 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
663 close(fd);
664 COMM_SetCommError(handle,CE_IOE);
665 return FALSE;
666 } else
667 result= TRUE;
668 else
670 if (result == -1)
672 result= FALSE;
673 COMM_SetCommError(handle,CE_IOE);
675 else
676 result = TRUE;
678 close(fd);
679 return result;
682 /********************************************************************
683 * PurgeComm (KERNEL32.@)
685 * Terminates pending operations and/or discards buffers on a
686 * communication resource.
688 * RETURNS
690 * True on success and false if the communications handle is bad.
692 BOOL WINAPI PurgeComm(
693 HANDLE handle, /* [in] The communication resource to be purged. */
694 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
696 int fd;
698 TRACE("handle %p, flags %lx\n", handle, flags);
700 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
701 if(fd<0) {
702 FIXME("no handle %p found\n",handle);
703 return FALSE;
707 ** not exactly sure how these are different
708 ** Perhaps if we had our own internal queues, one flushes them
709 ** and the other flushes the kernel's buffers.
711 if(flags&PURGE_TXABORT)
712 tcflush(fd,TCOFLUSH);
713 if(flags&PURGE_RXABORT)
714 tcflush(fd,TCIFLUSH);
715 if(flags&PURGE_TXCLEAR)
716 tcflush(fd,TCOFLUSH);
717 if(flags&PURGE_RXCLEAR)
718 tcflush(fd,TCIFLUSH);
719 close(fd);
721 return 1;
724 /*****************************************************************************
725 * ClearCommError (KERNEL32.@)
727 * Enables further I/O operations on a communications resource after
728 * supplying error and current status information.
730 * RETURNS
732 * True on success, false if the communication resource handle is bad.
734 BOOL WINAPI ClearCommError(
735 HANDLE handle, /* [in] The communication resource with the error. */
736 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
737 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
739 int fd;
741 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
742 if(0>fd)
744 FIXME("no handle %p found\n",handle);
745 return FALSE;
748 if (lpStat)
750 lpStat->fCtsHold = 0;
751 lpStat->fDsrHold = 0;
752 lpStat->fRlsdHold = 0;
753 lpStat->fXoffHold = 0;
754 lpStat->fXoffSent = 0;
755 lpStat->fEof = 0;
756 lpStat->fTxim = 0;
757 lpStat->fReserved = 0;
759 #ifdef TIOCOUTQ
760 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
761 WARN("ioctl returned error\n");
762 #else
763 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
764 #endif
766 #ifdef TIOCINQ
767 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
768 WARN("ioctl returned error\n");
769 #endif
771 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
772 handle, lpStat->cbInQue, lpStat->cbOutQue);
775 close(fd);
777 COMM_GetCommError(handle, errors);
778 COMM_SetCommError(handle, 0);
780 return TRUE;
783 /*****************************************************************************
784 * SetupComm (KERNEL32.@)
786 * Called after CreateFile to hint to the communication resource to use
787 * specified sizes for input and output buffers rather than the default values.
789 * RETURNS
791 * True if successful, false if the communications resource handle is bad.
793 * BUGS
795 * Stub.
797 BOOL WINAPI SetupComm(
798 HANDLE handle, /* [in] The just created communication resource handle. */
799 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
800 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
802 int fd;
804 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
805 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
806 if(0>fd) {
807 FIXME("handle %p not found?\n",handle);
808 return FALSE;
810 close(fd);
811 return TRUE;
814 /*****************************************************************************
815 * GetCommMask (KERNEL32.@)
817 * Obtain the events associated with a communication device that will cause
818 * a call WaitCommEvent to return.
820 * RETURNS
822 * True on success, fail on bad device handle etc.
824 BOOL WINAPI GetCommMask(
825 HANDLE handle, /* [in] The communications device. */
826 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
828 BOOL ret;
830 TRACE("handle %p, mask %p\n", handle, evtmask);
832 SERVER_START_REQ( get_serial_info )
834 req->handle = handle;
835 if ((ret = !wine_server_call_err( req )))
837 if (evtmask) *evtmask = reply->eventmask;
840 SERVER_END_REQ;
841 return ret;
844 /*****************************************************************************
845 * SetCommMask (KERNEL32.@)
847 * There be some things we need to hear about yon there communications device.
848 * (Set which events associated with a communication device should cause
849 * a call WaitCommEvent to return.)
851 * RETURNS
853 * True on success, false on bad handle etc.
855 BOOL WINAPI SetCommMask(
856 HANDLE handle, /* [in] The communications device. */
857 DWORD evtmask) /* [in] The events that are to be monitored. */
859 BOOL ret;
861 TRACE("handle %p, mask %lx\n", handle, evtmask);
863 SERVER_START_REQ( set_serial_info )
865 req->handle = handle;
866 req->flags = SERIALINFO_SET_MASK;
867 req->eventmask = evtmask;
868 ret = !wine_server_call_err( req );
870 SERVER_END_REQ;
871 return ret;
874 /*****************************************************************************
875 * SetCommState (KERNEL32.@)
877 * Re-initializes all hardware and control settings of a communications device,
878 * with values from a device control block without effecting the input and output
879 * queues.
881 * RETURNS
883 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
885 BOOL WINAPI SetCommState(
886 HANDLE handle, /* [in] The communications device. */
887 LPDCB lpdcb) /* [out] The device control block. */
889 struct termios port;
890 int fd, bytesize, stopbits;
892 TRACE("handle %p, ptr %p\n", handle, lpdcb);
893 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
894 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
895 (lpdcb->StopBits == ONESTOPBIT)?1:
896 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
897 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
898 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
900 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
901 if (fd < 0) {
902 FIXME("no handle %p found\n",handle);
903 return FALSE;
906 if ((tcgetattr(fd,&port)) == -1) {
907 int save_error = errno;
908 COMM_SetCommError(handle,CE_IOE);
909 close( fd );
910 ERR("tcgetattr error '%s'\n", strerror(save_error));
911 return FALSE;
914 port.c_cc[VMIN] = 0;
915 port.c_cc[VTIME] = 1;
917 #ifdef IMAXBEL
918 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
919 #else
920 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
921 #endif
922 port.c_iflag |= (IGNBRK);
924 port.c_oflag &= ~(OPOST);
926 port.c_cflag &= ~(HUPCL);
927 port.c_cflag |= CLOCAL | CREAD;
929 port.c_lflag &= ~(ICANON|ECHO|ISIG);
930 port.c_lflag |= NOFLSH;
932 #ifdef CBAUD
933 port.c_cflag &= ~CBAUD;
934 switch (lpdcb->BaudRate) {
935 case 110:
936 case CBR_110:
937 port.c_cflag |= B110;
938 break;
939 case 300:
940 case CBR_300:
941 port.c_cflag |= B300;
942 break;
943 case 600:
944 case CBR_600:
945 port.c_cflag |= B600;
946 break;
947 case 1200:
948 case CBR_1200:
949 port.c_cflag |= B1200;
950 break;
951 case 2400:
952 case CBR_2400:
953 port.c_cflag |= B2400;
954 break;
955 case 4800:
956 case CBR_4800:
957 port.c_cflag |= B4800;
958 break;
959 case 9600:
960 case CBR_9600:
961 port.c_cflag |= B9600;
962 break;
963 case 19200:
964 case CBR_19200:
965 port.c_cflag |= B19200;
966 break;
967 case 38400:
968 case CBR_38400:
969 port.c_cflag |= B38400;
970 break;
971 #ifdef B57600
972 case 57600:
973 port.c_cflag |= B57600;
974 break;
975 #endif
976 #ifdef B115200
977 case 115200:
978 port.c_cflag |= B115200;
979 break;
980 #endif
981 #ifdef B230400
982 case 230400:
983 port.c_cflag |= B230400;
984 break;
985 #endif
986 #ifdef B460800
987 case 460800:
988 port.c_cflag |= B460800;
989 break;
990 #endif
991 default:
992 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
993 { struct serial_struct nuts;
994 int arby;
995 ioctl(fd, TIOCGSERIAL, &nuts);
996 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
997 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
998 arby = nuts.baud_base / nuts.custom_divisor;
999 nuts.flags &= ~ASYNC_SPD_MASK;
1000 nuts.flags |= ASYNC_SPD_CUST;
1001 WARN("You (or a program acting at your behest) have specified\n"
1002 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1003 "which is as close as we can get by our present understanding of your\n"
1004 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1005 "has caused to your linux system can be undone with setserial \n"
1006 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1007 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1008 ioctl(fd, TIOCSSERIAL, &nuts);
1009 port.c_cflag |= B38400;
1011 break;
1012 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1015 COMM_SetCommError(handle,IE_BAUDRATE);
1016 close( fd );
1017 ERR("baudrate %ld\n",lpdcb->BaudRate);
1018 return FALSE;
1020 #elif !defined(__EMX__)
1021 switch (lpdcb->BaudRate) {
1022 case 110:
1023 case CBR_110:
1024 port.c_ospeed = B110;
1025 break;
1026 case 300:
1027 case CBR_300:
1028 port.c_ospeed = B300;
1029 break;
1030 case 600:
1031 case CBR_600:
1032 port.c_ospeed = B600;
1033 break;
1034 case 1200:
1035 case CBR_1200:
1036 port.c_ospeed = B1200;
1037 break;
1038 case 2400:
1039 case CBR_2400:
1040 port.c_ospeed = B2400;
1041 break;
1042 case 4800:
1043 case CBR_4800:
1044 port.c_ospeed = B4800;
1045 break;
1046 case 9600:
1047 case CBR_9600:
1048 port.c_ospeed = B9600;
1049 break;
1050 case 19200:
1051 case CBR_19200:
1052 port.c_ospeed = B19200;
1053 break;
1054 case 38400:
1055 case CBR_38400:
1056 port.c_ospeed = B38400;
1057 break;
1058 #ifdef B57600
1059 case 57600:
1060 case CBR_57600:
1061 port.c_cflag |= B57600;
1062 break;
1063 #endif
1064 #ifdef B115200
1065 case 115200:
1066 case CBR_115200:
1067 port.c_cflag |= B115200;
1068 break;
1069 #endif
1070 #ifdef B230400
1071 case 230400:
1072 port.c_cflag |= B230400;
1073 break;
1074 #endif
1075 #ifdef B460800
1076 case 460800:
1077 port.c_cflag |= B460800;
1078 break;
1079 #endif
1080 default:
1081 COMM_SetCommError(handle,IE_BAUDRATE);
1082 close( fd );
1083 ERR("baudrate %ld\n",lpdcb->BaudRate);
1084 return FALSE;
1086 port.c_ispeed = port.c_ospeed;
1087 #endif
1088 bytesize=lpdcb->ByteSize;
1089 stopbits=lpdcb->StopBits;
1091 #ifdef CMSPAR
1092 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1093 #else
1094 port.c_cflag &= ~(PARENB | PARODD);
1095 #endif
1096 if (lpdcb->fParity)
1097 port.c_iflag |= INPCK;
1098 else
1099 port.c_iflag &= ~INPCK;
1100 switch (lpdcb->Parity) {
1101 case NOPARITY:
1102 break;
1103 case ODDPARITY:
1104 port.c_cflag |= (PARENB | PARODD);
1105 break;
1106 case EVENPARITY:
1107 port.c_cflag |= PARENB;
1108 break;
1109 #ifdef CMSPAR
1110 /* Linux defines mark/space (stick) parity */
1111 case MARKPARITY:
1112 port.c_cflag |= (PARENB | CMSPAR);
1113 break;
1114 case SPACEPARITY:
1115 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1116 break;
1117 #else
1118 /* try the POSIX way */
1119 case MARKPARITY:
1120 if( stopbits == ONESTOPBIT) {
1121 stopbits = TWOSTOPBITS;
1122 port.c_iflag &= ~INPCK;
1123 } else {
1124 COMM_SetCommError(handle,IE_BYTESIZE);
1125 close( fd );
1126 ERR("Cannot set MARK Parity\n");
1127 return FALSE;
1129 break;
1130 case SPACEPARITY:
1131 if( bytesize < 8) {
1132 bytesize +=1;
1133 port.c_iflag &= ~INPCK;
1134 } else {
1135 COMM_SetCommError(handle,IE_BYTESIZE);
1136 close( fd );
1137 ERR("Cannot set SPACE Parity\n");
1138 return FALSE;
1140 break;
1141 #endif
1142 default:
1143 COMM_SetCommError(handle,IE_BYTESIZE);
1144 close( fd );
1145 ERR("Parity\n");
1146 return FALSE;
1150 port.c_cflag &= ~CSIZE;
1151 switch (bytesize) {
1152 case 5:
1153 port.c_cflag |= CS5;
1154 break;
1155 case 6:
1156 port.c_cflag |= CS6;
1157 break;
1158 case 7:
1159 port.c_cflag |= CS7;
1160 break;
1161 case 8:
1162 port.c_cflag |= CS8;
1163 break;
1164 default:
1165 COMM_SetCommError(handle,IE_BYTESIZE);
1166 close( fd );
1167 ERR("ByteSize\n");
1168 return FALSE;
1171 switch (stopbits) {
1172 case ONESTOPBIT:
1173 port.c_cflag &= ~CSTOPB;
1174 break;
1175 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1176 case TWOSTOPBITS:
1177 port.c_cflag |= CSTOPB;
1178 break;
1179 default:
1180 COMM_SetCommError(handle,IE_BYTESIZE);
1181 close( fd );
1182 ERR("StopBits\n");
1183 return FALSE;
1185 #ifdef CRTSCTS
1186 if ( lpdcb->fOutxCtsFlow ||
1187 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1190 port.c_cflag |= CRTSCTS;
1191 TRACE("CRTSCTS\n");
1193 #endif
1195 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1197 WARN("DSR/DTR flow control not supported\n");
1200 if (lpdcb->fInX)
1201 port.c_iflag |= IXON;
1202 else
1203 port.c_iflag &= ~IXON;
1204 if (lpdcb->fOutX)
1205 port.c_iflag |= IXOFF;
1206 else
1207 port.c_iflag &= ~IXOFF;
1209 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1210 int save_error=errno;
1211 COMM_SetCommError(handle,CE_IOE);
1212 close( fd );
1213 ERR("tcsetattr error '%s'\n", strerror(save_error));
1214 return FALSE;
1215 } else {
1216 COMM_SetCommError(handle,0);
1217 close( fd );
1218 return TRUE;
1223 /*****************************************************************************
1224 * GetCommState (KERNEL32.@)
1226 * Fills in a device control block with information from a communications device.
1228 * RETURNS
1230 * True on success, false if the communication device handle is bad etc
1232 * BUGS
1234 * XonChar and XoffChar are not set.
1236 BOOL WINAPI GetCommState(
1237 HANDLE handle, /* [in] The communications device. */
1238 LPDCB lpdcb) /* [out] The device control block. */
1240 struct termios port;
1241 int fd,speed;
1243 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1245 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1246 if (fd < 0)
1248 ERR("FILE_GetUnixHandle failed\n");
1249 return FALSE;
1251 if (tcgetattr(fd, &port) == -1) {
1252 int save_error=errno;
1253 ERR("tcgetattr error '%s'\n", strerror(save_error));
1254 COMM_SetCommError(handle,CE_IOE);
1255 close( fd );
1256 return FALSE;
1258 close( fd );
1259 #ifndef __EMX__
1260 #ifdef CBAUD
1261 speed= (port.c_cflag & CBAUD);
1262 #else
1263 speed= (cfgetospeed(&port));
1264 #endif
1265 switch (speed) {
1266 case B110:
1267 lpdcb->BaudRate = 110;
1268 break;
1269 case B300:
1270 lpdcb->BaudRate = 300;
1271 break;
1272 case B600:
1273 lpdcb->BaudRate = 600;
1274 break;
1275 case B1200:
1276 lpdcb->BaudRate = 1200;
1277 break;
1278 case B2400:
1279 lpdcb->BaudRate = 2400;
1280 break;
1281 case B4800:
1282 lpdcb->BaudRate = 4800;
1283 break;
1284 case B9600:
1285 lpdcb->BaudRate = 9600;
1286 break;
1287 case B19200:
1288 lpdcb->BaudRate = 19200;
1289 break;
1290 case B38400:
1291 lpdcb->BaudRate = 38400;
1292 break;
1293 #ifdef B57600
1294 case B57600:
1295 lpdcb->BaudRate = 57600;
1296 break;
1297 #endif
1298 #ifdef B115200
1299 case B115200:
1300 lpdcb->BaudRate = 115200;
1301 break;
1302 #endif
1303 #ifdef B230400
1304 case B230400:
1305 lpdcb->BaudRate = 230400;
1306 break;
1307 #endif
1308 #ifdef B460800
1309 case B460800:
1310 lpdcb->BaudRate = 460800;
1311 break;
1312 #endif
1313 default:
1314 ERR("unknown speed %x \n",speed);
1316 #endif
1317 switch (port.c_cflag & CSIZE) {
1318 case CS5:
1319 lpdcb->ByteSize = 5;
1320 break;
1321 case CS6:
1322 lpdcb->ByteSize = 6;
1323 break;
1324 case CS7:
1325 lpdcb->ByteSize = 7;
1326 break;
1327 case CS8:
1328 lpdcb->ByteSize = 8;
1329 break;
1330 default:
1331 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1334 if(port.c_iflag & INPCK)
1335 lpdcb->fParity = TRUE;
1336 else
1337 lpdcb->fParity = FALSE;
1338 #ifdef CMSPAR
1339 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1340 #else
1341 switch (port.c_cflag & (PARENB | PARODD))
1342 #endif
1344 case 0:
1345 lpdcb->Parity = NOPARITY;
1346 break;
1347 case PARENB:
1348 lpdcb->Parity = EVENPARITY;
1349 break;
1350 case (PARENB | PARODD):
1351 lpdcb->Parity = ODDPARITY;
1352 break;
1353 #ifdef CMSPAR
1354 case (PARENB | CMSPAR):
1355 lpdcb->Parity = MARKPARITY;
1356 break;
1357 case (PARENB | PARODD | CMSPAR):
1358 lpdcb->Parity = SPACEPARITY;
1359 break;
1360 #endif
1363 if (port.c_cflag & CSTOPB)
1364 if(lpdcb->ByteSize == 5)
1365 lpdcb->StopBits = ONE5STOPBITS;
1366 else
1367 lpdcb->StopBits = TWOSTOPBITS;
1368 else
1369 lpdcb->StopBits = ONESTOPBIT;
1371 lpdcb->fNull = 0;
1372 lpdcb->fBinary = 1;
1374 /* termios does not support DTR/DSR flow control */
1375 lpdcb->fOutxDsrFlow = 0;
1376 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1378 #ifdef CRTSCTS
1380 if (port.c_cflag & CRTSCTS) {
1381 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1382 lpdcb->fOutxCtsFlow = 1;
1383 } else
1384 #endif
1386 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1387 lpdcb->fOutxCtsFlow = 0;
1389 if (port.c_iflag & IXON)
1390 lpdcb->fInX = 1;
1391 else
1392 lpdcb->fInX = 0;
1394 if (port.c_iflag & IXOFF)
1395 lpdcb->fOutX = 1;
1396 else
1397 lpdcb->fOutX = 0;
1399 lpdcb->XonChar =
1400 lpdcb->XoffChar =
1402 lpdcb->XonLim = 10;
1403 lpdcb->XoffLim = 10;
1405 COMM_SetCommError(handle,0);
1407 TRACE("OK\n");
1409 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1410 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1411 (lpdcb->StopBits == ONESTOPBIT)?1:
1412 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1413 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1414 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1415 #ifdef CRTSCTS
1416 if ( lpdcb->fOutxCtsFlow ||
1417 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1419 TRACE("CRTSCTS\n");
1420 else
1422 TRACE("~CRTSCTS\n");
1424 #endif
1425 return TRUE;
1428 /*****************************************************************************
1429 * TransmitCommChar (KERNEL32.@)
1431 * Transmits a single character in front of any pending characters in the
1432 * output buffer. Usually used to send an interrupt character to a host.
1434 * RETURNS
1436 * True if the call succeeded, false if the previous command character to the
1437 * same device has not been sent yet the handle is bad etc.
1439 * BUGS
1441 * Stub.
1443 BOOL WINAPI TransmitCommChar(
1444 HANDLE hComm, /* [in] The communication device in need of a command character. */
1445 CHAR chTransmit) /* [in] The character to transmit. */
1447 BOOL r = FALSE;
1448 int fd;
1450 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1452 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1453 if ( fd < 0 )
1454 SetLastError ( ERROR_INVALID_PARAMETER );
1455 else
1457 r = (1 == write(fd, &chTransmit, 1));
1458 close(fd);
1461 return r;
1465 /*****************************************************************************
1466 * GetCommTimeouts (KERNEL32.@)
1468 * Obtains the request timeout values for the communications device.
1470 * RETURNS
1472 * True on success, false if communications device handle is bad
1473 * or the target structure is null.
1475 BOOL WINAPI GetCommTimeouts(
1476 HANDLE hComm, /* [in] The communications device. */
1477 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1479 BOOL ret;
1481 TRACE("(%p,%p)\n",hComm,lptimeouts);
1483 if(!lptimeouts)
1485 SetLastError(ERROR_INVALID_PARAMETER);
1486 return FALSE;
1489 SERVER_START_REQ( get_serial_info )
1491 req->handle = hComm;
1492 if ((ret = !wine_server_call_err( req )))
1494 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1495 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1496 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1497 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1498 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1501 SERVER_END_REQ;
1502 return ret;
1505 /*****************************************************************************
1506 * SetCommTimeouts (KERNEL32.@)
1508 * Sets the timeouts used when reading and writing data to/from COMM ports.
1510 * ReadIntervalTimeout
1511 * - converted and passes to linux kernel as c_cc[VTIME]
1512 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1513 * - used in ReadFile to calculate GetOverlappedResult's timeout
1514 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1515 * - used in WriteFile to calculate GetOverlappedResult's timeout
1517 * RETURNS
1519 * True if the timeouts were set, false otherwise.
1521 BOOL WINAPI SetCommTimeouts(
1522 HANDLE hComm, /* [in] handle of COMM device */
1523 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1525 BOOL ret;
1526 int fd;
1527 struct termios tios;
1529 TRACE("(%p,%p)\n",hComm,lptimeouts);
1531 if(!lptimeouts)
1533 SetLastError(ERROR_INVALID_PARAMETER);
1534 return FALSE;
1537 SERVER_START_REQ( set_serial_info )
1539 req->handle = hComm;
1540 req->flags = SERIALINFO_SET_TIMEOUTS;
1541 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1542 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1543 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1544 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1545 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1546 ret = !wine_server_call_err( req );
1548 SERVER_END_REQ;
1549 if (!ret) return FALSE;
1551 /* FIXME: move this stuff to the server */
1552 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1553 if (fd < 0) {
1554 FIXME("no fd for handle = %p!.\n",hComm);
1555 return FALSE;
1558 if (-1==tcgetattr(fd,&tios)) {
1559 FIXME("tcgetattr on fd %d failed!\n",fd);
1560 close(fd);
1561 return FALSE;
1564 /* VTIME is in 1/10 seconds */
1566 unsigned int ux_timeout;
1568 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1570 ux_timeout = 0;
1572 else
1574 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1575 if(ux_timeout == 0)
1577 ux_timeout = 1; /* must be at least some timeout */
1580 tios.c_cc[VTIME] = ux_timeout;
1583 if (-1==tcsetattr(fd,0,&tios)) {
1584 FIXME("tcsetattr on fd %d failed!\n",fd);
1585 close(fd);
1586 return FALSE;
1588 close(fd);
1589 return TRUE;
1592 /***********************************************************************
1593 * GetCommModemStatus (KERNEL32.@)
1595 * Obtains the four control register bits if supported by the hardware.
1597 * RETURNS
1599 * True if the communications handle was good and for hardware that
1600 * control register access, false otherwise.
1602 BOOL WINAPI GetCommModemStatus(
1603 HANDLE hFile, /* [in] The communications device. */
1604 LPDWORD lpModemStat) /* [out] The control register bits. */
1606 int fd,mstat, result=FALSE;
1608 *lpModemStat=0;
1609 #ifdef TIOCMGET
1610 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
1611 if(fd<0)
1612 return FALSE;
1613 result = ioctl(fd, TIOCMGET, &mstat);
1614 close(fd);
1615 if (result == -1)
1617 WARN("ioctl failed\n");
1618 return FALSE;
1620 #ifdef TIOCM_CTS
1621 if (mstat & TIOCM_CTS)
1622 *lpModemStat |= MS_CTS_ON;
1623 #endif
1624 #ifdef TIOCM_DSR
1625 if (mstat & TIOCM_DSR)
1626 *lpModemStat |= MS_DSR_ON;
1627 #endif
1628 #ifdef TIOCM_RNG
1629 if (mstat & TIOCM_RNG)
1630 *lpModemStat |= MS_RING_ON;
1631 #endif
1632 #ifdef TIOCM_CAR
1633 /*FIXME: Not really sure about RLSD UB 990810*/
1634 if (mstat & TIOCM_CAR)
1635 *lpModemStat |= MS_RLSD_ON;
1636 #endif
1637 TRACE("%04x -> %s%s%s%s\n", mstat,
1638 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1639 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1640 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1641 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1642 return TRUE;
1643 #else
1644 return FALSE;
1645 #endif
1648 /***********************************************************************
1649 * COMM_WaitCommEventService (INTERNAL)
1651 * This function is called while the client is waiting on the
1652 * server, so we can't make any server calls here.
1654 static void COMM_WaitCommEventService(async_private *ovp)
1656 async_commio *commio = (async_commio*) ovp;
1657 IO_STATUS_BLOCK* iosb = commio->async.iosb;
1659 TRACE("iosb %p\n",iosb);
1661 /* FIXME: detect other events */
1662 *commio->buffer = EV_RXCHAR;
1664 iosb->u.Status = STATUS_SUCCESS;
1668 /***********************************************************************
1669 * COMM_WaitCommEvent (INTERNAL)
1671 * This function must have an lpOverlapped.
1673 static BOOL COMM_WaitCommEvent(
1674 HANDLE hFile, /* [in] handle of comm port to wait for */
1675 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1676 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1678 int fd;
1679 async_commio *ovp;
1681 if(!lpOverlapped)
1683 SetLastError(ERROR_INVALID_PARAMETER);
1684 return FALSE;
1687 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1688 return FALSE;
1690 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
1691 if(fd<0)
1692 return FALSE;
1694 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1695 if(!ovp)
1697 close(fd);
1698 return FALSE;
1701 ovp->async.ops = &commio_async_ops;
1702 ovp->async.handle = hFile;
1703 ovp->async.fd = fd;
1704 ovp->async.type = ASYNC_TYPE_WAIT;
1705 ovp->async.func = COMM_WaitCommEventService;
1706 ovp->async.event = lpOverlapped->hEvent;
1707 ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
1708 ovp->buffer = (char *)lpdwEvents;
1710 lpOverlapped->InternalHigh = 0;
1711 lpOverlapped->Offset = 0;
1712 lpOverlapped->OffsetHigh = 0;
1714 if ( !register_new_async (&ovp->async) )
1715 SetLastError( ERROR_IO_PENDING );
1717 return FALSE;
1720 /***********************************************************************
1721 * WaitCommEvent (KERNEL32.@)
1723 * Wait until something interesting happens on a COMM port.
1724 * Interesting things (events) are set by calling SetCommMask before
1725 * this function is called.
1727 * RETURNS:
1728 * TRUE if successful
1729 * FALSE if failure
1731 * The set of detected events will be written to *lpdwEventMask
1732 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1734 * BUGS:
1735 * Only supports EV_RXCHAR and EV_TXEMPTY
1737 BOOL WINAPI WaitCommEvent(
1738 HANDLE hFile, /* [in] handle of comm port to wait for */
1739 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1740 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1742 OVERLAPPED ov;
1743 int ret;
1745 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1747 if(lpOverlapped)
1748 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1750 /* if there is no overlapped structure, create our own */
1751 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1753 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1755 /* wait for the overlapped to complete */
1756 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1757 CloseHandle(ov.hEvent);
1759 return ret;
1762 /***********************************************************************
1763 * GetCommProperties (KERNEL32.@)
1765 * This function fills in a structure with the capabilities of the
1766 * communications port driver.
1768 * RETURNS
1770 * TRUE on success, FALSE on failure
1771 * If successful, the lpCommProp structure be filled in with
1772 * properties of the comm port.
1774 BOOL WINAPI GetCommProperties(
1775 HANDLE hFile, /* [in] handle of the comm port */
1776 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1778 FIXME("(%p %p )\n",hFile,lpCommProp);
1779 if(!lpCommProp)
1780 return FALSE;
1783 * These values should be valid for LINUX's serial driver
1784 * FIXME: Perhaps they deserve an #ifdef LINUX
1786 memset(lpCommProp,0,sizeof(COMMPROP));
1787 lpCommProp->wPacketLength = 1;
1788 lpCommProp->wPacketVersion = 1;
1789 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1790 lpCommProp->dwReserved1 = 0;
1791 lpCommProp->dwMaxTxQueue = 4096;
1792 lpCommProp->dwMaxRxQueue = 4096;
1793 lpCommProp->dwMaxBaud = BAUD_115200;
1794 lpCommProp->dwProvSubType = PST_RS232;
1795 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1796 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1797 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1798 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1799 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1800 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1801 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1802 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1803 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1804 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1805 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1807 return TRUE;
1810 /***********************************************************************
1811 * FIXME:
1812 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1813 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1814 * This is dependent on the type of COMM port, but since it is doubtful
1815 * anybody will get around to implementing support for fancy serial
1816 * ports in WINE, this is hardcoded for the time being. The name of
1817 * this DLL should be stored in and read from the system registry in
1818 * the hive HKEY_LOCAL_MACHINE, key
1819 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1820 * where ???? is the port number... that is determined by PNP
1821 * The DLL should be loaded when the COMM port is opened, and closed
1822 * when the COMM port is closed. - MJM 20 June 2000
1823 ***********************************************************************/
1824 static CHAR lpszSerialUI[] = "serialui.dll";
1827 /***********************************************************************
1828 * CommConfigDialogA (KERNEL32.@)
1830 * Raises a dialog that allows the user to configure a comm port.
1831 * Fills the COMMCONFIG struct with information specified by the user.
1832 * This function should call a similar routine in the COMM driver...
1834 * RETURNS
1836 * TRUE on success, FALSE on failure
1837 * If successful, the lpCommConfig structure will contain a new
1838 * configuration for the comm port, as specified by the user.
1840 * BUGS
1841 * The library with the CommConfigDialog code is never unloaded.
1842 * Perhaps this should be done when the comm port is closed?
1844 BOOL WINAPI CommConfigDialogA(
1845 LPCSTR lpszDevice, /* [in] name of communications device */
1846 HANDLE hWnd, /* [in] parent window for the dialog */
1847 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1849 FARPROC lpfnCommDialog;
1850 HMODULE hConfigModule;
1851 BOOL r;
1853 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
1855 hConfigModule = LoadLibraryA(lpszSerialUI);
1856 if(!hConfigModule)
1857 return FALSE;
1859 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
1861 if(!lpfnCommDialog)
1862 return FALSE;
1864 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1866 /* UnloadLibrary(hConfigModule); */
1868 return r;
1871 /***********************************************************************
1872 * CommConfigDialogW (KERNEL32.@)
1874 * see CommConfigDialogA for more info
1876 BOOL WINAPI CommConfigDialogW(
1877 LPCWSTR lpszDevice, /* [in] name of communications device */
1878 HANDLE hWnd, /* [in] parent window for the dialog */
1879 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1881 BOOL r;
1882 LPSTR lpDeviceA;
1884 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1885 if(lpDeviceA)
1886 return FALSE;
1887 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
1888 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1889 return r;
1892 /***********************************************************************
1893 * GetCommConfig (KERNEL32.@)
1895 * Fill in the COMMCONFIG structure for the comm port hFile
1897 * RETURNS
1899 * TRUE on success, FALSE on failure
1900 * If successful, lpCommConfig contains the comm port configuration.
1902 * BUGS
1905 BOOL WINAPI GetCommConfig(
1906 HANDLE hFile, /* [in] The communications device. */
1907 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1908 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1909 afterwards the number of bytes copied to the buffer or
1910 the needed size of the buffer. */
1912 BOOL r;
1914 TRACE("(%p %p)\n",hFile,lpCommConfig);
1916 if(lpCommConfig == NULL)
1917 return FALSE;
1919 r = *lpdwSize < sizeof(COMMCONFIG);
1920 *lpdwSize = sizeof(COMMCONFIG);
1921 if(!r)
1922 return FALSE;
1924 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1925 lpCommConfig->wVersion = 1;
1926 lpCommConfig->wReserved = 0;
1927 r = GetCommState(hFile,&lpCommConfig->dcb);
1928 lpCommConfig->dwProviderSubType = PST_RS232;
1929 lpCommConfig->dwProviderOffset = 0;
1930 lpCommConfig->dwProviderSize = 0;
1932 return r;
1935 /***********************************************************************
1936 * SetCommConfig (KERNEL32.@)
1938 * Sets the configuration of the communications device.
1940 * RETURNS
1942 * True on success, false if the handle was bad is not a communications device.
1944 BOOL WINAPI SetCommConfig(
1945 HANDLE hFile, /* [in] The communications device. */
1946 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1947 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1949 TRACE("(%p %p)\n",hFile,lpCommConfig);
1950 return SetCommState(hFile,&lpCommConfig->dcb);
1953 /***********************************************************************
1954 * SetDefaultCommConfigA (KERNEL32.@)
1956 * Initializes the default configuration for the specified communication
1957 * device. (ascii)
1959 * RETURNS
1961 * True if the device was found and the defaults set, false otherwise
1963 BOOL WINAPI SetDefaultCommConfigA(
1964 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1965 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1966 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1968 FARPROC lpfnSetDefaultCommConfig;
1969 HMODULE hConfigModule;
1970 BOOL r;
1972 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1974 hConfigModule = LoadLibraryA(lpszSerialUI);
1975 if(!hConfigModule)
1976 return FALSE;
1978 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
1980 if(! lpfnSetDefaultCommConfig)
1981 return TRUE;
1983 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1985 /* UnloadLibrary(hConfigModule); */
1987 return r;
1991 /***********************************************************************
1992 * SetDefaultCommConfigW (KERNEL32.@)
1994 * Initializes the default configuration for the specified
1995 * communication device. (unicode)
1997 * RETURNS
2000 BOOL WINAPI SetDefaultCommConfigW(
2001 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2002 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2003 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2005 BOOL r;
2006 LPSTR lpDeviceA;
2008 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2010 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2011 if(lpDeviceA)
2012 return FALSE;
2013 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2014 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2015 return r;
2019 /***********************************************************************
2020 * GetDefaultCommConfigA (KERNEL32.@)
2022 * Acquires the default configuration of the specified communication device. (unicode)
2024 * RETURNS
2026 * True on successful reading of the default configuration,
2027 * if the device is not found or the buffer is too small.
2029 BOOL WINAPI GetDefaultCommConfigA(
2030 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2031 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2032 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2033 afterwards the number of bytes copied to the buffer or
2034 the needed size of the buffer. */
2036 LPDCB lpdcb = &(lpCC->dcb);
2037 char temp[40];
2039 if (strncasecmp(lpszName,"COM",3)) {
2040 ERR("not implemented for <%s>\n", lpszName);
2041 return FALSE;
2044 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2045 if (*lpdwSize < sizeof(COMMCONFIG)) {
2046 *lpdwSize = sizeof(COMMCONFIG);
2047 return FALSE;
2050 *lpdwSize = sizeof(COMMCONFIG);
2052 lpCC->dwSize = sizeof(COMMCONFIG);
2053 lpCC->wVersion = 1;
2054 lpCC->dwProviderSubType = PST_RS232;
2055 lpCC->dwProviderOffset = 0L;
2056 lpCC->dwProviderSize = 0L;
2058 sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2059 FIXME("setting %s as default\n", temp);
2061 return BuildCommDCBA( temp, lpdcb);
2064 /**************************************************************************
2065 * GetDefaultCommConfigW (KERNEL32.@)
2067 * Acquires the default configuration of the specified communication device. (unicode)
2069 * RETURNS
2071 * True on successful reading of the default configuration,
2072 * if the device is not found or the buffer is too small.
2074 BOOL WINAPI GetDefaultCommConfigW(
2075 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2076 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2077 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2078 afterwards the number of bytes copied to the buffer or
2079 the needed size of the buffer. */
2081 BOOL ret = FALSE;
2082 LPSTR lpszNameA;
2084 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2085 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2086 if (lpszNameA)
2088 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2089 HeapFree( GetProcessHeap(), 0, lpszNameA );
2091 return ret;