VirtualBox

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

Last change on this file since 33959 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

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