Hi,

sorry for sending a wrong version of tha patch. The correct version ist
attached.

Kind regards,
Alexander Eichner

Am Donnerstag, den 16.08.2007, 16:34 +0200 schrieb Alexander Eichner:
> Hi,
> 
> the attached patch improves the code of the host serial driver.
> The code now uses IPRT functions where possible and adds error handling
> in case the driver can not open the serial port.
> The patch hopefully adds support for serial ports on Windows host OS but
> i couldn't check if it works because I'm not able to compile the whole
> VirtualBox tree on Windows. I only checked that it compiles without an
> error.
> At last the driver has it's own log group now.
> 
> Kind regards,
> Alexander Eichner
> _______________________________________________
> vbox-dev mailing list
> [email protected]
> http://vbox.innotek.de/mailman/listinfo/vbox-dev
Index: include/VBox/log.h
===================================================================
--- include/VBox/log.h	(Revision 4144)
+++ include/VBox/log.h	(Arbeitskopie)
@@ -134,6 +134,8 @@
     LOG_GROUP_DRV_HOST_HDD,
     /** Host Parallel Driver group */
     LOG_GROUP_DRV_HOST_PARALLEL,
+    /** Host Serial Driver Group */
+    LOG_GROUP_DRV_HOST_SERIAL,
     /** The internal networking transport driver group. */
     LOG_GROUP_DRV_INTNET,
     /** iSCSI Initiator driver group. */
@@ -323,6 +325,7 @@
     "DRV_HOST_FLOPPY", \
     "DRV_HOST_HDD", \
     "DRV_HOST_PARALLEL", \
+    "DRV_HOST_SERIAL", \
     "DRV_INTNET",   \
     "DRV_ISCSI",    \
     "DRV_ISCSI_TRANSPORT_TCP", \
Index: src/VBox/Devices/Serial/DrvHostSerial.cpp
===================================================================
--- src/VBox/Devices/Serial/DrvHostSerial.cpp	(Revision 4144)
+++ src/VBox/Devices/Serial/DrvHostSerial.cpp	(Arbeitskopie)
@@ -27,7 +27,7 @@
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
-#define LOG_GROUP LOG_GROUP_DRV_CHAR
+#define LOG_GROUP LOG_GROUP_DRV_HOST_SERIAL
 #include <VBox/pdm.h>
 #include <VBox/err.h>
 
@@ -35,14 +35,18 @@
 #include <iprt/asm.h>
 #include <iprt/assert.h>
 #include <iprt/stream.h>
-#include <iprt/semaphore.h>
+#include <iprt/semaphore.h>
+#include <iprt/file.h>
+#include <iprt/alloc.h>
 
 #ifdef RT_OS_LINUX
-#include <termios.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
+# include <termios.h>
+# include <sys/types.h>
+# include <fcntl.h>
+# include <string.h>
+# include <unistd.h>
+#elif defined(RT_OS_WINDOWS)
+# include <windows.h>
 #endif
 
 #include "Builtins.h"
@@ -79,7 +83,7 @@
     /** the device path */
     char                        *pszDevicePath;
     /** the device handle */
-    int                         DeviceFile;
+    RTFILE                      DeviceFile;
 
     /** Internal send FIFO queue */
     uint8_t                     aSendQueue[CHAR_MAX_SEND_QUEUE];
@@ -148,16 +152,21 @@
 
 static DECLCALLBACK(int) drvHostSerialSetParameters(PPDMICHAR pInterface, int speed, int parity, int data_bits, int stop_bits)
 {
-    PDRVHOSTSERIAL pData = PDMICHAR_2_DRVHOSTSERIAL(pInterface);
-    struct termios termiosSetup;
+    PDRVHOSTSERIAL pData = PDMICHAR_2_DRVHOSTSERIAL(pInterface);
+#ifdef RT_OS_LINUX
+    struct termios *termiosSetup;
     int baud_rate;
+#elif defined(RT_OS_WINDOWS)
+    LPDCB comSetup;
+#endif
 
     LogFlow(("%s: speed=%d parity=%c data_bits=%d stop_bits=%d\n", __FUNCTION__, speed, parity, data_bits, stop_bits));
+
+#ifdef RT_OS_LINUX
+    termiosSetup = (struct termios *)RTMemTmpAllocZ(sizeof(struct termios));
 
-    memset(&termiosSetup, 0, sizeof(termiosSetup));
-
     /* Enable receiver */
-    termiosSetup.c_cflag |= (CLOCAL | CREAD);
+    termiosSetup->c_cflag |= (CLOCAL | CREAD);
 
     switch (speed) {
         case 50:
@@ -215,15 +224,15 @@
             baud_rate = B9600;
     }
 
-    cfsetispeed(&termiosSetup, baud_rate);
-    cfsetospeed(&termiosSetup, baud_rate);
+    cfsetispeed(termiosSetup, baud_rate);
+    cfsetospeed(termiosSetup, baud_rate);
 
     switch (parity) {
         case 'E':
-            termiosSetup.c_cflag |= PARENB;
+            termiosSetup->c_cflag |= PARENB;
             break;
         case 'O':
-            termiosSetup.c_cflag |= (PARENB | PARODD);
+            termiosSetup->c_cflag |= (PARENB | PARODD);
             break;
         case 'N':
             break;
@@ -233,16 +242,16 @@
 
     switch (data_bits) {
         case 5:
-            termiosSetup.c_cflag |= CS5;
+            termiosSetup->c_cflag |= CS5;
             break;
         case 6:
-            termiosSetup.c_cflag |= CS6;
+            termiosSetup->c_cflag |= CS6;
             break;
         case 7:
-            termiosSetup.c_cflag |= CS7;
+            termiosSetup->c_cflag |= CS7;
             break;
         case 8:
-            termiosSetup.c_cflag |= CS8;
+            termiosSetup->c_cflag |= CS8;
             break;
         default:
             break;
@@ -250,15 +259,115 @@
 
     switch (stop_bits) {
         case 2:
-            termiosSetup.c_cflag |= CSTOPB;
+            termiosSetup->c_cflag |= CSTOPB;
         default:
             break;
     }
 
     /* set serial port to raw input */
-    termiosSetup.c_lflag = ~(ICANON | ECHO | ECHOE | ISIG); 
+    termiosSetup->c_lflag = ~(ICANON | ECHO | ECHOE | ISIG); 
 
-    tcsetattr(pData->DeviceFile, TCSANOW, &termiosSetup);
+    tcsetattr(pData->DeviceFile, TCSANOW, termiosSetup);
+    RTMemFree(termiosSetup);
+#elif defined(RT_OS_WINDOWS)
+    comSetup = (LPDCB)RTMemTmpAllocZ(sizeof(DCB));
+
+    comSetup->DCBLength = sizeof(DCB);
+
+    switch (speed) {
+        case 110:
+            comSetup->BaudRate = CBR_110;
+            break;
+        case 300:
+            comSetup->BaudRate = CBR_300;
+            break;
+        case 600:
+            comSetup->BaudRate = CBR_600;
+            break;
+        case 1200:
+            comSetup->BaudRate = CBR_1200;
+            break;
+        case 2400:
+            comSetup->BaudRate = CBR_2400;
+            break;
+        case 4800:
+            comSetup->BaudRate = CBR_4800;
+            break;
+        case 9600:
+            comSetup->BaudRate = CBR_9600;
+            break;
+        case 14400:
+            comSetup->BaudRate = CBR_14400;
+            break;
+        case 19200:
+            comSetup->BaudRate = CBR_19200;
+            break;
+        case 38400:
+            comSetup->BaudRate = CBR_38400;
+            break;
+        case 57600:
+            comSetup->BaudRate = CBR_57600;
+            break;
+        case 115200:
+            comSetup->BaudRate = CBR_115200;
+            break;
+        default:
+            comSetup->BaudRate = CBR_9600;
+    }
+
+    comSetup->fBinary = TRUE;
+    comSetup->fOutxCtsFlow = FALSE;
+    comSetup->fOutxDsrFlow = FALSE;
+    comSetup->fDtrControl = DTR_CONTROL_DISABLE;
+    comSetup->fDsrSensitivity = FALSE;
+    comSetup->fTXContinueOnXoff = TRUE;
+    comSetup->fOutX = FALSE;
+    comSetup->fInX = FALSE;
+    comSetup->fErrorChar = FALSE;
+    comSetup->fNull = FALSE;
+    comSetup->fRtsControl = RTS_CONTROL_DISABLE;
+    comSetup->fAbortOnError = FALSE;
+    comSetup->wReserved = 0;
+    comSetup->XonLim = 5;
+    comSetup->XoffLim = 5;
+    comSetup->ByteSize = data_bits;
+
+    switch (parity) {
+        case 'E':
+            comSetup->Parity = EVENPARITY;
+            break;
+        case 'O':
+            comSetup->Parity = ODDPARITY;
+            break;
+        case 'N':
+            comSetup->Parity = NOPARITY;
+            break;
+        default:
+            break;
+    }
+
+    switch (stop_bits) {
+        case 1:
+            comSetup->StopBits = ONESTOPBIT;
+            break;
+        case 2:
+            comSetup->StopBits = TWOSTOPBITS;
+            break;
+        default:
+            break;
+    }
+
+    comSetup->XonChar = 0;
+    comSetup->XoffChar = 0;
+    comSetup->ErrorChar = 0;
+    comSetup->EofChar = 0;
+    comSetup->EvtChar = 0;
+
+    SetCommState((HANDLE)pData->DeviceFile, comSetup);
+    RTMemFree(comSetup);
+#endif
+
+    return VINF_SUCCESS;
 }
 
 /* -=-=-=-=- receive thread -=-=-=-=- */
@@ -289,14 +398,14 @@
             {
                 size_t cbProcessed = 1;
 
-                rc = write(pData->DeviceFile, &pData->aSendQueue[pData->iSendQueueTail], cbProcessed);
-                if (rc > 0)
+                rc = RTFileWrite(pData->DeviceFile, &pData->aSendQueue[pData->iSendQueueTail], cbProcessed, NULL);
+                if (VBOX_SUCCESS(rc))
                 {
                     Assert(cbProcessed);
                     pData->iSendQueueTail++;
                     pData->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK;
                 }
-                else if (rc < 0)
+                else if (VBOX_FAILURE(rc))
                 {
                     LogFlow(("Write failed with %Vrc; skipping\n", rc));
                     break;
@@ -326,7 +435,7 @@
 {
     PDRVHOSTSERIAL pData = (PDRVHOSTSERIAL)pvUser;
     char aBuffer[256], *pBuffer;
-    size_t cbRemaining, cbProcessed;
+    size_t cbRemaining, cbProcessed, cbRead;
     int rc;
 
     cbRemaining = 0;
@@ -335,15 +444,15 @@
     {
         if (!cbRemaining)
         {
-            /* Get block of data from stream driver. */
+            /* Get block of data from serial device. */
             cbRemaining = sizeof(aBuffer);
-            rc = read(pData->DeviceFile, aBuffer, cbRemaining);
-            if (rc < 0)
+            rc = RTFileRead(pData->DeviceFile, aBuffer, cbRemaining, &cbRead);
+            if (VBOX_FAILURE(rc))
             {
                 LogFlow(("Read failed with %Vrc\n", rc));
                 break;
             } else {
-                cbRemaining = rc;
+                cbRemaining = cbRead;
             }
             pBuffer = aBuffer;
         }
@@ -423,32 +532,68 @@
     /*
      * Open the device
      */
-    pData->DeviceFile = open(pData->pszDevicePath, O_RDWR | O_NONBLOCK);
-    if (pData->DeviceFile < 0) {
-        
+    rc = RTFileOpen(&pData->DeviceFile, pData->pszDevicePath, RTFILE_O_OPEN | RTFILE_O_READWRITE);
+
+    if (VBOX_FAILURE(rc)) {
+        pData->DeviceFile = NIL_RTFILE;
+        AssertMsgFailed(("Could not open host device %s, rc=%Vrc\n", pData->pszDevicePath, rc));
+        switch (rc) {
+            case VERR_ACCESS_DENIED:
+                return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
+#ifdef RT_OS_LINUX
+                N_("Cannot open host device '%s' for read/write access. Check the permissions "
+                   "of that device ('/bin/ls -l %s'): Most probably you need to be member "
+                   "of the device group. Make sure that you logout/login after changing "
+                   "the group settings of the current user"),
+#else
+                N_("Cannot open host device '%s' for read/write access. Check the permissions "
+                   "of that device"),
+#endif
+                pData->pszDevicePath, pData->pszDevicePath);
+           default:
+                return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
+                                           N_("Failed to open host device '%s'"), 
+                                           pData->pszDevicePath);
+        }
     }
+
+    /* Set to non blocking I/O */
+#ifdef RT_OS_LINUX
+    fcntl(pData->DeviceFile, F_SETFL, O_NONBLOCK);
+#elif defined(RT_OS_WINDOWS)
+    /* Set the COMMTIMEOUTS to get non blocking I/O */
+    COMMTIMEOUTS comTimeout;
+
+    comTimeout.ReadIntervalTimeout         = MAXDWORD; 
+    comTimeout.ReadTotalTimeoutMultiplier  = 0;
+    comTimeout.ReadTotalTimeoutConstant    = 0;
+    comTimeout.WriteTotalTimeoutMultiplier = 0;
+    comTimeout.WriteTotalTimeoutConstant   = 0;
+
+    SetCommTimeouts((HANDLE)pData->DeviceFile, &comTimeout);
+#endif
 
     /*
      * Get the ICharPort interface of the above driver/device.
      */
     pData->pDrvCharPort = (PPDMICHARPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_CHAR_PORT);
     if (!pData->pDrvCharPort)
-        return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Char#%d has no char port interface above"), pDrvIns->iInstance);
+        return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("HostSerial#%d has no char port interface above"), pDrvIns->iInstance);
 
-    rc = RTThreadCreate(&pData->ReceiveThread, drvHostSerialReceiveLoop, (void *)pData, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "Char Receive");
+    rc = RTThreadCreate(&pData->ReceiveThread, drvHostSerialReceiveLoop, (void *)pData, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "Serial Receive");
     if (VBOX_FAILURE(rc))
-        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create receive thread"), pDrvIns->iInstance);
+        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostSerial#%d cannot create receive thread"), pDrvIns->iInstance);
 
     rc = RTSemEventCreate(&pData->SendSem);
     AssertRC(rc);
 
-    rc = RTThreadCreate(&pData->SendThread, drvHostSerialSendLoop, (void *)pData, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "Char Send");
+    rc = RTThreadCreate(&pData->SendThread, drvHostSerialSendLoop, (void *)pData, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "Serial Send");
     if (VBOX_FAILURE(rc))
-        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create send thread"), pDrvIns->iInstance);
+        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostSerial#%d cannot create send thread"), pDrvIns->iInstance);
 
 
-    PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatBytesWritten,    STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES, "Nr of bytes written",         "/Devices/Char%d/Written", pDrvIns->iInstance);
-    PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatBytesRead,       STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES, "Nr of bytes read",            "/Devices/Char%d/Read", pDrvIns->iInstance);
+    PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatBytesWritten,    STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES, "Nr of bytes written",         "/Devices/HostSerial%d/Written", pDrvIns->iInstance);
+    PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatBytesRead,       STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES, "Nr of bytes read",            "/Devices/HostSerial%d/Read", pDrvIns->iInstance);
     
     return VINF_SUCCESS;
 }
@@ -473,7 +618,7 @@
     {
         RTThreadWait(pData->ReceiveThread, 1000, NULL);
         if (pData->ReceiveThread != NIL_RTTHREAD)
-            LogRel(("Char%d: receive thread did not terminate\n", pDrvIns->iInstance));
+            LogRel(("HostSerial%d: receive thread did not terminate\n", pDrvIns->iInstance));
     }
 
     /* Empty the send queue */
@@ -487,7 +632,7 @@
     {
         RTThreadWait(pData->SendThread, 1000, NULL);
         if (pData->SendThread != NIL_RTTHREAD)
-            LogRel(("Char%d: send thread did not terminate\n", pDrvIns->iInstance));
+            LogRel(("HostSerial%d: send thread did not terminate\n", pDrvIns->iInstance));
     }
 }
 
Index: src/VBox/Devices/Makefile.kmk
===================================================================
--- src/VBox/Devices/Makefile.kmk	(Revision 4144)
+++ src/VBox/Devices/Makefile.kmk	(Arbeitskopie)
@@ -441,7 +441,8 @@
 
 Drivers_SOURCES.win   = \
 	Network/DrvTAPWin32.cpp \
-	Audio/dsoundaudio.c
+	Audio/dsoundaudio.c \
+	Serial/DrvHostSerial.cpp
 
 
 # -- features --
_______________________________________________
vbox-dev mailing list
[email protected]
http://vbox.innotek.de/mailman/listinfo/vbox-dev

Reply via email to