VirtualBox

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

Last change on this file since 55805 was 53297, checked in by vboxsync, 10 years ago

Main: Added API to report actual USB device speed.

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