VirtualBox

source: vbox/trunk/src/VBox/Main/include/USBProxyService.h@ 47148

Last change on this file since 47148 was 41528, checked in by vboxsync, 13 years ago

Main/HostUSBDevice(all platforms)+USBProxyService: redo USB locking, fixes major regression, added lots of assertions to catch locking flaws early, whitespace cleanup
Main/Machine: small USB locking fix to be consistent with the remaining code
Main/Host+glue/AutoLock: replace USB list lock by host lock, small numbering cleanup
Main/Console: redo USB locking, do less in USB callbacks/EMT (addresses long standing todo items), eliminate unsafe iterator parameters

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1/* $Id: USBProxyService.h 41528 2012-05-31 16:48:33Z vboxsync $ */
2/** @file
3 * VirtualBox USB Proxy Service (base) class.
4 */
5
6/*
7 * Copyright (C) 2005-2012 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_USBPROXYSERVICE
20#define ____H_USBPROXYSERVICE
21
22#include <VBox/usb.h>
23#include <VBox/usbfilter.h>
24
25#include "VirtualBoxBase.h"
26#include "VirtualBoxImpl.h"
27#include "HostUSBDeviceImpl.h"
28class Host;
29
30/**
31 * Base class for the USB Proxy service.
32 */
33class USBProxyService
34 : public VirtualBoxTranslatable
35{
36public:
37 USBProxyService(Host *aHost);
38 virtual HRESULT init(void);
39 virtual ~USBProxyService();
40
41 /**
42 * Override of the default locking class to be used for validating lock
43 * order with the standard member lock handle.
44 */
45 virtual VBoxLockingClass getLockingClass() const
46 {
47 // the USB proxy service uses the Host object lock, so return the
48 // same locking class as the host
49 return LOCKCLASS_HOSTOBJECT;
50 }
51
52 bool isActive(void);
53 int getLastError(void);
54 HRESULT getLastErrorMessage(BSTR *aError);
55
56 RWLockHandle *lockHandle() const;
57
58 /** @name Host Interfaces
59 * @{ */
60 HRESULT getDeviceCollection(ComSafeArrayOut(IHostUSBDevice *, aUSBDevices));
61 /** @} */
62
63 /** @name SessionMachine Interfaces
64 * @{ */
65 HRESULT captureDeviceForVM(SessionMachine *aMachine, IN_GUID aId);
66 HRESULT detachDeviceFromVM(SessionMachine *aMachine, IN_GUID aId, bool aDone);
67 HRESULT autoCaptureDevicesForVM(SessionMachine *aMachine);
68 HRESULT detachAllDevicesFromVM(SessionMachine *aMachine, bool aDone, bool aAbnormal);
69 /** @} */
70
71 /** @name Interface for the USBController and the Host object.
72 * @{ */
73 virtual void *insertFilter(PCUSBFILTER aFilter);
74 virtual void removeFilter(void *aId);
75 /** @} */
76
77 /** @name Interfaces for the HostUSBDevice
78 * @{ */
79 virtual int captureDevice(HostUSBDevice *aDevice);
80 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
81 /** @todo unused */
82 virtual void detachingDevice(HostUSBDevice *aDevice);
83 virtual int releaseDevice(HostUSBDevice *aDevice);
84 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
85 /** @} */
86
87protected:
88 int start(void);
89 int stop(void);
90 virtual void serviceThreadInit(void);
91 virtual void serviceThreadTerm(void);
92
93 virtual int wait(RTMSINTERVAL aMillies);
94 virtual int interruptWait(void);
95 virtual PUSBDEVICE getDevices(void);
96 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice);
97 virtual void deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice);
98 virtual void deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList *pllOpenedMachines, SessionMachine *aIgnoreMachine);
99 bool updateDeviceStateFake(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);
100 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);
101
102 ComObjPtr<HostUSBDevice> findDeviceById(IN_GUID aId);
103
104 static HRESULT setError(HRESULT aResultCode, const char *aText, ...);
105
106 static void initFilterFromDevice(PUSBFILTER aFilter, HostUSBDevice *aDevice);
107 static void freeDeviceMembers(PUSBDEVICE pDevice);
108public:
109 static void freeDevice(PUSBDEVICE pDevice);
110
111private:
112 HRESULT runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice,
113 SessionMachinesList &llOpenedMachines,
114 SessionMachine *aIgnoreMachine);
115 bool runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice);
116 void processChanges(void);
117 static DECLCALLBACK(int) serviceThread(RTTHREAD Thread, void *pvUser);
118
119protected:
120 /** Pointer to the Host object. */
121 Host *mHost;
122 /** Thread handle of the service thread. */
123 RTTHREAD mThread;
124 /** Flag which stop() sets to cause serviceThread to return. */
125 bool volatile mTerminate;
126 /** VBox status code of the last failure.
127 * (Only used by start(), stop() and the child constructors.) */
128 int mLastError;
129 /** Optional error message to complement mLastError. */
130 Bstr mLastErrorMessage;
131 /** List of smart HostUSBDevice pointers. */
132 typedef std::list<ComObjPtr<HostUSBDevice> > HostUSBDeviceList;
133 /** List of the known USB devices. */
134 HostUSBDeviceList mDevices;
135};
136
137
138# ifdef RT_OS_DARWIN
139# include <VBox/param.h>
140# undef PAGE_SHIFT
141# undef PAGE_SIZE
142# define OSType Carbon_OSType
143# include <Carbon/Carbon.h>
144# undef OSType
145
146/**
147 * The Darwin hosted USB Proxy Service.
148 */
149class USBProxyServiceDarwin : public USBProxyService
150{
151public:
152 USBProxyServiceDarwin(Host *aHost);
153 HRESULT init(void);
154 ~USBProxyServiceDarwin();
155
156#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
157 virtual void *insertFilter(PCUSBFILTER aFilter);
158 virtual void removeFilter(void *aId);
159#endif
160
161 virtual int captureDevice(HostUSBDevice *aDevice);
162 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
163 /** @todo unused */
164 virtual void detachingDevice(HostUSBDevice *aDevice);
165 virtual int releaseDevice(HostUSBDevice *aDevice);
166 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
167
168protected:
169 virtual int wait(RTMSINTERVAL aMillies);
170 virtual int interruptWait (void);
171 virtual PUSBDEVICE getDevices (void);
172 virtual void serviceThreadInit (void);
173 virtual void serviceThreadTerm (void);
174 virtual bool updateDeviceState (HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);
175
176private:
177 /** Reference to the runloop of the service thread.
178 * This is NULL if the service thread isn't running. */
179 CFRunLoopRef mServiceRunLoopRef;
180 /** The opaque value returned by DarwinSubscribeUSBNotifications. */
181 void *mNotifyOpaque;
182 /** A hack to work around the problem with the usb device enumeration
183 * not including newly attached devices. */
184 bool mWaitABitNextTime;
185#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
186 /** Whether we've got a fake async event and should return without entering the runloop. */
187 bool volatile mFakeAsync;
188#endif
189 /** Whether we've successfully initialized the USBLib and should call USBLibTerm in the destructor. */
190 bool mUSBLibInitialized;
191};
192# endif /* RT_OS_DARWIN */
193
194
195# ifdef RT_OS_LINUX
196# include <stdio.h>
197# ifdef VBOX_USB_WITH_SYSFS
198# include <HostHardwareLinux.h>
199# endif
200
201/**
202 * The Linux hosted USB Proxy Service.
203 */
204class USBProxyServiceLinux
205 : public USBProxyService
206{
207public:
208 USBProxyServiceLinux(Host *aHost);
209 HRESULT init(void);
210 ~USBProxyServiceLinux();
211
212 virtual int captureDevice(HostUSBDevice *aDevice);
213 virtual int releaseDevice(HostUSBDevice *aDevice);
214
215protected:
216 int initUsbfs(void);
217 int initSysfs(void);
218 void doUsbfsCleanupAsNeeded(void);
219 virtual int wait(RTMSINTERVAL aMillies);
220 virtual int interruptWait(void);
221 virtual PUSBDEVICE getDevices(void);
222 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice);
223 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);
224
225private:
226 int waitUsbfs(RTMSINTERVAL aMillies);
227 int waitSysfs(RTMSINTERVAL aMillies);
228
229private:
230 /** File handle to the '/proc/bus/usb/devices' file. */
231 RTFILE mhFile;
232 /** Pipe used to interrupt wait(), the read end. */
233 RTPIPE mhWakeupPipeR;
234 /** Pipe used to interrupt wait(), the write end. */
235 RTPIPE mhWakeupPipeW;
236 /** The root of usbfs. */
237 Utf8Str mDevicesRoot;
238 /** Whether we're using <mUsbfsRoot>/devices or /sys/whatever. */
239 bool mUsingUsbfsDevices;
240 /** Number of 500ms polls left to do. See usbDeterminState for details. */
241 unsigned mUdevPolls;
242# ifdef VBOX_USB_WITH_SYSFS
243 /** Object used for polling for hotplug events from hal. */
244 VBoxMainHotplugWaiter *mpWaiter;
245# endif
246};
247# endif /* RT_OS_LINUX */
248
249
250# ifdef RT_OS_OS2
251# include <usbcalls.h>
252
253/**
254 * The Linux hosted USB Proxy Service.
255 */
256class USBProxyServiceOs2 : public USBProxyService
257{
258public:
259 USBProxyServiceOs2 (Host *aHost);
260 /// @todo virtual HRESULT init(void);
261 ~USBProxyServiceOs2();
262
263 virtual int captureDevice (HostUSBDevice *aDevice);
264 virtual int releaseDevice (HostUSBDevice *aDevice);
265
266protected:
267 virtual int wait(RTMSINTERVAL aMillies);
268 virtual int interruptWait(void);
269 virtual PUSBDEVICE getDevices(void);
270 int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc);
271 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);
272
273private:
274 /** The notification event semaphore */
275 HEV mhev;
276 /** The notification id. */
277 USBNOTIFY mNotifyId;
278 /** The usbcalls.dll handle. */
279 HMODULE mhmod;
280 /** UsbRegisterChangeNotification */
281 APIRET (APIENTRY *mpfnUsbRegisterChangeNotification)(PUSBNOTIFY, HEV, HEV);
282 /** UsbDeregisterNotification */
283 APIRET (APIENTRY *mpfnUsbDeregisterNotification)(USBNOTIFY);
284 /** UsbQueryNumberDevices */
285 APIRET (APIENTRY *mpfnUsbQueryNumberDevices)(PULONG);
286 /** UsbQueryDeviceReport */
287 APIRET (APIENTRY *mpfnUsbQueryDeviceReport)(ULONG, PULONG, PVOID);
288};
289# endif /* RT_OS_LINUX */
290
291
292# ifdef RT_OS_SOLARIS
293# include <libdevinfo.h>
294
295/**
296 * The Solaris hosted USB Proxy Service.
297 */
298class USBProxyServiceSolaris : public USBProxyService
299{
300public:
301 USBProxyServiceSolaris(Host *aHost);
302 HRESULT init(void);
303 ~USBProxyServiceSolaris();
304
305 virtual void *insertFilter (PCUSBFILTER aFilter);
306 virtual void removeFilter (void *aID);
307
308 virtual int captureDevice (HostUSBDevice *aDevice);
309 virtual int releaseDevice (HostUSBDevice *aDevice);
310 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
311 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
312
313protected:
314 virtual int wait(RTMSINTERVAL aMillies);
315 virtual int interruptWait(void);
316 virtual PUSBDEVICE getDevices(void);
317 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);
318
319private:
320 RTSEMEVENT mNotifyEventSem;
321 /** Whether we've successfully initialized the USBLib and should call USBLibTerm in the destructor. */
322 bool mUSBLibInitialized;
323};
324#endif /* RT_OS_SOLARIS */
325
326
327# ifdef RT_OS_WINDOWS
328/**
329 * The Windows hosted USB Proxy Service.
330 */
331class USBProxyServiceWindows : public USBProxyService
332{
333public:
334 USBProxyServiceWindows(Host *aHost);
335 HRESULT init(void);
336 ~USBProxyServiceWindows();
337
338 virtual void *insertFilter (PCUSBFILTER aFilter);
339 virtual void removeFilter (void *aID);
340
341 virtual int captureDevice (HostUSBDevice *aDevice);
342 virtual int releaseDevice (HostUSBDevice *aDevice);
343
344protected:
345 virtual int wait(RTMSINTERVAL aMillies);
346 virtual int interruptWait(void);
347 virtual PUSBDEVICE getDevices(void);
348 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);
349
350private:
351
352 HANDLE mhEventInterrupt;
353};
354# endif /* RT_OS_WINDOWS */
355
356# ifdef RT_OS_FREEBSD
357/**
358 * The FreeBSD hosted USB Proxy Service.
359 */
360class USBProxyServiceFreeBSD : public USBProxyService
361{
362public:
363 USBProxyServiceFreeBSD(Host *aHost);
364 HRESULT init(void);
365 ~USBProxyServiceFreeBSD();
366
367 virtual int captureDevice(HostUSBDevice *aDevice);
368 virtual int releaseDevice(HostUSBDevice *aDevice);
369
370protected:
371 int initUsbfs(void);
372 int initSysfs(void);
373 virtual int wait(RTMSINTERVAL aMillies);
374 virtual int interruptWait(void);
375 virtual PUSBDEVICE getDevices(void);
376 int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc);
377 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice);
378 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);
379
380private:
381 RTSEMEVENT mNotifyEventSem;
382};
383# endif /* RT_OS_FREEBSD */
384
385#endif /* !____H_USBPROXYSERVICE */
386/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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