Exemplo n.º 1
0
/**
 * Performs the required actions when a device has been added.
 *
 * This means things like running filters and subsequent capturing and
 * VM attaching. This may result in IPC and temporary lock abandonment.
 *
 * @param   aDevice     The device in question.
 * @param   aUSBDevice  The USB device structure.
 */
void USBProxyService::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice,
                                  SessionMachinesList &llOpenedMachines,
                                  PUSBDEVICE aUSBDevice)
{
    /*
     * Validate preconditions.
     */
    AssertReturnVoid(!isWriteLockOnCurrentThread());
    AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid}\n",
                     (HostUSBDevice *)aDevice,
                     aDevice->getName().c_str(),
                     aDevice->getStateName(),
                     aDevice->getId().raw()));

    /*
     * Run filters on the device.
     */
    if (aDevice->isCapturableOrHeld())
    {
        devLock.release();
        HRESULT rc = runAllFiltersOnDevice(aDevice, llOpenedMachines, NULL /* aIgnoreMachine */);
        AssertComRC(rc);
    }

    NOREF(aUSBDevice);
}
Exemplo n.º 2
0
/**
 * Handle a device which state changed in some significant way.
 *
 * This means things like running filters and subsequent capturing and
 * VM attaching. This may result in IPC and temporary lock abandonment.
 *
 * @param   aDevice         The device.
 * @param   pllOpenedMachines list of running session machines (VirtualBox::getOpenedMachines()); if NULL, we don't run filters
 * @param   aIgnoreMachine  Machine to ignore when running filters.
 */
void USBProxyService::deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList *pllOpenedMachines, SessionMachine *aIgnoreMachine)
{
    /*
     * Validate preconditions.
     */
    AssertReturnVoid(!isWriteLockOnCurrentThread());
    AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid} aRunFilters=%RTbool aIgnoreMachine=%p\n",
                     (HostUSBDevice *)aDevice,
                     aDevice->getName().c_str(),
                     aDevice->getStateName(),
                     aDevice->getId().raw(),
                     (pllOpenedMachines != NULL),       // used to be "bool aRunFilters"
                     aIgnoreMachine));
    devLock.release();

    /*
     * Run filters if requested to do so.
     */
    if (pllOpenedMachines)
    {
        HRESULT rc = runAllFiltersOnDevice(aDevice, *pllOpenedMachines, aIgnoreMachine);
        AssertComRC(rc);
    }
}
/** Must be called from under this object's write lock. */
void MediumAttachment::i_updateEjected()
{
    Assert(isWriteLockOnCurrentThread());
    Assert(!m->pMachine->i_isSnapshotMachine());

    m->fIsEjected = true;
}
Exemplo n.º 4
0
void NetworkAdapter::updateBandwidthGroup(BandwidthGroup *aBwGroup)
{
    LogFlowThisFuncEnter();
    Assert(isWriteLockOnCurrentThread());

    ComObjPtr<BandwidthGroup> pOldBwGroup;
    if (!mData->mBandwidthGroup.isEmpty())
        {
            HRESULT hrc = mParent->getBandwidthGroup(mData->mBandwidthGroup, pOldBwGroup, false /* fSetError */);
            NOREF(hrc);
            Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
        }

    mData.backup();
    if (!pOldBwGroup.isNull())
    {
        pOldBwGroup->release();
        mData->mBandwidthGroup = Utf8Str::Empty;
    }

    if (aBwGroup)
    {
        mData->mBandwidthGroup = aBwGroup->getName();
        aBwGroup->reference();
    }

    LogFlowThisFuncLeave();
}
Exemplo n.º 5
0
/**
 * Runs the USB filters of the machine on the device.
 *
 * If a match is found we will request capture for VM. This may cause
 * us to temporary abandon locks while doing IPC.
 *
 * @param   aMachine    Machine whose filters are to be run.
 * @param   aDevice     The USB device in question.
 * @returns @c true if the device has been or is being attached to the VM, @c false otherwise.
 *
 * @note    Locks several objects temporarily for reading or writing.
 */
bool USBProxyService::runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice)
{
    LogFlowThisFunc(("{%s} aMachine=%p \n", aDevice->getName().c_str(), aMachine));

    /*
     * Validate preconditions.
     */
    AssertReturn(aMachine, false);
    AssertReturn(!isWriteLockOnCurrentThread(), false);
    AssertReturn(!aMachine->isWriteLockOnCurrentThread(), false);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
    /* Let HostUSBDevice::requestCaptureToVM() validate the state. */

    /*
     * Do the job.
     */
    ULONG ulMaskedIfs;
    if (aMachine->hasMatchingUSBFilter(aDevice, &ulMaskedIfs))
    {
        /* try to capture the device */
        HRESULT hrc = aDevice->requestCaptureForVM(aMachine, false /* aSetError */, ulMaskedIfs);
        return SUCCEEDED(hrc)
            || hrc == E_UNEXPECTED /* bad device state, give up */;
    }

    return false;
}
/** Must be called from under this object's write lock. */
void MediumAttachment::i_updateHotPluggable(bool aHotPluggable)
{
    Assert(isWriteLockOnCurrentThread());
    Assert(!m->pMachine->i_isSnapshotMachine());

    m->bd.backup();
    m->bd->mData.fHotPluggable = aHotPluggable;
}
/** Must be called from under this object's write lock. */
void MediumAttachment::i_updateDiscard(bool aDiscard)
{
    Assert(isWriteLockOnCurrentThread());
    Assert(!m->pMachine->i_isSnapshotMachine());

    m->bd.backup();
    m->bd->mData.fDiscard = aDiscard;
}
/** Must be called from under this object's write lock. */
void MediumAttachment::i_updateNonRotational(bool aNonRotational)
{
    Assert(isWriteLockOnCurrentThread());
    Assert(!m->pMachine->i_isSnapshotMachine());

    m->bd.backup();
    m->bd->mData.fNonRotational = aNonRotational;
}
/** Must be called from under this object's write lock. */
void MediumAttachment::i_updateTempEject(bool aTempEject)
{
    Assert(isWriteLockOnCurrentThread());
    Assert(!m->pMachine->i_isSnapshotMachine());

    m->bd.backup();
    m->bd->mData.fTempEject = aTempEject;
}
/** Must be called from under this object's write lock. */
void MediumAttachment::i_updatePassthrough(bool aPassthrough)
{
    Assert(isWriteLockOnCurrentThread());
    Assert(!m->pMachine->i_isSnapshotMachine());

    m->bd.backup();
    m->bd->mData.fPassThrough = aPassthrough;
}
/**
 * Sets the medium of this attachment and unsets the "implicit" flag.
 * @param aMedium
 */
void MediumAttachment::i_updateMedium(const ComObjPtr<Medium> &aMedium)
{
    Assert(isWriteLockOnCurrentThread());
    /* No assertion for a snapshot. Method used in deleting snapshot. */

    m->bd.backup();
    m->bd->pMedium = aMedium;
    m->bd->fImplicit = false;
    m->fIsEjected = false;
}
void MediumAttachment::i_updateBandwidthGroup(const Utf8Str &aBandwidthGroup)
{
    LogFlowThisFuncEnter();
    Assert(isWriteLockOnCurrentThread());
    Assert(!m->pMachine->i_isSnapshotMachine());

    m->bd.backup();
    m->bd->mData.strBwGroup = aBandwidthGroup;

    LogFlowThisFuncLeave();
}
/** Must be called from under this object's write lock. */
void MediumAttachment::i_updateName(const Utf8Str &aName)
{
    Assert(isWriteLockOnCurrentThread());
    Assert(!m->pMachine->i_isSnapshotMachine());

    m->bd.backup();
    unconst(m->bd->strControllerName) = aName;

    /* Construct a short log name for this attachment. */
    i_updateLogName();
}
Exemplo n.º 14
0
/**
 * Gets the collection of USB devices, slave of Host::USBDevices.
 *
 * This is an interface for the HostImpl::USBDevices property getter.
 *
 *
 * @param   aUSBDevices     Where to store the pointer to the collection.
 *
 * @returns COM status code.
 *
 * @remarks The caller must own the write lock of the host object.
 */
HRESULT USBProxyService::getDeviceCollection(ComSafeArrayOut(IHostUSBDevice *, aUSBDevices))
{
    AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
    CheckComArgOutSafeArrayPointerValid(aUSBDevices);

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    SafeIfaceArray<IHostUSBDevice> Collection(mDevices);
    Collection.detachTo(ComSafeArrayOutArg(aUSBDevices));

    return S_OK;
}
Exemplo n.º 15
0
int USBProxyBackendUsbIp::interruptWait(void)
{
    AssertReturn(!isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);

    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);

    int rc = RTPipeWriteBlocking(m->hWakeupPipeW, "", 1, NULL);
    if (RT_SUCCESS(rc))
        RTPipeFlush(m->hWakeupPipeW);
    LogFlowFunc(("returning %Rrc\n", rc));
    return rc;
}
/**
 * Gets the collection of USB devices, slave of Host::USBDevices.
 *
 * This is an interface for the HostImpl::USBDevices property getter.
 *
 *
 * @param   aUSBDevices     Where to store the pointer to the collection.
 *
 * @returns COM status code.
 *
 * @remarks The caller must own the write lock of the host object.
 */
HRESULT USBProxyService::getDeviceCollection(std::vector<ComPtr<IHostUSBDevice> > &aUSBDevices)
{
    AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    aUSBDevices.resize(mDevices.size());
    size_t i = 0;
    for (HostUSBDeviceList::const_iterator it = mDevices.begin(); it != mDevices.end(); ++it, ++i)
        aUSBDevices[i] = *it;

    return S_OK;
}
Exemplo n.º 17
0
/**
 *  Validates COMSETTER(Path) arguments.
 */
HRESULT SerialPort::i_checkSetPath(const Utf8Str &str)
{
    AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);

    if (    (    m->bd->portMode == PortMode_HostDevice
              || m->bd->portMode == PortMode_HostPipe
              || m->bd->portMode == PortMode_RawFile
            ) && str.isEmpty()
       )
        return setError(E_INVALIDARG,
                        tr("Path of the serial port %d may not be empty or null in "
                           "host pipe or host device mode"),
                        m->bd->ulSlot);

    return S_OK;
}
Exemplo n.º 18
0
int USBProxyBackendLinux::interruptWait(void)
{
    AssertReturn(!isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);

    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
#ifdef VBOX_USB_WITH_SYSFS
    LogFlowFunc(("mUsingUsbfsDevices=%d\n", mUsingUsbfsDevices));
    if (!mUsingUsbfsDevices)
    {
        mpWaiter->Interrupt();
        LogFlowFunc(("Returning VINF_SUCCESS\n"));
        return VINF_SUCCESS;
    }
#endif /* VBOX_USB_WITH_SYSFS */
    int rc = RTPipeWriteBlocking(mhWakeupPipeW, WAKE_UP_STRING, WAKE_UP_STRING_LEN, NULL);
    if (RT_SUCCESS(rc))
        RTPipeFlush(mhWakeupPipeW);
    LogFlowFunc(("returning %Rrc\n", rc));
    return rc;
}
Exemplo n.º 19
0
/**
 * Remove device notification hook for the OS specific code.
 *
 * This is means things like
 *
 * @param   aDevice     The device in question.
 */
void USBProxyService::deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice)
{
    /*
     * Validate preconditions.
     */
    AssertReturnVoid(!isWriteLockOnCurrentThread());
    AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
    AutoWriteLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid}\n",
                     (HostUSBDevice *)aDevice,
                     aDevice->getName().c_str(),
                     aDevice->getStateName(),
                     aDevice->getId().raw()));

    /*
     * Detach the device from any machine currently using it,
     * reset all data and uninitialize the device object.
     */
    devLock.release();
    aDevice->onPhysicalDetached();
}
Exemplo n.º 20
0
/**
 * Runs all the filters on the specified device.
 *
 * All filters mean global and active VM, with the exception of those
 * belonging to \a aMachine. If a global ignore filter matched or if
 * none of the filters matched, the device will be released back to
 * the host.
 *
 * The device calling us here will be in the HeldByProxy, Unused, or
 * Capturable state. The caller is aware that locks held might have
 * to be abandond because of IPC and that the device might be in
 * almost any state upon return.
 *
 *
 * @returns COM status code (only parameter & state checks will fail).
 * @param   aDevice         The USB device to apply filters to.
 * @param   aIgnoreMachine  The machine to ignore filters from (we've just
 *                          detached the device from this machine).
 *
 * @note    The caller is expected to own no locks.
 */
HRESULT USBProxyService::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice,
                                               SessionMachinesList &llOpenedMachines,
                                               SessionMachine *aIgnoreMachine)
{
    LogFlowThisFunc(("{%s} ignoring=%p\n", aDevice->getName().c_str(), aIgnoreMachine));

    /*
     * Verify preconditions.
     */
    AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), E_FAIL);
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    AutoWriteLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    AssertMsgReturn(aDevice->isCapturableOrHeld(), ("{%s} %s\n", aDevice->getName().c_str(), aDevice->getStateName()), E_FAIL);

    /*
     * Get the lists we'll iterate.
     */
    Host::USBDeviceFilterList globalFilters;

    mHost->getUSBFilters(&globalFilters);

    /*
     * Run global filters filters first.
     */
    bool fHoldIt = false;
    for (Host::USBDeviceFilterList::const_iterator it = globalFilters.begin();
         it != globalFilters.end();
         ++it)
    {
        AutoWriteLock filterLock(*it COMMA_LOCKVAL_SRC_POS);
        const HostUSBDeviceFilter::Data &data = (*it)->getData();
        if (aDevice->isMatch(data))
        {
            USBDeviceFilterAction_T action = USBDeviceFilterAction_Null;
            (*it)->COMGETTER(Action)(&action);
            if (action == USBDeviceFilterAction_Ignore)
            {
                /*
                 * Release the device to the host and we're done.
                 */
                filterLock.release();
                devLock.release();
                alock.release();
                aDevice->requestReleaseToHost();
                return S_OK;
            }
            if (action == USBDeviceFilterAction_Hold)
            {
                /*
                 * A device held by the proxy needs to be subjected
                 * to the machine filters.
                 */
                fHoldIt = true;
                break;
            }
            AssertMsgFailed(("action=%d\n", action));
        }
    }
    globalFilters.clear();

    /*
     * Run the per-machine filters.
     */
    for (SessionMachinesList::const_iterator it = llOpenedMachines.begin();
         it != llOpenedMachines.end();
         ++it)
    {
        ComObjPtr<SessionMachine> pMachine = *it;

        /* Skip the machine the device was just detached from. */
        if (    aIgnoreMachine
            &&  pMachine == aIgnoreMachine)
            continue;

        /* runMachineFilters takes care of checking the machine state. */
        devLock.release();
        alock.release();
        if (runMachineFilters(pMachine, aDevice))
        {
            LogFlowThisFunc(("{%s} attached to %p\n", aDevice->getName().c_str(), (void *)pMachine));
            return S_OK;
        }
        alock.acquire();
        devLock.acquire();
    }

    /*
     * No matching machine, so request hold or release depending
     * on global filter match.
     */
    devLock.release();
    alock.release();
    if (fHoldIt)
        aDevice->requestHold();
    else
        aDevice->requestReleaseToHost();
    return S_OK;
}