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