Eric Pouech : ntdll/kernel32: GetCommState & SERIAL_GET_LINE_CONTROL

Alexandre Julliard julliard at wine.codeweavers.com
Tue May 9 14:15:48 CDT 2006


Module: wine
Branch: refs/heads/master
Commit: efb3244b0aeec890e16b210b1b25e424777b8147
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=efb3244b0aeec890e16b210b1b25e424777b8147

Author: Eric Pouech <eric.pouech at wanadoo.fr>
Date:   Sun May  7 14:10:49 2006 +0200

ntdll/kernel32: GetCommState & SERIAL_GET_LINE_CONTROL

- implemented SERIAL_GET_LINE_CONTROL ioctl
- made use of it in kernel.GetCommState

---

 dlls/kernel/comm.c  |   60 +++++++++------------------------------------------
 dlls/ntdll/serial.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 50 deletions(-)

diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c
index 8fd765b..6fa5b89 100644
--- a/dlls/kernel/comm.c
+++ b/dlls/kernel/comm.c
@@ -1082,6 +1082,7 @@ BOOL WINAPI GetCommState(HANDLE handle, 
      int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
 
     SERIAL_BAUD_RATE    sbr;
+    SERIAL_LINE_CONTROL slc;
 
     TRACE("handle %p, ptr %p\n", handle, lpdcb);
 
@@ -1093,13 +1094,21 @@ BOOL WINAPI GetCommState(HANDLE handle, 
     lpdcb->DCBlength = sizeof(*lpdcb);
     
     if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE,
-                         NULL, 0, &sbr, sizeof(sbr), NULL, NULL))
+                         NULL, 0, &sbr, sizeof(sbr), NULL, NULL) ||
+        !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL,
+                         NULL, 0, &slc, sizeof(slc), NULL, NULL))
         return FALSE;
+
     /* yes, they seem no never be (re)set on NT */
     lpdcb->fBinary = 1;
     lpdcb->fParity = 0;
 
     lpdcb->BaudRate = sbr.BaudRate;
+
+    lpdcb->StopBits = slc.StopBits;
+    lpdcb->Parity = slc.Parity;
+    lpdcb->ByteSize = slc.WordLength;
+
      fd = get_comm_fd( handle, FILE_READ_DATA );
      if (fd < 0) return FALSE;
      if (tcgetattr(fd, &port) == -1) {
@@ -1118,59 +1127,10 @@ #ifdef TIOCMGET
      }
 #endif
      release_comm_fd( handle, fd );
-	switch (port.c_cflag & CSIZE) {
-		case CS5:
-			lpdcb->ByteSize = 5;
-			break;
-		case CS6:
-			lpdcb->ByteSize = 6;
-			break;
-		case CS7:
-			lpdcb->ByteSize = 7;
-			break;
-		case CS8:
-			lpdcb->ByteSize = 8;
-			break;
-	        default:
-		        ERR("unknown size %x\n", port.c_cflag & CSIZE);
-	}
-
         if(port.c_iflag & INPCK)
             lpdcb->fParity = TRUE;
         else
             lpdcb->fParity = FALSE;
-#ifdef CMSPAR
-	switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
-#else
-	switch (port.c_cflag & (PARENB | PARODD))
-#endif
-	{
-		case 0:
-			lpdcb->Parity = NOPARITY;
-			break;
-		case PARENB:
-			lpdcb->Parity = EVENPARITY;
-			break;
-		case (PARENB | PARODD):
-			lpdcb->Parity = ODDPARITY;
-			break;
-#ifdef CMSPAR
-		case (PARENB | CMSPAR):
-			lpdcb->Parity = MARKPARITY;
-			break;
-                case (PARENB | PARODD | CMSPAR):
-			lpdcb->Parity = SPACEPARITY;
-			break;
-#endif
-	}
-
-	if (port.c_cflag & CSTOPB)
-            if(lpdcb->ByteSize == 5)
-                lpdcb->StopBits = ONE5STOPBITS;
-            else
-                lpdcb->StopBits = TWOSTOPBITS;
-	else
-            lpdcb->StopBits = ONESTOPBIT;
 
 	lpdcb->fNull = 0;
 
diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c
index c86dc66..0a6d8f1 100644
--- a/dlls/ntdll/serial.c
+++ b/dlls/ntdll/serial.c
@@ -185,6 +185,53 @@ #endif
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS get_line_control(int fd, SERIAL_LINE_CONTROL* slc)
+{
+    struct termios port;
+    
+    if (tcgetattr(fd, &port) == -1)
+    {
+        ERR("tcgetattr error '%s'\n", strerror(errno));
+        return FILE_GetNtStatus();
+    }
+    
+#ifdef CMSPAR
+    switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
+#else
+    switch (port.c_cflag & (PARENB | PARODD))
+#endif
+    {
+    case 0:                     slc->Parity = NOPARITY;         break;
+    case PARENB:                slc->Parity = EVENPARITY;       break;
+    case PARENB|PARODD:         slc->Parity = ODDPARITY;        break;
+#ifdef CMSPAR
+    case PARENB|CMSPAR:         slc->Parity = MARKPARITY;       break;
+    case PARENB|PARODD|CMSPAR:  slc->Parity = SPACEPARITY;      break;
+        break;
+#endif
+    }
+    switch (port.c_cflag & CSIZE)
+    {
+    case CS5:   slc->WordLength = 5;    break;
+    case CS6:   slc->WordLength = 6;    break;
+    case CS7:   slc->WordLength = 7;	break;
+    case CS8:	slc->WordLength = 8;	break;
+    default: ERR("unknown size %x\n", port.c_cflag & CSIZE);
+    }
+    
+    if (port.c_cflag & CSTOPB)
+    {
+        if (slc->WordLength == 5)
+            slc->StopBits = ONE5STOPBITS;
+        else
+            slc->StopBits = TWOSTOPBITS;
+    }
+    else
+        slc->StopBits = ONESTOPBIT;
+
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS get_modem_status(int fd, DWORD* lpModemStat)
 {
     NTSTATUS    status = STATUS_SUCCESS;
@@ -692,6 +739,15 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDe
         }
         else status = STATUS_INVALID_PARAMETER;
         break;
+    case IOCTL_SERIAL_GET_LINE_CONTROL:
+        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_LINE_CONTROL))
+        {
+            if (!(status = get_line_control(fd, (SERIAL_LINE_CONTROL*)lpOutBuffer)))
+                sz = sizeof(SERIAL_LINE_CONTROL);
+        }
+        else
+            status = STATUS_INVALID_PARAMETER;
+        break;
     case IOCTL_SERIAL_GET_MODEMSTATUS:
         if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
         {




More information about the wine-cvs mailing list