VirtualBox

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

Last change on this file since 53283 was 53062, checked in by vboxsync, 10 years ago

USB: Integrate USB sniffer. Make it possible to specify a file to dump the traffic to when attaching a USB device with VBoxManage

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.2 KB
Line 
1/* $Id: HostUSBDeviceImpl.h 53062 2014-10-15 12:34:18Z 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 getRemote(BOOL *aRemote);
260 HRESULT getName(com::Utf8Str &aName);
261 HRESULT getState(USBDeviceState_T *aState);
262
263
264 const Guid mId;
265
266 /** @name The state machine variables
267 * Only setState(), init() and uninit() will modify these members!
268 * @{ */
269 /** The RTTimeNanoTS() corresponding to the last state change.
270 *
271 * Old state machine: RTTimeNanoTS() of when mIsStatePending was set or mDetaching changed
272 * from kNotDetaching. For operations that cannot be canceled it's 0. */
273 uint64_t mLastStateChangeTS;
274 /** Current state. */
275 HostUSBDeviceState mUniState;
276 /** Sub-state for tracking re-enumeration. */
277 HostUSBDeviceSubState mUniSubState;
278 /** The final state of an pending transition.
279 * This is mainly a measure to reduce the number of HostUSBDeviceState values. */
280 HostUSBDeviceState mPendingUniState;
281 /** Previous state.
282 * This is used for bailing out when a transition like capture fails. */
283 HostUSBDeviceState mPrevUniState;
284 /** Indicator set by onDetachedPhys and check when advancing a transitional state. */
285 bool mIsPhysicallyDetached;
286 /** @} */
287
288 /** The machine the usb device is (being) attached to. */
289 ComObjPtr<SessionMachine> mMachine;
290 /** Pointer to the USB Proxy Service instance. */
291 USBProxyService *mUSBProxyService;
292 /** Pointer to the USB Device structure owned by this device.
293 * Only used for host devices. */
294 PUSBDEVICE mUsb;
295 /** The interface mask to be used in the pending capture.
296 * This is a filter property. */
297 ULONG mMaskedIfs;
298 /** The name of this device. */
299 Utf8Str mNameObj;
300 /** The name of this device (for logging purposes).
301 * This points to the string in mNameObj. */
302 const char *mName;
303 /** The filename to capture the USB traffic to. */
304 com::Utf8Str mCaptureFilename;
305
306 friend class USBProxyService;
307#ifdef RT_OS_SOLARIS
308 friend class USBProxyServiceSolaris;
309
310 /** One-shot filter id only for new code */
311 void *mOneShotId;
312#endif
313#ifdef RT_OS_LINUX
314 friend class USBProxyServiceLinux;
315#endif
316#ifdef RT_OS_DARWIN
317 /** One-shot filter id. */
318 void *mOneShotId;
319
320 friend class USBProxyServiceDarwin;
321#endif
322#ifdef RT_OS_FreeBSD
323 friend class USBProxyServiceFreeBSD;
324#endif
325};
326
327#endif // ____H_HOSTUSBDEVICEIMPL
328/* 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