VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp@ 44824

Last change on this file since 44824 was 41528, checked in by vboxsync, 13 years ago

Main/HostUSBDevice(all platforms)+USBProxyService: redo USB locking, fixes major regression, added lots of assertions to catch locking flaws early, whitespace cleanup
Main/Machine: small USB locking fix to be consistent with the remaining code
Main/Host+glue/AutoLock: replace USB list lock by host lock, small numbering cleanup
Main/Console: redo USB locking, do less in USB callbacks/EMT (addresses long standing todo items), eliminate unsafe iterator parameters

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: USBProxyServiceOs2.cpp 41528 2012-05-31 16:48:33Z vboxsync $ */
2/** @file
3 * VirtualBox USB Proxy Service, OS/2 Specialization.
4 */
5
6/*
7 * Copyright (C) 2005-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define INCL_BASE
23#define INCL_ERRORS
24#include "USBProxyService.h"
25#include "Logging.h"
26
27#include <VBox/usb.h>
28#include <VBox/err.h>
29
30#include <iprt/string.h>
31#include <iprt/alloc.h>
32#include <iprt/assert.h>
33#include <iprt/file.h>
34#include <iprt/err.h>
35
36
37/**
38 * Initialize data members.
39 */
40USBProxyServiceOs2::USBProxyServiceOs2(Host *aHost)
41 : USBProxyService(aHost), mhev(NULLHANDLE), mhmod(NULLHANDLE),
42 mpfnUsbRegisterChangeNotification(NULL), mpfnUsbDeregisterNotification(NULL),
43 mpfnUsbQueryNumberDevices(NULL), mpfnUsbQueryDeviceReport(NULL)
44{
45 LogFlowThisFunc(("aHost=%p\n", aHost));
46
47 /*
48 * Try initialize the usbcalls stuff.
49 */
50 int rc = DosCreateEventSem(NULL, &mhev, 0, FALSE);
51 rc = RTErrConvertFromOS2(rc);
52 if (RT_SUCCESS(rc))
53 {
54 rc = DosLoadModule(NULL, 0, (PCSZ)"usbcalls", &mhmod);
55 rc = RTErrConvertFromOS2(rc);
56 if (RT_SUCCESS(rc))
57 {
58 if ( (rc = DosQueryProcAddr(mhmod, 0, (PCSZ)"UsbQueryNumberDevices", (PPFN)&mpfnUsbQueryNumberDevices)) == NO_ERROR
59 && (rc = DosQueryProcAddr(mhmod, 0, (PCSZ)"UsbQueryDeviceReport", (PPFN)&mpfnUsbQueryDeviceReport)) == NO_ERROR
60 && (rc = DosQueryProcAddr(mhmod, 0, (PCSZ)"UsbRegisterChangeNotification", (PPFN)&mpfnUsbRegisterChangeNotification)) == NO_ERROR
61 && (rc = DosQueryProcAddr(mhmod, 0, (PCSZ)"UsbDeregisterNotification", (PPFN)&mpfnUsbDeregisterNotification)) == NO_ERROR
62 )
63 {
64 rc = mpfnUsbRegisterChangeNotification(&mNotifyId, mhev, mhev);
65 if (!rc)
66 {
67 /*
68 * Start the poller thread.
69 */
70 rc = start();
71 if (RT_SUCCESS(rc))
72 {
73 LogFlowThisFunc(("returns successfully - mNotifyId=%d\n", mNotifyId));
74 mLastError = VINF_SUCCESS;
75 return;
76 }
77 }
78
79 LogRel(("USBProxyServiceOs2: failed to register change notification, rc=%d\n", rc));
80 }
81 else
82 LogRel(("USBProxyServiceOs2: failed to load usbcalls\n"));
83
84 DosFreeModule(mhmod);
85 }
86 else
87 LogRel(("USBProxyServiceOs2: failed to load usbcalls, rc=%d\n", rc));
88 mhmod = NULLHANDLE;
89 }
90 else
91 mhev = NULLHANDLE;
92
93 mLastError = rc;
94 LogFlowThisFunc(("returns failure!!! (rc=%Rrc)\n", rc));
95}
96
97
98/**
99 * Stop all service threads and free the device chain.
100 */
101USBProxyServiceOs2::~USBProxyServiceOs2()
102{
103 LogFlowThisFunc(("\n"));
104
105 /*
106 * Stop the service.
107 */
108 if (isActive())
109 stop();
110
111 /*
112 * Free resources.
113 */
114 if (mhmod)
115 {
116 if (mpfnUsbDeregisterNotification)
117 mpfnUsbDeregisterNotification(mNotifyId);
118
119 mpfnUsbRegisterChangeNotification = NULL;
120 mpfnUsbDeregisterNotification = NULL;
121 mpfnUsbQueryNumberDevices = NULL;
122 mpfnUsbQueryDeviceReport = NULL;
123
124 DosFreeModule(mhmod);
125 mhmod = NULLHANDLE;
126 }
127}
128
129
130int USBProxyServiceOs2::captureDevice(HostUSBDevice *aDevice)
131{
132 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
133 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
134
135 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
136 LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
137
138 /*
139 * Don't think we need to do anything when the device is held... fake it.
140 */
141 Assert(aDevice->isStatePending());
142 devLock.release();
143 interruptWait();
144
145 return VINF_SUCCESS;
146}
147
148
149int USBProxyServiceOs2::releaseDevice(HostUSBDevice *aDevice)
150{
151 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
152 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
153
154 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
155 LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
156
157 /*
158 * We're not really holding it atm., just fake it.
159 */
160 Assert(aDevice->isStatePending());
161 devLock.release();
162 interruptWait();
163
164 return VINF_SUCCESS;
165}
166
167
168bool USBProxyServiceOs2::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
169{
170 AssertReturn(aDevice, false);
171 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
172 return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
173}
174
175
176
177int USBProxyServiceOs2::wait(RTMSINTERVAL aMillies)
178{
179 int rc = DosWaitEventSem(mhev, aMillies);
180 return RTErrConvertFromOS2(rc);
181}
182
183
184int USBProxyServiceOs2::interruptWait(void)
185{
186 int rc = DosPostEventSem(mhev);
187 return rc == NO_ERROR || rc == ERROR_ALREADY_POSTED
188 ? VINF_SUCCESS
189 : RTErrConvertFromOS2(rc);
190}
191
192#include <stdio.h>
193
194PUSBDEVICE USBProxyServiceOs2::getDevices(void)
195{
196 /*
197 * Count the devices.
198 */
199 ULONG cDevices = 0;
200 int rc = mpfnUsbQueryNumberDevices((PULONG)&cDevices); /* Thanks to com/xpcom, PULONG and ULONG * aren't the same. */
201 if (rc)
202 return NULL;
203
204 /*
205 * Retrieve information about each device.
206 */
207 PUSBDEVICE pFirst = NULL;
208 PUSBDEVICE *ppNext = &pFirst;
209 for (ULONG i = 0; i < cDevices; i++)
210 {
211 /*
212 * Query the device and config descriptors.
213 */
214 uint8_t abBuf[1024];
215 ULONG cb = sizeof(abBuf);
216 rc = mpfnUsbQueryDeviceReport(i + 1, (PULONG)&cb, &abBuf[0]); /* see above (PULONG) */
217 if (rc)
218 continue;
219 PUSBDEVICEDESC pDevDesc = (PUSBDEVICEDESC)&abBuf[0];
220 if ( cb < sizeof(*pDevDesc)
221 || pDevDesc->bDescriptorType != USB_DT_DEVICE
222 || pDevDesc->bLength < sizeof(*pDevDesc)
223 || pDevDesc->bLength > sizeof(*pDevDesc) * 2)
224 continue;
225 PUSBCONFIGDESC pCfgDesc = (PUSBCONFIGDESC)&abBuf[pDevDesc->bLength];
226 if ( pCfgDesc->bDescriptorType != USB_DT_CONFIG
227 || pCfgDesc->bLength >= sizeof(*pCfgDesc))
228 pCfgDesc = NULL;
229
230 /*
231 * Skip it if it's some kind of hub.
232 */
233 if (pDevDesc->bDeviceClass == USB_HUB_CLASSCODE)
234 continue;
235
236 /*
237 * Allocate a new device node and initialize it with the basic stuff.
238 */
239 PUSBDEVICE pCur = (PUSBDEVICE)RTMemAlloc(sizeof(*pCur));
240 pCur->bcdUSB = pDevDesc->bcdUSB;
241 pCur->bDeviceClass = pDevDesc->bDeviceClass;
242 pCur->bDeviceSubClass = pDevDesc->bDeviceSubClass;
243 pCur->bDeviceProtocol = pDevDesc->bDeviceProtocol;
244 pCur->idVendor = pDevDesc->idVendor;
245 pCur->idProduct = pDevDesc->idProduct;
246 pCur->bcdDevice = pDevDesc->bcdDevice;
247 pCur->pszManufacturer = RTStrDup("");
248 pCur->pszProduct = RTStrDup("");
249 pCur->pszSerialNumber = NULL;
250 pCur->u64SerialHash = 0;
251 //pCur->bNumConfigurations = pDevDesc->bNumConfigurations;
252 pCur->bNumConfigurations = 0;
253 pCur->paConfigurations = NULL;
254 pCur->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
255 pCur->enmSpeed = USBDEVICESPEED_UNKNOWN;
256 pCur->pszAddress = NULL;
257 RTStrAPrintf((char **)&pCur->pszAddress, "p=0x%04RX16;v=0x%04RX16;r=0x%04RX16;e=0x%08RX32",
258 pDevDesc->idProduct, pDevDesc->idVendor, pDevDesc->bcdDevice, i);
259
260 pCur->bBus = 0;
261 pCur->bLevel = 0;
262 pCur->bDevNum = 0;
263 pCur->bDevNumParent = 0;
264 pCur->bPort = 0;
265 pCur->bNumDevices = 0;
266 pCur->bMaxChildren = 0;
267
268 /* link it */
269 pCur->pNext = NULL;
270 pCur->pPrev = *ppNext;
271 *ppNext = pCur;
272 ppNext = &pCur->pNext;
273 }
274
275 return pFirst;
276}
277
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette