Install notepad.exe in c:\windows too.
[wine/testsucceed.git] / dlls / kernel / comm.c
blob2cba3c6ce8ae14962639ad8d4416fee24f239e0a
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * History:
22 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
23 * - Fixed the modem control part of EscapeCommFunction16.
25 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
26 * - Implemented buffers and EnableCommNotification.
28 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
29 * - Use port indices instead of unixfds for win16
30 * - Moved things around (separated win16 and win32 routines)
31 * - Added some hints on how to implement buffers and EnableCommNotification.
33 * Oktober 98, Rein Klazes [RHK]
34 * A program that wants to monitor the modem status line (RLSD/DCD) may
35 * poll the modem status register in the commMask structure. I update the bit
36 * in GetCommError, waiting for an implementation of communication events.
38 * July 6, 1998. Fixes and comments by Valentijn Sessink
39 * <vsessink@ic.uva.nl> [V]
41 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
42 * <lawson_whitney@juno.com>
44 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
45 * - ptr->fd wasn't getting cleared on close.
46 * - GetCommEventMask() and GetCommError() didn't do much of anything.
47 * IMHO, they are still wrong, but they at least implement the RXCHAR
48 * event and return I/O queue sizes, which makes the app I'm interested
49 * in (analog devices EZKIT DSP development system) work.
52 #include "config.h"
53 #include "wine/port.h"
55 #include <stdlib.h>
56 #include <stdio.h>
57 #ifdef HAVE_TERMIOS_H
58 #include <termios.h>
59 #endif
60 #include <fcntl.h>
61 #include <string.h>
62 #ifdef HAVE_STRINGS_H
63 # include <strings.h>
64 #endif
65 #include <errno.h>
66 #include <ctype.h>
67 #include <sys/stat.h>
68 #ifdef HAVE_SYS_FILIO_H
69 # include <sys/filio.h>
70 #endif
71 #ifdef HAVE_SYS_IOCTL_H
72 #include <sys/ioctl.h>
73 #endif
74 #ifdef HAVE_UNISTD_H
75 # include <unistd.h>
76 #endif
77 #ifdef HAVE_SYS_POLL_H
78 # include <sys/poll.h>
79 #endif
80 #ifdef HAVE_SYS_MODEM_H
81 # include <sys/modem.h>
82 #endif
83 #ifdef HAVE_SYS_STRTIO_H
84 # include <sys/strtio.h>
85 #endif
87 #include "winbase.h"
88 #include "winerror.h"
90 #include "wine/server.h"
91 #include "async.h"
92 #include "file.h"
93 #include "heap.h"
95 #include "wine/debug.h"
97 #ifdef HAVE_LINUX_SERIAL_H
98 #include <linux/serial.h>
99 #endif
101 WINE_DEFAULT_DEBUG_CHANNEL(comm);
103 /***********************************************************************
104 * Asynchronous I/O for asynchronous wait requests *
107 static DWORD commio_get_async_status (const async_private *ovp);
108 static DWORD commio_get_async_count (const async_private *ovp);
109 static void commio_set_async_status (async_private *ovp, const DWORD status);
110 static void commio_async_cleanup (async_private *ovp);
112 static async_ops commio_async_ops =
114 commio_get_async_status, /* get_status */
115 commio_set_async_status, /* set_status */
116 commio_get_async_count, /* get_count */
117 NULL, /* call_completion */
118 commio_async_cleanup /* cleanup */
121 typedef struct async_commio
123 struct async_private async;
124 LPOVERLAPPED lpOverlapped;
125 char *buffer;
126 } async_commio;
128 static DWORD commio_get_async_status (const struct async_private *ovp)
130 return ((async_commio*) ovp)->lpOverlapped->Internal;
133 static void commio_set_async_status (async_private *ovp, const DWORD status)
135 ((async_commio*) ovp)->lpOverlapped->Internal = status;
138 static DWORD commio_get_async_count (const struct async_private *ovp)
140 return 0;
143 static void commio_async_cleanup (async_private *ovp)
145 HeapFree(GetProcessHeap(), 0, ovp );
148 /***********************************************************************/
150 #if !defined(TIOCINQ) && defined(FIONREAD)
151 #define TIOCINQ FIONREAD
152 #endif
154 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
156 #ifdef TIOCMGET
157 unsigned int mstat, okay;
158 okay = ioctl(fd, TIOCMGET, &mstat);
159 if (okay) return okay;
160 if (andy) mstat &= andy;
161 mstat |= orrie;
162 return ioctl(fd, TIOCMSET, &mstat);
163 #else
164 return 0;
165 #endif
168 /***********************************************************************
169 * COMM_BuildOldCommDCB (Internal)
171 * Build a DCB using the old style settings string eg: "COMx:96,n,8,1"
172 * We ignore the COM port index, since we can support more than 4 ports.
174 BOOL WINAPI COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
176 /* "COM1:96,n,8,1" */
177 /* 012345 */
178 char *ptr, temp[256], last;
179 int rate;
181 TRACE("(%s), ptr %p\n", device, lpdcb);
183 /* Some applications call this function with "9600,n,8,1"
184 * not sending the "COM1:" parameter at left of string */
185 if (!strncasecmp(device,"COM",3))
187 if (!device[3]) return FALSE;
188 if (device[4] != ':' && device[4] != ' ') return FALSE;
189 strcpy(temp,device+5);
191 else strcpy(temp,device);
193 last=temp[strlen(temp)-1];
194 ptr = strtok(temp, ", ");
196 /* DOS/Windows only compares the first two numbers
197 * and assigns an appropriate baud rate.
198 * You can supply 961324245, it still returns 9600 ! */
199 if (strlen(ptr) < 2)
201 WARN("Unknown baudrate string '%s' !\n", ptr);
202 return FALSE; /* error: less than 2 chars */
204 ptr[2] = '\0';
205 rate = atoi(ptr);
207 switch (rate) {
208 case 11:
209 case 30:
210 case 60:
211 rate *= 10;
212 break;
213 case 12:
214 case 24:
215 case 48:
216 case 96:
217 rate *= 100;
218 break;
219 case 19:
220 rate = 19200;
221 break;
222 default:
223 WARN("Unknown baudrate indicator %d !\n", rate);
224 return FALSE;
227 lpdcb->BaudRate = rate;
228 TRACE("baudrate (%ld)\n", lpdcb->BaudRate);
230 ptr = strtok(NULL, ", ");
231 if (islower(*ptr))
232 *ptr = toupper(*ptr);
234 TRACE("parity (%c)\n", *ptr);
235 lpdcb->fParity = TRUE;
236 switch (*ptr) {
237 case 'N':
238 lpdcb->Parity = NOPARITY;
239 lpdcb->fParity = FALSE;
240 break;
241 case 'E':
242 lpdcb->Parity = EVENPARITY;
243 break;
244 case 'M':
245 lpdcb->Parity = MARKPARITY;
246 break;
247 case 'O':
248 lpdcb->Parity = ODDPARITY;
249 break;
250 case 'S':
251 lpdcb->Parity = SPACEPARITY;
252 break;
253 default:
254 WARN("Unknown parity `%c'!\n", *ptr);
255 return FALSE;
258 ptr = strtok(NULL, ", ");
259 TRACE("charsize (%c)\n", *ptr);
260 lpdcb->ByteSize = *ptr - '0';
262 ptr = strtok(NULL, ", ");
263 TRACE("stopbits (%c)\n", *ptr);
264 switch (*ptr) {
265 case '1':
266 lpdcb->StopBits = ONESTOPBIT;
267 break;
268 case '2':
269 lpdcb->StopBits = TWOSTOPBITS;
270 break;
271 default:
272 WARN("Unknown # of stopbits `%c'!\n", *ptr);
273 return FALSE;
276 if (last == 'x') {
277 lpdcb->fInX = TRUE;
278 lpdcb->fOutX = TRUE;
279 lpdcb->fOutxCtsFlow = FALSE;
280 lpdcb->fOutxDsrFlow = FALSE;
281 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
282 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
283 } else if (last=='p') {
284 lpdcb->fInX = FALSE;
285 lpdcb->fOutX = FALSE;
286 lpdcb->fOutxCtsFlow = TRUE;
287 lpdcb->fOutxDsrFlow = FALSE;
288 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
289 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
290 } else {
291 lpdcb->fInX = FALSE;
292 lpdcb->fOutX = FALSE;
293 lpdcb->fOutxCtsFlow = FALSE;
294 lpdcb->fOutxDsrFlow = FALSE;
295 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
296 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
299 return TRUE;
302 /**************************************************************************
303 * BuildCommDCBA (KERNEL32.@)
305 * Updates a device control block data structure with values from an
306 * ascii device control string. The device control string has two forms
307 * normal and extended, it must be exclusively in one or the other form.
309 * RETURNS
311 * True on success, false on a malformed control string.
313 BOOL WINAPI BuildCommDCBA(
314 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
315 LPDCB lpdcb) /* [out] The device control block to be updated. */
317 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
320 /**************************************************************************
321 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
323 * Updates a device control block data structure with values from an
324 * ascii device control string. Taking timeout values from a timeouts
325 * struct if desired by the control string.
327 * RETURNS
329 * True on success, false bad handles etc
331 BOOL WINAPI BuildCommDCBAndTimeoutsA(
332 LPCSTR device, /* [in] The ascii device control string. */
333 LPDCB lpdcb, /* [out] The device control block to be updated. */
334 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
336 int port;
337 char *ptr,*temp;
339 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
341 if (!strncasecmp(device,"COM",3)) {
342 port=device[3]-'0';
343 if (port--==0) {
344 ERR("BUG! COM0 can't exist!\n");
345 return FALSE;
347 if ((*(device+4)!=':') && (*(device+4)!=' '))
348 return FALSE;
349 temp=(LPSTR)(device+5);
350 } else
351 temp=(LPSTR)device;
353 memset(lpdcb,0,sizeof (DCB));
354 lpdcb->DCBlength = sizeof(DCB);
355 if (strchr(temp,',')) { /* old style */
357 return COMM_BuildOldCommDCB(device,lpdcb);
359 ptr=strtok(temp," ");
360 while (ptr) {
361 DWORD flag,x;
363 flag=0;
364 if (!strncmp("baud=",ptr,5)) {
365 if (!sscanf(ptr+5,"%ld",&x))
366 WARN("Couldn't parse %s\n",ptr);
367 lpdcb->BaudRate = x;
368 flag=1;
370 if (!strncmp("stop=",ptr,5)) {
371 if (!sscanf(ptr+5,"%ld",&x))
372 WARN("Couldn't parse %s\n",ptr);
373 lpdcb->StopBits = x;
374 flag=1;
376 if (!strncmp("data=",ptr,5)) {
377 if (!sscanf(ptr+5,"%ld",&x))
378 WARN("Couldn't parse %s\n",ptr);
379 lpdcb->ByteSize = x;
380 flag=1;
382 if (!strncmp("parity=",ptr,7)) {
383 lpdcb->fParity = TRUE;
384 switch (ptr[7]) {
385 case 'N':case 'n':
386 lpdcb->fParity = FALSE;
387 lpdcb->Parity = NOPARITY;
388 break;
389 case 'E':case 'e':
390 lpdcb->Parity = EVENPARITY;
391 break;
392 case 'O':case 'o':
393 lpdcb->Parity = ODDPARITY;
394 break;
395 case 'M':case 'm':
396 lpdcb->Parity = MARKPARITY;
397 break;
398 case 'S':case 's':
399 lpdcb->Parity = SPACEPARITY;
400 break;
402 flag=1;
404 if (!flag)
405 ERR("Unhandled specifier '%s', please report.\n",ptr);
406 ptr=strtok(NULL," ");
408 if (lpdcb->BaudRate==110)
409 lpdcb->StopBits = 2;
410 return TRUE;
413 /**************************************************************************
414 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
416 * Updates a device control block data structure with values from an
417 * unicode device control string. Taking timeout values from a timeouts
418 * struct if desired by the control string.
420 * RETURNS
422 * True on success, false bad handles etc.
424 BOOL WINAPI BuildCommDCBAndTimeoutsW(
425 LPCWSTR devid, /* [in] The unicode device control string. */
426 LPDCB lpdcb, /* [out] The device control block to be updated. */
427 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
429 BOOL ret = FALSE;
430 LPSTR devidA;
432 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
433 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
434 if (devidA)
436 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
437 HeapFree( GetProcessHeap(), 0, devidA );
439 return ret;
442 /**************************************************************************
443 * BuildCommDCBW (KERNEL32.@)
445 * Updates a device control block structure with values from an
446 * unicode device control string. The device control string has two forms
447 * normal and extended, it must be exclusively in one or the other form.
449 * RETURNS
451 * True on success, false on an malformed control string.
453 BOOL WINAPI BuildCommDCBW(
454 LPCWSTR devid, /* [in] The unicode device control string. */
455 LPDCB lpdcb) /* [out] The device control block to be updated. */
457 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
460 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
462 DWORD ret;
464 SERVER_START_REQ( set_serial_info )
466 req->handle = handle;
467 req->flags = SERIALINFO_SET_ERROR;
468 req->commerror = error;
469 ret = !wine_server_call_err( req );
471 SERVER_END_REQ;
472 return ret;
475 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
477 DWORD ret;
479 if(!lperror)
480 return FALSE;
482 SERVER_START_REQ( get_serial_info )
484 req->handle = handle;
485 ret = !wine_server_call_err( req );
486 *lperror = reply->commerror;
488 SERVER_END_REQ;
490 return ret;
493 /*****************************************************************************
494 * SetCommBreak (KERNEL32.@)
496 * Halts the transmission of characters to a communications device.
498 * RETURNS
500 * True on success, and false if the communications device could not be found,
501 * the control is not supported.
503 * BUGS
505 * Only TIOCSBRK and TIOCCBRK are supported.
507 BOOL WINAPI SetCommBreak(
508 HANDLE handle) /* [in] The communictions device to suspend. */
510 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
511 int fd,result;
513 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
514 if(fd<0) {
515 TRACE("FILE_GetUnixHandle failed\n");
516 return FALSE;
518 result = ioctl(fd,TIOCSBRK,0);
519 close(fd);
520 if (result ==-1)
522 TRACE("ioctl failed\n");
523 SetLastError(ERROR_NOT_SUPPORTED);
524 return FALSE;
526 return TRUE;
527 #else
528 FIXME("ioctl not available\n");
529 SetLastError(ERROR_NOT_SUPPORTED);
530 return FALSE;
531 #endif
534 /*****************************************************************************
535 * ClearCommBreak (KERNEL32.@)
537 * Resumes character transmission from a communication device.
539 * RETURNS
541 * True on success and false if the communications device could not be found.
543 * BUGS
545 * Only TIOCSBRK and TIOCCBRK are supported.
547 BOOL WINAPI ClearCommBreak(
548 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
550 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
551 int fd,result;
553 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
554 if(fd<0) {
555 TRACE("FILE_GetUnixHandle failed\n");
556 return FALSE;
558 result = ioctl(fd,TIOCCBRK,0);
559 close(fd);
560 if (result ==-1)
562 TRACE("ioctl failed\n");
563 SetLastError(ERROR_NOT_SUPPORTED);
564 return FALSE;
566 return TRUE;
567 #else
568 FIXME("ioctl not available\n");
569 SetLastError(ERROR_NOT_SUPPORTED);
570 return FALSE;
571 #endif
574 /*****************************************************************************
575 * EscapeCommFunction (KERNEL32.@)
577 * Directs a communication device to perform an extended function.
579 * RETURNS
581 * True or requested data on successful completion of the command,
582 * false if the device is not present cannot execute the command
583 * or the command failed.
585 BOOL WINAPI EscapeCommFunction(
586 HANDLE handle, /* [in] The communication device to perform the extended function. */
587 UINT nFunction) /* [in] The extended function to be performed. */
589 int fd,direct=FALSE,result=FALSE;
590 struct termios port;
592 TRACE("handle %d, function=%d\n", handle, nFunction);
593 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
594 if(fd<0) {
595 FIXME("handle %d not found.\n",handle);
596 return FALSE;
599 if (tcgetattr(fd,&port) == -1) {
600 COMM_SetCommError(handle,CE_IOE);
601 close(fd);
602 return FALSE;
605 switch (nFunction) {
606 case RESETDEV:
607 TRACE("\n");
608 break;
610 case CLRDTR:
611 TRACE("CLRDTR\n");
612 #ifdef TIOCM_DTR
613 direct=TRUE;
614 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
615 break;
616 #endif
618 case CLRRTS:
619 TRACE("CLRRTS\n");
620 #ifdef TIOCM_RTS
621 direct=TRUE;
622 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
623 break;
624 #endif
626 case SETDTR:
627 TRACE("SETDTR\n");
628 #ifdef TIOCM_DTR
629 direct=TRUE;
630 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
631 break;
632 #endif
634 case SETRTS:
635 TRACE("SETRTS\n");
636 #ifdef TIOCM_RTS
637 direct=TRUE;
638 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
639 break;
640 #endif
642 case SETXOFF:
643 TRACE("SETXOFF\n");
644 port.c_iflag |= IXOFF;
645 break;
647 case SETXON:
648 TRACE("SETXON\n");
649 port.c_iflag |= IXON;
650 break;
651 case SETBREAK:
652 TRACE("setbreak\n");
653 #ifdef TIOCSBRK
654 direct=TRUE;
655 result = ioctl(fd,TIOCSBRK,0);
656 break;
657 #endif
658 case CLRBREAK:
659 TRACE("clrbreak\n");
660 #ifdef TIOCSBRK
661 direct=TRUE;
662 result = ioctl(fd,TIOCCBRK,0);
663 break;
664 #endif
665 default:
666 WARN("(handle=%d,nFunction=%d): Unknown function\n",
667 handle, nFunction);
668 break;
671 if (!direct)
672 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
673 close(fd);
674 COMM_SetCommError(handle,CE_IOE);
675 return FALSE;
676 } else
677 result= TRUE;
678 else
680 if (result == -1)
682 result= FALSE;
683 COMM_SetCommError(handle,CE_IOE);
685 else
686 result = TRUE;
688 close(fd);
689 return result;
692 /********************************************************************
693 * PurgeComm (KERNEL32.@)
695 * Terminates pending operations and/or discards buffers on a
696 * communication resource.
698 * RETURNS
700 * True on success and false if the communications handle is bad.
702 BOOL WINAPI PurgeComm(
703 HANDLE handle, /* [in] The communication resource to be purged. */
704 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
706 int fd;
708 TRACE("handle %d, flags %lx\n", handle, flags);
710 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
711 if(fd<0) {
712 FIXME("no handle %d found\n",handle);
713 return FALSE;
717 ** not exactly sure how these are different
718 ** Perhaps if we had our own internal queues, one flushes them
719 ** and the other flushes the kernel's buffers.
721 if(flags&PURGE_TXABORT)
722 tcflush(fd,TCOFLUSH);
723 if(flags&PURGE_RXABORT)
724 tcflush(fd,TCIFLUSH);
725 if(flags&PURGE_TXCLEAR)
726 tcflush(fd,TCOFLUSH);
727 if(flags&PURGE_RXCLEAR)
728 tcflush(fd,TCIFLUSH);
729 close(fd);
731 return 1;
734 /*****************************************************************************
735 * ClearCommError (KERNEL32.@)
737 * Enables further I/O operations on a communications resource after
738 * supplying error and current status information.
740 * RETURNS
742 * True on success, false if the communication resource handle is bad.
744 BOOL WINAPI ClearCommError(
745 HANDLE handle, /* [in] The communication resource with the error. */
746 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
747 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
749 int fd;
751 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
752 if(0>fd)
754 FIXME("no handle %d found\n",handle);
755 return FALSE;
758 if (lpStat)
760 lpStat->status = 0;
762 #ifdef TIOCOUTQ
763 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
764 WARN("ioctl returned error\n");
765 #else
766 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
767 #endif
769 #ifdef TIOCINQ
770 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
771 WARN("ioctl returned error\n");
772 #endif
774 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
775 handle, lpStat->cbInQue, lpStat->cbOutQue);
778 close(fd);
780 COMM_GetCommError(handle, errors);
781 COMM_SetCommError(handle, 0);
783 return TRUE;
786 /*****************************************************************************
787 * SetupComm (KERNEL32.@)
789 * Called after CreateFile to hint to the communication resource to use
790 * specified sizes for input and output buffers rather than the default values.
792 * RETURNS
794 * True if successful, false if the communications resource handle is bad.
796 * BUGS
798 * Stub.
800 BOOL WINAPI SetupComm(
801 HANDLE handle, /* [in] The just created communication resource handle. */
802 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
803 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
805 int fd;
807 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
808 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
809 if(0>fd) {
810 FIXME("handle %d not found?\n",handle);
811 return FALSE;
813 close(fd);
814 return TRUE;
817 /*****************************************************************************
818 * GetCommMask (KERNEL32.@)
820 * Obtain the events associated with a communication device that will cause
821 * a call WaitCommEvent to return.
823 * RETURNS
825 * True on success, fail on bad device handle etc.
827 BOOL WINAPI GetCommMask(
828 HANDLE handle, /* [in] The communications device. */
829 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
831 BOOL ret;
833 TRACE("handle %d, mask %p\n", handle, evtmask);
835 SERVER_START_REQ( get_serial_info )
837 req->handle = handle;
838 if ((ret = !wine_server_call_err( req )))
840 if (evtmask) *evtmask = reply->eventmask;
843 SERVER_END_REQ;
844 return ret;
847 /*****************************************************************************
848 * SetCommMask (KERNEL32.@)
850 * There be some things we need to hear about yon there communications device.
851 * (Set which events associated with a communication device should cause
852 * a call WaitCommEvent to return.)
854 * RETURNS
856 * True on success, false on bad handle etc.
858 BOOL WINAPI SetCommMask(
859 HANDLE handle, /* [in] The communications device. */
860 DWORD evtmask) /* [in] The events that are to be monitored. */
862 BOOL ret;
864 TRACE("handle %d, mask %lx\n", handle, evtmask);
866 SERVER_START_REQ( set_serial_info )
868 req->handle = handle;
869 req->flags = SERIALINFO_SET_MASK;
870 req->eventmask = evtmask;
871 ret = !wine_server_call_err( req );
873 SERVER_END_REQ;
874 return ret;
877 /*****************************************************************************
878 * SetCommState (KERNEL32.@)
880 * Re-initializes all hardware and control settings of a communications device,
881 * with values from a device control block without effecting the input and output
882 * queues.
884 * RETURNS
886 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
888 BOOL WINAPI SetCommState(
889 HANDLE handle, /* [in] The communications device. */
890 LPDCB lpdcb) /* [out] The device control block. */
892 struct termios port;
893 int fd, bytesize, stopbits;
895 TRACE("handle %d, ptr %p\n", handle, lpdcb);
896 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
897 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
898 (lpdcb->StopBits == ONESTOPBIT)?1:
899 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
900 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
901 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
903 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
904 if (fd < 0) {
905 FIXME("no handle %d found\n",handle);
906 return FALSE;
909 if ((tcgetattr(fd,&port)) == -1) {
910 int save_error = errno;
911 COMM_SetCommError(handle,CE_IOE);
912 close( fd );
913 ERR("tcgetattr error '%s'\n", strerror(save_error));
914 return FALSE;
917 port.c_cc[VMIN] = 0;
918 port.c_cc[VTIME] = 1;
920 #ifdef IMAXBEL
921 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
922 #else
923 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
924 #endif
925 port.c_iflag |= (IGNBRK);
927 port.c_oflag &= ~(OPOST);
929 port.c_cflag &= ~(HUPCL);
930 port.c_cflag |= CLOCAL | CREAD;
932 port.c_lflag &= ~(ICANON|ECHO|ISIG);
933 port.c_lflag |= NOFLSH;
935 #ifdef CBAUD
936 port.c_cflag &= ~CBAUD;
937 switch (lpdcb->BaudRate) {
938 case 110:
939 case CBR_110:
940 port.c_cflag |= B110;
941 break;
942 case 300:
943 case CBR_300:
944 port.c_cflag |= B300;
945 break;
946 case 600:
947 case CBR_600:
948 port.c_cflag |= B600;
949 break;
950 case 1200:
951 case CBR_1200:
952 port.c_cflag |= B1200;
953 break;
954 case 2400:
955 case CBR_2400:
956 port.c_cflag |= B2400;
957 break;
958 case 4800:
959 case CBR_4800:
960 port.c_cflag |= B4800;
961 break;
962 case 9600:
963 case CBR_9600:
964 port.c_cflag |= B9600;
965 break;
966 case 19200:
967 case CBR_19200:
968 port.c_cflag |= B19200;
969 break;
970 case 38400:
971 case CBR_38400:
972 port.c_cflag |= B38400;
973 break;
974 #ifdef B57600
975 case 57600:
976 port.c_cflag |= B57600;
977 break;
978 #endif
979 #ifdef B115200
980 case 115200:
981 port.c_cflag |= B115200;
982 break;
983 #endif
984 #ifdef B230400
985 case 230400:
986 port.c_cflag |= B230400;
987 break;
988 #endif
989 #ifdef B460800
990 case 460800:
991 port.c_cflag |= B460800;
992 break;
993 #endif
994 default:
995 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
996 { struct serial_struct nuts;
997 int arby;
998 ioctl(fd, TIOCGSERIAL, &nuts);
999 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1000 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1001 arby = nuts.baud_base / nuts.custom_divisor;
1002 nuts.flags &= ~ASYNC_SPD_MASK;
1003 nuts.flags |= ASYNC_SPD_CUST;
1004 WARN("You (or a program acting at your behest) have specified\n"
1005 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1006 "which is as close as we can get by our present understanding of your\n"
1007 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1008 "has caused to your linux system can be undone with setserial \n"
1009 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1010 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1011 ioctl(fd, TIOCSSERIAL, &nuts);
1012 port.c_cflag |= B38400;
1014 break;
1015 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1018 COMM_SetCommError(handle,IE_BAUDRATE);
1019 close( fd );
1020 ERR("baudrate %ld\n",lpdcb->BaudRate);
1021 return FALSE;
1023 #elif !defined(__EMX__)
1024 switch (lpdcb->BaudRate) {
1025 case 110:
1026 case CBR_110:
1027 port.c_ospeed = B110;
1028 break;
1029 case 300:
1030 case CBR_300:
1031 port.c_ospeed = B300;
1032 break;
1033 case 600:
1034 case CBR_600:
1035 port.c_ospeed = B600;
1036 break;
1037 case 1200:
1038 case CBR_1200:
1039 port.c_ospeed = B1200;
1040 break;
1041 case 2400:
1042 case CBR_2400:
1043 port.c_ospeed = B2400;
1044 break;
1045 case 4800:
1046 case CBR_4800:
1047 port.c_ospeed = B4800;
1048 break;
1049 case 9600:
1050 case CBR_9600:
1051 port.c_ospeed = B9600;
1052 break;
1053 case 19200:
1054 case CBR_19200:
1055 port.c_ospeed = B19200;
1056 break;
1057 case 38400:
1058 case CBR_38400:
1059 port.c_ospeed = B38400;
1060 break;
1061 #ifdef B57600
1062 case 57600:
1063 case CBR_57600:
1064 port.c_cflag |= B57600;
1065 break;
1066 #endif
1067 #ifdef B115200
1068 case 115200:
1069 case CBR_115200:
1070 port.c_cflag |= B115200;
1071 break;
1072 #endif
1073 #ifdef B230400
1074 case 230400:
1075 port.c_cflag |= B230400;
1076 break;
1077 #endif
1078 #ifdef B460800
1079 case 460800:
1080 port.c_cflag |= B460800;
1081 break;
1082 #endif
1083 default:
1084 COMM_SetCommError(handle,IE_BAUDRATE);
1085 close( fd );
1086 ERR("baudrate %ld\n",lpdcb->BaudRate);
1087 return FALSE;
1089 port.c_ispeed = port.c_ospeed;
1090 #endif
1091 bytesize=lpdcb->ByteSize;
1092 stopbits=lpdcb->StopBits;
1094 #ifdef CMSPAR
1095 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1096 #else
1097 port.c_cflag &= ~(PARENB | PARODD);
1098 #endif
1099 if (lpdcb->fParity)
1100 port.c_iflag |= INPCK;
1101 else
1102 port.c_iflag &= ~INPCK;
1103 switch (lpdcb->Parity) {
1104 case NOPARITY:
1105 break;
1106 case ODDPARITY:
1107 port.c_cflag |= (PARENB | PARODD);
1108 break;
1109 case EVENPARITY:
1110 port.c_cflag |= PARENB;
1111 break;
1112 #ifdef CMSPAR
1113 /* Linux defines mark/space (stick) parity */
1114 case MARKPARITY:
1115 port.c_cflag |= (PARENB | CMSPAR);
1116 break;
1117 case SPACEPARITY:
1118 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1119 break;
1120 #else
1121 /* try the POSIX way */
1122 case MARKPARITY:
1123 if( stopbits == ONESTOPBIT) {
1124 stopbits = TWOSTOPBITS;
1125 port.c_iflag &= ~INPCK;
1126 } else {
1127 COMM_SetCommError(handle,IE_BYTESIZE);
1128 close( fd );
1129 ERR("Cannot set MARK Parity\n");
1130 return FALSE;
1132 break;
1133 case SPACEPARITY:
1134 if( bytesize < 8) {
1135 bytesize +=1;
1136 port.c_iflag &= ~INPCK;
1137 } else {
1138 COMM_SetCommError(handle,IE_BYTESIZE);
1139 close( fd );
1140 ERR("Cannot set SPACE Parity\n");
1141 return FALSE;
1143 break;
1144 #endif
1145 default:
1146 COMM_SetCommError(handle,IE_BYTESIZE);
1147 close( fd );
1148 ERR("Parity\n");
1149 return FALSE;
1153 port.c_cflag &= ~CSIZE;
1154 switch (bytesize) {
1155 case 5:
1156 port.c_cflag |= CS5;
1157 break;
1158 case 6:
1159 port.c_cflag |= CS6;
1160 break;
1161 case 7:
1162 port.c_cflag |= CS7;
1163 break;
1164 case 8:
1165 port.c_cflag |= CS8;
1166 break;
1167 default:
1168 COMM_SetCommError(handle,IE_BYTESIZE);
1169 close( fd );
1170 ERR("ByteSize\n");
1171 return FALSE;
1174 switch (stopbits) {
1175 case ONESTOPBIT:
1176 port.c_cflag &= ~CSTOPB;
1177 break;
1178 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1179 case TWOSTOPBITS:
1180 port.c_cflag |= CSTOPB;
1181 break;
1182 default:
1183 COMM_SetCommError(handle,IE_BYTESIZE);
1184 close( fd );
1185 ERR("StopBits\n");
1186 return FALSE;
1188 #ifdef CRTSCTS
1189 if ( lpdcb->fOutxCtsFlow ||
1190 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1193 port.c_cflag |= CRTSCTS;
1194 TRACE("CRTSCTS\n");
1196 #endif
1198 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1200 WARN("DSR/DTR flow control not supported\n");
1203 if (lpdcb->fInX)
1204 port.c_iflag |= IXON;
1205 else
1206 port.c_iflag &= ~IXON;
1207 if (lpdcb->fOutX)
1208 port.c_iflag |= IXOFF;
1209 else
1210 port.c_iflag &= ~IXOFF;
1212 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1213 int save_error=errno;
1214 COMM_SetCommError(handle,CE_IOE);
1215 close( fd );
1216 ERR("tcsetattr error '%s'\n", strerror(save_error));
1217 return FALSE;
1218 } else {
1219 COMM_SetCommError(handle,0);
1220 close( fd );
1221 return TRUE;
1226 /*****************************************************************************
1227 * GetCommState (KERNEL32.@)
1229 * Fills in a device control block with information from a communications device.
1231 * RETURNS
1233 * True on success, false if the communication device handle is bad etc
1235 * BUGS
1237 * XonChar and XoffChar are not set.
1239 BOOL WINAPI GetCommState(
1240 HANDLE handle, /* [in] The communications device. */
1241 LPDCB lpdcb) /* [out] The device control block. */
1243 struct termios port;
1244 int fd,speed;
1246 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1248 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1249 if (fd < 0)
1251 ERR("FILE_GetUnixHandle failed\n");
1252 return FALSE;
1254 if (tcgetattr(fd, &port) == -1) {
1255 int save_error=errno;
1256 ERR("tcgetattr error '%s'\n", strerror(save_error));
1257 COMM_SetCommError(handle,CE_IOE);
1258 close( fd );
1259 return FALSE;
1261 close( fd );
1262 #ifndef __EMX__
1263 #ifdef CBAUD
1264 speed= (port.c_cflag & CBAUD);
1265 #else
1266 speed= (cfgetospeed(&port));
1267 #endif
1268 switch (speed) {
1269 case B110:
1270 lpdcb->BaudRate = 110;
1271 break;
1272 case B300:
1273 lpdcb->BaudRate = 300;
1274 break;
1275 case B600:
1276 lpdcb->BaudRate = 600;
1277 break;
1278 case B1200:
1279 lpdcb->BaudRate = 1200;
1280 break;
1281 case B2400:
1282 lpdcb->BaudRate = 2400;
1283 break;
1284 case B4800:
1285 lpdcb->BaudRate = 4800;
1286 break;
1287 case B9600:
1288 lpdcb->BaudRate = 9600;
1289 break;
1290 case B19200:
1291 lpdcb->BaudRate = 19200;
1292 break;
1293 case B38400:
1294 lpdcb->BaudRate = 38400;
1295 break;
1296 #ifdef B57600
1297 case B57600:
1298 lpdcb->BaudRate = 57600;
1299 break;
1300 #endif
1301 #ifdef B115200
1302 case B115200:
1303 lpdcb->BaudRate = 115200;
1304 break;
1305 #endif
1306 #ifdef B230400
1307 case B230400:
1308 lpdcb->BaudRate = 230400;
1309 break;
1310 #endif
1311 #ifdef B460800
1312 case B460800:
1313 lpdcb->BaudRate = 460800;
1314 break;
1315 #endif
1316 default:
1317 ERR("unknown speed %x \n",speed);
1319 #endif
1320 switch (port.c_cflag & CSIZE) {
1321 case CS5:
1322 lpdcb->ByteSize = 5;
1323 break;
1324 case CS6:
1325 lpdcb->ByteSize = 6;
1326 break;
1327 case CS7:
1328 lpdcb->ByteSize = 7;
1329 break;
1330 case CS8:
1331 lpdcb->ByteSize = 8;
1332 break;
1333 default:
1334 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1337 if(port.c_iflag & INPCK)
1338 lpdcb->fParity = TRUE;
1339 else
1340 lpdcb->fParity = FALSE;
1341 #ifdef CMSPAR
1342 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1343 #else
1344 switch (port.c_cflag & (PARENB | PARODD))
1345 #endif
1347 case 0:
1348 lpdcb->Parity = NOPARITY;
1349 break;
1350 case PARENB:
1351 lpdcb->Parity = EVENPARITY;
1352 break;
1353 case (PARENB | PARODD):
1354 lpdcb->Parity = ODDPARITY;
1355 break;
1356 #ifdef CMSPAR
1357 case (PARENB | CMSPAR):
1358 lpdcb->Parity = MARKPARITY;
1359 break;
1360 case (PARENB | PARODD | CMSPAR):
1361 lpdcb->Parity = SPACEPARITY;
1362 break;
1363 #endif
1366 if (port.c_cflag & CSTOPB)
1367 if(lpdcb->ByteSize == 5)
1368 lpdcb->StopBits = ONE5STOPBITS;
1369 else
1370 lpdcb->StopBits = TWOSTOPBITS;
1371 else
1372 lpdcb->StopBits = ONESTOPBIT;
1374 lpdcb->fNull = 0;
1375 lpdcb->fBinary = 1;
1377 /* termios does not support DTR/DSR flow control */
1378 lpdcb->fOutxDsrFlow = 0;
1379 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1381 #ifdef CRTSCTS
1383 if (port.c_cflag & CRTSCTS) {
1384 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1385 lpdcb->fOutxCtsFlow = 1;
1386 } else
1387 #endif
1389 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1390 lpdcb->fOutxCtsFlow = 0;
1392 if (port.c_iflag & IXON)
1393 lpdcb->fInX = 1;
1394 else
1395 lpdcb->fInX = 0;
1397 if (port.c_iflag & IXOFF)
1398 lpdcb->fOutX = 1;
1399 else
1400 lpdcb->fOutX = 0;
1402 lpdcb->XonChar =
1403 lpdcb->XoffChar =
1405 lpdcb->XonLim = 10;
1406 lpdcb->XoffLim = 10;
1408 COMM_SetCommError(handle,0);
1410 TRACE("OK\n");
1412 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1413 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1414 (lpdcb->StopBits == ONESTOPBIT)?1:
1415 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1416 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1417 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1418 #ifdef CRTSCTS
1419 if ( lpdcb->fOutxCtsFlow ||
1420 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1422 TRACE("CRTSCTS\n");
1423 else
1425 TRACE("~CRTSCTS\n");
1427 #endif
1428 return TRUE;
1431 /*****************************************************************************
1432 * TransmitCommChar (KERNEL32.@)
1434 * Transmits a single character in front of any pending characters in the
1435 * output buffer. Usually used to send an interrupt character to a host.
1437 * RETURNS
1439 * True if the call succeeded, false if the previous command character to the
1440 * same device has not been sent yet the handle is bad etc.
1442 * BUGS
1444 * Stub.
1446 BOOL WINAPI TransmitCommChar(
1447 HANDLE hComm, /* [in] The communication device in need of a command character. */
1448 CHAR chTransmit) /* [in] The character to transmit. */
1450 BOOL r = FALSE;
1451 int fd;
1453 WARN("(%x,'%c') not perfect!\n",hComm,chTransmit);
1455 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1456 if ( fd < 0 )
1457 SetLastError ( ERROR_INVALID_PARAMETER );
1458 else
1460 r = (1 == write(fd, &chTransmit, 1));
1461 close(fd);
1464 return r;
1468 /*****************************************************************************
1469 * GetCommTimeouts (KERNEL32.@)
1471 * Obtains the request timeout values for the communications device.
1473 * RETURNS
1475 * True on success, false if communications device handle is bad
1476 * or the target structure is null.
1478 BOOL WINAPI GetCommTimeouts(
1479 HANDLE hComm, /* [in] The communications device. */
1480 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1482 BOOL ret;
1484 TRACE("(%x,%p)\n",hComm,lptimeouts);
1486 if(!lptimeouts)
1488 SetLastError(ERROR_INVALID_PARAMETER);
1489 return FALSE;
1492 SERVER_START_REQ( get_serial_info )
1494 req->handle = hComm;
1495 if ((ret = !wine_server_call_err( req )))
1497 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1498 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1499 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1500 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1501 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1504 SERVER_END_REQ;
1505 return ret;
1508 /*****************************************************************************
1509 * SetCommTimeouts (KERNEL32.@)
1511 * Sets the timeouts used when reading and writing data to/from COMM ports.
1513 * ReadIntervalTimeout
1514 * - converted and passes to linux kernel as c_cc[VTIME]
1515 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1516 * - used in ReadFile to calculate GetOverlappedResult's timeout
1517 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1518 * - used in WriteFile to calculate GetOverlappedResult's timeout
1520 * RETURNS
1522 * True if the timeouts were set, false otherwise.
1524 BOOL WINAPI SetCommTimeouts(
1525 HANDLE hComm, /* [in] handle of COMM device */
1526 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1528 BOOL ret;
1529 int fd;
1530 struct termios tios;
1532 TRACE("(%x,%p)\n",hComm,lptimeouts);
1534 if(!lptimeouts)
1536 SetLastError(ERROR_INVALID_PARAMETER);
1537 return FALSE;
1540 SERVER_START_REQ( set_serial_info )
1542 req->handle = hComm;
1543 req->flags = SERIALINFO_SET_TIMEOUTS;
1544 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1545 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1546 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1547 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1548 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1549 ret = !wine_server_call_err( req );
1551 SERVER_END_REQ;
1552 if (!ret) return FALSE;
1554 /* FIXME: move this stuff to the server */
1555 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1556 if (fd < 0) {
1557 FIXME("no fd for handle = %0x!.\n",hComm);
1558 return FALSE;
1561 if (-1==tcgetattr(fd,&tios)) {
1562 FIXME("tcgetattr on fd %d failed!\n",fd);
1563 return FALSE;
1566 /* VTIME is in 1/10 seconds */
1568 unsigned int ux_timeout;
1570 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1572 ux_timeout = 0;
1574 else
1576 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1577 if(ux_timeout == 0)
1579 ux_timeout = 1; /* must be at least some timeout */
1582 tios.c_cc[VTIME] = ux_timeout;
1585 if (-1==tcsetattr(fd,0,&tios)) {
1586 FIXME("tcsetattr on fd %d failed!\n",fd);
1587 return FALSE;
1589 close(fd);
1590 return TRUE;
1593 /***********************************************************************
1594 * GetCommModemStatus (KERNEL32.@)
1596 * Obtains the four control register bits if supported by the hardware.
1598 * RETURNS
1600 * True if the communications handle was good and for hardware that
1601 * control register access, false otherwise.
1603 BOOL WINAPI GetCommModemStatus(
1604 HANDLE hFile, /* [in] The communications device. */
1605 LPDWORD lpModemStat) /* [out] The control register bits. */
1607 int fd,mstat, result=FALSE;
1609 *lpModemStat=0;
1610 #ifdef TIOCMGET
1611 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
1612 if(fd<0)
1613 return FALSE;
1614 result = ioctl(fd, TIOCMGET, &mstat);
1615 close(fd);
1616 if (result == -1)
1618 WARN("ioctl failed\n");
1619 return FALSE;
1621 #ifdef TIOCM_CTS
1622 if (mstat & TIOCM_CTS)
1623 *lpModemStat |= MS_CTS_ON;
1624 #endif
1625 #ifdef TIOCM_DSR
1626 if (mstat & TIOCM_DSR)
1627 *lpModemStat |= MS_DSR_ON;
1628 #endif
1629 #ifdef TIOCM_RNG
1630 if (mstat & TIOCM_RNG)
1631 *lpModemStat |= MS_RING_ON;
1632 #endif
1633 #ifdef TIOCM_CAR
1634 /*FIXME: Not really sure about RLSD UB 990810*/
1635 if (mstat & TIOCM_CAR)
1636 *lpModemStat |= MS_RLSD_ON;
1637 #endif
1638 TRACE("%04x -> %s%s%s%s\n", mstat,
1639 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1640 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1641 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1642 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1643 return TRUE;
1644 #else
1645 return FALSE;
1646 #endif
1649 /***********************************************************************
1650 * COMM_WaitCommEventService (INTERNAL)
1652 * This function is called while the client is waiting on the
1653 * server, so we can't make any server calls here.
1655 static void COMM_WaitCommEventService(async_private *ovp)
1657 async_commio *commio = (async_commio*) ovp;
1658 LPOVERLAPPED lpOverlapped = commio->lpOverlapped;
1660 TRACE("overlapped %p\n",lpOverlapped);
1662 /* FIXME: detect other events */
1663 *commio->buffer = EV_RXCHAR;
1665 lpOverlapped->Internal = STATUS_SUCCESS;
1669 /***********************************************************************
1670 * COMM_WaitCommEvent (INTERNAL)
1672 * This function must have an lpOverlapped.
1674 static BOOL COMM_WaitCommEvent(
1675 HANDLE hFile, /* [in] handle of comm port to wait for */
1676 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1677 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1679 int fd;
1680 async_commio *ovp;
1682 if(!lpOverlapped)
1684 SetLastError(ERROR_INVALID_PARAMETER);
1685 return FALSE;
1688 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1689 return FALSE;
1691 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
1692 if(fd<0)
1693 return FALSE;
1695 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1696 if(!ovp)
1698 close(fd);
1699 return FALSE;
1702 ovp->async.ops = &commio_async_ops;
1703 ovp->async.handle = hFile;
1704 ovp->async.fd = fd;
1705 ovp->async.type = ASYNC_TYPE_WAIT;
1706 ovp->async.func = COMM_WaitCommEventService;
1707 ovp->async.event = lpOverlapped->hEvent;
1708 ovp->lpOverlapped = lpOverlapped;
1709 ovp->buffer = (char *)lpdwEvents;
1711 lpOverlapped->InternalHigh = 0;
1712 lpOverlapped->Offset = 0;
1713 lpOverlapped->OffsetHigh = 0;
1715 if ( !register_new_async (&ovp->async) )
1716 SetLastError( ERROR_IO_PENDING );
1718 return FALSE;
1721 /***********************************************************************
1722 * WaitCommEvent (KERNEL32.@)
1724 * Wait until something interesting happens on a COMM port.
1725 * Interesting things (events) are set by calling SetCommMask before
1726 * this function is called.
1728 * RETURNS:
1729 * TRUE if successful
1730 * FALSE if failure
1732 * The set of detected events will be written to *lpdwEventMask
1733 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1735 * BUGS:
1736 * Only supports EV_RXCHAR and EV_TXEMPTY
1738 BOOL WINAPI WaitCommEvent(
1739 HANDLE hFile, /* [in] handle of comm port to wait for */
1740 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1741 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1743 OVERLAPPED ov;
1744 int ret;
1746 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1748 if(lpOverlapped)
1749 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1751 /* if there is no overlapped structure, create our own */
1752 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1754 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1756 if(GetLastError()!=STATUS_PENDING)
1758 CloseHandle(ov.hEvent);
1759 return FALSE;
1762 /* wait for the overlapped to complete */
1763 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1764 CloseHandle(ov.hEvent);
1766 return ret;
1769 /***********************************************************************
1770 * GetCommProperties (KERNEL32.@)
1772 * This function fills in a structure with the capabilities of the
1773 * communications port driver.
1775 * RETURNS
1777 * TRUE on success, FALSE on failure
1778 * If successful, the lpCommProp structure be filled in with
1779 * properties of the comm port.
1781 BOOL WINAPI GetCommProperties(
1782 HANDLE hFile, /* [in] handle of the comm port */
1783 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1785 FIXME("(%d %p )\n",hFile,lpCommProp);
1786 if(!lpCommProp)
1787 return FALSE;
1790 * These values should be valid for LINUX's serial driver
1791 * FIXME: Perhaps they deserve an #ifdef LINUX
1793 memset(lpCommProp,0,sizeof(COMMPROP));
1794 lpCommProp->wPacketLength = 1;
1795 lpCommProp->wPacketVersion = 1;
1796 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1797 lpCommProp->dwReserved1 = 0;
1798 lpCommProp->dwMaxTxQueue = 4096;
1799 lpCommProp->dwMaxRxQueue = 4096;
1800 lpCommProp->dwMaxBaud = BAUD_115200;
1801 lpCommProp->dwProvSubType = PST_RS232;
1802 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1803 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1804 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1805 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1806 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1807 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1808 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1809 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1810 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1811 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1812 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1814 return TRUE;
1817 /***********************************************************************
1818 * FIXME:
1819 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1820 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1821 * This is dependent on the type of COMM port, but since it is doubtful
1822 * anybody will get around to implementing support for fancy serial
1823 * ports in WINE, this is hardcoded for the time being. The name of
1824 * this DLL should be stored in and read from the system registry in
1825 * the hive HKEY_LOCAL_MACHINE, key
1826 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1827 * where ???? is the port number... that is determined by PNP
1828 * The DLL should be loaded when the COMM port is opened, and closed
1829 * when the COMM port is closed. - MJM 20 June 2000
1830 ***********************************************************************/
1831 static CHAR lpszSerialUI[] = "serialui.dll";
1834 /***********************************************************************
1835 * CommConfigDialogA (KERNEL32.@)
1837 * Raises a dialog that allows the user to configure a comm port.
1838 * Fills the COMMCONFIG struct with information specified by the user.
1839 * This function should call a similar routine in the COMM driver...
1841 * RETURNS
1843 * TRUE on success, FALSE on failure
1844 * If successful, the lpCommConfig structure will contain a new
1845 * configuration for the comm port, as specified by the user.
1847 * BUGS
1848 * The library with the CommConfigDialog code is never unloaded.
1849 * Perhaps this should be done when the comm port is closed?
1851 BOOL WINAPI CommConfigDialogA(
1852 LPCSTR lpszDevice, /* [in] name of communications device */
1853 HANDLE hWnd, /* [in] parent window for the dialog */
1854 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1856 FARPROC lpfnCommDialog;
1857 HMODULE hConfigModule;
1858 BOOL r;
1860 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
1862 hConfigModule = LoadLibraryA(lpszSerialUI);
1863 if(!hConfigModule)
1864 return FALSE;
1866 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
1868 if(!lpfnCommDialog)
1869 return FALSE;
1871 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1873 /* UnloadLibrary(hConfigModule); */
1875 return r;
1878 /***********************************************************************
1879 * CommConfigDialogW (KERNEL32.@)
1881 * see CommConfigDialogA for more info
1883 BOOL WINAPI CommConfigDialogW(
1884 LPCWSTR lpszDevice, /* [in] name of communications device */
1885 HANDLE hWnd, /* [in] parent window for the dialog */
1886 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1888 BOOL r;
1889 LPSTR lpDeviceA;
1891 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1892 if(lpDeviceA)
1893 return FALSE;
1894 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
1895 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1896 return r;
1899 /***********************************************************************
1900 * GetCommConfig (KERNEL32.@)
1902 * Fill in the COMMCONFIG structure for the comm port hFile
1904 * RETURNS
1906 * TRUE on success, FALSE on failure
1907 * If successful, lpCommConfig contains the comm port configuration.
1909 * BUGS
1912 BOOL WINAPI GetCommConfig(
1913 HANDLE hFile, /* [in] The communications device. */
1914 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1915 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1916 afterwards the number of bytes copied to the buffer or
1917 the needed size of the buffer. */
1919 BOOL r;
1921 TRACE("(%x %p)\n",hFile,lpCommConfig);
1923 if(lpCommConfig == NULL)
1924 return FALSE;
1926 r = *lpdwSize < sizeof(COMMCONFIG);
1927 *lpdwSize = sizeof(COMMCONFIG);
1928 if(!r)
1929 return FALSE;
1931 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1932 lpCommConfig->wVersion = 1;
1933 lpCommConfig->wReserved = 0;
1934 r = GetCommState(hFile,&lpCommConfig->dcb);
1935 lpCommConfig->dwProviderSubType = PST_RS232;
1936 lpCommConfig->dwProviderOffset = 0;
1937 lpCommConfig->dwProviderSize = 0;
1939 return r;
1942 /***********************************************************************
1943 * SetCommConfig (KERNEL32.@)
1945 * Sets the configuration of the communications device.
1947 * RETURNS
1949 * True on success, false if the handle was bad is not a communications device.
1951 BOOL WINAPI SetCommConfig(
1952 HANDLE hFile, /* [in] The communications device. */
1953 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1954 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1956 TRACE("(%x %p)\n",hFile,lpCommConfig);
1957 return SetCommState(hFile,&lpCommConfig->dcb);
1960 /***********************************************************************
1961 * SetDefaultCommConfigA (KERNEL32.@)
1963 * Initializes the default configuration for the specified communication
1964 * device. (ascii)
1966 * RETURNS
1968 * True if the device was found and the defaults set, false otherwise
1970 BOOL WINAPI SetDefaultCommConfigA(
1971 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1972 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1973 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1975 FARPROC lpfnSetDefaultCommConfig;
1976 HMODULE hConfigModule;
1977 BOOL r;
1979 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1981 hConfigModule = LoadLibraryA(lpszSerialUI);
1982 if(!hConfigModule)
1983 return FALSE;
1985 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
1987 if(! lpfnSetDefaultCommConfig)
1988 return TRUE;
1990 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1992 /* UnloadLibrary(hConfigModule); */
1994 return r;
1998 /***********************************************************************
1999 * SetDefaultCommConfigW (KERNEL32.@)
2001 * Initializes the default configuration for the specified
2002 * communication device. (unicode)
2004 * RETURNS
2007 BOOL WINAPI SetDefaultCommConfigW(
2008 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2009 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2010 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2012 BOOL r;
2013 LPSTR lpDeviceA;
2015 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2017 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2018 if(lpDeviceA)
2019 return FALSE;
2020 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2021 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2022 return r;
2026 /***********************************************************************
2027 * GetDefaultCommConfigA (KERNEL32.@)
2029 * Acquires the default configuration of the specified communication device. (unicode)
2031 * RETURNS
2033 * True on successful reading of the default configuration,
2034 * if the device is not found or the buffer is too small.
2036 BOOL WINAPI GetDefaultCommConfigA(
2037 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2038 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2039 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2040 afterwards the number of bytes copied to the buffer or
2041 the needed size of the buffer. */
2043 LPDCB lpdcb = &(lpCC->dcb);
2044 char temp[40];
2046 if (strncasecmp(lpszName,"COM",3)) {
2047 ERR("not implemented for <%s>\n", lpszName);
2048 return FALSE;
2051 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2052 if (*lpdwSize < sizeof(COMMCONFIG)) {
2053 *lpdwSize = sizeof(COMMCONFIG);
2054 return FALSE;
2057 *lpdwSize = sizeof(COMMCONFIG);
2059 lpCC->dwSize = sizeof(COMMCONFIG);
2060 lpCC->wVersion = 1;
2061 lpCC->dwProviderSubType = PST_RS232;
2062 lpCC->dwProviderOffset = 0L;
2063 lpCC->dwProviderSize = 0L;
2065 sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2066 FIXME("setting %s as default\n", temp);
2068 return BuildCommDCBA( temp, lpdcb);
2071 /**************************************************************************
2072 * GetDefaultCommConfigW (KERNEL32.@)
2074 * Acquires the default configuration of the specified communication device. (unicode)
2076 * RETURNS
2078 * True on successful reading of the default configuration,
2079 * if the device is not found or the buffer is too small.
2081 BOOL WINAPI GetDefaultCommConfigW(
2082 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2083 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2084 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2085 afterwards the number of bytes copied to the buffer or
2086 the needed size of the buffer. */
2088 BOOL ret = FALSE;
2089 LPSTR lpszNameA;
2091 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2092 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2093 if (lpszNameA)
2095 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2096 HeapFree( GetProcessHeap(), 0, lpszNameA );
2098 return ret;