VirtualBox

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

Last change on this file since 7954 was 7954, checked in by vboxsync, 16 years ago

HostUSBDeviceState and HostUSBDeviceSubState typedefs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/** @file
2 *
3 * VirtualBox IHostUSBDevice COM interface implementation
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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#include "Collection.h"
26
27#include <VBox/usb.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 has 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} 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 VirtualBoxBaseNEXT,
170 public VirtualBoxSupportErrorInfoImpl <HostUSBDevice, IHostUSBDevice>,
171 public VirtualBoxSupportTranslation <HostUSBDevice>,
172 public IHostUSBDevice
173{
174public:
175
176 VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT (HostUSBDevice)
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 END_COM_MAP()
187
188 NS_DECL_ISUPPORTS
189
190 DECLARE_EMPTY_CTOR_DTOR (HostUSBDevice)
191
192 HRESULT FinalConstruct();
193 void FinalRelease();
194
195 // public initializer/uninitializer for internal purposes only
196 HRESULT init(PUSBDEVICE aUsb, USBProxyService *aUSBProxyService);
197 void uninit();
198
199 // IUSBDevice properties
200 STDMETHOD(COMGETTER(Id))(GUIDPARAMOUT aId);
201 STDMETHOD(COMGETTER(VendorId))(USHORT *aVendorId);
202 STDMETHOD(COMGETTER(ProductId))(USHORT *aProductId);
203 STDMETHOD(COMGETTER(Revision))(USHORT *aRevision);
204 STDMETHOD(COMGETTER(Manufacturer))(BSTR *aManufacturer);
205 STDMETHOD(COMGETTER(Product))(BSTR *aProduct);
206 STDMETHOD(COMGETTER(SerialNumber))(BSTR *aSerialNumber);
207 STDMETHOD(COMGETTER(Address))(BSTR *aAddress);
208 STDMETHOD(COMGETTER(Port))(USHORT *aPort);
209 STDMETHOD(COMGETTER(Version))(USHORT *aVersion);
210 STDMETHOD(COMGETTER(PortVersion))(USHORT *aPortVersion);
211 STDMETHOD(COMGETTER(Remote))(BOOL *aRemote);
212
213 // IHostUSBDevice properties
214 STDMETHOD(COMGETTER(State))(USBDeviceState_T *aState);
215
216 /** Additional internal states.
217 * The async detach stuff for Darwin is a two stage journey with a variation
218 * (filters) depending on who won the race to lock the Host object.
219 *
220 * @remark Trying out mac os x style enum naming convention here. nice or what?
221 */
222 typedef enum
223 {
224 /** Nothing is pending here, check mPendingState. */
225 kNothingPending,
226 /** 1st stage of the detch, waiting for the logical detach notification. */
227 kDetachingPendingDetach,
228 /** 1st stage of the detch, waiting for the logical detach notification - re-run filters.
229 * Prev: kDetachingPendingDetach */
230 kDetachingPendingDetachFilters,
231 /** 2nd stage of the detach, waiting for the logical attach notification.
232 * Prev: kDetachingPendingDetach */
233 kDetachingPendingAttach,
234 /** 2nd stage of the detach, waiting for the logical attach notification - re-run filters.
235 * Prev: kDetachingPendingDetachFilters */
236 kDetachingPendingAttachFilters
237 } InternalState;
238
239 // public methods only for internal purposes
240
241 /** @note Must be called from under the object read lock. */
242 const Guid &id() const { return mId; }
243
244 /** @note Must be called from under the object read lock. */
245 USBDeviceState_T state() const { return mState; }
246
247 /** @note Must be called from under the object read lock. */
248 USBDeviceState_T pendingState() const { return mPendingState; }
249
250 /** @note Must be called from under the object read lock. */
251 InternalState pendingStateEx() const { return mPendingStateEx; }
252
253 /** @note Must be called from under the object read lock. */
254 ComObjPtr <SessionMachine> &machine() { return mMachine; }
255
256 /** @note Must be called from under the object read lock. */
257 bool isStatePending() const { return mIsStatePending; }
258
259 /** @note Must be called from under the object read lock. */
260 PCUSBDEVICE usbData() const { return mUsb; }
261
262 Utf8Str name();
263
264 bool requestCapture (SessionMachine *aMachine, ULONG aMaskedIfs = 0);
265 void requestRelease();
266 void requestHold();
267
268 void setHeld();
269 void onDetachedPhys();
270
271 void handlePendingStateChange();
272 void cancelPendingState(bool aTimeout = false);
273
274 bool isMatch (const USBDeviceFilter::Data &aData);
275
276 int compare (PCUSBDEVICE aDev2);
277 static int compare (PCUSBDEVICE aDev1, PCUSBDEVICE aDev2,
278 bool aIsStrict = true);
279
280 bool updateState (PCUSBDEVICE aDev);
281
282 void checkForAsyncTimeout();
283
284 bool setLogicalReconnect (InternalState aStage);
285
286 // for VirtualBoxSupportErrorInfoImpl
287 static const wchar_t *getComponentName() { return L"HostUSBDevice"; }
288
289private:
290
291 const Guid mId;
292 USBDeviceState_T mState;
293 USBDeviceState_T mPendingState;
294 /** Same as mPendingState but for the internal states. */
295 InternalState mPendingStateEx;
296 /** RTTimeNanoTS() of when mIsStatePending was set or mDetaching changed
297 * from kNotDetaching. For operations that cannot be cancelled it's 0. */
298 uint64_t mPendingSince;
299 ComObjPtr <SessionMachine> mMachine;
300 bool mIsStatePending : 1;
301
302 /** Pointer to the USB Proxy Service instance. */
303 USBProxyService *mUSBProxyService;
304
305 /** Pointer to the USB Device structure owned by this device.
306 * Only used for host devices. */
307 PUSBDEVICE mUsb;
308
309 /** The interface mask to be use in the pending capture. */
310 ULONG mMaskedIfs;
311
312 friend class USBProxyService;
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};
323
324
325COM_DECL_READONLY_ENUM_AND_COLLECTION_BEGIN (HostUSBDevice)
326
327 STDMETHOD(FindById) (INPTR GUIDPARAM aId, IHostUSBDevice **aDevice)
328 {
329 Guid idToFind = aId;
330 if (idToFind.isEmpty())
331 return E_INVALIDARG;
332 if (!aDevice)
333 return E_POINTER;
334
335 *aDevice = NULL;
336 Vector::value_type found;
337 Vector::iterator it = vec.begin();
338 while (!found && it != vec.end())
339 {
340 Guid id;
341 (*it)->COMGETTER(Id) (id.asOutParam());
342 if (id == idToFind)
343 found = *it;
344 ++ it;
345 }
346
347 if (!found)
348 return setError (E_INVALIDARG, HostUSBDeviceCollection::tr (
349 "Could not find a USB device with UUID {%s}"),
350 idToFind.toString().raw());
351
352 return found.queryInterfaceTo (aDevice);
353 }
354
355 STDMETHOD(FindByAddress) (INPTR BSTR aAddress, IHostUSBDevice **aDevice)
356 {
357 if (!aAddress)
358 return E_INVALIDARG;
359 if (!aDevice)
360 return E_POINTER;
361
362 *aDevice = NULL;
363 Vector::value_type found;
364 Vector::iterator it = vec.begin();
365 while (!found && it != vec.end())
366 {
367 Bstr address;
368 (*it)->COMGETTER(Address) (address.asOutParam());
369 if (address == aAddress)
370 found = *it;
371 ++ it;
372 }
373
374 if (!found)
375 return setError (E_INVALIDARG, HostUSBDeviceCollection::tr (
376 "Could not find a USB device with address '%ls'"),
377 aAddress);
378
379 return found.queryInterfaceTo (aDevice);
380 }
381
382COM_DECL_READONLY_ENUM_AND_COLLECTION_END (HostUSBDevice)
383
384
385#endif // ____H_HOSTUSBDEVICEIMPL
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