Eric Pouech : ntdll/kernel32: EscapeCommFunction & associated IOCTLs
Alexandre Julliard
julliard at wine.codeweavers.com
Tue May 9 14:15:54 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: 5f9e9836cf2d183a7645ef6d4badc362fef15f56
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=5f9e9836cf2d183a7645ef6d4badc362fef15f56
Author: Eric Pouech <eric.pouech at wanadoo.fr>
Date: Sun May 7 14:11:05 2006 +0200
ntdll/kernel32: EscapeCommFunction & associated IOCTLs
- implemented ntdll's serial IOCTL: CLR_DTR, CLR_RTS, SET_DTR,
SET_RTS, SET_XOFF, SET_XON, RESET_DEVICE
- implemented kernel32.EscapeCommFunction on top of them
---
dlls/kernel/comm.c | 134 +++++++++------------------------------------------
dlls/ntdll/serial.c | 75 +++++++++++++++++++++++++++++
2 files changed, 99 insertions(+), 110 deletions(-)
diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c
index 8f5c18d..8f5b9fd 100644
--- a/dlls/kernel/comm.c
+++ b/dlls/kernel/comm.c
@@ -146,19 +146,6 @@ #endif
return -1;
}
-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_Parse* (Internal)
@@ -699,111 +686,38 @@ BOOL WINAPI ClearCommBreak(HANDLE handle
*
* Directs a communication device to perform an extended function.
*
+ * PARAMS
+ *
+ * handle [in] The communication device to perform the extended function
+ * nFunction [in] The extended function to be performed
+ *
* RETURNS
*
* True or requested data on successful completion of the command,
* false if the device is not present cannot execute the command
* or the command failed.
*/
-BOOL WINAPI EscapeCommFunction(
- HANDLE handle, /* [in] The communication device to perform the extended function. */
- UINT nFunction) /* [in] The extended function to be performed. */
+BOOL WINAPI EscapeCommFunction(HANDLE handle, UINT func)
{
- int fd,direct=FALSE,result=FALSE;
- struct termios port;
-
- TRACE("handle %p, function=%d\n", handle, nFunction);
- fd = get_comm_fd( handle, FILE_READ_DATA );
- if(fd<0) return FALSE;
-
- if (tcgetattr(fd,&port) == -1) {
- release_comm_fd( handle, fd );
- return FALSE;
- }
-
- switch (nFunction) {
- case RESETDEV:
- TRACE("\n");
- break;
-
- case CLRDTR:
- TRACE("CLRDTR\n");
-#ifdef TIOCM_DTR
- direct=TRUE;
- result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
- break;
-#endif
-
- case CLRRTS:
- TRACE("CLRRTS\n");
-#ifdef TIOCM_RTS
- direct=TRUE;
- result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
- break;
-#endif
+ DWORD ioc;
- case SETDTR:
- TRACE("SETDTR\n");
-#ifdef TIOCM_DTR
- direct=TRUE;
- result= COMM_WhackModem(fd, 0, TIOCM_DTR);
- break;
-#endif
-
- case SETRTS:
- TRACE("SETRTS\n");
-#ifdef TIOCM_RTS
- direct=TRUE;
- result= COMM_WhackModem(fd, 0, TIOCM_RTS);
- break;
-#endif
-
- case SETXOFF:
- TRACE("SETXOFF\n");
- port.c_iflag |= IXOFF;
- break;
-
- case SETXON:
- TRACE("SETXON\n");
- port.c_iflag |= IXON;
- break;
- case SETBREAK:
- TRACE("setbreak\n");
-#ifdef TIOCSBRK
- direct=TRUE;
- result = ioctl(fd,TIOCSBRK,0);
- break;
-#endif
- case CLRBREAK:
- TRACE("clrbreak\n");
-#ifdef TIOCSBRK
- direct=TRUE;
- result = ioctl(fd,TIOCCBRK,0);
- break;
-#endif
- default:
- WARN("(handle=%p,nFunction=%d): Unknown function\n",
- handle, nFunction);
- break;
- }
-
- if (!direct)
- if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
- release_comm_fd( handle, fd );
- return FALSE;
- } else
- result= TRUE;
- else
- {
- if (result == -1)
- {
- result= FALSE;
- }
- else
- result = TRUE;
- }
- release_comm_fd( handle, fd );
- return result;
+ switch (func)
+ {
+ case CLRDTR: ioc = IOCTL_SERIAL_CLR_DTR; break;
+ case CLRRTS: ioc = IOCTL_SERIAL_CLR_RTS; break;
+ case SETDTR: ioc = IOCTL_SERIAL_SET_DTR; break;
+ case SETRTS: ioc = IOCTL_SERIAL_SET_RTS; break;
+ case SETXOFF: ioc = IOCTL_SERIAL_SET_XOFF; break;
+ case SETXON: ioc = IOCTL_SERIAL_SET_XON; break;
+ case SETBREAK: ioc = IOCTL_SERIAL_SET_BREAK_ON; break;
+ case CLRBREAK: ioc = IOCTL_SERIAL_SET_BREAK_OFF; break;
+ case RESETDEV: ioc = IOCTL_SERIAL_RESET_DEVICE; break;
+ default:
+ ERR("Unknown function code (%u)\n", func);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ return DeviceIoControl(handle, ioc, NULL, 0, NULL, 0, NULL, NULL);
}
/********************************************************************
diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c
index 15d1941..64e181a 100644
--- a/dlls/ntdll/serial.c
+++ b/dlls/ntdll/serial.c
@@ -823,6 +823,44 @@ static NTSTATUS set_wait_mask(HANDLE hDe
return status;
}
+static NTSTATUS set_XOff(int fd)
+{
+ struct termios port;
+
+ if (tcgetattr(fd,&port) == -1)
+ {
+ FIXME("tcgetattr on fd %d failed (%s)!\n", fd, strerror(errno));
+ return FILE_GetNtStatus();
+
+
+ }
+ port.c_iflag |= IXOFF;
+ if (tcsetattr(fd, TCSADRAIN, &port) == -1)
+ {
+ FIXME("tcsetattr on fd %d failed (%s)!\n", fd, strerror(errno));
+ return FILE_GetNtStatus();
+ }
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS set_XOn(int fd)
+{
+ struct termios port;
+
+ if (tcgetattr(fd,&port) == -1)
+ {
+ FIXME("tcgetattr on fd %d failed (%s)!\n", fd, strerror(errno));
+ return FILE_GetNtStatus();
+ }
+ port.c_iflag |= IXON;
+ if (tcsetattr(fd, TCSADRAIN, &port) == -1)
+ {
+ FIXME("tcsetattr on fd %d failed (%s)!\n", fd, strerror(errno));
+ return FILE_GetNtStatus();
+ }
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS xmit_immediate(HANDLE hDevice, int fd, char* ptr)
{
/* FIXME: not perfect as it should bypass the in-queue */
@@ -861,6 +899,20 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDe
switch (dwIoControlCode)
{
+ case IOCTL_SERIAL_CLR_DTR:
+#ifdef TIOCM_DTR
+ if (whack_modem(fd, ~TIOCM_DTR, 0) == -1) status = FILE_GetNtStatus();
+#else
+ status = STATUS_NOT_SUPPORTED;
+#endif
+ break;
+ case IOCTL_SERIAL_CLR_RTS:
+#ifdef TIOCM_RTS
+ if (whack_modem(fd, ~TIOCM_RTS, 0) == -1) status = FILE_GetNtStatus();
+#else
+ status = STATUS_NOT_SUPPORTED;
+#endif
+ break;
case IOCTL_SERIAL_GET_BAUD_RATE:
if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_BAUD_RATE))
{
@@ -943,6 +995,9 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDe
else
status = STATUS_INVALID_PARAMETER;
break;
+ case IOCTL_SERIAL_RESET_DEVICE:
+ FIXME("Unsupported\n");
+ break;
case IOCTL_SERIAL_SET_BAUD_RATE:
if (lpInBuffer && nInBufferSize == sizeof(SERIAL_BAUD_RATE))
status = set_baud_rate(fd, (const SERIAL_BAUD_RATE*)lpInBuffer);
@@ -979,6 +1034,13 @@ #endif
else
status = STATUS_INVALID_PARAMETER;
break;
+ case IOCTL_SERIAL_SET_DTR:
+#ifdef TIOCM_DTR
+ if (whack_modem(fd, 0, TIOCM_DTR) == -1) status = FILE_GetNtStatus();
+#else
+ status = STATUS_NOT_SUPPORTED;
+#endif
+ break;
case IOCTL_SERIAL_SET_HANDFLOW:
if (lpInBuffer && nInBufferSize == sizeof(SERIAL_HANDFLOW))
status = set_handflow(fd, (const SERIAL_HANDFLOW*)lpInBuffer);
@@ -997,6 +1059,13 @@ #endif
else
status = STATUS_INVALID_PARAMETER;
break;
+ case IOCTL_SERIAL_SET_RTS:
+#ifdef TIOCM_RTS
+ if (whack_modem(fd, 0, TIOCM_RTS) == -1) status = FILE_GetNtStatus();
+#else
+ status = STATUS_NOT_SUPPORTED;
+#endif
+ break;
case IOCTL_SERIAL_SET_TIMEOUTS:
if (lpInBuffer && nInBufferSize == sizeof(SERIAL_TIMEOUTS))
status = set_timeouts(hDevice, fd, (const SERIAL_TIMEOUTS*)lpInBuffer);
@@ -1010,6 +1079,12 @@ #endif
}
else status = STATUS_INVALID_PARAMETER;
break;
+ case IOCTL_SERIAL_SET_XOFF:
+ status = set_XOff(fd);
+ break;
+ case IOCTL_SERIAL_SET_XON:
+ status = set_XOn(fd);
+ break;
default:
FIXME("Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n",
dwIoControlCode, dwIoControlCode >> 16, (dwIoControlCode >> 14) & 3,
More information about the wine-cvs
mailing list