VirtualBox

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

Last change on this file since 60742 was 60742, checked in by vboxsync, 9 years ago

Main/USBProxy{Service|Backend}: Rework interaction between thos two to be more sane than it currently is (calling into each other back and forth)

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