VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/os2/USBProxyBackendOs2.cpp@ 98651

Last change on this file since 98651 was 98292, checked in by vboxsync, 22 months ago

Main/src-server: rc -> hrc/vrc. Enabled scm rc checks. bugref:10223

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