VirtualBox

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

Last change on this file since 70675 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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