Use Interlocked* functions in AddRef and Release.
[wine.git] / dlls / kernel / comm.c
blob0eee0b0b3b6fe47ab594679349af9cbc605517b4
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 "heap.h"
98 #include "wine/unicode.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 /* retrieve the Unix handle corresponding to a comm handle */
109 static int get_comm_fd( HANDLE handle, DWORD access )
111 int fd, ret;
113 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
114 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
115 return fd;
118 /* release the Unix handle returned by get_comm_fd */
119 static inline void release_comm_fd( HANDLE handle, int fd )
121 wine_server_release_fd( handle, fd );
125 /***********************************************************************
126 * Asynchronous I/O for asynchronous wait requests *
129 static DWORD commio_get_async_count (const async_private *ovp);
130 static void commio_async_cleanup (async_private *ovp);
132 static async_ops commio_async_ops =
134 commio_get_async_count, /* get_count */
135 NULL, /* call_completion */
136 commio_async_cleanup /* cleanup */
139 typedef struct async_commio
141 struct async_private async;
142 char *buffer;
143 } async_commio;
145 static DWORD commio_get_async_count (const struct async_private *ovp)
147 return 0;
150 static void commio_async_cleanup (async_private *ovp)
152 HeapFree(GetProcessHeap(), 0, ovp );
155 /***********************************************************************/
157 #if !defined(TIOCINQ) && defined(FIONREAD)
158 #define TIOCINQ FIONREAD
159 #endif
161 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
163 #ifdef TIOCMGET
164 unsigned int mstat, okay;
165 okay = ioctl(fd, TIOCMGET, &mstat);
166 if (okay) return okay;
167 if (andy) mstat &= andy;
168 mstat |= orrie;
169 return ioctl(fd, TIOCMSET, &mstat);
170 #else
171 return 0;
172 #endif
175 /***********************************************************************
176 * COMM_Parse* (Internal)
178 * The following COMM_Parse* functions are used by the BuildCommDCB
179 * functions to help parse the various parts of the device control string.
181 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
183 static const WCHAR comW[] = {'C','O','M',0};
185 /* The device control string may optionally start with "COMx" followed
186 by an optional ':' and spaces. */
187 if(!strncmpiW(ptr, comW, 3))
189 ptr += 3;
191 /* Allow any com port above 0 as Win 9x does (NT only allows
192 values for com ports which are actually present) */
193 if(*ptr < '1' || *ptr > '9')
194 return NULL;
196 /* Advance pointer past port number */
197 while(*ptr >= '0' && *ptr <= '9') ptr++;
199 /* The com port number must be followed by a ':' or ' ' */
200 if(*ptr != ':' && *ptr != ' ')
201 return NULL;
203 /* Advance pointer to beginning of next parameter */
204 while(*ptr == ' ') ptr++;
205 if(*ptr == ':')
207 ptr++;
208 while(*ptr == ' ') ptr++;
211 /* The device control string must not start with a space. */
212 else if(*ptr == ' ')
213 return NULL;
215 return ptr;
218 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
220 if(*ptr < '0' || *ptr > '9') return NULL;
221 *lpnumber = strtoulW(ptr, NULL, 10);
222 while(*ptr >= '0' && *ptr <= '9') ptr++;
223 return ptr;
226 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
228 /* Contrary to what you might expect, Windows only sets the Parity
229 member of DCB and not fParity even when parity is specified in the
230 device control string */
232 switch(toupperW(*ptr++))
234 case 'E':
235 *lpparity = EVENPARITY;
236 break;
237 case 'M':
238 *lpparity = MARKPARITY;
239 break;
240 case 'N':
241 *lpparity = NOPARITY;
242 break;
243 case 'O':
244 *lpparity = ODDPARITY;
245 break;
246 case 'S':
247 *lpparity = SPACEPARITY;
248 break;
249 default:
250 return NULL;
253 return ptr;
256 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
258 DWORD temp;
260 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
261 return NULL;
263 if(temp >= 5 && temp <= 8)
265 *lpbytesize = temp;
266 return ptr;
268 else
269 return NULL;
272 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
274 DWORD temp;
275 static const WCHAR stopbits15W[] = {'1','.','5',0};
277 if(!strncmpW(stopbits15W, ptr, 3))
279 ptr += 3;
280 *lpstopbits = ONE5STOPBITS;
282 else
284 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
285 return NULL;
287 if(temp == 1)
288 *lpstopbits = ONESTOPBIT;
289 else if(temp == 2)
290 *lpstopbits = TWOSTOPBITS;
291 else
292 return NULL;
295 return ptr;
298 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
300 static const WCHAR onW[] = {'o','n',0};
301 static const WCHAR offW[] = {'o','f','f',0};
303 if(!strncmpiW(onW, ptr, 2))
305 ptr += 2;
306 *lponoff = 1;
308 else if(!strncmpiW(offW, ptr, 3))
310 ptr += 3;
311 *lponoff = 0;
313 else
314 return NULL;
316 return ptr;
319 /***********************************************************************
320 * COMM_BuildOldCommDCB (Internal)
322 * Build a DCB using the old style settings string eg: "96,n,8,1"
324 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
326 WCHAR last = 0;
328 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
329 return FALSE;
331 switch(lpdcb->BaudRate)
333 case 11:
334 case 30:
335 case 60:
336 lpdcb->BaudRate *= 10;
337 break;
338 case 12:
339 case 24:
340 case 48:
341 case 96:
342 lpdcb->BaudRate *= 100;
343 break;
344 case 19:
345 lpdcb->BaudRate = 19200;
346 break;
349 while(*device == ' ') device++;
350 if(*device++ != ',') return FALSE;
351 while(*device == ' ') device++;
353 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
354 return FALSE;
356 while(*device == ' ') device++;
357 if(*device++ != ',') return FALSE;
358 while(*device == ' ') device++;
360 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
361 return FALSE;
363 while(*device == ' ') device++;
364 if(*device++ != ',') return FALSE;
365 while(*device == ' ') device++;
367 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
368 return FALSE;
370 /* The last parameter for flow control is optional. */
371 while(*device == ' ') device++;
372 if(*device == ',')
374 device++;
375 while(*device == ' ') device++;
376 if(*device) last = toupperW(*device++);
377 while(*device == ' ') device++;
380 /* Win NT sets the flow control members based on (or lack of) the last
381 parameter. Win 9x does not set these members. */
382 switch(last)
384 case 0:
385 lpdcb->fInX = FALSE;
386 lpdcb->fOutX = FALSE;
387 lpdcb->fOutxCtsFlow = FALSE;
388 lpdcb->fOutxDsrFlow = FALSE;
389 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
390 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
391 break;
392 case 'X':
393 lpdcb->fInX = TRUE;
394 lpdcb->fOutX = TRUE;
395 lpdcb->fOutxCtsFlow = FALSE;
396 lpdcb->fOutxDsrFlow = FALSE;
397 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
398 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
399 break;
400 case 'P':
401 lpdcb->fInX = FALSE;
402 lpdcb->fOutX = FALSE;
403 lpdcb->fOutxCtsFlow = TRUE;
404 lpdcb->fOutxDsrFlow = TRUE;
405 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
406 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
407 break;
408 default:
409 return FALSE;
412 /* This should be the end of the string. */
413 if(*device) return FALSE;
415 return TRUE;
418 /***********************************************************************
419 * COMM_BuildNewCommDCB (Internal)
421 * Build a DCB using the new style settings string.
422 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
424 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
426 DWORD temp;
427 BOOL baud = FALSE, stop = FALSE;
428 static const WCHAR baudW[] = {'b','a','u','d','=',0};
429 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
430 static const WCHAR dataW[] = {'d','a','t','a','=',0};
431 static const WCHAR stopW[] = {'s','t','o','p','=',0};
432 static const WCHAR toW[] = {'t','o','=',0};
433 static const WCHAR xonW[] = {'x','o','n','=',0};
434 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
435 static const WCHAR octsW[] = {'o','c','t','s','=',0};
436 static const WCHAR dtrW[] = {'d','t','r','=',0};
437 static const WCHAR rtsW[] = {'r','t','s','=',0};
438 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
440 while(*device)
442 while(*device == ' ') device++;
444 if(!strncmpiW(baudW, device, 5))
446 baud = TRUE;
448 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
449 return FALSE;
451 else if(!strncmpiW(parityW, device, 7))
453 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
454 return FALSE;
456 else if(!strncmpiW(dataW, device, 5))
458 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
459 return FALSE;
461 else if(!strncmpiW(stopW, device, 5))
463 stop = TRUE;
465 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
466 return FALSE;
468 else if(!strncmpiW(toW, device, 3))
470 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
471 return FALSE;
473 lptimeouts->ReadIntervalTimeout = 0;
474 lptimeouts->ReadTotalTimeoutMultiplier = 0;
475 lptimeouts->ReadTotalTimeoutConstant = 0;
476 lptimeouts->WriteTotalTimeoutMultiplier = 0;
477 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
479 else if(!strncmpiW(xonW, device, 4))
481 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
482 return FALSE;
484 lpdcb->fOutX = temp;
485 lpdcb->fInX = temp;
487 else if(!strncmpiW(odsrW, device, 5))
489 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
490 return FALSE;
492 lpdcb->fOutxDsrFlow = temp;
494 else if(!strncmpiW(octsW, device, 5))
496 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
497 return FALSE;
499 lpdcb->fOutxCtsFlow = temp;
501 else if(!strncmpiW(dtrW, device, 4))
503 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
504 return FALSE;
506 lpdcb->fDtrControl = temp;
508 else if(!strncmpiW(rtsW, device, 4))
510 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
511 return FALSE;
513 lpdcb->fRtsControl = temp;
515 else if(!strncmpiW(idsrW, device, 5))
517 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
518 return FALSE;
520 /* Win NT sets the fDsrSensitivity member based on the
521 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
522 lpdcb->fDsrSensitivity = temp;
524 else
525 return FALSE;
527 /* After the above parsing, the next character (if not the end of
528 the string) should be a space */
529 if(*device && *device != ' ')
530 return FALSE;
533 /* If stop bits were not specified, a default is always supplied. */
534 if(!stop)
536 if(baud && lpdcb->BaudRate == 110)
537 lpdcb->StopBits = TWOSTOPBITS;
538 else
539 lpdcb->StopBits = ONESTOPBIT;
542 return TRUE;
545 /**************************************************************************
546 * BuildCommDCBA (KERNEL32.@)
548 * Updates a device control block data structure with values from an
549 * ascii device control string. The device control string has two forms
550 * normal and extended, it must be exclusively in one or the other form.
552 * RETURNS
554 * True on success, false on a malformed control string.
556 BOOL WINAPI BuildCommDCBA(
557 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
558 LPDCB lpdcb) /* [out] The device control block to be updated. */
560 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
563 /**************************************************************************
564 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
566 * Updates a device control block data structure with values from an
567 * ascii device control string. Taking timeout values from a timeouts
568 * struct if desired by the control string.
570 * RETURNS
572 * True on success, false bad handles etc.
574 BOOL WINAPI BuildCommDCBAndTimeoutsA(
575 LPCSTR device, /* [in] The ascii device control string. */
576 LPDCB lpdcb, /* [out] The device control block to be updated. */
577 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
579 BOOL ret = FALSE;
580 UNICODE_STRING deviceW;
582 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
583 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
584 else deviceW.Buffer = NULL;
586 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
588 RtlFreeUnicodeString(&deviceW);
589 return ret;
592 /**************************************************************************
593 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
595 * Updates a device control block data structure with values from a
596 * unicode device control string. Taking timeout values from a timeouts
597 * struct if desired by the control string.
599 * RETURNS
601 * True on success, false bad handles etc
603 BOOL WINAPI BuildCommDCBAndTimeoutsW(
604 LPCWSTR devid, /* [in] The unicode device control string. */
605 LPDCB lpdcb, /* [out] The device control block to be updated. */
606 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
608 DCB dcb;
609 COMMTIMEOUTS timeouts;
610 BOOL result;
611 LPCWSTR ptr = devid;
613 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
615 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
616 lpdcb->DCBlength = sizeof(DCB);
618 /* Make a copy of the original data structures to work with since if
619 if there is an error in the device control string the originals
620 should not be modified (except possibly DCBlength) */
621 memcpy(&dcb, lpdcb, sizeof(DCB));
622 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
624 ptr = COMM_ParseStart(ptr);
626 if(ptr == NULL)
627 result = FALSE;
628 else if(strchrW(ptr, ','))
629 result = COMM_BuildOldCommDCB(ptr, &dcb);
630 else
631 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
633 if(result)
635 memcpy(lpdcb, &dcb, sizeof(DCB));
636 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
637 return TRUE;
639 else
641 WARN("Invalid device control string: %s\n", debugstr_w(devid));
642 SetLastError(ERROR_INVALID_PARAMETER);
643 return FALSE;
647 /**************************************************************************
648 * BuildCommDCBW (KERNEL32.@)
650 * Updates a device control block structure with values from an
651 * unicode device control string. The device control string has two forms
652 * normal and extended, it must be exclusively in one or the other form.
654 * RETURNS
656 * True on success, false on an malformed control string.
658 BOOL WINAPI BuildCommDCBW(
659 LPCWSTR devid, /* [in] The unicode device control string. */
660 LPDCB lpdcb) /* [out] The device control block to be updated. */
662 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
665 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
667 DWORD ret;
669 SERVER_START_REQ( set_serial_info )
671 req->handle = handle;
672 req->flags = SERIALINFO_SET_ERROR;
673 req->commerror = error;
674 ret = !wine_server_call_err( req );
676 SERVER_END_REQ;
677 return ret;
680 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
682 DWORD ret;
684 if(!lperror)
685 return FALSE;
687 SERVER_START_REQ( get_serial_info )
689 req->handle = handle;
690 ret = !wine_server_call_err( req );
691 *lperror = reply->commerror;
693 SERVER_END_REQ;
695 return ret;
698 /*****************************************************************************
699 * SetCommBreak (KERNEL32.@)
701 * Halts the transmission of characters to a communications device.
703 * RETURNS
705 * True on success, and false if the communications device could not be found,
706 * the control is not supported.
708 * BUGS
710 * Only TIOCSBRK and TIOCCBRK are supported.
712 BOOL WINAPI SetCommBreak(
713 HANDLE handle) /* [in] The communictions device to suspend. */
715 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
716 int fd,result;
718 fd = get_comm_fd( handle, GENERIC_READ );
719 if(fd<0) return FALSE;
720 result = ioctl(fd,TIOCSBRK,0);
721 release_comm_fd( handle, fd );
722 if (result ==-1)
724 TRACE("ioctl failed\n");
725 SetLastError(ERROR_NOT_SUPPORTED);
726 return FALSE;
728 return TRUE;
729 #else
730 FIXME("ioctl not available\n");
731 SetLastError(ERROR_NOT_SUPPORTED);
732 return FALSE;
733 #endif
736 /*****************************************************************************
737 * ClearCommBreak (KERNEL32.@)
739 * Resumes character transmission from a communication device.
741 * RETURNS
743 * True on success and false if the communications device could not be found.
745 * BUGS
747 * Only TIOCSBRK and TIOCCBRK are supported.
749 BOOL WINAPI ClearCommBreak(
750 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
752 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
753 int fd,result;
755 fd = get_comm_fd( handle, GENERIC_READ );
756 if(fd<0) return FALSE;
757 result = ioctl(fd,TIOCCBRK,0);
758 release_comm_fd( handle, fd );
759 if (result ==-1)
761 TRACE("ioctl failed\n");
762 SetLastError(ERROR_NOT_SUPPORTED);
763 return FALSE;
765 return TRUE;
766 #else
767 FIXME("ioctl not available\n");
768 SetLastError(ERROR_NOT_SUPPORTED);
769 return FALSE;
770 #endif
773 /*****************************************************************************
774 * EscapeCommFunction (KERNEL32.@)
776 * Directs a communication device to perform an extended function.
778 * RETURNS
780 * True or requested data on successful completion of the command,
781 * false if the device is not present cannot execute the command
782 * or the command failed.
784 BOOL WINAPI EscapeCommFunction(
785 HANDLE handle, /* [in] The communication device to perform the extended function. */
786 UINT nFunction) /* [in] The extended function to be performed. */
788 int fd,direct=FALSE,result=FALSE;
789 struct termios port;
791 TRACE("handle %p, function=%d\n", handle, nFunction);
792 fd = get_comm_fd( handle, GENERIC_READ );
793 if(fd<0) return FALSE;
795 if (tcgetattr(fd,&port) == -1) {
796 COMM_SetCommError(handle,CE_IOE);
797 release_comm_fd( handle, fd );
798 return FALSE;
801 switch (nFunction) {
802 case RESETDEV:
803 TRACE("\n");
804 break;
806 case CLRDTR:
807 TRACE("CLRDTR\n");
808 #ifdef TIOCM_DTR
809 direct=TRUE;
810 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
811 break;
812 #endif
814 case CLRRTS:
815 TRACE("CLRRTS\n");
816 #ifdef TIOCM_RTS
817 direct=TRUE;
818 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
819 break;
820 #endif
822 case SETDTR:
823 TRACE("SETDTR\n");
824 #ifdef TIOCM_DTR
825 direct=TRUE;
826 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
827 break;
828 #endif
830 case SETRTS:
831 TRACE("SETRTS\n");
832 #ifdef TIOCM_RTS
833 direct=TRUE;
834 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
835 break;
836 #endif
838 case SETXOFF:
839 TRACE("SETXOFF\n");
840 port.c_iflag |= IXOFF;
841 break;
843 case SETXON:
844 TRACE("SETXON\n");
845 port.c_iflag |= IXON;
846 break;
847 case SETBREAK:
848 TRACE("setbreak\n");
849 #ifdef TIOCSBRK
850 direct=TRUE;
851 result = ioctl(fd,TIOCSBRK,0);
852 break;
853 #endif
854 case CLRBREAK:
855 TRACE("clrbreak\n");
856 #ifdef TIOCSBRK
857 direct=TRUE;
858 result = ioctl(fd,TIOCCBRK,0);
859 break;
860 #endif
861 default:
862 WARN("(handle=%p,nFunction=%d): Unknown function\n",
863 handle, nFunction);
864 break;
867 if (!direct)
868 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
869 release_comm_fd( handle, fd );
870 COMM_SetCommError(handle,CE_IOE);
871 return FALSE;
872 } else
873 result= TRUE;
874 else
876 if (result == -1)
878 result= FALSE;
879 COMM_SetCommError(handle,CE_IOE);
881 else
882 result = TRUE;
884 release_comm_fd( handle, fd );
885 return result;
888 /********************************************************************
889 * PurgeComm (KERNEL32.@)
891 * Terminates pending operations and/or discards buffers on a
892 * communication resource.
894 * RETURNS
896 * True on success and false if the communications handle is bad.
898 BOOL WINAPI PurgeComm(
899 HANDLE handle, /* [in] The communication resource to be purged. */
900 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
902 int fd;
904 TRACE("handle %p, flags %lx\n", handle, flags);
906 fd = get_comm_fd( handle, GENERIC_READ );
907 if(fd<0) return FALSE;
910 ** not exactly sure how these are different
911 ** Perhaps if we had our own internal queues, one flushes them
912 ** and the other flushes the kernel's buffers.
914 if(flags&PURGE_TXABORT)
915 tcflush(fd,TCOFLUSH);
916 if(flags&PURGE_RXABORT)
917 tcflush(fd,TCIFLUSH);
918 if(flags&PURGE_TXCLEAR)
919 tcflush(fd,TCOFLUSH);
920 if(flags&PURGE_RXCLEAR)
921 tcflush(fd,TCIFLUSH);
922 release_comm_fd( handle, fd );
924 return 1;
927 /*****************************************************************************
928 * ClearCommError (KERNEL32.@)
930 * Enables further I/O operations on a communications resource after
931 * supplying error and current status information.
933 * RETURNS
935 * True on success, false if the communication resource handle is bad.
937 BOOL WINAPI ClearCommError(
938 HANDLE handle, /* [in] The communication resource with the error. */
939 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
940 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
942 int fd;
944 fd=get_comm_fd( handle, GENERIC_READ );
945 if(0>fd) return FALSE;
947 if (lpStat)
949 lpStat->fCtsHold = 0;
950 lpStat->fDsrHold = 0;
951 lpStat->fRlsdHold = 0;
952 lpStat->fXoffHold = 0;
953 lpStat->fXoffSent = 0;
954 lpStat->fEof = 0;
955 lpStat->fTxim = 0;
956 lpStat->fReserved = 0;
958 #ifdef TIOCOUTQ
959 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
960 WARN("ioctl returned error\n");
961 #else
962 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
963 #endif
965 #ifdef TIOCINQ
966 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
967 WARN("ioctl returned error\n");
968 #endif
970 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
971 handle, lpStat->cbInQue, lpStat->cbOutQue);
974 release_comm_fd( handle, fd );
976 COMM_GetCommError(handle, errors);
977 COMM_SetCommError(handle, 0);
979 return TRUE;
982 /*****************************************************************************
983 * SetupComm (KERNEL32.@)
985 * Called after CreateFile to hint to the communication resource to use
986 * specified sizes for input and output buffers rather than the default values.
988 * RETURNS
990 * True if successful, false if the communications resource handle is bad.
992 * BUGS
994 * Stub.
996 BOOL WINAPI SetupComm(
997 HANDLE handle, /* [in] The just created communication resource handle. */
998 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
999 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
1001 int fd;
1003 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1004 fd=get_comm_fd( handle, GENERIC_READ );
1005 if(0>fd) return FALSE;
1006 release_comm_fd( handle, fd );
1007 return TRUE;
1010 /*****************************************************************************
1011 * GetCommMask (KERNEL32.@)
1013 * Obtain the events associated with a communication device that will cause
1014 * a call WaitCommEvent to return.
1016 * RETURNS
1018 * True on success, fail on bad device handle etc.
1020 BOOL WINAPI GetCommMask(
1021 HANDLE handle, /* [in] The communications device. */
1022 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1024 BOOL ret;
1026 TRACE("handle %p, mask %p\n", handle, evtmask);
1028 SERVER_START_REQ( get_serial_info )
1030 req->handle = handle;
1031 if ((ret = !wine_server_call_err( req )))
1033 if (evtmask) *evtmask = reply->eventmask;
1036 SERVER_END_REQ;
1037 return ret;
1040 /*****************************************************************************
1041 * SetCommMask (KERNEL32.@)
1043 * There be some things we need to hear about yon there communications device.
1044 * (Set which events associated with a communication device should cause
1045 * a call WaitCommEvent to return.)
1047 * RETURNS
1049 * True on success, false on bad handle etc.
1051 BOOL WINAPI SetCommMask(
1052 HANDLE handle, /* [in] The communications device. */
1053 DWORD evtmask) /* [in] The events that are to be monitored. */
1055 BOOL ret;
1057 TRACE("handle %p, mask %lx\n", handle, evtmask);
1059 SERVER_START_REQ( set_serial_info )
1061 req->handle = handle;
1062 req->flags = SERIALINFO_SET_MASK;
1063 req->eventmask = evtmask;
1064 ret = !wine_server_call_err( req );
1066 SERVER_END_REQ;
1067 return ret;
1070 /*****************************************************************************
1071 * SetCommState (KERNEL32.@)
1073 * Re-initializes all hardware and control settings of a communications device,
1074 * with values from a device control block without effecting the input and output
1075 * queues.
1077 * RETURNS
1079 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1081 BOOL WINAPI SetCommState(
1082 HANDLE handle, /* [in] The communications device. */
1083 LPDCB lpdcb) /* [out] The device control block. */
1085 struct termios port;
1086 int fd, bytesize, stopbits;
1087 BOOL ret;
1089 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1090 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1091 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1092 (lpdcb->StopBits == ONESTOPBIT)?1:
1093 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1094 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1095 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1096 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1097 lpdcb->fRtsControl);
1098 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1099 lpdcb->fDtrControl);
1102 fd = get_comm_fd( handle, GENERIC_READ );
1103 if (fd < 0) return FALSE;
1105 if ((tcgetattr(fd,&port)) == -1) {
1106 int save_error = errno;
1107 COMM_SetCommError(handle,CE_IOE);
1108 release_comm_fd( handle, fd );
1109 ERR("tcgetattr error '%s'\n", strerror(save_error));
1110 return FALSE;
1113 port.c_cc[VMIN] = 0;
1114 port.c_cc[VTIME] = 1;
1116 #ifdef IMAXBEL
1117 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1118 #else
1119 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1120 #endif
1121 port.c_iflag |= (IGNBRK);
1123 port.c_oflag &= ~(OPOST);
1125 port.c_cflag &= ~(HUPCL);
1126 port.c_cflag |= CLOCAL | CREAD;
1128 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1129 port.c_lflag |= NOFLSH;
1131 #ifdef CBAUD
1132 port.c_cflag &= ~CBAUD;
1133 switch (lpdcb->BaudRate) {
1134 case 0:
1135 port.c_cflag |= B0;
1136 break;
1137 case 50:
1138 port.c_cflag |= B50;
1139 break;
1140 case 75:
1141 port.c_cflag |= B75;
1142 break;
1143 case 110:
1144 case CBR_110:
1145 port.c_cflag |= B110;
1146 break;
1147 case 134:
1148 port.c_cflag |= B134;
1149 break;
1150 case 150:
1151 port.c_cflag |= B150;
1152 break;
1153 case 200:
1154 port.c_cflag |= B200;
1155 break;
1156 case 300:
1157 case CBR_300:
1158 port.c_cflag |= B300;
1159 break;
1160 case 600:
1161 case CBR_600:
1162 port.c_cflag |= B600;
1163 break;
1164 case 1200:
1165 case CBR_1200:
1166 port.c_cflag |= B1200;
1167 break;
1168 case 1800:
1169 port.c_cflag |= B1800;
1170 break;
1171 case 2400:
1172 case CBR_2400:
1173 port.c_cflag |= B2400;
1174 break;
1175 case 4800:
1176 case CBR_4800:
1177 port.c_cflag |= B4800;
1178 break;
1179 case 9600:
1180 case CBR_9600:
1181 port.c_cflag |= B9600;
1182 break;
1183 case 19200:
1184 case CBR_19200:
1185 port.c_cflag |= B19200;
1186 break;
1187 case 38400:
1188 case CBR_38400:
1189 port.c_cflag |= B38400;
1190 break;
1191 #ifdef B57600
1192 case 57600:
1193 port.c_cflag |= B57600;
1194 break;
1195 #endif
1196 #ifdef B115200
1197 case 115200:
1198 port.c_cflag |= B115200;
1199 break;
1200 #endif
1201 #ifdef B230400
1202 case 230400:
1203 port.c_cflag |= B230400;
1204 break;
1205 #endif
1206 #ifdef B460800
1207 case 460800:
1208 port.c_cflag |= B460800;
1209 break;
1210 #endif
1211 default:
1212 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1213 { struct serial_struct nuts;
1214 int arby;
1215 ioctl(fd, TIOCGSERIAL, &nuts);
1216 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1217 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1218 arby = nuts.baud_base / nuts.custom_divisor;
1219 nuts.flags &= ~ASYNC_SPD_MASK;
1220 nuts.flags |= ASYNC_SPD_CUST;
1221 WARN("You (or a program acting at your behest) have specified\n"
1222 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1223 "which is as close as we can get by our present understanding of your\n"
1224 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1225 "has caused to your linux system can be undone with setserial \n"
1226 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1227 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1228 ioctl(fd, TIOCSSERIAL, &nuts);
1229 port.c_cflag |= B38400;
1231 break;
1232 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1235 COMM_SetCommError(handle,IE_BAUDRATE);
1236 release_comm_fd( handle, fd );
1237 ERR("baudrate %ld\n",lpdcb->BaudRate);
1238 return FALSE;
1240 #elif !defined(__EMX__)
1241 switch (lpdcb->BaudRate) {
1242 case 0:
1243 port.c_ospeed = B0;
1244 break;
1245 case 50:
1246 port.c_ospeed = B50;
1247 break;
1248 case 75:
1249 port.c_ospeed = B75;
1250 break;
1251 case 110:
1252 case CBR_110:
1253 port.c_ospeed = B110;
1254 break;
1255 case 134:
1256 port.c_ospeed = B134;
1257 break;
1258 case 150:
1259 port.c_ospeed = B150;
1260 break;
1261 case 200:
1262 port.c_ospeed = B200;
1263 break;
1264 case 300:
1265 case CBR_300:
1266 port.c_ospeed = B300;
1267 break;
1268 case 600:
1269 case CBR_600:
1270 port.c_ospeed = B600;
1271 break;
1272 case 1200:
1273 case CBR_1200:
1274 port.c_ospeed = B1200;
1275 break;
1276 case 1800:
1277 port.c_ospeed = B1800;
1278 break;
1279 case 2400:
1280 case CBR_2400:
1281 port.c_ospeed = B2400;
1282 break;
1283 case 4800:
1284 case CBR_4800:
1285 port.c_ospeed = B4800;
1286 break;
1287 case 9600:
1288 case CBR_9600:
1289 port.c_ospeed = B9600;
1290 break;
1291 case 19200:
1292 case CBR_19200:
1293 port.c_ospeed = B19200;
1294 break;
1295 case 38400:
1296 case CBR_38400:
1297 port.c_ospeed = B38400;
1298 break;
1299 #ifdef B57600
1300 case 57600:
1301 case CBR_57600:
1302 port.c_cflag |= B57600;
1303 break;
1304 #endif
1305 #ifdef B115200
1306 case 115200:
1307 case CBR_115200:
1308 port.c_cflag |= B115200;
1309 break;
1310 #endif
1311 #ifdef B230400
1312 case 230400:
1313 port.c_cflag |= B230400;
1314 break;
1315 #endif
1316 #ifdef B460800
1317 case 460800:
1318 port.c_cflag |= B460800;
1319 break;
1320 #endif
1321 default:
1322 COMM_SetCommError(handle,IE_BAUDRATE);
1323 release_comm_fd( handle, fd );
1324 ERR("baudrate %ld\n",lpdcb->BaudRate);
1325 return FALSE;
1327 port.c_ispeed = port.c_ospeed;
1328 #endif
1329 bytesize=lpdcb->ByteSize;
1330 stopbits=lpdcb->StopBits;
1332 #ifdef CMSPAR
1333 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1334 #else
1335 port.c_cflag &= ~(PARENB | PARODD);
1336 #endif
1337 if (lpdcb->fParity)
1338 port.c_iflag |= INPCK;
1339 else
1340 port.c_iflag &= ~INPCK;
1341 switch (lpdcb->Parity) {
1342 case NOPARITY:
1343 break;
1344 case ODDPARITY:
1345 port.c_cflag |= (PARENB | PARODD);
1346 break;
1347 case EVENPARITY:
1348 port.c_cflag |= PARENB;
1349 break;
1350 #ifdef CMSPAR
1351 /* Linux defines mark/space (stick) parity */
1352 case MARKPARITY:
1353 port.c_cflag |= (PARENB | CMSPAR);
1354 break;
1355 case SPACEPARITY:
1356 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1357 break;
1358 #else
1359 /* try the POSIX way */
1360 case MARKPARITY:
1361 if( stopbits == ONESTOPBIT) {
1362 stopbits = TWOSTOPBITS;
1363 port.c_iflag &= ~INPCK;
1364 } else {
1365 COMM_SetCommError(handle,IE_BYTESIZE);
1366 release_comm_fd( handle, fd );
1367 ERR("Cannot set MARK Parity\n");
1368 return FALSE;
1370 break;
1371 case SPACEPARITY:
1372 if( bytesize < 8) {
1373 bytesize +=1;
1374 port.c_iflag &= ~INPCK;
1375 } else {
1376 COMM_SetCommError(handle,IE_BYTESIZE);
1377 release_comm_fd( handle, fd );
1378 ERR("Cannot set SPACE Parity\n");
1379 return FALSE;
1381 break;
1382 #endif
1383 default:
1384 COMM_SetCommError(handle,IE_BYTESIZE);
1385 release_comm_fd( handle, fd );
1386 ERR("Parity\n");
1387 return FALSE;
1391 port.c_cflag &= ~CSIZE;
1392 switch (bytesize) {
1393 case 5:
1394 port.c_cflag |= CS5;
1395 break;
1396 case 6:
1397 port.c_cflag |= CS6;
1398 break;
1399 case 7:
1400 port.c_cflag |= CS7;
1401 break;
1402 case 8:
1403 port.c_cflag |= CS8;
1404 break;
1405 default:
1406 COMM_SetCommError(handle,IE_BYTESIZE);
1407 release_comm_fd( handle, fd );
1408 ERR("ByteSize\n");
1409 return FALSE;
1412 switch (stopbits) {
1413 case ONESTOPBIT:
1414 port.c_cflag &= ~CSTOPB;
1415 break;
1416 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1417 case TWOSTOPBITS:
1418 port.c_cflag |= CSTOPB;
1419 break;
1420 default:
1421 COMM_SetCommError(handle,IE_BYTESIZE);
1422 release_comm_fd( handle, fd );
1423 ERR("StopBits\n");
1424 return FALSE;
1426 #ifdef CRTSCTS
1427 if ( lpdcb->fOutxCtsFlow ||
1428 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1431 port.c_cflag |= CRTSCTS;
1432 TRACE("CRTSCTS\n");
1434 #endif
1436 if (lpdcb->fInX)
1437 port.c_iflag |= IXON;
1438 else
1439 port.c_iflag &= ~IXON;
1440 if (lpdcb->fOutX)
1441 port.c_iflag |= IXOFF;
1442 else
1443 port.c_iflag &= ~IXOFF;
1445 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1446 ERR("tcsetattr error '%s'\n", strerror(errno));
1447 COMM_SetCommError(handle,CE_IOE);
1448 ret = FALSE;
1449 } else {
1450 COMM_SetCommError(handle,0);
1451 ret = TRUE;
1454 /* note: change DTR/RTS lines after setting the comm attributes,
1455 * so flow control does not interfere. */
1456 #ifdef TIOCM_DTR
1457 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1459 WARN("DSR/DTR flow control not supported\n");
1460 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1461 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1462 else
1463 COMM_WhackModem(fd, 0, TIOCM_DTR);
1464 #endif
1465 #ifdef TIOCM_RTS
1466 if(!lpdcb->fOutxCtsFlow )
1468 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1469 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1470 else
1471 COMM_WhackModem(fd, 0, TIOCM_RTS);
1473 #endif
1474 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1475 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1476 release_comm_fd( handle, fd );
1477 return ret;
1482 /*****************************************************************************
1483 * GetCommState (KERNEL32.@)
1485 * Fills in a device control block with information from a communications device.
1487 * RETURNS
1489 * True on success, false if the communication device handle is bad etc
1491 * BUGS
1493 * XonChar and XoffChar are not set.
1495 BOOL WINAPI GetCommState(
1496 HANDLE handle, /* [in] The communications device. */
1497 LPDCB lpdcb) /* [out] The device control block. */
1499 struct termios port;
1500 int fd,speed;
1501 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1503 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1505 fd = get_comm_fd( handle, GENERIC_READ );
1506 if (fd < 0) return FALSE;
1507 if (tcgetattr(fd, &port) == -1
1508 #ifdef TIOCMGET
1509 || ioctl(fd, TIOCMGET, &stat) == -1
1510 #endif
1512 int save_error=errno;
1513 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
1514 COMM_SetCommError(handle,CE_IOE);
1515 release_comm_fd( handle, fd );
1516 return FALSE;
1518 release_comm_fd( handle, fd );
1519 #ifndef __EMX__
1520 #ifdef CBAUD
1521 speed= (port.c_cflag & CBAUD);
1522 #else
1523 speed= (cfgetospeed(&port));
1524 #endif
1525 switch (speed) {
1526 case B0:
1527 lpdcb->BaudRate = 0;
1528 break;
1529 case B50:
1530 lpdcb->BaudRate = 50;
1531 break;
1532 case B75:
1533 lpdcb->BaudRate = 75;
1534 break;
1535 case B110:
1536 lpdcb->BaudRate = 110;
1537 break;
1538 case B134:
1539 lpdcb->BaudRate = 134;
1540 break;
1541 case B150:
1542 lpdcb->BaudRate = 150;
1543 break;
1544 case B200:
1545 lpdcb->BaudRate = 200;
1546 break;
1547 case B300:
1548 lpdcb->BaudRate = 300;
1549 break;
1550 case B600:
1551 lpdcb->BaudRate = 600;
1552 break;
1553 case B1200:
1554 lpdcb->BaudRate = 1200;
1555 break;
1556 case B1800:
1557 lpdcb->BaudRate = 1800;
1558 break;
1559 case B2400:
1560 lpdcb->BaudRate = 2400;
1561 break;
1562 case B4800:
1563 lpdcb->BaudRate = 4800;
1564 break;
1565 case B9600:
1566 lpdcb->BaudRate = 9600;
1567 break;
1568 case B19200:
1569 lpdcb->BaudRate = 19200;
1570 break;
1571 case B38400:
1572 lpdcb->BaudRate = 38400;
1573 break;
1574 #ifdef B57600
1575 case B57600:
1576 lpdcb->BaudRate = 57600;
1577 break;
1578 #endif
1579 #ifdef B115200
1580 case B115200:
1581 lpdcb->BaudRate = 115200;
1582 break;
1583 #endif
1584 #ifdef B230400
1585 case B230400:
1586 lpdcb->BaudRate = 230400;
1587 break;
1588 #endif
1589 #ifdef B460800
1590 case B460800:
1591 lpdcb->BaudRate = 460800;
1592 break;
1593 #endif
1594 default:
1595 ERR("unknown speed %x \n",speed);
1597 #endif
1598 switch (port.c_cflag & CSIZE) {
1599 case CS5:
1600 lpdcb->ByteSize = 5;
1601 break;
1602 case CS6:
1603 lpdcb->ByteSize = 6;
1604 break;
1605 case CS7:
1606 lpdcb->ByteSize = 7;
1607 break;
1608 case CS8:
1609 lpdcb->ByteSize = 8;
1610 break;
1611 default:
1612 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1615 if(port.c_iflag & INPCK)
1616 lpdcb->fParity = TRUE;
1617 else
1618 lpdcb->fParity = FALSE;
1619 #ifdef CMSPAR
1620 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1621 #else
1622 switch (port.c_cflag & (PARENB | PARODD))
1623 #endif
1625 case 0:
1626 lpdcb->Parity = NOPARITY;
1627 break;
1628 case PARENB:
1629 lpdcb->Parity = EVENPARITY;
1630 break;
1631 case (PARENB | PARODD):
1632 lpdcb->Parity = ODDPARITY;
1633 break;
1634 #ifdef CMSPAR
1635 case (PARENB | CMSPAR):
1636 lpdcb->Parity = MARKPARITY;
1637 break;
1638 case (PARENB | PARODD | CMSPAR):
1639 lpdcb->Parity = SPACEPARITY;
1640 break;
1641 #endif
1644 if (port.c_cflag & CSTOPB)
1645 if(lpdcb->ByteSize == 5)
1646 lpdcb->StopBits = ONE5STOPBITS;
1647 else
1648 lpdcb->StopBits = TWOSTOPBITS;
1649 else
1650 lpdcb->StopBits = ONESTOPBIT;
1652 lpdcb->fNull = 0;
1653 lpdcb->fBinary = 1;
1655 /* termios does not support DTR/DSR flow control */
1656 lpdcb->fOutxDsrFlow = 0;
1657 lpdcb->fDtrControl =
1658 #ifdef TIOCM_DTR
1659 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1660 #endif
1661 DTR_CONTROL_ENABLE ;
1663 #ifdef CRTSCTS
1665 if (port.c_cflag & CRTSCTS) {
1666 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1667 lpdcb->fOutxCtsFlow = 1;
1668 } else
1669 #endif
1671 lpdcb->fRtsControl =
1672 #ifdef TIOCM_RTS
1673 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1674 #endif
1675 RTS_CONTROL_ENABLE ;
1676 lpdcb->fOutxCtsFlow = 0;
1678 if (port.c_iflag & IXON)
1679 lpdcb->fInX = 1;
1680 else
1681 lpdcb->fInX = 0;
1683 if (port.c_iflag & IXOFF)
1684 lpdcb->fOutX = 1;
1685 else
1686 lpdcb->fOutX = 0;
1688 lpdcb->XonChar =
1689 lpdcb->XoffChar =
1691 lpdcb->XonLim = 10;
1692 lpdcb->XoffLim = 10;
1694 COMM_SetCommError(handle,0);
1696 TRACE("OK\n");
1698 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1699 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1700 (lpdcb->StopBits == ONESTOPBIT)?1:
1701 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1702 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1703 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1704 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1705 lpdcb->fRtsControl);
1706 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1707 lpdcb->fDtrControl);
1708 #ifdef CRTSCTS
1709 if ( lpdcb->fOutxCtsFlow ||
1710 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1712 TRACE("CRTSCTS\n");
1713 else
1715 TRACE("~CRTSCTS\n");
1716 #endif
1717 return TRUE;
1720 /*****************************************************************************
1721 * TransmitCommChar (KERNEL32.@)
1723 * Transmits a single character in front of any pending characters in the
1724 * output buffer. Usually used to send an interrupt character to a host.
1726 * RETURNS
1728 * True if the call succeeded, false if the previous command character to the
1729 * same device has not been sent yet the handle is bad etc.
1731 * BUGS
1733 * Stub.
1735 BOOL WINAPI TransmitCommChar(
1736 HANDLE hComm, /* [in] The communication device in need of a command character. */
1737 CHAR chTransmit) /* [in] The character to transmit. */
1739 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1741 return WriteFile( hComm, &chTransmit, 1, NULL, NULL );
1745 /*****************************************************************************
1746 * GetCommTimeouts (KERNEL32.@)
1748 * Obtains the request timeout values for the communications device.
1750 * RETURNS
1752 * True on success, false if communications device handle is bad
1753 * or the target structure is null.
1755 BOOL WINAPI GetCommTimeouts(
1756 HANDLE hComm, /* [in] The communications device. */
1757 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1759 BOOL ret;
1761 TRACE("(%p,%p)\n",hComm,lptimeouts);
1763 if(!lptimeouts)
1765 SetLastError(ERROR_INVALID_PARAMETER);
1766 return FALSE;
1769 SERVER_START_REQ( get_serial_info )
1771 req->handle = hComm;
1772 if ((ret = !wine_server_call_err( req )))
1774 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1775 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1776 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1777 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1778 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1781 SERVER_END_REQ;
1782 return ret;
1785 /*****************************************************************************
1786 * SetCommTimeouts (KERNEL32.@)
1788 * Sets the timeouts used when reading and writing data to/from COMM ports.
1790 * ReadIntervalTimeout
1791 * - converted and passes to linux kernel as c_cc[VTIME]
1792 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1793 * - used in ReadFile to calculate GetOverlappedResult's timeout
1794 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1795 * - used in WriteFile to calculate GetOverlappedResult's timeout
1797 * RETURNS
1799 * True if the timeouts were set, false otherwise.
1801 BOOL WINAPI SetCommTimeouts(
1802 HANDLE hComm, /* [in] handle of COMM device */
1803 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1805 BOOL ret;
1806 int fd;
1807 struct termios tios;
1809 TRACE("(%p,%p)\n",hComm,lptimeouts);
1811 if(!lptimeouts)
1813 SetLastError(ERROR_INVALID_PARAMETER);
1814 return FALSE;
1817 SERVER_START_REQ( set_serial_info )
1819 req->handle = hComm;
1820 req->flags = SERIALINFO_SET_TIMEOUTS;
1821 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1822 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1823 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1824 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1825 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1826 ret = !wine_server_call_err( req );
1828 SERVER_END_REQ;
1829 if (!ret) return FALSE;
1831 /* FIXME: move this stuff to the server */
1832 fd = get_comm_fd( hComm, GENERIC_READ );
1833 if (fd < 0) return FALSE;
1835 if (-1==tcgetattr(fd,&tios)) {
1836 FIXME("tcgetattr on fd %d failed!\n",fd);
1837 release_comm_fd( hComm, fd );
1838 return FALSE;
1841 /* VTIME is in 1/10 seconds */
1843 unsigned int ux_timeout;
1845 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1847 ux_timeout = 0;
1849 else
1851 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1852 if(ux_timeout == 0)
1854 ux_timeout = 1; /* must be at least some timeout */
1857 tios.c_cc[VTIME] = ux_timeout;
1860 if (-1==tcsetattr(fd,0,&tios)) {
1861 FIXME("tcsetattr on fd %d failed!\n",fd);
1862 release_comm_fd( hComm, fd );
1863 return FALSE;
1865 release_comm_fd( hComm, fd );
1866 return TRUE;
1869 /***********************************************************************
1870 * GetCommModemStatus (KERNEL32.@)
1872 * Obtains the four control register bits if supported by the hardware.
1874 * RETURNS
1876 * True if the communications handle was good and for hardware that
1877 * control register access, false otherwise.
1879 BOOL WINAPI GetCommModemStatus(
1880 HANDLE hFile, /* [in] The communications device. */
1881 LPDWORD lpModemStat) /* [out] The control register bits. */
1883 int fd,mstat, result=FALSE;
1885 *lpModemStat=0;
1886 #ifdef TIOCMGET
1887 fd = get_comm_fd( hFile, GENERIC_READ );
1888 if(fd<0)
1889 return FALSE;
1890 result = ioctl(fd, TIOCMGET, &mstat);
1891 release_comm_fd( hFile, fd );
1892 if (result == -1)
1894 WARN("ioctl failed\n");
1895 return FALSE;
1897 #ifdef TIOCM_CTS
1898 if (mstat & TIOCM_CTS)
1899 *lpModemStat |= MS_CTS_ON;
1900 #endif
1901 #ifdef TIOCM_DSR
1902 if (mstat & TIOCM_DSR)
1903 *lpModemStat |= MS_DSR_ON;
1904 #endif
1905 #ifdef TIOCM_RNG
1906 if (mstat & TIOCM_RNG)
1907 *lpModemStat |= MS_RING_ON;
1908 #endif
1909 #ifdef TIOCM_CAR
1910 /*FIXME: Not really sure about RLSD UB 990810*/
1911 if (mstat & TIOCM_CAR)
1912 *lpModemStat |= MS_RLSD_ON;
1913 #endif
1914 TRACE("%04x -> %s%s%s%s\n", mstat,
1915 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1916 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1917 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1918 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1919 return TRUE;
1920 #else
1921 return FALSE;
1922 #endif
1925 /***********************************************************************
1926 * COMM_WaitCommEventService (INTERNAL)
1928 * This function is called while the client is waiting on the
1929 * server, so we can't make any server calls here.
1931 static void COMM_WaitCommEventService(async_private *ovp)
1933 async_commio *commio = (async_commio*) ovp;
1934 IO_STATUS_BLOCK* iosb = commio->async.iosb;
1936 TRACE("iosb %p\n",iosb);
1938 /* FIXME: detect other events */
1939 *commio->buffer = EV_RXCHAR;
1941 iosb->u.Status = STATUS_SUCCESS;
1945 /***********************************************************************
1946 * COMM_WaitCommEvent (INTERNAL)
1948 * This function must have an lpOverlapped.
1950 static BOOL COMM_WaitCommEvent(
1951 HANDLE hFile, /* [in] handle of comm port to wait for */
1952 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1953 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1955 int fd;
1956 async_commio *ovp;
1958 if(!lpOverlapped)
1960 SetLastError(ERROR_INVALID_PARAMETER);
1961 return FALSE;
1964 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1965 return FALSE;
1967 fd = get_comm_fd( hFile, GENERIC_WRITE );
1968 if(fd<0)
1969 return FALSE;
1971 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1972 if(!ovp)
1974 release_comm_fd( hFile, fd );
1975 return FALSE;
1978 ovp->async.ops = &commio_async_ops;
1979 ovp->async.handle = hFile;
1980 ovp->async.fd = fd; /* FIXME */
1981 ovp->async.type = ASYNC_TYPE_WAIT;
1982 ovp->async.func = COMM_WaitCommEventService;
1983 ovp->async.event = lpOverlapped->hEvent;
1984 ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
1985 ovp->buffer = (char *)lpdwEvents;
1987 lpOverlapped->InternalHigh = 0;
1988 lpOverlapped->Offset = 0;
1989 lpOverlapped->OffsetHigh = 0;
1991 if ( !register_new_async (&ovp->async) )
1992 SetLastError( ERROR_IO_PENDING );
1994 return FALSE;
1997 /***********************************************************************
1998 * WaitCommEvent (KERNEL32.@)
2000 * Wait until something interesting happens on a COMM port.
2001 * Interesting things (events) are set by calling SetCommMask before
2002 * this function is called.
2004 * RETURNS:
2005 * TRUE if successful
2006 * FALSE if failure
2008 * The set of detected events will be written to *lpdwEventMask
2009 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2011 * BUGS:
2012 * Only supports EV_RXCHAR and EV_TXEMPTY
2014 BOOL WINAPI WaitCommEvent(
2015 HANDLE hFile, /* [in] handle of comm port to wait for */
2016 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2017 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2019 OVERLAPPED ov;
2020 int ret;
2022 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2024 if(lpOverlapped)
2025 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2027 /* if there is no overlapped structure, create our own */
2028 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
2030 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2032 /* wait for the overlapped to complete */
2033 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
2034 CloseHandle(ov.hEvent);
2036 return ret;
2039 /***********************************************************************
2040 * GetCommProperties (KERNEL32.@)
2042 * This function fills in a structure with the capabilities of the
2043 * communications port driver.
2045 * RETURNS
2047 * TRUE on success, FALSE on failure
2048 * If successful, the lpCommProp structure be filled in with
2049 * properties of the comm port.
2051 BOOL WINAPI GetCommProperties(
2052 HANDLE hFile, /* [in] handle of the comm port */
2053 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2055 FIXME("(%p %p )\n",hFile,lpCommProp);
2056 if(!lpCommProp)
2057 return FALSE;
2060 * These values should be valid for LINUX's serial driver
2061 * FIXME: Perhaps they deserve an #ifdef LINUX
2063 memset(lpCommProp,0,sizeof(COMMPROP));
2064 lpCommProp->wPacketLength = 1;
2065 lpCommProp->wPacketVersion = 1;
2066 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2067 lpCommProp->dwReserved1 = 0;
2068 lpCommProp->dwMaxTxQueue = 4096;
2069 lpCommProp->dwMaxRxQueue = 4096;
2070 lpCommProp->dwMaxBaud = BAUD_115200;
2071 lpCommProp->dwProvSubType = PST_RS232;
2072 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2073 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2074 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2075 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2076 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2077 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2078 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2079 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2080 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2081 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2082 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2084 return TRUE;
2087 /***********************************************************************
2088 * FIXME:
2089 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2090 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2091 * This is dependent on the type of COMM port, but since it is doubtful
2092 * anybody will get around to implementing support for fancy serial
2093 * ports in WINE, this is hardcoded for the time being. The name of
2094 * this DLL should be stored in and read from the system registry in
2095 * the hive HKEY_LOCAL_MACHINE, key
2096 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2097 * where ???? is the port number... that is determined by PNP
2098 * The DLL should be loaded when the COMM port is opened, and closed
2099 * when the COMM port is closed. - MJM 20 June 2000
2100 ***********************************************************************/
2101 static CHAR lpszSerialUI[] = "serialui.dll";
2104 /***********************************************************************
2105 * CommConfigDialogA (KERNEL32.@)
2107 * Raises a dialog that allows the user to configure a comm port.
2108 * Fills the COMMCONFIG struct with information specified by the user.
2109 * This function should call a similar routine in the COMM driver...
2111 * RETURNS
2113 * TRUE on success, FALSE on failure
2114 * If successful, the lpCommConfig structure will contain a new
2115 * configuration for the comm port, as specified by the user.
2117 * BUGS
2118 * The library with the CommConfigDialog code is never unloaded.
2119 * Perhaps this should be done when the comm port is closed?
2121 BOOL WINAPI CommConfigDialogA(
2122 LPCSTR lpszDevice, /* [in] name of communications device */
2123 HANDLE hWnd, /* [in] parent window for the dialog */
2124 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2126 FARPROC lpfnCommDialog;
2127 HMODULE hConfigModule;
2128 BOOL r;
2130 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2132 hConfigModule = LoadLibraryA(lpszSerialUI);
2133 if(!hConfigModule)
2134 return FALSE;
2136 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2138 if(!lpfnCommDialog)
2139 return FALSE;
2141 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2143 /* UnloadLibrary(hConfigModule); */
2145 return r;
2148 /***********************************************************************
2149 * CommConfigDialogW (KERNEL32.@)
2151 * see CommConfigDialogA for more info
2153 BOOL WINAPI CommConfigDialogW(
2154 LPCWSTR lpszDevice, /* [in] name of communications device */
2155 HANDLE hWnd, /* [in] parent window for the dialog */
2156 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2158 BOOL r;
2159 LPSTR lpDeviceA;
2161 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2162 if(lpDeviceA)
2163 return FALSE;
2164 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
2165 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2166 return r;
2169 /***********************************************************************
2170 * GetCommConfig (KERNEL32.@)
2172 * Fill in the COMMCONFIG structure for the comm port hFile
2174 * RETURNS
2176 * TRUE on success, FALSE on failure
2177 * If successful, lpCommConfig contains the comm port configuration.
2179 * BUGS
2182 BOOL WINAPI GetCommConfig(
2183 HANDLE hFile, /* [in] The communications device. */
2184 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2185 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2186 afterwards the number of bytes copied to the buffer or
2187 the needed size of the buffer. */
2189 BOOL r;
2191 TRACE("(%p %p)\n",hFile,lpCommConfig);
2193 if(lpCommConfig == NULL)
2194 return FALSE;
2195 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2196 *lpdwSize = sizeof(COMMCONFIG);
2197 if(r)
2198 return FALSE;
2200 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2201 lpCommConfig->wVersion = 1;
2202 lpCommConfig->wReserved = 0;
2203 r = GetCommState(hFile,&lpCommConfig->dcb);
2204 lpCommConfig->dwProviderSubType = PST_RS232;
2205 lpCommConfig->dwProviderOffset = 0;
2206 lpCommConfig->dwProviderSize = 0;
2208 return r;
2211 /***********************************************************************
2212 * SetCommConfig (KERNEL32.@)
2214 * Sets the configuration of the communications device.
2216 * RETURNS
2218 * True on success, false if the handle was bad is not a communications device.
2220 BOOL WINAPI SetCommConfig(
2221 HANDLE hFile, /* [in] The communications device. */
2222 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2223 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2225 TRACE("(%p %p)\n",hFile,lpCommConfig);
2226 return SetCommState(hFile,&lpCommConfig->dcb);
2229 /***********************************************************************
2230 * SetDefaultCommConfigA (KERNEL32.@)
2232 * Initializes the default configuration for the specified communication
2233 * device. (ascii)
2235 * RETURNS
2237 * True if the device was found and the defaults set, false otherwise
2239 BOOL WINAPI SetDefaultCommConfigA(
2240 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2241 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2242 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2244 FARPROC lpfnSetDefaultCommConfig;
2245 HMODULE hConfigModule;
2246 BOOL r;
2248 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2250 hConfigModule = LoadLibraryA(lpszSerialUI);
2251 if(!hConfigModule)
2252 return FALSE;
2254 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
2256 if(! lpfnSetDefaultCommConfig)
2257 return TRUE;
2259 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2261 /* UnloadLibrary(hConfigModule); */
2263 return r;
2267 /***********************************************************************
2268 * SetDefaultCommConfigW (KERNEL32.@)
2270 * Initializes the default configuration for the specified
2271 * communication device. (unicode)
2273 * RETURNS
2276 BOOL WINAPI SetDefaultCommConfigW(
2277 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2278 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2279 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2281 BOOL r;
2282 LPSTR lpDeviceA;
2284 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2286 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2287 if(lpDeviceA)
2288 return FALSE;
2289 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2290 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2291 return r;
2295 /***********************************************************************
2296 * GetDefaultCommConfigW (KERNEL32.@)
2298 * Acquires the default configuration of the specified communication device. (unicode)
2300 * RETURNS
2302 * True on successful reading of the default configuration,
2303 * if the device is not found or the buffer is too small.
2305 BOOL WINAPI GetDefaultCommConfigW(
2306 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2307 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2308 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2309 afterwards the number of bytes copied to the buffer or
2310 the needed size of the buffer. */
2312 LPDCB lpdcb = &(lpCC->dcb);
2313 WCHAR temp[40];
2314 static const WCHAR comW[] = {'C','O','M',0};
2315 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2317 if (strncmpiW(lpszName,comW,3)) {
2318 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2319 return FALSE;
2322 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2323 if (*lpdwSize < sizeof(COMMCONFIG)) {
2324 *lpdwSize = sizeof(COMMCONFIG);
2325 return FALSE;
2328 *lpdwSize = sizeof(COMMCONFIG);
2330 lpCC->dwSize = sizeof(COMMCONFIG);
2331 lpCC->wVersion = 1;
2332 lpCC->dwProviderSubType = PST_RS232;
2333 lpCC->dwProviderOffset = 0L;
2334 lpCC->dwProviderSize = 0L;
2336 sprintfW( temp, formatW, lpszName[3]);
2337 FIXME("setting %s as default\n", debugstr_w(temp));
2339 return BuildCommDCBW( temp, lpdcb);
2342 /**************************************************************************
2343 * GetDefaultCommConfigA (KERNEL32.@)
2345 * Acquires the default configuration of the specified communication device. (ascii)
2347 * RETURNS
2349 * True on successful reading of the default configuration,
2350 * if the device is not found or the buffer is too small.
2352 BOOL WINAPI GetDefaultCommConfigA(
2353 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2354 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2355 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2356 afterwards the number of bytes copied to the buffer or
2357 the needed size of the buffer. */
2359 BOOL ret = FALSE;
2360 UNICODE_STRING lpszNameW;
2362 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2363 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2364 else lpszNameW.Buffer = NULL;
2366 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2368 RtlFreeUnicodeString(&lpszNameW);
2369 return ret;