VirtualBox

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

Last change on this file since 92154 was 91333, checked in by vboxsync, 3 years ago

Main: Darwin build fix, bugref:10098

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

© 2023 Oracle
ContactPrivacy policyTerms of Use