VirtualBox

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

Last change on this file since 51498 was 49960, checked in by vboxsync, 11 years ago

6813 stage 6 - Make use of server side API wrapper code in all interfaces

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.0 KB
Line 
1/* $Id: HostUSBDeviceImpl.h 49960 2013-12-17 17:24:57Z 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, 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::Data &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
229protected:
230
231 HRESULT i_attachToVM(SessionMachine *aMachine, ULONG aMaskedIfs = 0);
232 void i_detachFromVM(HostUSBDeviceState aFinalState);
233 void i_onPhysicalDetachedInternal();
234 bool i_hasAsyncOperationTimedOut() const;
235
236 bool i_setState (HostUSBDeviceState aNewState, HostUSBDeviceState aNewPendingState = kHostUSBDeviceState_Invalid,
237 HostUSBDeviceSubState aNewSubState = kHostUSBDeviceSubState_Default);
238 bool i_startTransition (HostUSBDeviceState aNewState, HostUSBDeviceState aFinalState,
239 HostUSBDeviceSubState aNewSubState = kHostUSBDeviceSubState_Default);
240 bool i_advanceTransition(bool aSkipReAttach = false);
241 bool i_failTransition();
242 USBDeviceState_T i_canonicalState() const;
243
244private:
245
246 // wrapped IUSBDevice properties
247 HRESULT getId(com::Guid &aId);
248 HRESULT getVendorId(USHORT *aVendorId);
249 HRESULT getProductId(USHORT *aProductId);
250 HRESULT getRevision(USHORT *aRevision);
251 HRESULT getManufacturer(com::Utf8Str &aManufacturer);
252 HRESULT getProduct(com::Utf8Str &aProduct);
253 HRESULT getSerialNumber(com::Utf8Str &aSerialNumber);
254 HRESULT getAddress(com::Utf8Str &aAddress);
255 HRESULT getPort(USHORT *aPort);
256 HRESULT getVersion(USHORT *aVersion);
257 HRESULT getPortVersion(USHORT *aPortVersion);
258 HRESULT getRemote(BOOL *aRemote);
259 HRESULT getName(com::Utf8Str &aName);
260 HRESULT getState(USBDeviceState_T *aState);
261
262
263 const Guid mId;
264
265 /** @name The state machine variables
266 * Only setState(), init() and uninit() will modify these members!
267 * @{ */
268 /** The RTTimeNanoTS() corresponding to the last state change.
269 *
270 * Old state machine: RTTimeNanoTS() of when mIsStatePending was set or mDetaching changed
271 * from kNotDetaching. For operations that cannot be canceled it's 0. */
272 uint64_t mLastStateChangeTS;
273 /** Current state. */
274 HostUSBDeviceState mUniState;
275 /** Sub-state for tracking re-enumeration. */
276 HostUSBDeviceSubState mUniSubState;
277 /** The final state of an pending transition.
278 * This is mainly a measure to reduce the number of HostUSBDeviceState values. */
279 HostUSBDeviceState mPendingUniState;
280 /** Previous state.
281 * This is used for bailing out when a transition like capture fails. */
282 HostUSBDeviceState mPrevUniState;
283 /** Indicator set by onDetachedPhys and check when advancing a transitional state. */
284 bool mIsPhysicallyDetached;
285 /** @} */
286
287 /** The machine the usb device is (being) attached to. */
288 ComObjPtr<SessionMachine> mMachine;
289 /** Pointer to the USB Proxy Service instance. */
290 USBProxyService *mUSBProxyService;
291 /** Pointer to the USB Device structure owned by this device.
292 * Only used for host devices. */
293 PUSBDEVICE mUsb;
294 /** The interface mask to be used in the pending capture.
295 * This is a filter property. */
296 ULONG mMaskedIfs;
297 /** The name of this device. */
298 Utf8Str mNameObj;
299 /** The name of this device (for logging purposes).
300 * This points to the string in mNameObj. */
301 const char *mName;
302
303 friend class USBProxyService;
304#ifdef RT_OS_SOLARIS
305 friend class USBProxyServiceSolaris;
306
307 /** One-shot filter id only for new code */
308 void *mOneShotId;
309#endif
310#ifdef RT_OS_LINUX
311 friend class USBProxyServiceLinux;
312#endif
313#ifdef RT_OS_DARWIN
314 /** One-shot filter id. */
315 void *mOneShotId;
316
317 friend class USBProxyServiceDarwin;
318#endif
319#ifdef RT_OS_FreeBSD
320 friend class USBProxyServiceFreeBSD;
321#endif
322};
323
324#endif // ____H_HOSTUSBDEVICEIMPL
325/* 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