summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp
diff options
context:
space:
mode:
authorMichael Meskes <meskes@debian.org>2011-01-20 11:21:45 +0100
committerMichael Meskes <meskes@debian.org>2011-01-20 11:21:45 +0100
commit14ee89c73b263c9a9e6e5bd300ef05c1ed41742a (patch)
treeba2010adc07bd73710310b25adb8428ea866e067 /src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp
parent361589e3ae692db27161410309b92c6b89e1ec6c (diff)
downloadvirtualbox-14ee89c73b263c9a9e6e5bd300ef05c1ed41742a.tar.gz
Imported Upstream version 4.0.2-dfsgupstream/4.0.2-dfsg
Diffstat (limited to 'src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp')
-rw-r--r--src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp269
1 files changed, 269 insertions, 0 deletions
diff --git a/src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp b/src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp
new file mode 100644
index 000000000..22ba59ba0
--- /dev/null
+++ b/src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp
@@ -0,0 +1,269 @@
+/* $Id: USBProxyServiceOs2.cpp 31892 2010-08-24 08:00:51Z vboxsync $ */
+/** @file
+ * VirtualBox USB Proxy Service, OS/2 Specialization.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#define INCL_BASE
+#define INCL_ERRORS
+#include "USBProxyService.h"
+#include "Logging.h"
+
+#include <VBox/usb.h>
+#include <VBox/err.h>
+
+#include <iprt/string.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/file.h>
+#include <iprt/err.h>
+
+
+/**
+ * Initialize data members.
+ */
+USBProxyServiceOs2::USBProxyServiceOs2 (Host *aHost)
+ : USBProxyService (aHost), mhev (NULLHANDLE), mhmod (NULLHANDLE),
+ mpfnUsbRegisterChangeNotification (NULL), mpfnUsbDeregisterNotification (NULL),
+ mpfnUsbQueryNumberDevices (NULL), mpfnUsbQueryDeviceReport (NULL)
+{
+ LogFlowThisFunc(("aHost=%p\n", aHost));
+
+ /*
+ * Try initialize the usbcalls stuff.
+ */
+ int rc = DosCreateEventSem (NULL, &mhev, 0, FALSE);
+ rc = RTErrConvertFromOS2 (rc);
+ if (RT_SUCCESS(rc))
+ {
+ rc = DosLoadModule (NULL, 0, (PCSZ)"usbcalls", &mhmod);
+ rc = RTErrConvertFromOS2 (rc);
+ if (RT_SUCCESS(rc))
+ {
+ if ( (rc = DosQueryProcAddr (mhmod, 0, (PCSZ)"UsbQueryNumberDevices", (PPFN)&mpfnUsbQueryNumberDevices)) == NO_ERROR
+ && (rc = DosQueryProcAddr (mhmod, 0, (PCSZ)"UsbQueryDeviceReport", (PPFN)&mpfnUsbQueryDeviceReport)) == NO_ERROR
+ && (rc = DosQueryProcAddr (mhmod, 0, (PCSZ)"UsbRegisterChangeNotification", (PPFN)&mpfnUsbRegisterChangeNotification)) == NO_ERROR
+ && (rc = DosQueryProcAddr (mhmod, 0, (PCSZ)"UsbDeregisterNotification", (PPFN)&mpfnUsbDeregisterNotification)) == NO_ERROR
+ )
+ {
+ rc = mpfnUsbRegisterChangeNotification (&mNotifyId, mhev, mhev);
+ if (!rc)
+ {
+ /*
+ * Start the poller thread.
+ */
+ rc = start();
+ if (RT_SUCCESS(rc))
+ {
+ LogFlowThisFunc(("returns successfully - mNotifyId=%d\n", mNotifyId));
+ mLastError = VINF_SUCCESS;
+ return;
+ }
+ }
+
+ LogRel (("USBProxyServiceOs2: failed to register change notification, rc=%d\n", rc));
+ }
+ else
+ LogRel (("USBProxyServiceOs2: failed to load usbcalls\n"));
+
+ DosFreeModule (mhmod);
+ }
+ else
+ LogRel (("USBProxyServiceOs2: failed to load usbcalls, rc=%d\n", rc));
+ mhmod = NULLHANDLE;
+ }
+ else
+ mhev = NULLHANDLE;
+
+ mLastError = rc;
+ LogFlowThisFunc(("returns failure!!! (rc=%Rrc)\n", rc));
+}
+
+
+/**
+ * Stop all service threads and free the device chain.
+ */
+USBProxyServiceOs2::~USBProxyServiceOs2()
+{
+ LogFlowThisFunc(("\n"));
+
+ /*
+ * Stop the service.
+ */
+ if (isActive())
+ stop();
+
+ /*
+ * Free resources.
+ */
+ if (mhmod)
+ {
+ if (mpfnUsbDeregisterNotification)
+ mpfnUsbDeregisterNotification (mNotifyId);
+
+ mpfnUsbRegisterChangeNotification = NULL;
+ mpfnUsbDeregisterNotification = NULL;
+ mpfnUsbQueryNumberDevices = NULL;
+ mpfnUsbQueryDeviceReport = NULL;
+
+ DosFreeModule (mhmod);
+ mhmod = NULLHANDLE;
+ }
+}
+
+
+int USBProxyServiceOs2::captureDevice (HostUSBDevice *aDevice)
+{
+ Log (("USBProxyServiceOs2::captureDevice: %p\n", aDevice));
+ AssertReturn(aDevice, VERR_GENERAL_FAILURE);
+ AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ /*
+ * Don't think we need to do anything when the device is held... fake it.
+ */
+ Assert(aDevice->isStatePending());
+ interruptWait();
+
+ return VINF_SUCCESS;
+}
+
+
+int USBProxyServiceOs2::releaseDevice (HostUSBDevice *aDevice)
+{
+ Log (("USBProxyServiceOs2::releaseDevice: %p\n", aDevice));
+ AssertReturn(aDevice, VERR_GENERAL_FAILURE);
+ AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ /*
+ * We're not really holding it atm., just fake it.
+ */
+ Assert(aDevice->isStatePending());
+ interruptWait();
+
+ return VINF_SUCCESS;
+}
+
+
+bool USBProxyServiceOs2::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
+{
+ return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
+}
+
+
+
+int USBProxyServiceOs2::wait(RTMSINTERVAL aMillies)
+{
+ int rc = DosWaitEventSem(mhev, aMillies);
+ return RTErrConvertFromOS2(rc);
+}
+
+
+int USBProxyServiceOs2::interruptWait (void)
+{
+ int rc = DosPostEventSem (mhev);
+ return rc == NO_ERROR || rc == ERROR_ALREADY_POSTED
+ ? VINF_SUCCESS
+ : RTErrConvertFromOS2 (rc);
+}
+
+#include <stdio.h>
+
+PUSBDEVICE USBProxyServiceOs2::getDevices (void)
+{
+ /*
+ * Count the devices.
+ */
+ ULONG cDevices = 0;
+ int rc = mpfnUsbQueryNumberDevices ((PULONG)&cDevices); /* Thanks to com/xpcom, PULONG and ULONG * aren't the same. */
+ if (rc)
+ return NULL;
+
+ /*
+ * Retrieve information about each device.
+ */
+ PUSBDEVICE pFirst = NULL;
+ PUSBDEVICE *ppNext = &pFirst;
+ for (ULONG i = 0; i < cDevices; i++)
+ {
+ /*
+ * Query the device and config descriptors.
+ */
+ uint8_t abBuf[1024];
+ ULONG cb = sizeof(abBuf);
+ rc = mpfnUsbQueryDeviceReport(i + 1, (PULONG)&cb, &abBuf[0]); /* see above (PULONG) */
+ if (rc)
+ continue;
+ PUSBDEVICEDESC pDevDesc = (PUSBDEVICEDESC)&abBuf[0];
+ if ( cb < sizeof(*pDevDesc)
+ || pDevDesc->bDescriptorType != USB_DT_DEVICE
+ || pDevDesc->bLength < sizeof(*pDevDesc)
+ || pDevDesc->bLength > sizeof(*pDevDesc) * 2)
+ continue;
+ PUSBCONFIGDESC pCfgDesc = (PUSBCONFIGDESC)&abBuf[pDevDesc->bLength];
+ if ( pCfgDesc->bDescriptorType != USB_DT_CONFIG
+ || pCfgDesc->bLength >= sizeof(*pCfgDesc))
+ pCfgDesc = NULL;
+
+ /*
+ * Skip it if it's some kind of hub.
+ */
+ if (pDevDesc->bDeviceClass == USB_HUB_CLASSCODE)
+ continue;
+
+ /*
+ * Allocate a new device node and initialize it with the basic stuff.
+ */
+ PUSBDEVICE pCur = (PUSBDEVICE)RTMemAlloc(sizeof(*pCur));
+ pCur->bcdUSB = pDevDesc->bcdUSB;
+ pCur->bDeviceClass = pDevDesc->bDeviceClass;
+ pCur->bDeviceSubClass = pDevDesc->bDeviceSubClass;
+ pCur->bDeviceProtocol = pDevDesc->bDeviceProtocol;
+ pCur->idVendor = pDevDesc->idVendor;
+ pCur->idProduct = pDevDesc->idProduct;
+ pCur->bcdDevice = pDevDesc->bcdDevice;
+ pCur->pszManufacturer = RTStrDup("");
+ pCur->pszProduct = RTStrDup("");
+ pCur->pszSerialNumber = NULL;
+ pCur->u64SerialHash = 0;
+ //pCur->bNumConfigurations = pDevDesc->bNumConfigurations;
+ pCur->bNumConfigurations = 0;
+ pCur->paConfigurations = NULL;
+ pCur->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
+ pCur->enmSpeed = USBDEVICESPEED_UNKNOWN;
+ pCur->pszAddress = NULL;
+ RTStrAPrintf((char **)&pCur->pszAddress, "p=0x%04RX16;v=0x%04RX16;r=0x%04RX16;e=0x%08RX32",
+ pDevDesc->idProduct, pDevDesc->idVendor, pDevDesc->bcdDevice, i);
+
+ pCur->bBus = 0;
+ pCur->bLevel = 0;
+ pCur->bDevNum = 0;
+ pCur->bDevNumParent = 0;
+ pCur->bPort = 0;
+ pCur->bNumDevices = 0;
+ pCur->bMaxChildren = 0;
+
+ /* link it */
+ pCur->pNext = NULL;
+ pCur->pPrev = *ppNext;
+ *ppNext = pCur;
+ ppNext = &pCur->pNext;
+ }
+
+ return pFirst;
+}
+