summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-server/USBControllerImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-server/USBControllerImpl.cpp')
-rw-r--r--src/VBox/Main/src-server/USBControllerImpl.cpp1010
1 files changed, 86 insertions, 924 deletions
diff --git a/src/VBox/Main/src-server/USBControllerImpl.cpp b/src/VBox/Main/src-server/USBControllerImpl.cpp
index 8f4d1c48..18c4f43e 100644
--- a/src/VBox/Main/src-server/USBControllerImpl.cpp
+++ b/src/VBox/Main/src-server/USBControllerImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2005-2012 Oracle Corporation
+ * Copyright (C) 2005-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -21,18 +21,13 @@
#include "MachineImpl.h"
#include "VirtualBoxImpl.h"
#include "HostImpl.h"
-#ifdef VBOX_WITH_USB
-# include "USBDeviceImpl.h"
-# include "HostUSBDeviceImpl.h"
-# include "USBProxyService.h"
-# include "USBDeviceFilterImpl.h"
-#endif
#include <iprt/string.h>
#include <iprt/cpp/utils.h>
#include <VBox/err.h>
#include <VBox/settings.h>
+#include <VBox/com/array.h>
#include <algorithm>
@@ -43,41 +38,31 @@
// defines
/////////////////////////////////////////////////////////////////////////////
-typedef std::list< ComObjPtr<USBDeviceFilter> > DeviceFilterList;
-
struct BackupableUSBData
{
BackupableUSBData()
- : fEnabled(false),
- fEnabledEHCI(false)
+ : enmType(USBControllerType_Null)
{ }
- BOOL fEnabled;
- BOOL fEnabledEHCI;
+ Utf8Str strName;
+ USBControllerType_T enmType;
};
struct USBController::Data
{
Data(Machine *pMachine)
- : pParent(pMachine),
- pHost(pMachine->getVirtualBox()->host())
+ : pParent(pMachine)
{ }
~Data()
{};
Machine * const pParent;
- Host * const pHost;
// peer machine's USB controller
const ComObjPtr<USBController> pPeer;
Backupable<BackupableUSBData> bd;
-#ifdef VBOX_WITH_USB
- // the following fields need special backup/rollback/commit handling,
- // so they cannot be a part of BackupableData
- Backupable<DeviceFilterList> llDeviceFilters;
-#endif
};
@@ -106,12 +91,18 @@ void USBController::FinalRelease()
*
* @returns COM result indicator.
* @param aParent Pointer to our parent object.
+ * @param aName The name of the USB controller.
+ * @param enmType The USB controller type.
*/
-HRESULT USBController::init(Machine *aParent)
+HRESULT USBController::init(Machine *aParent, const Utf8Str &aName, USBControllerType_T enmType)
{
- LogFlowThisFunc(("aParent=%p\n", aParent));
+ LogFlowThisFunc(("aParent=%p aName=\"%s\"\n", aParent, aName.c_str()));
- ComAssertRet(aParent, E_INVALIDARG);
+ ComAssertRet(aParent && !aName.isEmpty(), E_INVALIDARG);
+ if ( (enmType <= USBControllerType_Null)
+ || (enmType > USBControllerType_EHCI))
+ return setError(E_INVALIDARG,
+ tr("Invalid USB controller type"));
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
@@ -122,9 +113,8 @@ HRESULT USBController::init(Machine *aParent)
/* mPeer is left null */
m->bd.allocate();
-#ifdef VBOX_WITH_USB
- m->llDeviceFilters.allocate();
-#endif
+ m->bd->strName = aName;
+ m->bd->enmType = enmType;
/* Confirm a successful initialization */
autoInitSpan.setSucceeded();
@@ -140,13 +130,22 @@ HRESULT USBController::init(Machine *aParent)
* @returns COM result indicator.
* @param aParent Pointer to our parent object.
* @param aPeer The object to share.
+ * @param aReshare
+ * When false, the original object will remain a data owner.
+ * Otherwise, data ownership will be transferred from the original
+ * object to this one.
+ *
+ * @note This object must be destroyed before the original object
+ * it shares data with is destroyed.
*
- * @note This object must be destroyed before the original object
- * it shares data with is destroyed.
+ * @note Locks @a aThat object for writing if @a aReshare is @c true, or for
+ * reading if @a aReshare is false.
*/
-HRESULT USBController::init(Machine *aParent, USBController *aPeer)
+HRESULT USBController::init(Machine *aParent, USBController *aPeer,
+ bool fReshare /* = false */)
{
- LogFlowThisFunc(("aParent=%p, aPeer=%p\n", aParent, aPeer));
+ LogFlowThisFunc(("aParent=%p, aPeer=%p, fReshare=%RTbool\n",
+ aParent, aPeer, fReshare));
ComAssertRet(aParent && aPeer, E_INVALIDARG);
@@ -156,24 +155,24 @@ HRESULT USBController::init(Machine *aParent, USBController *aPeer)
m = new Data(aParent);
- unconst(m->pPeer) = aPeer;
+ /* sanity */
+ AutoCaller peerCaller(aPeer);
+ AssertComRCReturnRC(peerCaller.rc());
- AutoWriteLock thatlock(aPeer COMMA_LOCKVAL_SRC_POS);
- m->bd.share(aPeer->m->bd);
+ if (fReshare)
+ {
+ AutoWriteLock peerLock(aPeer COMMA_LOCKVAL_SRC_POS);
-#ifdef VBOX_WITH_USB
- /* create copies of all filters */
- m->llDeviceFilters.allocate();
- DeviceFilterList::const_iterator it = aPeer->m->llDeviceFilters->begin();
- while (it != aPeer->m->llDeviceFilters->end())
+ unconst(aPeer->m->pPeer) = this;
+ m->bd.attach (aPeer->m->bd);
+ }
+ else
{
- ComObjPtr<USBDeviceFilter> filter;
- filter.createObject();
- filter->init(this, *it);
- m->llDeviceFilters->push_back(filter);
- ++it;
+ unconst(m->pPeer) = aPeer;
+
+ AutoReadLock peerLock(aPeer COMMA_LOCKVAL_SRC_POS);
+ m->bd.share (aPeer->m->bd);
}
-#endif /* VBOX_WITH_USB */
/* Confirm a successful initialization */
autoInitSpan.setSucceeded();
@@ -204,20 +203,6 @@ HRESULT USBController::initCopy(Machine *aParent, USBController *aPeer)
AutoWriteLock thatlock(aPeer COMMA_LOCKVAL_SRC_POS);
m->bd.attachCopy(aPeer->m->bd);
-#ifdef VBOX_WITH_USB
- /* create private copies of all filters */
- m->llDeviceFilters.allocate();
- DeviceFilterList::const_iterator it = aPeer->m->llDeviceFilters->begin();
- while (it != aPeer->m->llDeviceFilters->end())
- {
- ComObjPtr<USBDeviceFilter> filter;
- filter.createObject();
- filter->initCopy(this, *it);
- m->llDeviceFilters->push_back(filter);
- ++it;
- }
-#endif /* VBOX_WITH_USB */
-
/* Confirm a successful initialization */
autoInitSpan.setSucceeded();
@@ -238,16 +223,6 @@ void USBController::uninit()
if (autoUninitSpan.uninitDone())
return;
-#ifdef VBOX_WITH_USB
- // uninit all device filters on the list (it's a standard std::list not an ObjectsList
- // so we must uninit() manually)
- for (DeviceFilterList::iterator it = m->llDeviceFilters->begin();
- it != m->llDeviceFilters->end();
- ++it)
- (*it)->uninit();
-
- m->llDeviceFilters.free();
-#endif
m->bd.free();
unconst(m->pPeer) = NULL;
@@ -260,112 +235,29 @@ void USBController::uninit()
// IUSBController properties
/////////////////////////////////////////////////////////////////////////////
-
-STDMETHODIMP USBController::COMGETTER(Enabled)(BOOL *aEnabled)
-{
- CheckComArgOutPointerValid(aEnabled);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- *aEnabled = m->bd->fEnabled;
-
- return S_OK;
-}
-
-
-STDMETHODIMP USBController::COMSETTER(Enabled)(BOOL aEnabled)
-{
- LogFlowThisFunc(("aEnabled=%RTbool\n", aEnabled));
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* the machine needs to be mutable */
- AutoMutableStateDependency adep(m->pParent);
- if (FAILED(adep.rc())) return adep.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- if (m->bd->fEnabled != aEnabled)
- {
- m->bd.backup();
- m->bd->fEnabled = aEnabled;
-
- // leave the lock for safety
- alock.release();
-
- AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
- m->pParent->setModified(Machine::IsModified_USB);
- mlock.release();
-
- m->pParent->onUSBControllerChange();
- }
-
- return S_OK;
-}
-
-STDMETHODIMP USBController::COMGETTER(EnabledEHCI)(BOOL *aEnabled)
-{
- CheckComArgOutPointerValid(aEnabled);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- *aEnabled = m->bd->fEnabledEHCI;
-
- return S_OK;
-}
-
-STDMETHODIMP USBController::COMSETTER(EnabledEHCI)(BOOL aEnabled)
+STDMETHODIMP USBController::COMGETTER(Name) (BSTR *aName)
{
- LogFlowThisFunc(("aEnabled=%RTbool\n", aEnabled));
+ CheckComArgOutPointerValid(aName);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* the machine needs to be mutable */
- AutoMutableStateDependency adep(m->pParent);
- if (FAILED(adep.rc())) return adep.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- if (m->bd->fEnabledEHCI != aEnabled)
- {
- m->bd.backup();
- m->bd->fEnabledEHCI = aEnabled;
-
- // leave the lock for safety
- alock.release();
-
- AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
- m->pParent->setModified(Machine::IsModified_USB);
- mlock.release();
-
- m->pParent->onUSBControllerChange();
- }
+ /* strName is constant during life time, no need to lock */
+ m->bd->strName.cloneTo(aName);
return S_OK;
}
-STDMETHODIMP USBController::COMGETTER(ProxyAvailable)(BOOL *aEnabled)
+STDMETHODIMP USBController::COMGETTER(Type)(USBControllerType_T *aType)
{
- CheckComArgOutPointerValid(aEnabled);
+ CheckComArgOutPointerValid(aType);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-#ifdef VBOX_WITH_USB
- *aEnabled = true;
-#else
- *aEnabled = false;
-#endif
+ *aType = m->bd->enmType;
return S_OK;
}
@@ -377,366 +269,27 @@ STDMETHODIMP USBController::COMGETTER(USBStandard)(USHORT *aUSBStandard)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* not accessing data -- no need to lock */
-
- /** @todo This is no longer correct */
- *aUSBStandard = 0x0101;
-
- return S_OK;
-}
-
-#ifndef VBOX_WITH_USB
-/**
- * Fake class for build without USB.
- * We need an empty collection & enum for deviceFilters, that's all.
- */
-class ATL_NO_VTABLE USBDeviceFilter :
- public VirtualBoxBase,
- VBOX_SCRIPTABLE_IMPL(IUSBDeviceFilter)
-{
-public:
- DECLARE_NOT_AGGREGATABLE(USBDeviceFilter)
- DECLARE_PROTECT_FINAL_CONSTRUCT()
- BEGIN_COM_MAP(USBDeviceFilter)
- VBOX_DEFAULT_INTERFACE_ENTRIES(IUSBDeviceFilter)
- END_COM_MAP()
-
- DECLARE_EMPTY_CTOR_DTOR(USBDeviceFilter)
-
- // IUSBDeviceFilter properties
- STDMETHOD(COMGETTER(Name))(BSTR *aName);
- STDMETHOD(COMSETTER(Name))(IN_BSTR aName);
- STDMETHOD(COMGETTER(Active))(BOOL *aActive);
- STDMETHOD(COMSETTER(Active))(BOOL aActive);
- STDMETHOD(COMGETTER(VendorId))(BSTR *aVendorId);
- STDMETHOD(COMSETTER(VendorId))(IN_BSTR aVendorId);
- STDMETHOD(COMGETTER(ProductId))(BSTR *aProductId);
- STDMETHOD(COMSETTER(ProductId))(IN_BSTR aProductId);
- STDMETHOD(COMGETTER(Revision))(BSTR *aRevision);
- STDMETHOD(COMSETTER(Revision))(IN_BSTR aRevision);
- STDMETHOD(COMGETTER(Manufacturer))(BSTR *aManufacturer);
- STDMETHOD(COMSETTER(Manufacturer))(IN_BSTR aManufacturer);
- STDMETHOD(COMGETTER(Product))(BSTR *aProduct);
- STDMETHOD(COMSETTER(Product))(IN_BSTR aProduct);
- STDMETHOD(COMGETTER(SerialNumber))(BSTR *aSerialNumber);
- STDMETHOD(COMSETTER(SerialNumber))(IN_BSTR aSerialNumber);
- STDMETHOD(COMGETTER(Port))(BSTR *aPort);
- STDMETHOD(COMSETTER(Port))(IN_BSTR aPort);
- STDMETHOD(COMGETTER(Remote))(BSTR *aRemote);
- STDMETHOD(COMSETTER(Remote))(IN_BSTR aRemote);
- STDMETHOD(COMGETTER(MaskedInterfaces))(ULONG *aMaskedIfs);
- STDMETHOD(COMSETTER(MaskedInterfaces))(ULONG aMaskedIfs);
-};
-#endif /* !VBOX_WITH_USB */
-
-
-STDMETHODIMP USBController::COMGETTER(DeviceFilters)(ComSafeArrayOut(IUSBDeviceFilter *, aDevicesFilters))
-{
-#ifdef VBOX_WITH_USB
- CheckComArgOutSafeArrayPointerValid(aDevicesFilters);
-
- AutoCaller autoCaller(this);
- if(FAILED(autoCaller.rc())) return autoCaller.rc();
-
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- SafeIfaceArray<IUSBDeviceFilter> collection(*m->llDeviceFilters.data());
- collection.detachTo(ComSafeArrayOutArg(aDevicesFilters));
-
- return S_OK;
-#else
- NOREF(aDevicesFilters);
-# ifndef RT_OS_WINDOWS
- NOREF(aDevicesFiltersSize);
-# endif
- ReturnComNotImplemented();
-#endif
-}
-
-// IUSBController methods
-/////////////////////////////////////////////////////////////////////////////
-
-STDMETHODIMP USBController::CreateDeviceFilter(IN_BSTR aName,
- IUSBDeviceFilter **aFilter)
-{
-#ifdef VBOX_WITH_USB
- CheckComArgOutPointerValid(aFilter);
-
- CheckComArgStrNotEmptyOrNull(aName);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* the machine needs to be mutable */
- AutoMutableStateDependency adep(m->pParent);
- if (FAILED(adep.rc())) return adep.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- ComObjPtr<USBDeviceFilter> filter;
- filter.createObject();
- HRESULT rc = filter->init(this, aName);
- ComAssertComRCRetRC(rc);
- rc = filter.queryInterfaceTo(aFilter);
- AssertComRCReturnRC(rc);
-
- return S_OK;
-#else
- NOREF(aName);
- NOREF(aFilter);
- ReturnComNotImplemented();
-#endif
-}
-
-STDMETHODIMP USBController::InsertDeviceFilter(ULONG aPosition,
- IUSBDeviceFilter *aFilter)
-{
-#ifdef VBOX_WITH_USB
-
- CheckComArgNotNull(aFilter);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* the machine needs to be mutable */
- AutoMutableStateDependency adep(m->pParent);
- if (FAILED(adep.rc())) return adep.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- ComObjPtr<USBDeviceFilter> filter = static_cast<USBDeviceFilter*>(aFilter);
- // @todo r=dj make sure the input object is actually from us
-// if (!filter)
-// return setError(E_INVALIDARG,
-// tr("The given USB device filter is not created within "
-// "this VirtualBox instance"));
-
- if (filter->mInList)
- return setError(VBOX_E_INVALID_OBJECT_STATE,
- tr("The given USB device filter is already in the list"));
-
- /* backup the list before modification */
- m->llDeviceFilters.backup();
-
- /* iterate to the position... */
- DeviceFilterList::iterator it;
- if (aPosition < m->llDeviceFilters->size())
+ switch (m->bd->enmType)
{
- it = m->llDeviceFilters->begin();
- std::advance(it, aPosition);
- }
- else
- it = m->llDeviceFilters->end();
- /* ...and insert */
- m->llDeviceFilters->insert(it, filter);
- filter->mInList = true;
-
- /* notify the proxy (only when it makes sense) */
- if (filter->getData().mActive && Global::IsOnline(adep.machineState())
- && filter->getData().mRemote.isMatch(false))
- {
- USBProxyService *service = m->pHost->usbProxyService();
- ComAssertRet(service, E_FAIL);
-
- ComAssertRet(filter->getId() == NULL, E_FAIL);
- filter->getId() = service->insertFilter(&filter->getData().mUSBFilter);
+ case USBControllerType_OHCI:
+ *aUSBStandard = 0x0101;
+ break;
+ case USBControllerType_EHCI:
+ *aUSBStandard = 0x0200;
+ break;
+ default:
+ AssertMsgFailedReturn(("Invalid controller type %d\n", m->bd->enmType),
+ E_FAIL);
}
- alock.release();
- AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
- m->pParent->setModified(Machine::IsModified_USB);
- mlock.release();
-
return S_OK;
-
-#else /* VBOX_WITH_USB */
-
- NOREF(aPosition);
- NOREF(aFilter);
- ReturnComNotImplemented();
-
-#endif /* VBOX_WITH_USB */
-}
-
-STDMETHODIMP USBController::RemoveDeviceFilter(ULONG aPosition,
- IUSBDeviceFilter **aFilter)
-{
-#ifdef VBOX_WITH_USB
-
- CheckComArgOutPointerValid(aFilter);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* the machine needs to be mutable */
- AutoMutableStateDependency adep(m->pParent);
- if (FAILED(adep.rc())) return adep.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- if (!m->llDeviceFilters->size())
- return setError(E_INVALIDARG,
- tr("The USB device filter list is empty"));
-
- if (aPosition >= m->llDeviceFilters->size())
- return setError(E_INVALIDARG,
- tr("Invalid position: %lu (must be in range [0, %lu])"),
- aPosition, m->llDeviceFilters->size() - 1);
-
- /* backup the list before modification */
- m->llDeviceFilters.backup();
-
- ComObjPtr<USBDeviceFilter> filter;
- {
- /* iterate to the position... */
- DeviceFilterList::iterator it = m->llDeviceFilters->begin();
- std::advance(it, aPosition);
- /* ...get an element from there... */
- filter = *it;
- /* ...and remove */
- filter->mInList = false;
- m->llDeviceFilters->erase(it);
- }
-
- /* cancel sharing (make an independent copy of data) */
- filter->unshare();
-
- filter.queryInterfaceTo(aFilter);
-
- /* notify the proxy (only when it makes sense) */
- if (filter->getData().mActive && Global::IsOnline(adep.machineState())
- && filter->getData().mRemote.isMatch(false))
- {
- USBProxyService *service = m->pHost->usbProxyService();
- ComAssertRet(service, E_FAIL);
-
- ComAssertRet(filter->getId() != NULL, E_FAIL);
- service->removeFilter(filter->getId());
- filter->getId() = NULL;
- }
-
- alock.release();
- AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
- m->pParent->setModified(Machine::IsModified_USB);
- mlock.release();
-
- return S_OK;
-
-#else /* VBOX_WITH_USB */
-
- NOREF(aPosition);
- NOREF(aFilter);
- ReturnComNotImplemented();
-
-#endif /* VBOX_WITH_USB */
}
// public methods only for internal purposes
/////////////////////////////////////////////////////////////////////////////
-/**
- * Loads settings from the given machine node.
- * May be called once right after this object creation.
- *
- * @param aMachineNode <Machine> node.
- *
- * @note Does not lock "this" as Machine::loadHardware, which calls this, does not lock either.
- */
-HRESULT USBController::loadSettings(const settings::USBController &data)
-{
- AutoCaller autoCaller(this);
- AssertComRCReturnRC(autoCaller.rc());
-
- /* Note: we assume that the default values for attributes of optional
- * nodes are assigned in the Data::Data() constructor and don't do it
- * here. It implies that this method may only be called after constructing
- * a new BIOSSettings object while all its data fields are in the default
- * values. Exceptions are fields whose creation time defaults don't match
- * values that should be applied when these fields are not explicitly set
- * in the settings file (for backwards compatibility reasons). This takes
- * place when a setting of a newly created object must default to A while
- * the same setting of an object loaded from the old settings file must
- * default to B. */
-
- m->bd->fEnabled = data.fEnabled;
- m->bd->fEnabledEHCI = data.fEnabledEHCI;
-
-#ifdef VBOX_WITH_USB
- for (settings::USBDeviceFiltersList::const_iterator it = data.llDeviceFilters.begin();
- it != data.llDeviceFilters.end();
- ++it)
- {
- const settings::USBDeviceFilter &f = *it;
- ComObjPtr<USBDeviceFilter> pFilter;
- pFilter.createObject();
- HRESULT rc = pFilter->init(this, // parent
- f);
- if (FAILED(rc)) return rc;
-
- m->llDeviceFilters->push_back(pFilter);
- pFilter->mInList = true;
- }
-#endif /* VBOX_WITH_USB */
-
- return S_OK;
-}
-
-/**
- * Saves settings to the given machine node.
- *
- * @param aMachineNode <Machine> node.
- *
- * @note Locks this object for reading.
- */
-HRESULT USBController::saveSettings(settings::USBController &data)
-{
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- data.fEnabled = !!m->bd->fEnabled;
- data.fEnabledEHCI = !!m->bd->fEnabledEHCI;
-
-#ifdef VBOX_WITH_USB
- data.llDeviceFilters.clear();
-
- for (DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
- it != m->llDeviceFilters->end();
- ++it)
- {
- AutoWriteLock filterLock(*it COMMA_LOCKVAL_SRC_POS);
- const USBDeviceFilter::Data &filterData = (*it)->getData();
-
- Bstr str;
-
- settings::USBDeviceFilter f;
- f.strName = filterData.mName;
- f.fActive = !!filterData.mActive;
- (*it)->COMGETTER(VendorId)(str.asOutParam());
- f.strVendorId = str;
- (*it)->COMGETTER(ProductId)(str.asOutParam());
- f.strProductId = str;
- (*it)->COMGETTER(Revision)(str.asOutParam());
- f.strRevision = str;
- (*it)->COMGETTER(Manufacturer)(str.asOutParam());
- f.strManufacturer = str;
- (*it)->COMGETTER(Product)(str.asOutParam());
- f.strProduct = str;
- (*it)->COMGETTER(SerialNumber)(str.asOutParam());
- f.strSerialNumber = str;
- (*it)->COMGETTER(Port)(str.asOutParam());
- f.strPort = str;
- f.strRemote = filterData.mRemote.string();
- f.ulMaskedInterfaces = filterData.mMaskedIfs;
-
- data.llDeviceFilters.push_back(f);
- }
-#endif /* VBOX_WITH_USB */
-
- return S_OK;
-}
-
/** @note Locks objects for writing! */
void USBController::rollback()
{
@@ -750,82 +303,6 @@ void USBController::rollback()
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
m->bd.rollback();
-
-#ifdef VBOX_WITH_USB
-
- if (m->llDeviceFilters.isBackedUp())
- {
- USBProxyService *service = m->pHost->usbProxyService();
- Assert(service);
-
- /* uninitialize all new filters (absent in the backed up list) */
- DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
- DeviceFilterList *backedList = m->llDeviceFilters.backedUpData();
- while (it != m->llDeviceFilters->end())
- {
- if (std::find(backedList->begin(), backedList->end(), *it) ==
- backedList->end())
- {
- /* notify the proxy (only when it makes sense) */
- if ((*it)->getData().mActive &&
- Global::IsOnline(adep.machineState())
- && (*it)->getData().mRemote.isMatch(false))
- {
- USBDeviceFilter *filter = *it;
- Assert(filter->getId() != NULL);
- service->removeFilter(filter->getId());
- filter->getId() = NULL;
- }
-
- (*it)->uninit();
- }
- ++it;
- }
-
- if (Global::IsOnline(adep.machineState()))
- {
- /* find all removed old filters (absent in the new list)
- * and insert them back to the USB proxy */
- it = backedList->begin();
- while (it != backedList->end())
- {
- if (std::find(m->llDeviceFilters->begin(), m->llDeviceFilters->end(), *it) ==
- m->llDeviceFilters->end())
- {
- /* notify the proxy (only when necessary) */
- if ((*it)->getData().mActive
- && (*it)->getData().mRemote.isMatch(false))
- {
- USBDeviceFilter *flt = *it; /* resolve ambiguity */
- Assert(flt->getId() == NULL);
- flt->getId() = service->insertFilter(&flt->getData().mUSBFilter);
- }
- }
- ++it;
- }
- }
-
- /* restore the list */
- m->llDeviceFilters.rollback();
- }
-
- /* here we don't depend on the machine state any more */
- adep.release();
-
- /* rollback any changes to filters after restoring the list */
- DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
- while (it != m->llDeviceFilters->end())
- {
- if ((*it)->isModified())
- {
- (*it)->rollback();
- /* call this to notify the USB proxy about changes */
- onDeviceFilterChange(*it);
- }
- ++it;
- }
-
-#endif /* VBOX_WITH_USB */
}
/**
@@ -856,82 +333,6 @@ void USBController::commit()
m->pPeer->m->bd.attach(m->bd);
}
}
-
-#ifdef VBOX_WITH_USB
- bool commitFilters = false;
-
- if (m->llDeviceFilters.isBackedUp())
- {
- m->llDeviceFilters.commit();
-
- /* apply changes to peer */
- if (m->pPeer)
- {
- AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
-
- /* commit all changes to new filters (this will reshare data with
- * peers for those who have peers) */
- DeviceFilterList *newList = new DeviceFilterList();
- DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
- while (it != m->llDeviceFilters->end())
- {
- (*it)->commit();
-
- /* look if this filter has a peer filter */
- ComObjPtr<USBDeviceFilter> peer = (*it)->peer();
- if (!peer)
- {
- /* no peer means the filter is a newly created one;
- * create a peer owning data this filter share it with */
- peer.createObject();
- peer->init(m->pPeer, *it, true /* aReshare */);
- }
- else
- {
- /* remove peer from the old list */
- m->pPeer->m->llDeviceFilters->remove(peer);
- }
- /* and add it to the new list */
- newList->push_back(peer);
-
- ++it;
- }
-
- /* uninit old peer's filters that are left */
- it = m->pPeer->m->llDeviceFilters->begin();
- while (it != m->pPeer->m->llDeviceFilters->end())
- {
- (*it)->uninit();
- ++it;
- }
-
- /* attach new list of filters to our peer */
- m->pPeer->m->llDeviceFilters.attach(newList);
- }
- else
- {
- /* we have no peer (our parent is the newly created machine);
- * just commit changes to filters */
- commitFilters = true;
- }
- }
- else
- {
- /* the list of filters itself is not changed,
- * just commit changes to filters themselves */
- commitFilters = true;
- }
-
- if (commitFilters)
- {
- DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
- while (it != m->llDeviceFilters->end())
- {
- (*it)->commit();
- ++it;
- }
- }
-#endif /* VBOX_WITH_USB */
}
/**
@@ -963,295 +364,56 @@ void USBController::copyFrom(USBController *aThat)
/* this will back up current data */
m->bd.assignCopy(aThat->m->bd);
-
-#ifdef VBOX_WITH_USB
-
- /* Note that we won't inform the USB proxy about new filters since the VM is
- * not running when we are here and therefore no need to do so */
-
- /* create private copies of all filters */
- m->llDeviceFilters.backup();
- m->llDeviceFilters->clear();
- for (DeviceFilterList::const_iterator it = aThat->m->llDeviceFilters->begin();
- it != aThat->m->llDeviceFilters->end();
- ++it)
- {
- ComObjPtr<USBDeviceFilter> filter;
- filter.createObject();
- filter->initCopy(this, *it);
- m->llDeviceFilters->push_back(filter);
- }
-
-#endif /* VBOX_WITH_USB */
}
-#ifdef VBOX_WITH_USB
-
/**
- * Called by setter methods of all USB device filters.
+ * Cancels sharing (if any) by making an independent copy of data.
+ * This operation also resets this object's peer to NULL.
*
- * @note Locks nothing.
+ * @note Locks this object for writing, together with the peer object
+ * represented by @a aThat (locked for reading).
*/
-HRESULT USBController::onDeviceFilterChange(USBDeviceFilter *aFilter,
- BOOL aActiveChanged /* = FALSE */)
+void USBController::unshare()
{
+ /* sanity */
AutoCaller autoCaller(this);
- AssertComRCReturnRC(autoCaller.rc());
+ AssertComRCReturnVoid (autoCaller.rc());
- /* we need the machine state */
- AutoAnyStateDependency adep(m->pParent);
- AssertComRCReturnRC(adep.rc());
-
- /* nothing to do if the machine isn't running */
- if (!Global::IsOnline(adep.machineState()))
- return S_OK;
+ /* sanity too */
+ AutoCaller peerCaller (m->pPeer);
+ AssertComRCReturnVoid (peerCaller.rc());
- /* we don't modify our data fields -- no need to lock */
+ /* peer is not modified, lock it for reading (m->pPeer is "master" so locked
+ * first) */
+ AutoReadLock rl(m->pPeer COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
- if ( aFilter->mInList
- && m->pParent->isRegistered())
+ if (m->bd.isShared())
{
- USBProxyService *service = m->pHost->usbProxyService();
- ComAssertRet(service, E_FAIL);
-
- if (aActiveChanged)
- {
- if (aFilter->getData().mRemote.isMatch(false))
- {
- /* insert/remove the filter from the proxy */
- if (aFilter->getData().mActive)
- {
- ComAssertRet(aFilter->getId() == NULL, E_FAIL);
- aFilter->getId() = service->insertFilter(&aFilter->getData().mUSBFilter);
- }
- else
- {
- ComAssertRet(aFilter->getId() != NULL, E_FAIL);
- service->removeFilter(aFilter->getId());
- aFilter->getId() = NULL;
- }
- }
- }
- else
- {
- if (aFilter->getData().mActive)
- {
- /* update the filter in the proxy */
- ComAssertRet(aFilter->getId() != NULL, E_FAIL);
- service->removeFilter(aFilter->getId());
- if (aFilter->getData().mRemote.isMatch(false))
- {
- aFilter->getId() = service->insertFilter(&aFilter->getData().mUSBFilter);
- }
- }
- }
- }
-
- return S_OK;
-}
-
-/**
- * Returns true if the given USB device matches to at least one of
- * this controller's USB device filters.
- *
- * A HostUSBDevice specific version.
- *
- * @note Locks this object for reading.
- */
-bool USBController::hasMatchingFilter(const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs)
-{
- AutoCaller autoCaller(this);
- AssertComRCReturn(autoCaller.rc(), false);
+ if (!m->bd.isBackedUp())
+ m->bd.backup();
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /* Disabled USB controllers cannot actually work with USB devices */
- if (!m->bd->fEnabled)
- return false;
-
- /* apply self filters */
- for (DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
- it != m->llDeviceFilters->end();
- ++it)
- {
- AutoWriteLock filterLock(*it COMMA_LOCKVAL_SRC_POS);
- if (aDevice->isMatch((*it)->getData()))
- {
- *aMaskedIfs = (*it)->getData().mMaskedIfs;
- return true;
- }
+ m->bd.commit();
}
- return false;
+ unconst(m->pPeer) = NULL;
}
-/**
- * Returns true if the given USB device matches to at least one of
- * this controller's USB device filters.
- *
- * A generic version that accepts any IUSBDevice on input.
- *
- * @note
- * This method MUST correlate with HostUSBDevice::isMatch()
- * in the sense of the device matching logic.
- *
- * @note Locks this object for reading.
- */
-bool USBController::hasMatchingFilter(IUSBDevice *aUSBDevice, ULONG *aMaskedIfs)
+const Utf8Str& USBController::getName() const
{
- LogFlowThisFuncEnter();
-
- AutoCaller autoCaller(this);
- AssertComRCReturn(autoCaller.rc(), false);
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /* Disabled USB controllers cannot actually work with USB devices */
- if (!m->bd->fEnabled)
- return false;
-
- HRESULT rc = S_OK;
-
- /* query fields */
- USBFILTER dev;
- USBFilterInit(&dev, USBFILTERTYPE_CAPTURE);
-
- USHORT vendorId = 0;
- rc = aUSBDevice->COMGETTER(VendorId)(&vendorId);
- ComAssertComRCRet(rc, false);
- ComAssertRet(vendorId, false);
- int vrc = USBFilterSetNumExact(&dev, USBFILTERIDX_VENDOR_ID, vendorId, true); AssertRC(vrc);
-
- USHORT productId = 0;
- rc = aUSBDevice->COMGETTER(ProductId)(&productId);
- ComAssertComRCRet(rc, false);
- vrc = USBFilterSetNumExact(&dev, USBFILTERIDX_PRODUCT_ID, productId, true); AssertRC(vrc);
-
- USHORT revision;
- rc = aUSBDevice->COMGETTER(Revision)(&revision);
- ComAssertComRCRet(rc, false);
- vrc = USBFilterSetNumExact(&dev, USBFILTERIDX_DEVICE, revision, true); AssertRC(vrc);
-
- Bstr manufacturer;
- rc = aUSBDevice->COMGETTER(Manufacturer)(manufacturer.asOutParam());
- ComAssertComRCRet(rc, false);
- if (!manufacturer.isEmpty())
- USBFilterSetStringExact(&dev, USBFILTERIDX_MANUFACTURER_STR, Utf8Str(manufacturer).c_str(), true);
-
- Bstr product;
- rc = aUSBDevice->COMGETTER(Product)(product.asOutParam());
- ComAssertComRCRet(rc, false);
- if (!product.isEmpty())
- USBFilterSetStringExact(&dev, USBFILTERIDX_PRODUCT_STR, Utf8Str(product).c_str(), true);
-
- Bstr serialNumber;
- rc = aUSBDevice->COMGETTER(SerialNumber)(serialNumber.asOutParam());
- ComAssertComRCRet(rc, false);
- if (!serialNumber.isEmpty())
- USBFilterSetStringExact(&dev, USBFILTERIDX_SERIAL_NUMBER_STR, Utf8Str(serialNumber).c_str(), true);
-
- Bstr address;
- rc = aUSBDevice->COMGETTER(Address)(address.asOutParam());
- ComAssertComRCRet(rc, false);
-
- USHORT port = 0;
- rc = aUSBDevice->COMGETTER(Port)(&port);
- ComAssertComRCRet(rc, false);
- USBFilterSetNumExact(&dev, USBFILTERIDX_PORT, port, true);
-
- BOOL remote = FALSE;
- rc = aUSBDevice->COMGETTER(Remote)(&remote);
- ComAssertComRCRet(rc, false);
- ComAssertRet(remote == TRUE, false);
-
- bool match = false;
-
- /* apply self filters */
- for (DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
- it != m->llDeviceFilters->end();
- ++it)
- {
- AutoWriteLock filterLock(*it COMMA_LOCKVAL_SRC_POS);
- const USBDeviceFilter::Data &aData = (*it)->getData();
-
- if (!aData.mActive)
- continue;
- if (!aData.mRemote.isMatch(remote))
- continue;
- if (!USBFilterMatch(&aData.mUSBFilter, &dev))
- continue;
-
- match = true;
- *aMaskedIfs = aData.mMaskedIfs;
- break;
- }
-
- LogFlowThisFunc(("returns: %d\n", match));
- LogFlowThisFuncLeave();
-
- return match;
+ return m->bd->strName;
}
-/**
- * Notifies the proxy service about all filters as requested by the
- * @a aInsertFilters argument.
- *
- * @param aInsertFilters @c true to insert filters, @c false to remove.
- *
- * @note Locks this object for reading.
- */
-HRESULT USBController::notifyProxy(bool aInsertFilters)
+USBControllerType_T USBController::getControllerType() const
{
- LogFlowThisFunc(("aInsertFilters=%RTbool\n", aInsertFilters));
-
- AutoCaller autoCaller(this);
- AssertComRCReturn(autoCaller.rc(), false);
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- USBProxyService *service = m->pHost->usbProxyService();
- AssertReturn(service, E_FAIL);
-
- DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
- while (it != m->llDeviceFilters->end())
- {
- USBDeviceFilter *flt = *it; /* resolve ambiguity (for ComPtr below) */
-
- /* notify the proxy (only if the filter is active) */
- if ( flt->getData().mActive
- && flt->getData().mRemote.isMatch(false) /* and if the filter is NOT remote */
- )
- {
- if (aInsertFilters)
- {
- AssertReturn(flt->getId() == NULL, E_FAIL);
- flt->getId() = service->insertFilter(&flt->getData().mUSBFilter);
- }
- else
- {
- /* It's possible that the given filter was not inserted the proxy
- * when this method gets called (as a result of an early VM
- * process crash for example. So, don't assert that ID != NULL. */
- if (flt->getId() != NULL)
- {
- service->removeFilter(flt->getId());
- flt->getId() = NULL;
- }
- }
- }
- ++it;
- }
-
- return S_OK;
+ return m->bd->enmType;
}
-Machine* USBController::getMachine()
+ComObjPtr<USBController> USBController::getPeer()
{
- return m->pParent;
+ return m->pPeer;
}
-#endif /* VBOX_WITH_USB */
-
// private methods
/////////////////////////////////////////////////////////////////////////////
/* vi: set tabstop=4 shiftwidth=4 expandtab: */