VirtualBox

source: vbox/trunk/src/VBox/Main/include/USBProxyBackend.h@ 98102

Last change on this file since 98102 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.4 KB
Line 
1/* $Id: USBProxyBackend.h 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * VirtualBox USB Proxy Backend (base) class.
4 */
5
6/*
7 * Copyright (C) 2005-2022 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#ifndef MAIN_INCLUDED_USBProxyBackend_h
29#define MAIN_INCLUDED_USBProxyBackend_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include <VBox/usb.h>
35#include <VBox/usbfilter.h>
36
37#include <iprt/socket.h>
38#include <iprt/poll.h>
39#include <iprt/semaphore.h>
40#include <iprt/cpp/utils.h>
41
42#include "VirtualBoxBase.h"
43#include "VirtualBoxImpl.h"
44#include "HostUSBDeviceImpl.h"
45#include "USBProxyBackendWrap.h"
46class USBProxyService;
47
48/**
49 * Base class for the USB Proxy Backend.
50 */
51class ATL_NO_VTABLE USBProxyBackend
52 : public USBProxyBackendWrap
53{
54public:
55
56 DECLARE_COMMON_CLASS_METHODS(USBProxyBackend)
57
58 HRESULT FinalConstruct();
59 void FinalRelease();
60
61 // public initializer/uninitializer for internal purposes only
62 virtual int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
63 const com::Utf8Str &strAddress, bool fLoadingSettings);
64 virtual void uninit();
65
66 bool isActive(void);
67 const com::Utf8Str &i_getId();
68 const com::Utf8Str &i_getAddress();
69 virtual const com::Utf8Str &i_getBackend();
70 uint32_t i_getRefCount();
71
72 virtual bool i_isDevReEnumerationRequired();
73
74 /** @name Interface for the USBController and the Host object.
75 * @{ */
76 virtual void *insertFilter(PCUSBFILTER aFilter);
77 virtual void removeFilter(void *aId);
78 /** @} */
79
80 /** @name Interfaces for the HostUSBDevice
81 * @{ */
82 virtual int captureDevice(HostUSBDevice *aDevice);
83 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
84 virtual int releaseDevice(HostUSBDevice *aDevice);
85 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
86 /** @} */
87
88 static void freeDevice(PUSBDEVICE pDevice);
89
90protected:
91 int start(void);
92 int stop(void);
93 virtual void serviceThreadInit(void);
94 virtual void serviceThreadTerm(void);
95
96 virtual int wait(RTMSINTERVAL aMillies);
97 virtual int interruptWait(void);
98 virtual PUSBDEVICE getDevices(void);
99 uint32_t incRef();
100 uint32_t decRef();
101
102 static HRESULT setError(HRESULT aResultCode, const char *aText, ...);
103
104 static void initFilterFromDevice(PUSBFILTER aFilter, HostUSBDevice *aDevice);
105 static void freeDeviceMembers(PUSBDEVICE pDevice);
106
107 /**
108 * Backend specific callback when a device was added.
109 * (Currently only Linux uses it to adjust the udev polling).
110 */
111 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, PUSBDEVICE pDev);
112 virtual bool isFakeUpdateRequired();
113
114private:
115
116 // wrapped IUSBProxyBackend properties
117 HRESULT getName(com::Utf8Str &aName);
118 HRESULT getType(com::Utf8Str &aType);
119
120 static DECLCALLBACK(int) serviceThread(RTTHREAD Thread, void *pvUser);
121
122 void updateDeviceList(PUSBDEVICE pDevices);
123
124protected:
125 /** Pointer to the owning USB Proxy Service object. */
126 USBProxyService *m_pUsbProxyService;
127 /** Thread handle of the service thread. */
128 RTTHREAD mThread;
129 /** Flag which stop() sets to cause serviceThread to return. */
130 bool volatile mTerminate;
131 /** Id of the instance. */
132 const com::Utf8Str m_strId;
133 /** Address of the instance. */
134 const com::Utf8Str m_strAddress;
135 /** Backend identifier as used in the settings. */
136 const com::Utf8Str m_strBackend;
137 /** Reference counter which prevents the backend instance from being removed. */
138 uint32_t m_cRefs;
139 /** List of smart HostUSBDevice pointers. */
140 typedef std::list<ComObjPtr<HostUSBDevice> > HostUSBDeviceList;
141 /** List of the known USB devices for this backend. */
142 HostUSBDeviceList m_llDevices;
143};
144
145
146# if defined(RT_OS_DARWIN) || defined(DOXYGEN_RUNNING)
147# include <VBox/param.h>
148# undef PAGE_SHIFT
149# undef PAGE_SIZE
150# define OSType Carbon_OSType
151# include <Carbon/Carbon.h>
152# undef OSType
153# undef PVM
154
155/**
156 * The Darwin hosted USB Proxy Backend.
157 */
158class USBProxyBackendDarwin : public USBProxyBackend
159{
160public:
161 DECLARE_COMMON_CLASS_METHODS(USBProxyBackendDarwin)
162
163 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
164 const com::Utf8Str &strAddress, bool fLoadingSettings);
165 void uninit();
166
167 virtual int captureDevice(HostUSBDevice *aDevice);
168 virtual int releaseDevice(HostUSBDevice *aDevice);
169
170protected:
171 virtual int wait(RTMSINTERVAL aMillies);
172 virtual int interruptWait (void);
173 virtual PUSBDEVICE getDevices (void);
174 virtual void serviceThreadInit (void);
175 virtual void serviceThreadTerm (void);
176 virtual bool isFakeUpdateRequired();
177
178private:
179 /** Reference to the runloop of the service thread.
180 * This is NULL if the service thread isn't running. */
181 CFRunLoopRef mServiceRunLoopRef;
182 /** The opaque value returned by DarwinSubscribeUSBNotifications. */
183 void *mNotifyOpaque;
184 /** A hack to work around the problem with the usb device enumeration
185 * not including newly attached devices. */
186 bool mWaitABitNextTime;
187};
188# endif /* RT_OS_DARWIN */
189
190
191# if defined(RT_OS_LINUX) || defined(DOXYGEN_RUNNING)
192# include <stdio.h>
193# ifdef VBOX_USB_WITH_SYSFS
194# include <HostHardwareLinux.h>
195# endif
196
197/**
198 * The Linux hosted USB Proxy Backend.
199 */
200class USBProxyBackendLinux: public USBProxyBackend
201{
202public:
203 DECLARE_COMMON_CLASS_METHODS(USBProxyBackendLinux)
204
205 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
206 const com::Utf8Str &strAddress, bool fLoadingSettings);
207 void uninit();
208
209 virtual int captureDevice(HostUSBDevice *aDevice);
210 virtual int releaseDevice(HostUSBDevice *aDevice);
211
212protected:
213 int initUsbfs(void);
214 int initSysfs(void);
215 void doUsbfsCleanupAsNeeded(void);
216 virtual int wait(RTMSINTERVAL aMillies);
217 virtual int interruptWait(void);
218 virtual PUSBDEVICE getDevices(void);
219 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, PUSBDEVICE aUSBDevice);
220 virtual bool isFakeUpdateRequired();
221
222private:
223 int waitUsbfs(RTMSINTERVAL aMillies);
224 int waitSysfs(RTMSINTERVAL aMillies);
225
226private:
227 /** File handle to the '/proc/bus/usb/devices' file. */
228 RTFILE mhFile;
229 /** Pipe used to interrupt wait(), the read end. */
230 RTPIPE mhWakeupPipeR;
231 /** Pipe used to interrupt wait(), the write end. */
232 RTPIPE mhWakeupPipeW;
233 /** The root of usbfs. */
234 Utf8Str mDevicesRoot;
235 /** Whether we're using \<mUsbfsRoot\>/devices or /sys/whatever. */
236 bool mUsingUsbfsDevices;
237 /** Number of 500ms polls left to do. See usbDeterminState for details. */
238 unsigned mUdevPolls;
239# ifdef VBOX_USB_WITH_SYSFS
240 /** Object used for polling for hotplug events from hal. */
241 VBoxMainHotplugWaiter *mpWaiter;
242# endif
243};
244# endif /* RT_OS_LINUX */
245
246
247# if defined(RT_OS_OS2) || defined(DOXYGEN_RUNNING)
248# include <usbcalls.h>
249
250/**
251 * The Linux hosted USB Proxy Backend.
252 */
253class USBProxyBackendOs2 : public USBProxyBackend
254{
255public:
256 DECLARE_COMMON_CLASS_METHODS(USBProxyBackendOs2)
257
258 virtual int captureDevice(HostUSBDevice *aDevice);
259 virtual int releaseDevice(HostUSBDevice *aDevice);
260
261protected:
262 virtual int wait(RTMSINTERVAL aMillies);
263 virtual int interruptWait(void);
264 virtual PUSBDEVICE getDevices(void);
265 int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc);
266
267private:
268 /** The notification event semaphore */
269 HEV mhev;
270 /** The notification id. */
271 USBNOTIFY mNotifyId;
272 /** The usbcalls.dll handle. */
273 HMODULE mhmod;
274 /** UsbRegisterChangeNotification */
275 APIRET (APIENTRY *mpfnUsbRegisterChangeNotification)(PUSBNOTIFY, HEV, HEV);
276 /** UsbDeregisterNotification */
277 APIRET (APIENTRY *mpfnUsbDeregisterNotification)(USBNOTIFY);
278 /** UsbQueryNumberDevices */
279 APIRET (APIENTRY *mpfnUsbQueryNumberDevices)(PULONG);
280 /** UsbQueryDeviceReport */
281 APIRET (APIENTRY *mpfnUsbQueryDeviceReport)(ULONG, PULONG, PVOID);
282};
283# endif /* RT_OS_OS2 */
284
285
286# if defined(RT_OS_SOLARIS) || defined(DOXYGEN_RUNNING)
287# include <libdevinfo.h>
288
289/**
290 * The Solaris hosted USB Proxy Backend.
291 */
292class USBProxyBackendSolaris : public USBProxyBackend
293{
294public:
295 DECLARE_COMMON_CLASS_METHODS(USBProxyBackendSolaris)
296
297 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
298 const com::Utf8Str &strAddress, bool fLoadingSettings);
299 void uninit();
300
301 virtual void *insertFilter (PCUSBFILTER aFilter);
302 virtual void removeFilter (void *aID);
303
304 virtual int captureDevice(HostUSBDevice *aDevice);
305 virtual int releaseDevice(HostUSBDevice *aDevice);
306 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
307 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
308
309 virtual bool i_isDevReEnumerationRequired();
310
311protected:
312 virtual int wait(RTMSINTERVAL aMillies);
313 virtual int interruptWait(void);
314 virtual PUSBDEVICE getDevices(void);
315
316private:
317 RTSEMEVENT mNotifyEventSem;
318 /** Whether we've successfully initialized the USBLib and should call USBLibTerm in the destructor. */
319 bool mUSBLibInitialized;
320};
321#endif /* RT_OS_SOLARIS */
322
323
324# if defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)
325/**
326 * The Windows hosted USB Proxy Backend.
327 */
328class USBProxyBackendWindows : public USBProxyBackend
329{
330public:
331 DECLARE_COMMON_CLASS_METHODS(USBProxyBackendWindows)
332
333 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
334 const com::Utf8Str &strAddress, bool fLoadingSettings);
335 void uninit();
336
337 virtual void *insertFilter (PCUSBFILTER aFilter);
338 virtual void removeFilter (void *aID);
339
340 virtual int captureDevice(HostUSBDevice *aDevice);
341 virtual int releaseDevice(HostUSBDevice *aDevice);
342
343 virtual bool i_isDevReEnumerationRequired();
344
345protected:
346 virtual int wait(RTMSINTERVAL aMillies);
347 virtual int interruptWait(void);
348 virtual PUSBDEVICE getDevices(void);
349
350private:
351
352 HANDLE mhEventInterrupt;
353};
354# endif /* RT_OS_WINDOWS */
355
356# if defined(RT_OS_FREEBSD) || defined(DOXYGEN_RUNNING)
357/**
358 * The FreeBSD hosted USB Proxy Backend.
359 */
360class USBProxyBackendFreeBSD : public USBProxyBackend
361{
362public:
363 DECLARE_COMMON_CLASS_METHODS(USBProxyBackendFreeBSD)
364
365 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
366 const com::Utf8Str &strAddress, bool fLoadingSettings);
367 void uninit();
368
369 virtual int captureDevice(HostUSBDevice *aDevice);
370 virtual int releaseDevice(HostUSBDevice *aDevice);
371
372protected:
373 int initUsbfs(void);
374 int initSysfs(void);
375 virtual int wait(RTMSINTERVAL aMillies);
376 virtual int interruptWait(void);
377 virtual PUSBDEVICE getDevices(void);
378 int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc);
379 virtual bool isFakeUpdateRequired();
380
381private:
382 RTSEMEVENT mNotifyEventSem;
383};
384# endif /* RT_OS_FREEBSD */
385
386/**
387 * USB/IP Proxy receive state.
388 */
389typedef enum USBIPRECVSTATE
390{
391 /** Invalid state. */
392 kUsbIpRecvState_Invalid = 0,
393 /** There is no request waiting for an answer. */
394 kUsbIpRecvState_None,
395 /** Waiting for the complete reception of UsbIpRetDevList. */
396 kUsbIpRecvState_Hdr,
397 /** Waiting for the complete reception of a UsbIpExportedDevice structure. */
398 kUsbIpRecvState_ExportedDevice,
399 /** Waiting for a complete reception of a UsbIpDeviceInterface structure to skip. */
400 kUsbIpRecvState_DeviceInterface,
401 /** 32bit hack. */
402 kUsbIpRecvState_32Bit_Hack = 0x7fffffff
403} USBIPRECVSTATE;
404/** Pointer to a USB/IP receive state enum. */
405typedef USBIPRECVSTATE *PUSBIPRECVSTATE;
406
407struct UsbIpExportedDevice;
408
409/**
410 * The USB/IP Proxy Backend.
411 */
412class USBProxyBackendUsbIp: public USBProxyBackend
413{
414public:
415 DECLARE_COMMON_CLASS_METHODS(USBProxyBackendUsbIp)
416
417 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
418 const com::Utf8Str &strAddress, bool fLoadingSettings);
419 void uninit();
420
421 virtual int captureDevice(HostUSBDevice *aDevice);
422 virtual int releaseDevice(HostUSBDevice *aDevice);
423
424protected:
425 virtual int wait(RTMSINTERVAL aMillies);
426 virtual int interruptWait(void);
427 virtual PUSBDEVICE getDevices(void);
428 virtual bool isFakeUpdateRequired();
429
430private:
431 int updateDeviceList(bool *pfDeviceListChanged);
432 bool hasDevListChanged(PUSBDEVICE pDevices);
433 void freeDeviceList(PUSBDEVICE pHead);
434 void resetRecvState();
435 int reconnect();
436 void disconnect();
437 int startListExportedDevicesReq();
438 void advanceState(USBIPRECVSTATE enmRecvState);
439 int receiveData();
440 int processData();
441 int addDeviceToList(UsbIpExportedDevice *pDev);
442
443 struct Data; // opaque data struct, defined in USBProxyBackendUsbIp.cpp
444 Data *m;
445};
446
447#endif /* !MAIN_INCLUDED_USBProxyBackend_h */
448
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