Use CreateEventW in preference to CreateEventA for unnamed events.
[wine/multimedia.git] / dlls / kernel / comm.c
blob2e6f8f7d4aa119ae45367eb70acc368ac7f75bb3
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 "wine/unicode.h"
99 #include "wine/debug.h"
101 #ifdef HAVE_LINUX_SERIAL_H
102 #include <linux/serial.h>
103 #endif
105 WINE_DEFAULT_DEBUG_CHANNEL(comm);
107 /* retrieve the Unix handle corresponding to a comm handle */
108 static int get_comm_fd( HANDLE handle, DWORD access )
110 int fd, ret;
112 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
113 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
114 return fd;
117 /* release the Unix handle returned by get_comm_fd */
118 static inline void release_comm_fd( HANDLE handle, int fd )
120 wine_server_release_fd( handle, fd );
124 /***********************************************************************
125 * Asynchronous I/O for asynchronous wait requests *
128 static DWORD commio_get_async_count (const async_private *ovp);
129 static void commio_async_cleanup (async_private *ovp);
131 static async_ops commio_async_ops =
133 commio_get_async_count, /* get_count */
134 NULL, /* call_completion */
135 commio_async_cleanup /* cleanup */
138 typedef struct async_commio
140 struct async_private async;
141 char *buffer;
142 } async_commio;
144 static DWORD commio_get_async_count (const struct async_private *ovp)
146 return 0;
149 static void commio_async_cleanup (async_private *ovp)
151 HeapFree(GetProcessHeap(), 0, ovp );
154 /***********************************************************************/
156 #if !defined(TIOCINQ) && defined(FIONREAD)
157 #define TIOCINQ FIONREAD
158 #endif
160 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
162 #ifdef TIOCMGET
163 unsigned int mstat, okay;
164 okay = ioctl(fd, TIOCMGET, &mstat);
165 if (okay) return okay;
166 if (andy) mstat &= andy;
167 mstat |= orrie;
168 return ioctl(fd, TIOCMSET, &mstat);
169 #else
170 return 0;
171 #endif
174 /***********************************************************************
175 * COMM_Parse* (Internal)
177 * The following COMM_Parse* functions are used by the BuildCommDCB
178 * functions to help parse the various parts of the device control string.
180 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
182 static const WCHAR comW[] = {'C','O','M',0};
184 /* The device control string may optionally start with "COMx" followed
185 by an optional ':' and spaces. */
186 if(!strncmpiW(ptr, comW, 3))
188 ptr += 3;
190 /* Allow any com port above 0 as Win 9x does (NT only allows
191 values for com ports which are actually present) */
192 if(*ptr < '1' || *ptr > '9')
193 return NULL;
195 /* Advance pointer past port number */
196 while(*ptr >= '0' && *ptr <= '9') ptr++;
198 /* The com port number must be followed by a ':' or ' ' */
199 if(*ptr != ':' && *ptr != ' ')
200 return NULL;
202 /* Advance pointer to beginning of next parameter */
203 while(*ptr == ' ') ptr++;
204 if(*ptr == ':')
206 ptr++;
207 while(*ptr == ' ') ptr++;
210 /* The device control string must not start with a space. */
211 else if(*ptr == ' ')
212 return NULL;
214 return ptr;
217 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
219 if(*ptr < '0' || *ptr > '9') return NULL;
220 *lpnumber = strtoulW(ptr, NULL, 10);
221 while(*ptr >= '0' && *ptr <= '9') ptr++;
222 return ptr;
225 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
227 /* Contrary to what you might expect, Windows only sets the Parity
228 member of DCB and not fParity even when parity is specified in the
229 device control string */
231 switch(toupperW(*ptr++))
233 case 'E':
234 *lpparity = EVENPARITY;
235 break;
236 case 'M':
237 *lpparity = MARKPARITY;
238 break;
239 case 'N':
240 *lpparity = NOPARITY;
241 break;
242 case 'O':
243 *lpparity = ODDPARITY;
244 break;
245 case 'S':
246 *lpparity = SPACEPARITY;
247 break;
248 default:
249 return NULL;
252 return ptr;
255 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
257 DWORD temp;
259 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
260 return NULL;
262 if(temp >= 5 && temp <= 8)
264 *lpbytesize = temp;
265 return ptr;
267 else
268 return NULL;
271 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
273 DWORD temp;
274 static const WCHAR stopbits15W[] = {'1','.','5',0};
276 if(!strncmpW(stopbits15W, ptr, 3))
278 ptr += 3;
279 *lpstopbits = ONE5STOPBITS;
281 else
283 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
284 return NULL;
286 if(temp == 1)
287 *lpstopbits = ONESTOPBIT;
288 else if(temp == 2)
289 *lpstopbits = TWOSTOPBITS;
290 else
291 return NULL;
294 return ptr;
297 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
299 static const WCHAR onW[] = {'o','n',0};
300 static const WCHAR offW[] = {'o','f','f',0};
302 if(!strncmpiW(onW, ptr, 2))
304 ptr += 2;
305 *lponoff = 1;
307 else if(!strncmpiW(offW, ptr, 3))
309 ptr += 3;
310 *lponoff = 0;
312 else
313 return NULL;
315 return ptr;
318 /***********************************************************************
319 * COMM_BuildOldCommDCB (Internal)
321 * Build a DCB using the old style settings string eg: "96,n,8,1"
323 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
325 WCHAR last = 0;
327 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
328 return FALSE;
330 switch(lpdcb->BaudRate)
332 case 11:
333 case 30:
334 case 60:
335 lpdcb->BaudRate *= 10;
336 break;
337 case 12:
338 case 24:
339 case 48:
340 case 96:
341 lpdcb->BaudRate *= 100;
342 break;
343 case 19:
344 lpdcb->BaudRate = 19200;
345 break;
348 while(*device == ' ') device++;
349 if(*device++ != ',') return FALSE;
350 while(*device == ' ') device++;
352 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
353 return FALSE;
355 while(*device == ' ') device++;
356 if(*device++ != ',') return FALSE;
357 while(*device == ' ') device++;
359 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
360 return FALSE;
362 while(*device == ' ') device++;
363 if(*device++ != ',') return FALSE;
364 while(*device == ' ') device++;
366 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
367 return FALSE;
369 /* The last parameter for flow control is optional. */
370 while(*device == ' ') device++;
371 if(*device == ',')
373 device++;
374 while(*device == ' ') device++;
375 if(*device) last = toupperW(*device++);
376 while(*device == ' ') device++;
379 /* Win NT sets the flow control members based on (or lack of) the last
380 parameter. Win 9x does not set these members. */
381 switch(last)
383 case 0:
384 lpdcb->fInX = FALSE;
385 lpdcb->fOutX = FALSE;
386 lpdcb->fOutxCtsFlow = FALSE;
387 lpdcb->fOutxDsrFlow = FALSE;
388 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
389 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
390 break;
391 case 'X':
392 lpdcb->fInX = TRUE;
393 lpdcb->fOutX = TRUE;
394 lpdcb->fOutxCtsFlow = FALSE;
395 lpdcb->fOutxDsrFlow = FALSE;
396 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
397 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
398 break;
399 case 'P':
400 lpdcb->fInX = FALSE;
401 lpdcb->fOutX = FALSE;
402 lpdcb->fOutxCtsFlow = TRUE;
403 lpdcb->fOutxDsrFlow = TRUE;
404 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
405 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
406 break;
407 default:
408 return FALSE;
411 /* This should be the end of the string. */
412 if(*device) return FALSE;
414 return TRUE;
417 /***********************************************************************
418 * COMM_BuildNewCommDCB (Internal)
420 * Build a DCB using the new style settings string.
421 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
423 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
425 DWORD temp;
426 BOOL baud = FALSE, stop = FALSE;
427 static const WCHAR baudW[] = {'b','a','u','d','=',0};
428 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
429 static const WCHAR dataW[] = {'d','a','t','a','=',0};
430 static const WCHAR stopW[] = {'s','t','o','p','=',0};
431 static const WCHAR toW[] = {'t','o','=',0};
432 static const WCHAR xonW[] = {'x','o','n','=',0};
433 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
434 static const WCHAR octsW[] = {'o','c','t','s','=',0};
435 static const WCHAR dtrW[] = {'d','t','r','=',0};
436 static const WCHAR rtsW[] = {'r','t','s','=',0};
437 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
439 while(*device)
441 while(*device == ' ') device++;
443 if(!strncmpiW(baudW, device, 5))
445 baud = TRUE;
447 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
448 return FALSE;
450 else if(!strncmpiW(parityW, device, 7))
452 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
453 return FALSE;
455 else if(!strncmpiW(dataW, device, 5))
457 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
458 return FALSE;
460 else if(!strncmpiW(stopW, device, 5))
462 stop = TRUE;
464 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
465 return FALSE;
467 else if(!strncmpiW(toW, device, 3))
469 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
470 return FALSE;
472 lptimeouts->ReadIntervalTimeout = 0;
473 lptimeouts->ReadTotalTimeoutMultiplier = 0;
474 lptimeouts->ReadTotalTimeoutConstant = 0;
475 lptimeouts->WriteTotalTimeoutMultiplier = 0;
476 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
478 else if(!strncmpiW(xonW, device, 4))
480 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
481 return FALSE;
483 lpdcb->fOutX = temp;
484 lpdcb->fInX = temp;
486 else if(!strncmpiW(odsrW, device, 5))
488 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
489 return FALSE;
491 lpdcb->fOutxDsrFlow = temp;
493 else if(!strncmpiW(octsW, device, 5))
495 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
496 return FALSE;
498 lpdcb->fOutxCtsFlow = temp;
500 else if(!strncmpiW(dtrW, device, 4))
502 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
503 return FALSE;
505 lpdcb->fDtrControl = temp;
507 else if(!strncmpiW(rtsW, device, 4))
509 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
510 return FALSE;
512 lpdcb->fRtsControl = temp;
514 else if(!strncmpiW(idsrW, device, 5))
516 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
517 return FALSE;
519 /* Win NT sets the fDsrSensitivity member based on the
520 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
521 lpdcb->fDsrSensitivity = temp;
523 else
524 return FALSE;
526 /* After the above parsing, the next character (if not the end of
527 the string) should be a space */
528 if(*device && *device != ' ')
529 return FALSE;
532 /* If stop bits were not specified, a default is always supplied. */
533 if(!stop)
535 if(baud && lpdcb->BaudRate == 110)
536 lpdcb->StopBits = TWOSTOPBITS;
537 else
538 lpdcb->StopBits = ONESTOPBIT;
541 return TRUE;
544 /**************************************************************************
545 * BuildCommDCBA (KERNEL32.@)
547 * Updates a device control block data structure with values from an
548 * ascii device control string. The device control string has two forms
549 * normal and extended, it must be exclusively in one or the other form.
551 * RETURNS
553 * True on success, false on a malformed control string.
555 BOOL WINAPI BuildCommDCBA(
556 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
557 LPDCB lpdcb) /* [out] The device control block to be updated. */
559 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
562 /**************************************************************************
563 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
565 * Updates a device control block data structure with values from an
566 * ascii device control string. Taking timeout values from a timeouts
567 * struct if desired by the control string.
569 * RETURNS
571 * True on success, false bad handles etc.
573 BOOL WINAPI BuildCommDCBAndTimeoutsA(
574 LPCSTR device, /* [in] The ascii device control string. */
575 LPDCB lpdcb, /* [out] The device control block to be updated. */
576 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
578 BOOL ret = FALSE;
579 UNICODE_STRING deviceW;
581 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
582 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
583 else deviceW.Buffer = NULL;
585 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
587 RtlFreeUnicodeString(&deviceW);
588 return ret;
591 /**************************************************************************
592 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
594 * Updates a device control block data structure with values from a
595 * unicode device control string. Taking timeout values from a timeouts
596 * struct if desired by the control string.
598 * RETURNS
600 * True on success, false bad handles etc
602 BOOL WINAPI BuildCommDCBAndTimeoutsW(
603 LPCWSTR devid, /* [in] The unicode device control string. */
604 LPDCB lpdcb, /* [out] The device control block to be updated. */
605 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
607 DCB dcb;
608 COMMTIMEOUTS timeouts;
609 BOOL result;
610 LPCWSTR ptr = devid;
612 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
614 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
615 lpdcb->DCBlength = sizeof(DCB);
617 /* Make a copy of the original data structures to work with since if
618 if there is an error in the device control string the originals
619 should not be modified (except possibly DCBlength) */
620 memcpy(&dcb, lpdcb, sizeof(DCB));
621 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
623 ptr = COMM_ParseStart(ptr);
625 if(ptr == NULL)
626 result = FALSE;
627 else if(strchrW(ptr, ','))
628 result = COMM_BuildOldCommDCB(ptr, &dcb);
629 else
630 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
632 if(result)
634 memcpy(lpdcb, &dcb, sizeof(DCB));
635 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
636 return TRUE;
638 else
640 WARN("Invalid device control string: %s\n", debugstr_w(devid));
641 SetLastError(ERROR_INVALID_PARAMETER);
642 return FALSE;
646 /**************************************************************************
647 * BuildCommDCBW (KERNEL32.@)
649 * Updates a device control block structure with values from an
650 * unicode device control string. The device control string has two forms
651 * normal and extended, it must be exclusively in one or the other form.
653 * RETURNS
655 * True on success, false on an malformed control string.
657 BOOL WINAPI BuildCommDCBW(
658 LPCWSTR devid, /* [in] The unicode device control string. */
659 LPDCB lpdcb) /* [out] The device control block to be updated. */
661 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
664 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
666 DWORD ret;
668 SERVER_START_REQ( set_serial_info )
670 req->handle = handle;
671 req->flags = SERIALINFO_SET_ERROR;
672 req->commerror = error;
673 ret = !wine_server_call_err( req );
675 SERVER_END_REQ;
676 return ret;
679 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
681 DWORD ret;
683 if(!lperror)
684 return FALSE;
686 SERVER_START_REQ( get_serial_info )
688 req->handle = handle;
689 ret = !wine_server_call_err( req );
690 *lperror = reply->commerror;
692 SERVER_END_REQ;
694 return ret;
697 /*****************************************************************************
698 * SetCommBreak (KERNEL32.@)
700 * Halts the transmission of characters to a communications device.
702 * RETURNS
704 * True on success, and false if the communications device could not be found,
705 * the control is not supported.
707 * BUGS
709 * Only TIOCSBRK and TIOCCBRK are supported.
711 BOOL WINAPI SetCommBreak(
712 HANDLE handle) /* [in] The communictions device to suspend. */
714 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
715 int fd,result;
717 fd = get_comm_fd( handle, GENERIC_READ );
718 if(fd<0) return FALSE;
719 result = ioctl(fd,TIOCSBRK,0);
720 release_comm_fd( handle, fd );
721 if (result ==-1)
723 TRACE("ioctl failed\n");
724 SetLastError(ERROR_NOT_SUPPORTED);
725 return FALSE;
727 return TRUE;
728 #else
729 FIXME("ioctl not available\n");
730 SetLastError(ERROR_NOT_SUPPORTED);
731 return FALSE;
732 #endif
735 /*****************************************************************************
736 * ClearCommBreak (KERNEL32.@)
738 * Resumes character transmission from a communication device.
740 * RETURNS
742 * True on success and false if the communications device could not be found.
744 * BUGS
746 * Only TIOCSBRK and TIOCCBRK are supported.
748 BOOL WINAPI ClearCommBreak(
749 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
751 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
752 int fd,result;
754 fd = get_comm_fd( handle, GENERIC_READ );
755 if(fd<0) return FALSE;
756 result = ioctl(fd,TIOCCBRK,0);
757 release_comm_fd( handle, fd );
758 if (result ==-1)
760 TRACE("ioctl failed\n");
761 SetLastError(ERROR_NOT_SUPPORTED);
762 return FALSE;
764 return TRUE;
765 #else
766 FIXME("ioctl not available\n");
767 SetLastError(ERROR_NOT_SUPPORTED);
768 return FALSE;
769 #endif
772 /*****************************************************************************
773 * EscapeCommFunction (KERNEL32.@)
775 * Directs a communication device to perform an extended function.
777 * RETURNS
779 * True or requested data on successful completion of the command,
780 * false if the device is not present cannot execute the command
781 * or the command failed.
783 BOOL WINAPI EscapeCommFunction(
784 HANDLE handle, /* [in] The communication device to perform the extended function. */
785 UINT nFunction) /* [in] The extended function to be performed. */
787 int fd,direct=FALSE,result=FALSE;
788 struct termios port;
790 TRACE("handle %p, function=%d\n", handle, nFunction);
791 fd = get_comm_fd( handle, GENERIC_READ );
792 if(fd<0) return FALSE;
794 if (tcgetattr(fd,&port) == -1) {
795 COMM_SetCommError(handle,CE_IOE);
796 release_comm_fd( handle, fd );
797 return FALSE;
800 switch (nFunction) {
801 case RESETDEV:
802 TRACE("\n");
803 break;
805 case CLRDTR:
806 TRACE("CLRDTR\n");
807 #ifdef TIOCM_DTR
808 direct=TRUE;
809 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
810 break;
811 #endif
813 case CLRRTS:
814 TRACE("CLRRTS\n");
815 #ifdef TIOCM_RTS
816 direct=TRUE;
817 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
818 break;
819 #endif
821 case SETDTR:
822 TRACE("SETDTR\n");
823 #ifdef TIOCM_DTR
824 direct=TRUE;
825 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
826 break;
827 #endif
829 case SETRTS:
830 TRACE("SETRTS\n");
831 #ifdef TIOCM_RTS
832 direct=TRUE;
833 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
834 break;
835 #endif
837 case SETXOFF:
838 TRACE("SETXOFF\n");
839 port.c_iflag |= IXOFF;
840 break;
842 case SETXON:
843 TRACE("SETXON\n");
844 port.c_iflag |= IXON;
845 break;
846 case SETBREAK:
847 TRACE("setbreak\n");
848 #ifdef TIOCSBRK
849 direct=TRUE;
850 result = ioctl(fd,TIOCSBRK,0);
851 break;
852 #endif
853 case CLRBREAK:
854 TRACE("clrbreak\n");
855 #ifdef TIOCSBRK
856 direct=TRUE;
857 result = ioctl(fd,TIOCCBRK,0);
858 break;
859 #endif
860 default:
861 WARN("(handle=%p,nFunction=%d): Unknown function\n",
862 handle, nFunction);
863 break;
866 if (!direct)
867 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
868 release_comm_fd( handle, fd );
869 COMM_SetCommError(handle,CE_IOE);
870 return FALSE;
871 } else
872 result= TRUE;
873 else
875 if (result == -1)
877 result= FALSE;
878 COMM_SetCommError(handle,CE_IOE);
880 else
881 result = TRUE;
883 release_comm_fd( handle, fd );
884 return result;
887 /********************************************************************
888 * PurgeComm (KERNEL32.@)
890 * Terminates pending operations and/or discards buffers on a
891 * communication resource.
893 * RETURNS
895 * True on success and false if the communications handle is bad.
897 BOOL WINAPI PurgeComm(
898 HANDLE handle, /* [in] The communication resource to be purged. */
899 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
901 int fd;
903 TRACE("handle %p, flags %lx\n", handle, flags);
905 fd = get_comm_fd( handle, GENERIC_READ );
906 if(fd<0) return FALSE;
909 ** not exactly sure how these are different
910 ** Perhaps if we had our own internal queues, one flushes them
911 ** and the other flushes the kernel's buffers.
913 if(flags&PURGE_TXABORT)
914 tcflush(fd,TCOFLUSH);
915 if(flags&PURGE_RXABORT)
916 tcflush(fd,TCIFLUSH);
917 if(flags&PURGE_TXCLEAR)
918 tcflush(fd,TCOFLUSH);
919 if(flags&PURGE_RXCLEAR)
920 tcflush(fd,TCIFLUSH);
921 release_comm_fd( handle, fd );
923 return 1;
926 /*****************************************************************************
927 * ClearCommError (KERNEL32.@)
929 * Enables further I/O operations on a communications resource after
930 * supplying error and current status information.
932 * RETURNS
934 * True on success, false if the communication resource handle is bad.
936 BOOL WINAPI ClearCommError(
937 HANDLE handle, /* [in] The communication resource with the error. */
938 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
939 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
941 int fd;
943 fd=get_comm_fd( handle, GENERIC_READ );
944 if(0>fd) return FALSE;
946 if (lpStat)
948 lpStat->fCtsHold = 0;
949 lpStat->fDsrHold = 0;
950 lpStat->fRlsdHold = 0;
951 lpStat->fXoffHold = 0;
952 lpStat->fXoffSent = 0;
953 lpStat->fEof = 0;
954 lpStat->fTxim = 0;
955 lpStat->fReserved = 0;
957 #ifdef TIOCOUTQ
958 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
959 WARN("ioctl returned error\n");
960 #else
961 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
962 #endif
964 #ifdef TIOCINQ
965 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
966 WARN("ioctl returned error\n");
967 #endif
969 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
970 handle, lpStat->cbInQue, lpStat->cbOutQue);
973 release_comm_fd( handle, fd );
975 COMM_GetCommError(handle, errors);
976 COMM_SetCommError(handle, 0);
978 return TRUE;
981 /*****************************************************************************
982 * SetupComm (KERNEL32.@)
984 * Called after CreateFile to hint to the communication resource to use
985 * specified sizes for input and output buffers rather than the default values.
987 * RETURNS
989 * True if successful, false if the communications resource handle is bad.
991 * BUGS
993 * Stub.
995 BOOL WINAPI SetupComm(
996 HANDLE handle, /* [in] The just created communication resource handle. */
997 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
998 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
1000 int fd;
1002 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1003 fd=get_comm_fd( handle, GENERIC_READ );
1004 if(0>fd) return FALSE;
1005 release_comm_fd( handle, fd );
1006 return TRUE;
1009 /*****************************************************************************
1010 * GetCommMask (KERNEL32.@)
1012 * Obtain the events associated with a communication device that will cause
1013 * a call WaitCommEvent to return.
1015 * RETURNS
1017 * True on success, fail on bad device handle etc.
1019 BOOL WINAPI GetCommMask(
1020 HANDLE handle, /* [in] The communications device. */
1021 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1023 BOOL ret;
1025 TRACE("handle %p, mask %p\n", handle, evtmask);
1027 SERVER_START_REQ( get_serial_info )
1029 req->handle = handle;
1030 if ((ret = !wine_server_call_err( req )))
1032 if (evtmask) *evtmask = reply->eventmask;
1035 SERVER_END_REQ;
1036 return ret;
1039 /*****************************************************************************
1040 * SetCommMask (KERNEL32.@)
1042 * There be some things we need to hear about yon there communications device.
1043 * (Set which events associated with a communication device should cause
1044 * a call WaitCommEvent to return.)
1046 * RETURNS
1048 * True on success, false on bad handle etc.
1050 BOOL WINAPI SetCommMask(
1051 HANDLE handle, /* [in] The communications device. */
1052 DWORD evtmask) /* [in] The events that are to be monitored. */
1054 BOOL ret;
1056 TRACE("handle %p, mask %lx\n", handle, evtmask);
1058 SERVER_START_REQ( set_serial_info )
1060 req->handle = handle;
1061 req->flags = SERIALINFO_SET_MASK;
1062 req->eventmask = evtmask;
1063 ret = !wine_server_call_err( req );
1065 SERVER_END_REQ;
1066 return ret;
1069 /*****************************************************************************
1070 * SetCommState (KERNEL32.@)
1072 * Re-initializes all hardware and control settings of a communications device,
1073 * with values from a device control block without effecting the input and output
1074 * queues.
1076 * RETURNS
1078 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1080 BOOL WINAPI SetCommState(
1081 HANDLE handle, /* [in] The communications device. */
1082 LPDCB lpdcb) /* [out] The device control block. */
1084 struct termios port;
1085 int fd, bytesize, stopbits;
1086 BOOL ret;
1088 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1089 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1090 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1091 (lpdcb->StopBits == ONESTOPBIT)?1:
1092 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1093 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1094 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1095 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1096 lpdcb->fRtsControl);
1097 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1098 lpdcb->fDtrControl);
1101 fd = get_comm_fd( handle, GENERIC_READ );
1102 if (fd < 0) return FALSE;
1104 if ((tcgetattr(fd,&port)) == -1) {
1105 int save_error = errno;
1106 COMM_SetCommError(handle,CE_IOE);
1107 release_comm_fd( handle, fd );
1108 ERR("tcgetattr error '%s'\n", strerror(save_error));
1109 return FALSE;
1112 port.c_cc[VMIN] = 0;
1113 port.c_cc[VTIME] = 1;
1115 #ifdef IMAXBEL
1116 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1117 #else
1118 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1119 #endif
1120 port.c_iflag |= (IGNBRK);
1122 port.c_oflag &= ~(OPOST);
1124 port.c_cflag &= ~(HUPCL);
1125 port.c_cflag |= CLOCAL | CREAD;
1127 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1128 port.c_lflag |= NOFLSH;
1130 #ifdef CBAUD
1131 port.c_cflag &= ~CBAUD;
1132 switch (lpdcb->BaudRate) {
1133 case 0:
1134 port.c_cflag |= B0;
1135 break;
1136 case 50:
1137 port.c_cflag |= B50;
1138 break;
1139 case 75:
1140 port.c_cflag |= B75;
1141 break;
1142 case 110:
1143 case CBR_110:
1144 port.c_cflag |= B110;
1145 break;
1146 case 134:
1147 port.c_cflag |= B134;
1148 break;
1149 case 150:
1150 port.c_cflag |= B150;
1151 break;
1152 case 200:
1153 port.c_cflag |= B200;
1154 break;
1155 case 300:
1156 case CBR_300:
1157 port.c_cflag |= B300;
1158 break;
1159 case 600:
1160 case CBR_600:
1161 port.c_cflag |= B600;
1162 break;
1163 case 1200:
1164 case CBR_1200:
1165 port.c_cflag |= B1200;
1166 break;
1167 case 1800:
1168 port.c_cflag |= B1800;
1169 break;
1170 case 2400:
1171 case CBR_2400:
1172 port.c_cflag |= B2400;
1173 break;
1174 case 4800:
1175 case CBR_4800:
1176 port.c_cflag |= B4800;
1177 break;
1178 case 9600:
1179 case CBR_9600:
1180 port.c_cflag |= B9600;
1181 break;
1182 case 19200:
1183 case CBR_19200:
1184 port.c_cflag |= B19200;
1185 break;
1186 case 38400:
1187 case CBR_38400:
1188 port.c_cflag |= B38400;
1189 break;
1190 #ifdef B57600
1191 case 57600:
1192 port.c_cflag |= B57600;
1193 break;
1194 #endif
1195 #ifdef B115200
1196 case 115200:
1197 port.c_cflag |= B115200;
1198 break;
1199 #endif
1200 #ifdef B230400
1201 case 230400:
1202 port.c_cflag |= B230400;
1203 break;
1204 #endif
1205 #ifdef B460800
1206 case 460800:
1207 port.c_cflag |= B460800;
1208 break;
1209 #endif
1210 default:
1211 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1212 { struct serial_struct nuts;
1213 int arby;
1214 ioctl(fd, TIOCGSERIAL, &nuts);
1215 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1216 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1217 arby = nuts.baud_base / nuts.custom_divisor;
1218 nuts.flags &= ~ASYNC_SPD_MASK;
1219 nuts.flags |= ASYNC_SPD_CUST;
1220 WARN("You (or a program acting at your behest) have specified\n"
1221 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1222 "which is as close as we can get by our present understanding of your\n"
1223 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1224 "has caused to your linux system can be undone with setserial \n"
1225 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1226 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1227 ioctl(fd, TIOCSSERIAL, &nuts);
1228 port.c_cflag |= B38400;
1230 break;
1231 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1234 COMM_SetCommError(handle,IE_BAUDRATE);
1235 release_comm_fd( handle, fd );
1236 ERR("baudrate %ld\n",lpdcb->BaudRate);
1237 return FALSE;
1239 #elif !defined(__EMX__)
1240 switch (lpdcb->BaudRate) {
1241 case 0:
1242 port.c_ospeed = B0;
1243 break;
1244 case 50:
1245 port.c_ospeed = B50;
1246 break;
1247 case 75:
1248 port.c_ospeed = B75;
1249 break;
1250 case 110:
1251 case CBR_110:
1252 port.c_ospeed = B110;
1253 break;
1254 case 134:
1255 port.c_ospeed = B134;
1256 break;
1257 case 150:
1258 port.c_ospeed = B150;
1259 break;
1260 case 200:
1261 port.c_ospeed = B200;
1262 break;
1263 case 300:
1264 case CBR_300:
1265 port.c_ospeed = B300;
1266 break;
1267 case 600:
1268 case CBR_600:
1269 port.c_ospeed = B600;
1270 break;
1271 case 1200:
1272 case CBR_1200:
1273 port.c_ospeed = B1200;
1274 break;
1275 case 1800:
1276 port.c_ospeed = B1800;
1277 break;
1278 case 2400:
1279 case CBR_2400:
1280 port.c_ospeed = B2400;
1281 break;
1282 case 4800:
1283 case CBR_4800:
1284 port.c_ospeed = B4800;
1285 break;
1286 case 9600:
1287 case CBR_9600:
1288 port.c_ospeed = B9600;
1289 break;
1290 case 19200:
1291 case CBR_19200:
1292 port.c_ospeed = B19200;
1293 break;
1294 case 38400:
1295 case CBR_38400:
1296 port.c_ospeed = B38400;
1297 break;
1298 #ifdef B57600
1299 case 57600:
1300 case CBR_57600:
1301 port.c_cflag |= B57600;
1302 break;
1303 #endif
1304 #ifdef B115200
1305 case 115200:
1306 case CBR_115200:
1307 port.c_cflag |= B115200;
1308 break;
1309 #endif
1310 #ifdef B230400
1311 case 230400:
1312 port.c_cflag |= B230400;
1313 break;
1314 #endif
1315 #ifdef B460800
1316 case 460800:
1317 port.c_cflag |= B460800;
1318 break;
1319 #endif
1320 default:
1321 COMM_SetCommError(handle,IE_BAUDRATE);
1322 release_comm_fd( handle, fd );
1323 ERR("baudrate %ld\n",lpdcb->BaudRate);
1324 return FALSE;
1326 port.c_ispeed = port.c_ospeed;
1327 #endif
1328 bytesize=lpdcb->ByteSize;
1329 stopbits=lpdcb->StopBits;
1331 #ifdef CMSPAR
1332 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1333 #else
1334 port.c_cflag &= ~(PARENB | PARODD);
1335 #endif
1336 if (lpdcb->fParity)
1337 port.c_iflag |= INPCK;
1338 else
1339 port.c_iflag &= ~INPCK;
1340 switch (lpdcb->Parity) {
1341 case NOPARITY:
1342 break;
1343 case ODDPARITY:
1344 port.c_cflag |= (PARENB | PARODD);
1345 break;
1346 case EVENPARITY:
1347 port.c_cflag |= PARENB;
1348 break;
1349 #ifdef CMSPAR
1350 /* Linux defines mark/space (stick) parity */
1351 case MARKPARITY:
1352 port.c_cflag |= (PARENB | CMSPAR);
1353 break;
1354 case SPACEPARITY:
1355 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1356 break;
1357 #else
1358 /* try the POSIX way */
1359 case MARKPARITY:
1360 if( stopbits == ONESTOPBIT) {
1361 stopbits = TWOSTOPBITS;
1362 port.c_iflag &= ~INPCK;
1363 } else {
1364 COMM_SetCommError(handle,IE_BYTESIZE);
1365 release_comm_fd( handle, fd );
1366 ERR("Cannot set MARK Parity\n");
1367 return FALSE;
1369 break;
1370 case SPACEPARITY:
1371 if( bytesize < 8) {
1372 bytesize +=1;
1373 port.c_iflag &= ~INPCK;
1374 } else {
1375 COMM_SetCommError(handle,IE_BYTESIZE);
1376 release_comm_fd( handle, fd );
1377 ERR("Cannot set SPACE Parity\n");
1378 return FALSE;
1380 break;
1381 #endif
1382 default:
1383 COMM_SetCommError(handle,IE_BYTESIZE);
1384 release_comm_fd( handle, fd );
1385 ERR("Parity\n");
1386 return FALSE;
1390 port.c_cflag &= ~CSIZE;
1391 switch (bytesize) {
1392 case 5:
1393 port.c_cflag |= CS5;
1394 break;
1395 case 6:
1396 port.c_cflag |= CS6;
1397 break;
1398 case 7:
1399 port.c_cflag |= CS7;
1400 break;
1401 case 8:
1402 port.c_cflag |= CS8;
1403 break;
1404 default:
1405 COMM_SetCommError(handle,IE_BYTESIZE);
1406 release_comm_fd( handle, fd );
1407 ERR("ByteSize\n");
1408 return FALSE;
1411 switch (stopbits) {
1412 case ONESTOPBIT:
1413 port.c_cflag &= ~CSTOPB;
1414 break;
1415 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1416 case TWOSTOPBITS:
1417 port.c_cflag |= CSTOPB;
1418 break;
1419 default:
1420 COMM_SetCommError(handle,IE_BYTESIZE);
1421 release_comm_fd( handle, fd );
1422 ERR("StopBits\n");
1423 return FALSE;
1425 #ifdef CRTSCTS
1426 if ( lpdcb->fOutxCtsFlow ||
1427 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1430 port.c_cflag |= CRTSCTS;
1431 TRACE("CRTSCTS\n");
1433 #endif
1435 if (lpdcb->fInX)
1436 port.c_iflag |= IXON;
1437 else
1438 port.c_iflag &= ~IXON;
1439 if (lpdcb->fOutX)
1440 port.c_iflag |= IXOFF;
1441 else
1442 port.c_iflag &= ~IXOFF;
1444 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1445 ERR("tcsetattr error '%s'\n", strerror(errno));
1446 COMM_SetCommError(handle,CE_IOE);
1447 ret = FALSE;
1448 } else {
1449 COMM_SetCommError(handle,0);
1450 ret = TRUE;
1453 /* note: change DTR/RTS lines after setting the comm attributes,
1454 * so flow control does not interfere. */
1455 #ifdef TIOCM_DTR
1456 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1458 WARN("DSR/DTR flow control not supported\n");
1459 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1460 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1461 else
1462 COMM_WhackModem(fd, 0, TIOCM_DTR);
1463 #endif
1464 #ifdef TIOCM_RTS
1465 if(!lpdcb->fOutxCtsFlow )
1467 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1468 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1469 else
1470 COMM_WhackModem(fd, 0, TIOCM_RTS);
1472 #endif
1473 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1474 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1475 release_comm_fd( handle, fd );
1476 return ret;
1481 /*****************************************************************************
1482 * GetCommState (KERNEL32.@)
1484 * Fills in a device control block with information from a communications device.
1486 * RETURNS
1488 * True on success, false if the communication device handle is bad etc
1490 * BUGS
1492 * XonChar and XoffChar are not set.
1494 BOOL WINAPI GetCommState(
1495 HANDLE handle, /* [in] The communications device. */
1496 LPDCB lpdcb) /* [out] The device control block. */
1498 struct termios port;
1499 int fd,speed;
1500 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1502 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1504 fd = get_comm_fd( handle, GENERIC_READ );
1505 if (fd < 0) return FALSE;
1506 if (tcgetattr(fd, &port) == -1
1507 #ifdef TIOCMGET
1508 || ioctl(fd, TIOCMGET, &stat) == -1
1509 #endif
1511 int save_error=errno;
1512 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
1513 COMM_SetCommError(handle,CE_IOE);
1514 release_comm_fd( handle, fd );
1515 return FALSE;
1517 release_comm_fd( handle, fd );
1518 #ifndef __EMX__
1519 #ifdef CBAUD
1520 speed= (port.c_cflag & CBAUD);
1521 #else
1522 speed= (cfgetospeed(&port));
1523 #endif
1524 switch (speed) {
1525 case B0:
1526 lpdcb->BaudRate = 0;
1527 break;
1528 case B50:
1529 lpdcb->BaudRate = 50;
1530 break;
1531 case B75:
1532 lpdcb->BaudRate = 75;
1533 break;
1534 case B110:
1535 lpdcb->BaudRate = 110;
1536 break;
1537 case B134:
1538 lpdcb->BaudRate = 134;
1539 break;
1540 case B150:
1541 lpdcb->BaudRate = 150;
1542 break;
1543 case B200:
1544 lpdcb->BaudRate = 200;
1545 break;
1546 case B300:
1547 lpdcb->BaudRate = 300;
1548 break;
1549 case B600:
1550 lpdcb->BaudRate = 600;
1551 break;
1552 case B1200:
1553 lpdcb->BaudRate = 1200;
1554 break;
1555 case B1800:
1556 lpdcb->BaudRate = 1800;
1557 break;
1558 case B2400:
1559 lpdcb->BaudRate = 2400;
1560 break;
1561 case B4800:
1562 lpdcb->BaudRate = 4800;
1563 break;
1564 case B9600:
1565 lpdcb->BaudRate = 9600;
1566 break;
1567 case B19200:
1568 lpdcb->BaudRate = 19200;
1569 break;
1570 case B38400:
1571 lpdcb->BaudRate = 38400;
1572 break;
1573 #ifdef B57600
1574 case B57600:
1575 lpdcb->BaudRate = 57600;
1576 break;
1577 #endif
1578 #ifdef B115200
1579 case B115200:
1580 lpdcb->BaudRate = 115200;
1581 break;
1582 #endif
1583 #ifdef B230400
1584 case B230400:
1585 lpdcb->BaudRate = 230400;
1586 break;
1587 #endif
1588 #ifdef B460800
1589 case B460800:
1590 lpdcb->BaudRate = 460800;
1591 break;
1592 #endif
1593 default:
1594 ERR("unknown speed %x \n",speed);
1596 #endif
1597 switch (port.c_cflag & CSIZE) {
1598 case CS5:
1599 lpdcb->ByteSize = 5;
1600 break;
1601 case CS6:
1602 lpdcb->ByteSize = 6;
1603 break;
1604 case CS7:
1605 lpdcb->ByteSize = 7;
1606 break;
1607 case CS8:
1608 lpdcb->ByteSize = 8;
1609 break;
1610 default:
1611 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1614 if(port.c_iflag & INPCK)
1615 lpdcb->fParity = TRUE;
1616 else
1617 lpdcb->fParity = FALSE;
1618 #ifdef CMSPAR
1619 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1620 #else
1621 switch (port.c_cflag & (PARENB | PARODD))
1622 #endif
1624 case 0:
1625 lpdcb->Parity = NOPARITY;
1626 break;
1627 case PARENB:
1628 lpdcb->Parity = EVENPARITY;
1629 break;
1630 case (PARENB | PARODD):
1631 lpdcb->Parity = ODDPARITY;
1632 break;
1633 #ifdef CMSPAR
1634 case (PARENB | CMSPAR):
1635 lpdcb->Parity = MARKPARITY;
1636 break;
1637 case (PARENB | PARODD | CMSPAR):
1638 lpdcb->Parity = SPACEPARITY;
1639 break;
1640 #endif
1643 if (port.c_cflag & CSTOPB)
1644 if(lpdcb->ByteSize == 5)
1645 lpdcb->StopBits = ONE5STOPBITS;
1646 else
1647 lpdcb->StopBits = TWOSTOPBITS;
1648 else
1649 lpdcb->StopBits = ONESTOPBIT;
1651 lpdcb->fNull = 0;
1652 lpdcb->fBinary = 1;
1654 /* termios does not support DTR/DSR flow control */
1655 lpdcb->fOutxDsrFlow = 0;
1656 lpdcb->fDtrControl =
1657 #ifdef TIOCM_DTR
1658 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1659 #endif
1660 DTR_CONTROL_ENABLE ;
1662 #ifdef CRTSCTS
1664 if (port.c_cflag & CRTSCTS) {
1665 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1666 lpdcb->fOutxCtsFlow = 1;
1667 } else
1668 #endif
1670 lpdcb->fRtsControl =
1671 #ifdef TIOCM_RTS
1672 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1673 #endif
1674 RTS_CONTROL_ENABLE ;
1675 lpdcb->fOutxCtsFlow = 0;
1677 if (port.c_iflag & IXON)
1678 lpdcb->fInX = 1;
1679 else
1680 lpdcb->fInX = 0;
1682 if (port.c_iflag & IXOFF)
1683 lpdcb->fOutX = 1;
1684 else
1685 lpdcb->fOutX = 0;
1687 lpdcb->XonChar =
1688 lpdcb->XoffChar =
1690 lpdcb->XonLim = 10;
1691 lpdcb->XoffLim = 10;
1693 COMM_SetCommError(handle,0);
1695 TRACE("OK\n");
1697 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1698 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1699 (lpdcb->StopBits == ONESTOPBIT)?1:
1700 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1701 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1702 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1703 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1704 lpdcb->fRtsControl);
1705 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1706 lpdcb->fDtrControl);
1707 #ifdef CRTSCTS
1708 if ( lpdcb->fOutxCtsFlow ||
1709 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1711 TRACE("CRTSCTS\n");
1712 else
1714 TRACE("~CRTSCTS\n");
1715 #endif
1716 return TRUE;
1719 /*****************************************************************************
1720 * TransmitCommChar (KERNEL32.@)
1722 * Transmits a single character in front of any pending characters in the
1723 * output buffer. Usually used to send an interrupt character to a host.
1725 * RETURNS
1727 * True if the call succeeded, false if the previous command character to the
1728 * same device has not been sent yet the handle is bad etc.
1730 * BUGS
1732 * Stub.
1734 BOOL WINAPI TransmitCommChar(
1735 HANDLE hComm, /* [in] The communication device in need of a command character. */
1736 CHAR chTransmit) /* [in] The character to transmit. */
1738 DWORD w;
1739 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1741 return WriteFile( hComm, &chTransmit, 1, &w, 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 = CreateEventW(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 WCHAR lpszSerialUI[] = {
2102 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2105 /***********************************************************************
2106 * CommConfigDialogA (KERNEL32.@)
2108 * Raises a dialog that allows the user to configure a comm port.
2109 * Fills the COMMCONFIG struct with information specified by the user.
2110 * This function should call a similar routine in the COMM driver...
2112 * RETURNS
2114 * TRUE on success, FALSE on failure
2115 * If successful, the lpCommConfig structure will contain a new
2116 * configuration for the comm port, as specified by the user.
2118 * BUGS
2119 * The library with the CommConfigDialog code is never unloaded.
2120 * Perhaps this should be done when the comm port is closed?
2122 BOOL WINAPI CommConfigDialogA(
2123 LPCSTR lpszDevice, /* [in] name of communications device */
2124 HANDLE hWnd, /* [in] parent window for the dialog */
2125 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2127 FARPROC lpfnCommDialog;
2128 HMODULE hConfigModule;
2129 BOOL r = FALSE;
2131 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2133 hConfigModule = LoadLibraryW(lpszSerialUI);
2134 if(!hConfigModule)
2135 return FALSE;
2137 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2139 if(lpfnCommDialog)
2140 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2142 FreeLibrary(hConfigModule);
2144 return r;
2147 /***********************************************************************
2148 * CommConfigDialogW (KERNEL32.@)
2150 * see CommConfigDialogA for more info
2152 BOOL WINAPI CommConfigDialogW(
2153 LPCWSTR lpszDevice, /* [in] name of communications device */
2154 HANDLE hWnd, /* [in] parent window for the dialog */
2155 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2157 FARPROC lpfnCommDialog;
2158 HMODULE hConfigModule;
2159 BOOL r = FALSE;
2161 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2163 hConfigModule = LoadLibraryW(lpszSerialUI);
2164 if(!hConfigModule)
2165 return FALSE;
2167 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2169 if(lpfnCommDialog)
2170 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2172 FreeLibrary(hConfigModule);
2174 return r;
2177 /***********************************************************************
2178 * GetCommConfig (KERNEL32.@)
2180 * Fill in the COMMCONFIG structure for the comm port hFile
2182 * RETURNS
2184 * TRUE on success, FALSE on failure
2185 * If successful, lpCommConfig contains the comm port configuration.
2187 * BUGS
2190 BOOL WINAPI GetCommConfig(
2191 HANDLE hFile, /* [in] The communications device. */
2192 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2193 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2194 afterwards the number of bytes copied to the buffer or
2195 the needed size of the buffer. */
2197 BOOL r;
2199 TRACE("(%p %p)\n",hFile,lpCommConfig);
2201 if(lpCommConfig == NULL)
2202 return FALSE;
2203 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2204 *lpdwSize = sizeof(COMMCONFIG);
2205 if(r)
2206 return FALSE;
2208 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2209 lpCommConfig->wVersion = 1;
2210 lpCommConfig->wReserved = 0;
2211 r = GetCommState(hFile,&lpCommConfig->dcb);
2212 lpCommConfig->dwProviderSubType = PST_RS232;
2213 lpCommConfig->dwProviderOffset = 0;
2214 lpCommConfig->dwProviderSize = 0;
2216 return r;
2219 /***********************************************************************
2220 * SetCommConfig (KERNEL32.@)
2222 * Sets the configuration of the communications device.
2224 * RETURNS
2226 * True on success, false if the handle was bad is not a communications device.
2228 BOOL WINAPI SetCommConfig(
2229 HANDLE hFile, /* [in] The communications device. */
2230 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2231 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2233 TRACE("(%p %p)\n",hFile,lpCommConfig);
2234 return SetCommState(hFile,&lpCommConfig->dcb);
2237 /***********************************************************************
2238 * SetDefaultCommConfigA (KERNEL32.@)
2240 * Initializes the default configuration for the specified communication
2241 * device. (ascii)
2243 * RETURNS
2245 * True if the device was found and the defaults set, false otherwise
2247 BOOL WINAPI SetDefaultCommConfigW(
2248 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2249 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2250 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2252 FARPROC lpfnSetDefaultCommConfig;
2253 HMODULE hConfigModule;
2254 BOOL r = FALSE;
2256 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2258 hConfigModule = LoadLibraryW(lpszSerialUI);
2259 if(!hConfigModule)
2260 return r;
2262 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2263 if (lpfnSetDefaultCommConfig)
2264 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2266 FreeLibrary(hConfigModule);
2268 return r;
2272 /***********************************************************************
2273 * SetDefaultCommConfigW (KERNEL32.@)
2275 * Initializes the default configuration for the specified
2276 * communication device. (unicode)
2278 * RETURNS
2281 BOOL WINAPI SetDefaultCommConfigA(
2282 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2283 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2284 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2286 BOOL r;
2287 LPWSTR lpDeviceW = NULL;
2288 DWORD len;
2290 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2292 if (lpszDevice)
2294 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2295 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2296 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2298 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2299 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2300 return r;
2304 /***********************************************************************
2305 * GetDefaultCommConfigW (KERNEL32.@)
2307 * Acquires the default configuration of the specified communication device. (unicode)
2309 * RETURNS
2311 * True on successful reading of the default configuration,
2312 * if the device is not found or the buffer is too small.
2314 BOOL WINAPI GetDefaultCommConfigW(
2315 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2316 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2317 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2318 afterwards the number of bytes copied to the buffer or
2319 the needed size of the buffer. */
2321 LPDCB lpdcb = &(lpCC->dcb);
2322 WCHAR temp[40];
2323 static const WCHAR comW[] = {'C','O','M',0};
2324 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2326 if (strncmpiW(lpszName,comW,3)) {
2327 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2328 return FALSE;
2331 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2332 if (*lpdwSize < sizeof(COMMCONFIG)) {
2333 *lpdwSize = sizeof(COMMCONFIG);
2334 return FALSE;
2337 *lpdwSize = sizeof(COMMCONFIG);
2339 lpCC->dwSize = sizeof(COMMCONFIG);
2340 lpCC->wVersion = 1;
2341 lpCC->dwProviderSubType = PST_RS232;
2342 lpCC->dwProviderOffset = 0L;
2343 lpCC->dwProviderSize = 0L;
2345 sprintfW( temp, formatW, lpszName[3]);
2346 FIXME("setting %s as default\n", debugstr_w(temp));
2348 return BuildCommDCBW( temp, lpdcb);
2351 /**************************************************************************
2352 * GetDefaultCommConfigA (KERNEL32.@)
2354 * Acquires the default configuration of the specified communication device. (ascii)
2356 * RETURNS
2358 * True on successful reading of the default configuration,
2359 * if the device is not found or the buffer is too small.
2361 BOOL WINAPI GetDefaultCommConfigA(
2362 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2363 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2364 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2365 afterwards the number of bytes copied to the buffer or
2366 the needed size of the buffer. */
2368 BOOL ret = FALSE;
2369 UNICODE_STRING lpszNameW;
2371 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2372 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2373 else lpszNameW.Buffer = NULL;
2375 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2377 RtlFreeUnicodeString(&lpszNameW);
2378 return ret;