Fix a regression in IE where the Favourites menu didn't appear
[wine/testsucceed.git] / dlls / kernel / comm.c
blob2d570a9762ea3d51d3ad880120e612874a81e4ee
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 #ifdef HAVE_SYS_STAT_H
69 # include <sys/stat.h>
70 #endif
71 #ifdef HAVE_SYS_FILIO_H
72 # include <sys/filio.h>
73 #endif
74 #ifdef HAVE_SYS_IOCTL_H
75 #include <sys/ioctl.h>
76 #endif
77 #ifdef HAVE_UNISTD_H
78 # include <unistd.h>
79 #endif
80 #ifdef HAVE_SYS_POLL_H
81 # include <sys/poll.h>
82 #endif
83 #ifdef HAVE_SYS_MODEM_H
84 # include <sys/modem.h>
85 #endif
86 #ifdef HAVE_SYS_STRTIO_H
87 # include <sys/strtio.h>
88 #endif
90 #define NONAMELESSUNION
91 #define NONAMELESSSTRUCT
92 #include "ntstatus.h"
93 #include "windef.h"
94 #include "winbase.h"
95 #include "winerror.h"
97 #include "thread.h"
98 #include "wine/server.h"
99 #include "wine/unicode.h"
101 #include "wine/debug.h"
103 #ifdef HAVE_LINUX_SERIAL_H
104 #include <linux/serial.h>
105 #endif
107 WINE_DEFAULT_DEBUG_CHANNEL(comm);
109 /* retrieve the Unix handle corresponding to a comm handle */
110 static int get_comm_fd( HANDLE handle, DWORD access )
112 int fd, ret;
114 ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
115 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
116 return fd;
119 /* release the Unix handle returned by get_comm_fd */
120 static inline void release_comm_fd( HANDLE handle, int fd )
122 wine_server_release_fd( handle, fd );
126 /***********************************************************************
127 * Asynchronous I/O for asynchronous wait requests *
130 typedef struct async_commio
132 HANDLE handle;
133 PIO_APC_ROUTINE apc_internal;
134 int type;
135 char* buffer;
136 int fd;
137 } async_commio;
139 /***********************************************************************/
141 #if !defined(TIOCINQ) && defined(FIONREAD)
142 #define TIOCINQ FIONREAD
143 #endif
145 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
147 #ifdef TIOCMGET
148 unsigned int mstat, okay;
149 okay = ioctl(fd, TIOCMGET, &mstat);
150 if (okay) return okay;
151 if (andy) mstat &= andy;
152 mstat |= orrie;
153 return ioctl(fd, TIOCMSET, &mstat);
154 #else
155 return 0;
156 #endif
159 /***********************************************************************
160 * COMM_Parse* (Internal)
162 * The following COMM_Parse* functions are used by the BuildCommDCB
163 * functions to help parse the various parts of the device control string.
165 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
167 static const WCHAR comW[] = {'C','O','M',0};
169 /* The device control string may optionally start with "COMx" followed
170 by an optional ':' and spaces. */
171 if(!strncmpiW(ptr, comW, 3))
173 ptr += 3;
175 /* Allow any com port above 0 as Win 9x does (NT only allows
176 values for com ports which are actually present) */
177 if(*ptr < '1' || *ptr > '9')
178 return NULL;
180 /* Advance pointer past port number */
181 while(*ptr >= '0' && *ptr <= '9') ptr++;
183 /* The com port number must be followed by a ':' or ' ' */
184 if(*ptr != ':' && *ptr != ' ')
185 return NULL;
187 /* Advance pointer to beginning of next parameter */
188 while(*ptr == ' ') ptr++;
189 if(*ptr == ':')
191 ptr++;
192 while(*ptr == ' ') ptr++;
195 /* The device control string must not start with a space. */
196 else if(*ptr == ' ')
197 return NULL;
199 return ptr;
202 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
204 if(*ptr < '0' || *ptr > '9') return NULL;
205 *lpnumber = strtoulW(ptr, NULL, 10);
206 while(*ptr >= '0' && *ptr <= '9') ptr++;
207 return ptr;
210 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
212 /* Contrary to what you might expect, Windows only sets the Parity
213 member of DCB and not fParity even when parity is specified in the
214 device control string */
216 switch(toupperW(*ptr++))
218 case 'E':
219 *lpparity = EVENPARITY;
220 break;
221 case 'M':
222 *lpparity = MARKPARITY;
223 break;
224 case 'N':
225 *lpparity = NOPARITY;
226 break;
227 case 'O':
228 *lpparity = ODDPARITY;
229 break;
230 case 'S':
231 *lpparity = SPACEPARITY;
232 break;
233 default:
234 return NULL;
237 return ptr;
240 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
242 DWORD temp;
244 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
245 return NULL;
247 if(temp >= 5 && temp <= 8)
249 *lpbytesize = temp;
250 return ptr;
252 else
253 return NULL;
256 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
258 DWORD temp;
259 static const WCHAR stopbits15W[] = {'1','.','5',0};
261 if(!strncmpW(stopbits15W, ptr, 3))
263 ptr += 3;
264 *lpstopbits = ONE5STOPBITS;
266 else
268 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
269 return NULL;
271 if(temp == 1)
272 *lpstopbits = ONESTOPBIT;
273 else if(temp == 2)
274 *lpstopbits = TWOSTOPBITS;
275 else
276 return NULL;
279 return ptr;
282 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
284 static const WCHAR onW[] = {'o','n',0};
285 static const WCHAR offW[] = {'o','f','f',0};
287 if(!strncmpiW(onW, ptr, 2))
289 ptr += 2;
290 *lponoff = 1;
292 else if(!strncmpiW(offW, ptr, 3))
294 ptr += 3;
295 *lponoff = 0;
297 else
298 return NULL;
300 return ptr;
303 /***********************************************************************
304 * COMM_BuildOldCommDCB (Internal)
306 * Build a DCB using the old style settings string eg: "96,n,8,1"
308 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
310 WCHAR last = 0;
312 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
313 return FALSE;
315 switch(lpdcb->BaudRate)
317 case 11:
318 case 30:
319 case 60:
320 lpdcb->BaudRate *= 10;
321 break;
322 case 12:
323 case 24:
324 case 48:
325 case 96:
326 lpdcb->BaudRate *= 100;
327 break;
328 case 19:
329 lpdcb->BaudRate = 19200;
330 break;
333 while(*device == ' ') device++;
334 if(*device++ != ',') return FALSE;
335 while(*device == ' ') device++;
337 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
338 return FALSE;
340 while(*device == ' ') device++;
341 if(*device++ != ',') return FALSE;
342 while(*device == ' ') device++;
344 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
345 return FALSE;
347 while(*device == ' ') device++;
348 if(*device++ != ',') return FALSE;
349 while(*device == ' ') device++;
351 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
352 return FALSE;
354 /* The last parameter for flow control is optional. */
355 while(*device == ' ') device++;
356 if(*device == ',')
358 device++;
359 while(*device == ' ') device++;
360 if(*device) last = toupperW(*device++);
361 while(*device == ' ') device++;
364 /* Win NT sets the flow control members based on (or lack of) the last
365 parameter. Win 9x does not set these members. */
366 switch(last)
368 case 0:
369 lpdcb->fInX = FALSE;
370 lpdcb->fOutX = FALSE;
371 lpdcb->fOutxCtsFlow = FALSE;
372 lpdcb->fOutxDsrFlow = FALSE;
373 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
374 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
375 break;
376 case 'X':
377 lpdcb->fInX = TRUE;
378 lpdcb->fOutX = TRUE;
379 lpdcb->fOutxCtsFlow = FALSE;
380 lpdcb->fOutxDsrFlow = FALSE;
381 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
382 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
383 break;
384 case 'P':
385 lpdcb->fInX = FALSE;
386 lpdcb->fOutX = FALSE;
387 lpdcb->fOutxCtsFlow = TRUE;
388 lpdcb->fOutxDsrFlow = TRUE;
389 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
390 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
391 break;
392 default:
393 return FALSE;
396 /* This should be the end of the string. */
397 if(*device) return FALSE;
399 return TRUE;
402 /***********************************************************************
403 * COMM_BuildNewCommDCB (Internal)
405 * Build a DCB using the new style settings string.
406 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
408 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
410 DWORD temp;
411 BOOL baud = FALSE, stop = FALSE;
412 static const WCHAR baudW[] = {'b','a','u','d','=',0};
413 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
414 static const WCHAR dataW[] = {'d','a','t','a','=',0};
415 static const WCHAR stopW[] = {'s','t','o','p','=',0};
416 static const WCHAR toW[] = {'t','o','=',0};
417 static const WCHAR xonW[] = {'x','o','n','=',0};
418 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
419 static const WCHAR octsW[] = {'o','c','t','s','=',0};
420 static const WCHAR dtrW[] = {'d','t','r','=',0};
421 static const WCHAR rtsW[] = {'r','t','s','=',0};
422 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
424 while(*device)
426 while(*device == ' ') device++;
428 if(!strncmpiW(baudW, device, 5))
430 baud = TRUE;
432 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
433 return FALSE;
435 else if(!strncmpiW(parityW, device, 7))
437 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
438 return FALSE;
440 else if(!strncmpiW(dataW, device, 5))
442 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
443 return FALSE;
445 else if(!strncmpiW(stopW, device, 5))
447 stop = TRUE;
449 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
450 return FALSE;
452 else if(!strncmpiW(toW, device, 3))
454 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
455 return FALSE;
457 lptimeouts->ReadIntervalTimeout = 0;
458 lptimeouts->ReadTotalTimeoutMultiplier = 0;
459 lptimeouts->ReadTotalTimeoutConstant = 0;
460 lptimeouts->WriteTotalTimeoutMultiplier = 0;
461 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
463 else if(!strncmpiW(xonW, device, 4))
465 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
466 return FALSE;
468 lpdcb->fOutX = temp;
469 lpdcb->fInX = temp;
471 else if(!strncmpiW(odsrW, device, 5))
473 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
474 return FALSE;
476 lpdcb->fOutxDsrFlow = temp;
478 else if(!strncmpiW(octsW, device, 5))
480 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
481 return FALSE;
483 lpdcb->fOutxCtsFlow = temp;
485 else if(!strncmpiW(dtrW, device, 4))
487 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
488 return FALSE;
490 lpdcb->fDtrControl = temp;
492 else if(!strncmpiW(rtsW, device, 4))
494 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
495 return FALSE;
497 lpdcb->fRtsControl = temp;
499 else if(!strncmpiW(idsrW, device, 5))
501 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
502 return FALSE;
504 /* Win NT sets the fDsrSensitivity member based on the
505 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
506 lpdcb->fDsrSensitivity = temp;
508 else
509 return FALSE;
511 /* After the above parsing, the next character (if not the end of
512 the string) should be a space */
513 if(*device && *device != ' ')
514 return FALSE;
517 /* If stop bits were not specified, a default is always supplied. */
518 if(!stop)
520 if(baud && lpdcb->BaudRate == 110)
521 lpdcb->StopBits = TWOSTOPBITS;
522 else
523 lpdcb->StopBits = ONESTOPBIT;
526 return TRUE;
529 /**************************************************************************
530 * BuildCommDCBA (KERNEL32.@)
532 * Updates a device control block data structure with values from an
533 * ascii device control string. The device control string has two forms
534 * normal and extended, it must be exclusively in one or the other form.
536 * RETURNS
538 * True on success, false on a malformed control string.
540 BOOL WINAPI BuildCommDCBA(
541 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
542 LPDCB lpdcb) /* [out] The device control block to be updated. */
544 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
547 /**************************************************************************
548 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
550 * Updates a device control block data structure with values from an
551 * ascii device control string. Taking timeout values from a timeouts
552 * struct if desired by the control string.
554 * RETURNS
556 * True on success, false bad handles etc.
558 BOOL WINAPI BuildCommDCBAndTimeoutsA(
559 LPCSTR device, /* [in] The ascii device control string. */
560 LPDCB lpdcb, /* [out] The device control block to be updated. */
561 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
563 BOOL ret = FALSE;
564 UNICODE_STRING deviceW;
566 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
567 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
568 else deviceW.Buffer = NULL;
570 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
572 RtlFreeUnicodeString(&deviceW);
573 return ret;
576 /**************************************************************************
577 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
579 * Updates a device control block data structure with values from a
580 * unicode device control string. Taking timeout values from a timeouts
581 * struct if desired by the control string.
583 * RETURNS
585 * True on success, false bad handles etc
587 BOOL WINAPI BuildCommDCBAndTimeoutsW(
588 LPCWSTR devid, /* [in] The unicode device control string. */
589 LPDCB lpdcb, /* [out] The device control block to be updated. */
590 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
592 DCB dcb;
593 COMMTIMEOUTS timeouts;
594 BOOL result;
595 LPCWSTR ptr = devid;
597 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
599 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
600 lpdcb->DCBlength = sizeof(DCB);
602 /* Make a copy of the original data structures to work with since if
603 if there is an error in the device control string the originals
604 should not be modified (except possibly DCBlength) */
605 memcpy(&dcb, lpdcb, sizeof(DCB));
606 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
608 ptr = COMM_ParseStart(ptr);
610 if(ptr == NULL)
611 result = FALSE;
612 else if(strchrW(ptr, ','))
613 result = COMM_BuildOldCommDCB(ptr, &dcb);
614 else
615 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
617 if(result)
619 memcpy(lpdcb, &dcb, sizeof(DCB));
620 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
621 return TRUE;
623 else
625 WARN("Invalid device control string: %s\n", debugstr_w(devid));
626 SetLastError(ERROR_INVALID_PARAMETER);
627 return FALSE;
631 /**************************************************************************
632 * BuildCommDCBW (KERNEL32.@)
634 * Updates a device control block structure with values from an
635 * unicode device control string. The device control string has two forms
636 * normal and extended, it must be exclusively in one or the other form.
638 * RETURNS
640 * True on success, false on a malformed control string.
642 BOOL WINAPI BuildCommDCBW(
643 LPCWSTR devid, /* [in] The unicode device control string. */
644 LPDCB lpdcb) /* [out] The device control block to be updated. */
646 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
649 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
651 DWORD ret;
653 SERVER_START_REQ( set_serial_info )
655 req->handle = handle;
656 req->flags = SERIALINFO_SET_ERROR;
657 req->commerror = error;
658 ret = !wine_server_call_err( req );
660 SERVER_END_REQ;
661 return ret;
664 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
666 DWORD ret;
668 if(!lperror)
669 return FALSE;
671 SERVER_START_REQ( get_serial_info )
673 req->handle = handle;
674 ret = !wine_server_call_err( req );
675 *lperror = reply->commerror;
677 SERVER_END_REQ;
679 return ret;
682 /*****************************************************************************
683 * SetCommBreak (KERNEL32.@)
685 * Halts the transmission of characters to a communications device.
687 * RETURNS
689 * True on success, and false if the communications device could not be found,
690 * the control is not supported.
692 * BUGS
694 * Only TIOCSBRK and TIOCCBRK are supported.
696 BOOL WINAPI SetCommBreak(
697 HANDLE handle) /* [in] The communications device to suspend. */
699 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
700 int fd,result;
702 fd = get_comm_fd( handle, GENERIC_READ );
703 if(fd<0) return FALSE;
704 result = ioctl(fd,TIOCSBRK,0);
705 release_comm_fd( handle, fd );
706 if (result ==-1)
708 TRACE("ioctl failed\n");
709 SetLastError(ERROR_NOT_SUPPORTED);
710 return FALSE;
712 return TRUE;
713 #else
714 FIXME("ioctl not available\n");
715 SetLastError(ERROR_NOT_SUPPORTED);
716 return FALSE;
717 #endif
720 /*****************************************************************************
721 * ClearCommBreak (KERNEL32.@)
723 * Resumes character transmission from a communication device.
725 * RETURNS
727 * True on success and false if the communications device could not be found.
729 * BUGS
731 * Only TIOCSBRK and TIOCCBRK are supported.
733 BOOL WINAPI ClearCommBreak(
734 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
736 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
737 int fd,result;
739 fd = get_comm_fd( handle, GENERIC_READ );
740 if(fd<0) return FALSE;
741 result = ioctl(fd,TIOCCBRK,0);
742 release_comm_fd( handle, fd );
743 if (result ==-1)
745 TRACE("ioctl failed\n");
746 SetLastError(ERROR_NOT_SUPPORTED);
747 return FALSE;
749 return TRUE;
750 #else
751 FIXME("ioctl not available\n");
752 SetLastError(ERROR_NOT_SUPPORTED);
753 return FALSE;
754 #endif
757 /*****************************************************************************
758 * EscapeCommFunction (KERNEL32.@)
760 * Directs a communication device to perform an extended function.
762 * RETURNS
764 * True or requested data on successful completion of the command,
765 * false if the device is not present cannot execute the command
766 * or the command failed.
768 BOOL WINAPI EscapeCommFunction(
769 HANDLE handle, /* [in] The communication device to perform the extended function. */
770 UINT nFunction) /* [in] The extended function to be performed. */
772 int fd,direct=FALSE,result=FALSE;
773 struct termios port;
775 TRACE("handle %p, function=%d\n", handle, nFunction);
776 fd = get_comm_fd( handle, GENERIC_READ );
777 if(fd<0) return FALSE;
779 if (tcgetattr(fd,&port) == -1) {
780 COMM_SetCommError(handle,CE_IOE);
781 release_comm_fd( handle, fd );
782 return FALSE;
785 switch (nFunction) {
786 case RESETDEV:
787 TRACE("\n");
788 break;
790 case CLRDTR:
791 TRACE("CLRDTR\n");
792 #ifdef TIOCM_DTR
793 direct=TRUE;
794 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
795 break;
796 #endif
798 case CLRRTS:
799 TRACE("CLRRTS\n");
800 #ifdef TIOCM_RTS
801 direct=TRUE;
802 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
803 break;
804 #endif
806 case SETDTR:
807 TRACE("SETDTR\n");
808 #ifdef TIOCM_DTR
809 direct=TRUE;
810 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
811 break;
812 #endif
814 case SETRTS:
815 TRACE("SETRTS\n");
816 #ifdef TIOCM_RTS
817 direct=TRUE;
818 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
819 break;
820 #endif
822 case SETXOFF:
823 TRACE("SETXOFF\n");
824 port.c_iflag |= IXOFF;
825 break;
827 case SETXON:
828 TRACE("SETXON\n");
829 port.c_iflag |= IXON;
830 break;
831 case SETBREAK:
832 TRACE("setbreak\n");
833 #ifdef TIOCSBRK
834 direct=TRUE;
835 result = ioctl(fd,TIOCSBRK,0);
836 break;
837 #endif
838 case CLRBREAK:
839 TRACE("clrbreak\n");
840 #ifdef TIOCSBRK
841 direct=TRUE;
842 result = ioctl(fd,TIOCCBRK,0);
843 break;
844 #endif
845 default:
846 WARN("(handle=%p,nFunction=%d): Unknown function\n",
847 handle, nFunction);
848 break;
851 if (!direct)
852 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
853 release_comm_fd( handle, fd );
854 COMM_SetCommError(handle,CE_IOE);
855 return FALSE;
856 } else
857 result= TRUE;
858 else
860 if (result == -1)
862 result= FALSE;
863 COMM_SetCommError(handle,CE_IOE);
865 else
866 result = TRUE;
868 release_comm_fd( handle, fd );
869 return result;
872 /********************************************************************
873 * PurgeComm (KERNEL32.@)
875 * Terminates pending operations and/or discards buffers on a
876 * communication resource.
878 * RETURNS
880 * True on success and false if the communications handle is bad.
882 BOOL WINAPI PurgeComm(
883 HANDLE handle, /* [in] The communication resource to be purged. */
884 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
886 int fd;
888 TRACE("handle %p, flags %lx\n", handle, flags);
890 fd = get_comm_fd( handle, GENERIC_READ );
891 if(fd<0) return FALSE;
894 ** not exactly sure how these are different
895 ** Perhaps if we had our own internal queues, one flushes them
896 ** and the other flushes the kernel's buffers.
898 if(flags&PURGE_TXABORT)
899 tcflush(fd,TCOFLUSH);
900 if(flags&PURGE_RXABORT)
901 tcflush(fd,TCIFLUSH);
902 if(flags&PURGE_TXCLEAR)
903 tcflush(fd,TCOFLUSH);
904 if(flags&PURGE_RXCLEAR)
905 tcflush(fd,TCIFLUSH);
906 release_comm_fd( handle, fd );
908 return 1;
911 /*****************************************************************************
912 * ClearCommError (KERNEL32.@)
914 * Enables further I/O operations on a communications resource after
915 * supplying error and current status information.
917 * RETURNS
919 * True on success, false if the communication resource handle is bad.
921 BOOL WINAPI ClearCommError(
922 HANDLE handle, /* [in] The communication resource with the error. */
923 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
924 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
926 int fd;
928 fd=get_comm_fd( handle, GENERIC_READ );
929 if(0>fd) return FALSE;
931 if (lpStat)
933 lpStat->fCtsHold = 0;
934 lpStat->fDsrHold = 0;
935 lpStat->fRlsdHold = 0;
936 lpStat->fXoffHold = 0;
937 lpStat->fXoffSent = 0;
938 lpStat->fEof = 0;
939 lpStat->fTxim = 0;
940 lpStat->fReserved = 0;
942 #ifdef TIOCOUTQ
943 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
944 WARN("ioctl returned error\n");
945 #else
946 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
947 #endif
949 #ifdef TIOCINQ
950 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
951 WARN("ioctl returned error\n");
952 #endif
954 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
955 handle, lpStat->cbInQue, lpStat->cbOutQue);
958 release_comm_fd( handle, fd );
960 COMM_GetCommError(handle, errors);
961 COMM_SetCommError(handle, 0);
963 return TRUE;
966 /*****************************************************************************
967 * SetupComm (KERNEL32.@)
969 * Called after CreateFile to hint to the communication resource to use
970 * specified sizes for input and output buffers rather than the default values.
972 * RETURNS
974 * True if successful, false if the communications resource handle is bad.
976 * BUGS
978 * Stub.
980 BOOL WINAPI SetupComm(
981 HANDLE handle, /* [in] The just created communication resource handle. */
982 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
983 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
985 int fd;
987 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
988 fd=get_comm_fd( handle, GENERIC_READ );
989 if(0>fd) return FALSE;
990 release_comm_fd( handle, fd );
991 return TRUE;
994 /*****************************************************************************
995 * GetCommMask (KERNEL32.@)
997 * Obtain the events associated with a communication device that will cause
998 * a call WaitCommEvent to return.
1000 * RETURNS
1002 * True on success, fail on bad device handle etc.
1004 BOOL WINAPI GetCommMask(
1005 HANDLE handle, /* [in] The communications device. */
1006 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1008 BOOL ret;
1010 TRACE("handle %p, mask %p\n", handle, evtmask);
1012 SERVER_START_REQ( get_serial_info )
1014 req->handle = handle;
1015 if ((ret = !wine_server_call_err( req )))
1017 if (evtmask) *evtmask = reply->eventmask;
1020 SERVER_END_REQ;
1021 return ret;
1024 /*****************************************************************************
1025 * SetCommMask (KERNEL32.@)
1027 * There be some things we need to hear about yon there communications device.
1028 * (Set which events associated with a communication device should cause
1029 * a call WaitCommEvent to return.)
1031 * RETURNS
1033 * True on success, false on bad handle etc.
1035 BOOL WINAPI SetCommMask(
1036 HANDLE handle, /* [in] The communications device. */
1037 DWORD evtmask) /* [in] The events that are to be monitored. */
1039 BOOL ret;
1041 TRACE("handle %p, mask %lx\n", handle, evtmask);
1043 SERVER_START_REQ( set_serial_info )
1045 req->handle = handle;
1046 req->flags = SERIALINFO_SET_MASK;
1047 req->eventmask = evtmask;
1048 ret = !wine_server_call_err( req );
1050 SERVER_END_REQ;
1051 return ret;
1054 /*****************************************************************************
1055 * SetCommState (KERNEL32.@)
1057 * Re-initializes all hardware and control settings of a communications device,
1058 * with values from a device control block without effecting the input and output
1059 * queues.
1061 * RETURNS
1063 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1065 BOOL WINAPI SetCommState(
1066 HANDLE handle, /* [in] The communications device. */
1067 LPDCB lpdcb) /* [out] The device control block. */
1069 struct termios port;
1070 int fd, bytesize, stopbits;
1071 BOOL ret;
1073 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1074 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1075 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1076 (lpdcb->StopBits == ONESTOPBIT)?1:
1077 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1078 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1079 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1080 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1081 lpdcb->fRtsControl);
1082 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1083 lpdcb->fDtrControl);
1086 fd = get_comm_fd( handle, GENERIC_READ );
1087 if (fd < 0) return FALSE;
1089 if ((tcgetattr(fd,&port)) == -1) {
1090 int save_error = errno;
1091 COMM_SetCommError(handle,CE_IOE);
1092 release_comm_fd( handle, fd );
1093 ERR("tcgetattr error '%s'\n", strerror(save_error));
1094 return FALSE;
1097 port.c_cc[VMIN] = 0;
1098 port.c_cc[VTIME] = 1;
1100 #ifdef IMAXBEL
1101 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1102 #else
1103 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1104 #endif
1105 port.c_iflag |= (IGNBRK);
1107 port.c_oflag &= ~(OPOST);
1109 port.c_cflag &= ~(HUPCL);
1110 port.c_cflag |= CLOCAL | CREAD;
1112 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1113 port.c_lflag |= NOFLSH;
1115 #ifdef CBAUD
1116 port.c_cflag &= ~CBAUD;
1117 switch (lpdcb->BaudRate) {
1118 case 0:
1119 port.c_cflag |= B0;
1120 break;
1121 case 50:
1122 port.c_cflag |= B50;
1123 break;
1124 case 75:
1125 port.c_cflag |= B75;
1126 break;
1127 case 110:
1128 case CBR_110:
1129 port.c_cflag |= B110;
1130 break;
1131 case 134:
1132 port.c_cflag |= B134;
1133 break;
1134 case 150:
1135 port.c_cflag |= B150;
1136 break;
1137 case 200:
1138 port.c_cflag |= B200;
1139 break;
1140 case 300:
1141 case CBR_300:
1142 port.c_cflag |= B300;
1143 break;
1144 case 600:
1145 case CBR_600:
1146 port.c_cflag |= B600;
1147 break;
1148 case 1200:
1149 case CBR_1200:
1150 port.c_cflag |= B1200;
1151 break;
1152 case 1800:
1153 port.c_cflag |= B1800;
1154 break;
1155 case 2400:
1156 case CBR_2400:
1157 port.c_cflag |= B2400;
1158 break;
1159 case 4800:
1160 case CBR_4800:
1161 port.c_cflag |= B4800;
1162 break;
1163 case 9600:
1164 case CBR_9600:
1165 port.c_cflag |= B9600;
1166 break;
1167 case 19200:
1168 case CBR_19200:
1169 port.c_cflag |= B19200;
1170 break;
1171 case 38400:
1172 case CBR_38400:
1173 port.c_cflag |= B38400;
1174 break;
1175 #ifdef B57600
1176 case 57600:
1177 port.c_cflag |= B57600;
1178 break;
1179 #endif
1180 #ifdef B115200
1181 case 115200:
1182 port.c_cflag |= B115200;
1183 break;
1184 #endif
1185 #ifdef B230400
1186 case 230400:
1187 port.c_cflag |= B230400;
1188 break;
1189 #endif
1190 #ifdef B460800
1191 case 460800:
1192 port.c_cflag |= B460800;
1193 break;
1194 #endif
1195 default:
1196 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1197 { struct serial_struct nuts;
1198 int arby;
1199 ioctl(fd, TIOCGSERIAL, &nuts);
1200 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1201 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1202 arby = nuts.baud_base / nuts.custom_divisor;
1203 nuts.flags &= ~ASYNC_SPD_MASK;
1204 nuts.flags |= ASYNC_SPD_CUST;
1205 WARN("You (or a program acting at your behest) have specified\n"
1206 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1207 "which is as close as we can get by our present understanding of your\n"
1208 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1209 "has caused to your linux system can be undone with setserial \n"
1210 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1211 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1212 ioctl(fd, TIOCSSERIAL, &nuts);
1213 port.c_cflag |= B38400;
1215 break;
1216 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1219 COMM_SetCommError(handle,IE_BAUDRATE);
1220 release_comm_fd( handle, fd );
1221 ERR("baudrate %ld\n",lpdcb->BaudRate);
1222 return FALSE;
1224 #elif !defined(__EMX__)
1225 switch (lpdcb->BaudRate) {
1226 case 0:
1227 port.c_ospeed = B0;
1228 break;
1229 case 50:
1230 port.c_ospeed = B50;
1231 break;
1232 case 75:
1233 port.c_ospeed = B75;
1234 break;
1235 case 110:
1236 case CBR_110:
1237 port.c_ospeed = B110;
1238 break;
1239 case 134:
1240 port.c_ospeed = B134;
1241 break;
1242 case 150:
1243 port.c_ospeed = B150;
1244 break;
1245 case 200:
1246 port.c_ospeed = B200;
1247 break;
1248 case 300:
1249 case CBR_300:
1250 port.c_ospeed = B300;
1251 break;
1252 case 600:
1253 case CBR_600:
1254 port.c_ospeed = B600;
1255 break;
1256 case 1200:
1257 case CBR_1200:
1258 port.c_ospeed = B1200;
1259 break;
1260 case 1800:
1261 port.c_ospeed = B1800;
1262 break;
1263 case 2400:
1264 case CBR_2400:
1265 port.c_ospeed = B2400;
1266 break;
1267 case 4800:
1268 case CBR_4800:
1269 port.c_ospeed = B4800;
1270 break;
1271 case 9600:
1272 case CBR_9600:
1273 port.c_ospeed = B9600;
1274 break;
1275 case 19200:
1276 case CBR_19200:
1277 port.c_ospeed = B19200;
1278 break;
1279 case 38400:
1280 case CBR_38400:
1281 port.c_ospeed = B38400;
1282 break;
1283 #ifdef B57600
1284 case 57600:
1285 case CBR_57600:
1286 port.c_cflag |= B57600;
1287 break;
1288 #endif
1289 #ifdef B115200
1290 case 115200:
1291 case CBR_115200:
1292 port.c_cflag |= B115200;
1293 break;
1294 #endif
1295 #ifdef B230400
1296 case 230400:
1297 port.c_cflag |= B230400;
1298 break;
1299 #endif
1300 #ifdef B460800
1301 case 460800:
1302 port.c_cflag |= B460800;
1303 break;
1304 #endif
1305 default:
1306 COMM_SetCommError(handle,IE_BAUDRATE);
1307 release_comm_fd( handle, fd );
1308 ERR("baudrate %ld\n",lpdcb->BaudRate);
1309 return FALSE;
1311 port.c_ispeed = port.c_ospeed;
1312 #endif
1313 bytesize=lpdcb->ByteSize;
1314 stopbits=lpdcb->StopBits;
1316 #ifdef CMSPAR
1317 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1318 #else
1319 port.c_cflag &= ~(PARENB | PARODD);
1320 #endif
1321 if (lpdcb->fParity)
1322 port.c_iflag |= INPCK;
1323 else
1324 port.c_iflag &= ~INPCK;
1325 switch (lpdcb->Parity) {
1326 case NOPARITY:
1327 break;
1328 case ODDPARITY:
1329 port.c_cflag |= (PARENB | PARODD);
1330 break;
1331 case EVENPARITY:
1332 port.c_cflag |= PARENB;
1333 break;
1334 #ifdef CMSPAR
1335 /* Linux defines mark/space (stick) parity */
1336 case MARKPARITY:
1337 port.c_cflag |= (PARENB | CMSPAR);
1338 break;
1339 case SPACEPARITY:
1340 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1341 break;
1342 #else
1343 /* try the POSIX way */
1344 case MARKPARITY:
1345 if( stopbits == ONESTOPBIT) {
1346 stopbits = TWOSTOPBITS;
1347 port.c_iflag &= ~INPCK;
1348 } else {
1349 COMM_SetCommError(handle,IE_BYTESIZE);
1350 release_comm_fd( handle, fd );
1351 ERR("Cannot set MARK Parity\n");
1352 return FALSE;
1354 break;
1355 case SPACEPARITY:
1356 if( bytesize < 8) {
1357 bytesize +=1;
1358 port.c_iflag &= ~INPCK;
1359 } else {
1360 COMM_SetCommError(handle,IE_BYTESIZE);
1361 release_comm_fd( handle, fd );
1362 ERR("Cannot set SPACE Parity\n");
1363 return FALSE;
1365 break;
1366 #endif
1367 default:
1368 COMM_SetCommError(handle,IE_BYTESIZE);
1369 release_comm_fd( handle, fd );
1370 ERR("Parity\n");
1371 return FALSE;
1375 port.c_cflag &= ~CSIZE;
1376 switch (bytesize) {
1377 case 5:
1378 port.c_cflag |= CS5;
1379 break;
1380 case 6:
1381 port.c_cflag |= CS6;
1382 break;
1383 case 7:
1384 port.c_cflag |= CS7;
1385 break;
1386 case 8:
1387 port.c_cflag |= CS8;
1388 break;
1389 default:
1390 COMM_SetCommError(handle,IE_BYTESIZE);
1391 release_comm_fd( handle, fd );
1392 ERR("ByteSize\n");
1393 return FALSE;
1396 switch (stopbits) {
1397 case ONESTOPBIT:
1398 port.c_cflag &= ~CSTOPB;
1399 break;
1400 case ONE5STOPBITS: /* will be selected if bytesize is 5 */
1401 case TWOSTOPBITS:
1402 port.c_cflag |= CSTOPB;
1403 break;
1404 default:
1405 COMM_SetCommError(handle,IE_BYTESIZE);
1406 release_comm_fd( handle, fd );
1407 ERR("StopBits\n");
1408 return FALSE;
1410 #ifdef CRTSCTS
1411 if ( lpdcb->fOutxCtsFlow ||
1412 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1415 port.c_cflag |= CRTSCTS;
1416 TRACE("CRTSCTS\n");
1418 #endif
1420 if (lpdcb->fInX)
1421 port.c_iflag |= IXON;
1422 else
1423 port.c_iflag &= ~IXON;
1424 if (lpdcb->fOutX)
1425 port.c_iflag |= IXOFF;
1426 else
1427 port.c_iflag &= ~IXOFF;
1429 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1430 ERR("tcsetattr error '%s'\n", strerror(errno));
1431 COMM_SetCommError(handle,CE_IOE);
1432 ret = FALSE;
1433 } else {
1434 COMM_SetCommError(handle,0);
1435 ret = TRUE;
1438 /* note: change DTR/RTS lines after setting the comm attributes,
1439 * so flow control does not interfere. */
1440 #ifdef TIOCM_DTR
1441 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1443 WARN("DSR/DTR flow control not supported\n");
1444 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1445 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1446 else
1447 COMM_WhackModem(fd, 0, TIOCM_DTR);
1448 #endif
1449 #ifdef TIOCM_RTS
1450 if(!lpdcb->fOutxCtsFlow )
1452 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1453 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1454 else
1455 COMM_WhackModem(fd, 0, TIOCM_RTS);
1457 #endif
1458 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1459 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1460 release_comm_fd( handle, fd );
1461 return ret;
1466 /*****************************************************************************
1467 * GetCommState (KERNEL32.@)
1469 * Fills in a device control block with information from a communications device.
1471 * RETURNS
1473 * True on success, false if the communication device handle is bad etc
1475 * BUGS
1477 * XonChar and XoffChar are not set.
1479 BOOL WINAPI GetCommState(
1480 HANDLE handle, /* [in] The communications device. */
1481 LPDCB lpdcb) /* [out] The device control block. */
1483 struct termios port;
1484 int fd,speed;
1485 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1487 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1489 fd = get_comm_fd( handle, GENERIC_READ );
1490 if (fd < 0) return FALSE;
1491 if (tcgetattr(fd, &port) == -1
1492 #ifdef TIOCMGET
1493 || ioctl(fd, TIOCMGET, &stat) == -1
1494 #endif
1496 int save_error=errno;
1497 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
1498 COMM_SetCommError(handle,CE_IOE);
1499 release_comm_fd( handle, fd );
1500 return FALSE;
1502 release_comm_fd( handle, fd );
1503 #ifndef __EMX__
1504 #ifdef CBAUD
1505 speed= (port.c_cflag & CBAUD);
1506 #else
1507 speed= (cfgetospeed(&port));
1508 #endif
1509 switch (speed) {
1510 case B0:
1511 lpdcb->BaudRate = 0;
1512 break;
1513 case B50:
1514 lpdcb->BaudRate = 50;
1515 break;
1516 case B75:
1517 lpdcb->BaudRate = 75;
1518 break;
1519 case B110:
1520 lpdcb->BaudRate = 110;
1521 break;
1522 case B134:
1523 lpdcb->BaudRate = 134;
1524 break;
1525 case B150:
1526 lpdcb->BaudRate = 150;
1527 break;
1528 case B200:
1529 lpdcb->BaudRate = 200;
1530 break;
1531 case B300:
1532 lpdcb->BaudRate = 300;
1533 break;
1534 case B600:
1535 lpdcb->BaudRate = 600;
1536 break;
1537 case B1200:
1538 lpdcb->BaudRate = 1200;
1539 break;
1540 case B1800:
1541 lpdcb->BaudRate = 1800;
1542 break;
1543 case B2400:
1544 lpdcb->BaudRate = 2400;
1545 break;
1546 case B4800:
1547 lpdcb->BaudRate = 4800;
1548 break;
1549 case B9600:
1550 lpdcb->BaudRate = 9600;
1551 break;
1552 case B19200:
1553 lpdcb->BaudRate = 19200;
1554 break;
1555 case B38400:
1556 lpdcb->BaudRate = 38400;
1557 break;
1558 #ifdef B57600
1559 case B57600:
1560 lpdcb->BaudRate = 57600;
1561 break;
1562 #endif
1563 #ifdef B115200
1564 case B115200:
1565 lpdcb->BaudRate = 115200;
1566 break;
1567 #endif
1568 #ifdef B230400
1569 case B230400:
1570 lpdcb->BaudRate = 230400;
1571 break;
1572 #endif
1573 #ifdef B460800
1574 case B460800:
1575 lpdcb->BaudRate = 460800;
1576 break;
1577 #endif
1578 default:
1579 ERR("unknown speed %x \n",speed);
1581 #endif
1582 switch (port.c_cflag & CSIZE) {
1583 case CS5:
1584 lpdcb->ByteSize = 5;
1585 break;
1586 case CS6:
1587 lpdcb->ByteSize = 6;
1588 break;
1589 case CS7:
1590 lpdcb->ByteSize = 7;
1591 break;
1592 case CS8:
1593 lpdcb->ByteSize = 8;
1594 break;
1595 default:
1596 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1599 if(port.c_iflag & INPCK)
1600 lpdcb->fParity = TRUE;
1601 else
1602 lpdcb->fParity = FALSE;
1603 #ifdef CMSPAR
1604 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1605 #else
1606 switch (port.c_cflag & (PARENB | PARODD))
1607 #endif
1609 case 0:
1610 lpdcb->Parity = NOPARITY;
1611 break;
1612 case PARENB:
1613 lpdcb->Parity = EVENPARITY;
1614 break;
1615 case (PARENB | PARODD):
1616 lpdcb->Parity = ODDPARITY;
1617 break;
1618 #ifdef CMSPAR
1619 case (PARENB | CMSPAR):
1620 lpdcb->Parity = MARKPARITY;
1621 break;
1622 case (PARENB | PARODD | CMSPAR):
1623 lpdcb->Parity = SPACEPARITY;
1624 break;
1625 #endif
1628 if (port.c_cflag & CSTOPB)
1629 if(lpdcb->ByteSize == 5)
1630 lpdcb->StopBits = ONE5STOPBITS;
1631 else
1632 lpdcb->StopBits = TWOSTOPBITS;
1633 else
1634 lpdcb->StopBits = ONESTOPBIT;
1636 lpdcb->fNull = 0;
1637 lpdcb->fBinary = 1;
1639 /* termios does not support DTR/DSR flow control */
1640 lpdcb->fOutxDsrFlow = 0;
1641 lpdcb->fDtrControl =
1642 #ifdef TIOCM_DTR
1643 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1644 #endif
1645 DTR_CONTROL_ENABLE ;
1647 #ifdef CRTSCTS
1649 if (port.c_cflag & CRTSCTS) {
1650 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1651 lpdcb->fOutxCtsFlow = 1;
1652 } else
1653 #endif
1655 lpdcb->fRtsControl =
1656 #ifdef TIOCM_RTS
1657 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1658 #endif
1659 RTS_CONTROL_ENABLE ;
1660 lpdcb->fOutxCtsFlow = 0;
1662 if (port.c_iflag & IXON)
1663 lpdcb->fInX = 1;
1664 else
1665 lpdcb->fInX = 0;
1667 if (port.c_iflag & IXOFF)
1668 lpdcb->fOutX = 1;
1669 else
1670 lpdcb->fOutX = 0;
1672 lpdcb->XonChar =
1673 lpdcb->XoffChar =
1675 lpdcb->XonLim = 10;
1676 lpdcb->XoffLim = 10;
1678 COMM_SetCommError(handle,0);
1680 TRACE("OK\n");
1682 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1683 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1684 (lpdcb->StopBits == ONESTOPBIT)?1:
1685 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1686 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1687 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1688 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1689 lpdcb->fRtsControl);
1690 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1691 lpdcb->fDtrControl);
1692 #ifdef CRTSCTS
1693 if ( lpdcb->fOutxCtsFlow ||
1694 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1696 TRACE("CRTSCTS\n");
1697 else
1699 TRACE("~CRTSCTS\n");
1700 #endif
1701 return TRUE;
1704 /*****************************************************************************
1705 * TransmitCommChar (KERNEL32.@)
1707 * Transmits a single character in front of any pending characters in the
1708 * output buffer. Usually used to send an interrupt character to a host.
1710 * RETURNS
1712 * True if the call succeeded, false if the previous command character to the
1713 * same device has not been sent yet the handle is bad etc.
1715 * BUGS
1717 * Stub.
1719 BOOL WINAPI TransmitCommChar(
1720 HANDLE hComm, /* [in] The communication device in need of a command character. */
1721 CHAR chTransmit) /* [in] The character to transmit. */
1723 DWORD w;
1724 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1726 return WriteFile( hComm, &chTransmit, 1, &w, NULL );
1730 /*****************************************************************************
1731 * GetCommTimeouts (KERNEL32.@)
1733 * Obtains the request timeout values for the communications device.
1735 * RETURNS
1737 * True on success, false if communications device handle is bad
1738 * or the target structure is null.
1740 BOOL WINAPI GetCommTimeouts(
1741 HANDLE hComm, /* [in] The communications device. */
1742 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1744 BOOL ret;
1746 TRACE("(%p,%p)\n",hComm,lptimeouts);
1748 if(!lptimeouts)
1750 SetLastError(ERROR_INVALID_PARAMETER);
1751 return FALSE;
1754 SERVER_START_REQ( get_serial_info )
1756 req->handle = hComm;
1757 if ((ret = !wine_server_call_err( req )))
1759 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1760 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1761 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1762 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1763 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1766 SERVER_END_REQ;
1767 return ret;
1770 /*****************************************************************************
1771 * SetCommTimeouts (KERNEL32.@)
1773 * Sets the timeouts used when reading and writing data to/from COMM ports.
1775 * ReadIntervalTimeout
1776 * - converted and passes to linux kernel as c_cc[VTIME]
1777 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1778 * - used in ReadFile to calculate GetOverlappedResult's timeout
1779 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1780 * - used in WriteFile to calculate GetOverlappedResult's timeout
1782 * RETURNS
1784 * True if the timeouts were set, false otherwise.
1786 BOOL WINAPI SetCommTimeouts(
1787 HANDLE hComm, /* [in] handle of COMM device */
1788 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1790 BOOL ret;
1791 int fd;
1792 struct termios tios;
1794 TRACE("(%p,%p)\n",hComm,lptimeouts);
1796 if(!lptimeouts)
1798 SetLastError(ERROR_INVALID_PARAMETER);
1799 return FALSE;
1802 SERVER_START_REQ( set_serial_info )
1804 req->handle = hComm;
1805 req->flags = SERIALINFO_SET_TIMEOUTS;
1806 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1807 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1808 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1809 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1810 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1811 ret = !wine_server_call_err( req );
1813 SERVER_END_REQ;
1814 if (!ret) return FALSE;
1816 /* FIXME: move this stuff to the server */
1817 fd = get_comm_fd( hComm, GENERIC_READ );
1818 if (fd < 0) return FALSE;
1820 if (-1==tcgetattr(fd,&tios)) {
1821 FIXME("tcgetattr on fd %d failed!\n",fd);
1822 release_comm_fd( hComm, fd );
1823 return FALSE;
1826 /* VTIME is in 1/10 seconds */
1828 unsigned int ux_timeout;
1830 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1832 ux_timeout = 0;
1834 else
1836 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1837 if(ux_timeout == 0)
1839 ux_timeout = 1; /* must be at least some timeout */
1842 tios.c_cc[VTIME] = ux_timeout;
1845 if (-1==tcsetattr(fd,0,&tios)) {
1846 FIXME("tcsetattr on fd %d failed!\n",fd);
1847 release_comm_fd( hComm, fd );
1848 return FALSE;
1850 release_comm_fd( hComm, fd );
1851 return TRUE;
1854 /***********************************************************************
1855 * GetCommModemStatus (KERNEL32.@)
1857 * Obtains the four control register bits if supported by the hardware.
1859 * RETURNS
1861 * True if the communications handle was good and for hardware that
1862 * control register access, false otherwise.
1864 BOOL WINAPI GetCommModemStatus(
1865 HANDLE hFile, /* [in] The communications device. */
1866 LPDWORD lpModemStat) /* [out] The control register bits. */
1868 int fd,mstat, result=FALSE;
1870 *lpModemStat=0;
1871 #ifdef TIOCMGET
1872 fd = get_comm_fd( hFile, GENERIC_READ );
1873 if(fd<0)
1874 return FALSE;
1875 result = ioctl(fd, TIOCMGET, &mstat);
1876 release_comm_fd( hFile, fd );
1877 if (result == -1)
1879 WARN("ioctl failed\n");
1880 return FALSE;
1882 #ifdef TIOCM_CTS
1883 if (mstat & TIOCM_CTS)
1884 *lpModemStat |= MS_CTS_ON;
1885 #endif
1886 #ifdef TIOCM_DSR
1887 if (mstat & TIOCM_DSR)
1888 *lpModemStat |= MS_DSR_ON;
1889 #endif
1890 #ifdef TIOCM_RNG
1891 if (mstat & TIOCM_RNG)
1892 *lpModemStat |= MS_RING_ON;
1893 #endif
1894 #ifdef TIOCM_CAR
1895 /*FIXME: Not really sure about RLSD UB 990810*/
1896 if (mstat & TIOCM_CAR)
1897 *lpModemStat |= MS_RLSD_ON;
1898 #endif
1899 TRACE("%04x -> %s%s%s%s\n", mstat,
1900 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1901 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1902 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1903 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1904 return TRUE;
1905 #else
1906 return FALSE;
1907 #endif
1910 /***********************************************************************
1911 * COMM_WaitCommEventService (INTERNAL)
1913 * This function is called while the client is waiting on the
1914 * server, so we can't make any server calls here.
1916 static void WINAPI COMM_WaitCommEventService(void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1918 async_commio *commio = (async_commio*) ovp;
1920 TRACE("iosb %p\n", iosb);
1922 switch (status)
1924 case STATUS_ALERTED: /* got some new stuff */
1925 /* FIXME: detect other events */
1926 *commio->buffer = EV_RXCHAR;
1927 iosb->u.Status = STATUS_SUCCESS;
1928 break;
1929 default:
1930 iosb->u.Status = status;
1931 break;
1933 wine_server_release_fd( commio->handle, commio->fd );
1934 if ( ((LPOVERLAPPED)iosb)->hEvent != INVALID_HANDLE_VALUE )
1935 NtSetEvent( ((LPOVERLAPPED)iosb)->hEvent, NULL );
1936 HeapFree(GetProcessHeap(), 0, commio );
1940 /***********************************************************************
1941 * COMM_WaitCommEvent (INTERNAL)
1943 * This function must have an lpOverlapped.
1945 static BOOL COMM_WaitCommEvent(
1946 HANDLE hFile, /* [in] handle of comm port to wait for */
1947 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1948 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1950 int fd;
1951 async_commio* commio;
1952 NTSTATUS status;
1954 if (!lpOverlapped)
1956 SetLastError(ERROR_INVALID_PARAMETER);
1957 return FALSE;
1960 if (NtResetEvent(lpOverlapped->hEvent,NULL))
1961 return FALSE;
1963 fd = get_comm_fd( hFile, GENERIC_WRITE );
1964 if (fd < 0) return FALSE;
1966 commio = HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1967 if (!commio)
1969 release_comm_fd( hFile, fd );
1970 return FALSE;
1973 commio->handle = hFile;
1974 commio->type = ASYNC_TYPE_WAIT;
1975 commio->apc_internal = COMM_WaitCommEventService;
1976 commio->buffer = (char *)lpdwEvents;
1977 commio->fd = fd; /* FIXME */
1979 lpOverlapped->InternalHigh = 0;
1980 lpOverlapped->u.s.Offset = 0;
1981 lpOverlapped->u.s.OffsetHigh = 0;
1983 SERVER_START_REQ( register_async )
1985 req->handle = hFile;
1986 req->io_apc = COMM_WaitCommEventService;
1987 req->io_user = commio;
1988 req->io_sb = (IO_STATUS_BLOCK*)lpOverlapped;
1989 req->count = 0;
1990 status = wine_server_call( req );
1992 SERVER_END_REQ;
1994 if ( status ) SetLastError( RtlNtStatusToDosError(status) );
1995 else NtCurrentTeb()->num_async_io++;
1997 return FALSE;
2000 /***********************************************************************
2001 * WaitCommEvent (KERNEL32.@)
2003 * Wait until something interesting happens on a COMM port.
2004 * Interesting things (events) are set by calling SetCommMask before
2005 * this function is called.
2007 * RETURNS:
2008 * TRUE if successful
2009 * FALSE if failure
2011 * The set of detected events will be written to *lpdwEventMask
2012 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2014 * BUGS:
2015 * Only supports EV_RXCHAR and EV_TXEMPTY
2017 BOOL WINAPI WaitCommEvent(
2018 HANDLE hFile, /* [in] handle of comm port to wait for */
2019 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2020 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2022 OVERLAPPED ov;
2023 int ret;
2025 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2027 if(lpOverlapped)
2028 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2030 /* if there is no overlapped structure, create our own */
2031 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
2033 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2035 /* wait for the overlapped to complete */
2036 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
2037 CloseHandle(ov.hEvent);
2039 return ret;
2042 /***********************************************************************
2043 * GetCommProperties (KERNEL32.@)
2045 * This function fills in a structure with the capabilities of the
2046 * communications port driver.
2048 * RETURNS
2050 * TRUE on success, FALSE on failure
2051 * If successful, the lpCommProp structure be filled in with
2052 * properties of the comm port.
2054 BOOL WINAPI GetCommProperties(
2055 HANDLE hFile, /* [in] handle of the comm port */
2056 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2058 FIXME("(%p %p )\n",hFile,lpCommProp);
2059 if(!lpCommProp)
2060 return FALSE;
2063 * These values should be valid for LINUX's serial driver
2064 * FIXME: Perhaps they deserve an #ifdef LINUX
2066 memset(lpCommProp,0,sizeof(COMMPROP));
2067 lpCommProp->wPacketLength = 1;
2068 lpCommProp->wPacketVersion = 1;
2069 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2070 lpCommProp->dwReserved1 = 0;
2071 lpCommProp->dwMaxTxQueue = 4096;
2072 lpCommProp->dwMaxRxQueue = 4096;
2073 lpCommProp->dwMaxBaud = BAUD_115200;
2074 lpCommProp->dwProvSubType = PST_RS232;
2075 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2076 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2077 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2078 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2079 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2080 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2081 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2082 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2083 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2084 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2085 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2087 return TRUE;
2090 /***********************************************************************
2091 * FIXME:
2092 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2093 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2094 * This is dependent on the type of COMM port, but since it is doubtful
2095 * anybody will get around to implementing support for fancy serial
2096 * ports in WINE, this is hardcoded for the time being. The name of
2097 * this DLL should be stored in and read from the system registry in
2098 * the hive HKEY_LOCAL_MACHINE, key
2099 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2100 * where ???? is the port number... that is determined by PNP
2101 * The DLL should be loaded when the COMM port is opened, and closed
2102 * when the COMM port is closed. - MJM 20 June 2000
2103 ***********************************************************************/
2104 static WCHAR lpszSerialUI[] = {
2105 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2108 /***********************************************************************
2109 * CommConfigDialogA (KERNEL32.@)
2111 * Raises a dialog that allows the user to configure a comm port.
2112 * Fills the COMMCONFIG struct with information specified by the user.
2113 * This function should call a similar routine in the COMM driver...
2115 * RETURNS
2117 * TRUE on success, FALSE on failure
2118 * If successful, the lpCommConfig structure will contain a new
2119 * configuration for the comm port, as specified by the user.
2121 * BUGS
2122 * The library with the CommConfigDialog code is never unloaded.
2123 * Perhaps this should be done when the comm port is closed?
2125 BOOL WINAPI CommConfigDialogA(
2126 LPCSTR lpszDevice, /* [in] name of communications device */
2127 HWND hWnd, /* [in] parent window for the dialog */
2128 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2130 FARPROC lpfnCommDialog;
2131 HMODULE hConfigModule;
2132 BOOL r = FALSE;
2134 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2136 hConfigModule = LoadLibraryW(lpszSerialUI);
2137 if(!hConfigModule)
2138 return FALSE;
2140 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2142 if(lpfnCommDialog)
2143 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2145 FreeLibrary(hConfigModule);
2147 return r;
2150 /***********************************************************************
2151 * CommConfigDialogW (KERNEL32.@)
2153 * see CommConfigDialogA for more info
2155 BOOL WINAPI CommConfigDialogW(
2156 LPCWSTR lpszDevice, /* [in] name of communications device */
2157 HWND hWnd, /* [in] parent window for the dialog */
2158 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2160 FARPROC lpfnCommDialog;
2161 HMODULE hConfigModule;
2162 BOOL r = FALSE;
2164 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2166 hConfigModule = LoadLibraryW(lpszSerialUI);
2167 if(!hConfigModule)
2168 return FALSE;
2170 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2172 if(lpfnCommDialog)
2173 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2175 FreeLibrary(hConfigModule);
2177 return r;
2180 /***********************************************************************
2181 * GetCommConfig (KERNEL32.@)
2183 * Fill in the COMMCONFIG structure for the comm port hFile
2185 * RETURNS
2187 * TRUE on success, FALSE on failure
2188 * If successful, lpCommConfig contains the comm port configuration.
2190 * BUGS
2193 BOOL WINAPI GetCommConfig(
2194 HANDLE hFile, /* [in] The communications device. */
2195 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2196 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2197 afterwards the number of bytes copied to the buffer or
2198 the needed size of the buffer. */
2200 BOOL r;
2202 TRACE("(%p %p)\n",hFile,lpCommConfig);
2204 if(lpCommConfig == NULL)
2205 return FALSE;
2206 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2207 *lpdwSize = sizeof(COMMCONFIG);
2208 if(r)
2209 return FALSE;
2211 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2212 lpCommConfig->wVersion = 1;
2213 lpCommConfig->wReserved = 0;
2214 r = GetCommState(hFile,&lpCommConfig->dcb);
2215 lpCommConfig->dwProviderSubType = PST_RS232;
2216 lpCommConfig->dwProviderOffset = 0;
2217 lpCommConfig->dwProviderSize = 0;
2219 return r;
2222 /***********************************************************************
2223 * SetCommConfig (KERNEL32.@)
2225 * Sets the configuration of the communications device.
2227 * RETURNS
2229 * True on success, false if the handle was bad is not a communications device.
2231 BOOL WINAPI SetCommConfig(
2232 HANDLE hFile, /* [in] The communications device. */
2233 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2234 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2236 TRACE("(%p %p)\n",hFile,lpCommConfig);
2237 return SetCommState(hFile,&lpCommConfig->dcb);
2240 /***********************************************************************
2241 * SetDefaultCommConfigA (KERNEL32.@)
2243 * Initializes the default configuration for the specified communication
2244 * device. (ascii)
2246 * RETURNS
2248 * True if the device was found and the defaults set, false otherwise
2250 BOOL WINAPI SetDefaultCommConfigW(
2251 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2252 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2253 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2255 FARPROC lpfnSetDefaultCommConfig;
2256 HMODULE hConfigModule;
2257 BOOL r = FALSE;
2259 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2261 hConfigModule = LoadLibraryW(lpszSerialUI);
2262 if(!hConfigModule)
2263 return r;
2265 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2266 if (lpfnSetDefaultCommConfig)
2267 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2269 FreeLibrary(hConfigModule);
2271 return r;
2275 /***********************************************************************
2276 * SetDefaultCommConfigW (KERNEL32.@)
2278 * Initializes the default configuration for the specified
2279 * communication device. (unicode)
2281 * RETURNS
2284 BOOL WINAPI SetDefaultCommConfigA(
2285 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2286 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2287 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2289 BOOL r;
2290 LPWSTR lpDeviceW = NULL;
2291 DWORD len;
2293 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2295 if (lpszDevice)
2297 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2298 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2299 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2301 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2302 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2303 return r;
2307 /***********************************************************************
2308 * GetDefaultCommConfigW (KERNEL32.@)
2310 * Acquires the default configuration of the specified communication device. (unicode)
2312 * RETURNS
2314 * True on successful reading of the default configuration,
2315 * if the device is not found or the buffer is too small.
2317 BOOL WINAPI GetDefaultCommConfigW(
2318 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2319 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2320 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2321 afterwards the number of bytes copied to the buffer or
2322 the needed size of the buffer. */
2324 LPDCB lpdcb = &(lpCC->dcb);
2325 WCHAR temp[40];
2326 static const WCHAR comW[] = {'C','O','M',0};
2327 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2329 if (strncmpiW(lpszName,comW,3)) {
2330 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2331 return FALSE;
2334 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2335 if (*lpdwSize < sizeof(COMMCONFIG)) {
2336 *lpdwSize = sizeof(COMMCONFIG);
2337 return FALSE;
2340 *lpdwSize = sizeof(COMMCONFIG);
2342 lpCC->dwSize = sizeof(COMMCONFIG);
2343 lpCC->wVersion = 1;
2344 lpCC->dwProviderSubType = PST_RS232;
2345 lpCC->dwProviderOffset = 0L;
2346 lpCC->dwProviderSize = 0L;
2348 sprintfW( temp, formatW, lpszName[3]);
2349 FIXME("setting %s as default\n", debugstr_w(temp));
2351 return BuildCommDCBW( temp, lpdcb);
2354 /**************************************************************************
2355 * GetDefaultCommConfigA (KERNEL32.@)
2357 * Acquires the default configuration of the specified communication device. (ascii)
2359 * RETURNS
2361 * True on successful reading of the default configuration,
2362 * if the device is not found or the buffer is too small.
2364 BOOL WINAPI GetDefaultCommConfigA(
2365 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2366 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2367 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2368 afterwards the number of bytes copied to the buffer or
2369 the needed size of the buffer. */
2371 BOOL ret = FALSE;
2372 UNICODE_STRING lpszNameW;
2374 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2375 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2376 else lpszNameW.Buffer = NULL;
2378 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2380 RtlFreeUnicodeString(&lpszNameW);
2381 return ret;