/** * 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); }
/** * 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; }
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(); }
/** * 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(); }
/** * 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; }
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; }
/** * 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; }
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; }
/** * 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(); }
/** * 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; }