*
* Copyright 1996 Marcus Meissner
*
- * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
- * - Implemented buffers and EnableCommNotification.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * History:
*
* Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
* - Fixed the modem control part of EscapeCommFunction16.
*
+ * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
+ * - Implemented buffers and EnableCommNotification.
+ *
* Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
* - Use port indices instead of unixfds for win16
* - Moved things around (separated win16 and win32 routines)
* - Added some hints on how to implement buffers and EnableCommNotification.
*
+ * Oktober 98, Rein Klazes [RHK]
+ * A program that wants to monitor the modem status line (RLSD/DCD) may
+ * poll the modem status register in the commMask structure. I update the bit
+ * in GetCommError, waiting for an implementation of communication events.
+ *
+ * July 6, 1998. Fixes and comments by Valentijn Sessink
+ * <vsessink@ic.uva.nl> [V]
+ *
+ * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
+ * <lawson_whitney@juno.com>
+ *
* May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
* - ptr->fd wasn't getting cleared on close.
* - GetCommEventMask() and GetCommError() didn't do much of anything.
* IMHO, they are still wrong, but they at least implement the RXCHAR
* event and return I/O queue sizes, which makes the app I'm interested
* in (analog devices EZKIT DSP development system) work.
- *
- * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
- * <lawson_whitney@juno.com>
- * July 6, 1998. Fixes and comments by Valentijn Sessink
- * <vsessink@ic.uva.nl> [V]
- * Oktober 98, Rein Klazes [RHK]
- * A program that wants to monitor the modem status line (RLSD/DCD) may
- * poll the modem status register in the commMask structure. I update the bit
- * in GetCommError, waiting for an implementation of communication events.
- *
*/
#include "config.h"
#include "wine/port.h"
#include <stdlib.h>
+#include <stdarg.h>
#include <stdio.h>
+#ifdef HAVE_TERMIOS_H
#include <termios.h>
+#endif
#include <fcntl.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_SYS_FILIO_H
# include <sys/filio.h>
#endif
+#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
-#include <unistd.h>
-#include <sys/poll.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
#ifdef HAVE_SYS_MODEM_H
# include <sys/modem.h>
#endif
# include <sys/strtio.h>
#endif
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "ntstatus.h"
+#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/server.h"
-#include "file.h"
-#include "heap.h"
-
-#include "debugtools.h"
+#include "wine/unicode.h"
+#include "thread.h"
-DEFAULT_DEBUG_CHANNEL(comm);
+#include "wine/debug.h"
-#if !defined(TIOCINQ) && defined(FIONREAD)
-#define TIOCINQ FIONREAD
+#ifdef HAVE_LINUX_SERIAL_H
+#include <linux/serial.h>
#endif
-static int WinError(void)
+WINE_DEFAULT_DEBUG_CHANNEL(comm);
+
+/* retrieve the Unix handle corresponding to a comm handle */
+static int get_comm_fd( HANDLE handle, DWORD access )
{
- TRACE("errno = %d\n", errno);
- switch (errno) {
- default:
- return CE_IOE;
- }
+ int fd, ret;
+
+ ret = wine_server_handle_to_fd( handle, access, &fd, NULL );
+ if (ret) SetLastError( RtlNtStatusToDosError(ret) );
+ return fd;
}
+/* release the Unix handle returned by get_comm_fd */
+static inline void release_comm_fd( HANDLE handle, int fd )
+{
+ wine_server_release_fd( handle, fd );
+}
+
+
+/***********************************************************************
+ * Asynchronous I/O for asynchronous wait requests *
+ */
+
+typedef struct async_commio
+{
+ HANDLE handle;
+ PIO_APC_ROUTINE apc_internal;
+ int type;
+ char* buffer;
+ int fd;
+} async_commio;
+
+/***********************************************************************/
+
+#if !defined(TIOCINQ) && defined(FIONREAD)
+#define TIOCINQ FIONREAD
+#endif
+
static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
{
+#ifdef TIOCMGET
unsigned int mstat, okay;
okay = ioctl(fd, TIOCMGET, &mstat);
if (okay) return okay;
if (andy) mstat &= andy;
mstat |= orrie;
return ioctl(fd, TIOCMSET, &mstat);
+#else
+ return 0;
+#endif
}
/***********************************************************************
- * COMM_BuildOldCommDCB (Internal)
+ * COMM_Parse* (Internal)
*
- * Build a DCB using the old style settings string eg: "COMx:96,n,8,1"
- * We ignore the COM port index, since we can support more than 4 ports.
+ * The following COMM_Parse* functions are used by the BuildCommDCB
+ * functions to help parse the various parts of the device control string.
*/
-BOOL WINAPI COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
+static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
{
- /* "COM1:96,n,8,1" */
- /* 012345 */
- char *ptr, temp[256], last;
- int rate;
+ static const WCHAR comW[] = {'C','O','M',0};
- TRACE("(%s), ptr %p\n", device, lpdcb);
+ /* The device control string may optionally start with "COMx" followed
+ by an optional ':' and spaces. */
+ if(!strncmpiW(ptr, comW, 3))
+ {
+ ptr += 3;
+
+ /* Allow any com port above 0 as Win 9x does (NT only allows
+ values for com ports which are actually present) */
+ if(*ptr < '1' || *ptr > '9')
+ return NULL;
+
+ /* Advance pointer past port number */
+ while(*ptr >= '0' && *ptr <= '9') ptr++;
+
+ /* The com port number must be followed by a ':' or ' ' */
+ if(*ptr != ':' && *ptr != ' ')
+ return NULL;
+
+ /* Advance pointer to beginning of next parameter */
+ while(*ptr == ' ') ptr++;
+ if(*ptr == ':')
+ {
+ ptr++;
+ while(*ptr == ' ') ptr++;
+ }
+ }
+ /* The device control string must not start with a space. */
+ else if(*ptr == ' ')
+ return NULL;
+
+ return ptr;
+}
+
+static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
+{
+ if(*ptr < '0' || *ptr > '9') return NULL;
+ *lpnumber = strtoulW(ptr, NULL, 10);
+ while(*ptr >= '0' && *ptr <= '9') ptr++;
+ return ptr;
+}
- if (strncasecmp(device,"COM",3))
- return FALSE;
+static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
+{
+ /* Contrary to what you might expect, Windows only sets the Parity
+ member of DCB and not fParity even when parity is specified in the
+ device control string */
- if (!*(device+4))
- return FALSE;
+ switch(toupperW(*ptr++))
+ {
+ case 'E':
+ *lpparity = EVENPARITY;
+ break;
+ case 'M':
+ *lpparity = MARKPARITY;
+ break;
+ case 'N':
+ *lpparity = NOPARITY;
+ break;
+ case 'O':
+ *lpparity = ODDPARITY;
+ break;
+ case 'S':
+ *lpparity = SPACEPARITY;
+ break;
+ default:
+ return NULL;
+ }
- if (*(device+4) != ':')
- return FALSE;
+ return ptr;
+}
+
+static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
+{
+ DWORD temp;
+
+ if(!(ptr = COMM_ParseNumber(ptr, &temp)))
+ return NULL;
+
+ if(temp >= 5 && temp <= 8)
+ {
+ *lpbytesize = temp;
+ return ptr;
+ }
+ else
+ return NULL;
+}
+
+static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
+{
+ DWORD temp;
+ static const WCHAR stopbits15W[] = {'1','.','5',0};
+
+ if(!strncmpW(stopbits15W, ptr, 3))
+ {
+ ptr += 3;
+ *lpstopbits = ONE5STOPBITS;
+ }
+ else
+ {
+ if(!(ptr = COMM_ParseNumber(ptr, &temp)))
+ return NULL;
+
+ if(temp == 1)
+ *lpstopbits = ONESTOPBIT;
+ else if(temp == 2)
+ *lpstopbits = TWOSTOPBITS;
+ else
+ return NULL;
+ }
- strcpy(temp,device+5);
- last=temp[strlen(temp)-1];
- ptr = strtok(temp, ", ");
-
- /* DOS/Windows only compares the first two numbers
- * and assigns an appropriate baud rate.
- * You can supply 961324245, it still returns 9600 ! */
- if (strlen(ptr) < 2)
+ return ptr;
+}
+
+static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
+{
+ static const WCHAR onW[] = {'o','n',0};
+ static const WCHAR offW[] = {'o','f','f',0};
+
+ if(!strncmpiW(onW, ptr, 2))
+ {
+ ptr += 2;
+ *lponoff = 1;
+ }
+ else if(!strncmpiW(offW, ptr, 3))
{
- WARN("Unknown baudrate string '%s' !\n", ptr);
- return FALSE; /* error: less than 2 chars */
+ ptr += 3;
+ *lponoff = 0;
}
- ptr[2] = '\0';
- rate = atoi(ptr);
+ else
+ return NULL;
+
+ return ptr;
+}
+
+/***********************************************************************
+ * COMM_BuildOldCommDCB (Internal)
+ *
+ * Build a DCB using the old style settings string eg: "96,n,8,1"
+ */
+static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
+{
+ WCHAR last = 0;
- switch (rate) {
+ if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
+ return FALSE;
+
+ switch(lpdcb->BaudRate)
+ {
case 11:
case 30:
case 60:
- rate *= 10;
+ lpdcb->BaudRate *= 10;
break;
case 12:
case 24:
case 48:
case 96:
- rate *= 100;
+ lpdcb->BaudRate *= 100;
break;
case 19:
- rate = 19200;
+ lpdcb->BaudRate = 19200;
break;
- default:
- WARN("Unknown baudrate indicator %d !\n", rate);
- return FALSE;
}
-
- lpdcb->BaudRate = rate;
- TRACE("baudrate (%ld)\n", lpdcb->BaudRate);
- ptr = strtok(NULL, ", ");
- if (islower(*ptr))
- *ptr = toupper(*ptr);
+ while(*device == ' ') device++;
+ if(*device++ != ',') return FALSE;
+ while(*device == ' ') device++;
- TRACE("parity (%c)\n", *ptr);
- lpdcb->fParity = TRUE;
- switch (*ptr) {
- case 'N':
- lpdcb->Parity = NOPARITY;
- lpdcb->fParity = FALSE;
- break;
- case 'E':
- lpdcb->Parity = EVENPARITY;
- break;
- case 'M':
- lpdcb->Parity = MARKPARITY;
- break;
- case 'O':
- lpdcb->Parity = ODDPARITY;
- break;
- default:
- WARN("Unknown parity `%c'!\n", *ptr);
+ if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
+ return FALSE;
+
+ while(*device == ' ') device++;
+ if(*device++ != ',') return FALSE;
+ while(*device == ' ') device++;
+
+ if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
return FALSE;
+
+ while(*device == ' ') device++;
+ if(*device++ != ',') return FALSE;
+ while(*device == ' ') device++;
+
+ if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
+ return FALSE;
+
+ /* The last parameter for flow control is optional. */
+ while(*device == ' ') device++;
+ if(*device == ',')
+ {
+ device++;
+ while(*device == ' ') device++;
+ if(*device) last = toupperW(*device++);
+ while(*device == ' ') device++;
}
- ptr = strtok(NULL, ", ");
- TRACE("charsize (%c)\n", *ptr);
- lpdcb->ByteSize = *ptr - '0';
-
- ptr = strtok(NULL, ", ");
- TRACE("stopbits (%c)\n", *ptr);
- switch (*ptr) {
- case '1':
- lpdcb->StopBits = ONESTOPBIT;
- break;
- case '2':
- lpdcb->StopBits = TWOSTOPBITS;
- break;
+ /* Win NT sets the flow control members based on (or lack of) the last
+ parameter. Win 9x does not set these members. */
+ switch(last)
+ {
+ case 0:
+ lpdcb->fInX = FALSE;
+ lpdcb->fOutX = FALSE;
+ lpdcb->fOutxCtsFlow = FALSE;
+ lpdcb->fOutxDsrFlow = FALSE;
+ lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
+ lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
+ break;
+ case 'X':
+ lpdcb->fInX = TRUE;
+ lpdcb->fOutX = TRUE;
+ lpdcb->fOutxCtsFlow = FALSE;
+ lpdcb->fOutxDsrFlow = FALSE;
+ lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
+ lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
+ break;
+ case 'P':
+ lpdcb->fInX = FALSE;
+ lpdcb->fOutX = FALSE;
+ lpdcb->fOutxCtsFlow = TRUE;
+ lpdcb->fOutxDsrFlow = TRUE;
+ lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
+ lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
+ break;
default:
- WARN("Unknown # of stopbits `%c'!\n", *ptr);
return FALSE;
- }
+ }
- if (last == 'x') {
- lpdcb->fInX = TRUE;
- lpdcb->fOutX = TRUE;
- lpdcb->fOutxCtsFlow = FALSE;
- lpdcb->fOutxDsrFlow = FALSE;
- lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
- lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
- } else if (last=='p') {
- lpdcb->fInX = FALSE;
- lpdcb->fOutX = FALSE;
- lpdcb->fOutxCtsFlow = TRUE;
- lpdcb->fOutxDsrFlow = TRUE;
- lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
- lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
- } else {
- lpdcb->fInX = FALSE;
- lpdcb->fOutX = FALSE;
- lpdcb->fOutxCtsFlow = FALSE;
- lpdcb->fOutxDsrFlow = FALSE;
- lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
- lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
+ /* This should be the end of the string. */
+ if(*device) return FALSE;
+
+ return TRUE;
+}
+
+/***********************************************************************
+ * COMM_BuildNewCommDCB (Internal)
+ *
+ * Build a DCB using the new style settings string.
+ * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
+ */
+static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
+{
+ DWORD temp;
+ BOOL baud = FALSE, stop = FALSE;
+ static const WCHAR baudW[] = {'b','a','u','d','=',0};
+ static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
+ static const WCHAR dataW[] = {'d','a','t','a','=',0};
+ static const WCHAR stopW[] = {'s','t','o','p','=',0};
+ static const WCHAR toW[] = {'t','o','=',0};
+ static const WCHAR xonW[] = {'x','o','n','=',0};
+ static const WCHAR odsrW[] = {'o','d','s','r','=',0};
+ static const WCHAR octsW[] = {'o','c','t','s','=',0};
+ static const WCHAR dtrW[] = {'d','t','r','=',0};
+ static const WCHAR rtsW[] = {'r','t','s','=',0};
+ static const WCHAR idsrW[] = {'i','d','s','r','=',0};
+
+ while(*device)
+ {
+ while(*device == ' ') device++;
+
+ if(!strncmpiW(baudW, device, 5))
+ {
+ baud = TRUE;
+
+ if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
+ return FALSE;
+ }
+ else if(!strncmpiW(parityW, device, 7))
+ {
+ if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
+ return FALSE;
+ }
+ else if(!strncmpiW(dataW, device, 5))
+ {
+ if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
+ return FALSE;
+ }
+ else if(!strncmpiW(stopW, device, 5))
+ {
+ stop = TRUE;
+
+ if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
+ return FALSE;
+ }
+ else if(!strncmpiW(toW, device, 3))
+ {
+ if(!(device = COMM_ParseOnOff(device + 3, &temp)))
+ return FALSE;
+
+ lptimeouts->ReadIntervalTimeout = 0;
+ lptimeouts->ReadTotalTimeoutMultiplier = 0;
+ lptimeouts->ReadTotalTimeoutConstant = 0;
+ lptimeouts->WriteTotalTimeoutMultiplier = 0;
+ lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
+ }
+ else if(!strncmpiW(xonW, device, 4))
+ {
+ if(!(device = COMM_ParseOnOff(device + 4, &temp)))
+ return FALSE;
+
+ lpdcb->fOutX = temp;
+ lpdcb->fInX = temp;
+ }
+ else if(!strncmpiW(odsrW, device, 5))
+ {
+ if(!(device = COMM_ParseOnOff(device + 5, &temp)))
+ return FALSE;
+
+ lpdcb->fOutxDsrFlow = temp;
+ }
+ else if(!strncmpiW(octsW, device, 5))
+ {
+ if(!(device = COMM_ParseOnOff(device + 5, &temp)))
+ return FALSE;
+
+ lpdcb->fOutxCtsFlow = temp;
+ }
+ else if(!strncmpiW(dtrW, device, 4))
+ {
+ if(!(device = COMM_ParseOnOff(device + 4, &temp)))
+ return FALSE;
+
+ lpdcb->fDtrControl = temp;
+ }
+ else if(!strncmpiW(rtsW, device, 4))
+ {
+ if(!(device = COMM_ParseOnOff(device + 4, &temp)))
+ return FALSE;
+
+ lpdcb->fRtsControl = temp;
+ }
+ else if(!strncmpiW(idsrW, device, 5))
+ {
+ if(!(device = COMM_ParseOnOff(device + 5, &temp)))
+ return FALSE;
+
+ /* Win NT sets the fDsrSensitivity member based on the
+ idsr parameter. Win 9x sets fOutxDsrFlow instead. */
+ lpdcb->fDsrSensitivity = temp;
+ }
+ else
+ return FALSE;
+
+ /* After the above parsing, the next character (if not the end of
+ the string) should be a space */
+ if(*device && *device != ' ')
+ return FALSE;
+ }
+
+ /* If stop bits were not specified, a default is always supplied. */
+ if(!stop)
+ {
+ if(baud && lpdcb->BaudRate == 110)
+ lpdcb->StopBits = TWOSTOPBITS;
+ else
+ lpdcb->StopBits = ONESTOPBIT;
}
- return 0;
+ return TRUE;
}
/**************************************************************************
*
* RETURNS
*
- * True on success, false on an malformed control string.
+ * True on success, false on a malformed control string.
*/
BOOL WINAPI BuildCommDCBA(
LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
}
/**************************************************************************
- * BuildCommDCBAndTimeoutsA (KERNEL32.@)
+ * BuildCommDCBAndTimeoutsA (KERNEL32.@)
*
* Updates a device control block data structure with values from an
- * ascii device control string. Taking time out values from a time outs
+ * ascii device control string. Taking timeout values from a timeouts
* struct if desired by the control string.
*
* RETURNS
*
- * True on success, false bad handles etc
+ * True on success, false bad handles etc.
*/
BOOL WINAPI BuildCommDCBAndTimeoutsA(
LPCSTR device, /* [in] The ascii device control string. */
LPDCB lpdcb, /* [out] The device control block to be updated. */
- LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
+ LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
{
- int port;
- char *ptr,*temp;
+ BOOL ret = FALSE;
+ UNICODE_STRING deviceW;
TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
+ if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
+ else deviceW.Buffer = NULL;
- if (!strncasecmp(device,"COM",3)) {
- port=device[3]-'0';
- if (port--==0) {
- ERR("BUG! COM0 can't exist!\n");
- return FALSE;
- }
- if (*(device+4)!=':')
- return FALSE;
- temp=(LPSTR)(device+5);
- } else
- temp=(LPSTR)device;
+ if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
- memset(lpdcb,0,sizeof (DCB));
- lpdcb->DCBlength = sizeof(DCB);
- if (strchr(temp,',')) { /* old style */
-
- return COMM_BuildOldCommDCB(device,lpdcb);
- }
- ptr=strtok(temp," ");
- while (ptr) {
- DWORD flag,x;
-
- flag=0;
- if (!strncmp("baud=",ptr,5)) {
- if (!sscanf(ptr+5,"%ld",&x))
- WARN("Couldn't parse %s\n",ptr);
- lpdcb->BaudRate = x;
- flag=1;
- }
- if (!strncmp("stop=",ptr,5)) {
- if (!sscanf(ptr+5,"%ld",&x))
- WARN("Couldn't parse %s\n",ptr);
- lpdcb->StopBits = x;
- flag=1;
- }
- if (!strncmp("data=",ptr,5)) {
- if (!sscanf(ptr+5,"%ld",&x))
- WARN("Couldn't parse %s\n",ptr);
- lpdcb->ByteSize = x;
- flag=1;
- }
- if (!strncmp("parity=",ptr,7)) {
- lpdcb->fParity = TRUE;
- switch (ptr[8]) {
- case 'N':case 'n':
- lpdcb->fParity = FALSE;
- lpdcb->Parity = NOPARITY;
- break;
- case 'E':case 'e':
- lpdcb->Parity = EVENPARITY;
- break;
- case 'O':case 'o':
- lpdcb->Parity = ODDPARITY;
- break;
- case 'M':case 'm':
- lpdcb->Parity = MARKPARITY;
- break;
- }
- flag=1;
- }
- if (!flag)
- ERR("Unhandled specifier '%s', please report.\n",ptr);
- ptr=strtok(NULL," ");
- }
- if (lpdcb->BaudRate==110)
- lpdcb->StopBits = 2;
- return TRUE;
+ RtlFreeUnicodeString(&deviceW);
+ return ret;
}
/**************************************************************************
- * BuildCommDCBAndTimeoutsW (KERNEL32.@)
+ * BuildCommDCBAndTimeoutsW (KERNEL32.@)
*
- * Updates a device control block data structure with values from an
- * unicode device control string. Taking time out values from a time outs
+ * Updates a device control block data structure with values from a
+ * unicode device control string. Taking timeout values from a timeouts
* struct if desired by the control string.
*
* RETURNS
*
- * True on success, false bad handles etc.
+ * True on success, false bad handles etc
*/
BOOL WINAPI BuildCommDCBAndTimeoutsW(
LPCWSTR devid, /* [in] The unicode device control string. */
LPDCB lpdcb, /* [out] The device control block to be updated. */
- LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
+ LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
{
- BOOL ret = FALSE;
- LPSTR devidA;
+ DCB dcb;
+ COMMTIMEOUTS timeouts;
+ BOOL result;
+ LPCWSTR ptr = devid;
+
+ TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
- TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
- devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
- if (devidA)
+ /* Set DCBlength. (Windows NT does not do this, but 9x does) */
+ lpdcb->DCBlength = sizeof(DCB);
+
+ /* Make a copy of the original data structures to work with since if
+ if there is an error in the device control string the originals
+ should not be modified (except possibly DCBlength) */
+ memcpy(&dcb, lpdcb, sizeof(DCB));
+ if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
+
+ ptr = COMM_ParseStart(ptr);
+
+ if(ptr == NULL)
+ result = FALSE;
+ else if(strchrW(ptr, ','))
+ result = COMM_BuildOldCommDCB(ptr, &dcb);
+ else
+ result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
+
+ if(result)
{
- ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
- HeapFree( GetProcessHeap(), 0, devidA );
+ memcpy(lpdcb, &dcb, sizeof(DCB));
+ if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
+ return TRUE;
}
- return ret;
+ else
+ {
+ WARN("Invalid device control string: %s\n", debugstr_w(devid));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
}
/**************************************************************************
return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
}
-/* FIXME: having these global for win32 for now */
-int commerror=0;
+static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
+{
+ DWORD ret;
+
+ SERVER_START_REQ( set_serial_info )
+ {
+ req->handle = handle;
+ req->flags = SERIALINFO_SET_ERROR;
+ req->commerror = error;
+ ret = !wine_server_call_err( req );
+ }
+ SERVER_END_REQ;
+ return ret;
+}
+
+static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
+{
+ DWORD ret;
+
+ if(!lperror)
+ return FALSE;
+
+ SERVER_START_REQ( get_serial_info )
+ {
+ req->handle = handle;
+ ret = !wine_server_call_err( req );
+ *lperror = reply->commerror;
+ }
+ SERVER_END_REQ;
+
+ return ret;
+}
/*****************************************************************************
* SetCommBreak (KERNEL32.@)
*
* BUGS
*
- * Only TIOCSBRK and TIOCCBRK are supported.
+ * Only TIOCSBRK and TIOCCBRK are supported.
*/
BOOL WINAPI SetCommBreak(
- HANDLE handle) /* [in] The communictions device to suspend. */
+ HANDLE handle) /* [in] The communications device to suspend. */
{
#if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
int fd,result;
-
- fd = FILE_GetUnixHandle( handle, GENERIC_READ );
- if(fd<0) {
- TRACE("FILE_GetUnixHandle failed\n");
- return FALSE;
- }
+
+ fd = get_comm_fd( handle, GENERIC_READ );
+ if(fd<0) return FALSE;
result = ioctl(fd,TIOCSBRK,0);
- close(fd);
+ release_comm_fd( handle, fd );
if (result ==-1)
{
TRACE("ioctl failed\n");
*
* BUGS
*
- * Only TIOCSBRK and TIOCCBRK are supported.
+ * Only TIOCSBRK and TIOCCBRK are supported.
*/
BOOL WINAPI ClearCommBreak(
HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
{
#if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
int fd,result;
-
- fd = FILE_GetUnixHandle( handle, GENERIC_READ );
- if(fd<0) {
- TRACE("FILE_GetUnixHandle failed\n");
- return FALSE;
- }
+
+ fd = get_comm_fd( handle, GENERIC_READ );
+ if(fd<0) return FALSE;
result = ioctl(fd,TIOCCBRK,0);
- close(fd);
+ release_comm_fd( handle, fd );
if (result ==-1)
{
TRACE("ioctl failed\n");
int fd,direct=FALSE,result=FALSE;
struct termios port;
- TRACE("handle %d, function=%d\n", handle, nFunction);
- fd = FILE_GetUnixHandle( handle, GENERIC_READ );
- if(fd<0) {
- FIXME("handle %d not found.\n",handle);
- return FALSE;
- }
+ TRACE("handle %p, function=%d\n", handle, nFunction);
+ fd = get_comm_fd( handle, GENERIC_READ );
+ if(fd<0) return FALSE;
if (tcgetattr(fd,&port) == -1) {
- commerror=WinError();
- close(fd);
+ COMM_SetCommError(handle,CE_IOE);
+ release_comm_fd( handle, fd );
return FALSE;
}
switch (nFunction) {
case RESETDEV:
TRACE("\n");
- break;
+ break;
case CLRDTR:
TRACE("CLRDTR\n");
result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
break;
#endif
-
+
case SETDTR:
TRACE("SETDTR\n");
#ifdef TIOCM_DTR
case SETRTS:
TRACE("SETRTS\n");
-#ifdef TIOCM_DTR
+#ifdef TIOCM_RTS
direct=TRUE;
result= COMM_WhackModem(fd, 0, TIOCM_RTS);
break;
break;
#endif
default:
- WARN("(handle=%d,nFunction=%d): Unknown function\n",
+ WARN("(handle=%p,nFunction=%d): Unknown function\n",
handle, nFunction);
- break;
+ break;
}
-
+
if (!direct)
if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
- commerror = WinError();
- close(fd);
- return FALSE;
- } else
+ release_comm_fd( handle, fd );
+ COMM_SetCommError(handle,CE_IOE);
+ return FALSE;
+ } else
result= TRUE;
else
{
if (result == -1)
{
result= FALSE;
- commerror=WinError();
+ COMM_SetCommError(handle,CE_IOE);
}
else
result = TRUE;
}
- close(fd);
+ release_comm_fd( handle, fd );
return result;
}
{
int fd;
- TRACE("handle %d, flags %lx\n", handle, flags);
+ TRACE("handle %p, flags %lx\n", handle, flags);
- fd = FILE_GetUnixHandle( handle, GENERIC_READ );
- if(fd<0) {
- FIXME("no handle %d found\n",handle);
- return FALSE;
- }
+ fd = get_comm_fd( handle, GENERIC_READ );
+ if(fd<0) return FALSE;
/*
** not exactly sure how these are different
tcflush(fd,TCOFLUSH);
if(flags&PURGE_RXCLEAR)
tcflush(fd,TCIFLUSH);
- close(fd);
+ release_comm_fd( handle, fd );
return 1;
}
{
int fd;
- fd=FILE_GetUnixHandle( handle, GENERIC_READ );
- if(0>fd)
- {
- FIXME("no handle %d found\n",handle);
- return FALSE;
- }
+ fd=get_comm_fd( handle, GENERIC_READ );
+ if(0>fd) return FALSE;
- if (lpStat)
+ if (lpStat)
{
- lpStat->status = 0;
+ lpStat->fCtsHold = 0;
+ lpStat->fDsrHold = 0;
+ lpStat->fRlsdHold = 0;
+ lpStat->fXoffHold = 0;
+ lpStat->fXoffSent = 0;
+ lpStat->fEof = 0;
+ lpStat->fTxim = 0;
+ lpStat->fReserved = 0;
#ifdef TIOCOUTQ
if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
WARN("ioctl returned error\n");
#endif
- TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
+ TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
handle, lpStat->cbInQue, lpStat->cbOutQue);
}
- close(fd);
+ release_comm_fd( handle, fd );
- if(errors)
- *errors = 0;
-
- /*
- ** After an asynchronous write opperation, the
- ** app will call ClearCommError to see if the
- ** results are ready yet. It waits for ERROR_IO_PENDING
- */
- commerror = ERROR_IO_PENDING;
+ COMM_GetCommError(handle, errors);
+ COMM_SetCommError(handle, 0);
return TRUE;
}
int fd;
FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
- fd=FILE_GetUnixHandle( handle, GENERIC_READ );
- if(0>fd) {
- FIXME("handle %d not found?\n",handle);
- return FALSE;
- }
- close(fd);
+ fd=get_comm_fd( handle, GENERIC_READ );
+ if(0>fd) return FALSE;
+ release_comm_fd( handle, fd );
return TRUE;
-}
+}
/*****************************************************************************
* GetCommMask (KERNEL32.@)
*
- * Obtain the events associated with a communication device that will cause a call
- * WaitCommEvent to return.
+ * Obtain the events associated with a communication device that will cause
+ * a call WaitCommEvent to return.
*
* RETURNS
*
{
BOOL ret;
- TRACE("handle %d, mask %p\n", handle, evtmask);
+ TRACE("handle %p, mask %p\n", handle, evtmask);
SERVER_START_REQ( get_serial_info )
{
req->handle = handle;
- if ((ret = !SERVER_CALL_ERR()))
+ if ((ret = !wine_server_call_err( req )))
{
- if (evtmask) *evtmask = req->eventmask;
+ if (evtmask) *evtmask = reply->eventmask;
}
}
SERVER_END_REQ;
*/
BOOL WINAPI SetCommMask(
HANDLE handle, /* [in] The communications device. */
- DWORD evtmask) /* [in] The events that to be monitored. */
+ DWORD evtmask) /* [in] The events that are to be monitored. */
{
BOOL ret;
- TRACE("handle %d, mask %lx\n", handle, evtmask);
+ TRACE("handle %p, mask %lx\n", handle, evtmask);
SERVER_START_REQ( set_serial_info )
{
req->handle = handle;
req->flags = SERIALINFO_SET_MASK;
req->eventmask = evtmask;
- ret = !SERVER_CALL_ERR();
+ ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
return ret;
{
struct termios port;
int fd, bytesize, stopbits;
+ BOOL ret;
- TRACE("handle %d, ptr %p\n", handle, lpdcb);
+ TRACE("handle %p, ptr %p\n", handle, lpdcb);
TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
(lpdcb->StopBits == ONESTOPBIT)?1:
(lpdcb->StopBits == TWOSTOPBITS)?2:0);
TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
(lpdcb->fOutX)?"IXOFF":"~IXOFF");
+ TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
+ lpdcb->fRtsControl);
+ TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
+ lpdcb->fDtrControl);
+
- fd = FILE_GetUnixHandle( handle, GENERIC_READ );
- if (fd < 0) {
- FIXME("no handle %d found\n",handle);
- return FALSE;
- }
+ fd = get_comm_fd( handle, GENERIC_READ );
+ if (fd < 0) return FALSE;
if ((tcgetattr(fd,&port)) == -1) {
int save_error = errno;
- commerror = WinError();
- close( fd );
+ COMM_SetCommError(handle,CE_IOE);
+ release_comm_fd( handle, fd );
ERR("tcgetattr error '%s'\n", strerror(save_error));
return FALSE;
}
port.c_lflag &= ~(ICANON|ECHO|ISIG);
port.c_lflag |= NOFLSH;
- /*
- ** MJM - removed default baudrate settings
- ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
- */
#ifdef CBAUD
port.c_cflag &= ~CBAUD;
switch (lpdcb->BaudRate) {
+ case 0:
+ port.c_cflag |= B0;
+ break;
+ case 50:
+ port.c_cflag |= B50;
+ break;
+ case 75:
+ port.c_cflag |= B75;
+ break;
case 110:
case CBR_110:
port.c_cflag |= B110;
- break;
+ break;
+ case 134:
+ port.c_cflag |= B134;
+ break;
+ case 150:
+ port.c_cflag |= B150;
+ break;
+ case 200:
+ port.c_cflag |= B200;
+ break;
case 300:
case CBR_300:
port.c_cflag |= B300;
- break;
+ break;
case 600:
case CBR_600:
port.c_cflag |= B600;
- break;
+ break;
case 1200:
case CBR_1200:
port.c_cflag |= B1200;
- break;
+ break;
+ case 1800:
+ port.c_cflag |= B1800;
+ break;
case 2400:
case CBR_2400:
port.c_cflag |= B2400;
- break;
+ break;
case 4800:
case CBR_4800:
port.c_cflag |= B4800;
- break;
+ break;
case 9600:
case CBR_9600:
port.c_cflag |= B9600;
- break;
+ break;
case 19200:
case CBR_19200:
port.c_cflag |= B19200;
- break;
+ break;
case 38400:
case CBR_38400:
port.c_cflag |= B38400;
- break;
+ break;
#ifdef B57600
case 57600:
port.c_cflag |= B57600;
- break;
+ break;
#endif
#ifdef B115200
case 115200:
port.c_cflag |= B115200;
- break;
+ break;
#endif
#ifdef B230400
case 230400:
port.c_cflag |= B230400;
- break;
+ break;
#endif
#ifdef B460800
- case 460600:
+ case 460800:
port.c_cflag |= B460800;
- break;
+ break;
#endif
default:
- commerror = IE_BAUDRATE;
- close( fd );
+#if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
+ { struct serial_struct nuts;
+ int arby;
+ ioctl(fd, TIOCGSERIAL, &nuts);
+ nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
+ if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
+ arby = nuts.baud_base / nuts.custom_divisor;
+ nuts.flags &= ~ASYNC_SPD_MASK;
+ nuts.flags |= ASYNC_SPD_CUST;
+ WARN("You (or a program acting at your behest) have specified\n"
+ "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
+ "which is as close as we can get by our present understanding of your\n"
+ "hardware. I hope you know what you are doing. Any disruption Wine\n"
+ "has caused to your linux system can be undone with setserial \n"
+ "(see man setserial). If you have incapacitated a Hayes type modem,\n"
+ "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
+ ioctl(fd, TIOCSSERIAL, &nuts);
+ port.c_cflag |= B38400;
+ }
+ break;
+#endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
+
+
+ COMM_SetCommError(handle,IE_BAUDRATE);
+ release_comm_fd( handle, fd );
ERR("baudrate %ld\n",lpdcb->BaudRate);
return FALSE;
}
#elif !defined(__EMX__)
switch (lpdcb->BaudRate) {
+ case 0:
+ port.c_ospeed = B0;
+ break;
+ case 50:
+ port.c_ospeed = B50;
+ break;
+ case 75:
+ port.c_ospeed = B75;
+ break;
case 110:
case CBR_110:
port.c_ospeed = B110;
break;
+ case 134:
+ port.c_ospeed = B134;
+ break;
+ case 150:
+ port.c_ospeed = B150;
+ break;
+ case 200:
+ port.c_ospeed = B200;
+ break;
case 300:
case CBR_300:
port.c_ospeed = B300;
case CBR_1200:
port.c_ospeed = B1200;
break;
+ case 1800:
+ port.c_ospeed = B1800;
+ break;
case 2400:
case CBR_2400:
port.c_ospeed = B2400;
case CBR_38400:
port.c_ospeed = B38400;
break;
+#ifdef B57600
+ case 57600:
+ case CBR_57600:
+ port.c_cflag |= B57600;
+ break;
+#endif
+#ifdef B115200
+ case 115200:
+ case CBR_115200:
+ port.c_cflag |= B115200;
+ break;
+#endif
+#ifdef B230400
+ case 230400:
+ port.c_cflag |= B230400;
+ break;
+#endif
+#ifdef B460800
+ case 460800:
+ port.c_cflag |= B460800;
+ break;
+#endif
default:
- commerror = IE_BAUDRATE;
- close( fd );
+ COMM_SetCommError(handle,IE_BAUDRATE);
+ release_comm_fd( handle, fd );
ERR("baudrate %ld\n",lpdcb->BaudRate);
return FALSE;
}
stopbits = TWOSTOPBITS;
port.c_iflag &= ~INPCK;
} else {
- commerror = IE_BYTESIZE;
- close( fd );
+ COMM_SetCommError(handle,IE_BYTESIZE);
+ release_comm_fd( handle, fd );
ERR("Cannot set MARK Parity\n");
return FALSE;
}
bytesize +=1;
port.c_iflag &= ~INPCK;
} else {
- commerror = IE_BYTESIZE;
- close( fd );
+ COMM_SetCommError(handle,IE_BYTESIZE);
+ release_comm_fd( handle, fd );
ERR("Cannot set SPACE Parity\n");
return FALSE;
}
break;
#endif
default:
- commerror = IE_BYTESIZE;
- close( fd );
+ COMM_SetCommError(handle,IE_BYTESIZE);
+ release_comm_fd( handle, fd );
ERR("Parity\n");
return FALSE;
}
-
+
port.c_cflag &= ~CSIZE;
switch (bytesize) {
port.c_cflag |= CS8;
break;
default:
- commerror = IE_BYTESIZE;
- close( fd );
+ COMM_SetCommError(handle,IE_BYTESIZE);
+ release_comm_fd( handle, fd );
ERR("ByteSize\n");
return FALSE;
}
-
+
switch (stopbits) {
case ONESTOPBIT:
port.c_cflag &= ~CSTOPB;
break;
- case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
+ case ONE5STOPBITS: /* will be selected if bytesize is 5 */
case TWOSTOPBITS:
port.c_cflag |= CSTOPB;
break;
default:
- commerror = IE_BYTESIZE;
- close( fd );
+ COMM_SetCommError(handle,IE_BYTESIZE);
+ release_comm_fd( handle, fd );
ERR("StopBits\n");
return FALSE;
}
#ifdef CRTSCTS
if ( lpdcb->fOutxCtsFlow ||
- lpdcb->fRtsControl == RTS_CONTROL_ENABLE
- )
+ lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
+ )
{
port.c_cflag |= CRTSCTS;
TRACE("CRTSCTS\n");
}
-
- if (lpdcb->fDtrControl == DTR_CONTROL_ENABLE)
- {
- port.c_cflag &= ~CRTSCTS;
- TRACE("~CRTSCTS\n");
- }
+#endif
-#endif
if (lpdcb->fInX)
port.c_iflag |= IXON;
else
port.c_iflag &= ~IXOFF;
if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
- int save_error=errno;
- commerror = WinError();
- close( fd );
- ERR("tcsetattr error '%s'\n", strerror(save_error));
- return FALSE;
+ ERR("tcsetattr error '%s'\n", strerror(errno));
+ COMM_SetCommError(handle,CE_IOE);
+ ret = FALSE;
} else {
- commerror = 0;
- close( fd );
- return TRUE;
+ COMM_SetCommError(handle,0);
+ ret = TRUE;
}
+
+ /* note: change DTR/RTS lines after setting the comm attributes,
+ * so flow control does not interfere. */
+#ifdef TIOCM_DTR
+ if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
+ {
+ WARN("DSR/DTR flow control not supported\n");
+ } else if(lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
+ COMM_WhackModem(fd, ~TIOCM_DTR, 0);
+ else
+ COMM_WhackModem(fd, 0, TIOCM_DTR);
+#endif
+#ifdef TIOCM_RTS
+ if(!lpdcb->fOutxCtsFlow )
+ {
+ if(lpdcb->fRtsControl == RTS_CONTROL_DISABLE)
+ COMM_WhackModem(fd, ~TIOCM_RTS, 0);
+ else
+ COMM_WhackModem(fd, 0, TIOCM_RTS);
+ }
+#endif
+ if(lpdcb->fRtsControl == RTS_CONTROL_TOGGLE)
+ FIXME("RTS_CONTROL_TOGGLE is not supported.\n");
+ release_comm_fd( handle, fd );
+ return ret;
+
}
* RETURNS
*
* True on success, false if the communication device handle is bad etc
- *
+ *
* BUGS
*
* XonChar and XoffChar are not set.
{
struct termios port;
int fd,speed;
+ int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
- TRACE("handle %d, ptr %p\n", handle, lpdcb);
+ TRACE("handle %p, ptr %p\n", handle, lpdcb);
- fd = FILE_GetUnixHandle( handle, GENERIC_READ );
- if (fd < 0)
- {
- ERR("FILE_GetUnixHandle failed\n");
- return FALSE;
- }
- if (tcgetattr(fd, &port) == -1) {
+ fd = get_comm_fd( handle, GENERIC_READ );
+ if (fd < 0) return FALSE;
+ if (tcgetattr(fd, &port) == -1
+#ifdef TIOCMGET
+ || ioctl(fd, TIOCMGET, &stat) == -1
+#endif
+ ) {
int save_error=errno;
- ERR("tcgetattr error '%s'\n", strerror(save_error));
- commerror = WinError();
- close( fd );
+ ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error));
+ COMM_SetCommError(handle,CE_IOE);
+ release_comm_fd( handle, fd );
return FALSE;
}
- close( fd );
+ release_comm_fd( handle, fd );
#ifndef __EMX__
#ifdef CBAUD
speed= (port.c_cflag & CBAUD);
speed= (cfgetospeed(&port));
#endif
switch (speed) {
+ case B0:
+ lpdcb->BaudRate = 0;
+ break;
+ case B50:
+ lpdcb->BaudRate = 50;
+ break;
+ case B75:
+ lpdcb->BaudRate = 75;
+ break;
case B110:
lpdcb->BaudRate = 110;
break;
+ case B134:
+ lpdcb->BaudRate = 134;
+ break;
+ case B150:
+ lpdcb->BaudRate = 150;
+ break;
+ case B200:
+ lpdcb->BaudRate = 200;
+ break;
case B300:
lpdcb->BaudRate = 300;
break;
case B1200:
lpdcb->BaudRate = 1200;
break;
+ case B1800:
+ lpdcb->BaudRate = 1800;
+ break;
case B2400:
lpdcb->BaudRate = 2400;
break;
#ifdef B57600
case B57600:
lpdcb->BaudRate = 57600;
- break;
+ break;
#endif
#ifdef B115200
case B115200:
lpdcb->BaudRate = 115200;
- break;
+ break;
#endif
#ifdef B230400
case B230400:
lpdcb->BaudRate = 230400;
- break;
+ break;
#endif
#ifdef B460800
case B460800:
lpdcb->BaudRate = 460800;
- break;
+ break;
#endif
default:
ERR("unknown speed %x \n",speed);
break;
default:
ERR("unknown size %x \n",port.c_cflag & CSIZE);
- }
-
+ }
+
if(port.c_iflag & INPCK)
lpdcb->fParity = TRUE;
else
lpdcb->Parity = EVENPARITY;
break;
case (PARENB | PARODD):
- lpdcb->Parity = ODDPARITY;
+ lpdcb->Parity = ODDPARITY;
break;
#ifdef CMSPAR
case (PARENB | CMSPAR):
- lpdcb->Parity = MARKPARITY;
+ lpdcb->Parity = MARKPARITY;
break;
case (PARENB | PARODD | CMSPAR):
- lpdcb->Parity = SPACEPARITY;
+ lpdcb->Parity = SPACEPARITY;
break;
#endif
}
lpdcb->fNull = 0;
lpdcb->fBinary = 1;
+ /* termios does not support DTR/DSR flow control */
+ lpdcb->fOutxDsrFlow = 0;
+ lpdcb->fDtrControl =
+#ifdef TIOCM_DTR
+ !(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
+#endif
+ DTR_CONTROL_ENABLE ;
+
#ifdef CRTSCTS
if (port.c_cflag & CRTSCTS) {
- lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
- lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
+ lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
lpdcb->fOutxCtsFlow = 1;
- lpdcb->fOutxDsrFlow = 1;
- } else
+ } else
#endif
{
- lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
- lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
+ lpdcb->fRtsControl =
+#ifdef TIOCM_RTS
+ !(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
+#endif
+ RTS_CONTROL_ENABLE ;
+ lpdcb->fOutxCtsFlow = 0;
}
if (port.c_iflag & IXON)
lpdcb->fInX = 1;
else
lpdcb->fOutX = 0;
/*
- lpdcb->XonChar =
- lpdcb->XoffChar =
+ lpdcb->XonChar =
+ lpdcb->XoffChar =
*/
lpdcb->XonLim = 10;
lpdcb->XoffLim = 10;
- commerror = 0;
+ COMM_SetCommError(handle,0);
TRACE("OK\n");
-
+
TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
(lpdcb->StopBits == ONESTOPBIT)?1:
(lpdcb->StopBits == TWOSTOPBITS)?2:0);
TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
(lpdcb->fOutX)?"IXOFF":"~IXOFF");
+ TRACE("fOutxCtsFlow %d fRtsControl %d\n", lpdcb->fOutxCtsFlow,
+ lpdcb->fRtsControl);
+ TRACE("fOutxDsrFlow %d fDtrControl%d\n", lpdcb->fOutxDsrFlow,
+ lpdcb->fDtrControl);
#ifdef CRTSCTS
if ( lpdcb->fOutxCtsFlow ||
- lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
- lpdcb->fRtsControl == RTS_CONTROL_ENABLE
- )
+ lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
+ )
TRACE("CRTSCTS\n");
-
- if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
+ else
+
TRACE("~CRTSCTS\n");
-
-#endif
+#endif
return TRUE;
}
HANDLE hComm, /* [in] The communication device in need of a command character. */
CHAR chTransmit) /* [in] The character to transmit. */
{
- FIXME("(%x,'%c'), use win32 handle!\n",hComm,chTransmit);
- return TRUE;
+ DWORD w;
+ WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
+
+ return WriteFile( hComm, &chTransmit, 1, &w, NULL );
}
+
/*****************************************************************************
* GetCommTimeouts (KERNEL32.@)
*
- * Obtains the request time out values for the communications device.
+ * Obtains the request timeout values for the communications device.
*
* RETURNS
*
*/
BOOL WINAPI GetCommTimeouts(
HANDLE hComm, /* [in] The communications device. */
- LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request time outs. */
+ LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
{
BOOL ret;
- TRACE("(%x,%p)\n",hComm,lptimeouts);
+ TRACE("(%p,%p)\n",hComm,lptimeouts);
if(!lptimeouts)
{
SERVER_START_REQ( get_serial_info )
{
req->handle = hComm;
- if ((ret = !SERVER_CALL_ERR()))
+ if ((ret = !wine_server_call_err( req )))
{
- lptimeouts->ReadIntervalTimeout = req->readinterval;
- lptimeouts->ReadTotalTimeoutMultiplier = req->readmult;
- lptimeouts->ReadTotalTimeoutConstant = req->readconst;
- lptimeouts->WriteTotalTimeoutMultiplier = req->writemult;
- lptimeouts->WriteTotalTimeoutConstant = req->writeconst;
+ lptimeouts->ReadIntervalTimeout = reply->readinterval;
+ lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
+ lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
+ lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
+ lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
}
}
SERVER_END_REQ;
*
* Sets the timeouts used when reading and writing data to/from COMM ports.
*
- * ReadIntervalTimeout
+ * ReadIntervalTimeout
* - converted and passes to linux kernel as c_cc[VTIME]
* ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
* - used in ReadFile to calculate GetOverlappedResult's timeout
*
* RETURNS
*
- * True if the time outs were set, false otherwise.
+ * True if the timeouts were set, false otherwise.
*/
BOOL WINAPI SetCommTimeouts(
HANDLE hComm, /* [in] handle of COMM device */
int fd;
struct termios tios;
- TRACE("(%x,%p)\n",hComm,lptimeouts);
+ TRACE("(%p,%p)\n",hComm,lptimeouts);
if(!lptimeouts)
{
req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
- ret = !SERVER_CALL_ERR();
+ ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
if (!ret) return FALSE;
/* FIXME: move this stuff to the server */
- fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
- if (fd < 0) {
- FIXME("no fd for handle = %0x!.\n",hComm);
- return FALSE;
- }
+ fd = get_comm_fd( hComm, GENERIC_READ );
+ if (fd < 0) return FALSE;
if (-1==tcgetattr(fd,&tios)) {
FIXME("tcgetattr on fd %d failed!\n",fd);
+ release_comm_fd( hComm, fd );
return FALSE;
}
if (-1==tcsetattr(fd,0,&tios)) {
FIXME("tcsetattr on fd %d failed!\n",fd);
+ release_comm_fd( hComm, fd );
return FALSE;
}
- close(fd);
+ release_comm_fd( hComm, fd );
return TRUE;
}
LPDWORD lpModemStat) /* [out] The control register bits. */
{
int fd,mstat, result=FALSE;
-
+
*lpModemStat=0;
#ifdef TIOCMGET
- fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
+ fd = get_comm_fd( hFile, GENERIC_READ );
if(fd<0)
return FALSE;
result = ioctl(fd, TIOCMGET, &mstat);
- close(fd);
+ release_comm_fd( hFile, fd );
if (result == -1)
{
WARN("ioctl failed\n");
* This function is called while the client is waiting on the
* server, so we can't make any server calls here.
*/
-static void COMM_WaitCommEventService(async_private *ovp, int events)
+static void WINAPI COMM_WaitCommEventService(void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
{
- LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
+ async_commio *commio = (async_commio*) ovp;
- TRACE("overlapped %p wait complete %p <- %x\n",lpOverlapped,ovp->buffer,events);
- if(events&POLLNVAL)
- {
- lpOverlapped->Internal = STATUS_HANDLES_CLOSED;
- return;
- }
- if(ovp->buffer)
+ TRACE("iosb %p\n", iosb);
+
+ switch (status)
{
- if(events&POLLIN)
- *ovp->buffer = EV_RXCHAR;
+ case STATUS_ALERTED: /* got some new stuff */
+ /* FIXME: detect other events */
+ *commio->buffer = EV_RXCHAR;
+ iosb->u.Status = STATUS_SUCCESS;
+ break;
+ default:
+ iosb->u.Status = status;
+ break;
}
-
- lpOverlapped->Internal = STATUS_SUCCESS;
+ wine_server_release_fd( commio->handle, commio->fd );
+ if ( ((LPOVERLAPPED)iosb)->hEvent != INVALID_HANDLE_VALUE )
+ NtSetEvent( ((LPOVERLAPPED)iosb)->hEvent, NULL );
+ HeapFree(GetProcessHeap(), 0, commio );
}
-
/***********************************************************************
* COMM_WaitCommEvent (INTERNAL)
*
LPDWORD lpdwEvents, /* [out] event(s) that were detected */
LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
{
- int fd,ret;
- async_private *ovp;
+ int fd;
+ async_commio* commio;
+ NTSTATUS status;
- if(!lpOverlapped)
+ if (!lpOverlapped)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
- if(NtResetEvent(lpOverlapped->hEvent,NULL))
+ if (NtResetEvent(lpOverlapped->hEvent,NULL))
return FALSE;
- lpOverlapped->Internal = STATUS_PENDING;
+ fd = get_comm_fd( hFile, GENERIC_WRITE );
+ if (fd < 0) return FALSE;
+
+ commio = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
+ if (!commio)
+ {
+ release_comm_fd( hFile, fd );
+ return FALSE;
+ }
+
+ commio->handle = hFile;
+ commio->type = ASYNC_TYPE_WAIT;
+ commio->apc_internal = COMM_WaitCommEventService;
+ commio->buffer = (char *)lpdwEvents;
+ commio->fd = fd; /* FIXME */
+
lpOverlapped->InternalHigh = 0;
lpOverlapped->Offset = 0;
lpOverlapped->OffsetHigh = 0;
- /* start an ASYNCHRONOUS WaitCommEvent */
- SERVER_START_REQ( create_async )
+ SERVER_START_REQ( register_async )
{
- req->file_handle = hFile;
+ req->handle = hFile;
+ req->io_apc = COMM_WaitCommEventService;
+ req->io_user = commio;
+ req->io_sb = (IO_STATUS_BLOCK*)lpOverlapped;
req->count = 0;
- req->type = ASYNC_TYPE_WAIT;
-
- ret=SERVER_CALL_ERR();
+ status = wine_server_call( req );
}
SERVER_END_REQ;
- if (ret)
- return FALSE;
-
- fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
- if(fd<0)
- return FALSE;
-
- ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
- if(!ovp)
- {
- close(fd);
- return FALSE;
- }
- ovp->lpOverlapped = lpOverlapped;
- ovp->timeout = 0;
- ovp->tv.tv_sec = 0;
- ovp->tv.tv_usec = 0;
- ovp->event = POLLIN;
- ovp->func = COMM_WaitCommEventService;
- ovp->buffer = (char *)lpdwEvents;
- ovp->fd = fd;
- ovp->count = 0;
- ovp->completion_func = 0;
-
- ovp->next = NtCurrentTeb()->pending_list;
- ovp->prev = NULL;
- if(ovp->next)
- ovp->next->prev=ovp;
- NtCurrentTeb()->pending_list = ovp;
-
- SetLastError(ERROR_IO_PENDING);
+ if ( status ) SetLastError( RtlNtStatusToDosError(status) );
+ else NtCurrentTeb()->num_async_io++;
return FALSE;
}
OVERLAPPED ov;
int ret;
- TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
+ TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
if(lpOverlapped)
return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
/* if there is no overlapped structure, create our own */
- ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
+ ov.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
- if(GetLastError()!=STATUS_PENDING)
- {
- CloseHandle(ov.hEvent);
- return FALSE;
- }
-
/* wait for the overlapped to complete */
ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
CloseHandle(ov.hEvent);
return ret;
}
-
+
/***********************************************************************
* GetCommProperties (KERNEL32.@)
*
- * This function fills in a structure with the capabilities of the
+ * This function fills in a structure with the capabilities of the
* communications port driver.
*
* RETURNS
HANDLE hFile, /* [in] handle of the comm port */
LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
{
- FIXME("(%d %p )\n",hFile,lpCommProp);
+ FIXME("(%p %p )\n",hFile,lpCommProp);
if(!lpCommProp)
return FALSE;
lpCommProp->dwMaxRxQueue = 4096;
lpCommProp->dwMaxBaud = BAUD_115200;
lpCommProp->dwProvSubType = PST_RS232;
- lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
- lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
+ lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
+ lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
- lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
+ lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
* SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
* This is dependent on the type of COMM port, but since it is doubtful
* anybody will get around to implementing support for fancy serial
- * ports in WINE, this is hardcoded for the time being. The name of
- * this DLL should be stored in and read from the system registry in
+ * ports in WINE, this is hardcoded for the time being. The name of
+ * this DLL should be stored in and read from the system registry in
* the hive HKEY_LOCAL_MACHINE, key
* System\\CurrentControlSet\\Services\\Class\\Ports\\????
* where ???? is the port number... that is determined by PNP
- * The DLL should be loaded when the COMM port is opened, and closed
+ * The DLL should be loaded when the COMM port is opened, and closed
* when the COMM port is closed. - MJM 20 June 2000
***********************************************************************/
-static CHAR lpszSerialUI[] = "serialui.dll";
+static WCHAR lpszSerialUI[] = {
+ 's','e','r','i','a','l','u','i','.','d','l','l',0 };
/***********************************************************************
{
FARPROC lpfnCommDialog;
HMODULE hConfigModule;
- BOOL r;
+ BOOL r = FALSE;
- TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
+ TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
- hConfigModule = LoadLibraryA(lpszSerialUI);
+ hConfigModule = LoadLibraryW(lpszSerialUI);
if(!hConfigModule)
return FALSE;
- lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
+ lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogA");
- if(!lpfnCommDialog)
- return FALSE;
+ if(lpfnCommDialog)
+ r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
- r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
-
- /* UnloadLibrary(hConfigModule); */
+ FreeLibrary(hConfigModule);
return r;
}
HANDLE hWnd, /* [in] parent window for the dialog */
LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
{
- BOOL r;
- LPSTR lpDeviceA;
+ FARPROC lpfnCommDialog;
+ HMODULE hConfigModule;
+ BOOL r = FALSE;
+
+ TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
- lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
- if(lpDeviceA)
+ hConfigModule = LoadLibraryW(lpszSerialUI);
+ if(!hConfigModule)
return FALSE;
- r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
- HeapFree( GetProcessHeap(), 0, lpDeviceA );
+
+ lpfnCommDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
+
+ if(lpfnCommDialog)
+ r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
+
+ FreeLibrary(hConfigModule);
+
return r;
}
*
* BUGS
*
- * The signature is missing a the parameter for the size of the COMMCONFIG
- * structure/buffer it should be
- * BOOL WINAPI GetCommConfig(HANDLE hFile,LPCOMMCONFIG lpCommConfig,LPDWORD lpdwSize)
*/
BOOL WINAPI GetCommConfig(
HANDLE hFile, /* [in] The communications device. */
LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
- afterwards the number of bytes copied to the buffer or
+ afterwards the number of bytes copied to the buffer or
the needed size of the buffer. */
{
BOOL r;
- TRACE("(%x %p)\n",hFile,lpCommConfig);
+ TRACE("(%p %p)\n",hFile,lpCommConfig);
if(lpCommConfig == NULL)
return FALSE;
-
- r = *lpdwSize < sizeof(COMMCONFIG);
+ r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
*lpdwSize = sizeof(COMMCONFIG);
- if(!r)
+ if(r)
return FALSE;
lpCommConfig->dwSize = sizeof(COMMCONFIG);
/***********************************************************************
* SetCommConfig (KERNEL32.@)
*
- * Sets the configuration of the commications device.
+ * Sets the configuration of the communications device.
*
* RETURNS
*
* True on success, false if the handle was bad is not a communications device.
*/
BOOL WINAPI SetCommConfig(
- HANDLE hFile, /* [in] The communications device. */
- LPCOMMCONFIG lpCommConfig) /* [in] The desired configuration. */
+ HANDLE hFile, /* [in] The communications device. */
+ LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
+ DWORD dwSize) /* [in] size of the lpCommConfig struct */
{
- TRACE("(%x %p)\n",hFile,lpCommConfig);
+ TRACE("(%p %p)\n",hFile,lpCommConfig);
return SetCommState(hFile,&lpCommConfig->dcb);
}
*
* True if the device was found and the defaults set, false otherwise
*/
-BOOL WINAPI SetDefaultCommConfigA(
- LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
+BOOL WINAPI SetDefaultCommConfigW(
+ LPCWSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
{
FARPROC lpfnSetDefaultCommConfig;
HMODULE hConfigModule;
- BOOL r;
+ BOOL r = FALSE;
TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
- hConfigModule = LoadLibraryA(lpszSerialUI);
+ hConfigModule = LoadLibraryW(lpszSerialUI);
if(!hConfigModule)
- return FALSE;
-
- lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
+ return r;
- if(! lpfnSetDefaultCommConfig)
- return TRUE;
-
- r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
+ lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
+ if (lpfnSetDefaultCommConfig)
+ r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
- /* UnloadLibrary(hConfigModule); */
+ FreeLibrary(hConfigModule);
return r;
}
* RETURNS
*
*/
-BOOL WINAPI SetDefaultCommConfigW(
- LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
+BOOL WINAPI SetDefaultCommConfigA(
+ LPCSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
{
BOOL r;
- LPSTR lpDeviceA;
+ LPWSTR lpDeviceW = NULL;
+ DWORD len;
- TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
+ TRACE("(%s %p %lx)\n",debugstr_a(lpszDevice),lpCommConfig,dwSize);
- lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
- if(lpDeviceA)
- return FALSE;
- r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
- HeapFree( GetProcessHeap(), 0, lpDeviceA );
+ if (lpszDevice)
+ {
+ len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
+ lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
+ }
+ r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
+ HeapFree( GetProcessHeap(), 0, lpDeviceW );
return r;
}
/***********************************************************************
- * GetDefaultCommConfigA (KERNEL32.@)
+ * GetDefaultCommConfigW (KERNEL32.@)
*
* Acquires the default configuration of the specified communication device. (unicode)
*
* True on successful reading of the default configuration,
* if the device is not found or the buffer is too small.
*/
-BOOL WINAPI GetDefaultCommConfigA(
- LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
+BOOL WINAPI GetDefaultCommConfigW(
+ LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
afterwards the number of bytes copied to the buffer or
the needed size of the buffer. */
{
LPDCB lpdcb = &(lpCC->dcb);
- char temp[40];
+ WCHAR temp[40];
+ static const WCHAR comW[] = {'C','O','M',0};
+ static const WCHAR formatW[] = {'C','O','M','%','c',':','3','8','4','0','0',',','n',',','8',',','1',0};
- if (strncasecmp(lpszName,"COM",3)) {
- ERR("not implemented for <%s>\n", lpszName);
+ if (strncmpiW(lpszName,comW,3)) {
+ ERR("not implemented for <%s>\n", debugstr_w(lpszName));
return FALSE;
}
- TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
+ TRACE("(%s %p %ld)\n", debugstr_w(lpszName), lpCC, *lpdwSize );
if (*lpdwSize < sizeof(COMMCONFIG)) {
*lpdwSize = sizeof(COMMCONFIG);
return FALSE;
lpCC->dwProviderOffset = 0L;
lpCC->dwProviderSize = 0L;
- (void) sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
- FIXME("setting %s as default\n", temp);
+ sprintfW( temp, formatW, lpszName[3]);
+ FIXME("setting %s as default\n", debugstr_w(temp));
- return BuildCommDCBA( temp, lpdcb);
+ return BuildCommDCBW( temp, lpdcb);
}
/**************************************************************************
- * GetDefaultCommConfigW (KERNEL32.@)
+ * GetDefaultCommConfigA (KERNEL32.@)
*
- * Acquires the default configuration of the specified communication device. (unicode)
+ * Acquires the default configuration of the specified communication device. (ascii)
*
* RETURNS
*
* True on successful reading of the default configuration,
* if the device is not found or the buffer is too small.
*/
-BOOL WINAPI GetDefaultCommConfigW(
- LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
+BOOL WINAPI GetDefaultCommConfigA(
+ LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
afterwards the number of bytes copied to the buffer or
the needed size of the buffer. */
{
BOOL ret = FALSE;
- LPSTR lpszNameA;
+ UNICODE_STRING lpszNameW;
- TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
- lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
- if (lpszNameA)
- {
- ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
- HeapFree( GetProcessHeap(), 0, lpszNameA );
- }
+ TRACE("(%s,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
+ if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
+ else lpszNameW.Buffer = NULL;
+
+ if(lpszNameW.Buffer) ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
+
+ RtlFreeUnicodeString(&lpszNameW);
return ret;
}
-