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
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.
53 #include "wine/port.h"
68 #ifdef HAVE_SYS_FILIO_H
69 # include <sys/filio.h>
71 #ifdef HAVE_SYS_IOCTL_H
72 #include <sys/ioctl.h>
76 #ifdef HAVE_SYS_MODEM_H
77 # include <sys/modem.h>
79 #ifdef HAVE_SYS_STRTIO_H
80 # include <sys/strtio.h>
86 #include "wine/server.h"
91 #include "wine/debug.h"
93 #ifdef HAVE_LINUX_SERIAL_H
94 #include <linux/serial.h>
97 WINE_DEFAULT_DEBUG_CHANNEL(comm);
99 /***********************************************************************
100 * Asynchronous I/O for asynchronous wait requests *
103 static DWORD commio_get_async_status (const async_private *ovp);
104 static DWORD commio_get_async_count (const async_private *ovp);
105 static void commio_set_async_status (async_private *ovp, const DWORD status);
106 static void commio_async_cleanup (async_private *ovp);
108 static async_ops commio_async_ops =
110 commio_get_async_status, /* get_status */
111 commio_set_async_status, /* set_status */
112 commio_get_async_count, /* get_count */
113 NULL, /* call_completion */
114 commio_async_cleanup /* cleanup */
117 typedef struct async_commio
119 struct async_private async;
120 LPOVERLAPPED lpOverlapped;
124 static DWORD commio_get_async_status (const struct async_private *ovp)
126 return ((async_commio*) ovp)->lpOverlapped->Internal;
129 static void commio_set_async_status (async_private *ovp, const DWORD status)
131 ((async_commio*) ovp)->lpOverlapped->Internal = status;
134 static DWORD commio_get_async_count (const struct async_private *ovp)
139 static void commio_async_cleanup (async_private *ovp)
141 HeapFree(GetProcessHeap(), 0, ovp );
144 /***********************************************************************/
146 #if !defined(TIOCINQ) && defined(FIONREAD)
147 #define TIOCINQ FIONREAD
150 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
153 unsigned int mstat, okay;
154 okay = ioctl(fd, TIOCMGET, &mstat);
155 if (okay) return okay;
156 if (andy) mstat &= andy;
158 return ioctl(fd, TIOCMSET, &mstat);
164 /***********************************************************************
165 * COMM_BuildOldCommDCB (Internal)
167 * Build a DCB using the old style settings string eg: "COMx:96,n,8,1"
168 * We ignore the COM port index, since we can support more than 4 ports.
170 BOOL WINAPI COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
172 /* "COM1:96,n,8,1" */
174 char *ptr, temp[256], last;
177 TRACE("(%s), ptr %p\n", device, lpdcb);
179 /* Some applications call this function with "9600,n,8,1"
180 * not sending the "COM1:" parameter at left of string */
181 if (!strncasecmp(device,"COM",3))
183 if (!device[3]) return FALSE;
184 if (device[4] != ':' && device[4] != ' ') return FALSE;
185 strcpy(temp,device+5);
187 else strcpy(temp,device);
189 last=temp[strlen(temp)-1];
190 ptr = strtok(temp, ", ");
192 /* DOS/Windows only compares the first two numbers
193 * and assigns an appropriate baud rate.
194 * You can supply 961324245, it still returns 9600 ! */
197 WARN("Unknown baudrate string '%s' !\n", ptr);
198 return FALSE; /* error: less than 2 chars */
219 WARN("Unknown baudrate indicator %d !\n", rate);
223 lpdcb->BaudRate = rate;
224 TRACE("baudrate (%ld)\n", lpdcb->BaudRate);
226 ptr = strtok(NULL, ", ");
228 *ptr = toupper(*ptr);
230 TRACE("parity (%c)\n", *ptr);
231 lpdcb->fParity = TRUE;
234 lpdcb->Parity = NOPARITY;
235 lpdcb->fParity = FALSE;
238 lpdcb->Parity = EVENPARITY;
241 lpdcb->Parity = MARKPARITY;
244 lpdcb->Parity = ODDPARITY;
247 lpdcb->Parity = SPACEPARITY;
250 WARN("Unknown parity `%c'!\n", *ptr);
254 ptr = strtok(NULL, ", ");
255 TRACE("charsize (%c)\n", *ptr);
256 lpdcb->ByteSize = *ptr - '0';
258 ptr = strtok(NULL, ", ");
259 TRACE("stopbits (%c)\n", *ptr);
262 lpdcb->StopBits = ONESTOPBIT;
265 lpdcb->StopBits = TWOSTOPBITS;
268 WARN("Unknown # of stopbits `%c'!\n", *ptr);
275 lpdcb->fOutxCtsFlow = FALSE;
276 lpdcb->fOutxDsrFlow = FALSE;
277 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
278 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
279 } else if (last=='p') {
281 lpdcb->fOutX = FALSE;
282 lpdcb->fOutxCtsFlow = TRUE;
283 lpdcb->fOutxDsrFlow = FALSE;
284 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
285 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
288 lpdcb->fOutX = FALSE;
289 lpdcb->fOutxCtsFlow = FALSE;
290 lpdcb->fOutxDsrFlow = FALSE;
291 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
292 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
298 /**************************************************************************
299 * BuildCommDCBA (KERNEL32.@)
301 * Updates a device control block data structure with values from an
302 * ascii device control string. The device control string has two forms
303 * normal and extended, it must be exclusively in one or the other form.
307 * True on success, false on a malformed control string.
309 BOOL WINAPI BuildCommDCBA(
310 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
311 LPDCB lpdcb) /* [out] The device control block to be updated. */
313 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
316 /**************************************************************************
317 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
319 * Updates a device control block data structure with values from an
320 * ascii device control string. Taking timeout values from a timeouts
321 * struct if desired by the control string.
325 * True on success, false bad handles etc
327 BOOL WINAPI BuildCommDCBAndTimeoutsA(
328 LPCSTR device, /* [in] The ascii device control string. */
329 LPDCB lpdcb, /* [out] The device control block to be updated. */
330 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
335 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
337 if (!strncasecmp(device,"COM",3)) {
340 ERR("BUG! COM0 can't exist!\n");
343 if ((*(device+4)!=':') && (*(device+4)!=' '))
345 temp=(LPSTR)(device+5);
349 memset(lpdcb,0,sizeof (DCB));
350 lpdcb->DCBlength = sizeof(DCB);
351 if (strchr(temp,',')) { /* old style */
353 return COMM_BuildOldCommDCB(device,lpdcb);
355 ptr=strtok(temp," ");
360 if (!strncmp("baud=",ptr,5)) {
361 if (!sscanf(ptr+5,"%ld",&x))
362 WARN("Couldn't parse %s\n",ptr);
366 if (!strncmp("stop=",ptr,5)) {
367 if (!sscanf(ptr+5,"%ld",&x))
368 WARN("Couldn't parse %s\n",ptr);
372 if (!strncmp("data=",ptr,5)) {
373 if (!sscanf(ptr+5,"%ld",&x))
374 WARN("Couldn't parse %s\n",ptr);
378 if (!strncmp("parity=",ptr,7)) {
379 lpdcb->fParity = TRUE;
382 lpdcb->fParity = FALSE;
383 lpdcb->Parity = NOPARITY;
386 lpdcb->Parity = EVENPARITY;
389 lpdcb->Parity = ODDPARITY;
392 lpdcb->Parity = MARKPARITY;
395 lpdcb->Parity = SPACEPARITY;
401 ERR("Unhandled specifier '%s', please report.\n",ptr);
402 ptr=strtok(NULL," ");
404 if (lpdcb->BaudRate==110)
409 /**************************************************************************
410 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
412 * Updates a device control block data structure with values from an
413 * unicode device control string. Taking timeout values from a timeouts
414 * struct if desired by the control string.
418 * True on success, false bad handles etc.
420 BOOL WINAPI BuildCommDCBAndTimeoutsW(
421 LPCWSTR devid, /* [in] The unicode device control string. */
422 LPDCB lpdcb, /* [out] The device control block to be updated. */
423 LPCOMMTIMEOUTS lptimeouts) /* [in] The timeouts to use if asked to set them by the control string. */
428 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
429 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
432 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
433 HeapFree( GetProcessHeap(), 0, devidA );
438 /**************************************************************************
439 * BuildCommDCBW (KERNEL32.@)
441 * Updates a device control block structure with values from an
442 * unicode device control string. The device control string has two forms
443 * normal and extended, it must be exclusively in one or the other form.
447 * True on success, false on an malformed control string.
449 BOOL WINAPI BuildCommDCBW(
450 LPCWSTR devid, /* [in] The unicode device control string. */
451 LPDCB lpdcb) /* [out] The device control block to be updated. */
453 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
456 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
460 SERVER_START_REQ( set_serial_info )
462 req->handle = handle;
463 req->flags = SERIALINFO_SET_ERROR;
464 req->commerror = error;
465 ret = !wine_server_call_err( req );
471 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
478 SERVER_START_REQ( get_serial_info )
480 req->handle = handle;
481 ret = !wine_server_call_err( req );
482 *lperror = reply->commerror;
489 /*****************************************************************************
490 * SetCommBreak (KERNEL32.@)
492 * Halts the transmission of characters to a communications device.
496 * True on success, and false if the communications device could not be found,
497 * the control is not supported.
501 * Only TIOCSBRK and TIOCCBRK are supported.
503 BOOL WINAPI SetCommBreak(
504 HANDLE handle) /* [in] The communictions device to suspend. */
506 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
509 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
511 TRACE("FILE_GetUnixHandle failed\n");
514 result = ioctl(fd,TIOCSBRK,0);
518 TRACE("ioctl failed\n");
519 SetLastError(ERROR_NOT_SUPPORTED);
524 FIXME("ioctl not available\n");
525 SetLastError(ERROR_NOT_SUPPORTED);
530 /*****************************************************************************
531 * ClearCommBreak (KERNEL32.@)
533 * Resumes character transmission from a communication device.
537 * True on success and false if the communications device could not be found.
541 * Only TIOCSBRK and TIOCCBRK are supported.
543 BOOL WINAPI ClearCommBreak(
544 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
546 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
549 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
551 TRACE("FILE_GetUnixHandle failed\n");
554 result = ioctl(fd,TIOCCBRK,0);
558 TRACE("ioctl failed\n");
559 SetLastError(ERROR_NOT_SUPPORTED);
564 FIXME("ioctl not available\n");
565 SetLastError(ERROR_NOT_SUPPORTED);
570 /*****************************************************************************
571 * EscapeCommFunction (KERNEL32.@)
573 * Directs a communication device to perform an extended function.
577 * True or requested data on successful completion of the command,
578 * false if the device is not present cannot execute the command
579 * or the command failed.
581 BOOL WINAPI EscapeCommFunction(
582 HANDLE handle, /* [in] The communication device to perform the extended function. */
583 UINT nFunction) /* [in] The extended function to be performed. */
585 int fd,direct=FALSE,result=FALSE;
588 TRACE("handle %d, function=%d\n", handle, nFunction);
589 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
591 FIXME("handle %d not found.\n",handle);
595 if (tcgetattr(fd,&port) == -1) {
596 COMM_SetCommError(handle,CE_IOE);
610 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
618 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
626 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
634 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
640 port.c_iflag |= IXOFF;
645 port.c_iflag |= IXON;
651 result = ioctl(fd,TIOCSBRK,0);
658 result = ioctl(fd,TIOCCBRK,0);
662 WARN("(handle=%d,nFunction=%d): Unknown function\n",
668 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
670 COMM_SetCommError(handle,CE_IOE);
679 COMM_SetCommError(handle,CE_IOE);
688 /********************************************************************
689 * PurgeComm (KERNEL32.@)
691 * Terminates pending operations and/or discards buffers on a
692 * communication resource.
696 * True on success and false if the communications handle is bad.
698 BOOL WINAPI PurgeComm(
699 HANDLE handle, /* [in] The communication resource to be purged. */
700 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
704 TRACE("handle %d, flags %lx\n", handle, flags);
706 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
708 FIXME("no handle %d found\n",handle);
713 ** not exactly sure how these are different
714 ** Perhaps if we had our own internal queues, one flushes them
715 ** and the other flushes the kernel's buffers.
717 if(flags&PURGE_TXABORT)
718 tcflush(fd,TCOFLUSH);
719 if(flags&PURGE_RXABORT)
720 tcflush(fd,TCIFLUSH);
721 if(flags&PURGE_TXCLEAR)
722 tcflush(fd,TCOFLUSH);
723 if(flags&PURGE_RXCLEAR)
724 tcflush(fd,TCIFLUSH);
730 /*****************************************************************************
731 * ClearCommError (KERNEL32.@)
733 * Enables further I/O operations on a communications resource after
734 * supplying error and current status information.
738 * True on success, false if the communication resource handle is bad.
740 BOOL WINAPI ClearCommError(
741 HANDLE handle, /* [in] The communication resource with the error. */
742 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
743 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
747 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
750 FIXME("no handle %d found\n",handle);
759 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
760 WARN("ioctl returned error\n");
762 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
766 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
767 WARN("ioctl returned error\n");
770 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
771 handle, lpStat->cbInQue, lpStat->cbOutQue);
776 COMM_GetCommError(handle, errors);
777 COMM_SetCommError(handle, 0);
782 /*****************************************************************************
783 * SetupComm (KERNEL32.@)
785 * Called after CreateFile to hint to the communication resource to use
786 * specified sizes for input and output buffers rather than the default values.
790 * True if successful, false if the communications resource handle is bad.
796 BOOL WINAPI SetupComm(
797 HANDLE handle, /* [in] The just created communication resource handle. */
798 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
799 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
803 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
804 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
806 FIXME("handle %d not found?\n",handle);
813 /*****************************************************************************
814 * GetCommMask (KERNEL32.@)
816 * Obtain the events associated with a communication device that will cause
817 * a call WaitCommEvent to return.
821 * True on success, fail on bad device handle etc.
823 BOOL WINAPI GetCommMask(
824 HANDLE handle, /* [in] The communications device. */
825 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
829 TRACE("handle %d, mask %p\n", handle, evtmask);
831 SERVER_START_REQ( get_serial_info )
833 req->handle = handle;
834 if ((ret = !wine_server_call_err( req )))
836 if (evtmask) *evtmask = reply->eventmask;
843 /*****************************************************************************
844 * SetCommMask (KERNEL32.@)
846 * There be some things we need to hear about yon there communications device.
847 * (Set which events associated with a communication device should cause
848 * a call WaitCommEvent to return.)
852 * True on success, false on bad handle etc.
854 BOOL WINAPI SetCommMask(
855 HANDLE handle, /* [in] The communications device. */
856 DWORD evtmask) /* [in] The events that are to be monitored. */
860 TRACE("handle %d, mask %lx\n", handle, evtmask);
862 SERVER_START_REQ( set_serial_info )
864 req->handle = handle;
865 req->flags = SERIALINFO_SET_MASK;
866 req->eventmask = evtmask;
867 ret = !wine_server_call_err( req );
873 /*****************************************************************************
874 * SetCommState (KERNEL32.@)
876 * Re-initializes all hardware and control settings of a communications device,
877 * with values from a device control block without effecting the input and output
882 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
884 BOOL WINAPI SetCommState(
885 HANDLE handle, /* [in] The communications device. */
886 LPDCB lpdcb) /* [out] The device control block. */
889 int fd, bytesize, stopbits;
891 TRACE("handle %d, ptr %p\n", handle, lpdcb);
892 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
893 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
894 (lpdcb->StopBits == ONESTOPBIT)?1:
895 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
896 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
897 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
899 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
901 FIXME("no handle %d found\n",handle);
905 if ((tcgetattr(fd,&port)) == -1) {
906 int save_error = errno;
907 COMM_SetCommError(handle,CE_IOE);
909 ERR("tcgetattr error '%s'\n", strerror(save_error));
914 port.c_cc[VTIME] = 1;
917 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
919 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
921 port.c_iflag |= (IGNBRK);
923 port.c_oflag &= ~(OPOST);
925 port.c_cflag &= ~(HUPCL);
926 port.c_cflag |= CLOCAL | CREAD;
928 port.c_lflag &= ~(ICANON|ECHO|ISIG);
929 port.c_lflag |= NOFLSH;
932 port.c_cflag &= ~CBAUD;
933 switch (lpdcb->BaudRate) {
936 port.c_cflag |= B110;
940 port.c_cflag |= B300;
944 port.c_cflag |= B600;
948 port.c_cflag |= B1200;
952 port.c_cflag |= B2400;
956 port.c_cflag |= B4800;
960 port.c_cflag |= B9600;
964 port.c_cflag |= B19200;
968 port.c_cflag |= B38400;
972 port.c_cflag |= B57600;
977 port.c_cflag |= B115200;
982 port.c_cflag |= B230400;
987 port.c_cflag |= B460800;
991 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
992 { struct serial_struct nuts;
994 ioctl(fd, TIOCGSERIAL, &nuts);
995 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
996 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
997 arby = nuts.baud_base / nuts.custom_divisor;
998 nuts.flags &= ~ASYNC_SPD_MASK;
999 nuts.flags |= ASYNC_SPD_CUST;
1000 WARN("You (or a program acting at your behest) have specified\n"
1001 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1002 "which is as close as we can get by our present understanding of your\n"
1003 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1004 "has caused to your linux system can be undone with setserial \n"
1005 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1006 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1007 ioctl(fd, TIOCSSERIAL, &nuts);
1008 port.c_cflag |= B38400;
1011 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1014 COMM_SetCommError(handle,IE_BAUDRATE);
1016 ERR("baudrate %ld\n",lpdcb->BaudRate);
1019 #elif !defined(__EMX__)
1020 switch (lpdcb->BaudRate) {
1023 port.c_ospeed = B110;
1027 port.c_ospeed = B300;
1031 port.c_ospeed = B600;
1035 port.c_ospeed = B1200;
1039 port.c_ospeed = B2400;
1043 port.c_ospeed = B4800;
1047 port.c_ospeed = B9600;
1051 port.c_ospeed = B19200;
1055 port.c_ospeed = B38400;
1060 port.c_cflag |= B57600;
1066 port.c_cflag |= B115200;
1071 port.c_cflag |= B230400;
1076 port.c_cflag |= B460800;
1080 COMM_SetCommError(handle,IE_BAUDRATE);
1082 ERR("baudrate %ld\n",lpdcb->BaudRate);
1085 port.c_ispeed = port.c_ospeed;
1087 bytesize=lpdcb->ByteSize;
1088 stopbits=lpdcb->StopBits;
1091 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1093 port.c_cflag &= ~(PARENB | PARODD);
1096 port.c_iflag |= INPCK;
1098 port.c_iflag &= ~INPCK;
1099 switch (lpdcb->Parity) {
1103 port.c_cflag |= (PARENB | PARODD);
1106 port.c_cflag |= PARENB;
1109 /* Linux defines mark/space (stick) parity */
1111 port.c_cflag |= (PARENB | CMSPAR);
1114 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1117 /* try the POSIX way */
1119 if( stopbits == ONESTOPBIT) {
1120 stopbits = TWOSTOPBITS;
1121 port.c_iflag &= ~INPCK;
1123 COMM_SetCommError(handle,IE_BYTESIZE);
1125 ERR("Cannot set MARK Parity\n");
1132 port.c_iflag &= ~INPCK;
1134 COMM_SetCommError(handle,IE_BYTESIZE);
1136 ERR("Cannot set SPACE Parity\n");
1142 COMM_SetCommError(handle,IE_BYTESIZE);
1149 port.c_cflag &= ~CSIZE;
1152 port.c_cflag |= CS5;
1155 port.c_cflag |= CS6;
1158 port.c_cflag |= CS7;
1161 port.c_cflag |= CS8;
1164 COMM_SetCommError(handle,IE_BYTESIZE);
1172 port.c_cflag &= ~CSTOPB;
1174 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1176 port.c_cflag |= CSTOPB;
1179 COMM_SetCommError(handle,IE_BYTESIZE);
1185 if ( lpdcb->fOutxCtsFlow ||
1186 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1189 port.c_cflag |= CRTSCTS;
1194 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1196 WARN("DSR/DTR flow control not supported\n");
1200 port.c_iflag |= IXON;
1202 port.c_iflag &= ~IXON;
1204 port.c_iflag |= IXOFF;
1206 port.c_iflag &= ~IXOFF;
1208 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1209 int save_error=errno;
1210 COMM_SetCommError(handle,CE_IOE);
1212 ERR("tcsetattr error '%s'\n", strerror(save_error));
1215 COMM_SetCommError(handle,0);
1222 /*****************************************************************************
1223 * GetCommState (KERNEL32.@)
1225 * Fills in a device control block with information from a communications device.
1229 * True on success, false if the communication device handle is bad etc
1233 * XonChar and XoffChar are not set.
1235 BOOL WINAPI GetCommState(
1236 HANDLE handle, /* [in] The communications device. */
1237 LPDCB lpdcb) /* [out] The device control block. */
1239 struct termios port;
1242 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1244 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1247 ERR("FILE_GetUnixHandle failed\n");
1250 if (tcgetattr(fd, &port) == -1) {
1251 int save_error=errno;
1252 ERR("tcgetattr error '%s'\n", strerror(save_error));
1253 COMM_SetCommError(handle,CE_IOE);
1260 speed= (port.c_cflag & CBAUD);
1262 speed= (cfgetospeed(&port));
1266 lpdcb->BaudRate = 110;
1269 lpdcb->BaudRate = 300;
1272 lpdcb->BaudRate = 600;
1275 lpdcb->BaudRate = 1200;
1278 lpdcb->BaudRate = 2400;
1281 lpdcb->BaudRate = 4800;
1284 lpdcb->BaudRate = 9600;
1287 lpdcb->BaudRate = 19200;
1290 lpdcb->BaudRate = 38400;
1294 lpdcb->BaudRate = 57600;
1299 lpdcb->BaudRate = 115200;
1304 lpdcb->BaudRate = 230400;
1309 lpdcb->BaudRate = 460800;
1313 ERR("unknown speed %x \n",speed);
1316 switch (port.c_cflag & CSIZE) {
1318 lpdcb->ByteSize = 5;
1321 lpdcb->ByteSize = 6;
1324 lpdcb->ByteSize = 7;
1327 lpdcb->ByteSize = 8;
1330 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1333 if(port.c_iflag & INPCK)
1334 lpdcb->fParity = TRUE;
1336 lpdcb->fParity = FALSE;
1338 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1340 switch (port.c_cflag & (PARENB | PARODD))
1344 lpdcb->Parity = NOPARITY;
1347 lpdcb->Parity = EVENPARITY;
1349 case (PARENB | PARODD):
1350 lpdcb->Parity = ODDPARITY;
1353 case (PARENB | CMSPAR):
1354 lpdcb->Parity = MARKPARITY;
1356 case (PARENB | PARODD | CMSPAR):
1357 lpdcb->Parity = SPACEPARITY;
1362 if (port.c_cflag & CSTOPB)
1363 if(lpdcb->ByteSize == 5)
1364 lpdcb->StopBits = ONE5STOPBITS;
1366 lpdcb->StopBits = TWOSTOPBITS;
1368 lpdcb->StopBits = ONESTOPBIT;
1373 /* termios does not support DTR/DSR flow control */
1374 lpdcb->fOutxDsrFlow = 0;
1375 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1379 if (port.c_cflag & CRTSCTS) {
1380 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1381 lpdcb->fOutxCtsFlow = 1;
1385 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1386 lpdcb->fOutxCtsFlow = 0;
1388 if (port.c_iflag & IXON)
1393 if (port.c_iflag & IXOFF)
1402 lpdcb->XoffLim = 10;
1404 COMM_SetCommError(handle,0);
1408 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1409 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1410 (lpdcb->StopBits == ONESTOPBIT)?1:
1411 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1412 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1413 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1415 if ( lpdcb->fOutxCtsFlow ||
1416 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1421 TRACE("~CRTSCTS\n");
1427 /*****************************************************************************
1428 * TransmitCommChar (KERNEL32.@)
1430 * Transmits a single character in front of any pending characters in the
1431 * output buffer. Usually used to send an interrupt character to a host.
1435 * True if the call succeeded, false if the previous command character to the
1436 * same device has not been sent yet the handle is bad etc.
1442 BOOL WINAPI TransmitCommChar(
1443 HANDLE hComm, /* [in] The communication device in need of a command character. */
1444 CHAR chTransmit) /* [in] The character to transmit. */
1449 WARN("(%x,'%c') not perfect!\n",hComm,chTransmit);
1451 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1453 SetLastError ( ERROR_INVALID_PARAMETER );
1456 r = (1 == write(fd, &chTransmit, 1));
1464 /*****************************************************************************
1465 * GetCommTimeouts (KERNEL32.@)
1467 * Obtains the request timeout values for the communications device.
1471 * True on success, false if communications device handle is bad
1472 * or the target structure is null.
1474 BOOL WINAPI GetCommTimeouts(
1475 HANDLE hComm, /* [in] The communications device. */
1476 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1480 TRACE("(%x,%p)\n",hComm,lptimeouts);
1484 SetLastError(ERROR_INVALID_PARAMETER);
1488 SERVER_START_REQ( get_serial_info )
1490 req->handle = hComm;
1491 if ((ret = !wine_server_call_err( req )))
1493 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1494 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1495 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1496 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1497 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1504 /*****************************************************************************
1505 * SetCommTimeouts (KERNEL32.@)
1507 * Sets the timeouts used when reading and writing data to/from COMM ports.
1509 * ReadIntervalTimeout
1510 * - converted and passes to linux kernel as c_cc[VTIME]
1511 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1512 * - used in ReadFile to calculate GetOverlappedResult's timeout
1513 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1514 * - used in WriteFile to calculate GetOverlappedResult's timeout
1518 * True if the timeouts were set, false otherwise.
1520 BOOL WINAPI SetCommTimeouts(
1521 HANDLE hComm, /* [in] handle of COMM device */
1522 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1526 struct termios tios;
1528 TRACE("(%x,%p)\n",hComm,lptimeouts);
1532 SetLastError(ERROR_INVALID_PARAMETER);
1536 SERVER_START_REQ( set_serial_info )
1538 req->handle = hComm;
1539 req->flags = SERIALINFO_SET_TIMEOUTS;
1540 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1541 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1542 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1543 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1544 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1545 ret = !wine_server_call_err( req );
1548 if (!ret) return FALSE;
1550 /* FIXME: move this stuff to the server */
1551 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1553 FIXME("no fd for handle = %0x!.\n",hComm);
1557 if (-1==tcgetattr(fd,&tios)) {
1558 FIXME("tcgetattr on fd %d failed!\n",fd);
1562 /* VTIME is in 1/10 seconds */
1564 unsigned int ux_timeout;
1566 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1572 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1575 ux_timeout = 1; /* must be at least some timeout */
1578 tios.c_cc[VTIME] = ux_timeout;
1581 if (-1==tcsetattr(fd,0,&tios)) {
1582 FIXME("tcsetattr on fd %d failed!\n",fd);
1589 /***********************************************************************
1590 * GetCommModemStatus (KERNEL32.@)
1592 * Obtains the four control register bits if supported by the hardware.
1596 * True if the communications handle was good and for hardware that
1597 * control register access, false otherwise.
1599 BOOL WINAPI GetCommModemStatus(
1600 HANDLE hFile, /* [in] The communications device. */
1601 LPDWORD lpModemStat) /* [out] The control register bits. */
1603 int fd,mstat, result=FALSE;
1607 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
1610 result = ioctl(fd, TIOCMGET, &mstat);
1614 WARN("ioctl failed\n");
1618 if (mstat & TIOCM_CTS)
1619 *lpModemStat |= MS_CTS_ON;
1622 if (mstat & TIOCM_DSR)
1623 *lpModemStat |= MS_DSR_ON;
1626 if (mstat & TIOCM_RNG)
1627 *lpModemStat |= MS_RING_ON;
1630 /*FIXME: Not really sure about RLSD UB 990810*/
1631 if (mstat & TIOCM_CAR)
1632 *lpModemStat |= MS_RLSD_ON;
1634 TRACE("%04x -> %s%s%s%s\n", mstat,
1635 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1636 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1637 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1638 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1645 /***********************************************************************
1646 * COMM_WaitCommEventService (INTERNAL)
1648 * This function is called while the client is waiting on the
1649 * server, so we can't make any server calls here.
1651 static void COMM_WaitCommEventService(async_private *ovp)
1653 async_commio *commio = (async_commio*) ovp;
1654 LPOVERLAPPED lpOverlapped = commio->lpOverlapped;
1656 TRACE("overlapped %p\n",lpOverlapped);
1658 /* FIXME: detect other events */
1659 *commio->buffer = EV_RXCHAR;
1661 lpOverlapped->Internal = STATUS_SUCCESS;
1665 /***********************************************************************
1666 * COMM_WaitCommEvent (INTERNAL)
1668 * This function must have an lpOverlapped.
1670 static BOOL COMM_WaitCommEvent(
1671 HANDLE hFile, /* [in] handle of comm port to wait for */
1672 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1673 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1680 SetLastError(ERROR_INVALID_PARAMETER);
1684 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1687 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
1691 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1698 ovp->async.ops = &commio_async_ops;
1699 ovp->async.handle = hFile;
1701 ovp->async.type = ASYNC_TYPE_WAIT;
1702 ovp->async.func = COMM_WaitCommEventService;
1703 ovp->async.event = lpOverlapped->hEvent;
1704 ovp->lpOverlapped = lpOverlapped;
1705 ovp->buffer = (char *)lpdwEvents;
1707 lpOverlapped->InternalHigh = 0;
1708 lpOverlapped->Offset = 0;
1709 lpOverlapped->OffsetHigh = 0;
1711 if ( !register_new_async (&ovp->async) )
1712 SetLastError( ERROR_IO_PENDING );
1717 /***********************************************************************
1718 * WaitCommEvent (KERNEL32.@)
1720 * Wait until something interesting happens on a COMM port.
1721 * Interesting things (events) are set by calling SetCommMask before
1722 * this function is called.
1725 * TRUE if successful
1728 * The set of detected events will be written to *lpdwEventMask
1729 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1732 * Only supports EV_RXCHAR and EV_TXEMPTY
1734 BOOL WINAPI WaitCommEvent(
1735 HANDLE hFile, /* [in] handle of comm port to wait for */
1736 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1737 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1742 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1745 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1747 /* if there is no overlapped structure, create our own */
1748 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1750 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1752 if(GetLastError()!=STATUS_PENDING)
1754 CloseHandle(ov.hEvent);
1758 /* wait for the overlapped to complete */
1759 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1760 CloseHandle(ov.hEvent);
1765 /***********************************************************************
1766 * GetCommProperties (KERNEL32.@)
1768 * This function fills in a structure with the capabilities of the
1769 * communications port driver.
1773 * TRUE on success, FALSE on failure
1774 * If successful, the lpCommProp structure be filled in with
1775 * properties of the comm port.
1777 BOOL WINAPI GetCommProperties(
1778 HANDLE hFile, /* [in] handle of the comm port */
1779 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1781 FIXME("(%d %p )\n",hFile,lpCommProp);
1786 * These values should be valid for LINUX's serial driver
1787 * FIXME: Perhaps they deserve an #ifdef LINUX
1789 memset(lpCommProp,0,sizeof(COMMPROP));
1790 lpCommProp->wPacketLength = 1;
1791 lpCommProp->wPacketVersion = 1;
1792 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1793 lpCommProp->dwReserved1 = 0;
1794 lpCommProp->dwMaxTxQueue = 4096;
1795 lpCommProp->dwMaxRxQueue = 4096;
1796 lpCommProp->dwMaxBaud = BAUD_115200;
1797 lpCommProp->dwProvSubType = PST_RS232;
1798 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1799 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1800 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1801 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1802 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1803 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1804 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1805 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1806 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1807 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1808 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1813 /***********************************************************************
1815 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1816 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1817 * This is dependent on the type of COMM port, but since it is doubtful
1818 * anybody will get around to implementing support for fancy serial
1819 * ports in WINE, this is hardcoded for the time being. The name of
1820 * this DLL should be stored in and read from the system registry in
1821 * the hive HKEY_LOCAL_MACHINE, key
1822 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1823 * where ???? is the port number... that is determined by PNP
1824 * The DLL should be loaded when the COMM port is opened, and closed
1825 * when the COMM port is closed. - MJM 20 June 2000
1826 ***********************************************************************/
1827 static CHAR lpszSerialUI[] = "serialui.dll";
1830 /***********************************************************************
1831 * CommConfigDialogA (KERNEL32.@)
1833 * Raises a dialog that allows the user to configure a comm port.
1834 * Fills the COMMCONFIG struct with information specified by the user.
1835 * This function should call a similar routine in the COMM driver...
1839 * TRUE on success, FALSE on failure
1840 * If successful, the lpCommConfig structure will contain a new
1841 * configuration for the comm port, as specified by the user.
1844 * The library with the CommConfigDialog code is never unloaded.
1845 * Perhaps this should be done when the comm port is closed?
1847 BOOL WINAPI CommConfigDialogA(
1848 LPCSTR lpszDevice, /* [in] name of communications device */
1849 HANDLE hWnd, /* [in] parent window for the dialog */
1850 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1852 FARPROC lpfnCommDialog;
1853 HMODULE hConfigModule;
1856 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
1858 hConfigModule = LoadLibraryA(lpszSerialUI);
1862 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
1867 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1869 /* UnloadLibrary(hConfigModule); */
1874 /***********************************************************************
1875 * CommConfigDialogW (KERNEL32.@)
1877 * see CommConfigDialogA for more info
1879 BOOL WINAPI CommConfigDialogW(
1880 LPCWSTR lpszDevice, /* [in] name of communications device */
1881 HANDLE hWnd, /* [in] parent window for the dialog */
1882 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1887 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1890 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
1891 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1895 /***********************************************************************
1896 * GetCommConfig (KERNEL32.@)
1898 * Fill in the COMMCONFIG structure for the comm port hFile
1902 * TRUE on success, FALSE on failure
1903 * If successful, lpCommConfig contains the comm port configuration.
1908 BOOL WINAPI GetCommConfig(
1909 HANDLE hFile, /* [in] The communications device. */
1910 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1911 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1912 afterwards the number of bytes copied to the buffer or
1913 the needed size of the buffer. */
1917 TRACE("(%x %p)\n",hFile,lpCommConfig);
1919 if(lpCommConfig == NULL)
1922 r = *lpdwSize < sizeof(COMMCONFIG);
1923 *lpdwSize = sizeof(COMMCONFIG);
1927 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1928 lpCommConfig->wVersion = 1;
1929 lpCommConfig->wReserved = 0;
1930 r = GetCommState(hFile,&lpCommConfig->dcb);
1931 lpCommConfig->dwProviderSubType = PST_RS232;
1932 lpCommConfig->dwProviderOffset = 0;
1933 lpCommConfig->dwProviderSize = 0;
1938 /***********************************************************************
1939 * SetCommConfig (KERNEL32.@)
1941 * Sets the configuration of the communications device.
1945 * True on success, false if the handle was bad is not a communications device.
1947 BOOL WINAPI SetCommConfig(
1948 HANDLE hFile, /* [in] The communications device. */
1949 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1950 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1952 TRACE("(%x %p)\n",hFile,lpCommConfig);
1953 return SetCommState(hFile,&lpCommConfig->dcb);
1956 /***********************************************************************
1957 * SetDefaultCommConfigA (KERNEL32.@)
1959 * Initializes the default configuration for the specified communication
1964 * True if the device was found and the defaults set, false otherwise
1966 BOOL WINAPI SetDefaultCommConfigA(
1967 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1968 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1969 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1971 FARPROC lpfnSetDefaultCommConfig;
1972 HMODULE hConfigModule;
1975 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1977 hConfigModule = LoadLibraryA(lpszSerialUI);
1981 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
1983 if(! lpfnSetDefaultCommConfig)
1986 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1988 /* UnloadLibrary(hConfigModule); */
1994 /***********************************************************************
1995 * SetDefaultCommConfigW (KERNEL32.@)
1997 * Initializes the default configuration for the specified
1998 * communication device. (unicode)
2003 BOOL WINAPI SetDefaultCommConfigW(
2004 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2005 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2006 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2011 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2013 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2016 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2017 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2022 /***********************************************************************
2023 * GetDefaultCommConfigA (KERNEL32.@)
2025 * Acquires the default configuration of the specified communication device. (unicode)
2029 * True on successful reading of the default configuration,
2030 * if the device is not found or the buffer is too small.
2032 BOOL WINAPI GetDefaultCommConfigA(
2033 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2034 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2035 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2036 afterwards the number of bytes copied to the buffer or
2037 the needed size of the buffer. */
2039 LPDCB lpdcb = &(lpCC->dcb);
2042 if (strncasecmp(lpszName,"COM",3)) {
2043 ERR("not implemented for <%s>\n", lpszName);
2047 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2048 if (*lpdwSize < sizeof(COMMCONFIG)) {
2049 *lpdwSize = sizeof(COMMCONFIG);
2053 *lpdwSize = sizeof(COMMCONFIG);
2055 lpCC->dwSize = sizeof(COMMCONFIG);
2057 lpCC->dwProviderSubType = PST_RS232;
2058 lpCC->dwProviderOffset = 0L;
2059 lpCC->dwProviderSize = 0L;
2061 sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2062 FIXME("setting %s as default\n", temp);
2064 return BuildCommDCBA( temp, lpdcb);
2067 /**************************************************************************
2068 * GetDefaultCommConfigW (KERNEL32.@)
2070 * Acquires the default configuration of the specified communication device. (unicode)
2074 * True on successful reading of the default configuration,
2075 * if the device is not found or the buffer is too small.
2077 BOOL WINAPI GetDefaultCommConfigW(
2078 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2079 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2080 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2081 afterwards the number of bytes copied to the buffer or
2082 the needed size of the buffer. */
2087 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2088 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2091 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2092 HeapFree( GetProcessHeap(), 0, lpszNameA );