VirtualBox

source: vbox/trunk/src/VBox/Main/HostUSBDeviceImpl.cpp@ 31891

Last change on this file since 31891 was 31891, checked in by vboxsync, 15 years ago

Main: export USBProxyService and USBFilter to OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 91.0 KB
Line 
1/* $Id: HostUSBDeviceImpl.cpp 31891 2010-08-24 07:58:48Z vboxsync $ */
2/** @file
3 * VirtualBox IHostUSBDevice COM interface implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * Oracle Corporation confidential
10 * All rights reserved
11 */
12
13#include <iprt/types.h> /* for UINT64_C */
14
15#include "HostUSBDeviceImpl.h"
16#include "MachineImpl.h"
17#include "HostImpl.h"
18#include "VirtualBoxErrorInfoImpl.h"
19#include "USBProxyService.h"
20
21#include "AutoCaller.h"
22#include "Logging.h"
23
24#include <VBox/err.h>
25#include <iprt/cpp/utils.h>
26
27// constructor / destructor
28/////////////////////////////////////////////////////////////////////////////
29
30DEFINE_EMPTY_CTOR_DTOR (HostUSBDevice)
31
32HRESULT HostUSBDevice::FinalConstruct()
33{
34 mUSBProxyService = NULL;
35 mUsb = NULL;
36
37 return S_OK;
38}
39
40void HostUSBDevice::FinalRelease()
41{
42 uninit();
43}
44
45// public initializer/uninitializer for internal purposes only
46/////////////////////////////////////////////////////////////////////////////
47
48/**
49 * Initializes the USB device object.
50 *
51 * @returns COM result indicator
52 * @param aUsb Pointer to the usb device structure for which the object is to be a wrapper.
53 * This structure is now fully owned by the HostUSBDevice object and will be
54 * freed when it is destructed.
55 * @param aUSBProxyService Pointer to the USB Proxy Service object.
56 */
57HRESULT HostUSBDevice::init(PUSBDEVICE aUsb, USBProxyService *aUSBProxyService)
58{
59 ComAssertRet(aUsb, E_INVALIDARG);
60
61 /* Enclose the state transition NotReady->InInit->Ready */
62 AutoInitSpan autoInitSpan(this);
63 AssertReturn(autoInitSpan.isOk(), E_FAIL);
64
65 /*
66 * We need a unique ID for this VBoxSVC session.
67 * The UUID isn't stored anywhere.
68 */
69 unconst(mId).create();
70
71 /*
72 * Set the initial device state.
73 */
74 AssertMsgReturn( aUsb->enmState >= USBDEVICESTATE_UNSUPPORTED
75 && aUsb->enmState < USBDEVICESTATE_USED_BY_GUEST, /* used-by-guest is not a legal initial state. */
76 ("%d\n", aUsb->enmState), E_FAIL);
77 mUniState = (HostUSBDeviceState)aUsb->enmState;
78 mUniSubState = kHostUSBDeviceSubState_Default;
79 mPendingUniState = kHostUSBDeviceState_Invalid;
80 mPrevUniState = mUniState;
81 mIsPhysicallyDetached = false;
82
83 /* Other data members */
84 mUSBProxyService = aUSBProxyService;
85 mUsb = aUsb;
86
87 /* Set the name. */
88 mNameObj = getName();
89 mName = mNameObj.c_str();
90
91 /* Confirm the successful initialization */
92 autoInitSpan.setSucceeded();
93
94 return S_OK;
95}
96
97/**
98 * Uninitializes the instance and sets the ready flag to FALSE.
99 * Called either from FinalRelease() or by the parent when it gets destroyed.
100 */
101void HostUSBDevice::uninit()
102{
103 /* Enclose the state transition Ready->InUninit->NotReady */
104 AutoUninitSpan autoUninitSpan(this);
105 if (autoUninitSpan.uninitDone())
106 return;
107
108 if (mUsb != NULL)
109 {
110 USBProxyService::freeDevice (mUsb);
111 mUsb = NULL;
112 }
113
114 mUSBProxyService = NULL;
115 mUniState = kHostUSBDeviceState_Invalid;
116}
117
118// IUSBDevice properties
119/////////////////////////////////////////////////////////////////////////////
120
121STDMETHODIMP HostUSBDevice::COMGETTER(Id)(BSTR *aId)
122{
123 CheckComArgOutPointerValid(aId);
124
125 AutoCaller autoCaller(this);
126 if (FAILED(autoCaller.rc())) return autoCaller.rc();
127
128 /* mId is constant during life time, no need to lock */
129 mId.toUtf16().cloneTo(aId);
130
131 return S_OK;
132}
133
134STDMETHODIMP HostUSBDevice::COMGETTER(VendorId)(USHORT *aVendorId)
135{
136 CheckComArgOutPointerValid(aVendorId);
137
138 AutoCaller autoCaller(this);
139 if (FAILED(autoCaller.rc())) return autoCaller.rc();
140
141 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
142
143 *aVendorId = mUsb->idVendor;
144
145 return S_OK;
146}
147
148STDMETHODIMP HostUSBDevice::COMGETTER(ProductId)(USHORT *aProductId)
149{
150 CheckComArgOutPointerValid(aProductId);
151
152 AutoCaller autoCaller(this);
153 if (FAILED(autoCaller.rc())) return autoCaller.rc();
154
155 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
156
157 *aProductId = mUsb->idProduct;
158
159 return S_OK;
160}
161
162STDMETHODIMP HostUSBDevice::COMGETTER(Revision)(USHORT *aRevision)
163{
164 CheckComArgOutPointerValid(aRevision);
165
166 AutoCaller autoCaller(this);
167 if (FAILED(autoCaller.rc())) return autoCaller.rc();
168
169 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
170
171 *aRevision = mUsb->bcdDevice;
172
173 return S_OK;
174}
175
176STDMETHODIMP HostUSBDevice::COMGETTER(Manufacturer)(BSTR *aManufacturer)
177{
178 CheckComArgOutPointerValid(aManufacturer);
179
180 AutoCaller autoCaller(this);
181 if (FAILED(autoCaller.rc())) return autoCaller.rc();
182
183 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
184
185 Bstr (mUsb->pszManufacturer).cloneTo(aManufacturer);
186
187 return S_OK;
188}
189
190STDMETHODIMP HostUSBDevice::COMGETTER(Product)(BSTR *aProduct)
191{
192 CheckComArgOutPointerValid(aProduct);
193
194 AutoCaller autoCaller(this);
195 if (FAILED(autoCaller.rc())) return autoCaller.rc();
196
197 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
198
199 Bstr (mUsb->pszProduct).cloneTo(aProduct);
200
201 return S_OK;
202}
203
204STDMETHODIMP HostUSBDevice::COMGETTER(SerialNumber)(BSTR *aSerialNumber)
205{
206 CheckComArgOutPointerValid(aSerialNumber);
207
208 AutoCaller autoCaller(this);
209 if (FAILED(autoCaller.rc())) return autoCaller.rc();
210
211 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
212
213 Bstr (mUsb->pszSerialNumber).cloneTo(aSerialNumber);
214
215 return S_OK;
216}
217
218STDMETHODIMP HostUSBDevice::COMGETTER(Address)(BSTR *aAddress)
219{
220 CheckComArgOutPointerValid(aAddress);
221
222 AutoCaller autoCaller(this);
223 if (FAILED(autoCaller.rc())) return autoCaller.rc();
224
225 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
226
227 Bstr (mUsb->pszAddress).cloneTo(aAddress);
228
229 return S_OK;
230}
231
232STDMETHODIMP HostUSBDevice::COMGETTER(Port)(USHORT *aPort)
233{
234 CheckComArgOutPointerValid(aPort);
235
236 AutoCaller autoCaller(this);
237 if (FAILED(autoCaller.rc())) return autoCaller.rc();
238
239 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
240
241#if !defined(RT_OS_WINDOWS) /// @todo check up the bPort value on Windows before enabling this.
242 *aPort = mUsb->bPort;
243#else
244 *aPort = 0;
245#endif
246
247 return S_OK;
248}
249
250STDMETHODIMP HostUSBDevice::COMGETTER(Version)(USHORT *aVersion)
251{
252 CheckComArgOutPointerValid(aVersion);
253
254 AutoCaller autoCaller(this);
255 if (FAILED(autoCaller.rc())) return autoCaller.rc();
256
257 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
258
259 *aVersion = mUsb->bcdUSB >> 8;
260
261 return S_OK;
262}
263
264STDMETHODIMP HostUSBDevice::COMGETTER(PortVersion)(USHORT *aPortVersion)
265{
266 CheckComArgOutPointerValid(aPortVersion);
267
268 AutoCaller autoCaller(this);
269 if (FAILED(autoCaller.rc())) return autoCaller.rc();
270
271 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
272
273 /* Port version is 2 (EHCI) if and only if the device runs at high speed;
274 * if speed is unknown, fall back to the old and innacurate method.
275 */
276 if (mUsb->enmSpeed == USBDEVICESPEED_UNKNOWN)
277 *aPortVersion = mUsb->bcdUSB >> 8;
278 else
279 *aPortVersion = (mUsb->enmSpeed == USBDEVICESPEED_HIGH) ? 2 : 1;
280
281 return S_OK;
282}
283
284STDMETHODIMP HostUSBDevice::COMGETTER(Remote)(BOOL *aRemote)
285{
286 CheckComArgOutPointerValid(aRemote);
287
288 AutoCaller autoCaller(this);
289 if (FAILED(autoCaller.rc())) return autoCaller.rc();
290
291 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
292
293 *aRemote = FALSE;
294
295 return S_OK;
296}
297
298// IHostUSBDevice properties
299/////////////////////////////////////////////////////////////////////////////
300
301STDMETHODIMP HostUSBDevice::COMGETTER(State) (USBDeviceState_T *aState)
302{
303 CheckComArgOutPointerValid(aState);
304
305 AutoCaller autoCaller(this);
306 if (FAILED(autoCaller.rc())) return autoCaller.rc();
307
308 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
309
310 *aState = canonicalState();
311
312 return S_OK;
313}
314
315
316// public methods only for internal purposes
317////////////////////////////////////////////////////////////////////////////////
318
319/**
320 * @note Locks this object for reading.
321 */
322Utf8Str HostUSBDevice::getName()
323{
324 Utf8Str name;
325
326 AutoCaller autoCaller(this);
327 AssertComRCReturn (autoCaller.rc(), name);
328
329 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
330
331 bool haveManufacturer = mUsb->pszManufacturer && *mUsb->pszManufacturer;
332 bool haveProduct = mUsb->pszProduct && *mUsb->pszProduct;
333 if (haveManufacturer && haveProduct)
334 name = Utf8StrFmt ("%s %s", mUsb->pszManufacturer, mUsb->pszProduct);
335 else if (haveManufacturer)
336 name = Utf8StrFmt ("%s", mUsb->pszManufacturer);
337 else if (haveProduct)
338 name = Utf8StrFmt ("%s", mUsb->pszProduct);
339 else
340 name = "<unknown>";
341
342 return name;
343}
344
345/**
346 * Requests the USB proxy service capture the device (from the host)
347 * and attach it to a VM.
348 *
349 * As a convenience, this method will operate like attachToVM() if the device
350 * is already held by the proxy. Note that it will then perform IPC to the VM
351 * process, which means it will temporarily leave all locks. (Is this a good idea?)
352 *
353 * @param aMachine Machine this device should be attach to.
354 * @param aSetError Whether to set full error message or not to bother.
355 * @param aMaskedIfs The interfaces to hide from the guest.
356 *
357 * @returns Status indicating whether it was successfully captured and/or attached.
358 * @retval S_OK on success.
359 * @retval E_UNEXPECTED if the device state doesn't permit for any attaching.
360 * @retval E_* as appropriate.
361 *
362 * @note Must be called from under the object write lock.
363 * @note May lock the given machine object for reading.
364 */
365HRESULT HostUSBDevice::requestCaptureForVM(SessionMachine *aMachine, bool aSetError, ULONG aMaskedIfs /* = 0*/)
366{
367 LogFlowThisFunc(("{%s} aMachine=%p aMaskedIfs=%#x\n", mName, aMachine, aMaskedIfs));
368
369 /*
370 * Validate preconditions and input.
371 */
372 AssertReturn(aMachine, E_INVALIDARG);
373 AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
374 if (aSetError)
375 {
376 if (mUniState == kHostUSBDeviceState_Unsupported)
377 return setError(E_INVALIDARG,
378 tr("USB device '%s' with UUID {%RTuuid} cannot be accessed by guest computers"),
379 mName, mId.raw());
380 if (mUniState == kHostUSBDeviceState_UsedByHost)
381 return setError(E_INVALIDARG,
382 tr("USB device '%s' with UUID {%RTuuid} is being exclusively used by the host computer"),
383 mName, mId.raw());
384 if (mUniState == kHostUSBDeviceState_UsedByVM)
385 {
386 /* Machine::name() requires a read lock */
387 AutoReadLock machLock(mMachine COMMA_LOCKVAL_SRC_POS);
388 return setError(E_INVALIDARG,
389 tr("USB device '%s' with UUID {%RTuuid} is already captured by the virtual machine '%ls'"),
390 mName, mId.raw(), mMachine->getName().c_str());
391 }
392 if (mUniState >= kHostUSBDeviceState_FirstTransitional)
393 return setError(E_INVALIDARG,
394 tr("USB device '%s' with UUID {%RTuuid} is busy with a previous request. Please try again later"),
395 mName, mId.raw());
396 if ( mUniState != kHostUSBDeviceState_Unused
397 && mUniState != kHostUSBDeviceState_HeldByProxy
398 && mUniState != kHostUSBDeviceState_Capturable)
399 return setError(E_INVALIDARG,
400 tr("USB device '%s' with UUID {%RTuuid} is not in the right state for capturing (%s)"),
401 mName, mId.raw(), getStateName());
402 }
403
404 AssertReturn( mUniState == kHostUSBDeviceState_HeldByProxy
405 || mUniState == kHostUSBDeviceState_Unused
406 || mUniState == kHostUSBDeviceState_Capturable,
407 E_UNEXPECTED);
408 Assert(mMachine.isNull());
409
410 /*
411 * If it's already held by the proxy, we'll simply call
412 * attachToVM synchronously.
413 */
414 if (mUniState == kHostUSBDeviceState_HeldByProxy)
415 {
416 HRESULT hrc = attachToVM(aMachine, aMaskedIfs);
417 return SUCCEEDED(hrc);
418 }
419
420 /*
421 * Need to capture the device before it can be used.
422 *
423 * The device will be attached to the VM by the USB proxy service thread
424 * when the request succeeds (i.e. asynchronously).
425 */
426 LogFlowThisFunc(("{%s} capturing the device.\n", mName));
427#if (defined(RT_OS_DARWIN) && defined(VBOX_WITH_NEW_USB_CODE_ON_DARWIN)) /* PORTME */ \
428 || defined(RT_OS_WINDOWS) || defined(RT_OS_SOLARIS)
429 setState(kHostUSBDeviceState_Capturing, kHostUSBDeviceState_UsedByVM, kHostUSBDeviceSubState_AwaitingDetach);
430#else
431 setState(kHostUSBDeviceState_Capturing, kHostUSBDeviceState_UsedByVM);
432#endif
433 mMachine = aMachine;
434 mMaskedIfs = aMaskedIfs;
435 int rc = mUSBProxyService->captureDevice(this);
436 if (RT_FAILURE(rc))
437 {
438 failTransition();
439 mMachine.setNull();
440 if (rc == VERR_SHARING_VIOLATION)
441 return setError(E_FAIL,
442 tr("USB device '%s' with UUID {%RTuuid} is in use by someone else"),
443 mName, mId.raw());
444 return E_FAIL;
445 }
446
447 return S_OK;
448}
449
450/**
451 * Attempts to attach the USB device to a VM.
452 *
453 * The device must be in the HeldByProxy state or about to exit the
454 * Capturing state.
455 *
456 * This method will make an IPC to the VM process and do the actual
457 * attaching. While in the IPC locks will be abandond.
458 *
459 * @returns Status indicating whether it was successfully attached or not.
460 * @retval S_OK on success.
461 * @retval E_UNEXPECTED if the device state doesn't permit for any attaching.
462 * @retval E_* as appropriate.
463 *
464 * @param aMachine Machine this device should be attach to.
465 * @param aMaskedIfs The interfaces to hide from the guest.
466 */
467HRESULT HostUSBDevice::attachToVM(SessionMachine *aMachine, ULONG aMaskedIfs /* = 0*/)
468{
469 /*
470 * Validate and update the state.
471 */
472 AssertReturn( mUniState == kHostUSBDeviceState_Capturing
473 || mUniState == kHostUSBDeviceState_HeldByProxy
474 || mUniState == kHostUSBDeviceState_AttachingToVM,
475 E_UNEXPECTED);
476 setState(kHostUSBDeviceState_AttachingToVM, kHostUSBDeviceState_UsedByVM);
477
478 /*
479 * The VM process will query the object, so grab a refernce to ourselves and leave the locks.
480 */
481 ComPtr<IUSBDevice> d = this;
482
483 AutoWriteLock alockSelf(this COMMA_LOCKVAL_SRC_POS);
484 alockSelf.leave();
485 AutoWriteLock alockProxy(mUSBProxyService COMMA_LOCKVAL_SRC_POS);
486 alockProxy.leave();
487
488 /*
489 * Call the VM process (IPC) and request it to attach the device.
490 *
491 * There are many reasonas for this to fail, so, as a consequence we don't
492 * assert the return code as it will crash the daemon and annoy the heck
493 * out of people.
494 */
495 LogFlowThisFunc(("{%s} Calling machine->onUSBDeviceAttach()...\n", mName));
496 HRESULT hrc = aMachine->onUSBDeviceAttach (d, NULL, aMaskedIfs);
497 LogFlowThisFunc(("{%s} Done machine->onUSBDeviceAttach()=%08X\n", mName, hrc));
498
499 /*
500 * As we re-enter the lock, we'll have to check if the device was
501 * physically detached while we were busy.
502 */
503 alockProxy.enter();
504 alockSelf.enter();
505
506 if (SUCCEEDED(hrc))
507 {
508 mMachine = aMachine;
509 if (!mIsPhysicallyDetached)
510 setState(kHostUSBDeviceState_UsedByVM);
511 else
512 {
513 detachFromVM(kHostUSBDeviceState_PhysDetached);
514 hrc = E_UNEXPECTED;
515 }
516 }
517 else
518 {
519 mMachine.setNull();
520 if (!mIsPhysicallyDetached)
521 {
522 setState(kHostUSBDeviceState_HeldByProxy);
523 if (hrc == E_UNEXPECTED)
524 hrc = E_FAIL; /* No confusion. */
525 }
526 else
527 {
528 onPhysicalDetachedInternal();
529 hrc = E_UNEXPECTED;
530 }
531 }
532 return hrc;
533}
534
535
536/**
537 * Detaches the device from the VM.
538 *
539 * This is used for a special scenario in attachToVM() and from
540 * onPhysicalDetachedInternal().
541 *
542 * @param aFinalState The final state (PhysDetached).
543 */
544void HostUSBDevice::detachFromVM(HostUSBDeviceState aFinalState)
545{
546 NOREF(aFinalState);
547
548 /*
549 * Assert preconditions.
550 */
551 Assert(aFinalState == kHostUSBDeviceState_PhysDetached);
552 Assert( mUniState == kHostUSBDeviceState_AttachingToVM
553 || mUniState == kHostUSBDeviceState_UsedByVM);
554 Assert(!mMachine.isNull());
555
556 /*
557 * Change the state and abandond the locks. The VM may query
558 * data and we don't want to deadlock - the state protects us,
559 * so, it's not a bit issue here.
560 */
561 setState(kHostUSBDeviceState_PhysDetachingFromVM, kHostUSBDeviceState_PhysDetached);
562 AutoWriteLock alockSelf(this COMMA_LOCKVAL_SRC_POS);
563 alockSelf.leave();
564 AutoWriteLock alockProxy(mUSBProxyService COMMA_LOCKVAL_SRC_POS);
565 alockProxy.leave();
566
567 /*
568 * Call the VM process (IPC) and request it to detach the device.
569 *
570 * There are many reasonas for this to fail, so, as a consequence we don't
571 * assert the return code as it will crash the daemon and annoy the heck
572 * out of people.
573 */
574 LogFlowThisFunc(("{%s} Calling machine->onUSBDeviceDetach()...\n", mName));
575 HRESULT hrc = mMachine->onUSBDeviceDetach(mId.toUtf16(), NULL);
576 LogFlowThisFunc(("{%s} Done machine->onUSBDeviceDetach()=%Rhrc\n", mName, hrc));
577 NOREF(hrc);
578
579 /*
580 * Re-enter the locks and complete the transition.
581 */
582 alockProxy.enter();
583 alockSelf.enter();
584 advanceTransition();
585}
586
587/**
588 * Called when the VM process to inform us about the device being
589 * detached from it.
590 *
591 * This is NOT called when we detach the device via onUSBDeviceDetach.
592 *
593 *
594 * @param[in] aMachine The machine making the request.
595 * This must be the machine this device is currently attached to.
596 * @param[in] aDone When set to false, the VM just informs us that it's about
597 * to detach this device but hasn't done it just yet.
598 * When set to true, the VM informs us that it has completed
599 * the detaching of this device.
600 * @param[out] aRunFilters Whether to run filters.
601 * @param[in] aAbnormal Set if we're cleaning up after a crashed VM.
602 *
603 * @returns S_OK on success, and E_UNEXPECTED if the device isn't in the right state.
604 *
605 * @note Must be called from under the object write lock.
606 */
607HRESULT HostUSBDevice::onDetachFromVM(SessionMachine *aMachine, bool aDone, bool *aRunFilters, bool aAbnormal /*= true*/)
608{
609 LogFlowThisFunc(("{%s} state=%s aDone=%RTbool aAbnormal=%RTbool\n", mName, getStateName(), aDone, aAbnormal));
610
611 /*
612 * Validate preconditions.
613 */
614 AssertPtrReturn(aRunFilters, E_INVALIDARG);
615 AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
616 if (!aDone)
617 {
618 if (mUniState != kHostUSBDeviceState_UsedByVM)
619 return setError(E_INVALIDARG,
620 tr("USB device '%s' with UUID {%RTuuid} is busy (state '%s'). Please try again later"),
621 mName, mId.raw(), getStateName());
622 }
623 else
624 AssertMsgReturn( mUniState == kHostUSBDeviceState_DetachingFromVM /** @todo capturing for VM ends up here on termination. */
625 || (mUniState == kHostUSBDeviceState_UsedByVM && aAbnormal),
626 ("{%s} %s\n", mName, getStateName()), E_UNEXPECTED);
627 AssertMsgReturn((mMachine == aMachine), ("%p != %p\n", (void *)mMachine, aMachine), E_FAIL);
628
629 /*
630 * Change the state.
631 */
632 if (!aDone)
633 {
634 *aRunFilters = startTransition(kHostUSBDeviceState_DetachingFromVM, kHostUSBDeviceState_HeldByProxy);
635 /* PORTME: This might require host specific changes if you re-enumerate the device. */
636 }
637 else if (aAbnormal && mUniState == kHostUSBDeviceState_UsedByVM)
638 {
639 /* Fast forward thru the DetachingFromVM state and on to HeldByProxy. */
640 /** @todo need to update the state machine to handle crashed VMs. */
641 startTransition(kHostUSBDeviceState_DetachingFromVM, kHostUSBDeviceState_HeldByProxy);
642 *aRunFilters = advanceTransition();
643 mMachine.setNull();
644 /* PORTME: ditto / trouble if you depend on the VM process to do anything. */
645 }
646 else
647 {
648 /* normal completion. */
649 Assert(mUniSubState == kHostUSBDeviceSubState_Default); /* PORTME: ditto */
650 *aRunFilters = advanceTransition();
651 mMachine.setNull();
652 }
653
654 return S_OK;
655}
656
657/**
658 * Requests the USB proxy service to release the device back to the host.
659 *
660 * This method will ignore (not assert) calls for devices that already
661 * belong to the host because it simplifies the usage a bit.
662 *
663 * @returns COM status code.
664 * @retval S_OK on success.
665 * @retval E_UNEXPECTED on bad state.
666 * @retval E_* as appropriate.
667 *
668 * @note Must be called from under the object write lock.
669 */
670HRESULT HostUSBDevice::requestReleaseToHost()
671{
672 LogFlowThisFunc(("{%s}\n", mName));
673
674 /*
675 * Validate preconditions.
676 */
677 AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
678 Assert(mMachine.isNull());
679 if ( mUniState == kHostUSBDeviceState_Unused
680 || mUniState == kHostUSBDeviceState_Capturable)
681 return S_OK;
682 AssertMsgReturn(mUniState == kHostUSBDeviceState_HeldByProxy, ("{%s} %s\n", mName, getStateName()), E_UNEXPECTED);
683
684 /*
685 * Try release it.
686 */
687#if (defined(RT_OS_DARWIN) && defined(VBOX_WITH_NEW_USB_CODE_ON_DARWIN)) /* PORTME */ \
688 || defined(RT_OS_WINDOWS)
689 startTransition(kHostUSBDeviceState_ReleasingToHost, kHostUSBDeviceState_Unused, kHostUSBDeviceSubState_AwaitingDetach);
690#else
691 startTransition(kHostUSBDeviceState_ReleasingToHost, kHostUSBDeviceState_Unused);
692#endif
693 int rc = mUSBProxyService->releaseDevice(this);
694 if (RT_FAILURE(rc))
695 {
696 failTransition();
697 return E_FAIL;
698 }
699 return S_OK;
700}
701
702/**
703 * Requests the USB proxy service to capture and hold the device.
704 *
705 * The device must be owned by the host at the time of the call. But for
706 * the callers convenience, calling this method on a device that is already
707 * being held will success without any assertions.
708 *
709 * @returns COM status code.
710 * @retval S_OK on success.
711 * @retval E_UNEXPECTED on bad state.
712 * @retval E_* as appropriate.
713 *
714 * @note Must be called from under the object write lock.
715 */
716HRESULT HostUSBDevice::requestHold()
717{
718 LogFlowThisFunc(("{%s}\n", mName));
719
720 /*
721 * Validate preconditions.
722 */
723 AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
724 AssertMsgReturn( mUniState == kHostUSBDeviceState_Unused
725 || mUniState == kHostUSBDeviceState_Capturable
726 || mUniState == kHostUSBDeviceState_HeldByProxy,
727 ("{%s} %s\n", mName, getStateName()),
728 E_UNEXPECTED);
729
730 Assert(mMachine.isNull());
731 mMachine.setNull();
732
733 if (mUniState == kHostUSBDeviceState_HeldByProxy)
734 return S_OK;
735
736 /*
737 * Do the job.
738 */
739#if (defined(RT_OS_DARWIN) && defined(VBOX_WITH_NEW_USB_CODE_ON_DARWIN)) /* PORTME */ \
740 || defined(RT_OS_WINDOWS)
741 startTransition(kHostUSBDeviceState_Capturing, kHostUSBDeviceState_HeldByProxy, kHostUSBDeviceSubState_AwaitingDetach);
742#else
743 startTransition(kHostUSBDeviceState_Capturing, kHostUSBDeviceState_HeldByProxy);
744#endif
745 int rc = mUSBProxyService->captureDevice(this);
746 if (RT_FAILURE(rc))
747 {
748 failTransition();
749 return E_FAIL;
750 }
751 return S_OK;
752}
753
754
755/**
756 * Check a detach detected by the USB Proxy Service to see if
757 * it's a real one or just a logical following a re-enumeration.
758 *
759 * This will work the internal sub state of the device and do time
760 * outs, so it does more than just querying data!
761 *
762 * @returns true if it was actually detached, false if it's just a re-enumeration.
763 */
764bool HostUSBDevice::wasActuallyDetached()
765{
766 /*
767 * This only applies to the detach and re-attach states.
768 */
769 switch (mUniState)
770 {
771 case kHostUSBDeviceState_Capturing:
772 case kHostUSBDeviceState_ReleasingToHost:
773 case kHostUSBDeviceState_AttachingToVM:
774 case kHostUSBDeviceState_DetachingFromVM:
775 switch (mUniSubState)
776 {
777 /*
778 * If we're awaiting a detach, the this has now occurred
779 * and the state should be advanced.
780 */
781 case kHostUSBDeviceSubState_AwaitingDetach:
782 advanceTransition();
783 return false; /* not physically detached. */
784
785 /*
786 * Check for timeouts.
787 */
788 case kHostUSBDeviceSubState_AwaitingReAttach:
789 {
790#ifndef RT_OS_WINDOWS /* check the implementation details here. */
791 uint64_t elapsedNanoseconds = RTTimeNanoTS() - mLastStateChangeTS;
792 if (elapsedNanoseconds > UINT64_C (60000000000) ) /* 60 seconds */
793 {
794 LogRel (("USB: Async operation timed out for device %s (state: %s)\n", mName, getStateName()));
795 failTransition();
796 }
797#endif
798 return false; /* not physically detached. */
799 }
800
801 /* not applicable.*/
802 case kHostUSBDeviceSubState_Default:
803 break;
804 }
805 break;
806
807 /* not applicable. */
808 case kHostUSBDeviceState_Unsupported:
809 case kHostUSBDeviceState_UsedByHost:
810 case kHostUSBDeviceState_Capturable:
811 case kHostUSBDeviceState_Unused:
812 case kHostUSBDeviceState_HeldByProxy:
813 case kHostUSBDeviceState_UsedByVM:
814 case kHostUSBDeviceState_PhysDetachingFromVM:
815 case kHostUSBDeviceState_PhysDetached:
816 break;
817
818 default:
819 AssertLogRelMsgFailed (("this=%p %s\n", this, getStateName()));
820 break;
821 }
822
823 /* It was detached. */
824 return true;
825}
826
827/**
828 * Notification from the USB Proxy that the device was physically detached.
829 *
830 * If a transition is pending, mIsPhysicallyDetached will be set and
831 * handled when the transition advances forward.
832 *
833 * Otherwsie the device will be detached from any VM currently using it - this
834 * involves IPC and will temporarily abandond locks - and all the device data
835 * reset.
836 *
837 * @note Must be called from under the object write lock.
838 */
839void HostUSBDevice::onPhysicalDetached()
840{
841 LogFlowThisFunc(("{%s}\n", mName));
842 AssertReturnVoid(isWriteLockOnCurrentThread());
843
844 mIsPhysicallyDetached = true;
845 if (mUniState < kHostUSBDeviceState_FirstTransitional)
846 onPhysicalDetachedInternal();
847}
848
849
850/**
851 * Do the physical detach work for a device in a stable state or
852 * at a transition state change.
853 *
854 * See onPhysicalDetach() for details.
855 *
856 * @note Must be called from under the object write lock.
857 */
858void HostUSBDevice::onPhysicalDetachedInternal()
859{
860 LogFlowThisFunc(("{%s}\n", mName));
861 AssertReturnVoid(isWriteLockOnCurrentThread());
862 Assert(mIsPhysicallyDetached);
863
864 /*
865 * Do we need to detach it from the VM first?
866 */
867 if ( !mMachine.isNull()
868 && ( mUniState == kHostUSBDeviceState_UsedByVM
869 || mUniState == kHostUSBDeviceState_AttachingToVM))
870 detachFromVM(kHostUSBDeviceState_PhysDetached);
871 else
872 AssertMsg(mMachine.isNull(), ("%s\n", getStateName()));
873
874 /*
875 * Reset the data and enter the final state.
876 */
877 mMachine.setNull();
878 setState(kHostUSBDeviceState_PhysDetached);
879}
880
881
882/**
883 * Returns true if this device matches the given filter data.
884 *
885 * @note It is assumed, that the filter data owner is appropriately
886 * locked before calling this method.
887 *
888 * @note
889 * This method MUST correlate with
890 * USBController::hasMatchingFilter (IUSBDevice *)
891 * in the sense of the device matching logic.
892 *
893 * @note Locks this object for reading.
894 */
895bool HostUSBDevice::isMatch(const USBDeviceFilter::Data &aData)
896{
897 AutoCaller autoCaller(this);
898 AssertComRCReturn(autoCaller.rc(), false);
899
900 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
901
902 if (!aData.mActive)
903 return false;
904
905 if (!aData.mRemote.isMatch(FALSE))
906 return false;
907
908 if (!USBFilterMatchDevice(&aData.mUSBFilter, mUsb))
909 return false;
910
911 /* Don't match busy devices with a 100% wildcard filter - this will
912 later become a filter prop (ring-3 only). */
913 if ( mUsb->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE
914 && !USBFilterHasAnySubstatialCriteria(&aData.mUSBFilter))
915 return false;
916
917 LogFlowThisFunc(("returns true\n"));
918 return true;
919}
920
921/**
922 * Compares this device with a USBDEVICE and decides if the match or which comes first.
923 *
924 * This will take into account device re-attaching and omit the bits
925 * that may change during a device re-enumeration.
926 *
927 * @param aDev2 Device 2.
928 *
929 * @returns < 0 if this should come before aDev2.
930 * @returns 0 if this and aDev2 are equal.
931 * @returns > 0 if this should come after aDev2.
932 *
933 * @note Must be called from under the object write lock.
934 */
935int HostUSBDevice::compare(PCUSBDEVICE aDev2)
936{
937 AssertReturn(isWriteLockOnCurrentThread(), -1);
938 //Log3(("%Rfn: %p {%s}\n", __PRETTY_FUNCTION__, this, mName));
939 return compare(mUsb, aDev2,
940 mUniSubState == kHostUSBDeviceSubState_AwaitingDetach /* (In case we don't get the detach notice.) */
941 || mUniSubState == kHostUSBDeviceSubState_AwaitingReAttach);
942}
943
944/**
945 * Compares two USBDEVICE structures and decides if the match or which comes first.
946 *
947 * @param aDev1 Device 1.
948 * @param aDev2 Device 2.
949 * @param aIsAwaitingReAttach Whether to omit bits that will change in a device
950 * re-enumeration (true) or not (false).
951 *
952 * @returns < 0 if aDev1 should come before aDev2.
953 * @returns 0 if aDev1 and aDev2 are equal.
954 * @returns > 0 if aDev1 should come after aDev2.
955 */
956/*static*/
957int HostUSBDevice::compare(PCUSBDEVICE aDev1, PCUSBDEVICE aDev2, bool aIsAwaitingReAttach /*= false */)
958{
959 /*
960 * Things that stays the same everywhere.
961 *
962 * The more uniquely these properties identifies a device the less the chance
963 * that we mix similar devices during re-enumeration. Bus+port would help
964 * provide ~99.8% accuracy if the host can provide those attributes.
965 */
966 int iDiff = aDev1->idVendor - aDev2->idVendor;
967 if (iDiff)
968 return iDiff;
969
970 iDiff = aDev1->idProduct - aDev2->idProduct;
971 if (iDiff)
972 return iDiff;
973
974 iDiff = aDev1->bcdDevice - aDev2->bcdDevice;
975 if (iDiff)
976 {
977 //Log3(("compare: bcdDevice: %#x != %#x\n", aDev1->bcdDevice, aDev2->bcdDevice));
978 return iDiff;
979 }
980
981#ifdef RT_OS_WINDOWS /* the string query may fail on windows during replugging, ignore serial mismatch if this is the case. */
982 if ( aDev1->u64SerialHash != aDev2->u64SerialHash
983 && ( !aIsAwaitingReAttach
984 || (aDev2->pszSerialNumber && *aDev2->pszSerialNumber)
985 || (aDev2->pszManufacturer && *aDev2->pszManufacturer)
986 || (aDev2->pszProduct && *aDev2->pszProduct))
987 )
988#else
989 if (aDev1->u64SerialHash != aDev2->u64SerialHash)
990#endif
991 {
992 //Log3(("compare: u64SerialHash: %#llx != %#llx\n", aDev1->u64SerialHash, aDev2->u64SerialHash));
993 return aDev1->u64SerialHash < aDev2->u64SerialHash ? -1 : 1;
994 }
995
996 /* The hub/bus + port should help a lot in a re-attach situation. */
997#ifdef RT_OS_WINDOWS
998 iDiff = strcmp(aDev1->pszHubName, aDev2->pszHubName);
999 if (iDiff)
1000 {
1001 //Log3(("compare: HubName: %s != %s\n", aDev1->pszHubName, aDev2->pszHubName));
1002 return iDiff;
1003 }
1004#else
1005 iDiff = aDev1->bBus - aDev2->bBus;
1006 if (iDiff)
1007 {
1008 //Log3(("compare: bBus: %#x != %#x\n", aDev1->bBus, aDev2->bBus));
1009 return iDiff;
1010 }
1011#endif
1012
1013 iDiff = aDev1->bPort - aDev2->bPort; /* shouldn't change anywhere and help pinpoint it very accurately. */
1014 if (iDiff)
1015 {
1016 //Log3(("compare: bPort: %#x != %#x\n", aDev1->bPort, aDev2->bPort));
1017 return iDiff;
1018 }
1019
1020 /*
1021 * Things that usually doesn't stay the same when re-enumerating
1022 * a device. The fewer things in the category the better chance
1023 * that we avoid messing up when more than one device of the same
1024 * kind is attached.
1025 */
1026 if (aIsAwaitingReAttach)
1027 {
1028 //Log3(("aDev1=%p == aDev2=%p\n", aDev1, aDev2));
1029 return 0;
1030 }
1031 /* device number always changes. */
1032 return strcmp(aDev1->pszAddress, aDev2->pszAddress);
1033}
1034
1035/**
1036 * Updates the state of the device.
1037 *
1038 * If this method returns @c true, Host::onUSBDeviceStateChanged() will be
1039 * called to process the state change (complete the state change request,
1040 * inform the VM process etc.).
1041 *
1042 * If this method returns @c false, it is assumed that the given state change
1043 * is "minor": it doesn't require any further action other than update the
1044 * mState field with the actual state value.
1045 *
1046 * Regardless of the return value, this method always takes ownership of the
1047 * new USBDEVICE structure passed in and updates the pNext and pPrev fiends in
1048 * it using the values of the old structure.
1049 *
1050 * @param[in] aDev The current device state as seen by the proxy backend.
1051 * @param[out] aRunFilters Whether the state change should be accompanied by
1052 * running filters on the device.
1053 * @param[out] aIgnoreMachine Machine to ignore when running filters.
1054 *
1055 * @returns Whether the Host object should be bothered with this state change.
1056 *
1057 * @note Locks this object for writing.
1058 *
1059 * @todo Just do everything here, that is, call filter runners and everything that
1060 * works by state change. Using 3 return codes/parameters is just plain ugly.
1061 */
1062bool HostUSBDevice::updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMachine **aIgnoreMachine)
1063{
1064 *aRunFilters = false;
1065 *aIgnoreMachine = NULL;
1066
1067 /*
1068 * Locking.
1069 */
1070 AssertReturn(isWriteLockOnCurrentThread(), false);
1071 AutoCaller autoCaller(this);
1072 AssertComRCReturn(autoCaller.rc(), false);
1073 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1074
1075
1076 /*
1077 * Replace the existing structure by the new one.
1078 */
1079 const USBDEVICESTATE enmOldState = mUsb->enmState; NOREF(enmOldState);
1080 if (mUsb != aDev)
1081 {
1082 aDev->pNext = mUsb->pNext;
1083 aDev->pPrev = mUsb->pPrev;
1084 USBProxyService::freeDevice (mUsb);
1085 mUsb = aDev;
1086 }
1087
1088/** @def HOSTUSBDEVICE_FUZZY_STATE
1089 * Defined on hosts where we have a driver that keeps proper device states.
1090 */
1091# if defined(RT_OS_LINUX) || defined(DOXYGEN_RUNNING)
1092# define HOSTUSBDEVICE_FUZZY_STATE 1
1093# else
1094# undef HOSTUSBDEVICE_FUZZY_STATE
1095# endif
1096 /*
1097 * For some hosts we'll have to be pretty carefule here because
1098 * they don't always have a clue what is going on. This is
1099 * particularly true on linux and solaris, while windows and
1100 * darwin generally knows a bit more.
1101 */
1102 bool fIsImportant = false;
1103 if (enmOldState != mUsb->enmState)
1104 {
1105 LogFlowThisFunc(("%p {%s} %s\n", this, mName, getStateName()));
1106 switch (mUsb->enmState)
1107 {
1108 /*
1109 * Little fuzzyness here, except where we fake capture.
1110 */
1111 case USBDEVICESTATE_USED_BY_HOST:
1112 switch (mUniState)
1113 {
1114 /* Host drivers installed, that's fine. */
1115 case kHostUSBDeviceState_Capturable:
1116 case kHostUSBDeviceState_Unused:
1117 LogThisFunc(("{%s} %s -> %s\n", mName, getStateName(), stateName(kHostUSBDeviceState_UsedByHost)));
1118 *aRunFilters = setState(kHostUSBDeviceState_UsedByHost);
1119 break;
1120 case kHostUSBDeviceState_UsedByHost:
1121 break;
1122
1123 /* Can only mean that we've failed capturing it. */
1124 case kHostUSBDeviceState_Capturing:
1125 LogThisFunc(("{%s} capture failed!\n", mName));
1126 mUSBProxyService->captureDeviceCompleted(this, false /* aSuccess */);
1127 *aRunFilters = failTransition();
1128 mMachine.setNull();
1129 break;
1130
1131 /* Guess we've successfully released it. */
1132 case kHostUSBDeviceState_ReleasingToHost:
1133 LogThisFunc(("{%s} %s -> %s\n", mName, getStateName(), stateName(kHostUSBDeviceState_UsedByHost)));
1134 mUSBProxyService->releaseDeviceCompleted(this, true /* aSuccess */);
1135 *aRunFilters = setState(kHostUSBDeviceState_UsedByHost);
1136 break;
1137
1138 /* These are IPC states and should be left alone. */
1139 case kHostUSBDeviceState_AttachingToVM:
1140 case kHostUSBDeviceState_DetachingFromVM:
1141 case kHostUSBDeviceState_PhysDetachingFromVM:
1142 LogThisFunc(("{%s} %s - changed to USED_BY_HOST...\n", mName, getStateName()));
1143 break;
1144
1145#ifdef HOSTUSBDEVICE_FUZZY_STATE
1146 /* Fake: We can't prevent anyone from grabbing it. */
1147 case kHostUSBDeviceState_HeldByProxy:
1148 LogThisFunc(("{%s} %s -> %s!\n", mName, getStateName(), stateName(kHostUSBDeviceState_UsedByHost)));
1149 *aRunFilters = setState(kHostUSBDeviceState_UsedByHost);
1150 break;
1151 //case kHostUSBDeviceState_UsedByVM:
1152 // /** @todo needs to be detached from the VM. */
1153 // break;
1154#endif
1155 /* Not supposed to happen... */
1156#ifndef HOSTUSBDEVICE_FUZZY_STATE
1157 case kHostUSBDeviceState_HeldByProxy:
1158#endif
1159 case kHostUSBDeviceState_UsedByVM:
1160 case kHostUSBDeviceState_PhysDetached:
1161 case kHostUSBDeviceState_Unsupported:
1162 default:
1163 AssertMsgFailed(("{%s} %s\n", mName, getStateName()));
1164 break;
1165 }
1166 break;
1167
1168 /*
1169 * It changed to capturable. Fuzzy hosts might easily
1170 * confuse UsedByVM with this one.
1171 */
1172 case USBDEVICESTATE_USED_BY_HOST_CAPTURABLE:
1173 switch (mUniState)
1174 {
1175 /* No change. */
1176#ifdef HOSTUSBDEVICE_FUZZY_STATE
1177 case kHostUSBDeviceState_HeldByProxy:
1178 case kHostUSBDeviceState_UsedByVM:
1179#endif
1180 case kHostUSBDeviceState_Capturable:
1181 break;
1182
1183 /* Changed! */
1184 case kHostUSBDeviceState_UsedByHost:
1185 fIsImportant = true;
1186 case kHostUSBDeviceState_Unused:
1187 LogThisFunc(("{%s} %s -> %s\n", mName, getStateName(), stateName(kHostUSBDeviceState_Capturable)));
1188 *aRunFilters = setState(kHostUSBDeviceState_Capturable);
1189 break;
1190
1191 /* Can only mean that we've failed capturing it. */
1192 case kHostUSBDeviceState_Capturing:
1193 LogThisFunc(("{%s} capture failed!\n", mName));
1194 mUSBProxyService->captureDeviceCompleted(this, false /* aSuccess */);
1195 *aRunFilters = failTransition();
1196 mMachine.setNull();
1197 break;
1198
1199 /* Guess we've successfully released it. */
1200 case kHostUSBDeviceState_ReleasingToHost:
1201 LogThisFunc(("{%s} %s -> %s\n", mName, getStateName(), stateName(kHostUSBDeviceState_Capturable)));
1202 mUSBProxyService->releaseDeviceCompleted(this, true /* aSuccess */);
1203 *aRunFilters = setState(kHostUSBDeviceState_Capturable);
1204 break;
1205
1206 /* These are IPC states and should be left alone. */
1207 case kHostUSBDeviceState_AttachingToVM:
1208 case kHostUSBDeviceState_DetachingFromVM:
1209 case kHostUSBDeviceState_PhysDetachingFromVM:
1210 LogThisFunc(("{%s} %s - changed to USED_BY_HOST_CAPTURABLE...\n", mName, getStateName()));
1211 break;
1212
1213 /* Not supposed to happen*/
1214#ifndef HOSTUSBDEVICE_FUZZY_STATE
1215 case kHostUSBDeviceState_HeldByProxy:
1216 case kHostUSBDeviceState_UsedByVM:
1217#endif
1218 case kHostUSBDeviceState_Unsupported:
1219 case kHostUSBDeviceState_PhysDetached:
1220 default:
1221 AssertMsgFailed(("{%s} %s\n", mName, getStateName()));
1222 break;
1223 }
1224 break;
1225
1226
1227 /*
1228 * It changed to capturable. Fuzzy hosts might easily
1229 * confuse UsedByVM and HeldByProxy with this one.
1230 */
1231 case USBDEVICESTATE_UNUSED:
1232 switch (mUniState)
1233 {
1234 /* No change. */
1235#ifdef HOSTUSBDEVICE_FUZZY_STATE
1236 case kHostUSBDeviceState_HeldByProxy:
1237 case kHostUSBDeviceState_UsedByVM:
1238#endif
1239 case kHostUSBDeviceState_Unused:
1240 break;
1241
1242 /* Changed! */
1243 case kHostUSBDeviceState_UsedByHost:
1244 case kHostUSBDeviceState_Capturable:
1245 fIsImportant = true;
1246 LogThisFunc(("{%s} %s -> %s\n", mName, getStateName(), stateName(kHostUSBDeviceState_Unused)));
1247 *aRunFilters = setState(kHostUSBDeviceState_Unused);
1248 break;
1249
1250 /* Can mean that we've failed capturing it, but on windows it is the detach signal. */
1251 case kHostUSBDeviceState_Capturing:
1252#if defined(RT_OS_WINDOWS)
1253 if (mUniSubState == kHostUSBDeviceSubState_AwaitingDetach)
1254 {
1255 LogThisFunc(("{%s} capture advancing thru UNUSED...\n", mName));
1256 *aRunFilters = advanceTransition();
1257 }
1258 else
1259#endif
1260 {
1261 LogThisFunc(("{%s} capture failed!\n", mName));
1262 mUSBProxyService->captureDeviceCompleted(this, false /* aSuccess */);
1263 *aRunFilters = failTransition();
1264 mMachine.setNull();
1265 }
1266 break;
1267
1268 /* Guess we've successfully released it. */
1269 case kHostUSBDeviceState_ReleasingToHost:
1270 LogThisFunc(("{%s} %s -> %s\n", mName, getStateName(), stateName(kHostUSBDeviceState_Unused)));
1271 mUSBProxyService->releaseDeviceCompleted(this, true /* aSuccess */);
1272 *aRunFilters = setState(kHostUSBDeviceState_Unused);
1273 break;
1274
1275 /* These are IPC states and should be left alone. */
1276 case kHostUSBDeviceState_AttachingToVM:
1277 case kHostUSBDeviceState_DetachingFromVM:
1278 case kHostUSBDeviceState_PhysDetachingFromVM:
1279 LogThisFunc(("{%s} %s - changed to UNUSED...\n", mName, getStateName()));
1280 break;
1281
1282 /* Not supposed to happen*/
1283#ifndef HOSTUSBDEVICE_FUZZY_STATE
1284 case kHostUSBDeviceState_HeldByProxy:
1285 case kHostUSBDeviceState_UsedByVM:
1286#endif
1287 case kHostUSBDeviceState_Unsupported:
1288 case kHostUSBDeviceState_PhysDetached:
1289 default:
1290 AssertMsgFailed(("{%s} %s\n", mName, getStateName()));
1291 break;
1292 }
1293 break;
1294
1295 /*
1296 * This is pretty straight forward, except that everyone
1297 * might sometimes confuse this and the UsedByVM state.
1298 */
1299 case USBDEVICESTATE_HELD_BY_PROXY:
1300 switch (mUniState)
1301 {
1302 /* No change. */
1303 case kHostUSBDeviceState_HeldByProxy:
1304 break;
1305 case kHostUSBDeviceState_UsedByVM:
1306 LogThisFunc(("{%s} %s - changed to HELD_BY_PROXY...\n", mName, getStateName()));
1307 break;
1308
1309 /* Guess we've successfully captured it. */
1310 case kHostUSBDeviceState_Capturing:
1311 LogThisFunc(("{%s} capture succeeded!\n", mName));
1312 mUSBProxyService->captureDeviceCompleted(this, true /* aSuccess */);
1313 *aRunFilters = advanceTransition(true /* fast forward thru re-attach */);
1314
1315 /* Take action if we're supposed to attach it to a VM. */
1316 if (mUniState == kHostUSBDeviceState_AttachingToVM)
1317 attachToVM(mMachine, mMaskedIfs);
1318 break;
1319
1320 /* Can only mean that we've failed capturing it. */
1321 case kHostUSBDeviceState_ReleasingToHost:
1322 LogThisFunc(("{%s} %s failed!\n", mName, getStateName()));
1323 mUSBProxyService->releaseDeviceCompleted(this, false /* aSuccess */);
1324 *aRunFilters = setState(kHostUSBDeviceState_HeldByProxy);
1325 break;
1326
1327 /* These are IPC states and should be left alone. */
1328 case kHostUSBDeviceState_AttachingToVM:
1329 case kHostUSBDeviceState_DetachingFromVM:
1330 case kHostUSBDeviceState_PhysDetachingFromVM:
1331 LogThisFunc(("{%s} %s - changed to HELD_BY_PROXY...\n", mName, getStateName()));
1332 break;
1333
1334 /* Not supposed to happen. */
1335 case kHostUSBDeviceState_Unsupported:
1336 case kHostUSBDeviceState_UsedByHost:
1337 case kHostUSBDeviceState_Capturable:
1338 case kHostUSBDeviceState_Unused:
1339 case kHostUSBDeviceState_PhysDetached:
1340 default:
1341 AssertMsgFailed(("{%s} %s\n", mName, getStateName()));
1342 break;
1343 }
1344 break;
1345
1346 /*
1347 * This is very straight forward and only Darwin implements it.
1348 */
1349 case USBDEVICESTATE_USED_BY_GUEST:
1350 switch (mUniState)
1351 {
1352 /* No change. */
1353 case kHostUSBDeviceState_HeldByProxy:
1354 LogThisFunc(("{%s} %s - changed to USED_BY_GUEST...\n", mName, getStateName()));
1355 break;
1356 case kHostUSBDeviceState_UsedByVM:
1357 break;
1358
1359 /* These are IPC states and should be left alone. */
1360 case kHostUSBDeviceState_AttachingToVM:
1361 case kHostUSBDeviceState_DetachingFromVM:
1362 case kHostUSBDeviceState_PhysDetachingFromVM:
1363 LogThisFunc(("{%s} %s - changed to USED_BY_GUEST...\n", mName, getStateName()));
1364 break;
1365
1366 /* Not supposed to happen. */
1367 case kHostUSBDeviceState_Unsupported:
1368 case kHostUSBDeviceState_Capturable:
1369 case kHostUSBDeviceState_Unused:
1370 case kHostUSBDeviceState_UsedByHost:
1371 case kHostUSBDeviceState_PhysDetached:
1372 case kHostUSBDeviceState_ReleasingToHost:
1373 case kHostUSBDeviceState_Capturing:
1374 default:
1375 AssertMsgFailed(("{%s} %s\n", mName, getStateName()));
1376 break;
1377 }
1378 break;
1379
1380 /*
1381 * This is not supposed to happen and indicates a bug in the backend!
1382 */
1383 case USBDEVICESTATE_UNSUPPORTED:
1384 AssertMsgFailed(("enmOldState=%d {%s} %s\n", enmOldState, mName, getStateName()));
1385 break;
1386 default:
1387 AssertMsgFailed(("enmState=%d {%s} %s\n", mUsb->enmState, mName, getStateName()));
1388 break;
1389 }
1390 }
1391 else if ( mUniSubState == kHostUSBDeviceSubState_AwaitingDetach
1392 && hasAsyncOperationTimedOut())
1393 {
1394 LogRel(("USB: timeout in %s for {%RTuuid} / {%s}\n",
1395 getStateName(), mId.raw(), mName));
1396 *aRunFilters = failTransition();
1397 fIsImportant = true;
1398 }
1399 else
1400 {
1401 LogFlowThisFunc(("%p {%s} %s - no change %d\n", this, mName, getStateName(), enmOldState));
1402 /** @todo might have to handle some stuff here too if we cannot make the release/capture handling deal with that above ... */
1403 }
1404
1405 return fIsImportant;
1406
1407}
1408
1409
1410/**
1411 * Updates the state of the device, checking for cases which we fake.
1412 *
1413 * See HostUSBDevice::updateState() for details.
1414 *
1415 * @param[in] aDev See HostUSBDevice::updateState().
1416 * @param[out] aRunFilters See HostUSBDevice::updateState()
1417 * @param[out] aIgnoreMachine See HostUSBDevice::updateState()
1418 *
1419 * @returns See HostUSBDevice::updateState()
1420 *
1421 * @note Caller must write lock the object.
1422 */
1423bool HostUSBDevice::updateStateFake(PCUSBDEVICE aDev, bool *aRunFilters, SessionMachine **aIgnoreMachine)
1424{
1425 const HostUSBDeviceState enmState = mUniState;
1426 switch (enmState)
1427 {
1428 case kHostUSBDeviceState_Capturing:
1429 case kHostUSBDeviceState_ReleasingToHost:
1430 {
1431 Assert(isWriteLockOnCurrentThread());
1432
1433 *aIgnoreMachine = mUniState == kHostUSBDeviceState_ReleasingToHost ? mMachine : NULL;
1434 *aRunFilters = advanceTransition();
1435 LogThisFunc(("{%s} %s\n", mName, getStateName()));
1436
1437 if (mUsb != aDev)
1438 {
1439 aDev->pNext = mUsb->pNext;
1440 aDev->pPrev = mUsb->pPrev;
1441 USBProxyService::freeDevice(mUsb);
1442 mUsb = aDev;
1443 }
1444
1445 /* call the completion method */
1446 if (enmState == kHostUSBDeviceState_Capturing)
1447 mUSBProxyService->captureDeviceCompleted(this, true /* aSuccess */);
1448 else
1449 mUSBProxyService->releaseDeviceCompleted(this, true /* aSuccess */);
1450
1451 /* Take action if we're supposed to attach it to a VM. */
1452 if (mUniState == kHostUSBDeviceState_AttachingToVM)
1453 attachToVM(mMachine, mMaskedIfs);
1454 return true;
1455 }
1456
1457 default:
1458 return updateState(aDev, aRunFilters, aIgnoreMachine);
1459 }
1460}
1461
1462
1463/**
1464 * Checks if there is a pending asynchronous operation and whether
1465 * it has timed out or not.
1466 *
1467 * @returns true on timeout, false if not.
1468 *
1469 * @note Caller must have read or write locked the object before calling.
1470 */
1471bool HostUSBDevice::hasAsyncOperationTimedOut() const
1472{
1473 switch (mUniSubState)
1474 {
1475#ifndef RT_OS_WINDOWS /* no timeouts on windows yet since I don't have all the details here... */
1476 case kHostUSBDeviceSubState_AwaitingDetach:
1477 case kHostUSBDeviceSubState_AwaitingReAttach:
1478 {
1479 uint64_t elapsedNanoseconds = RTTimeNanoTS() - mLastStateChangeTS;
1480 return elapsedNanoseconds > UINT64_C(60000000000); /* 60 seconds */ /* PORTME */
1481 }
1482#endif
1483 default:
1484 return false;
1485 }
1486}
1487
1488
1489/**
1490 * Translate the state into
1491 *
1492 * @returns
1493 * @param aState
1494 * @param aSubState
1495 * @param aPendingState
1496 */
1497/*static*/ const char *HostUSBDevice::stateName(HostUSBDeviceState aState,
1498 HostUSBDeviceState aPendingState /*= kHostUSBDeviceState_Invalid*/,
1499 HostUSBDeviceSubState aSubState /*= kHostUSBDeviceSubState_Default*/)
1500{
1501 switch (aState)
1502 {
1503 case kHostUSBDeviceState_Unsupported:
1504 AssertReturn(aPendingState == kHostUSBDeviceState_Invalid, "Unsupported{bad}");
1505 AssertReturn(aSubState == kHostUSBDeviceSubState_Default, "Unsupported[bad]");
1506 return "Unsupported";
1507
1508 case kHostUSBDeviceState_UsedByHost:
1509 AssertReturn(aPendingState == kHostUSBDeviceState_Invalid, "UsedByHost{bad}");
1510 AssertReturn(aSubState == kHostUSBDeviceSubState_Default, "UsedByHost[bad]");
1511 return "UsedByHost";
1512
1513 case kHostUSBDeviceState_Capturable:
1514 AssertReturn(aPendingState == kHostUSBDeviceState_Invalid, "Capturable{bad}");
1515 AssertReturn(aSubState == kHostUSBDeviceSubState_Default, "Capturable[bad]");
1516 return "Capturable";
1517
1518 case kHostUSBDeviceState_Unused:
1519 AssertReturn(aPendingState == kHostUSBDeviceState_Invalid, "Unused{bad}");
1520 AssertReturn(aSubState == kHostUSBDeviceSubState_Default, "Unused[bad]");
1521 return "Unused";
1522
1523 case kHostUSBDeviceState_HeldByProxy:
1524 AssertReturn(aPendingState == kHostUSBDeviceState_Invalid, "HeldByProxy{bad}");
1525 AssertReturn(aSubState == kHostUSBDeviceSubState_Default, "HeldByProxy[bad]");
1526 return "HeldByProxy";
1527
1528 case kHostUSBDeviceState_UsedByVM:
1529 AssertReturn(aPendingState == kHostUSBDeviceState_Invalid, "UsedByVM{bad}");
1530 AssertReturn(aSubState == kHostUSBDeviceSubState_Default, "UsedByVM[bad]");
1531 return "UsedByVM";
1532
1533 case kHostUSBDeviceState_PhysDetached:
1534 AssertReturn(aPendingState == kHostUSBDeviceState_Invalid, "PhysDetached{bad}");
1535 AssertReturn(aSubState == kHostUSBDeviceSubState_Default, "PhysDetached[bad]");
1536 return "PhysDetached";
1537
1538 case kHostUSBDeviceState_Capturing:
1539 switch (aPendingState)
1540 {
1541 case kHostUSBDeviceState_UsedByVM:
1542 switch (aSubState)
1543 {
1544 case kHostUSBDeviceSubState_Default:
1545 return "CapturingForVM";
1546 case kHostUSBDeviceSubState_AwaitingDetach:
1547 return "CapturingForVM[Detach]";
1548 case kHostUSBDeviceSubState_AwaitingReAttach:
1549 return "CapturingForVM[Attach]";
1550 default:
1551 AssertFailedReturn("CapturingForVM[bad]");
1552 }
1553 break;
1554
1555 case kHostUSBDeviceState_HeldByProxy:
1556 switch (aSubState)
1557 {
1558 case kHostUSBDeviceSubState_Default:
1559 return "CapturingForProxy";
1560 case kHostUSBDeviceSubState_AwaitingDetach:
1561 return "CapturingForProxy[Detach]";
1562 case kHostUSBDeviceSubState_AwaitingReAttach:
1563 return "CapturingForProxy[Attach]";
1564 default:
1565 AssertFailedReturn("CapturingForProxy[bad]");
1566 }
1567 break;
1568
1569 default:
1570 AssertFailedReturn("Capturing{bad}");
1571 }
1572 break;
1573
1574 case kHostUSBDeviceState_ReleasingToHost:
1575 switch (aPendingState)
1576 {
1577 case kHostUSBDeviceState_Unused:
1578 switch (aSubState)
1579 {
1580 case kHostUSBDeviceSubState_Default:
1581 return "ReleasingToHost";
1582 case kHostUSBDeviceSubState_AwaitingDetach:
1583 return "ReleasingToHost[Detach]";
1584 case kHostUSBDeviceSubState_AwaitingReAttach:
1585 return "ReleasingToHost[Attach]";
1586 default:
1587 AssertFailedReturn("ReleasingToHost[bad]");
1588 }
1589 break;
1590 default:
1591 AssertFailedReturn("ReleasingToHost{bad}");
1592 }
1593 break;
1594
1595 case kHostUSBDeviceState_DetachingFromVM:
1596 switch (aPendingState)
1597 {
1598 case kHostUSBDeviceState_HeldByProxy:
1599 switch (aSubState)
1600 {
1601 case kHostUSBDeviceSubState_Default:
1602 return "DetatchingFromVM>Proxy";
1603 case kHostUSBDeviceSubState_AwaitingDetach:
1604 return "DetatchingFromVM>Proxy[Detach]";
1605 case kHostUSBDeviceSubState_AwaitingReAttach:
1606 return "DetatchingFromVM>Proxy[Attach]";
1607 default:
1608 AssertFailedReturn("DetatchingFromVM>Proxy[bad]");
1609 }
1610 break;
1611
1612 case kHostUSBDeviceState_Unused:
1613 switch (aSubState)
1614 {
1615 case kHostUSBDeviceSubState_Default:
1616 return "DetachingFromVM>Host";
1617 case kHostUSBDeviceSubState_AwaitingDetach:
1618 return "DetachingFromVM>Host[Detach]";
1619 case kHostUSBDeviceSubState_AwaitingReAttach:
1620 return "DetachingFromVM>Host[Attach]";
1621 default:
1622 AssertFailedReturn("DetachingFromVM>Host[bad]");
1623 }
1624 break;
1625
1626 default:
1627 AssertFailedReturn("DetachingFromVM{bad}");
1628 }
1629 break;
1630
1631 case kHostUSBDeviceState_AttachingToVM:
1632 switch (aPendingState)
1633 {
1634 case kHostUSBDeviceState_UsedByVM:
1635 switch (aSubState)
1636 {
1637 case kHostUSBDeviceSubState_Default:
1638 return "AttachingToVM";
1639 case kHostUSBDeviceSubState_AwaitingDetach:
1640 return "AttachingToVM[Detach]";
1641 case kHostUSBDeviceSubState_AwaitingReAttach:
1642 return "AttachingToVM[Attach]";
1643 default:
1644 AssertFailedReturn("AttachingToVM[bad]");
1645 }
1646 break;
1647
1648 default:
1649 AssertFailedReturn("AttachingToVM{bad}");
1650 }
1651 break;
1652
1653
1654 case kHostUSBDeviceState_PhysDetachingFromVM:
1655 switch (aPendingState)
1656 {
1657 case kHostUSBDeviceState_PhysDetached:
1658 switch (aSubState)
1659 {
1660 case kHostUSBDeviceSubState_Default:
1661 return "PhysDetachingFromVM";
1662 default:
1663 AssertFailedReturn("AttachingToVM[bad]");
1664 }
1665 break;
1666
1667 default:
1668 AssertFailedReturn("AttachingToVM{bad}");
1669 }
1670 break;
1671
1672 default:
1673 AssertFailedReturn("BadState");
1674
1675 }
1676
1677 AssertFailedReturn("shouldn't get here");
1678}
1679
1680/**
1681 * Set the device state.
1682 *
1683 * This method will verify that the state transition is a legal one
1684 * according to the statemachine. It will also take care of the
1685 * associated house keeping and determin if filters needs to be applied.
1686 *
1687 * @param aNewState The new state.
1688 * @param aNewPendingState The final state of a transition when applicable.
1689 * @param aNewSubState The new sub-state when applicable.
1690 *
1691 * @returns true if filters should be applied to the device, false if not.
1692 *
1693 * @note The caller must own the write lock for this object.
1694 */
1695bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aNewPendingState /*= kHostUSBDeviceState_Invalid*/,
1696 HostUSBDeviceSubState aNewSubState /*= kHostUSBDeviceSubState_Default*/)
1697{
1698 Assert(isWriteLockOnCurrentThread());
1699 Assert( aNewSubState == kHostUSBDeviceSubState_Default
1700 || aNewSubState == kHostUSBDeviceSubState_AwaitingDetach
1701 || aNewSubState == kHostUSBDeviceSubState_AwaitingReAttach);
1702
1703 /*
1704 * If the state is unchanged, then don't bother going
1705 * thru the validation and setting. This saves a bit of code.
1706 */
1707 if ( aNewState == mUniState
1708 && aNewPendingState == mPendingUniState
1709 && aNewSubState == mUniSubState)
1710 return false;
1711
1712 /*
1713 * Welcome to the switch orgies!
1714 * You're welcome to check out the ones in startTransition(),
1715 * advanceTransition(), failTransition() and getStateName() too. Enjoy!
1716 */
1717
1718 bool fFilters = false;
1719 HostUSBDeviceState NewPrevState = mUniState;
1720 switch (mUniState)
1721 {
1722 /*
1723 * Not much can be done with a device in this state.
1724 */
1725 case kHostUSBDeviceState_Unsupported:
1726 switch (aNewState)
1727 {
1728 case kHostUSBDeviceState_PhysDetached:
1729 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1730 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1731 break;
1732 default:
1733 AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
1734 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1735 }
1736 break;
1737
1738 /*
1739 * Only the host OS (or the user) can make changes
1740 * that'll make a device get out of this state.
1741 */
1742 case kHostUSBDeviceState_UsedByHost:
1743 switch (aNewState)
1744 {
1745 case kHostUSBDeviceState_Capturable:
1746 case kHostUSBDeviceState_Unused:
1747 fFilters = true;
1748 case kHostUSBDeviceState_PhysDetached:
1749 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1750 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1751 break;
1752 default:
1753 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1754 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1755 }
1756 break;
1757
1758 /*
1759 * Now it gets interesting.
1760 */
1761 case kHostUSBDeviceState_Capturable:
1762 switch (aNewState)
1763 {
1764 /* Host changes. */
1765 case kHostUSBDeviceState_Unused:
1766 fFilters = true; /* Wildcard only... */
1767 case kHostUSBDeviceState_UsedByHost:
1768 case kHostUSBDeviceState_PhysDetached:
1769 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1770 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1771 break;
1772
1773 /* VBox actions */
1774 case kHostUSBDeviceState_Capturing:
1775 switch (aNewPendingState)
1776 {
1777 case kHostUSBDeviceState_HeldByProxy:
1778 case kHostUSBDeviceState_UsedByVM:
1779 break;
1780 default:
1781 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1782 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1783 }
1784 break;
1785 default:
1786 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1787 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1788 }
1789 break;
1790
1791 case kHostUSBDeviceState_Unused:
1792 switch (aNewState)
1793 {
1794 /* Host changes. */
1795 case kHostUSBDeviceState_PhysDetached:
1796 case kHostUSBDeviceState_UsedByHost:
1797 case kHostUSBDeviceState_Capturable:
1798 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1799 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1800 break;
1801
1802 /* VBox actions */
1803 case kHostUSBDeviceState_Capturing:
1804 switch (aNewPendingState)
1805 {
1806 case kHostUSBDeviceState_HeldByProxy:
1807 case kHostUSBDeviceState_UsedByVM:
1808 break;
1809 default:
1810 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1811 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1812 }
1813 break;
1814 default:
1815 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1816 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1817 }
1818 break;
1819
1820 /*
1821 * VBox owns this device now, what's next...
1822 */
1823 case kHostUSBDeviceState_HeldByProxy:
1824 switch (aNewState)
1825 {
1826 /* Host changes. */
1827 case kHostUSBDeviceState_PhysDetached:
1828 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1829 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1830 break;
1831
1832 /* VBox actions */
1833 case kHostUSBDeviceState_AttachingToVM:
1834 switch (aNewPendingState)
1835 {
1836 case kHostUSBDeviceState_UsedByVM:
1837 break;
1838 default:
1839 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1840 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1841 }
1842 break;
1843 case kHostUSBDeviceState_ReleasingToHost:
1844 switch (aNewPendingState)
1845 {
1846 case kHostUSBDeviceState_Unused: /* Only this! */
1847 break;
1848 default:
1849 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1850 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1851 }
1852 break;
1853 default:
1854 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1855 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1856 }
1857 break;
1858
1859
1860 case kHostUSBDeviceState_UsedByVM:
1861 switch (aNewState)
1862 {
1863 /* Host changes. */
1864 case kHostUSBDeviceState_PhysDetachingFromVM:
1865 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1866 Assert(aNewPendingState == kHostUSBDeviceState_PhysDetached);
1867 break;
1868
1869 /* VBox actions */
1870 case kHostUSBDeviceState_DetachingFromVM:
1871 switch (aNewPendingState)
1872 {
1873 case kHostUSBDeviceState_HeldByProxy:
1874 case kHostUSBDeviceState_Unused: /* Only this! */
1875 break;
1876 default:
1877 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1878 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1879 }
1880 break;
1881 default:
1882 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1883 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1884 }
1885 break;
1886
1887 /*
1888 * The final state.
1889 */
1890 case kHostUSBDeviceState_PhysDetached:
1891 switch (mUniState)
1892 {
1893 case kHostUSBDeviceState_Unsupported:
1894 case kHostUSBDeviceState_UsedByHost:
1895 case kHostUSBDeviceState_Capturable:
1896 case kHostUSBDeviceState_Unused:
1897 case kHostUSBDeviceState_HeldByProxy:
1898 case kHostUSBDeviceState_PhysDetachingFromVM:
1899 case kHostUSBDeviceState_DetachingFromVM: // ??
1900 case kHostUSBDeviceState_Capturing:
1901 case kHostUSBDeviceState_ReleasingToHost:
1902 break;
1903
1904 case kHostUSBDeviceState_AttachingToVM: // ??
1905 case kHostUSBDeviceState_UsedByVM:
1906 default:
1907 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1908 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1909 }
1910 break;
1911
1912
1913 /*
1914 * The transitional states.
1915 */
1916 case kHostUSBDeviceState_Capturing:
1917 NewPrevState = mPrevUniState;
1918 switch (aNewState)
1919 {
1920 /* Sub state advance. */
1921 case kHostUSBDeviceState_Capturing:
1922 switch (aNewSubState)
1923 {
1924 case kHostUSBDeviceSubState_AwaitingReAttach:
1925 Assert(mUniSubState == kHostUSBDeviceSubState_AwaitingDetach);
1926 Assert(aNewPendingState == mPendingUniState);
1927 break;
1928 default:
1929 AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
1930 }
1931 break;
1932
1933 /* Host/User/Failure. */
1934 case kHostUSBDeviceState_PhysDetached:
1935 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1936 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1937 break;
1938 case kHostUSBDeviceState_UsedByHost:
1939 case kHostUSBDeviceState_Capturable:
1940 case kHostUSBDeviceState_Unused:
1941 Assert(aNewState == mPrevUniState);
1942 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1943 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1944 break;
1945
1946 /* VBox */
1947 case kHostUSBDeviceState_HeldByProxy:
1948 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1949 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1950 Assert( mPendingUniState == kHostUSBDeviceState_HeldByProxy
1951 || mPendingUniState == kHostUSBDeviceState_UsedByVM /* <- failure */ );
1952 break;
1953 case kHostUSBDeviceState_AttachingToVM:
1954 Assert(aNewPendingState == kHostUSBDeviceState_UsedByVM);
1955 NewPrevState = kHostUSBDeviceState_HeldByProxy;
1956 break;
1957
1958 default:
1959 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
1960 stateName(aNewState, aNewPendingState, aNewSubState)), false);
1961 }
1962 break;
1963
1964 case kHostUSBDeviceState_ReleasingToHost:
1965 Assert(mPrevUniState == kHostUSBDeviceState_HeldByProxy);
1966 NewPrevState = mPrevUniState;
1967 switch (aNewState)
1968 {
1969 /* Sub state advance. */
1970 case kHostUSBDeviceState_ReleasingToHost:
1971 switch (aNewSubState)
1972 {
1973 case kHostUSBDeviceSubState_AwaitingReAttach:
1974 Assert(mUniSubState == kHostUSBDeviceSubState_AwaitingDetach);
1975 Assert(aNewPendingState == mPendingUniState);
1976 break;
1977 default:
1978 AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
1979 }
1980 break;
1981
1982 /* Host/Failure. */
1983 case kHostUSBDeviceState_PhysDetached:
1984 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1985 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1986 break;
1987 case kHostUSBDeviceState_HeldByProxy:
1988 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1989 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1990 Assert(mPendingUniState == kHostUSBDeviceState_Unused);
1991 break;
1992
1993 /* Success */
1994 case kHostUSBDeviceState_UsedByHost:
1995 case kHostUSBDeviceState_Capturable:
1996 case kHostUSBDeviceState_Unused:
1997 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
1998 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
1999 Assert(mPendingUniState == kHostUSBDeviceState_Unused);
2000 break;
2001
2002 default:
2003 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
2004 stateName(aNewState, aNewPendingState, aNewSubState)), false);
2005 }
2006 break;
2007
2008 case kHostUSBDeviceState_AttachingToVM:
2009 Assert(mPrevUniState == kHostUSBDeviceState_HeldByProxy);
2010 NewPrevState = mPrevUniState;
2011 switch (aNewState)
2012 {
2013 /* Host/Failure. */
2014 case kHostUSBDeviceState_PhysDetachingFromVM:
2015 Assert(aNewPendingState == kHostUSBDeviceState_PhysDetached);
2016 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
2017 break;
2018 case kHostUSBDeviceState_HeldByProxy:
2019 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
2020 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
2021 Assert(mPendingUniState == kHostUSBDeviceState_Unused);
2022 break;
2023
2024 /* Success */
2025 case kHostUSBDeviceState_UsedByVM:
2026 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
2027 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
2028 Assert(mPendingUniState == kHostUSBDeviceState_UsedByVM);
2029 break;
2030
2031 default:
2032 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
2033 stateName(aNewState, aNewPendingState, aNewSubState)), false);
2034 }
2035 break;
2036
2037 case kHostUSBDeviceState_DetachingFromVM:
2038 Assert(mPrevUniState == kHostUSBDeviceState_UsedByVM);
2039 NewPrevState = mPrevUniState;
2040 switch (aNewState)
2041 {
2042 /* Host/Failure. */
2043 case kHostUSBDeviceState_PhysDetached: //??
2044 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
2045 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
2046 break;
2047 case kHostUSBDeviceState_PhysDetachingFromVM:
2048 Assert(aNewPendingState == kHostUSBDeviceState_PhysDetached);
2049 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
2050 break;
2051
2052 /* Success */
2053 case kHostUSBDeviceState_HeldByProxy:
2054 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
2055 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
2056 Assert(mPendingUniState == kHostUSBDeviceState_HeldByProxy);
2057 fFilters = true;
2058 break;
2059
2060 case kHostUSBDeviceState_ReleasingToHost:
2061 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
2062 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
2063 Assert(mPendingUniState == kHostUSBDeviceState_Unused);
2064 NewPrevState = kHostUSBDeviceState_HeldByProxy;
2065 break;
2066
2067 default:
2068 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
2069 stateName(aNewState, aNewPendingState, aNewSubState)), false);
2070 }
2071 break;
2072
2073 case kHostUSBDeviceState_PhysDetachingFromVM:
2074 Assert( mPrevUniState == kHostUSBDeviceState_DetachingFromVM
2075 || mPrevUniState == kHostUSBDeviceState_AttachingToVM
2076 || mPrevUniState == kHostUSBDeviceState_UsedByVM);
2077 NewPrevState = mPrevUniState; /* preserving it is more useful. */
2078 switch (aNewState)
2079 {
2080 case kHostUSBDeviceState_PhysDetached:
2081 Assert(aNewPendingState == kHostUSBDeviceState_Invalid);
2082 Assert(aNewSubState == kHostUSBDeviceSubState_Default);
2083 break;
2084 default:
2085 AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
2086 stateName(aNewState, aNewPendingState, aNewSubState)), false);
2087 }
2088 break;
2089
2090 default:
2091 AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), false);
2092 }
2093
2094 /*
2095 * Make the state change.
2096 */
2097 if (NewPrevState != mPrevUniState)
2098 LogFlowThisFunc(("%s -> %s (prev: %s -> %s) [%s]\n",
2099 getStateName(), stateName(aNewState, aNewPendingState, aNewSubState),
2100 stateName(mPrevUniState), stateName(NewPrevState), mName));
2101 else
2102 LogFlowThisFunc(("%s -> %s (prev: %s) [%s]\n",
2103 getStateName(), stateName(aNewState, aNewPendingState, aNewSubState), stateName(NewPrevState), mName));
2104 mPrevUniState = NewPrevState;
2105 mUniState = aNewState;
2106 mUniSubState = aNewSubState;
2107 mPendingUniState = aNewPendingState;
2108 mLastStateChangeTS = RTTimeNanoTS();
2109
2110 return fFilters;
2111}
2112
2113
2114
2115/**
2116 * A convenience for entering a transitional state.
2117
2118 * @param aNewState The new state (transitional).
2119 * @param aFinalSubState The final state of the transition (non-transitional).
2120 * @param aNewSubState The new sub-state when applicable.
2121 *
2122 * @returns Always false because filters are never applied for the start of a transition.
2123 *
2124 * @note The caller must own the write lock for this object.
2125 */
2126bool HostUSBDevice::startTransition (HostUSBDeviceState aNewState, HostUSBDeviceState aFinalState,
2127 HostUSBDeviceSubState aNewSubState /*= kHostUSBDeviceSubState_Default*/)
2128{
2129 /*
2130 * A quick prevalidation thing. Not really necessary since setState
2131 * verifies this too, but it's very easy here.
2132 */
2133 switch (mUniState)
2134 {
2135 case kHostUSBDeviceState_Unsupported:
2136 case kHostUSBDeviceState_UsedByHost:
2137 case kHostUSBDeviceState_Capturable:
2138 case kHostUSBDeviceState_Unused:
2139 case kHostUSBDeviceState_HeldByProxy:
2140 case kHostUSBDeviceState_UsedByVM:
2141 break;
2142
2143 case kHostUSBDeviceState_DetachingFromVM:
2144 case kHostUSBDeviceState_Capturing:
2145 case kHostUSBDeviceState_ReleasingToHost:
2146 case kHostUSBDeviceState_AttachingToVM:
2147 case kHostUSBDeviceState_PhysDetachingFromVM:
2148 AssertMsgFailedReturn (("this=%p %s is a transitional state.\n", this, getStateName()), false);
2149
2150 case kHostUSBDeviceState_PhysDetached:
2151 default:
2152 AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), false);
2153 }
2154
2155 return setState (aNewState, aFinalState, aNewSubState);
2156}
2157
2158
2159/**
2160 * A convenience for advancing a transitional state forward.
2161 *
2162 * @param aSkipReAttach Fast forwards thru the re-attach substate if
2163 * applicable.
2164 *
2165 * @returns true if filters should be applied to the device, false if not.
2166 *
2167 * @note The caller must own the write lock for this object.
2168 */
2169bool HostUSBDevice::advanceTransition(bool aSkipReAttach /* = false */)
2170{
2171 HostUSBDeviceState enmPending = mPendingUniState;
2172 HostUSBDeviceSubState enmSub = mUniSubState;
2173 HostUSBDeviceState enmState = mUniState;
2174 switch (enmState)
2175 {
2176 case kHostUSBDeviceState_Capturing:
2177 switch (enmSub)
2178 {
2179 case kHostUSBDeviceSubState_AwaitingDetach:
2180 enmSub = kHostUSBDeviceSubState_AwaitingReAttach;
2181 break;
2182 case kHostUSBDeviceSubState_AwaitingReAttach:
2183 enmSub = kHostUSBDeviceSubState_Default;
2184 /* fall thru */
2185 case kHostUSBDeviceSubState_Default:
2186 switch (enmPending)
2187 {
2188 case kHostUSBDeviceState_UsedByVM:
2189 enmState = kHostUSBDeviceState_AttachingToVM;
2190 break;
2191 case kHostUSBDeviceState_HeldByProxy:
2192 enmState = enmPending;
2193 enmPending = kHostUSBDeviceState_Invalid;
2194 break;
2195 default:
2196 AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
2197 }
2198 break;
2199 default:
2200 AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
2201 }
2202 break;
2203
2204 case kHostUSBDeviceState_ReleasingToHost:
2205 switch (enmSub)
2206 {
2207 case kHostUSBDeviceSubState_AwaitingDetach:
2208 enmSub = kHostUSBDeviceSubState_AwaitingReAttach;
2209 break;
2210 case kHostUSBDeviceSubState_AwaitingReAttach:
2211 enmSub = kHostUSBDeviceSubState_Default;
2212 /* fall thru */
2213 case kHostUSBDeviceSubState_Default:
2214 switch (enmPending)
2215 {
2216 /* Use Unused here since it implies that filters has been applied
2217 and will make sure they aren't applied if the final state really
2218 is Capturable. */
2219 case kHostUSBDeviceState_Unused:
2220 enmState = enmPending;
2221 enmPending = kHostUSBDeviceState_Invalid;
2222 break;
2223 default:
2224 AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
2225 }
2226 break;
2227 default:
2228 AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
2229 }
2230 break;
2231
2232 case kHostUSBDeviceState_AttachingToVM:
2233 switch (enmSub)
2234 {
2235 case kHostUSBDeviceSubState_AwaitingDetach:
2236 enmSub = kHostUSBDeviceSubState_AwaitingReAttach;
2237 break;
2238 case kHostUSBDeviceSubState_AwaitingReAttach:
2239 enmSub = kHostUSBDeviceSubState_Default;
2240 /* fall thru */
2241 case kHostUSBDeviceSubState_Default:
2242 switch (enmPending)
2243 {
2244 case kHostUSBDeviceState_UsedByVM:
2245 enmState = enmPending;
2246 enmPending = kHostUSBDeviceState_Invalid;
2247 break;
2248 default:
2249 AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
2250 }
2251 break;
2252 default:
2253 AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
2254 }
2255 break;
2256
2257 case kHostUSBDeviceState_DetachingFromVM:
2258 switch (enmSub)
2259 {
2260 case kHostUSBDeviceSubState_AwaitingDetach:
2261 enmSub = kHostUSBDeviceSubState_AwaitingReAttach;
2262 break;
2263 case kHostUSBDeviceSubState_AwaitingReAttach:
2264 enmSub = kHostUSBDeviceSubState_Default;
2265 /* fall thru */
2266 case kHostUSBDeviceSubState_Default:
2267 switch (enmPending)
2268 {
2269 case kHostUSBDeviceState_HeldByProxy:
2270 enmState = enmPending;
2271 enmPending = kHostUSBDeviceState_Invalid;
2272 break;
2273 case kHostUSBDeviceState_Unused:
2274 enmState = kHostUSBDeviceState_ReleasingToHost;
2275 break;
2276 default:
2277 AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
2278 }
2279 break;
2280 default:
2281 AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
2282 }
2283 break;
2284
2285 case kHostUSBDeviceState_PhysDetachingFromVM:
2286 switch (enmSub)
2287 {
2288 case kHostUSBDeviceSubState_Default:
2289 switch (enmPending)
2290 {
2291 case kHostUSBDeviceState_PhysDetached:
2292 enmState = enmPending;
2293 enmPending = kHostUSBDeviceState_Invalid;
2294 break;
2295 default:
2296 AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
2297 }
2298 break;
2299 default:
2300 AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
2301 }
2302 break;
2303
2304 case kHostUSBDeviceState_Unsupported:
2305 case kHostUSBDeviceState_UsedByHost:
2306 case kHostUSBDeviceState_Capturable:
2307 case kHostUSBDeviceState_Unused:
2308 case kHostUSBDeviceState_HeldByProxy:
2309 case kHostUSBDeviceState_UsedByVM:
2310 AssertMsgFailedReturn(("this=%p %s is not transitional\n", this, getStateName()), false);
2311 case kHostUSBDeviceState_PhysDetached:
2312 default:
2313 AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, enmState), false);
2314
2315 }
2316
2317 bool fRc = setState(enmState, enmPending, enmSub);
2318 if (aSkipReAttach && mUniSubState == kHostUSBDeviceSubState_AwaitingReAttach)
2319 fRc |= advanceTransition(false /* don't fast forward re-attach */);
2320 return fRc;
2321}
2322
2323/**
2324 * A convenience for failing a transitional state.
2325 *
2326 * @return true if filters should be applied to the device, false if not.
2327 *
2328 * @note The caller must own the write lock for this object.
2329 */
2330bool HostUSBDevice::failTransition()
2331{
2332 HostUSBDeviceSubState enmSub = mUniSubState;
2333 HostUSBDeviceState enmState = mUniState;
2334 switch (enmState)
2335 {
2336 /*
2337 * There are just two cases, either we got back to the
2338 * previous state (assumes Capture+Attach-To-VM updates it)
2339 * or we assume the device has been unplugged (physically).
2340 */
2341 case kHostUSBDeviceState_DetachingFromVM:
2342 case kHostUSBDeviceState_Capturing:
2343 case kHostUSBDeviceState_ReleasingToHost:
2344 case kHostUSBDeviceState_AttachingToVM:
2345 switch (enmSub)
2346 {
2347 case kHostUSBDeviceSubState_AwaitingDetach:
2348 enmSub = kHostUSBDeviceSubState_Default;
2349 /* fall thru */
2350 case kHostUSBDeviceSubState_Default:
2351 enmState = mPrevUniState;
2352 break;
2353 case kHostUSBDeviceSubState_AwaitingReAttach:
2354 enmSub = kHostUSBDeviceSubState_Default;
2355 enmState = kHostUSBDeviceState_PhysDetached;
2356 break;
2357 default:
2358 AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), false);
2359 }
2360 break;
2361
2362 case kHostUSBDeviceState_PhysDetachingFromVM:
2363 AssertMsgFailedReturn (("this=%p %s shall not fail\n", this, getStateName()), false);
2364
2365 case kHostUSBDeviceState_Unsupported:
2366 case kHostUSBDeviceState_UsedByHost:
2367 case kHostUSBDeviceState_Capturable:
2368 case kHostUSBDeviceState_Unused:
2369 case kHostUSBDeviceState_HeldByProxy:
2370 case kHostUSBDeviceState_UsedByVM:
2371 AssertMsgFailedReturn (("this=%p %s is not transitional\n", this, getStateName()), false);
2372 case kHostUSBDeviceState_PhysDetached:
2373 default:
2374 AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), false);
2375
2376 }
2377
2378 return setState(enmState, kHostUSBDeviceState_Invalid, enmSub);
2379}
2380
2381
2382/**
2383 * Determins the canonical state of the device.
2384 *
2385 * @returns canonical state.
2386 *
2387 * @note The caller must own the read (or write) lock for this object.
2388 */
2389USBDeviceState_T HostUSBDevice::canonicalState() const
2390{
2391 switch (mUniState)
2392 {
2393 /*
2394 * Straight forward.
2395 */
2396 case kHostUSBDeviceState_Unsupported:
2397 return USBDeviceState_NotSupported;
2398
2399 case kHostUSBDeviceState_UsedByHost:
2400 return USBDeviceState_Unavailable;
2401
2402 case kHostUSBDeviceState_Capturable:
2403 return USBDeviceState_Busy;
2404
2405 case kHostUSBDeviceState_Unused:
2406 return USBDeviceState_Available;
2407
2408 case kHostUSBDeviceState_HeldByProxy:
2409 return USBDeviceState_Held;
2410
2411 case kHostUSBDeviceState_UsedByVM:
2412 return USBDeviceState_Captured;
2413
2414 /*
2415 * Pretend we've reached the final state.
2416 */
2417 case kHostUSBDeviceState_Capturing:
2418 Assert( mPendingUniState == kHostUSBDeviceState_UsedByVM
2419 || mPendingUniState == kHostUSBDeviceState_HeldByProxy);
2420 return mPendingUniState == kHostUSBDeviceState_UsedByVM
2421 ? (USBDeviceState_T)USBDeviceState_Captured
2422 : (USBDeviceState_T)USBDeviceState_Held;
2423 /* The cast ^^^^ is because xidl is using different enums for
2424 each of the values. *Very* nice idea... :-) */
2425
2426 case kHostUSBDeviceState_AttachingToVM:
2427 return USBDeviceState_Captured;
2428
2429 /*
2430 * Return the previous state.
2431 */
2432 case kHostUSBDeviceState_ReleasingToHost:
2433 Assert( mPrevUniState == kHostUSBDeviceState_UsedByVM
2434 || mPrevUniState == kHostUSBDeviceState_HeldByProxy);
2435 return mPrevUniState == kHostUSBDeviceState_UsedByVM
2436 ? (USBDeviceState_T)USBDeviceState_Captured
2437 : (USBDeviceState_T)USBDeviceState_Held;
2438 /* The cast ^^^^ is because xidl is using different enums for
2439 each of the values. *Very* nice idea... :-) */
2440
2441 case kHostUSBDeviceState_DetachingFromVM:
2442 return USBDeviceState_Captured;
2443 case kHostUSBDeviceState_PhysDetachingFromVM:
2444 return USBDeviceState_Captured;
2445
2446 case kHostUSBDeviceState_PhysDetached:
2447 default:
2448 AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), USBDeviceState_NotSupported);
2449 }
2450 /* won't ever get here. */
2451}
2452/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette