Changeset 3001 in vbox
- Timestamp:
- Jun 3, 2007 7:29:42 PM (18 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
r2980 r3001 486 486 gfGuestCapsLockPressed = fCapsLock; 487 487 gfGuestScrollLockPressed = fScrollLock; 488 return S_OK; 489 } 490 491 STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *device, BOOL attached, 492 IVirtualBoxErrorInfo *message) 493 { 488 494 return S_OK; 489 495 } -
trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp
r2981 r3001 383 383 new ModifierKeyChangeEvent (fNumLock, fCapsLock, 384 384 fScrollLock)); 385 return S_OK; 386 } 387 388 STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *device, BOOL attached, 389 IVirtualBoxErrorInfo *error) 390 { 391 Q_UNUSED (device); 392 Q_UNUSED (attached); 393 Q_UNUSED (error); 394 395 /// @todo update menu entries 396 385 397 return S_OK; 386 398 } -
trunk/src/VBox/Main/ConsoleImpl.cpp
r2981 r3001 1946 1946 tr ("The virtual machine does not have a USB controller")); 1947 1947 1948 PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG) pBase-> 1949 pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG); 1950 ComAssertRet (pRhConfig, E_FAIL); 1951 1952 /// @todo (dmik) REMOTE_USB 1953 // when remote USB devices are ready, first search for a device with the 1954 // given UUID in mRemoteUSBDevices. If found, request a capture from 1955 // a remote client. If not found, search it on the local host as done below 1956 1957 /* 1958 * Try attach the given host USB device (a proper errror message should 1959 * be returned in case of error). 1960 */ 1961 ComPtr <IUSBDevice> hostDevice; 1962 HRESULT hrc = mControl->CaptureUSBDevice (aId, hostDevice.asOutParam()); 1963 CheckComRCReturnRC (hrc); 1964 1965 return attachUSBDevice (hostDevice, true /* aManual */, pRhConfig); 1948 /* Request the device capture */ 1949 HRESULT rc = mControl->CaptureUSBDevice (aId); 1950 CheckComRCReturnRC (rc); 1951 1952 return rc; 1966 1953 } 1967 1954 … … 1991 1978 if (!device) 1992 1979 return setError (E_INVALIDARG, 1993 tr ("Cannot detach the USB device (UUID: %s) as it is not attached here."), 1994 Guid (aId).toString().raw()); 1995 1996 /* protect mpVM */ 1997 AutoVMCaller autoVMCaller (this); 1998 CheckComRCReturnRC (autoVMCaller.rc()); 1999 2000 PPDMIBASE pBase = NULL; 2001 int vrc = PDMR3QueryLun (mpVM, "usb-ohci", 0, 0, &pBase); 2002 2003 /* if the device is attached, then there must be a USB controller */ 2004 ComAssertRCRet (vrc, E_FAIL); 2005 2006 PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG) pBase-> 2007 pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG); 2008 ComAssertRet (pRhConfig, E_FAIL); 2009 2010 Guid Uuid(aId); 2011 2012 LogFlowThisFunc (("Detaching USB proxy device {%Vuuid}...\n", Uuid.raw())); 2013 2014 /* leave the lock before a VMR3* call (EMT will call us back)! */ 2015 alock.leave(); 2016 2017 PVMREQ pReq = NULL; 2018 vrc = VMR3ReqCall (mpVM, &pReq, RT_INDEFINITE_WAIT, 2019 (PFNRT) usbDetachCallback, 5, 2020 this, &it, true /* aManual */, pRhConfig, Uuid.raw()); 2021 if (VBOX_SUCCESS (vrc)) 2022 vrc = pReq->iStatus; 2023 VMR3ReqFree (pReq); 2024 2025 HRESULT hrc = S_OK; 2026 2027 if (VBOX_SUCCESS (vrc)) 2028 device.queryInterfaceTo (aDevice); 2029 else 2030 hrc = setError (E_FAIL, 2031 tr ("Error detaching the USB device. (Failed to destroy the USB proxy device: %Vrc)"), vrc); 2032 2033 return hrc; 1980 tr ("USB device with UUID {%Vuuid} is not attached to this machine"), 1981 Guid (aId).raw()); 1982 1983 /* Request the device release */ 1984 HRESULT rc = mControl->ReleaseUSBDevice (aId); 1985 CheckComRCReturnRC (rc); 1986 1987 return rc; 2034 1988 } 2035 1989 … … 3221 3175 * @note Locks this object for writing. 3222 3176 */ 3223 HRESULT Console::onUSBDeviceAttach (IUSBDevice *aDevice )3224 { 3225 LogFlowThisFunc (("aDevice=%p \n", aDevice));3177 HRESULT Console::onUSBDeviceAttach (IUSBDevice *aDevice, IVirtualBoxErrorInfo *aError) 3178 { 3179 LogFlowThisFunc (("aDevice=%p aError=%p\n", aDevice, aError)); 3226 3180 3227 3181 AutoCaller autoCaller (this); … … 3236 3190 mMachineState)); 3237 3191 return E_FAIL; 3192 } 3193 3194 if (aError != NULL) 3195 { 3196 /* notify callback about an error */ 3197 onUSBDeviceStateChange (aDevice, true /* aAttached */, aError); 3198 return S_OK; 3238 3199 } 3239 3200 … … 3255 3216 ComAssertRet (pRhConfig, E_FAIL); 3256 3217 3257 return attachUSBDevice (aDevice, false /* aManual */, pRhConfig); 3218 /// @todo notify listeners of IConsoleCallback in case of error 3219 return attachUSBDevice (aDevice, pRhConfig); 3258 3220 } 3259 3221 … … 3264 3226 * @note Locks this object for writing. 3265 3227 */ 3266 HRESULT Console::onUSBDeviceDetach (INPTR GUIDPARAM aId) 3228 HRESULT Console::onUSBDeviceDetach (INPTR GUIDPARAM aId, 3229 IVirtualBoxErrorInfo *aError) 3267 3230 { 3268 3231 Guid Uuid (aId); 3269 LogFlowThisFunc (("aId={%Vuuid} \n", Uuid.raw()));3232 LogFlowThisFunc (("aId={%Vuuid} aError=%p\n", Uuid.raw(), aError)); 3270 3233 3271 3234 AutoCaller autoCaller (this); … … 3302 3265 } 3303 3266 3267 if (aError != NULL) 3268 { 3269 /* notify callback about an error */ 3270 onUSBDeviceStateChange (device, false /* aAttached */, aError); 3271 return S_OK; 3272 } 3273 3304 3274 /* protect mpVM */ 3305 3275 AutoVMCaller autoVMCaller (this); … … 3324 3294 vrc = VMR3ReqCall (mpVM, &pReq, RT_INDEFINITE_WAIT, 3325 3295 (PFNRT) usbDetachCallback, 5, 3326 this, &it, false /* aManual */,pRhConfig, Uuid.raw());3296 this, &it, pRhConfig, Uuid.raw()); 3327 3297 if (VBOX_SUCCESS (vrc)) 3328 3298 vrc = pReq->iStatus; … … 3331 3301 AssertRC (vrc); 3332 3302 3303 /// @todo notify listeners of IConsoleCallback in case of error 3333 3304 return VBOX_SUCCESS (vrc) ? S_OK : E_FAIL; 3334 3305 } … … 3520 3491 while (it != mCallbacks.end()) 3521 3492 (*it++)->OnKeyboardLedsChange(fNumLock, fCapsLock, fScrollLock); 3493 } 3494 3495 /** 3496 * @note Locks this object for reading. 3497 */ 3498 void Console::onUSBDeviceStateChange (IUSBDevice *aDevice, bool aAttached, 3499 IVirtualBoxErrorInfo *aError) 3500 { 3501 AutoCaller autoCaller (this); 3502 AssertComRCReturnVoid (autoCaller.rc()); 3503 3504 AutoReaderLock alock (this); 3505 3506 CallbackList::iterator it = mCallbacks.begin(); 3507 while (it != mCallbacks.end()) 3508 (*it++)->OnUSBDeviceStateChange (aDevice, aAttached, aError); 3522 3509 } 3523 3510 … … 4188 4175 * mUSBDevices collection. 4189 4176 * 4190 * If \a aManual is true and a failure occures, the given device4191 * will be returned back to the USB proxy manager.4192 *4193 4177 * @param aHostDevice device to attach 4194 * @param aManual true if device is being manually attached4195 4178 * 4196 4179 * @note Locks this object for writing. 4197 4180 * @note Synchronously calls EMT. 4198 4181 */ 4199 HRESULT Console::attachUSBDevice (IUSBDevice *aHostDevice, bool aManual, 4200 PVUSBIRHCONFIG aConfig) 4182 HRESULT Console::attachUSBDevice (IUSBDevice *aHostDevice, PVUSBIRHCONFIG aConfig) 4201 4183 { 4202 4184 AssertReturn (aHostDevice && aConfig, E_FAIL); … … 4262 4244 LogWarningThisFunc (("Failed to create proxy device for '%s' {%Vuuid} (%Vrc)\n", 4263 4245 Address.raw(), Uuid.ptr(), vrc)); 4264 4265 if (aManual)4266 {4267 /*4268 * Neither SessionMachine::ReleaseUSBDevice() nor Host::releaseUSBDevice()4269 * should call the Console back, so keep the lock to provide atomicity4270 * (to protect Host reapplying USB filters)4271 */4272 hrc = mControl->ReleaseUSBDevice (Uuid);4273 AssertComRC (hrc);4274 }4275 4246 4276 4247 switch (vrc) … … 4348 4319 that->mUSBDevices.push_back (device); 4349 4320 LogFlowFunc (("Attached device {%Vuuid}\n", device->id().raw())); 4321 4322 /* notify callbacks */ 4323 that->onUSBDeviceStateChange (device, true /* aAttached */, NULL); 4350 4324 } 4351 4325 … … 4367 4341 DECLCALLBACK(int) 4368 4342 Console::usbDetachCallback (Console *that, USBDeviceList::iterator *aIt, 4369 bool aManual,PVUSBIRHCONFIG aConfig, PCRTUUID aUuid)4343 PVUSBIRHCONFIG aConfig, PCRTUUID aUuid) 4370 4344 { 4371 4345 LogFlowFuncEnter(); … … 4401 4375 LogFlowFunc (("Detached device {%Vuuid}\n", (**aIt)->id().raw())); 4402 4376 4403 /// @todo (dmik) REMOTE_USB 4404 // if the device is remote, notify a remote client that we have 4405 // detached the device 4406 4407 /* If it's a manual detach, give it back to the USB Proxy */ 4408 if (aManual) 4409 { 4410 /* 4411 * Neither SessionMachine::ReleaseUSBDevice() nor Host::releaseUSBDevice() 4412 * should call the Console back, so keep the lock to provide atomicity 4413 * (to protect Host reapplying USB filters) 4414 */ 4415 LogFlowFunc (("Giving it back it to USB proxy...\n")); 4416 HRESULT hrc = that->mControl->ReleaseUSBDevice (Guid (*aUuid)); 4417 AssertComRC (hrc); 4418 vrc = SUCCEEDED (hrc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; 4419 } 4377 /* notify callbacks */ 4378 that->onUSBDeviceStateChange (**aIt, false /* aAttached */, NULL); 4420 4379 } 4421 4380 … … 6206 6165 6207 6166 /** 6208 * Captures and attaches USB devices to a newly created VM. 6167 * Captures USB devices that match filters of the VM. 6168 * Called at VM startup. 6209 6169 * 6210 6170 * @param pVM The VM handle. … … 6219 6179 ComAssertRet (isLockedOnCurrentThread(), E_FAIL); 6220 6180 6221 /* 6222 * If the machine has an USB controller, capture devices and attach 6223 * them to it. 6224 */ 6181 /* If the machine has an USB controller, ask the USB proxy service to 6182 * capture devices */ 6225 6183 PPDMIBASE pBase; 6226 6184 int vrc = PDMR3QueryLun (pVM, "usb-ohci", 0, 0, &pBase); 6227 6185 if (VBOX_SUCCESS (vrc)) 6228 6186 { 6229 PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG) pBase-> 6230 pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG); 6231 ComAssertRet (pRhConfig, E_FAIL); 6232 6233 /* 6234 * Get the list of USB devices that should be captured and attached to 6235 * the newly created machine. 6236 */ 6237 ComPtr <IUSBDeviceCollection> coll; 6238 HRESULT hrc = mControl->AutoCaptureUSBDevices (coll.asOutParam()); 6187 HRESULT hrc = mControl->AutoCaptureUSBDevices(); 6239 6188 ComAssertComRCRetRC (hrc); 6240 6241 /*6242 * Enumerate the devices and attach them.6243 * Failing to attach an device is currently ignored and the device6244 * released.6245 */6246 ComPtr <IUSBDeviceEnumerator> en;6247 hrc = coll->Enumerate (en.asOutParam());6248 ComAssertComRCRetRC (hrc);6249 6250 BOOL hasMore = FALSE;6251 while (SUCCEEDED (en->HasMore (&hasMore)) && hasMore)6252 {6253 ComPtr <IUSBDevice> hostDevice;6254 hrc = en->GetNext (hostDevice.asOutParam());6255 ComAssertComRCRetRC (hrc);6256 ComAssertRet (!hostDevice.isNull(), E_FAIL);6257 6258 hrc = attachUSBDevice (hostDevice, true /* aManual */, pRhConfig);6259 6260 /// @todo (r=dmik) warning reporting subsystem6261 }6262 6189 } 6263 6190 else if ( vrc == VERR_PDM_DEVICE_NOT_FOUND … … 6391 6318 if (fMatched) 6392 6319 { 6393 hrc = onUSBDeviceAttach (device);6320 hrc = onUSBDeviceAttach (device, NULL); 6394 6321 6395 6322 /// @todo (r=dmik) warning reporting subsystem … … 6457 6384 Guid uuid; 6458 6385 device->COMGETTER (Id) (uuid.asOutParam()); 6459 onUSBDeviceDetach (uuid );6386 onUSBDeviceDetach (uuid, NULL); 6460 6387 } 6461 6388 -
trunk/src/VBox/Main/HostImpl.cpp
r2981 r3001 110 110 HRESULT Host::init (VirtualBox *parent) 111 111 { 112 LogFlow Member(("Host::init():isReady=%d\n", isReady()));112 LogFlowThisFunc (("isReady=%d\n", isReady())); 113 113 114 114 ComAssertRet (parent, E_INVALIDARG); … … 142 142 void Host::uninit() 143 143 { 144 LogFlow Member(("Host::uninit():isReady=%d\n", isReady()));144 LogFlowThisFunc (("isReady=%d\n", isReady())); 145 145 146 146 AssertReturn (isReady(), (void) 0); 147 147 148 // uninit all USB device filters still referenced by clients 148 /* wait for USB proxy service to terminate before we uninit all USB 149 * devices */ 150 LogFlowThisFunc (("Stopping USB proxy service...\n")); 151 delete mUSBProxyService; 152 LogFlowThisFunc (("Done stopping USB proxy service.\n")); 153 mUSBProxyService = NULL; 154 155 /* uninit all USB device filters still referenced by clients */ 149 156 uninitDependentChildren(); 150 151 delete mUSBProxyService;152 mUSBProxyService = NULL;153 157 154 158 mUSBDeviceFilters.clear(); … … 1202 1206 1203 1207 /** 1204 * Marks the given host USB device as captured by the given machine and returns 1205 * it as IUSBDevice to the caller. 1208 * Requests the USB proxy service to capture the given host USB device. 1209 * 1210 * When the request is completed, 1211 * IInternalSessionControl::onUSBDeviceAttach() will be called on the given 1212 * machine object. 1206 1213 * 1207 1214 * Called by Console from the VM process (throug IInternalMachineControl). 1208 1215 * Must return extended error info in case of errors. 1209 1216 */ 1210 HRESULT Host::captureUSBDevice (SessionMachine *aMachine, INPTR GUIDPARAM aId, 1211 IUSBDevice **aHostDevice) 1217 HRESULT Host::captureUSBDevice (SessionMachine *aMachine, INPTR GUIDPARAM aId) 1212 1218 { 1213 1219 ComAssertRet (aMachine, E_INVALIDARG); 1214 ComAssertRet (aHostDevice, E_POINTER);1215 1220 1216 1221 AutoLock lock (this); … … 1230 1235 if (!device) 1231 1236 return setError (E_INVALIDARG, 1232 tr ("USB device with UUID {% s} is not currently attached to the host"),1233 id. toString().raw());1237 tr ("USB device with UUID {%Vuuid} is not currently attached to the host"), 1238 id.raw()); 1234 1239 1235 1240 AutoLock devLock (device); 1241 1242 if (device->isStatePending()) 1243 return setError (E_INVALIDARG, 1244 tr ("USB device '%s' with UUID {%Vuuid} is busy (waiting for a pending " 1245 "state change). Please try later"), 1246 device->name().raw(), id.raw()); 1236 1247 1237 1248 if (device->state() == USBDeviceState_USBDeviceNotSupported) 1238 1249 return setError (E_INVALIDARG, 1239 tr ("USB device '%s' with UUID {% s} cannot be accessed by guest "1250 tr ("USB device '%s' with UUID {%Vuuid} cannot be accessed by guest " 1240 1251 "computers"), 1241 device->name().raw(), id. toString().raw());1252 device->name().raw(), id.raw()); 1242 1253 1243 1254 if (device->state() == USBDeviceState_USBDeviceUnavailable) 1244 1255 return setError (E_INVALIDARG, 1245 tr ("USB device '%s' with UUID {% s} is being exclusively used by the "1256 tr ("USB device '%s' with UUID {%Vuuid} is being exclusively used by the " 1246 1257 "host computer"), 1247 device->name().raw(), id. toString().raw());1258 device->name().raw(), id.raw()); 1248 1259 1249 1260 if (device->state() == USBDeviceState_USBDeviceCaptured) 1250 1261 return setError (E_INVALIDARG, 1251 tr ("USB device '%s' with UUID {% s} is already captured by the virtual "1262 tr ("USB device '%s' with UUID {%Vuuid} is already captured by the virtual " 1252 1263 "machine '%ls'"), 1253 device->name().raw(), id. toString().raw(),1264 device->name().raw(), id.raw(), 1254 1265 aMachine->userData()->mName.raw()); 1255 1266 1256 // try capture the device 1257 bool ok = device->setCaptured (aMachine); 1258 if (!ok) 1259 { 1260 if (device->state() == USBDeviceState_USBDeviceBusy) 1261 return setError (E_FAIL, 1262 tr ("USB device with UUID {%s} is being accessed by the host " 1263 "computer and cannot be attached to the virtual machine." 1264 "Please try later"), 1265 id.toString().raw()); 1266 else 1267 ComAssertRet (ok, E_FAIL); 1268 } 1269 1270 // return the device to the caller as IUSBDevice 1271 device.queryInterfaceTo (aHostDevice); 1267 /* try to capture the device */ 1268 device->requestCapture (aMachine); 1269 1272 1270 return S_OK; 1273 1271 } … … 1277 1275 * machine the device is currently marked as captured by. 1278 1276 * 1277 * When the request is completed, 1278 * IInternalSessionControl::onUSBDeviceDetach() will be called on the given 1279 * machine object. 1280 * 1279 1281 * Called by Console from the VM process (throug IInternalMachineControl). 1280 1282 */ … … 1299 1301 AutoLock devLock (device); 1300 1302 1303 LogFlowThisFunc (("id={%Vuuid} state=%d isStatePending=%RTbool pendingState=%d\n", 1304 device->id().raw(), device->state(), device->isStatePending(), 1305 device->pendingState())); 1306 1307 if (device->isStatePending()) 1308 return setError (E_INVALIDARG, 1309 tr ("USB device '%s' with UUID {%Vuuid} is busy (waiting for a pending " 1310 "state change). Please try later"), 1311 device->name().raw(), device->id().raw()); 1312 1301 1313 ComAssertRet (device->machine() == aMachine, E_FAIL); 1302 1314 1303 /* reset the device and apply filters */ 1304 int vrc = device->reset(); 1305 ComAssertRCRet (vrc, E_FAIL); 1306 1307 HRESULT rc = applyAllUSBFilters (device, aMachine); 1315 /* re-apply filters on the device before giving it back to the host */ 1316 device->setHeld(); 1317 HRESULT rc = applyAllUSBFilters (device); 1308 1318 ComAssertComRC (rc); 1309 1319 … … 1312 1322 1313 1323 /** 1314 * Runs the filters of the given machine against all currently available USB 1315 * devices, marks those that match as captured and returns them as the colection 1316 * of IUSBDevice instances. 1324 * Asks the USB proxy service to capture all currently available USB devices 1325 * that match filters of the given machine. 1326 * 1327 * When the request is completed, 1328 * IInternalSessionControl::onUSBDeviceDetach() will be called on the given 1329 * machine object per every captured USB device. 1317 1330 * 1318 1331 * Called by Console from the VM process (through IInternalMachineControl) … … 1322 1335 * to the new locking scheme). 1323 1336 */ 1324 HRESULT Host::autoCaptureUSBDevices (SessionMachine *aMachine, 1325 IUSBDeviceCollection **aHostDevices) 1337 HRESULT Host::autoCaptureUSBDevices (SessionMachine *aMachine) 1326 1338 { 1327 1339 LogFlowThisFunc (("aMachine=%p\n", aMachine)); … … 1330 1342 CHECK_READY(); 1331 1343 1332 std::list <ComPtr <IUSBDevice> > list; 1333 1334 USBDeviceList::iterator it = mUSBDevices.begin(); 1335 while (it != mUSBDevices.end()) 1344 for (USBDeviceList::iterator it = mUSBDevices.begin(); 1345 it != mUSBDevices.end(); 1346 ++ it) 1336 1347 { 1337 1348 ComObjPtr <HostUSBDevice> device = *it; … … 1339 1350 AutoLock devLock (device); 1340 1351 1341 /// @todo remove 1342 #if 0 1343 if (device->isIgnored()) 1352 /* skip pending devices */ 1353 if (device->isStatePending()) 1344 1354 continue; 1345 #endif1346 1355 1347 1356 if (device->state() == USBDeviceState_USBDeviceBusy || … … 1350 1359 { 1351 1360 applyMachineUSBFilters (aMachine, device); 1352 1353 if (device->state() == USBDeviceState_USBDeviceCaptured) 1354 { 1355 /* put the device to the return list */ 1356 ComPtr <IUSBDevice> d; 1357 device.queryInterfaceTo (d.asOutParam()); 1358 Assert (!d.isNull()); 1359 list.push_back (d); 1360 } 1361 } 1362 ++ it; 1363 } 1364 1365 ComObjPtr <IfaceUSBDeviceCollection> coll; 1366 coll.createObject(); 1367 coll->init (list); 1368 coll.queryInterfaceTo (aHostDevices); 1361 } 1362 } 1369 1363 1370 1364 return S_OK; … … 1396 1390 if (device->machine() == aMachine) 1397 1391 { 1398 /* reset the device and apply filters */ 1399 device->reset(); 1400 HRESULT rc = applyAllUSBFilters (device, aMachine); 1401 ComAssertComRC (rc); 1392 if (!device->isStatePending()) 1393 { 1394 Assert (device->state() == USBDeviceState_USBDeviceCaptured); 1395 1396 /* re-apply filters on the device before giving it back to the 1397 * host */ 1398 device->setHeld(); 1399 HRESULT rc = applyAllUSBFilters (device); 1400 AssertComRC (rc); 1401 } 1402 else 1403 { 1404 device->cancelPendingState(); 1405 } 1402 1406 } 1403 1407 ++ it; … … 1833 1837 1834 1838 /** 1835 * Runs through all global filters to determine the state of the given1836 * USB device, then unless ignored, runs trhough filters of all running machines1837 * (excluding the given one) to automatically capture the device when there is a1838 * match (the state of the device will be set to USBDeviceCaptured if so, and1839 * the machine's process will be informed about the auto-capture).1840 * 1841 * @param aDevice USB device to set state for1842 * @param a Machine the machine whose filters are to be excluded (can be NULL)1843 * 1844 * @note the method must be called from under this object's lock1845 * /1846 HRESULT Host::applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice, 1847 SessionMachine *aMachine /* = NULL */)1839 * Applies all (golbal and VM) filters to the given USB device. The device 1840 * must be either a newly attached device or a device released by a VM. 1841 * 1842 * This method will request the USB proxy service to release the device (give 1843 * it back to the host) if none of the global or VM filters want to capture 1844 * the device. 1845 * 1846 * @param aDevice USB device to apply filters to. 1847 * 1848 * @note the method must be called from under this object's write lock and 1849 * from the aDevice's write lock. 1850 */ 1851 HRESULT Host::applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice) 1848 1852 { 1849 1853 LogFlowThisFunc (("\n")); 1850 1854 1855 /// @todo must check for read lock, it's enough here 1851 1856 AssertReturn (isLockedOnCurrentThread(), E_FAIL); 1852 1857 1853 AutoLock devLock (aDevice); 1858 AssertReturn (aDevice->isLockedOnCurrentThread(), E_FAIL); 1859 1860 AssertReturn (aDevice->state() != USBDeviceState_USBDeviceCaptured, E_FAIL); 1861 1862 AssertReturn (aDevice->isStatePending() == false, E_FAIL); 1854 1863 1855 1864 /* ignore unsupported devices */ … … 1863 1872 mParent->getOpenedMachines (machines); 1864 1873 1874 /// @todo it may be better to take a copy of filters to iterate and leave 1875 /// the host lock before calling HostUSBDevice:requestCapture() (which 1876 /// calls the VM process). 1877 1865 1878 /* apply global filters */ 1866 1879 USBDeviceFilterList::const_iterator it = mUSBDeviceFilters.begin(); 1867 while (it != mUSBDeviceFilters.end())1880 for (; it != mUSBDeviceFilters.end(); ++ it) 1868 1881 { 1869 1882 AutoLock filterLock (*it); … … 1872 1885 { 1873 1886 if (data.mAction == USBDeviceFilterAction_USBDeviceFilterIgnore) 1887 { 1888 /* request to give the device back to the host*/ 1889 aDevice->requestRelease(); 1890 /* nothing to do any more */ 1874 1891 return S_OK; 1892 } 1875 1893 if (data.mAction == USBDeviceFilterAction_USBDeviceFilterHold) 1876 1894 break; 1877 1895 } 1878 ++ it;1879 1896 } 1880 1897 1881 1898 /* apply machine filters */ 1882 for (size_t i = 0; i < machines.size(); i++) 1883 { 1884 if (aMachine && machines [i] == aMachine) 1899 size_t i = 0; 1900 for (; i < machines.size(); ++ i) 1901 { 1902 /* skip the machine the device was just detached from */ 1903 if (aDevice->machine() && machines [i] == aDevice->machine()) 1885 1904 continue; 1886 1905 1887 applyMachineUSBFilters (machines [i], aDevice); 1888 1889 if (aDevice->state() == USBDeviceState_USBDeviceCaptured) 1890 { 1891 /* inform the VM process about the auto-capture */ 1892 ComPtr <IUSBDevice> d; 1893 aDevice.queryInterfaceTo (d.asOutParam()); 1894 1895 /* the VM process will query the object, so leave the lock */ 1896 devLock.leave(); 1897 1898 HRESULT rc = machines [i]->onUSBDeviceAttach (d); 1899 if (SUCCEEDED(rc)) 1900 return rc; 1901 1902 devLock.enter(); 1903 1904 /* the machine rejected it, continue applying filters. */ 1905 aDevice->reset(); 1906 } 1907 } 1908 1909 /* no machine filters were matched. 1910 * if no global filters were matched as well, release the device 1911 * to make it available on the host */ 1912 if ( it == mUSBDeviceFilters.end() 1913 && aDevice->state() == USBDeviceState_USBDeviceHeld) 1914 aDevice->setHostDriven(); 1915 /** @todo dmik, what about USBDeviceFilterHold??? */ 1906 if (applyMachineUSBFilters (machines [i], aDevice)) 1907 break; 1908 } 1909 1910 if (i == machines.size()) 1911 { 1912 /* no matched machine filters, check what to do */ 1913 if (it == mUSBDeviceFilters.end()) 1914 { 1915 /* no any filter matched at all */ 1916 /* request to give the device back to the host */ 1917 aDevice->requestRelease(); 1918 } 1919 else 1920 { 1921 /* there was a global Hold filter */ 1922 aDevice->requestHold(); 1923 } 1924 } 1925 1926 return S_OK; 1927 } 1928 1916 1929 /** 1917 * bird, everything's ok from what I see. if USBDeviceFilterHold filter was 1918 * matched, setHostDevice() will not (and should not) be called 1919 * (because it != mUSBDeviceFilters.end() in that case). 1920 */ 1921 1922 return S_OK; 1923 } 1924 1925 /** 1926 * Runs through filters of the given machine in order to automatically capture 1927 * the given USB device when there is a match (the state of the device will 1928 * be set to USBDeviceCaptured if so, but the machine's process will *NOT* be) 1929 * informed about the auto-capture). 1930 * 1931 * @param aMachine the machine whose filters are to be run 1932 * @param aDevice USB device, a candidate for auto-attaching 1930 * Runs through filters of the given machine and asks the USB proxy service 1931 * to capture the given USB device when there is a match. 1932 * 1933 * @param aMachine Machine whose filters are to be run. 1934 * @param aDevice USB device, a candidate for auto-capturing. 1935 * @return @c true if there was a match and @c false otherwise. 1936 * 1937 * @note the method must be called from under this object's write lock and 1938 * from the aDevice's write lock. 1933 1939 * 1934 1940 * @note Locks aMachine for reading. 1935 1941 */ 1936 voidHost::applyMachineUSBFilters (SessionMachine *aMachine,1942 bool Host::applyMachineUSBFilters (SessionMachine *aMachine, 1937 1943 ComObjPtr <HostUSBDevice> &aDevice) 1938 1944 { 1939 1945 LogFlowThisFunc (("\n")); 1940 1946 1941 AssertReturnVoid (isLockedOnCurrentThread()); 1942 AssertReturnVoid (aDevice->isLockedOnCurrentThread()); 1943 1944 AssertReturnVoid (aMachine); 1945 AssertReturnVoid (aDevice->state() != USBDeviceState_USBDeviceUnavailable); 1946 1947 /* We're going to use aMachine which is not our child/parent, add a caller */ 1948 AutoCaller autoCaller (aMachine); 1949 if (!autoCaller.isOk()) 1950 { 1951 /* silently return, the machine might be not running any more */ 1952 return; 1953 } 1954 1955 /* enter the machine's lock because we want to access its USB controller */ 1956 AutoReaderLock machineLock (aMachine); 1957 1958 if (aMachine->usbController()->hasMatchingFilter (aDevice)) 1959 { 1960 /* try capture the device */ 1961 bool ok = aDevice->setCaptured (aMachine); 1962 1963 /* 1964 * false is valid only when the state remains USBDeviceBusy meaning that 1965 * the device is currently busy (being accessed by the host) 1966 */ 1967 Assert (ok || aDevice->state() == USBDeviceState_USBDeviceBusy); 1968 NOREF (ok); 1969 } 1947 AssertReturn (aMachine, false); 1948 1949 /// @todo must check for read lock, it's enough here 1950 AssertReturn (isLockedOnCurrentThread(), false); 1951 1952 AssertReturn (aDevice->isLockedOnCurrentThread(), false); 1953 1954 AssertReturn (aDevice->state() != USBDeviceState_USBDeviceNotSupported, false); 1955 AssertReturn (aDevice->state() != USBDeviceState_USBDeviceUnavailable, false); 1956 1957 AssertReturn (aDevice->isStatePending() == false, false); 1958 1959 bool hasMatch = false; 1960 1961 { 1962 /* We're going to use aMachine which is not our child/parent, add a 1963 * caller */ 1964 AutoCaller autoCaller (aMachine); 1965 if (!autoCaller.isOk()) 1966 { 1967 /* silently return, the machine might be not running any more */ 1968 return false; 1969 } 1970 1971 /* enter the machine's lock because we want to access its USB controller */ 1972 AutoReaderLock machineLock (aMachine); 1973 hasMatch = aMachine->usbController()->hasMatchingFilter (aDevice); 1974 } 1975 1976 if (hasMatch) 1977 { 1978 /* try to capture the device */ 1979 return aDevice->requestCapture (aMachine); 1980 } 1981 1982 return hasMatch; 1970 1983 } 1971 1984 … … 1982 1995 AssertReturnVoid (aDevice); 1983 1996 1984 /// @todo (dmik) check locks 1985 AutoLock alock (this); 1986 1987 AutoLock devLock (aDevice); 1997 AssertReturnVoid (isLockedOnCurrentThread()); 1998 AssertReturnVoid (aDevice->isLockedOnCurrentThread()); 1999 2000 LogFlowThisFunc (("id={%Vuuid} state=%d isStatePending=%RTbool pendingState=%d\n", 2001 aDevice->id().raw(), aDevice->state(), aDevice->isStatePending(), 2002 aDevice->pendingState())); 2003 2004 Assert (aDevice->isStatePending() == false); 1988 2005 1989 2006 /* add to the collecion */ … … 1997 2014 1998 2015 /** 1999 * Called by USB proxy service (?)when the device is physically detached2016 * Called by USB proxy service when the device is physically detached 2000 2017 * from the host. 2001 2018 * … … 2008 2025 AssertReturnVoid (aDevice); 2009 2026 2010 /// @todo (dmik) check locks 2011 AutoLock alock (this); 2012 2013 AutoLock devLock (aDevice); 2027 AssertReturnVoid (isLockedOnCurrentThread()); 2028 AssertReturnVoid (aDevice->isLockedOnCurrentThread()); 2029 2030 LogFlowThisFunc (("id={%Vuuid} state=%d isStatePending=%RTbool pendingState=%d\n", 2031 aDevice->id().raw(), aDevice->state(), aDevice->isStatePending(), 2032 aDevice->pendingState())); 2014 2033 2015 2034 Guid id = aDevice->id(); … … 2032 2051 mUSBDevices.erase (it); 2033 2052 2034 if (device->machine()) 2035 { 2036 /* the device is captured by a machine, instruct it to release */ 2037 2038 devLock.leave(); 2039 alock.leave(); 2040 2041 HRESULT rc = device->machine()->onUSBDeviceDetach (device->id()); 2042 AssertComRC (rc); 2043 } 2053 /* reset all data */ 2054 device->reset(); 2044 2055 } 2045 2056 2046 2057 /** 2047 * Called by USB proxy service when the state of the host-driven device 2048 * has changed because of non proxy interaction. 2058 * Called by USB proxy service when the state of the device has changed 2059 * either because of the state change request or because of some external 2060 * interaction. 2049 2061 * 2050 2062 * @param aDevice The device in question. … … 2054 2066 LogFlowThisFunc (("aDevice=%p\n", aDevice)); 2055 2067 2056 /// @todo (dmik) check locks 2057 AutoLock alock (this); 2058 2059 /** @todo dmik, is there anything we should do here? For instance if the device now is available? */ 2068 AssertReturnVoid (aDevice); 2069 2070 AssertReturnVoid (isLockedOnCurrentThread()); 2071 AssertReturnVoid (aDevice->isLockedOnCurrentThread()); 2072 2073 LogFlowThisFunc (("id={%Vuuid} state=%d isStatePending=%RTbool pendingState=%d\n", 2074 aDevice->id().raw(), aDevice->state(), aDevice->isStatePending(), 2075 aDevice->pendingState())); 2076 2077 if (aDevice->isStatePending()) 2078 { 2079 /* it was a state change request */ 2080 aDevice->handlePendingStateChange(); 2081 } 2082 else 2083 { 2084 /* some external state change */ 2085 2086 /// @todo re-run all USB filters probably 2087 AssertFailed(); 2088 } 2060 2089 } 2061 2090 -
trunk/src/VBox/Main/HostUSBDeviceImpl.cpp
r2981 r3001 21 21 22 22 #include "HostUSBDeviceImpl.h" 23 #include "MachineImpl.h" 24 #include "VirtualBoxErrorInfoImpl.h" 23 25 #include "USBProxyService.h" 26 24 27 #include "Logging.h" 25 28 … … 96 99 break; 97 100 case USBDEVICESTATE_USED_BY_GUEST: 98 mState = USBDeviceState_USBDeviceCaptured; 101 /* @todo USBDEVICESTATE_USED_BY_GUEST seems not to be used 102 * anywhere in the proxy code; it's quite logical because the 103 * proxy doesn't know anything about guest VMs. */ 104 AssertFailedReturn (E_FAIL); 99 105 break; 100 106 } … … 104 110 /* Other data members */ 105 111 mIsStatePending = false; 106 /// @todo remove107 #if 0108 mIgnored = false;109 #endif110 112 mUSBProxyService = aUSBProxyService; 111 113 mUsb = aUsb; … … 339 341 } 340 342 341 /// @todo remove 342 #if 0 343 /** 344 * Sets the ignored flag and returns the device to the host. 345 * 346 * @note Locks this object for writing. 347 */ 348 void HostUSBDevice::setIgnored() 349 { 350 AutoCaller autoCaller (this); 351 AssertComRCReturnVoid (autoCaller.rc()); 352 353 AutoLock alock (this); 354 355 AssertReturnVoid (!mIgnored); 356 357 mIgnored = true; 358 359 setHostDriven(); 360 } 361 #endif 362 363 /** 364 * @note Locks this object for writing. 365 */ 366 bool HostUSBDevice::setCaptured (SessionMachine *aMachine) 367 { 343 /** 344 * Requests the USB proxy service to capture the device and sets the pending 345 * state to Captured. 346 * 347 * If the state change may be performed immediately (for example, Hold -> 348 * Captured), then the machine is informed before this method returns. 349 * 350 * @param aMachine Machine that will capture this device on success. 351 * @return @c false if the device could be immediately captured 352 * but the VM process refused to grab it; 353 * @c true otherwise. 354 * 355 * @note Must be called from under the object write lock. 356 * 357 * @note May lock the given machine object for reading. 358 */ 359 bool HostUSBDevice::requestCapture (SessionMachine *aMachine) 360 { 361 LogFlowThisFunc (("\n")); 362 368 363 AssertReturn (aMachine, false); 369 364 370 AutoCaller autoCaller (this); 371 AssertComRCReturn (autoCaller.rc(), false); 372 373 AutoLock alock (this); 365 AssertReturn (isLockedOnCurrentThread(), false); 366 367 AssertReturn (mIsStatePending == false, false); 374 368 375 369 AssertReturn ( … … 379 373 false); 380 374 381 mState = USBDeviceState_USBDeviceCaptured; 375 if (mState == USBDeviceState_USBDeviceHeld) 376 { 377 /* can perform immediate capture, inform the VM process */ 378 379 ComPtr <IUSBDevice> d = this; 380 381 mIsStatePending = true; 382 383 /* the VM process will query the object, so leave the lock */ 384 AutoLock alock (this); 385 alock.leave(); 386 387 LogFlowThisFunc (("Calling machine->onUSBDeviceAttach()...\n")); 388 389 HRESULT rc = aMachine->onUSBDeviceAttach (d, NULL); 390 391 LogFlowThisFunc (("Done machine->onUSBDeviceAttach()=%08X\n", rc)); 392 393 alock.enter(); 394 395 mIsStatePending = false; 396 397 if (SUCCEEDED (rc)) 398 { 399 mState = mPendingState = USBDeviceState_USBDeviceCaptured; 400 mMachine = aMachine; 401 return true; 402 } 403 404 return false; 405 } 406 407 mIsStatePending = true; 408 mPendingState = USBDeviceState_USBDeviceCaptured; 382 409 mMachine = aMachine; 383 410 … … 388 415 389 416 /** 390 * Returns the device back to the host 391 * 392 * @returns VBox status code. 393 * 394 * @note Locks this object for writing. 395 */ 396 int HostUSBDevice::setHostDriven() 397 { 398 AutoCaller autoCaller (this); 399 AssertComRCReturn (autoCaller.rc(), VERR_INVALID_PARAMETER); 400 401 AutoLock alock (this); 402 403 AssertReturn (mState == USBDeviceState_USBDeviceHeld, VERR_INVALID_PARAMETER); 404 405 mState = USBDeviceState_USBDeviceAvailable; 406 407 return mUSBProxyService->releaseDevice (this); 408 } 409 410 /** 411 * Resets the device as if it were just attached to the host 412 * 413 * @returns VBox status code. 414 * 415 * @note Locks this object for writing. 416 */ 417 int HostUSBDevice::reset() 418 { 419 AutoCaller autoCaller (this); 420 AssertComRCReturn (autoCaller.rc(), VERR_INVALID_PARAMETER); 421 422 AutoLock alock (this); 417 * Requests the USB proxy service to release the device and sets the pending 418 * state to Available. 419 * 420 * If the state change may be performed immediately (for example, the current 421 * state is Busy), this method does nothing. 422 * 423 * @note Must be called from under the object write lock. 424 */ 425 void HostUSBDevice::requestRelease() 426 { 427 LogFlowThisFunc (("\n")); 428 429 AssertReturnVoid (isLockedOnCurrentThread()); 430 431 AssertReturnVoid (mIsStatePending == false); 432 433 AssertReturnVoid ( 434 mState == USBDeviceState_USBDeviceBusy || 435 mState == USBDeviceState_USBDeviceAvailable || 436 mState == USBDeviceState_USBDeviceHeld); 437 438 if (mState != USBDeviceState_USBDeviceHeld) 439 return; 440 441 mIsStatePending = true; 442 mPendingState = USBDeviceState_USBDeviceAvailable; 443 444 mUSBProxyService->releaseDevice (this); 445 } 446 447 /** 448 * Requests the USB proxy service to release the device, sets the pending 449 * state to Held and removes the machine association if any. 450 * 451 * If the state change may be performed immediately (for example, the current 452 * state is already Held), this method does nothing but removes the machine 453 * association. 454 * 455 * @note Must be called from under the object write lock. 456 */ 457 void HostUSBDevice::requestHold() 458 { 459 LogFlowThisFunc (("\n")); 460 461 AssertReturnVoid (isLockedOnCurrentThread()); 462 463 AssertReturnVoid (mIsStatePending == false); 464 465 AssertReturnVoid ( 466 mState == USBDeviceState_USBDeviceBusy || 467 mState == USBDeviceState_USBDeviceAvailable || 468 mState == USBDeviceState_USBDeviceHeld); 469 470 mMachine.setNull(); 471 472 if (mState == USBDeviceState_USBDeviceHeld) 473 return; 474 475 mIsStatePending = true; 476 mPendingState = USBDeviceState_USBDeviceHeld; 477 478 mUSBProxyService->captureDevice (this); 479 } 480 481 /** 482 * Sets the device state from Captured to Held and preserves the machine 483 * association (if any). Usually called before applying filters. 484 * 485 * @note Must be called from under the object write lock. 486 */ 487 void HostUSBDevice::setHeld() 488 { 489 LogFlowThisFunc (("\n")); 490 491 AssertReturnVoid (isLockedOnCurrentThread()); 492 493 AssertReturnVoid (mState == USBDeviceState_USBDeviceCaptured); 494 AssertReturnVoid (mPendingState == USBDeviceState_USBDeviceCaptured); 495 AssertReturnVoid (mIsStatePending == false); 423 496 424 497 mState = USBDeviceState_USBDeviceHeld; 425 mMachine.setNull(); 426 /// @todo remove 427 #if 0 428 mIgnored = false; 429 #endif 430 431 /** @todo this operation might fail and cause the device to the reattached with a different address and all that. */ 432 return mUSBProxyService->resetDevice (this); 433 } 434 435 /// @todo remove 436 #if 0 437 /** 438 * Sets the state of the device, as it was reported by the host. 439 * This method applicable only for devices currently controlled by the host. 440 * 441 * @param aState new state 442 * 443 * @note Locks this object for writing. 444 */ 445 void HostUSBDevice::setHostState (USBDeviceState_T aState) 446 { 447 AutoCaller autoCaller (this); 448 AssertComRCReturnVoid (autoCaller.rc()); 449 450 AutoLock alock (this); 451 452 AssertReturn ( 453 aState == USBDeviceState_USBDeviceUnavailable || 454 aState == USBDeviceState_USBDeviceBusy || 455 aState == USBDeviceState_USBDeviceAvailable, 456 (void) 0); 457 458 AssertReturn ( 459 mState == USBDeviceState_USBDeviceNotSupported || /* initial state */ 460 mState == USBDeviceState_USBDeviceUnavailable || 461 mState == USBDeviceState_USBDeviceBusy || 462 mState == USBDeviceState_USBDeviceAvailable, 463 (void) 0); 464 465 if (mState != aState) 466 { 467 mState = aState; 468 } 469 } 470 #endif 498 } 499 500 /** 501 * Resets all device data and informs the machine (if any) about the 502 * detachment. Must be called when this device is physically detached from 503 * the host. 504 * 505 * @note Must be called from under the object write lock. 506 */ 507 void HostUSBDevice::reset() 508 { 509 LogFlowThisFunc (("\n")); 510 511 AssertReturnVoid (isLockedOnCurrentThread()); 512 513 if (!mMachine.isNull() && mState == USBDeviceState_USBDeviceCaptured) 514 { 515 /* the device is captured by a machine, instruct it to release */ 516 517 mIsStatePending = true; 518 519 /* the VM process will query the object, so leave the lock */ 520 AutoLock alock (this); 521 alock.leave(); 522 523 LogFlowThisFunc (("Calling machine->onUSBDeviceDetach()...\n")); 524 525 HRESULT rc = mMachine->onUSBDeviceDetach (mId, NULL); 526 AssertComRC (rc); 527 528 LogFlowThisFunc (("Done machine->onUSBDeviceDetach()=%08X\n", rc)); 529 530 alock.enter(); 531 532 mIsStatePending = false; 533 mState = mPendingState = USBDeviceState_USBDeviceNotSupported; 534 } 535 } 536 537 /** 538 * Handles the finished pending state change and informs the VM process if 539 * necessary. 540 * 541 * @note Must be called from under the object write lock. 542 */ 543 void HostUSBDevice::handlePendingStateChange() 544 { 545 LogFlowThisFunc (("\n")); 546 547 AssertReturnVoid (isLockedOnCurrentThread()); 548 549 AssertReturnVoid (mIsStatePending == true); 550 AssertReturnVoid (mState != USBDeviceState_USBDeviceCaptured); 551 552 bool wasCapture = false; 553 bool wasRelease = false; 554 555 HRESULT requestRC = S_OK; 556 Bstr errorText; 557 558 switch (mPendingState) 559 { 560 case USBDeviceState_USBDeviceCaptured: 561 { 562 if (mState == USBDeviceState_USBDeviceHeld) 563 { 564 if (!mMachine.isNull()) 565 wasCapture = true; 566 else 567 { 568 /* it is a canceled capture request. Give the device back 569 * to the host. */ 570 mPendingState = USBDeviceState_USBDeviceAvailable; 571 mUSBProxyService->releaseDevice (this); 572 } 573 } 574 else 575 { 576 /* couldn't capture the device, will report an error */ 577 wasCapture = true; 578 579 Assert (!mMachine.isNull()); 580 581 /// @todo more detailed error message depending on the state? 582 // probably need some error code/string from the USB proxy itself 583 584 requestRC = E_FAIL; 585 errorText = Utf8StrFmt ( 586 tr ("USB device '%s' with UUID {%Vuuid} is being accessed by the host " 587 "computer and cannot be attached to the virtual machine." 588 "Please try later"), 589 name().raw(), id().raw()); 590 } 591 break; 592 } 593 case USBDeviceState_USBDeviceAvailable: 594 { 595 if (mState == USBDeviceState_USBDeviceHeld) 596 { 597 /* couldn't release the device */ 598 wasRelease = true; 599 600 Assert (!mMachine.isNull()); 601 602 /* return the captured state back */ 603 mState = USBDeviceState_USBDeviceCaptured; 604 605 /// @todo more detailed error message depending on the state? 606 // probably need some error code/string from the USB proxy itself 607 608 requestRC = E_FAIL; 609 errorText = Utf8StrFmt ( 610 tr ("USB device '%s' with UUID {%Vuuid} is being accessed by the guest " 611 "computer and cannot be attached from the virtual machine." 612 "Please try later"), 613 name().raw(), id().raw()); 614 } 615 else 616 { 617 if (!mMachine.isNull()) 618 wasRelease = true; 619 else 620 { 621 /* it is a canceled release request. Leave at the host */ 622 /// @todo we may want to re-run all filters in this case 623 } 624 } 625 break; 626 } 627 case USBDeviceState_USBDeviceHeld: 628 { 629 if (mState == USBDeviceState_USBDeviceHeld) 630 { 631 break; 632 } 633 else 634 { 635 /* couldn't capture the device requested by the global 636 * filter, there is nobody to report an error to. */ 637 } 638 break; 639 } 640 default: 641 AssertFailed(); 642 } 643 644 ComObjPtr <VirtualBoxErrorInfo> error; 645 if (FAILED (requestRC)) 646 { 647 LogFlowThisFunc (("Request failed, requestRC=%08X, text='%ls'\n", 648 requestRC, errorText.raw())); 649 650 error.createObject(); 651 error->init (requestRC, COM_IIDOF (IHostUSBDevice), 652 Bstr (HostUSBDevice::getComponentName()), 653 errorText.raw()); 654 } 655 656 if (wasCapture) 657 { 658 /* inform the VM process */ 659 660 ComPtr <IUSBDevice> d = this; 661 662 /* the VM process will query the object, so leave the lock */ 663 AutoLock alock (this); 664 alock.leave(); 665 666 LogFlowThisFunc (("Calling machine->onUSBDeviceAttach()...\n")); 667 668 HRESULT rc = mMachine->onUSBDeviceAttach (d, error); 669 /// @todo we will probably want to re-run all filters on failure 670 // instead of asserting 671 AssertComRC (rc); 672 673 LogFlowThisFunc (("Done machine->onUSBDeviceAttach()=%08X\n", rc)); 674 675 alock.enter(); 676 677 if (SUCCEEDED (requestRC) && SUCCEEDED (rc)) 678 { 679 mIsStatePending = false; 680 mState = mPendingState = USBDeviceState_USBDeviceCaptured; 681 return; 682 } 683 } 684 else if (wasRelease) 685 { 686 /* inform the VM process */ 687 688 /* the VM process will query the object, so leave the lock */ 689 AutoLock alock (this); 690 alock.leave(); 691 692 LogFlowThisFunc (("Calling machine->onUSBDeviceDetach()...\n")); 693 694 HRESULT rc = mMachine->onUSBDeviceDetach (mId, error); 695 696 /* This call may expectedly fail with rc = NS_ERROR_FAILURE (on XPCOM) 697 * if the VM process requests device release right before termination 698 * and then terminates before onUSBDeviceDetach() is reached 699 * it. Therefore, we don't assert here. On MS COM, there should be 700 * something similar (with the different error code). */ 701 702 LogFlowThisFunc (("Done machine->onUSBDeviceDetach()=%08X\n", rc)); 703 704 alock.enter(); 705 706 if (SUCCEEDED (requestRC)) 707 { 708 /* deassociate from the machine */ 709 mMachine.setNull(); 710 } 711 } 712 713 mIsStatePending = false; 714 mPendingState = mState; 715 } 716 717 /** 718 * Cancels pending state change due to machine termination. 719 * 720 * @note Must be called from under the object write lock. 721 */ 722 void HostUSBDevice::cancelPendingState() 723 { 724 LogFlowThisFunc (("\n")); 725 726 AssertReturnVoid (isLockedOnCurrentThread()); 727 728 AssertReturnVoid (mIsStatePending == true); 729 AssertReturnVoid (!mMachine.isNull()); 730 731 switch (mPendingState) 732 { 733 case USBDeviceState_USBDeviceCaptured: 734 { 735 /* reset mMachine to deassociate it from the filter and tell 736 * handlePendingStateChange() what to do */ 737 mMachine.setNull(); 738 break; 739 } 740 case USBDeviceState_USBDeviceAvailable: 741 { 742 /* reset mMachine to deassociate it from the filter and tell 743 * handlePendingStateChange() what to do */ 744 mMachine.setNull(); 745 break; 746 } 747 default: 748 AssertFailed(); 749 } 750 } 471 751 472 752 /** … … 495 775 if (!aData.mVendorId.isMatch (mUsb->idVendor)) 496 776 { 497 LogFlow Member (("HostUSBDevice::isMatch:vendor not match %04X\n",498 mUsb->idVendor));777 LogFlowThisFunc (("vendor not match %04X\n", 778 mUsb->idVendor)); 499 779 return false; 500 780 } 501 781 if (!aData.mProductId.isMatch (mUsb->idProduct)) 502 782 { 503 LogFlow Member (("HostUSBDevice::isMatch:product id not match %04X\n",504 mUsb->idProduct));783 LogFlowThisFunc (("product id not match %04X\n", 784 mUsb->idProduct)); 505 785 return false; 506 786 } 507 787 if (!aData.mRevision.isMatch (mUsb->bcdDevice)) 508 788 { 509 LogFlow Member (("HostUSBDevice::isMatch:rev not match %04X\n",510 mUsb->bcdDevice));789 LogFlowThisFunc (("rev not match %04X\n", 790 mUsb->bcdDevice)); 511 791 return false; 512 792 } … … 564 844 return false; 565 845 566 LogFlow Member (("HostUSBDevice::isMatch:returns true\n"));846 LogFlowThisFunc (("returns true\n")); 567 847 return true; 568 848 } … … 570 850 571 851 /** 572 * Compares this device with a USBDEVICE and decides which comes first. 573 * 574 * @returns < 0 if this should come before pDev2. 575 * @returns 0 if this and pDev2 are equal. 576 * @returns > 0 if this should come after pDev2. 577 * 578 * @param pDev2 Device 2. 852 * Compares this device with a USBDEVICE and decides which comes first. 853 * 854 * @return < 0 if this should come before pDev2. 855 * @return 0 if this and pDev2 are equal. 856 * @return > 0 if this should come after pDev2. 857 * 858 * @param pDev2 Device 2. 859 * 860 * @note Must be called from under the object write lock. 579 861 */ 580 862 int HostUSBDevice::compare (PCUSBDEVICE pDev2) 581 863 { 864 AssertReturn (isLockedOnCurrentThread(), -1); 865 582 866 return compare (mUsb, pDev2); 583 867 } … … 585 869 586 870 /** 587 * Compares two USB devices and decides which comes first.588 * 589 * @returns< 0 if pDev1 should come before pDev2.590 * @returns0 if pDev1 and pDev2 are equal.591 * @returns> 0 if pDev1 should come after pDev2.592 * 593 * @param pDev1 Device 1.594 * @param pDev2 Device 2.871 * Compares two USB devices and decides which comes first. 872 * 873 * @return < 0 if pDev1 should come before pDev2. 874 * @return 0 if pDev1 and pDev2 are equal. 875 * @return > 0 if pDev1 should come after pDev2. 876 * 877 * @param pDev1 Device 1. 878 * @param pDev2 Device 2. 595 879 */ 596 880 /*static*/ int HostUSBDevice::compare (PCUSBDEVICE pDev1, PCUSBDEVICE pDev2) … … 609 893 610 894 /** 611 * Updates the state of the device. 612 * 613 * @return true if the state has actually changed. 614 * @return false if the state didn't change, or the change might have been caused by VBox. 615 * 616 * @param aDev The current device state as seen by the proxy backend. 617 * 618 * @note Locks this object for writing. 895 * Updates the state of the device. 896 * 897 * If this method returns @c true, Host::onUSBDeviceStateChanged() will be 898 * called to process the state change (complete the state change request, 899 * inform the VM process etc.). 900 * 901 * If this method returns @c false, it is assumed that the given state change 902 * is "minor": it doesn't require any further action other than update the 903 * mState field with the actual state value. 904 * 905 * @param aDev The current device state as seen by the proxy backend. 906 * 907 * @note Locks this object for writing. 619 908 */ 620 909 bool HostUSBDevice::updateState (PCUSBDEVICE aDev) 621 910 { 911 LogFlowThisFunc (("\n")); 912 913 AssertReturn (isLockedOnCurrentThread(), false); 914 622 915 AutoCaller autoCaller (this); 623 916 AssertComRCReturn (autoCaller.rc(), false); 624 917 625 918 AutoLock alock (this); 919 920 bool isImportant = false; 626 921 627 922 /* … … 629 924 * doesn't necessarily know everything that's going on. So, rather 630 925 * be overly careful than changing the state once when we shouldn't! 926 * 927 * In particular, we treat changing between three states Unavailable, Busy 928 * and Available as non-important (because they all mean that the device 929 * is owned by the host) and return false in this case. We may want to 930 * change it later and, e.g. re-run all USB filters when the device goes from 931 * from Busy to Available). 631 932 */ 933 632 934 switch (aDev->enmState) 633 935 { … … 642 944 { 643 945 case USBDeviceState_USBDeviceUnavailable: 644 /* the proxy may confuse following states with unavailable */645 case USBDeviceState_USBDeviceHeld:646 case USBDeviceState_USBDeviceCaptured:647 946 return false; 947 /* the following state changes don't require any action for now */ 948 case USBDeviceState_USBDeviceBusy: 949 case USBDeviceState_USBDeviceAvailable: 950 isImportant = false; 648 951 default: 649 LogFlowMember ((" HostUSBDevice::updateState: %d -> %d\n", 650 mState, USBDeviceState_USBDeviceUnavailable)); 651 mState = USBDeviceState_USBDeviceUnavailable; 652 return true; 952 isImportant = true; 653 953 } 654 break; 954 LogFlowThisFunc (("%d -> %d\n", 955 mState, USBDeviceState_USBDeviceUnavailable)); 956 mState = USBDeviceState_USBDeviceUnavailable; 957 return isImportant; 655 958 656 959 case USBDEVICESTATE_USED_BY_HOST_CAPTURABLE: … … 658 961 { 659 962 case USBDeviceState_USBDeviceBusy: 660 /* the proxy may confuse following states with capturable */661 case USBDeviceState_USBDeviceHeld:662 case USBDeviceState_USBDeviceCaptured:663 963 return false; 964 /* the following state changes don't require any action for now */ 965 case USBDeviceState_USBDeviceUnavailable: 966 case USBDeviceState_USBDeviceAvailable: 967 isImportant = false; 664 968 default: 665 LogFlowMember ((" HostUSBDevice::updateState: %d -> %d\n", 666 mState, USBDeviceState_USBDeviceBusy)); 667 mState = USBDeviceState_USBDeviceBusy; 668 return true; 969 isImportant = true; 669 970 } 670 break; 971 LogFlowThisFunc (("%d -> %d\n", 972 mState, USBDeviceState_USBDeviceBusy)); 973 mState = USBDeviceState_USBDeviceBusy; 974 return isImportant; 671 975 672 976 case USBDEVICESTATE_UNUSED: … … 674 978 { 675 979 case USBDeviceState_USBDeviceAvailable: 676 /* the proxy may confuse following state(s) with available */677 case USBDeviceState_USBDeviceHeld:678 case USBDeviceState_USBDeviceCaptured:679 980 return false; 981 /* the following state changes don't require any action for now */ 982 case USBDeviceState_USBDeviceUnavailable: 983 case USBDeviceState_USBDeviceBusy: 984 isImportant = false; 680 985 default: 681 LogFlowMember ((" HostUSBDevice::updateState: %d -> %d\n", 682 mState, USBDeviceState_USBDeviceAvailable)); 683 mState = USBDeviceState_USBDeviceAvailable; 684 return true; 986 isImportant = true; 685 987 } 686 break; 988 LogFlowThisFunc (("%d -> %d\n", 989 mState, USBDeviceState_USBDeviceAvailable)); 990 mState = USBDeviceState_USBDeviceAvailable; 991 return isImportant; 687 992 688 993 case USBDEVICESTATE_HELD_BY_PROXY: … … 690 995 { 691 996 case USBDeviceState_USBDeviceHeld: 692 /* the proxy may confuse following state(s) with held */693 case USBDeviceState_USBDeviceAvailable:694 case USBDeviceState_USBDeviceBusy:695 case USBDeviceState_USBDeviceCaptured:696 997 return false; 697 998 default: 698 LogFlow Member ((" HostUSBDevice::updateState:%d -> %d\n",699 mState, USBDeviceState_USBDeviceHeld));999 LogFlowThisFunc (("%d -> %d\n", 1000 mState, USBDeviceState_USBDeviceHeld)); 700 1001 mState = USBDeviceState_USBDeviceHeld; 701 1002 return true; … … 704 1005 705 1006 case USBDEVICESTATE_USED_BY_GUEST: 1007 /* @todo USBDEVICESTATE_USED_BY_GUEST seems not to be used 1008 * anywhere in the proxy code; it's quite logical because the 1009 * proxy doesn't know anything about guest VMs. */ 1010 AssertFailed(); 1011 #if 0 706 1012 switch (mState) 707 1013 { … … 713 1019 return false; 714 1020 default: 715 LogFlow Member ((" HostUSBDevice::updateState:%d -> %d\n",716 mState, USBDeviceState_USBDeviceHeld));1021 LogFlowThisFunc (("%d -> %d\n", 1022 mState, USBDeviceState_USBDeviceHeld)); 717 1023 mState = USBDeviceState_USBDeviceHeld; 718 1024 return true; 719 1025 } 1026 #endif 720 1027 break; 721 1028 } -
trunk/src/VBox/Main/MachineImpl.cpp
r2980 r3001 7709 7709 * @note Locks the same as Host::captureUSBDevice() does. 7710 7710 */ 7711 STDMETHODIMP SessionMachine::CaptureUSBDevice (INPTR GUIDPARAM aId, 7712 IUSBDevice **aHostDevice) 7711 STDMETHODIMP SessionMachine::CaptureUSBDevice (INPTR GUIDPARAM aId) 7713 7712 { 7714 7713 LogFlowThisFunc (("\n")); 7715 7714 7716 if (!aHostDevice)7717 return E_POINTER;7718 7719 7715 AutoCaller autoCaller (this); 7720 7716 AssertComRCReturn (autoCaller.rc(), autoCaller.rc()); 7721 7717 7722 7718 // if cautureUSBDevice() fails, it must have set extended error info 7723 return mParent->host()->captureUSBDevice (this, aId , aHostDevice);7719 return mParent->host()->captureUSBDevice (this, aId); 7724 7720 } 7725 7721 … … 7745 7741 * @note Locks what called methods lock. 7746 7742 */ 7747 STDMETHODIMP SessionMachine::AutoCaptureUSBDevices (IUSBDeviceCollection **aHostDevices)7743 STDMETHODIMP SessionMachine::AutoCaptureUSBDevices() 7748 7744 { 7749 7745 LogFlowThisFunc (("\n")); … … 7756 7752 NOREF (rc); 7757 7753 7758 return mParent->host()->autoCaptureUSBDevices (this , aHostDevices);7754 return mParent->host()->autoCaptureUSBDevices (this); 7759 7755 } 7760 7756 … … 8584 8580 * @note Locks this object for reading. 8585 8581 */ 8586 HRESULT SessionMachine::onUSBDeviceAttach (IUSBDevice *aDevice) 8582 HRESULT SessionMachine::onUSBDeviceAttach (IUSBDevice *aDevice, 8583 IVirtualBoxErrorInfo *aError) 8587 8584 { 8588 8585 LogFlowThisFunc (("\n")); … … 8601 8598 return S_OK; 8602 8599 8603 return directControl->OnUSBDeviceAttach (aDevice );8600 return directControl->OnUSBDeviceAttach (aDevice, aError); 8604 8601 } 8605 8602 … … 8607 8604 * @note Locks this object for reading. 8608 8605 */ 8609 HRESULT SessionMachine::onUSBDeviceDetach (INPTR GUIDPARAM aId) 8606 HRESULT SessionMachine::onUSBDeviceDetach (INPTR GUIDPARAM aId, 8607 IVirtualBoxErrorInfo *aError) 8610 8608 { 8611 8609 LogFlowThisFunc (("\n")); … … 8624 8622 return S_OK; 8625 8623 8626 return directControl->OnUSBDeviceDetach (aId );8624 return directControl->OnUSBDeviceDetach (aId, aError); 8627 8625 } 8628 8626 -
trunk/src/VBox/Main/SessionImpl.cpp
r2981 r3001 562 562 } 563 563 564 STDMETHODIMP Session::OnUSBDeviceAttach (IUSBDevice *aDevice) 564 STDMETHODIMP Session::OnUSBDeviceAttach (IUSBDevice *aDevice, 565 IVirtualBoxErrorInfo *aError) 565 566 { 566 567 LogFlowThisFunc (("\n")); … … 573 574 mType == SessionType_DirectSession, E_FAIL); 574 575 575 return mConsole->onUSBDeviceAttach (aDevice); 576 } 577 578 STDMETHODIMP Session::OnUSBDeviceDetach (INPTR GUIDPARAM aId) 576 return mConsole->onUSBDeviceAttach (aDevice, aError); 577 } 578 579 STDMETHODIMP Session::OnUSBDeviceDetach (INPTR GUIDPARAM aId, 580 IVirtualBoxErrorInfo *aError) 579 581 { 580 582 LogFlowThisFunc (("\n")); … … 587 589 mType == SessionType_DirectSession, E_FAIL); 588 590 589 return mConsole->onUSBDeviceDetach (aId );591 return mConsole->onUSBDeviceDetach (aId, aError); 590 592 } 591 593 -
trunk/src/VBox/Main/USBControllerImpl.cpp
r2981 r3001 1011 1011 AutoReaderLock alock (this); 1012 1012 1013 /* Disabled USB controllers cannot actually work with USB devices */ 1014 if (!mData->mEnabled) 1015 return false; 1016 1013 1017 bool match = false; 1014 1018 … … 1045 1049 1046 1050 AutoReaderLock alock (this); 1051 1052 /* Disabled USB controllers cannot actually work with USB devices */ 1053 if (!mData->mEnabled) 1054 return false; 1047 1055 1048 1056 HRESULT rc = S_OK; -
trunk/src/VBox/Main/USBProxyService.cpp
r2981 r3001 36 36 : mHost (aHost), mThread (NIL_RTTHREAD), mTerminate (false), mDevices (), mLastError (VINF_SUCCESS) 37 37 { 38 LogFlow Member (("USBProxyService::USBProxyService:aHost=%p\n", aHost));38 LogFlowThisFunc (("aHost=%p\n", aHost)); 39 39 } 40 40 … … 45 45 USBProxyService::~USBProxyService() 46 46 { 47 LogFlow Member (("USBProxyService::~USBProxyService:\n"));47 LogFlowThisFunc (("\n")); 48 48 Assert (mThread == NIL_RTTHREAD); 49 49 mDevices.clear(); … … 84 84 AssertRC (rc); 85 85 if (VBOX_SUCCESS (rc)) 86 LogFlow (("USBProxyService::start:started mThread=%RTthrd\n", mThread));86 LogFlowThisFunc (("started mThread=%RTthrd\n", mThread)); 87 87 else 88 88 { … … 92 92 } 93 93 else 94 LogFlow (("USBProxyService::start:already running, mThread=%RTthrd\n", mThread));94 LogFlowThisFunc (("already running, mThread=%RTthrd\n", mThread)); 95 95 return rc; 96 96 } … … 117 117 if (VBOX_SUCCESS (rc)) 118 118 { 119 LogFlow Member (("USBProxyService::stop:stopped mThread=%RTthrd\n", mThread));119 LogFlowThisFunc (("stopped mThread=%RTthrd\n", mThread)); 120 120 mThread = NIL_RTTHREAD; 121 121 mTerminate = false; … … 128 128 } 129 129 else 130 LogFlow Member (("USBProxyService::stop:not active\n"));130 LogFlowThisFunc (("not active\n")); 131 131 132 132 return rc; … … 186 186 void USBProxyService::processChanges (void) 187 187 { 188 LogFlow Member (("USBProxyService::processChanges:\n"));188 LogFlowThisFunc (("\n")); 189 189 190 190 /* … … 195 195 { 196 196 pDevices = sortDevices (pDevices); 197 198 /* we need to lock the host object for writing because 199 * a) the subsequent code may call Host methods that require a write 200 * lock 201 * b) we will lock HostUSBDevice objects below and want to make sure 202 * the lock order is always the same (Host, HostUSBDevice, as 203 * expected by Host) to avoid cross-deadlocks */ 204 205 AutoLock hostLock (mHost); 197 206 198 207 /* … … 204 213 || pDevices) 205 214 { 215 ComObjPtr <HostUSBDevice> DevPtr; 216 217 if (It != mDevices.end()) 218 DevPtr = *It; 219 220 /// @todo we want to AddCaller here to make sure the device hasn't 221 // been uninitialized (needs support for the no-op AddCaller when 222 // its argument is NULL) 223 224 /* Lock the device object since we will read/write it's 225 * properties. All Host callbacks also imply the object is 226 * locked. */ 227 AutoLock devLock (DevPtr.isNull() ? NULL : DevPtr); 228 206 229 /* 207 230 * Compare. 208 231 */ 209 ComObjPtr <HostUSBDevice> DevPtr;210 232 int iDiff; 211 if ( It == mDevices.end())233 if (DevPtr.isNull()) 212 234 iDiff = 1; 213 235 else 214 236 { 215 DevPtr = *It;216 237 if (!pDevices) 217 238 iDiff = -1; … … 248 269 (HostUSBDevice *)NewObj, pNew, pNew->idVendor, pNew->idProduct, pNew->pszProduct, pNew->pszManufacturer)); 249 270 271 /* not really necessary to lock here, but make Assert 272 * checks happy */ 273 AutoLock newDevLock (NewObj); 274 250 275 mDevices.insert (It, NewObj); 251 276 mHost->onUSBDeviceAttached (NewObj); … … 257 282 */ 258 283 /** @todo add a timeout here. */ 259 if (!DevPtr->isStatePending Unlocked())284 if (!DevPtr->isStatePending()) 260 285 { 261 286 It = mDevices.erase (It); … … 263 288 Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/ 264 289 } 265 /* else: operation pending */ 290 else 291 { 292 /* a state change (re-cycle) request is pending, go 293 * to the next device */ 294 It++; 295 } 266 296 } 267 297 } … … 270 300 else 271 301 { 302 /* we need to lock the host object for writing because 303 * a) the subsequent code may call Host methods that require a write 304 * lock 305 * b) we will lock HostUSBDevice objects below and want to make sure 306 * the lock order is always the same (Host, HostUSBDevice, as 307 * expected by Host) to avoid cross-deadlocks */ 308 309 AutoLock hostLock (mHost); 310 272 311 /* All devices were detached */ 273 312 HostUSBDeviceList::iterator It = this->mDevices.begin(); … … 275 314 { 276 315 ComObjPtr <HostUSBDevice> DevPtr = *It; 316 317 AutoLock devLock (DevPtr); 318 277 319 /* 278 320 * DevPtr was detached. … … 284 326 } 285 327 286 LogFlow Member (("USBProxyService::processChanges:returns void\n"));328 LogFlowThisFunc (("returns void\n")); 287 329 } 288 330 … … 291 333 { 292 334 USBProxyService *pThis = (USBProxyService *)pvUser; 293 LogFlow (("USBProxyService::serviceThread:pThis=%p\n", pThis));335 LogFlowFunc (("pThis=%p\n", pThis)); 294 336 pThis->serviceThreadInit(); 295 337 … … 306 348 307 349 pThis->serviceThreadTerm(); 308 LogFlow (("USBProxyService::serviceThread:returns VINF_SUCCESS\n"));350 LogFlowFunc (("returns VINF_SUCCESS\n")); 309 351 return VINF_SUCCESS; 310 352 } … … 378 420 bool USBProxyService::updateDeviceStateFake (HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice) 379 421 { 380 if (aDevice->isStatePendingUnlocked()) 381 { 382 switch (aDevice->pendingStateUnlocked()) 383 { 384 case USBDeviceState_USBDeviceCaptured: aUSBDevice->enmState = USBDEVICESTATE_USED_BY_GUEST; break; 422 AssertReturn (aDevice, false); 423 AssertReturn (aDevice->isLockedOnCurrentThread(), false); 424 425 if (aDevice->isStatePending()) 426 { 427 switch (aDevice->pendingState()) 428 { 429 /* @todo USBDEVICESTATE_USED_BY_GUEST seems not to be used anywhere in the proxy code; it's 430 * quite logical because the proxy doesn't know anything about guest VMs. We use HELD_BY_PROXY 431 * instead -- it is sufficient and is what Main expects. */ 432 case USBDeviceState_USBDeviceCaptured: aUSBDevice->enmState = USBDEVICESTATE_HELD_BY_PROXY; break; 385 433 case USBDeviceState_USBDeviceHeld: aUSBDevice->enmState = USBDEVICESTATE_HELD_BY_PROXY; break; 386 434 case USBDeviceState_USBDeviceAvailable: aUSBDevice->enmState = USBDEVICESTATE_UNUSED; break; … … 388 436 case USBDeviceState_USBDeviceBusy: aUSBDevice->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; break; 389 437 default: 390 AssertMsgFailed(("%d\n", aDevice->pendingState Unlocked()));438 AssertMsgFailed(("%d\n", aDevice->pendingState())); 391 439 break; 392 440 } … … 471 519 bool USBProxyService::updateDeviceState (HostUSBDevice *pDevice, PUSBDEVICE pUSBDevice) 472 520 { 521 AssertReturn (pDevice, false); 522 AssertReturn (pDevice->isLockedOnCurrentThread(), false); 523 473 524 return pDevice->updateState (pUSBDevice); 474 525 } -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r2988 r3001 1600 1600 <interface 1601 1601 name="IInternalMachineControl" extends="$unknown" 1602 uuid=" e780b585-585d-47e2-ab53-e94dc552353c"1602 uuid="67ef427d-5f01-4791-a45e-ae5e646ed7c6" 1603 1603 internal="yes" 1604 1604 wsmap="suppress" … … 1637 1637 <method name="captureUSBDevice"> 1638 1638 <desc> 1639 Requests a capture of the given host USB device, and returns 1640 the captured device (as IUSBDevice) to the caller. 1641 <note> 1642 The server must mark the device as USBDeviceCaptured 1643 during this call. 1644 1645 This method must return extended error info in case of any 1646 eroror (<link to="IConsole::detachUSBDevice()"/>) relies 1647 on this. 1648 </note> 1639 Requests a capture of the given host USB device. 1640 When the request is completed, the VM process will 1641 get a <link to="IInternalSessionControl::onUSBDeviceAttach"/> 1642 notification. 1649 1643 </desc> 1650 1644 <param name="id" type="uuid" dir="in"/> 1651 <param name="hostDevice" type="IUSBDevice" dir="return"/>1652 1645 </method> 1653 1646 1654 1647 <method name="releaseUSBDevice"> 1655 1648 <desc> 1656 Releases the given USB device. 1649 Requests to release the given USB device. 1650 When the request is completed, the VM process will 1651 get a <link to="IInternalSessionControl::onUSBDeviceDetach"/> 1652 notification. 1657 1653 <note> 1658 1654 The server must run its own filters and filters of all VMs 1659 but this one on the given device as if it were just attached1660 to the host computer.1655 but this one on all released devices as if they were just 1656 attached to the host computer. 1661 1657 </note> 1662 1658 </desc> … … 1666 1662 <method name="autoCaptureUSBDevices"> 1667 1663 <desc> 1668 Queries the list of available devices that must be auto-captured 1669 according to this VM's filters. Devices returned as IUSBDevice 1670 instances. 1671 <note> 1672 The server must mark all returned devices as USBDeviceCaptured 1673 during this call. 1674 </note> 1675 </desc> 1676 <param name="hostDevices" type="IUSBDeviceCollection" dir="return"/> 1664 Requests a capture all matching USB devices attached to the host. 1665 When the request is completed, the VM process will 1666 get a <link to="IInternalSessionControl::onUSBDeviceAttach"/> 1667 notification per every captured device. 1668 </desc> 1677 1669 </method> 1678 1670 … … 2647 2639 <interface 2648 2640 name="IConsoleCallback" extends="$unknown" 2649 uuid=" a56eff10-6db9-4985-a12a-039b604b491b"2641 uuid="ebd0c5f2-7b11-4508-803f-012099caee03" 2650 2642 wsmap="suppress" 2651 2643 > … … 2748 2740 find out what has changed. 2749 2741 </desc> 2742 </method> 2743 2744 <method name="onUSBDeviceStateChange"> 2745 <desc> 2746 Notification when a USB device is attached to or detached from 2747 the virtual USB controller. 2748 2749 This notification is sent as a result of the indirect 2750 request to attach the device because it matches one of the 2751 machine USB filters, or as a result of the direct request 2752 issued by <link to="IConsole::attachUSBDevice"/> or 2753 <link to="IConsole::detachUSBDevice"/>. 2754 2755 This notification is sent in case of both a succeeded and a 2756 failed request completion. When the request succeeds, the @a 2757 error parameter is @c null, and the given device has been 2758 already added to (when @a attached is @c true) or removed from 2759 (when @a attached is @c false) the collection represented by 2760 <link to="IConsole::USBDevices"/>. On failure, the collection 2761 doesn't change and the @a error perameter represents the error 2762 message describing the failure. 2763 2764 </desc> 2765 <param name="device" type="IUSBDevice" dir="in"> 2766 <desc>Device that is subject to state change.</desc> 2767 </param> 2768 <param name="attached" type="boolean" dir="in"> 2769 <desc> 2770 <tt>true</tt> if the device was attached 2771 and <tt>false</tt> otherwise. 2772 </desc> 2773 </param> 2774 <param name="error" type="IVirtualBoxErrorInfo" dir="in"> 2775 <desc> 2776 <tt>null</tt> on success or an error message object on 2777 failure. 2778 </desc> 2779 </param> 2750 2780 </method> 2751 2781 … … 7411 7441 <interface 7412 7442 name="IInternalSessionControl" extends="$unknown" 7413 uuid=" 9c6bec01-4135-40a0-b9d3-ab119a9c5412"7443 uuid="80a9b698-cc60-48cf-ab88-a7c2ea4013a6" 7414 7444 internal="yes" 7415 7445 wsmap="suppress" … … 7499 7529 <method name="onUSBDeviceAttach"> 7500 7530 <desc> 7501 Triggered when a USB device has just been attached to the host 7502 computer and is to be auto-captured by the machine according 7503 to its USB filters. 7531 Triggered when a request to capture a USB device (as a result 7532 of matched USB filters or direct call to 7533 <link to="IConsole::attachUSBDevice"/>) has completed. 7534 A @c null @a error object means success, otherwise it 7535 describes a failure. 7504 7536 </desc> 7505 7537 <param name="device" type="IUSBDevice" dir="in"/> 7538 <param name="error" type="IVirtualBoxErrorInfo" dir="in"/> 7506 7539 </method> 7507 7540 7508 7541 <method name="onUSBDeviceDetach"> 7509 7542 <desc> 7510 Triggered when a USB device has just been detached from the host 7511 computer and needs to be detached from the machine. 7543 Triggered when a request to release the USB device (as a result 7544 of machine termination or direct call to 7545 <link to="IConsole::detachUSBDevice"/>) has completed. 7546 A @c null @a error object means success, otherwise it 7512 7547 </desc> 7513 7548 <param name="id" type="uuid" dir="in"/> 7549 <param name="error" type="IVirtualBoxErrorInfo" dir="in"/> 7514 7550 </method> 7515 7551 -
trunk/src/VBox/Main/include/ConsoleImpl.h
r2981 r3001 174 174 HRESULT onVRDPServerChange(); 175 175 HRESULT onUSBControllerChange(); 176 HRESULT onUSBDeviceAttach (IUSBDevice *aDevice);177 HRESULT onUSBDeviceDetach (INPTR GUIDPARAM aId);176 HRESULT onUSBDeviceAttach (IUSBDevice *aDevice, IVirtualBoxErrorInfo *aError); 177 HRESULT onUSBDeviceDetach (INPTR GUIDPARAM aId, IVirtualBoxErrorInfo *aError); 178 178 179 179 VMMDev *getVMMDev() { return mVMMDev; } … … 198 198 void onAdditionsOutdated(); 199 199 void onKeyboardLedsChange (bool fNumLock, bool fCapsLock, bool fScrollLock); 200 void onUSBDeviceStateChange (IUSBDevice *aDevice, bool aAttached, 201 IVirtualBoxErrorInfo *aError); 200 202 void onRuntimeError (BOOL aFatal, INPTR BSTR aErrorID, INPTR BSTR aMessage); 201 203 HRESULT onShowWindow (BOOL aCheck, BOOL *aCanShow, ULONG64 *aWinId); … … 369 371 const char *pszPath, bool fPassthrough); 370 372 371 HRESULT attachUSBDevice (IUSBDevice *aHostDevice, bool aManual, 372 PVUSBIRHCONFIG aConfig); 373 HRESULT attachUSBDevice (IUSBDevice *aHostDevice, PVUSBIRHCONFIG aConfig); 373 374 374 375 static DECLCALLBACK(int) … … 378 379 static DECLCALLBACK(int) 379 380 usbDetachCallback (Console *that, USBDeviceList::iterator *aIt, 380 bool aManual,PVUSBIRHCONFIG aConfig, PCRTUUID aUuid);381 PVUSBIRHCONFIG aConfig, PCRTUUID aUuid); 381 382 382 383 static DECLCALLBACK (int) -
trunk/src/VBox/Main/include/DisplayImpl.h
r2981 r3001 103 103 } 104 104 105 STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *device, BOOL attached, 106 IVirtualBoxErrorInfo *message) 107 { 108 return S_OK; 109 } 110 105 111 STDMETHOD(OnRuntimeError)(BOOL fatal, INPTR BSTR id, INPTR BSTR message) 106 112 { -
trunk/src/VBox/Main/include/HostImpl.h
r2981 r3001 105 105 HRESULT saveSettings (CFGNODE aGlobal); 106 106 107 HRESULT captureUSBDevice (SessionMachine *aMachine, INPTR GUIDPARAM aId, 108 IUSBDevice **aHostDevice); 107 HRESULT captureUSBDevice (SessionMachine *aMachine, INPTR GUIDPARAM aId); 109 108 HRESULT releaseUSBDevice (SessionMachine *aMachine, INPTR GUIDPARAM aId); 110 HRESULT autoCaptureUSBDevices (SessionMachine *aMachine, 111 IUSBDeviceCollection **aHostDevices); 109 HRESULT autoCaptureUSBDevices (SessionMachine *aMachine); 112 110 HRESULT releaseAllUSBDevices (SessionMachine *aMachine); 113 111 … … 149 147 } 150 148 151 HRESULT applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice ,152 SessionMachine *aMachine = NULL); 153 voidapplyMachineUSBFilters (SessionMachine *aMachine,149 HRESULT applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice); 150 151 bool applyMachineUSBFilters (SessionMachine *aMachine, 154 152 ComObjPtr <HostUSBDevice> &aDevice); 155 153 -
trunk/src/VBox/Main/include/HostUSBDeviceImpl.h
r2981 r3001 91 91 USBDeviceState_T state() const { return mState; } 92 92 93 /** Same as state() except you don't need to lock any thing. */94 USBDeviceState_T stateUnlocked() const95 {96 AutoReaderLock (this);97 return state();98 }99 100 93 /* @note Must be called from under the object read lock. */ 101 94 USBDeviceState_T pendingState() const { return mPendingState; } 102 95 103 /** Same as pendingState() except you don't need to lock any thing. */104 USBDeviceState_T pendingStateUnlocked() const105 {106 AutoReaderLock (this);107 return pendingState();108 }109 110 96 /* @note Must be called from under the object read lock. */ 111 97 ComObjPtr <SessionMachine, ComWeakRef> &machine() { return mMachine; } 112 98 113 /// @todo remove114 #if 0115 /* @note Must be called from under the object read lock. */116 bool isIgnored() { return mIgnored; }117 #endif118 119 99 /* @note Must be called from under the object read lock. */ 120 100 bool isStatePending() const { return mIsStatePending; } 121 101 122 /** Same as isStatePending() except you don't need to lock any thing. */123 bool isStatePendingUnlocked() const124 {125 AutoReaderLock (this);126 return isStatePending();127 }128 129 102 /* @note Must be called from under the object read lock. */ 130 103 PCUSBDEVICE usbData() const { return mUsb; } … … 132 105 Utf8Str name(); 133 106 134 /// @todo remove 135 #if 0 136 void setIgnored(); 137 #endif 138 139 bool setCaptured (SessionMachine *aMachine); 140 int setHostDriven(); 141 int reset(); 142 143 /// @todo remove 144 #if 0 145 void setHostState (USBDeviceState_T aState); 146 #endif 107 bool requestCapture (SessionMachine *aMachine); 108 void requestRelease(); 109 void requestHold(); 110 111 void setHeld(); 112 void reset(); 113 114 void handlePendingStateChange(); 115 void cancelPendingState(); 147 116 148 117 bool isMatch (const USBDeviceFilter::Data &aData); … … 163 132 ComObjPtr <SessionMachine, ComWeakRef> mMachine; 164 133 bool mIsStatePending : 1; 165 /// @todo remove166 #if 0167 bool mIgnored : 1;168 #endif169 134 170 135 /** Pointer to the USB Proxy Service instance. */ -
trunk/src/VBox/Main/include/MachineImpl.h
r2981 r3001 727 727 STDMETHOD(GetIPCId)(BSTR *id); 728 728 STDMETHOD(RunUSBDeviceFilters) (IUSBDevice *aUSBDevice, BOOL *aMatched); 729 STDMETHOD(CaptureUSBDevice) (INPTR GUIDPARAM aId , IUSBDevice **aHostDevice);729 STDMETHOD(CaptureUSBDevice) (INPTR GUIDPARAM aId); 730 730 STDMETHOD(ReleaseUSBDevice) (INPTR GUIDPARAM aId); 731 STDMETHOD(AutoCaptureUSBDevices) (IUSBDeviceCollection **aHostDevices);731 STDMETHOD(AutoCaptureUSBDevices)(); 732 732 STDMETHOD(ReleaseAllUSBDevices)(); 733 733 STDMETHOD(OnSessionEnd)(ISession *aSession, IProgress **aProgress); … … 758 758 HRESULT onVRDPServerChange(); 759 759 HRESULT onUSBControllerChange(); 760 HRESULT onUSBDeviceAttach (IUSBDevice *aDevice); 761 HRESULT onUSBDeviceDetach (INPTR GUIDPARAM aId); 760 HRESULT onUSBDeviceAttach (IUSBDevice *aDevice, 761 IVirtualBoxErrorInfo *aError); 762 HRESULT onUSBDeviceDetach (INPTR GUIDPARAM aId, 763 IVirtualBoxErrorInfo *aError); 762 764 763 765 private: -
trunk/src/VBox/Main/include/SessionImpl.h
r2981 r3001 100 100 STDMETHOD(OnVRDPServerChange)(); 101 101 STDMETHOD(OnUSBControllerChange)(); 102 STDMETHOD(OnUSBDeviceAttach) (IUSBDevice *aDevice );103 STDMETHOD(OnUSBDeviceDetach) (INPTR GUIDPARAM aId );102 STDMETHOD(OnUSBDeviceAttach) (IUSBDevice *aDevice, IVirtualBoxErrorInfo *aError); 103 STDMETHOD(OnUSBDeviceDetach) (INPTR GUIDPARAM aId, IVirtualBoxErrorInfo *aError); 104 104 STDMETHOD(OnShowWindow) (BOOL aCheck, BOOL *aCanShow, ULONG64 *aWinId); 105 105
Note:
See TracChangeset
for help on using the changeset viewer.