[PATCH 09/11] [NtDll/Kernel32]: [SG]etCommTimeout, SERIAL_[GS]ET_TIMEOUT

Eric Pouech eric.pouech at wanadoo.fr
Sun May 7 07:10:58 CDT 2006


- implemented ntdll's COMM IOCTL GET_TIMEOUTS,
SET_TIMEOUTS
- implemented kernel32!GetCommTimeout and SetCommTimeout on top of them

A+
---

 dlls/kernel/comm.c  |  114 +++++++++++++++------------------------------------
 dlls/ntdll/serial.c |   87 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 117 insertions(+), 84 deletions(-)

diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c
index 7d8e6da..f12043d 100644
--- a/dlls/kernel/comm.c
+++ b/dlls/kernel/comm.c
@@ -1180,39 +1180,34 @@ BOOL WINAPI TransmitCommChar(HANDLE hCom
  *
  *  Obtains the request timeout values for the communications device.
  *
+ * PARAMS
+ *      hComm           [in]    The communications device
+ *      lptimeouts      [out]   The struct of request timeouts
+ *
  * RETURNS
  *
  *  True on success, false if communications device handle is bad
  *  or the target structure is null.
  */
-BOOL WINAPI GetCommTimeouts(
-    HANDLE         hComm,      /* [in] The communications device. */
-    LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
+BOOL WINAPI GetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
 {
-    BOOL ret;
+    SERIAL_TIMEOUTS     st;
 
-    TRACE("(%p,%p)\n",hComm,lptimeouts);
-
-    if(!lptimeouts)
+    TRACE("(%p, %p)\n", hComm, lptimeouts);
+    if (!lptimeouts)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
-
-    SERVER_START_REQ( get_serial_info )
-    {
-        req->handle = hComm;
-        if ((ret = !wine_server_call_err( req )))
-        {
-            lptimeouts->ReadIntervalTimeout         = reply->readinterval;
-            lptimeouts->ReadTotalTimeoutMultiplier  = reply->readmult;
-            lptimeouts->ReadTotalTimeoutConstant    = reply->readconst;
-            lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
-            lptimeouts->WriteTotalTimeoutConstant   = reply->writeconst;
-        }
-    }
-    SERVER_END_REQ;
-    return ret;
+    if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS,
+                         NULL, 0, &st, sizeof(st), NULL, NULL))
+        return FALSE;
+    lptimeouts->ReadIntervalTimeout         = st.ReadIntervalTimeout;
+    lptimeouts->ReadTotalTimeoutMultiplier  = st.ReadTotalTimeoutMultiplier;
+    lptimeouts->ReadTotalTimeoutConstant    = st.ReadTotalTimeoutConstant;
+    lptimeouts->WriteTotalTimeoutMultiplier = st.WriteTotalTimeoutMultiplier;
+    lptimeouts->WriteTotalTimeoutConstant   = st.WriteTotalTimeoutConstant;
+    return TRUE;
 }
 
 /*****************************************************************************
@@ -1220,6 +1215,10 @@ BOOL WINAPI GetCommTimeouts(
  *
  * Sets the timeouts used when reading and writing data to/from COMM ports.
  *
+ * PARAMS
+ *      hComm           [in]    handle of COMM device
+ *      lptimeouts      [in]    pointer to COMMTIMEOUTS structure
+ *
  * ReadIntervalTimeout
  *     - converted and passes to linux kernel as c_cc[VTIME]
  * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
@@ -1231,72 +1230,25 @@ BOOL WINAPI GetCommTimeouts(
  *
  *  True if the timeouts were set, false otherwise.
  */
-BOOL WINAPI SetCommTimeouts(
-    HANDLE hComm,              /* [in] handle of COMM device */
-    LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
+BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
 {
-    BOOL ret;
-    int fd;
-    struct termios tios;
+    SERIAL_TIMEOUTS     st;
 
-    TRACE("(%p,%p)\n",hComm,lptimeouts);
+    TRACE("(%p, %p)\n", hComm, lptimeouts);
 
-    if(!lptimeouts)
+    if (lptimeouts == NULL)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
-
-    SERVER_START_REQ( set_serial_info )
-    {
-        req->handle       = hComm;
-        req->flags        = SERIALINFO_SET_TIMEOUTS;
-        req->readinterval = lptimeouts->ReadIntervalTimeout ;
-        req->readmult     = lptimeouts->ReadTotalTimeoutMultiplier ;
-        req->readconst    = lptimeouts->ReadTotalTimeoutConstant ;
-        req->writemult    = lptimeouts->WriteTotalTimeoutMultiplier ;
-        req->writeconst   = lptimeouts->WriteTotalTimeoutConstant ;
-        ret = !wine_server_call_err( req );
-    }
-    SERVER_END_REQ;
-    if (!ret) return FALSE;
-
-    /* FIXME: move this stuff to the server */
-    fd = get_comm_fd( hComm, FILE_READ_DATA );
-    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;
-    }
-
-    /* VTIME is in 1/10 seconds */
-	{
-		unsigned int ux_timeout;
-
-		if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
-		{
-			ux_timeout = 0;
-		}
-		else
-		{
-			ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
-			if(ux_timeout == 0)
-			{
-				ux_timeout = 1; /* must be at least some timeout */
-			}
-		}
-		tios.c_cc[VTIME] = ux_timeout;
-	}
-
-    if (-1==tcsetattr(fd,0,&tios)) {
-        FIXME("tcsetattr on fd %d failed!\n",fd);
-        release_comm_fd( hComm, fd );
-        return FALSE;
-    }
-    release_comm_fd( hComm, fd );
-    return TRUE;
+    st.ReadIntervalTimeout         = lptimeouts->ReadIntervalTimeout;
+    st.ReadTotalTimeoutMultiplier  = lptimeouts->ReadTotalTimeoutMultiplier;
+    st.ReadTotalTimeoutConstant    = lptimeouts->ReadTotalTimeoutConstant;
+    st.WriteTotalTimeoutMultiplier = lptimeouts->WriteTotalTimeoutMultiplier;
+    st.WriteTotalTimeoutConstant   = lptimeouts->WriteTotalTimeoutConstant;
+ 
+    return DeviceIoControl(hComm, IOCTL_SERIAL_SET_TIMEOUTS,
+                           &st, sizeof(st), NULL, 0, NULL, NULL);
 }
 
 /***********************************************************************
diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c
index 9b56c6b..1b45a10 100644
--- a/dlls/ntdll/serial.c
+++ b/dlls/ntdll/serial.c
@@ -368,6 +368,25 @@ static NTSTATUS get_status(int fd, SERIA
     return status;
 }
 
+static NTSTATUS get_timeouts(HANDLE handle, SERIAL_TIMEOUTS* st)
+{
+    NTSTATUS    status;
+    SERVER_START_REQ( get_serial_info )
+    {
+        req->handle = handle;
+        if (!(status = wine_server_call( req )))
+        {
+            st->ReadIntervalTimeout         = reply->readinterval;
+            st->ReadTotalTimeoutMultiplier  = reply->readmult;
+            st->ReadTotalTimeoutConstant    = reply->readconst;
+            st->WriteTotalTimeoutMultiplier = reply->writemult;
+            st->WriteTotalTimeoutConstant   = reply->writeconst;
+        }
+    }
+    SERVER_END_REQ;
+    return status;
+}
+
 static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD* mask)
 {
     NTSTATUS    status;
@@ -738,6 +757,51 @@ static NTSTATUS set_special_chars(int fd
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS set_timeouts(HANDLE handle, int fd, const SERIAL_TIMEOUTS* st)
+{
+    NTSTATUS            status;
+    struct termios      port;
+    unsigned int        ux_timeout;
+
+    SERVER_START_REQ( set_serial_info )
+    {
+        req->handle       = handle;
+        req->flags        = SERIALINFO_SET_TIMEOUTS;
+        req->readinterval = st->ReadIntervalTimeout ;
+        req->readmult     = st->ReadTotalTimeoutMultiplier ;
+        req->readconst    = st->ReadTotalTimeoutConstant ;
+        req->writemult    = st->WriteTotalTimeoutMultiplier ;
+        req->writeconst   = st->WriteTotalTimeoutConstant ;
+        status = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+    if (status) return status;
+
+    if (tcgetattr(fd, &port) == -1)
+    {
+        FIXME("tcgetattr on fd %d failed (%s)!\n", fd, strerror(errno));
+        return FILE_GetNtStatus();
+    }
+
+    /* VTIME is in 1/10 seconds */
+    if (st->ReadIntervalTimeout == 0) /* 0 means no timeout */
+        ux_timeout = 0;
+    else
+    {
+        ux_timeout = (st->ReadIntervalTimeout + 99) / 100;
+        if (ux_timeout == 0)
+            ux_timeout = 1; /* must be at least some timeout */
+    }
+    port.c_cc[VTIME] = ux_timeout;
+
+    if (tcsetattr(fd, 0, &port) == -1)
+    {
+        FIXME("tcsetattr on fd %d failed (%s)!\n", fd, strerror(errno));
+        return FILE_GetNtStatus();
+    }
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS set_wait_mask(HANDLE hDevice, DWORD mask)
 {
     NTSTATUS status;
@@ -777,7 +841,7 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDe
 {
     DWORD       sz = 0, access = FILE_READ_DATA;
     NTSTATUS    status = STATUS_SUCCESS;
-    int         fd;
+    int         fd = -1;
 
     TRACE("%p %s %p %ld %p %ld %p\n",
           hDevice, iocode2str(dwIoControlCode), lpInBuffer, nInBufferSize,
@@ -785,7 +849,9 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDe
 
     piosb->Information = 0;
 
-    if ((status = wine_server_handle_to_fd( hDevice, access, &fd, NULL ))) goto error;
+    if (dwIoControlCode != IOCTL_SERIAL_GET_TIMEOUTS)
+        if ((status = wine_server_handle_to_fd( hDevice, access, &fd, NULL )))
+            goto error;
 
     switch (dwIoControlCode)
     {
@@ -841,6 +907,15 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDe
         }
         else status = STATUS_INVALID_PARAMETER;
         break;
+    case IOCTL_SERIAL_GET_TIMEOUTS:
+        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_TIMEOUTS))
+        {
+            if (!(status = get_timeouts(hDevice, (SERIAL_TIMEOUTS*)lpInBuffer)))
+                sz = sizeof(SERIAL_TIMEOUTS);
+        }
+        else
+            status = STATUS_INVALID_PARAMETER;
+        break;
     case IOCTL_SERIAL_GET_WAIT_MASK:
         if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
         {
@@ -910,6 +985,12 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDe
         else
             status = STATUS_INVALID_PARAMETER;
         break;
+    case IOCTL_SERIAL_SET_TIMEOUTS:
+        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_TIMEOUTS))
+            status = set_timeouts(hDevice, fd, (const SERIAL_TIMEOUTS*)lpInBuffer);
+        else
+            status = STATUS_INVALID_PARAMETER;
+        break;
     case IOCTL_SERIAL_SET_WAIT_MASK:
         if (lpInBuffer && nInBufferSize == sizeof(DWORD))
         {
@@ -925,7 +1006,7 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDe
         status = STATUS_INVALID_PARAMETER;
         break;
     }
-    wine_server_release_fd( hDevice, fd );
+    if (fd != -1) wine_server_release_fd( hDevice, fd );
  error:
     piosb->u.Status = status;
     piosb->Information = sz;





More information about the wine-patches mailing list