HostUSBDeviceImpl.cpp revision b52c24239bed9dc9f284d829b6059073afcb1894
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * VirtualBox IHostUSBDevice COM interface implementation.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Copyright (C) 2006-2007 Oracle Corporation
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * available from http://www.virtualbox.org. This file is free software;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * General Public License (GPL) as published by the Free Software
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync// constructor / destructor
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/////////////////////////////////////////////////////////////////////////////
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync// public initializer/uninitializer for internal purposes only
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/////////////////////////////////////////////////////////////////////////////
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Initializes the USB device object.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * @returns COM result indicator
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * @param aUsb Pointer to the usb device structure for which the object is to be a wrapper.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * This structure is now fully owned by the HostUSBDevice object and will be
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * freed when it is destructed.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * @param aUSBProxyService Pointer to the USB Proxy Service object.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsyncHRESULT HostUSBDevice::init(PUSBDEVICE aUsb, USBProxyService *aUSBProxyService)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync /* Enclose the state transition NotReady->InInit->Ready */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * We need a unique ID for this VBoxSVC session.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * The UUID isn't stored anywhere.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Set the initial device state.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync AssertMsgReturn( aUsb->enmState >= USBDEVICESTATE_UNSUPPORTED
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync && aUsb->enmState < USBDEVICESTATE_USED_BY_GUEST, /* used-by-guest is not a legal initial state. */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync /* Other data members */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync /* Set the name. */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync /* Confirm the successful initialization */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Uninitializes the instance and sets the ready flag to FALSE.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync /* Enclose the state transition Ready->InUninit->NotReady */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync// IUSBDevice properties
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/////////////////////////////////////////////////////////////////////////////
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsyncSTDMETHODIMP HostUSBDevice::COMGETTER(Id)(BSTR *aId)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync /* mId is constant during life time, no need to lock */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsyncSTDMETHODIMP HostUSBDevice::COMGETTER(VendorId)(USHORT *aVendorId)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
*aPort = 0;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
else if (haveManufacturer)
else if (haveProduct)
return name;
HRESULT HostUSBDevice::requestCaptureForVM(SessionMachine *aMachine, bool aSetError, ULONG aMaskedIfs /* = 0*/)
if (aSetError)
setState(kHostUSBDeviceState_Capturing, kHostUSBDeviceState_UsedByVM, kHostUSBDeviceSubState_AwaitingDetach);
return E_FAIL;
return S_OK;
if (!mIsPhysicallyDetached)
if (!mIsPhysicallyDetached)
return hrc;
HRESULT HostUSBDevice::onDetachFromVM(SessionMachine *aMachine, bool aDone, bool *aRunFilters, bool aAbnormal /*= true*/)
LogFlowThisFunc(("{%s} state=%s aDone=%RTbool aAbnormal=%RTbool\n", mName, getStateName(), aDone, aAbnormal));
if (!aDone)
AssertMsgReturn( mUniState == kHostUSBDeviceState_DetachingFromVM /** @todo capturing for VM ends up here on termination. */
if (!aDone)
*aRunFilters = startTransition(kHostUSBDeviceState_DetachingFromVM, kHostUSBDeviceState_HeldByProxy);
return S_OK;
return S_OK;
AssertMsgReturn(mUniState == kHostUSBDeviceState_HeldByProxy, ("{%s} %s\n", mName, getStateName()), E_UNEXPECTED);
|| defined(RT_OS_WINDOWS)
startTransition(kHostUSBDeviceState_ReleasingToHost, kHostUSBDeviceState_Unused, kHostUSBDeviceSubState_AwaitingDetach);
return E_FAIL;
return S_OK;
return S_OK;
|| defined(RT_OS_WINDOWS)
startTransition(kHostUSBDeviceState_Capturing, kHostUSBDeviceState_HeldByProxy, kHostUSBDeviceSubState_AwaitingDetach);
return E_FAIL;
return S_OK;
switch (mUniState)
switch (mUniSubState)
mIsPhysicallyDetached = true;
mUniSubState == kHostUSBDeviceSubState_AwaitingDetach /* (In case we don't get the detach notice.) */
int HostUSBDevice::compare(PCUSBDEVICE aDev1, PCUSBDEVICE aDev2, bool aIsAwaitingReAttach /*= false */)
if (iDiff)
return iDiff;
if (iDiff)
return iDiff;
if (iDiff)
return iDiff;
#ifdef RT_OS_WINDOWS /* the string query may fail on windows during replugging, ignore serial mismatch if this is the case. */
&& ( !aIsAwaitingReAttach
#ifdef RT_OS_WINDOWS
if (iDiff)
return iDiff;
if (iDiff)
return iDiff;
iDiff = aDev1->bPort - aDev2->bPort; /* shouldn't change anywhere and help pinpoint it very accurately. */
if (iDiff)
return iDiff;
if (aIsAwaitingReAttach)
* works by state change. Using 3 return codes/parameters is just plain ugly.
bool HostUSBDevice::updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMachine **aIgnoreMachine)
*aRunFilters = false;
bool fIsImportant = false;
switch (mUniState)
#ifdef HOSTUSBDEVICE_FUZZY_STATE
LogThisFunc(("{%s} %s -> %s!\n", mName, getStateName(), stateName(kHostUSBDeviceState_UsedByHost)));
#ifndef HOSTUSBDEVICE_FUZZY_STATE
switch (mUniState)
#ifdef HOSTUSBDEVICE_FUZZY_STATE
fIsImportant = true;
#ifndef HOSTUSBDEVICE_FUZZY_STATE
case USBDEVICESTATE_UNUSED:
switch (mUniState)
#ifdef HOSTUSBDEVICE_FUZZY_STATE
fIsImportant = true;
#if defined(RT_OS_WINDOWS)
#ifndef HOSTUSBDEVICE_FUZZY_STATE
switch (mUniState)
switch (mUniState)
fIsImportant = true;
/** @todo might have to handle some stuff here too if we cannot make the release/capture handling deal with that above ... */
return fIsImportant;
bool HostUSBDevice::updateStateFake(PCUSBDEVICE aDev, bool *aRunFilters, SessionMachine **aIgnoreMachine)
switch (enmState)
switch (mUniSubState)
switch (aState)
switch (aPendingState)
switch (aSubState)
switch (aSubState)
switch (aPendingState)
switch (aSubState)
switch (aPendingState)
switch (aSubState)
switch (aSubState)
switch (aPendingState)
switch (aSubState)
switch (aPendingState)
switch (aSubState)
bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aNewPendingState /*= kHostUSBDeviceState_Invalid*/,
bool fFilters = false;
switch (mUniState)
switch (aNewState)
switch (aNewState)
fFilters = true;
switch (aNewState)
switch (aNewPendingState)
switch (aNewState)
switch (aNewPendingState)
switch (aNewState)
switch (aNewPendingState)
switch (aNewPendingState)
switch (aNewState)
switch (aNewPendingState)
switch (mUniState)
switch (aNewState)
switch (aNewSubState)
switch (aNewState)
switch (aNewSubState)
switch (aNewState)
switch (aNewState)
fFilters = true;
switch (aNewState)
getStateName(), stateName(aNewState, aNewPendingState, aNewSubState), stateName(NewPrevState), mName));
return fFilters;
switch (mUniState)
switch (enmState)
switch (enmSub)
switch (enmPending)
AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
switch (enmSub)
switch (enmPending)
AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
switch (enmSub)
switch (enmPending)
AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
switch (enmSub)
switch (enmPending)
AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
switch (enmSub)
switch (enmPending)
AssertMsgFailedReturn(("this=%p invalid pending state %d: %s\n", this, enmPending, getStateName()), false);
return fRc;
switch (enmState)
switch (enmSub)
switch (mUniState)
return USBDeviceState_NotSupported;
return USBDeviceState_Unavailable;
return USBDeviceState_Busy;
return USBDeviceState_Available;
return USBDeviceState_Held;
return USBDeviceState_Captured;
return USBDeviceState_Captured;
return USBDeviceState_Captured;
return USBDeviceState_Captured;
AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), USBDeviceState_NotSupported);