Add LanguageGroup/GeoID enumeration fns.
[wine/hacks.git] / dlls / kernel / comm.c
blobdfd163e803316856ebfecf84bdc53933ee3375b2
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_Parse* (Internal)
161 * The following COMM_Parse* functions are used by the BuildCommDCB
162 * functions to help parse the various parts of the device control string.
164 static LPCSTR COMM_ParseStart(LPCSTR ptr)
166 /* The device control string may optionally start with "COMx" followed
167 by an optional ':' and spaces. */
168 if(!strncasecmp(ptr, "COM", 3))
170 ptr += 3;
172 /* Allow any com port above 0 as Win 9x does (NT only allows
173 values for com ports which are actually present) */
174 if(*ptr < '1' || *ptr > '9')
175 return NULL;
177 /* Advance pointer past port number */
178 while(*ptr >= '0' && *ptr <= '9') ptr++;
180 /* The com port number must be followed by a ':' or ' ' */
181 if(*ptr != ':' && *ptr != ' ')
182 return NULL;
184 /* Advance pointer to beginning of next parameter */
185 while(*ptr == ' ') ptr++;
186 if(*ptr == ':')
188 ptr++;
189 while(*ptr == ' ') ptr++;
192 /* The device control string must not start with a space. */
193 else if(*ptr == ' ')
194 return NULL;
196 return ptr;
199 static LPCSTR COMM_ParseNumber(LPCSTR ptr, LPDWORD lpnumber)
201 if(*ptr < '0' || *ptr > '9') return NULL;
202 if(!sscanf(ptr, "%lu", lpnumber)) return NULL;
203 while(*ptr >= '0' && *ptr <= '9') ptr++;
204 return ptr;
207 static LPCSTR COMM_ParseParity(LPCSTR ptr, LPBYTE lpparity)
209 /* Contrary to what you might expect, Windows only sets the Parity
210 member of DCB and not fParity even when parity is specified in the
211 device control string */
213 switch(toupper(*ptr++))
215 case 'E':
216 *lpparity = EVENPARITY;
217 break;
218 case 'M':
219 *lpparity = MARKPARITY;
220 break;
221 case 'N':
222 *lpparity = NOPARITY;
223 break;
224 case 'O':
225 *lpparity = ODDPARITY;
226 break;
227 case 'S':
228 *lpparity = SPACEPARITY;
229 break;
230 default:
231 return NULL;
234 return ptr;
237 static LPCSTR COMM_ParseByteSize(LPCSTR ptr, LPBYTE lpbytesize)
239 DWORD temp;
241 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
242 return NULL;
244 if(temp >= 5 && temp <= 8)
246 *lpbytesize = temp;
247 return ptr;
249 else
250 return NULL;
253 static LPCSTR COMM_ParseStopBits(LPCSTR ptr, LPBYTE lpstopbits)
255 DWORD temp;
257 if(!strncmp("1.5", ptr, 3))
259 ptr += 3;
260 *lpstopbits = ONE5STOPBITS;
262 else
264 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
265 return NULL;
267 if(temp == 1)
268 *lpstopbits = ONESTOPBIT;
269 else if(temp == 2)
270 *lpstopbits = TWOSTOPBITS;
271 else
272 return NULL;
275 return ptr;
278 static LPCSTR COMM_ParseOnOff(LPCSTR ptr, LPDWORD lponoff)
280 if(!strncasecmp("on", ptr, 2))
282 ptr += 2;
283 *lponoff = 1;
285 else if(!strncasecmp("off", ptr, 3))
287 ptr += 3;
288 *lponoff = 0;
290 else
291 return NULL;
293 return ptr;
296 /***********************************************************************
297 * COMM_BuildOldCommDCB (Internal)
299 * Build a DCB using the old style settings string eg: "96,n,8,1"
301 static BOOL COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
303 char last = 0;
305 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
306 return FALSE;
308 switch(lpdcb->BaudRate)
310 case 11:
311 case 30:
312 case 60:
313 lpdcb->BaudRate *= 10;
314 break;
315 case 12:
316 case 24:
317 case 48:
318 case 96:
319 lpdcb->BaudRate *= 100;
320 break;
321 case 19:
322 lpdcb->BaudRate = 19200;
323 break;
326 while(*device == ' ') device++;
327 if(*device++ != ',') return FALSE;
328 while(*device == ' ') device++;
330 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
331 return FALSE;
333 while(*device == ' ') device++;
334 if(*device++ != ',') return FALSE;
335 while(*device == ' ') device++;
337 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
338 return FALSE;
340 while(*device == ' ') device++;
341 if(*device++ != ',') return FALSE;
342 while(*device == ' ') device++;
344 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
345 return FALSE;
347 /* The last parameter for flow control is optional. */
348 while(*device == ' ') device++;
349 if(*device == ',')
351 device++;
352 while(*device == ' ') device++;
353 if(*device) last = toupper(*device++);
354 while(*device == ' ') device++;
357 /* Win NT sets the flow control members based on (or lack of) the last
358 parameter. Win 9x does not set these members. */
359 switch(last)
361 case 0:
362 lpdcb->fInX = FALSE;
363 lpdcb->fOutX = FALSE;
364 lpdcb->fOutxCtsFlow = FALSE;
365 lpdcb->fOutxDsrFlow = FALSE;
366 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
367 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
368 break;
369 case 'X':
370 lpdcb->fInX = TRUE;
371 lpdcb->fOutX = TRUE;
372 lpdcb->fOutxCtsFlow = FALSE;
373 lpdcb->fOutxDsrFlow = FALSE;
374 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
375 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
376 break;
377 case 'P':
378 lpdcb->fInX = FALSE;
379 lpdcb->fOutX = FALSE;
380 lpdcb->fOutxCtsFlow = TRUE;
381 lpdcb->fOutxDsrFlow = TRUE;
382 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
383 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
384 break;
385 default:
386 return FALSE;
389 /* This should be the end of the string. */
390 if(*device) return FALSE;
392 return TRUE;
395 /***********************************************************************
396 * COMM_BuildNewCommDCB (Internal)
398 * Build a DCB using the new style settings string.
399 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
401 static BOOL COMM_BuildNewCommDCB(LPCSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
403 DWORD temp;
404 BOOL baud = FALSE, stop = FALSE;
406 while(*device)
408 while(*device == ' ') device++;
410 if(!strncasecmp("baud=", device, 5))
412 baud = TRUE;
414 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
415 return FALSE;
417 else if(!strncasecmp("parity=", device, 7))
419 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
420 return FALSE;
422 else if(!strncasecmp("data=", device, 5))
424 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
425 return FALSE;
427 else if(!strncasecmp("stop=", device, 5))
429 stop = TRUE;
431 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
432 return FALSE;
434 else if(!strncasecmp("to=", device, 3))
436 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
437 return FALSE;
439 lptimeouts->ReadIntervalTimeout = 0;
440 lptimeouts->ReadTotalTimeoutMultiplier = 0;
441 lptimeouts->ReadTotalTimeoutConstant = 0;
442 lptimeouts->WriteTotalTimeoutMultiplier = 0;
443 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
445 else if(!strncasecmp("xon=", device, 4))
447 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
448 return FALSE;
450 lpdcb->fOutX = temp;
451 lpdcb->fInX = temp;
453 else if(!strncasecmp("odsr=", device, 5))
455 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
456 return FALSE;
458 lpdcb->fOutxDsrFlow = temp;
460 else if(!strncasecmp("octs=", device, 5))
462 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
463 return FALSE;
465 lpdcb->fOutxCtsFlow = temp;
467 else if(!strncasecmp("dtr=", device, 4))
469 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
470 return FALSE;
472 lpdcb->fDtrControl = temp;
474 else if(!strncasecmp("rts=", device, 4))
476 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
477 return FALSE;
479 lpdcb->fRtsControl = temp;
481 else if(!strncasecmp("idsr=", device, 5))
483 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
484 return FALSE;
486 /* Win NT sets the fDsrSensitivity member based on the
487 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
488 lpdcb->fDsrSensitivity = temp;
490 else
491 return FALSE;
493 /* After the above parsing, the next character (if not the end of
494 the string) should be a space */
495 if(*device && *device != ' ')
496 return FALSE;
499 /* If stop bits were not specified, a default is always supplied. */
500 if(!stop)
502 if(baud && lpdcb->BaudRate == 110)
503 lpdcb->StopBits = TWOSTOPBITS;
504 else
505 lpdcb->StopBits = ONESTOPBIT;
508 return TRUE;
511 /**************************************************************************
512 * BuildCommDCBA (KERNEL32.@)
514 * Updates a device control block data structure with values from an
515 * ascii device control string. The device control string has two forms
516 * normal and extended, it must be exclusively in one or the other form.
518 * RETURNS
520 * True on success, false on a malformed control string.
522 BOOL WINAPI BuildCommDCBA(
523 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
524 LPDCB lpdcb) /* [out] The device control block to be updated. */
526 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
529 /**************************************************************************
530 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
532 * Updates a device control block data structure with values from an
533 * ascii device control string. Taking timeout values from a timeouts
534 * struct if desired by the control string.
536 * RETURNS
538 * True on success, false bad handles etc
540 BOOL WINAPI BuildCommDCBAndTimeoutsA(
541 LPCSTR device, /* [in] The ascii device control string. */
542 LPDCB lpdcb, /* [out] The device control block to be updated. */
543 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
545 DCB dcb;
546 COMMTIMEOUTS timeouts;
547 BOOL result;
548 LPCSTR ptr = device;
550 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
552 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
553 lpdcb->DCBlength = sizeof(DCB);
555 /* Make a copy of the original data structures to work with since if
556 if there is an error in the device control string the originals
557 should not be modified (except possibly DCBlength) */
558 memcpy(&dcb, lpdcb, sizeof(DCB));
559 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
561 ptr = COMM_ParseStart(ptr);
563 if(ptr == NULL)
564 result = FALSE;
565 else if(strchr(ptr, ','))
566 result = COMM_BuildOldCommDCB(ptr, &dcb);
567 else
568 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
570 if(result)
572 memcpy(lpdcb, &dcb, sizeof(DCB));
573 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
574 return TRUE;
576 else
578 WARN("Invalid device control string: %s\n", device);
579 SetLastError(ERROR_INVALID_PARAMETER);
580 return FALSE;
584 /**************************************************************************
585 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
587 * Updates a device control block data structure with values from an
588 * unicode device control string. Taking timeout values from a timeouts
589 * struct if desired by the control string.
591 * RETURNS
593 * True on success, false bad handles etc.
595 BOOL WINAPI BuildCommDCBAndTimeoutsW(
596 LPCWSTR devid, /* [in] The unicode device control string. */
597 LPDCB lpdcb, /* [out] The device control block to be updated. */
598 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
600 BOOL ret = FALSE;
601 LPSTR devidA;
603 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
604 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
605 if (devidA)
607 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
608 HeapFree( GetProcessHeap(), 0, devidA );
610 return ret;
613 /**************************************************************************
614 * BuildCommDCBW (KERNEL32.@)
616 * Updates a device control block structure with values from an
617 * unicode device control string. The device control string has two forms
618 * normal and extended, it must be exclusively in one or the other form.
620 * RETURNS
622 * True on success, false on an malformed control string.
624 BOOL WINAPI BuildCommDCBW(
625 LPCWSTR devid, /* [in] The unicode device control string. */
626 LPDCB lpdcb) /* [out] The device control block to be updated. */
628 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
631 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
633 DWORD ret;
635 SERVER_START_REQ( set_serial_info )
637 req->handle = handle;
638 req->flags = SERIALINFO_SET_ERROR;
639 req->commerror = error;
640 ret = !wine_server_call_err( req );
642 SERVER_END_REQ;
643 return ret;
646 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
648 DWORD ret;
650 if(!lperror)
651 return FALSE;
653 SERVER_START_REQ( get_serial_info )
655 req->handle = handle;
656 ret = !wine_server_call_err( req );
657 *lperror = reply->commerror;
659 SERVER_END_REQ;
661 return ret;
664 /*****************************************************************************
665 * SetCommBreak (KERNEL32.@)
667 * Halts the transmission of characters to a communications device.
669 * RETURNS
671 * True on success, and false if the communications device could not be found,
672 * the control is not supported.
674 * BUGS
676 * Only TIOCSBRK and TIOCCBRK are supported.
678 BOOL WINAPI SetCommBreak(
679 HANDLE handle) /* [in] The communictions device to suspend. */
681 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
682 int fd,result;
684 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
685 if(fd<0) {
686 TRACE("FILE_GetUnixHandle failed\n");
687 return FALSE;
689 result = ioctl(fd,TIOCSBRK,0);
690 close(fd);
691 if (result ==-1)
693 TRACE("ioctl failed\n");
694 SetLastError(ERROR_NOT_SUPPORTED);
695 return FALSE;
697 return TRUE;
698 #else
699 FIXME("ioctl not available\n");
700 SetLastError(ERROR_NOT_SUPPORTED);
701 return FALSE;
702 #endif
705 /*****************************************************************************
706 * ClearCommBreak (KERNEL32.@)
708 * Resumes character transmission from a communication device.
710 * RETURNS
712 * True on success and false if the communications device could not be found.
714 * BUGS
716 * Only TIOCSBRK and TIOCCBRK are supported.
718 BOOL WINAPI ClearCommBreak(
719 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
721 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
722 int fd,result;
724 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
725 if(fd<0) {
726 TRACE("FILE_GetUnixHandle failed\n");
727 return FALSE;
729 result = ioctl(fd,TIOCCBRK,0);
730 close(fd);
731 if (result ==-1)
733 TRACE("ioctl failed\n");
734 SetLastError(ERROR_NOT_SUPPORTED);
735 return FALSE;
737 return TRUE;
738 #else
739 FIXME("ioctl not available\n");
740 SetLastError(ERROR_NOT_SUPPORTED);
741 return FALSE;
742 #endif
745 /*****************************************************************************
746 * EscapeCommFunction (KERNEL32.@)
748 * Directs a communication device to perform an extended function.
750 * RETURNS
752 * True or requested data on successful completion of the command,
753 * false if the device is not present cannot execute the command
754 * or the command failed.
756 BOOL WINAPI EscapeCommFunction(
757 HANDLE handle, /* [in] The communication device to perform the extended function. */
758 UINT nFunction) /* [in] The extended function to be performed. */
760 int fd,direct=FALSE,result=FALSE;
761 struct termios port;
763 TRACE("handle %p, function=%d\n", handle, nFunction);
764 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
765 if(fd<0) {
766 FIXME("handle %p not found.\n",handle);
767 return FALSE;
770 if (tcgetattr(fd,&port) == -1) {
771 COMM_SetCommError(handle,CE_IOE);
772 close(fd);
773 return FALSE;
776 switch (nFunction) {
777 case RESETDEV:
778 TRACE("\n");
779 break;
781 case CLRDTR:
782 TRACE("CLRDTR\n");
783 #ifdef TIOCM_DTR
784 direct=TRUE;
785 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
786 break;
787 #endif
789 case CLRRTS:
790 TRACE("CLRRTS\n");
791 #ifdef TIOCM_RTS
792 direct=TRUE;
793 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
794 break;
795 #endif
797 case SETDTR:
798 TRACE("SETDTR\n");
799 #ifdef TIOCM_DTR
800 direct=TRUE;
801 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
802 break;
803 #endif
805 case SETRTS:
806 TRACE("SETRTS\n");
807 #ifdef TIOCM_RTS
808 direct=TRUE;
809 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
810 break;
811 #endif
813 case SETXOFF:
814 TRACE("SETXOFF\n");
815 port.c_iflag |= IXOFF;
816 break;
818 case SETXON:
819 TRACE("SETXON\n");
820 port.c_iflag |= IXON;
821 break;
822 case SETBREAK:
823 TRACE("setbreak\n");
824 #ifdef TIOCSBRK
825 direct=TRUE;
826 result = ioctl(fd,TIOCSBRK,0);
827 break;
828 #endif
829 case CLRBREAK:
830 TRACE("clrbreak\n");
831 #ifdef TIOCSBRK
832 direct=TRUE;
833 result = ioctl(fd,TIOCCBRK,0);
834 break;
835 #endif
836 default:
837 WARN("(handle=%p,nFunction=%d): Unknown function\n",
838 handle, nFunction);
839 break;
842 if (!direct)
843 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
844 close(fd);
845 COMM_SetCommError(handle,CE_IOE);
846 return FALSE;
847 } else
848 result= TRUE;
849 else
851 if (result == -1)
853 result= FALSE;
854 COMM_SetCommError(handle,CE_IOE);
856 else
857 result = TRUE;
859 close(fd);
860 return result;
863 /********************************************************************
864 * PurgeComm (KERNEL32.@)
866 * Terminates pending operations and/or discards buffers on a
867 * communication resource.
869 * RETURNS
871 * True on success and false if the communications handle is bad.
873 BOOL WINAPI PurgeComm(
874 HANDLE handle, /* [in] The communication resource to be purged. */
875 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
877 int fd;
879 TRACE("handle %p, flags %lx\n", handle, flags);
881 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
882 if(fd<0) {
883 FIXME("no handle %p found\n",handle);
884 return FALSE;
888 ** not exactly sure how these are different
889 ** Perhaps if we had our own internal queues, one flushes them
890 ** and the other flushes the kernel's buffers.
892 if(flags&PURGE_TXABORT)
893 tcflush(fd,TCOFLUSH);
894 if(flags&PURGE_RXABORT)
895 tcflush(fd,TCIFLUSH);
896 if(flags&PURGE_TXCLEAR)
897 tcflush(fd,TCOFLUSH);
898 if(flags&PURGE_RXCLEAR)
899 tcflush(fd,TCIFLUSH);
900 close(fd);
902 return 1;
905 /*****************************************************************************
906 * ClearCommError (KERNEL32.@)
908 * Enables further I/O operations on a communications resource after
909 * supplying error and current status information.
911 * RETURNS
913 * True on success, false if the communication resource handle is bad.
915 BOOL WINAPI ClearCommError(
916 HANDLE handle, /* [in] The communication resource with the error. */
917 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
918 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
920 int fd;
922 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
923 if(0>fd)
925 FIXME("no handle %p found\n",handle);
926 return FALSE;
929 if (lpStat)
931 lpStat->fCtsHold = 0;
932 lpStat->fDsrHold = 0;
933 lpStat->fRlsdHold = 0;
934 lpStat->fXoffHold = 0;
935 lpStat->fXoffSent = 0;
936 lpStat->fEof = 0;
937 lpStat->fTxim = 0;
938 lpStat->fReserved = 0;
940 #ifdef TIOCOUTQ
941 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
942 WARN("ioctl returned error\n");
943 #else
944 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
945 #endif
947 #ifdef TIOCINQ
948 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
949 WARN("ioctl returned error\n");
950 #endif
952 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
953 handle, lpStat->cbInQue, lpStat->cbOutQue);
956 close(fd);
958 COMM_GetCommError(handle, errors);
959 COMM_SetCommError(handle, 0);
961 return TRUE;
964 /*****************************************************************************
965 * SetupComm (KERNEL32.@)
967 * Called after CreateFile to hint to the communication resource to use
968 * specified sizes for input and output buffers rather than the default values.
970 * RETURNS
972 * True if successful, false if the communications resource handle is bad.
974 * BUGS
976 * Stub.
978 BOOL WINAPI SetupComm(
979 HANDLE handle, /* [in] The just created communication resource handle. */
980 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
981 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
983 int fd;
985 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
986 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
987 if(0>fd) {
988 FIXME("handle %p not found?\n",handle);
989 return FALSE;
991 close(fd);
992 return TRUE;
995 /*****************************************************************************
996 * GetCommMask (KERNEL32.@)
998 * Obtain the events associated with a communication device that will cause
999 * a call WaitCommEvent to return.
1001 * RETURNS
1003 * True on success, fail on bad device handle etc.
1005 BOOL WINAPI GetCommMask(
1006 HANDLE handle, /* [in] The communications device. */
1007 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1009 BOOL ret;
1011 TRACE("handle %p, mask %p\n", handle, evtmask);
1013 SERVER_START_REQ( get_serial_info )
1015 req->handle = handle;
1016 if ((ret = !wine_server_call_err( req )))
1018 if (evtmask) *evtmask = reply->eventmask;
1021 SERVER_END_REQ;
1022 return ret;
1025 /*****************************************************************************
1026 * SetCommMask (KERNEL32.@)
1028 * There be some things we need to hear about yon there communications device.
1029 * (Set which events associated with a communication device should cause
1030 * a call WaitCommEvent to return.)
1032 * RETURNS
1034 * True on success, false on bad handle etc.
1036 BOOL WINAPI SetCommMask(
1037 HANDLE handle, /* [in] The communications device. */
1038 DWORD evtmask) /* [in] The events that are to be monitored. */
1040 BOOL ret;
1042 TRACE("handle %p, mask %lx\n", handle, evtmask);
1044 SERVER_START_REQ( set_serial_info )
1046 req->handle = handle;
1047 req->flags = SERIALINFO_SET_MASK;
1048 req->eventmask = evtmask;
1049 ret = !wine_server_call_err( req );
1051 SERVER_END_REQ;
1052 return ret;
1055 /*****************************************************************************
1056 * SetCommState (KERNEL32.@)
1058 * Re-initializes all hardware and control settings of a communications device,
1059 * with values from a device control block without effecting the input and output
1060 * queues.
1062 * RETURNS
1064 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1066 BOOL WINAPI SetCommState(
1067 HANDLE handle, /* [in] The communications device. */
1068 LPDCB lpdcb) /* [out] The device control block. */
1070 struct termios port;
1071 int fd, bytesize, stopbits;
1073 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1074 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1075 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1076 (lpdcb->StopBits == ONESTOPBIT)?1:
1077 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1078 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1079 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1081 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1082 if (fd < 0) {
1083 FIXME("no handle %p found\n",handle);
1084 return FALSE;
1087 if ((tcgetattr(fd,&port)) == -1) {
1088 int save_error = errno;
1089 COMM_SetCommError(handle,CE_IOE);
1090 close( fd );
1091 ERR("tcgetattr error '%s'\n", strerror(save_error));
1092 return FALSE;
1095 port.c_cc[VMIN] = 0;
1096 port.c_cc[VTIME] = 1;
1098 #ifdef IMAXBEL
1099 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1100 #else
1101 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1102 #endif
1103 port.c_iflag |= (IGNBRK);
1105 port.c_oflag &= ~(OPOST);
1107 port.c_cflag &= ~(HUPCL);
1108 port.c_cflag |= CLOCAL | CREAD;
1110 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1111 port.c_lflag |= NOFLSH;
1113 #ifdef CBAUD
1114 port.c_cflag &= ~CBAUD;
1115 switch (lpdcb->BaudRate) {
1116 case 110:
1117 case CBR_110:
1118 port.c_cflag |= B110;
1119 break;
1120 case 300:
1121 case CBR_300:
1122 port.c_cflag |= B300;
1123 break;
1124 case 600:
1125 case CBR_600:
1126 port.c_cflag |= B600;
1127 break;
1128 case 1200:
1129 case CBR_1200:
1130 port.c_cflag |= B1200;
1131 break;
1132 case 2400:
1133 case CBR_2400:
1134 port.c_cflag |= B2400;
1135 break;
1136 case 4800:
1137 case CBR_4800:
1138 port.c_cflag |= B4800;
1139 break;
1140 case 9600:
1141 case CBR_9600:
1142 port.c_cflag |= B9600;
1143 break;
1144 case 19200:
1145 case CBR_19200:
1146 port.c_cflag |= B19200;
1147 break;
1148 case 38400:
1149 case CBR_38400:
1150 port.c_cflag |= B38400;
1151 break;
1152 #ifdef B57600
1153 case 57600:
1154 port.c_cflag |= B57600;
1155 break;
1156 #endif
1157 #ifdef B115200
1158 case 115200:
1159 port.c_cflag |= B115200;
1160 break;
1161 #endif
1162 #ifdef B230400
1163 case 230400:
1164 port.c_cflag |= B230400;
1165 break;
1166 #endif
1167 #ifdef B460800
1168 case 460800:
1169 port.c_cflag |= B460800;
1170 break;
1171 #endif
1172 default:
1173 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1174 { struct serial_struct nuts;
1175 int arby;
1176 ioctl(fd, TIOCGSERIAL, &nuts);
1177 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1178 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1179 arby = nuts.baud_base / nuts.custom_divisor;
1180 nuts.flags &= ~ASYNC_SPD_MASK;
1181 nuts.flags |= ASYNC_SPD_CUST;
1182 WARN("You (or a program acting at your behest) have specified\n"
1183 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1184 "which is as close as we can get by our present understanding of your\n"
1185 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1186 "has caused to your linux system can be undone with setserial \n"
1187 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1188 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1189 ioctl(fd, TIOCSSERIAL, &nuts);
1190 port.c_cflag |= B38400;
1192 break;
1193 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1196 COMM_SetCommError(handle,IE_BAUDRATE);
1197 close( fd );
1198 ERR("baudrate %ld\n",lpdcb->BaudRate);
1199 return FALSE;
1201 #elif !defined(__EMX__)
1202 switch (lpdcb->BaudRate) {
1203 case 110:
1204 case CBR_110:
1205 port.c_ospeed = B110;
1206 break;
1207 case 300:
1208 case CBR_300:
1209 port.c_ospeed = B300;
1210 break;
1211 case 600:
1212 case CBR_600:
1213 port.c_ospeed = B600;
1214 break;
1215 case 1200:
1216 case CBR_1200:
1217 port.c_ospeed = B1200;
1218 break;
1219 case 2400:
1220 case CBR_2400:
1221 port.c_ospeed = B2400;
1222 break;
1223 case 4800:
1224 case CBR_4800:
1225 port.c_ospeed = B4800;
1226 break;
1227 case 9600:
1228 case CBR_9600:
1229 port.c_ospeed = B9600;
1230 break;
1231 case 19200:
1232 case CBR_19200:
1233 port.c_ospeed = B19200;
1234 break;
1235 case 38400:
1236 case CBR_38400:
1237 port.c_ospeed = B38400;
1238 break;
1239 #ifdef B57600
1240 case 57600:
1241 case CBR_57600:
1242 port.c_cflag |= B57600;
1243 break;
1244 #endif
1245 #ifdef B115200
1246 case 115200:
1247 case CBR_115200:
1248 port.c_cflag |= B115200;
1249 break;
1250 #endif
1251 #ifdef B230400
1252 case 230400:
1253 port.c_cflag |= B230400;
1254 break;
1255 #endif
1256 #ifdef B460800
1257 case 460800:
1258 port.c_cflag |= B460800;
1259 break;
1260 #endif
1261 default:
1262 COMM_SetCommError(handle,IE_BAUDRATE);
1263 close( fd );
1264 ERR("baudrate %ld\n",lpdcb->BaudRate);
1265 return FALSE;
1267 port.c_ispeed = port.c_ospeed;
1268 #endif
1269 bytesize=lpdcb->ByteSize;
1270 stopbits=lpdcb->StopBits;
1272 #ifdef CMSPAR
1273 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1274 #else
1275 port.c_cflag &= ~(PARENB | PARODD);
1276 #endif
1277 if (lpdcb->fParity)
1278 port.c_iflag |= INPCK;
1279 else
1280 port.c_iflag &= ~INPCK;
1281 switch (lpdcb->Parity) {
1282 case NOPARITY:
1283 break;
1284 case ODDPARITY:
1285 port.c_cflag |= (PARENB | PARODD);
1286 break;
1287 case EVENPARITY:
1288 port.c_cflag |= PARENB;
1289 break;
1290 #ifdef CMSPAR
1291 /* Linux defines mark/space (stick) parity */
1292 case MARKPARITY:
1293 port.c_cflag |= (PARENB | CMSPAR);
1294 break;
1295 case SPACEPARITY:
1296 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1297 break;
1298 #else
1299 /* try the POSIX way */
1300 case MARKPARITY:
1301 if( stopbits == ONESTOPBIT) {
1302 stopbits = TWOSTOPBITS;
1303 port.c_iflag &= ~INPCK;
1304 } else {
1305 COMM_SetCommError(handle,IE_BYTESIZE);
1306 close( fd );
1307 ERR("Cannot set MARK Parity\n");
1308 return FALSE;
1310 break;
1311 case SPACEPARITY:
1312 if( bytesize < 8) {
1313 bytesize +=1;
1314 port.c_iflag &= ~INPCK;
1315 } else {
1316 COMM_SetCommError(handle,IE_BYTESIZE);
1317 close( fd );
1318 ERR("Cannot set SPACE Parity\n");
1319 return FALSE;
1321 break;
1322 #endif
1323 default:
1324 COMM_SetCommError(handle,IE_BYTESIZE);
1325 close( fd );
1326 ERR("Parity\n");
1327 return FALSE;
1331 port.c_cflag &= ~CSIZE;
1332 switch (bytesize) {
1333 case 5:
1334 port.c_cflag |= CS5;
1335 break;
1336 case 6:
1337 port.c_cflag |= CS6;
1338 break;
1339 case 7:
1340 port.c_cflag |= CS7;
1341 break;
1342 case 8:
1343 port.c_cflag |= CS8;
1344 break;
1345 default:
1346 COMM_SetCommError(handle,IE_BYTESIZE);
1347 close( fd );
1348 ERR("ByteSize\n");
1349 return FALSE;
1352 switch (stopbits) {
1353 case ONESTOPBIT:
1354 port.c_cflag &= ~CSTOPB;
1355 break;
1356 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1357 case TWOSTOPBITS:
1358 port.c_cflag |= CSTOPB;
1359 break;
1360 default:
1361 COMM_SetCommError(handle,IE_BYTESIZE);
1362 close( fd );
1363 ERR("StopBits\n");
1364 return FALSE;
1366 #ifdef CRTSCTS
1367 if ( lpdcb->fOutxCtsFlow ||
1368 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1371 port.c_cflag |= CRTSCTS;
1372 TRACE("CRTSCTS\n");
1374 #endif
1376 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1378 WARN("DSR/DTR flow control not supported\n");
1381 if (lpdcb->fInX)
1382 port.c_iflag |= IXON;
1383 else
1384 port.c_iflag &= ~IXON;
1385 if (lpdcb->fOutX)
1386 port.c_iflag |= IXOFF;
1387 else
1388 port.c_iflag &= ~IXOFF;
1390 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1391 int save_error=errno;
1392 COMM_SetCommError(handle,CE_IOE);
1393 close( fd );
1394 ERR("tcsetattr error '%s'\n", strerror(save_error));
1395 return FALSE;
1396 } else {
1397 COMM_SetCommError(handle,0);
1398 close( fd );
1399 return TRUE;
1404 /*****************************************************************************
1405 * GetCommState (KERNEL32.@)
1407 * Fills in a device control block with information from a communications device.
1409 * RETURNS
1411 * True on success, false if the communication device handle is bad etc
1413 * BUGS
1415 * XonChar and XoffChar are not set.
1417 BOOL WINAPI GetCommState(
1418 HANDLE handle, /* [in] The communications device. */
1419 LPDCB lpdcb) /* [out] The device control block. */
1421 struct termios port;
1422 int fd,speed;
1424 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1426 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1427 if (fd < 0)
1429 ERR("FILE_GetUnixHandle failed\n");
1430 return FALSE;
1432 if (tcgetattr(fd, &port) == -1) {
1433 int save_error=errno;
1434 ERR("tcgetattr error '%s'\n", strerror(save_error));
1435 COMM_SetCommError(handle,CE_IOE);
1436 close( fd );
1437 return FALSE;
1439 close( fd );
1440 #ifndef __EMX__
1441 #ifdef CBAUD
1442 speed= (port.c_cflag & CBAUD);
1443 #else
1444 speed= (cfgetospeed(&port));
1445 #endif
1446 switch (speed) {
1447 case B110:
1448 lpdcb->BaudRate = 110;
1449 break;
1450 case B300:
1451 lpdcb->BaudRate = 300;
1452 break;
1453 case B600:
1454 lpdcb->BaudRate = 600;
1455 break;
1456 case B1200:
1457 lpdcb->BaudRate = 1200;
1458 break;
1459 case B2400:
1460 lpdcb->BaudRate = 2400;
1461 break;
1462 case B4800:
1463 lpdcb->BaudRate = 4800;
1464 break;
1465 case B9600:
1466 lpdcb->BaudRate = 9600;
1467 break;
1468 case B19200:
1469 lpdcb->BaudRate = 19200;
1470 break;
1471 case B38400:
1472 lpdcb->BaudRate = 38400;
1473 break;
1474 #ifdef B57600
1475 case B57600:
1476 lpdcb->BaudRate = 57600;
1477 break;
1478 #endif
1479 #ifdef B115200
1480 case B115200:
1481 lpdcb->BaudRate = 115200;
1482 break;
1483 #endif
1484 #ifdef B230400
1485 case B230400:
1486 lpdcb->BaudRate = 230400;
1487 break;
1488 #endif
1489 #ifdef B460800
1490 case B460800:
1491 lpdcb->BaudRate = 460800;
1492 break;
1493 #endif
1494 default:
1495 ERR("unknown speed %x \n",speed);
1497 #endif
1498 switch (port.c_cflag & CSIZE) {
1499 case CS5:
1500 lpdcb->ByteSize = 5;
1501 break;
1502 case CS6:
1503 lpdcb->ByteSize = 6;
1504 break;
1505 case CS7:
1506 lpdcb->ByteSize = 7;
1507 break;
1508 case CS8:
1509 lpdcb->ByteSize = 8;
1510 break;
1511 default:
1512 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1515 if(port.c_iflag & INPCK)
1516 lpdcb->fParity = TRUE;
1517 else
1518 lpdcb->fParity = FALSE;
1519 #ifdef CMSPAR
1520 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1521 #else
1522 switch (port.c_cflag & (PARENB | PARODD))
1523 #endif
1525 case 0:
1526 lpdcb->Parity = NOPARITY;
1527 break;
1528 case PARENB:
1529 lpdcb->Parity = EVENPARITY;
1530 break;
1531 case (PARENB | PARODD):
1532 lpdcb->Parity = ODDPARITY;
1533 break;
1534 #ifdef CMSPAR
1535 case (PARENB | CMSPAR):
1536 lpdcb->Parity = MARKPARITY;
1537 break;
1538 case (PARENB | PARODD | CMSPAR):
1539 lpdcb->Parity = SPACEPARITY;
1540 break;
1541 #endif
1544 if (port.c_cflag & CSTOPB)
1545 if(lpdcb->ByteSize == 5)
1546 lpdcb->StopBits = ONE5STOPBITS;
1547 else
1548 lpdcb->StopBits = TWOSTOPBITS;
1549 else
1550 lpdcb->StopBits = ONESTOPBIT;
1552 lpdcb->fNull = 0;
1553 lpdcb->fBinary = 1;
1555 /* termios does not support DTR/DSR flow control */
1556 lpdcb->fOutxDsrFlow = 0;
1557 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1559 #ifdef CRTSCTS
1561 if (port.c_cflag & CRTSCTS) {
1562 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1563 lpdcb->fOutxCtsFlow = 1;
1564 } else
1565 #endif
1567 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1568 lpdcb->fOutxCtsFlow = 0;
1570 if (port.c_iflag & IXON)
1571 lpdcb->fInX = 1;
1572 else
1573 lpdcb->fInX = 0;
1575 if (port.c_iflag & IXOFF)
1576 lpdcb->fOutX = 1;
1577 else
1578 lpdcb->fOutX = 0;
1580 lpdcb->XonChar =
1581 lpdcb->XoffChar =
1583 lpdcb->XonLim = 10;
1584 lpdcb->XoffLim = 10;
1586 COMM_SetCommError(handle,0);
1588 TRACE("OK\n");
1590 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1591 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1592 (lpdcb->StopBits == ONESTOPBIT)?1:
1593 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1594 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1595 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1596 #ifdef CRTSCTS
1597 if ( lpdcb->fOutxCtsFlow ||
1598 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1600 TRACE("CRTSCTS\n");
1601 else
1603 TRACE("~CRTSCTS\n");
1605 #endif
1606 return TRUE;
1609 /*****************************************************************************
1610 * TransmitCommChar (KERNEL32.@)
1612 * Transmits a single character in front of any pending characters in the
1613 * output buffer. Usually used to send an interrupt character to a host.
1615 * RETURNS
1617 * True if the call succeeded, false if the previous command character to the
1618 * same device has not been sent yet the handle is bad etc.
1620 * BUGS
1622 * Stub.
1624 BOOL WINAPI TransmitCommChar(
1625 HANDLE hComm, /* [in] The communication device in need of a command character. */
1626 CHAR chTransmit) /* [in] The character to transmit. */
1628 BOOL r = FALSE;
1629 int fd;
1631 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1633 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1634 if ( fd < 0 )
1635 SetLastError ( ERROR_INVALID_PARAMETER );
1636 else
1638 r = (1 == write(fd, &chTransmit, 1));
1639 close(fd);
1642 return r;
1646 /*****************************************************************************
1647 * GetCommTimeouts (KERNEL32.@)
1649 * Obtains the request timeout values for the communications device.
1651 * RETURNS
1653 * True on success, false if communications device handle is bad
1654 * or the target structure is null.
1656 BOOL WINAPI GetCommTimeouts(
1657 HANDLE hComm, /* [in] The communications device. */
1658 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1660 BOOL ret;
1662 TRACE("(%p,%p)\n",hComm,lptimeouts);
1664 if(!lptimeouts)
1666 SetLastError(ERROR_INVALID_PARAMETER);
1667 return FALSE;
1670 SERVER_START_REQ( get_serial_info )
1672 req->handle = hComm;
1673 if ((ret = !wine_server_call_err( req )))
1675 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1676 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1677 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1678 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1679 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1682 SERVER_END_REQ;
1683 return ret;
1686 /*****************************************************************************
1687 * SetCommTimeouts (KERNEL32.@)
1689 * Sets the timeouts used when reading and writing data to/from COMM ports.
1691 * ReadIntervalTimeout
1692 * - converted and passes to linux kernel as c_cc[VTIME]
1693 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1694 * - used in ReadFile to calculate GetOverlappedResult's timeout
1695 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1696 * - used in WriteFile to calculate GetOverlappedResult's timeout
1698 * RETURNS
1700 * True if the timeouts were set, false otherwise.
1702 BOOL WINAPI SetCommTimeouts(
1703 HANDLE hComm, /* [in] handle of COMM device */
1704 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1706 BOOL ret;
1707 int fd;
1708 struct termios tios;
1710 TRACE("(%p,%p)\n",hComm,lptimeouts);
1712 if(!lptimeouts)
1714 SetLastError(ERROR_INVALID_PARAMETER);
1715 return FALSE;
1718 SERVER_START_REQ( set_serial_info )
1720 req->handle = hComm;
1721 req->flags = SERIALINFO_SET_TIMEOUTS;
1722 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1723 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1724 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1725 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1726 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1727 ret = !wine_server_call_err( req );
1729 SERVER_END_REQ;
1730 if (!ret) return FALSE;
1732 /* FIXME: move this stuff to the server */
1733 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1734 if (fd < 0) {
1735 FIXME("no fd for handle = %p!.\n",hComm);
1736 return FALSE;
1739 if (-1==tcgetattr(fd,&tios)) {
1740 FIXME("tcgetattr on fd %d failed!\n",fd);
1741 close(fd);
1742 return FALSE;
1745 /* VTIME is in 1/10 seconds */
1747 unsigned int ux_timeout;
1749 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1751 ux_timeout = 0;
1753 else
1755 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1756 if(ux_timeout == 0)
1758 ux_timeout = 1; /* must be at least some timeout */
1761 tios.c_cc[VTIME] = ux_timeout;
1764 if (-1==tcsetattr(fd,0,&tios)) {
1765 FIXME("tcsetattr on fd %d failed!\n",fd);
1766 close(fd);
1767 return FALSE;
1769 close(fd);
1770 return TRUE;
1773 /***********************************************************************
1774 * GetCommModemStatus (KERNEL32.@)
1776 * Obtains the four control register bits if supported by the hardware.
1778 * RETURNS
1780 * True if the communications handle was good and for hardware that
1781 * control register access, false otherwise.
1783 BOOL WINAPI GetCommModemStatus(
1784 HANDLE hFile, /* [in] The communications device. */
1785 LPDWORD lpModemStat) /* [out] The control register bits. */
1787 int fd,mstat, result=FALSE;
1789 *lpModemStat=0;
1790 #ifdef TIOCMGET
1791 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
1792 if(fd<0)
1793 return FALSE;
1794 result = ioctl(fd, TIOCMGET, &mstat);
1795 close(fd);
1796 if (result == -1)
1798 WARN("ioctl failed\n");
1799 return FALSE;
1801 #ifdef TIOCM_CTS
1802 if (mstat & TIOCM_CTS)
1803 *lpModemStat |= MS_CTS_ON;
1804 #endif
1805 #ifdef TIOCM_DSR
1806 if (mstat & TIOCM_DSR)
1807 *lpModemStat |= MS_DSR_ON;
1808 #endif
1809 #ifdef TIOCM_RNG
1810 if (mstat & TIOCM_RNG)
1811 *lpModemStat |= MS_RING_ON;
1812 #endif
1813 #ifdef TIOCM_CAR
1814 /*FIXME: Not really sure about RLSD UB 990810*/
1815 if (mstat & TIOCM_CAR)
1816 *lpModemStat |= MS_RLSD_ON;
1817 #endif
1818 TRACE("%04x -> %s%s%s%s\n", mstat,
1819 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1820 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1821 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1822 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1823 return TRUE;
1824 #else
1825 return FALSE;
1826 #endif
1829 /***********************************************************************
1830 * COMM_WaitCommEventService (INTERNAL)
1832 * This function is called while the client is waiting on the
1833 * server, so we can't make any server calls here.
1835 static void COMM_WaitCommEventService(async_private *ovp)
1837 async_commio *commio = (async_commio*) ovp;
1838 IO_STATUS_BLOCK* iosb = commio->async.iosb;
1840 TRACE("iosb %p\n",iosb);
1842 /* FIXME: detect other events */
1843 *commio->buffer = EV_RXCHAR;
1845 iosb->u.Status = STATUS_SUCCESS;
1849 /***********************************************************************
1850 * COMM_WaitCommEvent (INTERNAL)
1852 * This function must have an lpOverlapped.
1854 static BOOL COMM_WaitCommEvent(
1855 HANDLE hFile, /* [in] handle of comm port to wait for */
1856 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1857 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1859 int fd;
1860 async_commio *ovp;
1862 if(!lpOverlapped)
1864 SetLastError(ERROR_INVALID_PARAMETER);
1865 return FALSE;
1868 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1869 return FALSE;
1871 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
1872 if(fd<0)
1873 return FALSE;
1875 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1876 if(!ovp)
1878 close(fd);
1879 return FALSE;
1882 ovp->async.ops = &commio_async_ops;
1883 ovp->async.handle = hFile;
1884 ovp->async.fd = fd;
1885 ovp->async.type = ASYNC_TYPE_WAIT;
1886 ovp->async.func = COMM_WaitCommEventService;
1887 ovp->async.event = lpOverlapped->hEvent;
1888 ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
1889 ovp->buffer = (char *)lpdwEvents;
1891 lpOverlapped->InternalHigh = 0;
1892 lpOverlapped->Offset = 0;
1893 lpOverlapped->OffsetHigh = 0;
1895 if ( !register_new_async (&ovp->async) )
1896 SetLastError( ERROR_IO_PENDING );
1898 return FALSE;
1901 /***********************************************************************
1902 * WaitCommEvent (KERNEL32.@)
1904 * Wait until something interesting happens on a COMM port.
1905 * Interesting things (events) are set by calling SetCommMask before
1906 * this function is called.
1908 * RETURNS:
1909 * TRUE if successful
1910 * FALSE if failure
1912 * The set of detected events will be written to *lpdwEventMask
1913 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1915 * BUGS:
1916 * Only supports EV_RXCHAR and EV_TXEMPTY
1918 BOOL WINAPI WaitCommEvent(
1919 HANDLE hFile, /* [in] handle of comm port to wait for */
1920 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1921 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1923 OVERLAPPED ov;
1924 int ret;
1926 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1928 if(lpOverlapped)
1929 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1931 /* if there is no overlapped structure, create our own */
1932 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1934 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1936 /* wait for the overlapped to complete */
1937 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1938 CloseHandle(ov.hEvent);
1940 return ret;
1943 /***********************************************************************
1944 * GetCommProperties (KERNEL32.@)
1946 * This function fills in a structure with the capabilities of the
1947 * communications port driver.
1949 * RETURNS
1951 * TRUE on success, FALSE on failure
1952 * If successful, the lpCommProp structure be filled in with
1953 * properties of the comm port.
1955 BOOL WINAPI GetCommProperties(
1956 HANDLE hFile, /* [in] handle of the comm port */
1957 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1959 FIXME("(%p %p )\n",hFile,lpCommProp);
1960 if(!lpCommProp)
1961 return FALSE;
1964 * These values should be valid for LINUX's serial driver
1965 * FIXME: Perhaps they deserve an #ifdef LINUX
1967 memset(lpCommProp,0,sizeof(COMMPROP));
1968 lpCommProp->wPacketLength = 1;
1969 lpCommProp->wPacketVersion = 1;
1970 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1971 lpCommProp->dwReserved1 = 0;
1972 lpCommProp->dwMaxTxQueue = 4096;
1973 lpCommProp->dwMaxRxQueue = 4096;
1974 lpCommProp->dwMaxBaud = BAUD_115200;
1975 lpCommProp->dwProvSubType = PST_RS232;
1976 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1977 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1978 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1979 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1980 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1981 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1982 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1983 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1984 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1985 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1986 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1988 return TRUE;
1991 /***********************************************************************
1992 * FIXME:
1993 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1994 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1995 * This is dependent on the type of COMM port, but since it is doubtful
1996 * anybody will get around to implementing support for fancy serial
1997 * ports in WINE, this is hardcoded for the time being. The name of
1998 * this DLL should be stored in and read from the system registry in
1999 * the hive HKEY_LOCAL_MACHINE, key
2000 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2001 * where ???? is the port number... that is determined by PNP
2002 * The DLL should be loaded when the COMM port is opened, and closed
2003 * when the COMM port is closed. - MJM 20 June 2000
2004 ***********************************************************************/
2005 static CHAR lpszSerialUI[] = "serialui.dll";
2008 /***********************************************************************
2009 * CommConfigDialogA (KERNEL32.@)
2011 * Raises a dialog that allows the user to configure a comm port.
2012 * Fills the COMMCONFIG struct with information specified by the user.
2013 * This function should call a similar routine in the COMM driver...
2015 * RETURNS
2017 * TRUE on success, FALSE on failure
2018 * If successful, the lpCommConfig structure will contain a new
2019 * configuration for the comm port, as specified by the user.
2021 * BUGS
2022 * The library with the CommConfigDialog code is never unloaded.
2023 * Perhaps this should be done when the comm port is closed?
2025 BOOL WINAPI CommConfigDialogA(
2026 LPCSTR lpszDevice, /* [in] name of communications device */
2027 HANDLE hWnd, /* [in] parent window for the dialog */
2028 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2030 FARPROC lpfnCommDialog;
2031 HMODULE hConfigModule;
2032 BOOL r;
2034 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2036 hConfigModule = LoadLibraryA(lpszSerialUI);
2037 if(!hConfigModule)
2038 return FALSE;
2040 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2042 if(!lpfnCommDialog)
2043 return FALSE;
2045 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2047 /* UnloadLibrary(hConfigModule); */
2049 return r;
2052 /***********************************************************************
2053 * CommConfigDialogW (KERNEL32.@)
2055 * see CommConfigDialogA for more info
2057 BOOL WINAPI CommConfigDialogW(
2058 LPCWSTR lpszDevice, /* [in] name of communications device */
2059 HANDLE hWnd, /* [in] parent window for the dialog */
2060 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2062 BOOL r;
2063 LPSTR lpDeviceA;
2065 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2066 if(lpDeviceA)
2067 return FALSE;
2068 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
2069 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2070 return r;
2073 /***********************************************************************
2074 * GetCommConfig (KERNEL32.@)
2076 * Fill in the COMMCONFIG structure for the comm port hFile
2078 * RETURNS
2080 * TRUE on success, FALSE on failure
2081 * If successful, lpCommConfig contains the comm port configuration.
2083 * BUGS
2086 BOOL WINAPI GetCommConfig(
2087 HANDLE hFile, /* [in] The communications device. */
2088 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2089 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2090 afterwards the number of bytes copied to the buffer or
2091 the needed size of the buffer. */
2093 BOOL r;
2095 TRACE("(%p %p)\n",hFile,lpCommConfig);
2097 if(lpCommConfig == NULL)
2098 return FALSE;
2100 r = *lpdwSize < sizeof(COMMCONFIG);
2101 *lpdwSize = sizeof(COMMCONFIG);
2102 if(!r)
2103 return FALSE;
2105 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2106 lpCommConfig->wVersion = 1;
2107 lpCommConfig->wReserved = 0;
2108 r = GetCommState(hFile,&lpCommConfig->dcb);
2109 lpCommConfig->dwProviderSubType = PST_RS232;
2110 lpCommConfig->dwProviderOffset = 0;
2111 lpCommConfig->dwProviderSize = 0;
2113 return r;
2116 /***********************************************************************
2117 * SetCommConfig (KERNEL32.@)
2119 * Sets the configuration of the communications device.
2121 * RETURNS
2123 * True on success, false if the handle was bad is not a communications device.
2125 BOOL WINAPI SetCommConfig(
2126 HANDLE hFile, /* [in] The communications device. */
2127 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2128 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2130 TRACE("(%p %p)\n",hFile,lpCommConfig);
2131 return SetCommState(hFile,&lpCommConfig->dcb);
2134 /***********************************************************************
2135 * SetDefaultCommConfigA (KERNEL32.@)
2137 * Initializes the default configuration for the specified communication
2138 * device. (ascii)
2140 * RETURNS
2142 * True if the device was found and the defaults set, false otherwise
2144 BOOL WINAPI SetDefaultCommConfigA(
2145 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2146 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2147 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2149 FARPROC lpfnSetDefaultCommConfig;
2150 HMODULE hConfigModule;
2151 BOOL r;
2153 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2155 hConfigModule = LoadLibraryA(lpszSerialUI);
2156 if(!hConfigModule)
2157 return FALSE;
2159 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
2161 if(! lpfnSetDefaultCommConfig)
2162 return TRUE;
2164 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2166 /* UnloadLibrary(hConfigModule); */
2168 return r;
2172 /***********************************************************************
2173 * SetDefaultCommConfigW (KERNEL32.@)
2175 * Initializes the default configuration for the specified
2176 * communication device. (unicode)
2178 * RETURNS
2181 BOOL WINAPI SetDefaultCommConfigW(
2182 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2183 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2184 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2186 BOOL r;
2187 LPSTR lpDeviceA;
2189 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2191 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2192 if(lpDeviceA)
2193 return FALSE;
2194 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2195 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2196 return r;
2200 /***********************************************************************
2201 * GetDefaultCommConfigA (KERNEL32.@)
2203 * Acquires the default configuration of the specified communication device. (unicode)
2205 * RETURNS
2207 * True on successful reading of the default configuration,
2208 * if the device is not found or the buffer is too small.
2210 BOOL WINAPI GetDefaultCommConfigA(
2211 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2212 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2213 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2214 afterwards the number of bytes copied to the buffer or
2215 the needed size of the buffer. */
2217 LPDCB lpdcb = &(lpCC->dcb);
2218 char temp[40];
2220 if (strncasecmp(lpszName,"COM",3)) {
2221 ERR("not implemented for <%s>\n", lpszName);
2222 return FALSE;
2225 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2226 if (*lpdwSize < sizeof(COMMCONFIG)) {
2227 *lpdwSize = sizeof(COMMCONFIG);
2228 return FALSE;
2231 *lpdwSize = sizeof(COMMCONFIG);
2233 lpCC->dwSize = sizeof(COMMCONFIG);
2234 lpCC->wVersion = 1;
2235 lpCC->dwProviderSubType = PST_RS232;
2236 lpCC->dwProviderOffset = 0L;
2237 lpCC->dwProviderSize = 0L;
2239 sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2240 FIXME("setting %s as default\n", temp);
2242 return BuildCommDCBA( temp, lpdcb);
2245 /**************************************************************************
2246 * GetDefaultCommConfigW (KERNEL32.@)
2248 * Acquires the default configuration of the specified communication device. (unicode)
2250 * RETURNS
2252 * True on successful reading of the default configuration,
2253 * if the device is not found or the buffer is too small.
2255 BOOL WINAPI GetDefaultCommConfigW(
2256 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2257 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2258 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2259 afterwards the number of bytes copied to the buffer or
2260 the needed size of the buffer. */
2262 BOOL ret = FALSE;
2263 LPSTR lpszNameA;
2265 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2266 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2267 if (lpszNameA)
2269 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2270 HeapFree( GetProcessHeap(), 0, lpszNameA );
2272 return ret;