VirtualBox

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

Last change on this file since 85574 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • 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 82968 2020-02-04 10:35:17Z 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_EMPTY_CTOR_DTOR(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
144/**
145 * The Darwin hosted USB Proxy Backend.
146 */
147class USBProxyBackendDarwin : public USBProxyBackend
148{
149public:
150 DECLARE_EMPTY_CTOR_DTOR(USBProxyBackendDarwin)
151
152 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
153 const com::Utf8Str &strAddress, bool fLoadingSettings);
154 void uninit();
155
156 virtual void *insertFilter(PCUSBFILTER aFilter);
157 virtual void removeFilter(void *aId);
158
159 virtual int captureDevice(HostUSBDevice *aDevice);
160 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
161 virtual int releaseDevice(HostUSBDevice *aDevice);
162 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
163
164 virtual bool i_isDevReEnumerationRequired();
165
166protected:
167 virtual int wait(RTMSINTERVAL aMillies);
168 virtual int interruptWait (void);
169 virtual PUSBDEVICE getDevices (void);
170 virtual void serviceThreadInit (void);
171 virtual void serviceThreadTerm (void);
172
173private:
174 /** Reference to the runloop of the service thread.
175 * This is NULL if the service thread isn't running. */
176 CFRunLoopRef mServiceRunLoopRef;
177 /** The opaque value returned by DarwinSubscribeUSBNotifications. */
178 void *mNotifyOpaque;
179 /** A hack to work around the problem with the usb device enumeration
180 * not including newly attached devices. */
181 bool mWaitABitNextTime;
182 /** Whether we've successfully initialized the USBLib and should call USBLibTerm in the destructor. */
183 bool mUSBLibInitialized;
184};
185# endif /* RT_OS_DARWIN */
186
187
188# if defined(RT_OS_LINUX) || defined(DOXYGEN_RUNNING)
189# include <stdio.h>
190# ifdef VBOX_USB_WITH_SYSFS
191# include <HostHardwareLinux.h>
192# endif
193
194/**
195 * The Linux hosted USB Proxy Backend.
196 */
197class USBProxyBackendLinux: public USBProxyBackend
198{
199public:
200 DECLARE_EMPTY_CTOR_DTOR(USBProxyBackendLinux)
201
202 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
203 const com::Utf8Str &strAddress, bool fLoadingSettings);
204 void uninit();
205
206 virtual int captureDevice(HostUSBDevice *aDevice);
207 virtual int releaseDevice(HostUSBDevice *aDevice);
208
209protected:
210 int initUsbfs(void);
211 int initSysfs(void);
212 void doUsbfsCleanupAsNeeded(void);
213 virtual int wait(RTMSINTERVAL aMillies);
214 virtual int interruptWait(void);
215 virtual PUSBDEVICE getDevices(void);
216 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, PUSBDEVICE aUSBDevice);
217 virtual bool isFakeUpdateRequired();
218
219private:
220 int waitUsbfs(RTMSINTERVAL aMillies);
221 int waitSysfs(RTMSINTERVAL aMillies);
222
223private:
224 /** File handle to the '/proc/bus/usb/devices' file. */
225 RTFILE mhFile;
226 /** Pipe used to interrupt wait(), the read end. */
227 RTPIPE mhWakeupPipeR;
228 /** Pipe used to interrupt wait(), the write end. */
229 RTPIPE mhWakeupPipeW;
230 /** The root of usbfs. */
231 Utf8Str mDevicesRoot;
232 /** Whether we're using \<mUsbfsRoot\>/devices or /sys/whatever. */
233 bool mUsingUsbfsDevices;
234 /** Number of 500ms polls left to do. See usbDeterminState for details. */
235 unsigned mUdevPolls;
236# ifdef VBOX_USB_WITH_SYSFS
237 /** Object used for polling for hotplug events from hal. */
238 VBoxMainHotplugWaiter *mpWaiter;
239# endif
240};
241# endif /* RT_OS_LINUX */
242
243
244# if defined(RT_OS_OS2) || defined(DOXYGEN_RUNNING)
245# include <usbcalls.h>
246
247/**
248 * The Linux hosted USB Proxy Backend.
249 */
250class USBProxyBackendOs2 : public USBProxyBackend
251{
252public:
253 DECLARE_EMPTY_CTOR_DTOR(USBProxyBackendOs2)
254
255 virtual int captureDevice(HostUSBDevice *aDevice);
256 virtual int releaseDevice(HostUSBDevice *aDevice);
257
258protected:
259 virtual int wait(RTMSINTERVAL aMillies);
260 virtual int interruptWait(void);
261 virtual PUSBDEVICE getDevices(void);
262 int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc);
263
264private:
265 /** The notification event semaphore */
266 HEV mhev;
267 /** The notification id. */
268 USBNOTIFY mNotifyId;
269 /** The usbcalls.dll handle. */
270 HMODULE mhmod;
271 /** UsbRegisterChangeNotification */
272 APIRET (APIENTRY *mpfnUsbRegisterChangeNotification)(PUSBNOTIFY, HEV, HEV);
273 /** UsbDeregisterNotification */
274 APIRET (APIENTRY *mpfnUsbDeregisterNotification)(USBNOTIFY);
275 /** UsbQueryNumberDevices */
276 APIRET (APIENTRY *mpfnUsbQueryNumberDevices)(PULONG);
277 /** UsbQueryDeviceReport */
278 APIRET (APIENTRY *mpfnUsbQueryDeviceReport)(ULONG, PULONG, PVOID);
279};
280# endif /* RT_OS_OS2 */
281
282
283# if defined(RT_OS_SOLARIS) || defined(DOXYGEN_RUNNING)
284# include <libdevinfo.h>
285
286/**
287 * The Solaris hosted USB Proxy Backend.
288 */
289class USBProxyBackendSolaris : public USBProxyBackend
290{
291public:
292 DECLARE_EMPTY_CTOR_DTOR(USBProxyBackendSolaris)
293
294 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
295 const com::Utf8Str &strAddress, bool fLoadingSettings);
296 void uninit();
297
298 virtual void *insertFilter (PCUSBFILTER aFilter);
299 virtual void removeFilter (void *aID);
300
301 virtual int captureDevice(HostUSBDevice *aDevice);
302 virtual int releaseDevice(HostUSBDevice *aDevice);
303 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
304 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
305
306 virtual bool i_isDevReEnumerationRequired();
307
308protected:
309 virtual int wait(RTMSINTERVAL aMillies);
310 virtual int interruptWait(void);
311 virtual PUSBDEVICE getDevices(void);
312
313private:
314 RTSEMEVENT mNotifyEventSem;
315 /** Whether we've successfully initialized the USBLib and should call USBLibTerm in the destructor. */
316 bool mUSBLibInitialized;
317};
318#endif /* RT_OS_SOLARIS */
319
320
321# if defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)
322/**
323 * The Windows hosted USB Proxy Backend.
324 */
325class USBProxyBackendWindows : public USBProxyBackend
326{
327public:
328 DECLARE_EMPTY_CTOR_DTOR(USBProxyBackendWindows)
329
330 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
331 const com::Utf8Str &strAddress, bool fLoadingSettings);
332 void uninit();
333
334 virtual void *insertFilter (PCUSBFILTER aFilter);
335 virtual void removeFilter (void *aID);
336
337 virtual int captureDevice(HostUSBDevice *aDevice);
338 virtual int releaseDevice(HostUSBDevice *aDevice);
339
340 virtual bool i_isDevReEnumerationRequired();
341
342protected:
343 virtual int wait(RTMSINTERVAL aMillies);
344 virtual int interruptWait(void);
345 virtual PUSBDEVICE getDevices(void);
346
347private:
348
349 HANDLE mhEventInterrupt;
350};
351# endif /* RT_OS_WINDOWS */
352
353# if defined(RT_OS_FREEBSD) || defined(DOXYGEN_RUNNING)
354/**
355 * The FreeBSD hosted USB Proxy Backend.
356 */
357class USBProxyBackendFreeBSD : public USBProxyBackend
358{
359public:
360 DECLARE_EMPTY_CTOR_DTOR(USBProxyBackendFreeBSD)
361
362 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
363 const com::Utf8Str &strAddress, bool fLoadingSettings);
364 void uninit();
365
366 virtual int captureDevice(HostUSBDevice *aDevice);
367 virtual int releaseDevice(HostUSBDevice *aDevice);
368
369protected:
370 int initUsbfs(void);
371 int initSysfs(void);
372 virtual int wait(RTMSINTERVAL aMillies);
373 virtual int interruptWait(void);
374 virtual PUSBDEVICE getDevices(void);
375 int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc);
376 virtual bool isFakeUpdateRequired();
377
378private:
379 RTSEMEVENT mNotifyEventSem;
380};
381# endif /* RT_OS_FREEBSD */
382
383/**
384 * USB/IP Proxy receive state.
385 */
386typedef enum USBIPRECVSTATE
387{
388 /** Invalid state. */
389 kUsbIpRecvState_Invalid = 0,
390 /** There is no request waiting for an answer. */
391 kUsbIpRecvState_None,
392 /** Waiting for the complete reception of UsbIpRetDevList. */
393 kUsbIpRecvState_Hdr,
394 /** Waiting for the complete reception of a UsbIpExportedDevice structure. */
395 kUsbIpRecvState_ExportedDevice,
396 /** Waiting for a complete reception of a UsbIpDeviceInterface structure to skip. */
397 kUsbIpRecvState_DeviceInterface,
398 /** 32bit hack. */
399 kUsbIpRecvState_32Bit_Hack = 0x7fffffff
400} USBIPRECVSTATE;
401/** Pointer to a USB/IP receive state enum. */
402typedef USBIPRECVSTATE *PUSBIPRECVSTATE;
403
404struct UsbIpExportedDevice;
405
406/**
407 * The USB/IP Proxy Backend.
408 */
409class USBProxyBackendUsbIp: public USBProxyBackend
410{
411public:
412 DECLARE_EMPTY_CTOR_DTOR(USBProxyBackendUsbIp)
413
414 int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId,
415 const com::Utf8Str &strAddress, bool fLoadingSettings);
416 void uninit();
417
418 virtual int captureDevice(HostUSBDevice *aDevice);
419 virtual int releaseDevice(HostUSBDevice *aDevice);
420
421protected:
422 virtual int wait(RTMSINTERVAL aMillies);
423 virtual int interruptWait(void);
424 virtual PUSBDEVICE getDevices(void);
425 virtual bool isFakeUpdateRequired();
426
427private:
428 int updateDeviceList(bool *pfDeviceListChanged);
429 bool hasDevListChanged(PUSBDEVICE pDevices);
430 void freeDeviceList(PUSBDEVICE pHead);
431 void resetRecvState();
432 int reconnect();
433 void disconnect();
434 int startListExportedDevicesReq();
435 void advanceState(USBIPRECVSTATE enmRecvState);
436 int receiveData();
437 int processData();
438 int addDeviceToList(UsbIpExportedDevice *pDev);
439
440 struct Data; // opaque data struct, defined in USBProxyBackendUsbIp.cpp
441 Data *m;
442};
443
444#endif /* !MAIN_INCLUDED_USBProxyBackend_h */
445
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