VirtualBox

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

Last change on this file since 67954 was 65854, checked in by vboxsync, 8 years ago

Main/USBProxyBackendUsbIp: Don't prevent VBoxSVC from starting when the server is not reachable, just try to reconnect every 3 seconds. Smaller other fixes for stale USB device lists when the server is not reachable and a fix for saving the same USB source multiple times

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