VirtualBox

source: vbox/trunk/src/VBox/Main/include/HostUSBDeviceImpl.h@ 31891

Last change on this file since 31891 was 31891, checked in by vboxsync, 15 years ago

Main: export USBProxyService and USBFilter to OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
Line 
1/* $Id: HostUSBDeviceImpl.h 31891 2010-08-24 07:58:48Z vboxsync $ */
2/** @file
3 * VirtualBox IHostUSBDevice COM interface implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * Oracle Corporation confidential
10 * All rights reserved
11 */
12
13#ifndef ____H_HOSTUSBDEVICEIMPL
14#define ____H_HOSTUSBDEVICEIMPL
15
16#include "VirtualBoxBase.h"
17#include "USBDeviceFilterImpl.h"
18/* #include "USBProxyService.h" circular on Host/HostUSBDevice, the includer
19 * must include this. */
20
21#include <VBox/usb.h>
22#include "Logging.h"
23
24class SessionMachine;
25class USBProxyService;
26
27/**
28 * The unified state machine of HostUSBDevice.
29 *
30 * This is a super set of USBDEVICESTATE / USBDeviceState_T that
31 * includes additional states for tracking state transitions.
32 *
33 * @remarks
34 * The CapturingForVM and CapturingForProxy states have been merged
35 * into Capturing with a destination state (AttachingToVM or HeldByProxy).
36 *
37 * The DetachingFromVM state is a merge of DetachingFromVMToProxy and
38 * DetachingFromVMToHost and uses the destination state (HeldByProxy
39 * or ReleasingToHost) like Capturing.
40 *
41 * The *AwaitingDetach and *AwaitingReattach substates (optionally used
42 * in Capturing, AttachingToVM, DetachingFromVM and ReleasingToHost) are
43 * implemented via a substate kHostUSBDeviceSubState.
44 */
45typedef enum
46{
47 /** The device is unsupported (HUB).
48 * Next Host: PhysDetached.
49 * Next VBox: No change permitted.
50 */
51 kHostUSBDeviceState_Unsupported = USBDEVICESTATE_UNSUPPORTED,
52 /** The device is used exclusivly by the host or is inaccessible for some other reason.
53 * Next Host: Capturable, Unused, PhysDetached.
54 * Run filters.
55 * Next VBox: No change permitted.
56 */
57 kHostUSBDeviceState_UsedByHost = USBDEVICESTATE_USED_BY_HOST,
58 /** The device is used by the host but can be captured.
59 * Next Host: Unsupported, UsedByHost, Unused, PhysDetached.
60 * Run filters if Unused (for wildcard filters).
61 * Next VBox: CapturingForVM, CapturingForProxy.
62 */
63 kHostUSBDeviceState_Capturable = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE,
64 /** The device is not used by the host and can be captured.
65 * Next Host: UsedByHost, Capturable, PhysDetached
66 * Don't run any filters (done on state entry).
67 * Next VBox: CapturingForVM, CapturingForProxy.
68 */
69 kHostUSBDeviceState_Unused = USBDEVICESTATE_UNUSED,
70 /** The device is held captive by the proxy.
71 * Next Host: PhysDetached
72 * Next VBox: ReleasingHeld, AttachingToVM
73 */
74 kHostUSBDeviceState_HeldByProxy = USBDEVICESTATE_HELD_BY_PROXY,
75 /** The device is in use by a VM.
76 * Next Host: PhysDetachingFromVM
77 * Next VBox: DetachingFromVM
78 */
79 kHostUSBDeviceState_UsedByVM = USBDEVICESTATE_USED_BY_GUEST,
80 /** The device has been detach from both the host and VMs.
81 * This is the final state. */
82 kHostUSBDeviceState_PhysDetached = 9,
83
84
85 /** The start of the transitional states. */
86 kHostUSBDeviceState_FirstTransitional,
87
88 /** The device is being seized from the host, either for HeldByProxy or for AttachToVM.
89 *
90 * On some hosts we will need to re-enumerate the in which case the sub-state
91 * is employed to track this progress. On others, this is synchronous or faked, and
92 * will will then leave the device in this state and poke the service thread to do
93 * the completion state change.
94 *
95 * Next Host: PhysDetached.
96 * Next VBox: HeldByProxy or AttachingToVM on success,
97 * previous state (Unused or Capturable) or UsedByHost on failure.
98 */
99 kHostUSBDeviceState_Capturing = kHostUSBDeviceState_FirstTransitional,
100
101 /** The device is being released back to the host, following VM or Proxy usage.
102 * Most hosts needs to re-enumerate the device and will therefore employ the
103 * sub-state as during capturing. On the others we'll just leave it to the usb
104 * service thread to advance the device state.
105 *
106 * Next Host: Unused, UsedByHost, Capturable.
107 * No filters.
108 * Next VBox: PhysDetached (timeout), HeldByProxy (failure).
109 */
110 kHostUSBDeviceState_ReleasingToHost,
111
112 /** The device is being attached to a VM.
113 *
114 * This requires IPC to the VM and we will not advance the state until
115 * that completes.
116 *
117 * Next Host: PhysDetachingFromVM.
118 * Next VBox: UsedByGuest, HeldByProxy (failure).
119 */
120 kHostUSBDeviceState_AttachingToVM,
121
122 /** The device is being detached from a VM and will be returned to the proxy or host.
123 *
124 * This involves IPC and may or may not also require re-enumeration of the
125 * device. Which means that it might transition directly into the ReleasingToHost state
126 * because the client (VM) will do the actual re-enumeration.
127 *
128 * Next Host: PhysDetachingFromVM (?) or just PhysDetached.
129 * Next VBox: ReleasingToHost, HeldByProxy.
130 */
131 kHostUSBDeviceState_DetachingFromVM,
132
133 /** The device has been physically removed while a VM used it.
134 *
135 * This is the device state while VBoxSVC is doing IPC to the client (VM) telling it
136 * to detach it.
137 *
138 * Next Host: None.
139 * Next VBox: PhysDetached
140 */
141 kHostUSBDeviceState_PhysDetachingFromVM,
142
143 /** Just an invalid state value for use as default for some methods. */
144 kHostUSBDeviceState_Invalid = 0x7fff
145} HostUSBDeviceState;
146
147
148/**
149 * Sub-state for dealing with device re-enumeration.
150 */
151typedef enum
152{
153 /** Not in any sub-state. */
154 kHostUSBDeviceSubState_Default = 0,
155 /** Awaiting a logical device detach following a device re-enumeration. */
156 kHostUSBDeviceSubState_AwaitingDetach,
157 /** Awaiting a logical device re-attach following a device re-enumeration. */
158 kHostUSBDeviceSubState_AwaitingReAttach
159} HostUSBDeviceSubState;
160
161
162/**
163 * Object class used to hold Host USB Device properties.
164 */
165class ATL_NO_VTABLE HostUSBDevice :
166 public VirtualBoxBase,
167 VBOX_SCRIPTABLE_IMPL(IHostUSBDevice)
168{
169public:
170
171 VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(HostUSBDevice, IHostUSBDevice)
172
173 DECLARE_NOT_AGGREGATABLE(HostUSBDevice)
174
175 DECLARE_PROTECT_FINAL_CONSTRUCT()
176
177 BEGIN_COM_MAP(HostUSBDevice)
178 COM_INTERFACE_ENTRY(ISupportErrorInfo)
179 COM_INTERFACE_ENTRY(IHostUSBDevice)
180 COM_INTERFACE_ENTRY(IUSBDevice)
181 COM_INTERFACE_ENTRY(IDispatch)
182 END_COM_MAP()
183
184 DECLARE_EMPTY_CTOR_DTOR (HostUSBDevice)
185
186 HRESULT FinalConstruct();
187 void FinalRelease();
188
189 // public initializer/uninitializer for internal purposes only
190 HRESULT init(PUSBDEVICE aUsb, USBProxyService *aUSBProxyService);
191 void uninit();
192
193 // IUSBDevice properties
194 STDMETHOD(COMGETTER(Id))(BSTR *aId);
195 STDMETHOD(COMGETTER(VendorId))(USHORT *aVendorId);
196 STDMETHOD(COMGETTER(ProductId))(USHORT *aProductId);
197 STDMETHOD(COMGETTER(Revision))(USHORT *aRevision);
198 STDMETHOD(COMGETTER(Manufacturer))(BSTR *aManufacturer);
199 STDMETHOD(COMGETTER(Product))(BSTR *aProduct);
200 STDMETHOD(COMGETTER(SerialNumber))(BSTR *aSerialNumber);
201 STDMETHOD(COMGETTER(Address))(BSTR *aAddress);
202 STDMETHOD(COMGETTER(Port))(USHORT *aPort);
203 STDMETHOD(COMGETTER(Version))(USHORT *aVersion);
204 STDMETHOD(COMGETTER(PortVersion))(USHORT *aPortVersion);
205 STDMETHOD(COMGETTER(Remote))(BOOL *aRemote);
206
207 // IHostUSBDevice properties
208 STDMETHOD(COMGETTER(State))(USBDeviceState_T *aState);
209
210 // public methods only for internal purposes
211
212 /** @note Must be called from under the object read lock. */
213 const Guid& getId() const { return mId; }
214
215 /** @note Must be called from under the object read lock. */
216 HostUSBDeviceState getUnistate() const { return mUniState; }
217
218 /** @note Must be called from under the object read lock. */
219 const char *getStateName() { return stateName (mUniState, mPendingUniState, mUniSubState); }
220
221 /** @note Must be called from under the object read lock. */
222 bool isCapturableOrHeld()
223 {
224 return mUniState == kHostUSBDeviceState_Unused
225 || mUniState == kHostUSBDeviceState_Capturable
226 || mUniState == kHostUSBDeviceState_HeldByProxy;
227 }
228
229 /** @note Must be called from under the object read lock. */
230 ComObjPtr<SessionMachine> &getMachine() { return mMachine; }
231
232 /** @note Must be called from under the object read lock. */
233 PCUSBDEVICE getUsbData() const { return mUsb; }
234
235 Utf8Str getName();
236
237 HRESULT requestCaptureForVM(SessionMachine *aMachine, bool aSetError, ULONG aMaskedIfs = 0);
238 HRESULT onDetachFromVM(SessionMachine *aMachine, bool aDone, bool *aRunFilters, bool aAbnormal = false);
239 HRESULT requestReleaseToHost();
240 HRESULT requestHold();
241 bool wasActuallyDetached();
242 void onPhysicalDetached();
243
244 bool isMatch(const USBDeviceFilter::Data &aData);
245 int compare(PCUSBDEVICE aDev2);
246 static int compare(PCUSBDEVICE aDev1, PCUSBDEVICE aDev2, bool aIsAwaitingReAttach = false);
247
248 bool updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMachine **aIgnoreMachine);
249 bool updateStateFake(PCUSBDEVICE aDev, bool *aRunFilters, SessionMachine **aIgnoreMachine);
250
251 static const char *stateName(HostUSBDeviceState aState,
252 HostUSBDeviceState aPendingState = kHostUSBDeviceState_Invalid,
253 HostUSBDeviceSubState aSubState = kHostUSBDeviceSubState_Default);
254
255protected:
256 HRESULT attachToVM(SessionMachine *aMachine, ULONG aMaskedIfs = 0);
257 void detachFromVM(HostUSBDeviceState aFinalState);
258 void onPhysicalDetachedInternal();
259 bool hasAsyncOperationTimedOut() const;
260
261 bool setState (HostUSBDeviceState aNewState, HostUSBDeviceState aNewPendingState = kHostUSBDeviceState_Invalid,
262 HostUSBDeviceSubState aNewSubState = kHostUSBDeviceSubState_Default);
263 bool startTransition (HostUSBDeviceState aNewState, HostUSBDeviceState aFinalState,
264 HostUSBDeviceSubState aNewSubState = kHostUSBDeviceSubState_Default);
265 bool advanceTransition(bool aSkipReAttach = false);
266 bool failTransition();
267 USBDeviceState_T canonicalState() const;
268
269private:
270
271 const Guid mId;
272
273 /** @name The state machine variables
274 * Only setState(), init() and uninit() will modify these members!
275 * @{ */
276 /** The RTTimeNanoTS() corresponding to the last state change.
277 *
278 * Old state machine: RTTimeNanoTS() of when mIsStatePending was set or mDetaching changed
279 * from kNotDetaching. For operations that cannot be canceled it's 0. */
280 uint64_t mLastStateChangeTS;
281 /** Current state. */
282 HostUSBDeviceState mUniState;
283 /** Sub-state for tracking re-enumeration. */
284 HostUSBDeviceSubState mUniSubState;
285 /** The final state of an pending transition.
286 * This is mainly a measure to reduce the number of HostUSBDeviceState values. */
287 HostUSBDeviceState mPendingUniState;
288 /** Previous state.
289 * This is used for bailing out when a transition like caputure fails. */
290 HostUSBDeviceState mPrevUniState;
291 /** Indicator set by onDetachedPhys and check when advancing a transitional state. */
292 bool mIsPhysicallyDetached;
293 /** @} */
294
295 /** The machine the usb device is (being) attached to. */
296 ComObjPtr<SessionMachine> mMachine;
297 /** Pointer to the USB Proxy Service instance. */
298 USBProxyService *mUSBProxyService;
299 /** Pointer to the USB Device structure owned by this device.
300 * Only used for host devices. */
301 PUSBDEVICE mUsb;
302 /** The interface mask to be used in the pending capture.
303 * This is a filter property. */
304 ULONG mMaskedIfs;
305 /** The name of this device. */
306 Utf8Str mNameObj;
307 /** The name of this device (for logging purposes).
308 * This points to the string in mNameObj. */
309 const char *mName;
310
311 friend class USBProxyService;
312#ifdef RT_OS_SOLARIS
313 friend class USBProxyServiceSolaris;
314
315# ifdef VBOX_WITH_NEW_USB_CODE_ON_SOLARIS
316 /** One-shot filter id only for new code */
317 void *mOneShotId;
318# endif
319#endif
320#ifdef RT_OS_LINUX
321 friend class USBProxyServiceLinux;
322#endif
323#ifdef RT_OS_DARWIN
324 /** One-shot filter id. */
325 void *mOneShotId;
326
327 friend class USBProxyServiceDarwin;
328#endif
329#ifdef RT_OS_FreeBSD
330 friend class USBProxyServiceFreeBSD;
331#endif
332};
333
334#endif // ____H_HOSTUSBDEVICEIMPL
335/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette