Stub implementation for ReadDirectoryChangesW.
[wine/dcerpc.git] / dlls / kernel / comm.c
blob9c5dd6d2fe0585c527cfc0004524cbc7ad613365
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 "wine/unicode.h"
97 #include "thread.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 typedef struct async_commio
130 HANDLE handle;
131 PIO_APC_ROUTINE apc_internal;
132 int type;
133 char* buffer;
134 int fd;
135 } async_commio;
137 /***********************************************************************/
139 #if !defined(TIOCINQ) && defined(FIONREAD)
140 #define TIOCINQ FIONREAD
141 #endif
143 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
145 #ifdef TIOCMGET
146 unsigned int mstat, okay;
147 okay = ioctl(fd, TIOCMGET, &mstat);
148 if (okay) return okay;
149 if (andy) mstat &= andy;
150 mstat |= orrie;
151 return ioctl(fd, TIOCMSET, &mstat);
152 #else
153 return 0;
154 #endif
157 /***********************************************************************
158 * COMM_Parse* (Internal)
160 * The following COMM_Parse* functions are used by the BuildCommDCB
161 * functions to help parse the various parts of the device control string.
163 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
165 static const WCHAR comW[] = {'C','O','M',0};
167 /* The device control string may optionally start with "COMx" followed
168 by an optional ':' and spaces. */
169 if(!strncmpiW(ptr, comW, 3))
171 ptr += 3;
173 /* Allow any com port above 0 as Win 9x does (NT only allows
174 values for com ports which are actually present) */
175 if(*ptr < '1' || *ptr > '9')
176 return NULL;
178 /* Advance pointer past port number */
179 while(*ptr >= '0' && *ptr <= '9') ptr++;
181 /* The com port number must be followed by a ':' or ' ' */
182 if(*ptr != ':' && *ptr != ' ')
183 return NULL;
185 /* Advance pointer to beginning of next parameter */
186 while(*ptr == ' ') ptr++;
187 if(*ptr == ':')
189 ptr++;
190 while(*ptr == ' ') ptr++;
193 /* The device control string must not start with a space. */
194 else if(*ptr == ' ')
195 return NULL;
197 return ptr;
200 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
202 if(*ptr < '0' || *ptr > '9') return NULL;
203 *lpnumber = strtoulW(ptr, NULL, 10);
204 while(*ptr >= '0' && *ptr <= '9') ptr++;
205 return ptr;
208 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
210 /* Contrary to what you might expect, Windows only sets the Parity
211 member of DCB and not fParity even when parity is specified in the
212 device control string */
214 switch(toupperW(*ptr++))
216 case 'E':
217 *lpparity = EVENPARITY;
218 break;
219 case 'M':
220 *lpparity = MARKPARITY;
221 break;
222 case 'N':
223 *lpparity = NOPARITY;
224 break;
225 case 'O':
226 *lpparity = ODDPARITY;
227 break;
228 case 'S':
229 *lpparity = SPACEPARITY;
230 break;
231 default:
232 return NULL;
235 return ptr;
238 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
240 DWORD temp;
242 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
243 return NULL;
245 if(temp >= 5 && temp <= 8)
247 *lpbytesize = temp;
248 return ptr;
250 else
251 return NULL;
254 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
256 DWORD temp;
257 static const WCHAR stopbits15W[] = {'1','.','5',0};
259 if(!strncmpW(stopbits15W, ptr, 3))
261 ptr += 3;
262 *lpstopbits = ONE5STOPBITS;
264 else
266 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
267 return NULL;
269 if(temp == 1)
270 *lpstopbits = ONESTOPBIT;
271 else if(temp == 2)
272 *lpstopbits = TWOSTOPBITS;
273 else
274 return NULL;
277 return ptr;
280 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
282 static const WCHAR onW[] = {'o','n',0};
283 static const WCHAR offW[] = {'o','f','f',0};
285 if(!strncmpiW(onW, ptr, 2))
287 ptr += 2;
288 *lponoff = 1;
290 else if(!strncmpiW(offW, ptr, 3))
292 ptr += 3;
293 *lponoff = 0;
295 else
296 return NULL;
298 return ptr;
301 /***********************************************************************
302 * COMM_BuildOldCommDCB (Internal)
304 * Build a DCB using the old style settings string eg: "96,n,8,1"
306 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
308 WCHAR last = 0;
310 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
311 return FALSE;
313 switch(lpdcb->BaudRate)
315 case 11:
316 case 30:
317 case 60:
318 lpdcb->BaudRate *= 10;
319 break;
320 case 12:
321 case 24:
322 case 48:
323 case 96:
324 lpdcb->BaudRate *= 100;
325 break;
326 case 19:
327 lpdcb->BaudRate = 19200;
328 break;
331 while(*device == ' ') device++;
332 if(*device++ != ',') return FALSE;
333 while(*device == ' ') device++;
335 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
336 return FALSE;
338 while(*device == ' ') device++;
339 if(*device++ != ',') return FALSE;
340 while(*device == ' ') device++;
342 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
343 return FALSE;
345 while(*device == ' ') device++;
346 if(*device++ != ',') return FALSE;
347 while(*device == ' ') device++;
349 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
350 return FALSE;
352 /* The last parameter for flow control is optional. */
353 while(*device == ' ') device++;
354 if(*device == ',')
356 device++;
357 while(*device == ' ') device++;
358 if(*device) last = toupperW(*device++);
359 while(*device == ' ') device++;
362 /* Win NT sets the flow control members based on (or lack of) the last
363 parameter. Win 9x does not set these members. */
364 switch(last)
366 case 0:
367 lpdcb->fInX = FALSE;
368 lpdcb->fOutX = FALSE;
369 lpdcb->fOutxCtsFlow = FALSE;
370 lpdcb->fOutxDsrFlow = FALSE;
371 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
372 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
373 break;
374 case 'X':
375 lpdcb->fInX = TRUE;
376 lpdcb->fOutX = TRUE;
377 lpdcb->fOutxCtsFlow = FALSE;
378 lpdcb->fOutxDsrFlow = FALSE;
379 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
380 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
381 break;
382 case 'P':
383 lpdcb->fInX = FALSE;
384 lpdcb->fOutX = FALSE;
385 lpdcb->fOutxCtsFlow = TRUE;
386 lpdcb->fOutxDsrFlow = TRUE;
387 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
388 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
389 break;
390 default:
391 return FALSE;
394 /* This should be the end of the string. */
395 if(*device) return FALSE;
397 return TRUE;
400 /***********************************************************************
401 * COMM_BuildNewCommDCB (Internal)
403 * Build a DCB using the new style settings string.
404 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
406 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
408 DWORD temp;
409 BOOL baud = FALSE, stop = FALSE;
410 static const WCHAR baudW[] = {'b','a','u','d','=',0};
411 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
412 static const WCHAR dataW[] = {'d','a','t','a','=',0};
413 static const WCHAR stopW[] = {'s','t','o','p','=',0};
414 static const WCHAR toW[] = {'t','o','=',0};
415 static const WCHAR xonW[] = {'x','o','n','=',0};
416 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
417 static const WCHAR octsW[] = {'o','c','t','s','=',0};
418 static const WCHAR dtrW[] = {'d','t','r','=',0};
419 static const WCHAR rtsW[] = {'r','t','s','=',0};
420 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
422 while(*device)
424 while(*device == ' ') device++;
426 if(!strncmpiW(baudW, device, 5))
428 baud = TRUE;
430 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
431 return FALSE;
433 else if(!strncmpiW(parityW, device, 7))
435 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
436 return FALSE;
438 else if(!strncmpiW(dataW, device, 5))
440 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
441 return FALSE;
443 else if(!strncmpiW(stopW, device, 5))
445 stop = TRUE;
447 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
448 return FALSE;
450 else if(!strncmpiW(toW, device, 3))
452 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
453 return FALSE;
455 lptimeouts->ReadIntervalTimeout = 0;
456 lptimeouts->ReadTotalTimeoutMultiplier = 0;
457 lptimeouts->ReadTotalTimeoutConstant = 0;
458 lptimeouts->WriteTotalTimeoutMultiplier = 0;
459 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
461 else if(!strncmpiW(xonW, device, 4))
463 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
464 return FALSE;
466 lpdcb->fOutX = temp;
467 lpdcb->fInX = temp;
469 else if(!strncmpiW(odsrW, device, 5))
471 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
472 return FALSE;
474 lpdcb->fOutxDsrFlow = temp;
476 else if(!strncmpiW(octsW, device, 5))
478 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
479 return FALSE;
481 lpdcb->fOutxCtsFlow = temp;
483 else if(!strncmpiW(dtrW, device, 4))
485 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
486 return FALSE;
488 lpdcb->fDtrControl = temp;
490 else if(!strncmpiW(rtsW, device, 4))
492 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
493 return FALSE;
495 lpdcb->fRtsControl = temp;
497 else if(!strncmpiW(idsrW, device, 5))
499 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
500 return FALSE;
502 /* Win NT sets the fDsrSensitivity member based on the
503 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
504 lpdcb->fDsrSensitivity = temp;
506 else
507 return FALSE;
509 /* After the above parsing, the next character (if not the end of
510 the string) should be a space */
511 if(*device && *device != ' ')
512 return FALSE;
515 /* If stop bits were not specified, a default is always supplied. */
516 if(!stop)
518 if(baud && lpdcb->BaudRate == 110)
519 lpdcb->StopBits = TWOSTOPBITS;
520 else
521 lpdcb->StopBits = ONESTOPBIT;
524 return TRUE;
527 /**************************************************************************
528 * BuildCommDCBA (KERNEL32.@)
530 * Updates a device control block data structure with values from an
531 * ascii device control string. The device control string has two forms
532 * normal and extended, it must be exclusively in one or the other form.
534 * RETURNS
536 * True on success, false on a malformed control string.
538 BOOL WINAPI BuildCommDCBA(
539 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
540 LPDCB lpdcb) /* [out] The device control block to be updated. */
542 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
545 /**************************************************************************
546 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
548 * Updates a device control block data structure with values from an
549 * ascii device control string. Taking timeout values from a timeouts
550 * struct if desired by the control string.
552 * RETURNS
554 * True on success, false bad handles etc.
556 BOOL WINAPI BuildCommDCBAndTimeoutsA(
557 LPCSTR device, /* [in] The ascii device control string. */
558 LPDCB lpdcb, /* [out] The device control block to be updated. */
559 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
561 BOOL ret = FALSE;
562 UNICODE_STRING deviceW;
564 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
565 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
566 else deviceW.Buffer = NULL;
568 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
570 RtlFreeUnicodeString(&deviceW);
571 return ret;
574 /**************************************************************************
575 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
577 * Updates a device control block data structure with values from a
578 * unicode device control string. Taking timeout values from a timeouts
579 * struct if desired by the control string.
581 * RETURNS
583 * True on success, false bad handles etc
585 BOOL WINAPI BuildCommDCBAndTimeoutsW(
586 LPCWSTR devid, /* [in] The unicode device control string. */
587 LPDCB lpdcb, /* [out] The device control block to be updated. */
588 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
590 DCB dcb;
591 COMMTIMEOUTS timeouts;
592 BOOL result;
593 LPCWSTR ptr = devid;
595 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
597 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
598 lpdcb->DCBlength = sizeof(DCB);
600 /* Make a copy of the original data structures to work with since if
601 if there is an error in the device control string the originals
602 should not be modified (except possibly DCBlength) */
603 memcpy(&dcb, lpdcb, sizeof(DCB));
604 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
606 ptr = COMM_ParseStart(ptr);
608 if(ptr == NULL)
609 result = FALSE;
610 else if(strchrW(ptr, ','))
611 result = COMM_BuildOldCommDCB(ptr, &dcb);
612 else
613 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
615 if(result)
617 memcpy(lpdcb, &dcb, sizeof(DCB));
618 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
619 return TRUE;
621 else
623 WARN("Invalid device control string: %s\n", debugstr_w(devid));
624 SetLastError(ERROR_INVALID_PARAMETER);
625 return FALSE;
629 /**************************************************************************
630 * BuildCommDCBW (KERNEL32.@)
632 * Updates a device control block structure with values from an
633 * unicode device control string. The device control string has two forms
634 * normal and extended, it must be exclusively in one or the other form.
636 * RETURNS
638 * True on success, false on an malformed control string.
640 BOOL WINAPI BuildCommDCBW(
641 LPCWSTR devid, /* [in] The unicode device control string. */
642 LPDCB lpdcb) /* [out] The device control block to be updated. */
644 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
647 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
649 DWORD ret;
651 SERVER_START_REQ( set_serial_info )
653 req->handle = handle;
654 req->flags = SERIALINFO_SET_ERROR;
655 req->commerror = error;
656 ret = !wine_server_call_err( req );
658 SERVER_END_REQ;
659 return ret;
662 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
664 DWORD ret;
666 if(!lperror)
667 return FALSE;
669 SERVER_START_REQ( get_serial_info )
671 req->handle = handle;
672 ret = !wine_server_call_err( req );
673 *lperror = reply->commerror;
675 SERVER_END_REQ;
677 return ret;
680 /*****************************************************************************
681 * SetCommBreak (KERNEL32.@)
683 * Halts the transmission of characters to a communications device.
685 * RETURNS
687 * True on success, and false if the communications device could not be found,
688 * the control is not supported.
690 * BUGS
692 * Only TIOCSBRK and TIOCCBRK are supported.
694 BOOL WINAPI SetCommBreak(
695 HANDLE handle) /* [in] The communictions device to suspend. */
697 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
698 int fd,result;
700 fd = get_comm_fd( handle, GENERIC_READ );
701 if(fd<0) return FALSE;
702 result = ioctl(fd,TIOCSBRK,0);
703 release_comm_fd( handle, fd );
704 if (result ==-1)
706 TRACE("ioctl failed\n");
707 SetLastError(ERROR_NOT_SUPPORTED);
708 return FALSE;
710 return TRUE;
711 #else
712 FIXME("ioctl not available\n");
713 SetLastError(ERROR_NOT_SUPPORTED);
714 return FALSE;
715 #endif
718 /*****************************************************************************
719 * ClearCommBreak (KERNEL32.@)
721 * Resumes character transmission from a communication device.
723 * RETURNS
725 * True on success and false if the communications device could not be found.
727 * BUGS
729 * Only TIOCSBRK and TIOCCBRK are supported.
731 BOOL WINAPI ClearCommBreak(
732 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
734 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
735 int fd,result;
737 fd = get_comm_fd( handle, GENERIC_READ );
738 if(fd<0) return FALSE;
739 result = ioctl(fd,TIOCCBRK,0);
740 release_comm_fd( handle, fd );
741 if (result ==-1)
743 TRACE("ioctl failed\n");
744 SetLastError(ERROR_NOT_SUPPORTED);
745 return FALSE;
747 return TRUE;
748 #else
749 FIXME("ioctl not available\n");
750 SetLastError(ERROR_NOT_SUPPORTED);
751 return FALSE;
752 #endif
755 /*****************************************************************************
756 * EscapeCommFunction (KERNEL32.@)
758 * Directs a communication device to perform an extended function.
760 * RETURNS
762 * True or requested data on successful completion of the command,
763 * false if the device is not present cannot execute the command
764 * or the command failed.
766 BOOL WINAPI EscapeCommFunction(
767 HANDLE handle, /* [in] The communication device to perform the extended function. */
768 UINT nFunction) /* [in] The extended function to be performed. */
770 int fd,direct=FALSE,result=FALSE;
771 struct termios port;
773 TRACE("handle %p, function=%d\n", handle, nFunction);
774 fd = get_comm_fd( handle, GENERIC_READ );
775 if(fd<0) return FALSE;
777 if (tcgetattr(fd,&port) == -1) {
778 COMM_SetCommError(handle,CE_IOE);
779 release_comm_fd( handle, fd );
780 return FALSE;
783 switch (nFunction) {
784 case RESETDEV:
785 TRACE("\n");
786 break;
788 case CLRDTR:
789 TRACE("CLRDTR\n");
790 #ifdef TIOCM_DTR
791 direct=TRUE;
792 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
793 break;
794 #endif
796 case CLRRTS:
797 TRACE("CLRRTS\n");
798 #ifdef TIOCM_RTS
799 direct=TRUE;
800 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
801 break;
802 #endif
804 case SETDTR:
805 TRACE("SETDTR\n");
806 #ifdef TIOCM_DTR
807 direct=TRUE;
808 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
809 break;
810 #endif
812 case SETRTS:
813 TRACE("SETRTS\n");
814 #ifdef TIOCM_RTS
815 direct=TRUE;
816 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
817 break;
818 #endif
820 case SETXOFF:
821 TRACE("SETXOFF\n");
822 port.c_iflag |= IXOFF;
823 break;
825 case SETXON:
826 TRACE("SETXON\n");
827 port.c_iflag |= IXON;
828 break;
829 case SETBREAK:
830 TRACE("setbreak\n");
831 #ifdef TIOCSBRK
832 direct=TRUE;
833 result = ioctl(fd,TIOCSBRK,0);
834 break;
835 #endif
836 case CLRBREAK:
837 TRACE("clrbreak\n");
838 #ifdef TIOCSBRK
839 direct=TRUE;
840 result = ioctl(fd,TIOCCBRK,0);
841 break;
842 #endif
843 default:
844 WARN("(handle=%p,nFunction=%d): Unknown function\n",
845 handle, nFunction);
846 break;
849 if (!direct)
850 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
851 release_comm_fd( handle, fd );
852 COMM_SetCommError(handle,CE_IOE);
853 return FALSE;
854 } else
855 result= TRUE;
856 else
858 if (result == -1)
860 result= FALSE;
861 COMM_SetCommError(handle,CE_IOE);
863 else
864 result = TRUE;
866 release_comm_fd( handle, fd );
867 return result;
870 /********************************************************************
871 * PurgeComm (KERNEL32.@)
873 * Terminates pending operations and/or discards buffers on a
874 * communication resource.
876 * RETURNS
878 * True on success and false if the communications handle is bad.
880 BOOL WINAPI PurgeComm(
881 HANDLE handle, /* [in] The communication resource to be purged. */
882 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
884 int fd;
886 TRACE("handle %p, flags %lx\n", handle, flags);
888 fd = get_comm_fd( handle, GENERIC_READ );
889 if(fd<0) return FALSE;
892 ** not exactly sure how these are different
893 ** Perhaps if we had our own internal queues, one flushes them
894 ** and the other flushes the kernel's buffers.
896 if(flags&PURGE_TXABORT)
897 tcflush(fd,TCOFLUSH);
898 if(flags&PURGE_RXABORT)
899 tcflush(fd,TCIFLUSH);
900 if(flags&PURGE_TXCLEAR)
901 tcflush(fd,TCOFLUSH);
902 if(flags&PURGE_RXCLEAR)
903 tcflush(fd,TCIFLUSH);
904 release_comm_fd( handle, fd );
906 return 1;
909 /*****************************************************************************
910 * ClearCommError (KERNEL32.@)
912 * Enables further I/O operations on a communications resource after
913 * supplying error and current status information.
915 * RETURNS
917 * True on success, false if the communication resource handle is bad.
919 BOOL WINAPI ClearCommError(
920 HANDLE handle, /* [in] The communication resource with the error. */
921 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
922 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
924 int fd;
926 fd=get_comm_fd( handle, GENERIC_READ );
927 if(0>fd) return FALSE;
929 if (lpStat)
931 lpStat->fCtsHold = 0;
932 lpStat->fDsrHold = 0;
933 lpStat->fRlsdHold = 0;
934 lpStat->fXoffHold = 0;
935 lpStat->fXoffSent = 0;
936 lpStat->fEof = 0;
937 lpStat->fTxim = 0;
938 lpStat->fReserved = 0;
940 #ifdef TIOCOUTQ
941 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
942 WARN("ioctl returned error\n");
943 #else
944 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
945 #endif
947 #ifdef TIOCINQ
948 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
949 WARN("ioctl returned error\n");
950 #endif
952 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
953 handle, lpStat->cbInQue, lpStat->cbOutQue);
956 release_comm_fd( handle, fd );
958 COMM_GetCommError(handle, errors);
959 COMM_SetCommError(handle, 0);
961 return TRUE;
964 /*****************************************************************************
965 * SetupComm (KERNEL32.@)
967 * Called after CreateFile to hint to the communication resource to use
968 * specified sizes for input and output buffers rather than the default values.
970 * RETURNS
972 * True if successful, false if the communications resource handle is bad.
974 * BUGS
976 * Stub.
978 BOOL WINAPI SetupComm(
979 HANDLE handle, /* [in] The just created communication resource handle. */
980 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
981 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
983 int fd;
985 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
986 fd=get_comm_fd( handle, GENERIC_READ );
987 if(0>fd) return FALSE;
988 release_comm_fd( handle, fd );
989 return TRUE;
992 /*****************************************************************************
993 * GetCommMask (KERNEL32.@)
995 * Obtain the events associated with a communication device that will cause
996 * a call WaitCommEvent to return.
998 * RETURNS
1000 * True on success, fail on bad device handle etc.
1002 BOOL WINAPI GetCommMask(
1003 HANDLE handle, /* [in] The communications device. */
1004 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1006 BOOL ret;
1008 TRACE("handle %p, mask %p\n", handle, evtmask);
1010 SERVER_START_REQ( get_serial_info )
1012 req->handle = handle;
1013 if ((ret = !wine_server_call_err( req )))
1015 if (evtmask) *evtmask = reply->eventmask;
1018 SERVER_END_REQ;
1019 return ret;
1022 /*****************************************************************************
1023 * SetCommMask (KERNEL32.@)
1025 * There be some things we need to hear about yon there communications device.
1026 * (Set which events associated with a communication device should cause
1027 * a call WaitCommEvent to return.)
1029 * RETURNS
1031 * True on success, false on bad handle etc.
1033 BOOL WINAPI SetCommMask(
1034 HANDLE handle, /* [in] The communications device. */
1035 DWORD evtmask) /* [in] The events that are to be monitored. */
1037 BOOL ret;
1039 TRACE("handle %p, mask %lx\n", handle, evtmask);
1041 SERVER_START_REQ( set_serial_info )
1043 req->handle = handle;
1044 req->flags = SERIALINFO_SET_MASK;
1045 req->eventmask = evtmask;
1046 ret = !wine_server_call_err( req );
1048 SERVER_END_REQ;
1049 return ret;
1052 /*****************************************************************************
1053 * SetCommState (KERNEL32.@)
1055 * Re-initializes all hardware and control settings of a communications device,
1056 * with values from a device control block without effecting the input and output
1057 * queues.
1059 * RETURNS
1061 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1063 BOOL WINAPI SetCommState(
1064 HANDLE handle, /* [in] The communications device. */
1065 LPDCB lpdcb) /* [out] The device control block. */
1067 struct termios port;
1068 int fd, bytesize, stopbits;
1069 BOOL ret;
1071 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1072 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1073 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1074 (lpdcb->StopBits == ONESTOPBIT)?1:
1075 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1076 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1077 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1078 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1079 lpdcb->fRtsControl);
1080 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1081 lpdcb->fDtrControl);
1084 fd = get_comm_fd( handle, GENERIC_READ );
1085 if (fd < 0) return FALSE;
1087 if ((tcgetattr(fd,&port)) == -1) {
1088 int save_error = errno;
1089 COMM_SetCommError(handle,CE_IOE);
1090 release_comm_fd( handle, fd );
1091 ERR("tcgetattr error '%s'\n", strerror(save_error));
1092 return FALSE;
1095 port.c_cc[VMIN] = 0;
1096 port.c_cc[VTIME] = 1;
1098 #ifdef IMAXBEL
1099 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1100 #else
1101 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1102 #endif
1103 port.c_iflag |= (IGNBRK);
1105 port.c_oflag &= ~(OPOST);
1107 port.c_cflag &= ~(HUPCL);
1108 port.c_cflag |= CLOCAL | CREAD;
1110 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1111 port.c_lflag |= NOFLSH;
1113 #ifdef CBAUD
1114 port.c_cflag &= ~CBAUD;
1115 switch (lpdcb->BaudRate) {
1116 case 0:
1117 port.c_cflag |= B0;
1118 break;
1119 case 50:
1120 port.c_cflag |= B50;
1121 break;
1122 case 75:
1123 port.c_cflag |= B75;
1124 break;
1125 case 110:
1126 case CBR_110:
1127 port.c_cflag |= B110;
1128 break;
1129 case 134:
1130 port.c_cflag |= B134;
1131 break;
1132 case 150:
1133 port.c_cflag |= B150;
1134 break;
1135 case 200:
1136 port.c_cflag |= B200;
1137 break;
1138 case 300:
1139 case CBR_300:
1140 port.c_cflag |= B300;
1141 break;
1142 case 600:
1143 case CBR_600:
1144 port.c_cflag |= B600;
1145 break;
1146 case 1200:
1147 case CBR_1200:
1148 port.c_cflag |= B1200;
1149 break;
1150 case 1800:
1151 port.c_cflag |= B1800;
1152 break;
1153 case 2400:
1154 case CBR_2400:
1155 port.c_cflag |= B2400;
1156 break;
1157 case 4800:
1158 case CBR_4800:
1159 port.c_cflag |= B4800;
1160 break;
1161 case 9600:
1162 case CBR_9600:
1163 port.c_cflag |= B9600;
1164 break;
1165 case 19200:
1166 case CBR_19200:
1167 port.c_cflag |= B19200;
1168 break;
1169 case 38400:
1170 case CBR_38400:
1171 port.c_cflag |= B38400;
1172 break;
1173 #ifdef B57600
1174 case 57600:
1175 port.c_cflag |= B57600;
1176 break;
1177 #endif
1178 #ifdef B115200
1179 case 115200:
1180 port.c_cflag |= B115200;
1181 break;
1182 #endif
1183 #ifdef B230400
1184 case 230400:
1185 port.c_cflag |= B230400;
1186 break;
1187 #endif
1188 #ifdef B460800
1189 case 460800:
1190 port.c_cflag |= B460800;
1191 break;
1192 #endif
1193 default:
1194 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1195 { struct serial_struct nuts;
1196 int arby;
1197 ioctl(fd, TIOCGSERIAL, &nuts);
1198 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1199 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1200 arby = nuts.baud_base / nuts.custom_divisor;
1201 nuts.flags &= ~ASYNC_SPD_MASK;
1202 nuts.flags |= ASYNC_SPD_CUST;
1203 WARN("You (or a program acting at your behest) have specified\n"
1204 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1205 "which is as close as we can get by our present understanding of your\n"
1206 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1207 "has caused to your linux system can be undone with setserial \n"
1208 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1209 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1210 ioctl(fd, TIOCSSERIAL, &nuts);
1211 port.c_cflag |= B38400;
1213 break;
1214 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1217 COMM_SetCommError(handle,IE_BAUDRATE);
1218 release_comm_fd( handle, fd );
1219 ERR("baudrate %ld\n",lpdcb->BaudRate);
1220 return FALSE;
1222 #elif !defined(__EMX__)
1223 switch (lpdcb->BaudRate) {
1224 case 0:
1225 port.c_ospeed = B0;
1226 break;
1227 case 50:
1228 port.c_ospeed = B50;
1229 break;
1230 case 75:
1231 port.c_ospeed = B75;
1232 break;
1233 case 110:
1234 case CBR_110:
1235 port.c_ospeed = B110;
1236 break;
1237 case 134:
1238 port.c_ospeed = B134;
1239 break;
1240 case 150:
1241 port.c_ospeed = B150;
1242 break;
1243 case 200:
1244 port.c_ospeed = B200;
1245 break;
1246 case 300:
1247 case CBR_300:
1248 port.c_ospeed = B300;
1249 break;
1250 case 600:
1251 case CBR_600:
1252 port.c_ospeed = B600;
1253 break;
1254 case 1200:
1255 case CBR_1200:
1256 port.c_ospeed = B1200;
1257 break;
1258 case 1800:
1259 port.c_ospeed = B1800;
1260 break;
1261 case 2400:
1262 case CBR_2400:
1263 port.c_ospeed = B2400;
1264 break;
1265 case 4800:
1266 case CBR_4800:
1267 port.c_ospeed = B4800;
1268 break;
1269 case 9600:
1270 case CBR_9600:
1271 port.c_ospeed = B9600;
1272 break;
1273 case 19200:
1274 case CBR_19200:
1275 port.c_ospeed = B19200;
1276 break;
1277 case 38400:
1278 case CBR_38400:
1279 port.c_ospeed = B38400;
1280 break;
1281 #ifdef B57600
1282 case 57600:
1283 case CBR_57600:
1284 port.c_cflag |= B57600;
1285 break;
1286 #endif
1287 #ifdef B115200
1288 case 115200:
1289 case CBR_115200:
1290 port.c_cflag |= B115200;
1291 break;
1292 #endif
1293 #ifdef B230400
1294 case 230400:
1295 port.c_cflag |= B230400;
1296 break;
1297 #endif
1298 #ifdef B460800
1299 case 460800:
1300 port.c_cflag |= B460800;
1301 break;
1302 #endif
1303 default:
1304 COMM_SetCommError(handle,IE_BAUDRATE);
1305 release_comm_fd( handle, fd );
1306 ERR("baudrate %ld\n",lpdcb->BaudRate);
1307 return FALSE;
1309 port.c_ispeed = port.c_ospeed;
1310 #endif
1311 bytesize=lpdcb->ByteSize;
1312 stopbits=lpdcb->StopBits;
1314 #ifdef CMSPAR
1315 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1316 #else
1317 port.c_cflag &= ~(PARENB | PARODD);
1318 #endif
1319 if (lpdcb->fParity)
1320 port.c_iflag |= INPCK;
1321 else
1322 port.c_iflag &= ~INPCK;
1323 switch (lpdcb->Parity) {
1324 case NOPARITY:
1325 break;
1326 case ODDPARITY:
1327 port.c_cflag |= (PARENB | PARODD);
1328 break;
1329 case EVENPARITY:
1330 port.c_cflag |= PARENB;
1331 break;
1332 #ifdef CMSPAR
1333 /* Linux defines mark/space (stick) parity */
1334 case MARKPARITY:
1335 port.c_cflag |= (PARENB | CMSPAR);
1336 break;
1337 case SPACEPARITY:
1338 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1339 break;
1340 #else
1341 /* try the POSIX way */
1342 case MARKPARITY:
1343 if( stopbits == ONESTOPBIT) {
1344 stopbits = TWOSTOPBITS;
1345 port.c_iflag &= ~INPCK;
1346 } else {
1347 COMM_SetCommError(handle,IE_BYTESIZE);
1348 release_comm_fd( handle, fd );
1349 ERR("Cannot set MARK Parity\n");
1350 return FALSE;
1352 break;
1353 case SPACEPARITY:
1354 if( bytesize < 8) {
1355 bytesize +=1;
1356 port.c_iflag &= ~INPCK;
1357 } else {
1358 COMM_SetCommError(handle,IE_BYTESIZE);
1359 release_comm_fd( handle, fd );
1360 ERR("Cannot set SPACE Parity\n");
1361 return FALSE;
1363 break;
1364 #endif
1365 default:
1366 COMM_SetCommError(handle,IE_BYTESIZE);
1367 release_comm_fd( handle, fd );
1368 ERR("Parity\n");
1369 return FALSE;
1373 port.c_cflag &= ~CSIZE;
1374 switch (bytesize) {
1375 case 5:
1376 port.c_cflag |= CS5;
1377 break;
1378 case 6:
1379 port.c_cflag |= CS6;
1380 break;
1381 case 7:
1382 port.c_cflag |= CS7;
1383 break;
1384 case 8:
1385 port.c_cflag |= CS8;
1386 break;
1387 default:
1388 COMM_SetCommError(handle,IE_BYTESIZE);
1389 release_comm_fd( handle, fd );
1390 ERR("ByteSize\n");
1391 return FALSE;
1394 switch (stopbits) {
1395 case ONESTOPBIT:
1396 port.c_cflag &= ~CSTOPB;
1397 break;
1398 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1399 case TWOSTOPBITS:
1400 port.c_cflag |= CSTOPB;
1401 break;
1402 default:
1403 COMM_SetCommError(handle,IE_BYTESIZE);
1404 release_comm_fd( handle, fd );
1405 ERR("StopBits\n");
1406 return FALSE;
1408 #ifdef CRTSCTS
1409 if ( lpdcb->fOutxCtsFlow ||
1410 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1413 port.c_cflag |= CRTSCTS;
1414 TRACE("CRTSCTS\n");
1416 #endif
1418 if (lpdcb->fInX)
1419 port.c_iflag |= IXON;
1420 else
1421 port.c_iflag &= ~IXON;
1422 if (lpdcb->fOutX)
1423 port.c_iflag |= IXOFF;
1424 else
1425 port.c_iflag &= ~IXOFF;
1427 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1428 ERR("tcsetattr error '%s'\n", strerror(errno));
1429 COMM_SetCommError(handle,CE_IOE);
1430 ret = FALSE;
1431 } else {
1432 COMM_SetCommError(handle,0);
1433 ret = TRUE;
1436 /* note: change DTR/RTS lines after setting the comm attributes,
1437 * so flow control does not interfere. */
1438 #ifdef TIOCM_DTR
1439 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1441 WARN("DSR/DTR flow control not supported\n");
1442 } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1443 COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1444 else
1445 COMM_WhackModem(fd, 0, TIOCM_DTR);
1446 #endif
1447 #ifdef TIOCM_RTS
1448 if(!lpdcb->fOutxCtsFlow )
1450 if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
1451 COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1452 else
1453 COMM_WhackModem(fd, 0, TIOCM_RTS);
1455 #endif
1456 if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
1457 FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
1458 release_comm_fd( handle, fd );
1459 return ret;
1464 /*****************************************************************************
1465 * GetCommState (KERNEL32.@)
1467 * Fills in a device control block with information from a communications device.
1469 * RETURNS
1471 * True on success, false if the communication device handle is bad etc
1473 * BUGS
1475 * XonChar and XoffChar are not set.
1477 BOOL WINAPI GetCommState(
1478 HANDLE handle, /* [in] The communications device. */
1479 LPDCB lpdcb) /* [out] The device control block. */
1481 struct termios port;
1482 int fd,speed;
1483 int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
1485 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1487 fd = get_comm_fd( handle, GENERIC_READ );
1488 if (fd < 0) return FALSE;
1489 if (tcgetattr(fd, &port) == -1
1490 #ifdef TIOCMGET
1491 || ioctl(fd, TIOCMGET, &stat) == -1
1492 #endif
1494 int save_error=errno;
1495 ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
1496 COMM_SetCommError(handle,CE_IOE);
1497 release_comm_fd( handle, fd );
1498 return FALSE;
1500 release_comm_fd( handle, fd );
1501 #ifndef __EMX__
1502 #ifdef CBAUD
1503 speed= (port.c_cflag & CBAUD);
1504 #else
1505 speed= (cfgetospeed(&port));
1506 #endif
1507 switch (speed) {
1508 case B0:
1509 lpdcb->BaudRate = 0;
1510 break;
1511 case B50:
1512 lpdcb->BaudRate = 50;
1513 break;
1514 case B75:
1515 lpdcb->BaudRate = 75;
1516 break;
1517 case B110:
1518 lpdcb->BaudRate = 110;
1519 break;
1520 case B134:
1521 lpdcb->BaudRate = 134;
1522 break;
1523 case B150:
1524 lpdcb->BaudRate = 150;
1525 break;
1526 case B200:
1527 lpdcb->BaudRate = 200;
1528 break;
1529 case B300:
1530 lpdcb->BaudRate = 300;
1531 break;
1532 case B600:
1533 lpdcb->BaudRate = 600;
1534 break;
1535 case B1200:
1536 lpdcb->BaudRate = 1200;
1537 break;
1538 case B1800:
1539 lpdcb->BaudRate = 1800;
1540 break;
1541 case B2400:
1542 lpdcb->BaudRate = 2400;
1543 break;
1544 case B4800:
1545 lpdcb->BaudRate = 4800;
1546 break;
1547 case B9600:
1548 lpdcb->BaudRate = 9600;
1549 break;
1550 case B19200:
1551 lpdcb->BaudRate = 19200;
1552 break;
1553 case B38400:
1554 lpdcb->BaudRate = 38400;
1555 break;
1556 #ifdef B57600
1557 case B57600:
1558 lpdcb->BaudRate = 57600;
1559 break;
1560 #endif
1561 #ifdef B115200
1562 case B115200:
1563 lpdcb->BaudRate = 115200;
1564 break;
1565 #endif
1566 #ifdef B230400
1567 case B230400:
1568 lpdcb->BaudRate = 230400;
1569 break;
1570 #endif
1571 #ifdef B460800
1572 case B460800:
1573 lpdcb->BaudRate = 460800;
1574 break;
1575 #endif
1576 default:
1577 ERR("unknown speed %x \n",speed);
1579 #endif
1580 switch (port.c_cflag & CSIZE) {
1581 case CS5:
1582 lpdcb->ByteSize = 5;
1583 break;
1584 case CS6:
1585 lpdcb->ByteSize = 6;
1586 break;
1587 case CS7:
1588 lpdcb->ByteSize = 7;
1589 break;
1590 case CS8:
1591 lpdcb->ByteSize = 8;
1592 break;
1593 default:
1594 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1597 if(port.c_iflag & INPCK)
1598 lpdcb->fParity = TRUE;
1599 else
1600 lpdcb->fParity = FALSE;
1601 #ifdef CMSPAR
1602 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1603 #else
1604 switch (port.c_cflag & (PARENB | PARODD))
1605 #endif
1607 case 0:
1608 lpdcb->Parity = NOPARITY;
1609 break;
1610 case PARENB:
1611 lpdcb->Parity = EVENPARITY;
1612 break;
1613 case (PARENB | PARODD):
1614 lpdcb->Parity = ODDPARITY;
1615 break;
1616 #ifdef CMSPAR
1617 case (PARENB | CMSPAR):
1618 lpdcb->Parity = MARKPARITY;
1619 break;
1620 case (PARENB | PARODD | CMSPAR):
1621 lpdcb->Parity = SPACEPARITY;
1622 break;
1623 #endif
1626 if (port.c_cflag & CSTOPB)
1627 if(lpdcb->ByteSize == 5)
1628 lpdcb->StopBits = ONE5STOPBITS;
1629 else
1630 lpdcb->StopBits = TWOSTOPBITS;
1631 else
1632 lpdcb->StopBits = ONESTOPBIT;
1634 lpdcb->fNull = 0;
1635 lpdcb->fBinary = 1;
1637 /* termios does not support DTR/DSR flow control */
1638 lpdcb->fOutxDsrFlow = 0;
1639 lpdcb->fDtrControl =
1640 #ifdef TIOCM_DTR
1641 !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
1642 #endif
1643 DTR_CONTROL_ENABLE ;
1645 #ifdef CRTSCTS
1647 if (port.c_cflag & CRTSCTS) {
1648 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1649 lpdcb->fOutxCtsFlow = 1;
1650 } else
1651 #endif
1653 lpdcb->fRtsControl =
1654 #ifdef TIOCM_RTS
1655 !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
1656 #endif
1657 RTS_CONTROL_ENABLE ;
1658 lpdcb->fOutxCtsFlow = 0;
1660 if (port.c_iflag & IXON)
1661 lpdcb->fInX = 1;
1662 else
1663 lpdcb->fInX = 0;
1665 if (port.c_iflag & IXOFF)
1666 lpdcb->fOutX = 1;
1667 else
1668 lpdcb->fOutX = 0;
1670 lpdcb->XonChar =
1671 lpdcb->XoffChar =
1673 lpdcb->XonLim = 10;
1674 lpdcb->XoffLim = 10;
1676 COMM_SetCommError(handle,0);
1678 TRACE("OK\n");
1680 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1681 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1682 (lpdcb->StopBits == ONESTOPBIT)?1:
1683 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1684 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1685 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1686 TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
1687 lpdcb->fRtsControl);
1688 TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
1689 lpdcb->fDtrControl);
1690 #ifdef CRTSCTS
1691 if ( lpdcb->fOutxCtsFlow ||
1692 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1694 TRACE("CRTSCTS\n");
1695 else
1697 TRACE("~CRTSCTS\n");
1698 #endif
1699 return TRUE;
1702 /*****************************************************************************
1703 * TransmitCommChar (KERNEL32.@)
1705 * Transmits a single character in front of any pending characters in the
1706 * output buffer. Usually used to send an interrupt character to a host.
1708 * RETURNS
1710 * True if the call succeeded, false if the previous command character to the
1711 * same device has not been sent yet the handle is bad etc.
1713 * BUGS
1715 * Stub.
1717 BOOL WINAPI TransmitCommChar(
1718 HANDLE hComm, /* [in] The communication device in need of a command character. */
1719 CHAR chTransmit) /* [in] The character to transmit. */
1721 DWORD w;
1722 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1724 return WriteFile( hComm, &chTransmit, 1, &w, NULL );
1728 /*****************************************************************************
1729 * GetCommTimeouts (KERNEL32.@)
1731 * Obtains the request timeout values for the communications device.
1733 * RETURNS
1735 * True on success, false if communications device handle is bad
1736 * or the target structure is null.
1738 BOOL WINAPI GetCommTimeouts(
1739 HANDLE hComm, /* [in] The communications device. */
1740 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1742 BOOL ret;
1744 TRACE("(%p,%p)\n",hComm,lptimeouts);
1746 if(!lptimeouts)
1748 SetLastError(ERROR_INVALID_PARAMETER);
1749 return FALSE;
1752 SERVER_START_REQ( get_serial_info )
1754 req->handle = hComm;
1755 if ((ret = !wine_server_call_err( req )))
1757 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1758 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1759 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1760 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1761 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1764 SERVER_END_REQ;
1765 return ret;
1768 /*****************************************************************************
1769 * SetCommTimeouts (KERNEL32.@)
1771 * Sets the timeouts used when reading and writing data to/from COMM ports.
1773 * ReadIntervalTimeout
1774 * - converted and passes to linux kernel as c_cc[VTIME]
1775 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1776 * - used in ReadFile to calculate GetOverlappedResult's timeout
1777 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1778 * - used in WriteFile to calculate GetOverlappedResult's timeout
1780 * RETURNS
1782 * True if the timeouts were set, false otherwise.
1784 BOOL WINAPI SetCommTimeouts(
1785 HANDLE hComm, /* [in] handle of COMM device */
1786 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1788 BOOL ret;
1789 int fd;
1790 struct termios tios;
1792 TRACE("(%p,%p)\n",hComm,lptimeouts);
1794 if(!lptimeouts)
1796 SetLastError(ERROR_INVALID_PARAMETER);
1797 return FALSE;
1800 SERVER_START_REQ( set_serial_info )
1802 req->handle = hComm;
1803 req->flags = SERIALINFO_SET_TIMEOUTS;
1804 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1805 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1806 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1807 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1808 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1809 ret = !wine_server_call_err( req );
1811 SERVER_END_REQ;
1812 if (!ret) return FALSE;
1814 /* FIXME: move this stuff to the server */
1815 fd = get_comm_fd( hComm, GENERIC_READ );
1816 if (fd < 0) return FALSE;
1818 if (-1==tcgetattr(fd,&tios)) {
1819 FIXME("tcgetattr on fd %d failed!\n",fd);
1820 release_comm_fd( hComm, fd );
1821 return FALSE;
1824 /* VTIME is in 1/10 seconds */
1826 unsigned int ux_timeout;
1828 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1830 ux_timeout = 0;
1832 else
1834 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1835 if(ux_timeout == 0)
1837 ux_timeout = 1; /* must be at least some timeout */
1840 tios.c_cc[VTIME] = ux_timeout;
1843 if (-1==tcsetattr(fd,0,&tios)) {
1844 FIXME("tcsetattr on fd %d failed!\n",fd);
1845 release_comm_fd( hComm, fd );
1846 return FALSE;
1848 release_comm_fd( hComm, fd );
1849 return TRUE;
1852 /***********************************************************************
1853 * GetCommModemStatus (KERNEL32.@)
1855 * Obtains the four control register bits if supported by the hardware.
1857 * RETURNS
1859 * True if the communications handle was good and for hardware that
1860 * control register access, false otherwise.
1862 BOOL WINAPI GetCommModemStatus(
1863 HANDLE hFile, /* [in] The communications device. */
1864 LPDWORD lpModemStat) /* [out] The control register bits. */
1866 int fd,mstat, result=FALSE;
1868 *lpModemStat=0;
1869 #ifdef TIOCMGET
1870 fd = get_comm_fd( hFile, GENERIC_READ );
1871 if(fd<0)
1872 return FALSE;
1873 result = ioctl(fd, TIOCMGET, &mstat);
1874 release_comm_fd( hFile, fd );
1875 if (result == -1)
1877 WARN("ioctl failed\n");
1878 return FALSE;
1880 #ifdef TIOCM_CTS
1881 if (mstat & TIOCM_CTS)
1882 *lpModemStat |= MS_CTS_ON;
1883 #endif
1884 #ifdef TIOCM_DSR
1885 if (mstat & TIOCM_DSR)
1886 *lpModemStat |= MS_DSR_ON;
1887 #endif
1888 #ifdef TIOCM_RNG
1889 if (mstat & TIOCM_RNG)
1890 *lpModemStat |= MS_RING_ON;
1891 #endif
1892 #ifdef TIOCM_CAR
1893 /*FIXME: Not really sure about RLSD UB 990810*/
1894 if (mstat & TIOCM_CAR)
1895 *lpModemStat |= MS_RLSD_ON;
1896 #endif
1897 TRACE("%04x -> %s%s%s%s\n", mstat,
1898 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1899 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1900 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1901 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1902 return TRUE;
1903 #else
1904 return FALSE;
1905 #endif
1908 /***********************************************************************
1909 * COMM_WaitCommEventService (INTERNAL)
1911 * This function is called while the client is waiting on the
1912 * server, so we can't make any server calls here.
1914 static void WINAPI COMM_WaitCommEventService(void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1916 async_commio *commio = (async_commio*) ovp;
1918 TRACE("iosb %p\n", iosb);
1920 switch (status)
1922 case STATUS_ALERTED: /* got some new stuff */
1923 /* FIXME: detect other events */
1924 *commio->buffer = EV_RXCHAR;
1925 iosb->u.Status = STATUS_SUCCESS;
1926 break;
1927 default:
1928 iosb->u.Status = status;
1929 break;
1931 wine_server_release_fd( commio->handle, commio->fd );
1932 if ( ((LPOVERLAPPED)iosb)->hEvent != INVALID_HANDLE_VALUE )
1933 NtSetEvent( ((LPOVERLAPPED)iosb)->hEvent, NULL );
1934 HeapFree(GetProcessHeap(), 0, commio );
1938 /***********************************************************************
1939 * COMM_WaitCommEvent (INTERNAL)
1941 * This function must have an lpOverlapped.
1943 static BOOL COMM_WaitCommEvent(
1944 HANDLE hFile, /* [in] handle of comm port to wait for */
1945 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1946 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1948 int fd;
1949 async_commio* commio;
1950 NTSTATUS status;
1952 if (!lpOverlapped)
1954 SetLastError(ERROR_INVALID_PARAMETER);
1955 return FALSE;
1958 if (NtResetEvent(lpOverlapped->hEvent,NULL))
1959 return FALSE;
1961 fd = get_comm_fd( hFile, GENERIC_WRITE );
1962 if (fd < 0) return FALSE;
1964 commio = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1965 if (!commio)
1967 release_comm_fd( hFile, fd );
1968 return FALSE;
1971 commio->handle = hFile;
1972 commio->type = ASYNC_TYPE_WAIT;
1973 commio->apc_internal = COMM_WaitCommEventService;
1974 commio->buffer = (char *)lpdwEvents;
1975 commio->fd = fd; /* FIXME */
1977 lpOverlapped->InternalHigh = 0;
1978 lpOverlapped->Offset = 0;
1979 lpOverlapped->OffsetHigh = 0;
1981 SERVER_START_REQ( register_async )
1983 req->handle = hFile;
1984 req->io_apc = COMM_WaitCommEventService;
1985 req->io_user = commio;
1986 req->io_sb = (IO_STATUS_BLOCK*)lpOverlapped;
1987 req->count = 0;
1988 status = wine_server_call( req );
1990 SERVER_END_REQ;
1992 if ( status ) SetLastError( RtlNtStatusToDosError(status) );
1993 else NtCurrentTeb()->num_async_io++;
1995 return FALSE;
1998 /***********************************************************************
1999 * WaitCommEvent (KERNEL32.@)
2001 * Wait until something interesting happens on a COMM port.
2002 * Interesting things (events) are set by calling SetCommMask before
2003 * this function is called.
2005 * RETURNS:
2006 * TRUE if successful
2007 * FALSE if failure
2009 * The set of detected events will be written to *lpdwEventMask
2010 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2012 * BUGS:
2013 * Only supports EV_RXCHAR and EV_TXEMPTY
2015 BOOL WINAPI WaitCommEvent(
2016 HANDLE hFile, /* [in] handle of comm port to wait for */
2017 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2018 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2020 OVERLAPPED ov;
2021 int ret;
2023 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2025 if(lpOverlapped)
2026 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2028 /* if there is no overlapped structure, create our own */
2029 ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
2031 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2033 /* wait for the overlapped to complete */
2034 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
2035 CloseHandle(ov.hEvent);
2037 return ret;
2040 /***********************************************************************
2041 * GetCommProperties (KERNEL32.@)
2043 * This function fills in a structure with the capabilities of the
2044 * communications port driver.
2046 * RETURNS
2048 * TRUE on success, FALSE on failure
2049 * If successful, the lpCommProp structure be filled in with
2050 * properties of the comm port.
2052 BOOL WINAPI GetCommProperties(
2053 HANDLE hFile, /* [in] handle of the comm port */
2054 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2056 FIXME("(%p %p )\n",hFile,lpCommProp);
2057 if(!lpCommProp)
2058 return FALSE;
2061 * These values should be valid for LINUX's serial driver
2062 * FIXME: Perhaps they deserve an #ifdef LINUX
2064 memset(lpCommProp,0,sizeof(COMMPROP));
2065 lpCommProp->wPacketLength = 1;
2066 lpCommProp->wPacketVersion = 1;
2067 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2068 lpCommProp->dwReserved1 = 0;
2069 lpCommProp->dwMaxTxQueue = 4096;
2070 lpCommProp->dwMaxRxQueue = 4096;
2071 lpCommProp->dwMaxBaud = BAUD_115200;
2072 lpCommProp->dwProvSubType = PST_RS232;
2073 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
2074 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2075 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2076 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2077 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2078 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2079 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2080 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2081 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2082 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2083 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2085 return TRUE;
2088 /***********************************************************************
2089 * FIXME:
2090 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2091 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2092 * This is dependent on the type of COMM port, but since it is doubtful
2093 * anybody will get around to implementing support for fancy serial
2094 * ports in WINE, this is hardcoded for the time being. The name of
2095 * this DLL should be stored in and read from the system registry in
2096 * the hive HKEY_LOCAL_MACHINE, key
2097 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2098 * where ???? is the port number... that is determined by PNP
2099 * The DLL should be loaded when the COMM port is opened, and closed
2100 * when the COMM port is closed. - MJM 20 June 2000
2101 ***********************************************************************/
2102 static WCHAR lpszSerialUI[] = {
2103 's','e','r','i','a','l','u','i','.','d','l','l',0 };
2106 /***********************************************************************
2107 * CommConfigDialogA (KERNEL32.@)
2109 * Raises a dialog that allows the user to configure a comm port.
2110 * Fills the COMMCONFIG struct with information specified by the user.
2111 * This function should call a similar routine in the COMM driver...
2113 * RETURNS
2115 * TRUE on success, FALSE on failure
2116 * If successful, the lpCommConfig structure will contain a new
2117 * configuration for the comm port, as specified by the user.
2119 * BUGS
2120 * The library with the CommConfigDialog code is never unloaded.
2121 * Perhaps this should be done when the comm port is closed?
2123 BOOL WINAPI CommConfigDialogA(
2124 LPCSTR lpszDevice, /* [in] name of communications device */
2125 HANDLE hWnd, /* [in] parent window for the dialog */
2126 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2128 FARPROC lpfnCommDialog;
2129 HMODULE hConfigModule;
2130 BOOL r = FALSE;
2132 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2134 hConfigModule = LoadLibraryW(lpszSerialUI);
2135 if(!hConfigModule)
2136 return FALSE;
2138 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
2140 if(lpfnCommDialog)
2141 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2143 FreeLibrary(hConfigModule);
2145 return r;
2148 /***********************************************************************
2149 * CommConfigDialogW (KERNEL32.@)
2151 * see CommConfigDialogA for more info
2153 BOOL WINAPI CommConfigDialogW(
2154 LPCWSTR lpszDevice, /* [in] name of communications device */
2155 HANDLE hWnd, /* [in] parent window for the dialog */
2156 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2158 FARPROC lpfnCommDialog;
2159 HMODULE hConfigModule;
2160 BOOL r = FALSE;
2162 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2164 hConfigModule = LoadLibraryW(lpszSerialUI);
2165 if(!hConfigModule)
2166 return FALSE;
2168 lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
2170 if(lpfnCommDialog)
2171 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2173 FreeLibrary(hConfigModule);
2175 return r;
2178 /***********************************************************************
2179 * GetCommConfig (KERNEL32.@)
2181 * Fill in the COMMCONFIG structure for the comm port hFile
2183 * RETURNS
2185 * TRUE on success, FALSE on failure
2186 * If successful, lpCommConfig contains the comm port configuration.
2188 * BUGS
2191 BOOL WINAPI GetCommConfig(
2192 HANDLE hFile, /* [in] The communications device. */
2193 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2194 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2195 afterwards the number of bytes copied to the buffer or
2196 the needed size of the buffer. */
2198 BOOL r;
2200 TRACE("(%p %p)\n",hFile,lpCommConfig);
2202 if(lpCommConfig == NULL)
2203 return FALSE;
2204 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2205 *lpdwSize = sizeof(COMMCONFIG);
2206 if(r)
2207 return FALSE;
2209 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2210 lpCommConfig->wVersion = 1;
2211 lpCommConfig->wReserved = 0;
2212 r = GetCommState(hFile,&lpCommConfig->dcb);
2213 lpCommConfig->dwProviderSubType = PST_RS232;
2214 lpCommConfig->dwProviderOffset = 0;
2215 lpCommConfig->dwProviderSize = 0;
2217 return r;
2220 /***********************************************************************
2221 * SetCommConfig (KERNEL32.@)
2223 * Sets the configuration of the communications device.
2225 * RETURNS
2227 * True on success, false if the handle was bad is not a communications device.
2229 BOOL WINAPI SetCommConfig(
2230 HANDLE hFile, /* [in] The communications device. */
2231 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2232 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2234 TRACE("(%p %p)\n",hFile,lpCommConfig);
2235 return SetCommState(hFile,&lpCommConfig->dcb);
2238 /***********************************************************************
2239 * SetDefaultCommConfigA (KERNEL32.@)
2241 * Initializes the default configuration for the specified communication
2242 * device. (ascii)
2244 * RETURNS
2246 * True if the device was found and the defaults set, false otherwise
2248 BOOL WINAPI SetDefaultCommConfigW(
2249 LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2250 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2251 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2253 FARPROC lpfnSetDefaultCommConfig;
2254 HMODULE hConfigModule;
2255 BOOL r = FALSE;
2257 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2259 hConfigModule = LoadLibraryW(lpszSerialUI);
2260 if(!hConfigModule)
2261 return r;
2263 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
2264 if (lpfnSetDefaultCommConfig)
2265 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2267 FreeLibrary(hConfigModule);
2269 return r;
2273 /***********************************************************************
2274 * SetDefaultCommConfigW (KERNEL32.@)
2276 * Initializes the default configuration for the specified
2277 * communication device. (unicode)
2279 * RETURNS
2282 BOOL WINAPI SetDefaultCommConfigA(
2283 LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2284 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2285 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2287 BOOL r;
2288 LPWSTR lpDeviceW = NULL;
2289 DWORD len;
2291 TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
2293 if (lpszDevice)
2295 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
2296 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2297 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
2299 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
2300 HeapFree( GetProcessHeap(), 0, lpDeviceW );
2301 return r;
2305 /***********************************************************************
2306 * GetDefaultCommConfigW (KERNEL32.@)
2308 * Acquires the default configuration of the specified communication device. (unicode)
2310 * RETURNS
2312 * True on successful reading of the default configuration,
2313 * if the device is not found or the buffer is too small.
2315 BOOL WINAPI GetDefaultCommConfigW(
2316 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2317 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2318 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2319 afterwards the number of bytes copied to the buffer or
2320 the needed size of the buffer. */
2322 LPDCB lpdcb = &(lpCC->dcb);
2323 WCHAR temp[40];
2324 static const WCHAR comW[] = {'C','O','M',0};
2325 static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
2327 if (strncmpiW(lpszName,comW,3)) {
2328 ERR("not implemented for <%s>\n", debugstr_w(lpszName));
2329 return FALSE;
2332 TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
2333 if (*lpdwSize < sizeof(COMMCONFIG)) {
2334 *lpdwSize = sizeof(COMMCONFIG);
2335 return FALSE;
2338 *lpdwSize = sizeof(COMMCONFIG);
2340 lpCC->dwSize = sizeof(COMMCONFIG);
2341 lpCC->wVersion = 1;
2342 lpCC->dwProviderSubType = PST_RS232;
2343 lpCC->dwProviderOffset = 0L;
2344 lpCC->dwProviderSize = 0L;
2346 sprintfW( temp, formatW, lpszName[3]);
2347 FIXME("setting %s as default\n", debugstr_w(temp));
2349 return BuildCommDCBW( temp, lpdcb);
2352 /**************************************************************************
2353 * GetDefaultCommConfigA (KERNEL32.@)
2355 * Acquires the default configuration of the specified communication device. (ascii)
2357 * RETURNS
2359 * True on successful reading of the default configuration,
2360 * if the device is not found or the buffer is too small.
2362 BOOL WINAPI GetDefaultCommConfigA(
2363 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2364 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2365 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2366 afterwards the number of bytes copied to the buffer or
2367 the needed size of the buffer. */
2369 BOOL ret = FALSE;
2370 UNICODE_STRING lpszNameW;
2372 TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2373 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
2374 else lpszNameW.Buffer = NULL;
2376 if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
2378 RtlFreeUnicodeString(&lpszNameW);
2379 return ret;