Changeset 3034 in vbox
- Timestamp:
- Jun 4, 2007 3:51:26 PM (18 years ago)
- svn:sync-xref-src-repo-rev:
- 21789
- Location:
- trunk/src/VBox/Main
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl.cpp
r3007 r3034 1947 1947 tr ("The virtual machine does not have a USB controller")); 1948 1948 1949 /* leave the lock because the USB Proxy service may call us back 1950 * (via onUSBDeviceAttach()) */ 1951 alock.leave(); 1952 1949 1953 /* Request the device capture */ 1950 1954 HRESULT rc = mControl->CaptureUSBDevice (aId); … … 1982 1986 Guid (aId).raw()); 1983 1987 1984 /* Request the device release */ 1985 HRESULT rc = mControl->ReleaseUSBDevice (aId); 1986 CheckComRCReturnRC (rc); 1988 /* First, request VMM to detach the device */ 1989 HRESULT rc = detachUSBDevice (it); 1990 1991 if (SUCCEEDED (rc)) 1992 { 1993 /* leave the lock since we don't need it any more (note though that 1994 * the USB Proxy service must not call us back here) */ 1995 alock.leave(); 1996 1997 /* Request the device release. Even if it fails, the device will 1998 * remain as held by proxy, which is OK for us (the VM process). */ 1999 rc = mControl->ReleaseUSBDevice (aId); 2000 } 1987 2001 1988 2002 return rc; … … 3217 3231 ComAssertRet (pRhConfig, E_FAIL); 3218 3232 3233 HRESULT rc = attachUSBDevice (aDevice, pRhConfig); 3234 3219 3235 /// @todo notify listeners of IConsoleCallback in case of error 3220 return attachUSBDevice (aDevice, pRhConfig);3236 return rc; 3221 3237 } 3222 3238 … … 3273 3289 } 3274 3290 3275 /* protect mpVM */ 3276 AutoVMCaller autoVMCaller (this); 3277 CheckComRCReturnRC (autoVMCaller.rc()); 3278 3279 PPDMIBASE pBase = NULL; 3280 int vrc = PDMR3QueryLun (mpVM, "usb-ohci", 0, 0, &pBase); 3281 3282 /* if the device is attached, then there must be a USB controller */ 3283 AssertRCReturn (vrc, E_FAIL); 3284 3285 PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG) pBase-> 3286 pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG); 3287 AssertReturn (pRhConfig, E_FAIL); 3288 3289 LogFlowThisFunc (("Detaching USB proxy device {%Vuuid}...\n", Uuid.raw())); 3290 3291 /* leave the lock before a VMR3* call (EMT will call us back)! */ 3292 alock.leave(); 3293 3294 PVMREQ pReq; 3295 vrc = VMR3ReqCall (mpVM, &pReq, RT_INDEFINITE_WAIT, 3296 (PFNRT) usbDetachCallback, 5, 3297 this, &it, pRhConfig, Uuid.raw()); 3298 if (VBOX_SUCCESS (vrc)) 3299 vrc = pReq->iStatus; 3300 VMR3ReqFree (pReq); 3301 3302 AssertRC (vrc); 3291 HRESULT rc = detachUSBDevice (it); 3303 3292 3304 3293 /// @todo notify listeners of IConsoleCallback in case of error 3305 return VBOX_SUCCESS (vrc) ? S_OK : E_FAIL;3294 return rc; 3306 3295 } 3307 3296 … … 4178 4167 * @param aHostDevice device to attach 4179 4168 * 4180 * @note Locks this object for writing.4181 4169 * @note Synchronously calls EMT. 4170 * @note Must be called from under this object's lock. 4182 4171 */ 4183 4172 HRESULT Console::attachUSBDevice (IUSBDevice *aHostDevice, PVUSBIRHCONFIG aConfig) … … 4185 4174 AssertReturn (aHostDevice && aConfig, E_FAIL); 4186 4175 4176 AssertReturn (isLockedOnCurrentThread(), E_FAIL); 4177 4178 /* still want a lock object because we need to leave it */ 4187 4179 AutoLock alock (this); 4188 4180 … … 4328 4320 LogFlowFuncLeave(); 4329 4321 return vrc; 4322 } 4323 4324 /** 4325 * Sends a request to VMM to detach the given host device. After this method 4326 * succeeds, the detached device will disappear from the mUSBDevices 4327 * collection. 4328 * 4329 * @param aIt Iterator pointing to the device to detach. 4330 * 4331 * @note Synchronously calls EMT. 4332 * @note Must be called from under this object's lock. 4333 */ 4334 HRESULT Console::detachUSBDevice (USBDeviceList::iterator &aIt) 4335 { 4336 AssertReturn (isLockedOnCurrentThread(), E_FAIL); 4337 4338 /* still want a lock object because we need to leave it */ 4339 AutoLock alock (this); 4340 4341 /* protect mpVM */ 4342 AutoVMCaller autoVMCaller (this); 4343 CheckComRCReturnRC (autoVMCaller.rc()); 4344 4345 PPDMIBASE pBase = NULL; 4346 int vrc = PDMR3QueryLun (mpVM, "usb-ohci", 0, 0, &pBase); 4347 4348 /* if the device is attached, then there must be a USB controller */ 4349 AssertRCReturn (vrc, E_FAIL); 4350 4351 PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG) pBase-> 4352 pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG); 4353 AssertReturn (pRhConfig, E_FAIL); 4354 4355 LogFlowThisFunc (("Detaching USB proxy device {%Vuuid}...\n", 4356 (*aIt)->id().raw())); 4357 4358 /* leave the lock before a VMR3* call (EMT will call us back)! */ 4359 alock.leave(); 4360 4361 PVMREQ pReq; 4362 vrc = VMR3ReqCall (mpVM, &pReq, RT_INDEFINITE_WAIT, 4363 (PFNRT) usbDetachCallback, 5, 4364 this, &aIt, pRhConfig, (*aIt)->id().raw()); 4365 if (VBOX_SUCCESS (vrc)) 4366 vrc = pReq->iStatus; 4367 VMR3ReqFree (pReq); 4368 4369 ComAssertRCRet (vrc, E_FAIL); 4370 4371 return S_OK; 4330 4372 } 4331 4373 -
trunk/src/VBox/Main/HostImpl.cpp
r3001 r3034 1315 1315 /* re-apply filters on the device before giving it back to the host */ 1316 1316 device->setHeld(); 1317 HRESULT rc = applyAllUSBFilters (device );1317 HRESULT rc = applyAllUSBFilters (device, aMachine); 1318 1318 ComAssertComRC (rc); 1319 1319 … … 1397 1397 * host */ 1398 1398 device->setHeld(); 1399 HRESULT rc = applyAllUSBFilters (device );1399 HRESULT rc = applyAllUSBFilters (device, aMachine); 1400 1400 AssertComRC (rc); 1401 1401 } … … 1845 1845 * 1846 1846 * @param aDevice USB device to apply filters to. 1847 * @param aMachine Machine the device was released by or @c NULL. 1847 1848 * 1848 1849 * @note the method must be called from under this object's write lock and 1849 1850 * from the aDevice's write lock. 1850 1851 */ 1851 HRESULT Host::applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice) 1852 HRESULT Host::applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice, 1853 SessionMachine *aMachine /* = NULL */) 1852 1854 { 1853 1855 LogFlowThisFunc (("\n")); … … 1901 1903 { 1902 1904 /* skip the machine the device was just detached from */ 1903 if (a Device->machine() && machines [i] == aDevice->machine())1905 if (aMachine && machines [i] == aMachine) 1904 1906 continue; 1905 1907 … … 2051 2053 mUSBDevices.erase (it); 2052 2054 2053 /* reset all data */2055 /* reset all data and uninitialize the device object */ 2054 2056 device->reset(); 2055 2057 } -
trunk/src/VBox/Main/HostUSBDeviceImpl.cpp
r3029 r3034 332 332 name = Utf8StrFmt ("%s %s", mUsb->pszManufacturer, 333 333 mUsb->pszProduct); 334 else if (haveManufacturer)334 else if (haveManufacturer) 335 335 name = Utf8StrFmt ("%s", mUsb->pszManufacturer); 336 else if (haveProduct)337 name = Utf8StrFmt ("%s", mUsb->psz Manufacturer);336 else if (haveProduct) 337 name = Utf8StrFmt ("%s", mUsb->pszProduct); 338 338 else 339 339 name = "<unknown>"; … … 389 389 390 390 HRESULT rc = aMachine->onUSBDeviceAttach (d, NULL); 391 392 /* The VM process has a legal reason to fail (for example, incorrect 393 * usbfs permissions or out of virtual USB ports). More over, the VM 394 * process might have been accidentially crashed and not accessible 395 * any more (so that calling an uninitialized SessionMachine returns a 396 * failure). So don't assert. */ 391 397 392 398 LogFlowThisFunc (("Done machine->onUSBDeviceAttach()=%08X\n", rc)); … … 481 487 482 488 /** 483 * Sets the device state from Captured to Held and preserves the machine489 * Sets the device state from Captured to Held and resets the machine 484 490 * association (if any). Usually called before applying filters. 485 491 * … … 497 503 498 504 mState = USBDeviceState_USBDeviceHeld; 505 mMachine.setNull(); 499 506 } 500 507 … … 525 532 526 533 HRESULT rc = mMachine->onUSBDeviceDetach (mId, NULL); 527 AssertComRC (rc); 534 535 /* This call may expectedly fail with rc = NS_ERROR_FAILURE (on XPCOM) 536 * if the VM process requests device release right before termination 537 * and then terminates before onUSBDeviceDetach() reached 538 * it. Therefore, we don't assert here. On MS COM, there should be 539 * something similar (with the different error code). More over, the 540 * VM process might have been accidentially crashed and not accessible 541 * any more (so that calling an uninitialized SessionMachine returns a 542 * failure). So don't assert. */ 528 543 529 544 LogFlowThisFunc (("Done machine->onUSBDeviceDetach()=%08X\n", rc)); … … 531 546 alock.enter(); 532 547 548 /* Reset all fields. Tthe object should have been 549 * uninitialized after this method returns, so it doesn't really 550 * matter what state we put it in. */ 533 551 mIsStatePending = false; 534 552 mState = mPendingState = USBDeviceState_USBDeviceNotSupported; 553 mMachine.setNull(); 535 554 } 536 555 } … … 552 571 553 572 bool wasCapture = false; 554 bool wasRelease = false;555 573 556 574 HRESULT requestRC = S_OK; … … 594 612 case USBDeviceState_USBDeviceAvailable: 595 613 { 614 Assert (mMachine.isNull()); 615 596 616 if (mState == USBDeviceState_USBDeviceHeld) 597 617 { 598 /* couldn't release the device */ 599 wasRelease = true; 600 601 Assert (!mMachine.isNull()); 602 603 /* return the captured state back */ 604 mState = USBDeviceState_USBDeviceCaptured; 605 606 /// @todo more detailed error message depending on the state? 607 // probably need some error code/string from the USB proxy itself 608 609 requestRC = E_FAIL; 610 errorText = Utf8StrFmt ( 611 tr ("USB device '%s' with UUID {%Vuuid} is being accessed by the guest " 612 "computer and cannot be attached from the virtual machine." 613 "Please try later"), 614 name().raw(), id().raw()); 618 /* couldn't release the device (give it back to the host). 619 * there is nobody to report an error to (the machine has 620 * already been deassociated because VMM has already detached 621 * the device before requesting a release). */ 615 622 } 616 623 else 617 624 { 618 if (!mMachine.isNull()) 619 wasRelease = true; 620 else 621 { 622 /* it is a canceled release request. Leave at the host */ 623 /// @todo we may want to re-run all filters in this case 624 } 625 /* it is a canceled release request. Leave at the host */ 626 /// @todo we may want to re-run all filters in this case 625 627 } 626 628 break; … … 630 632 if (mState == USBDeviceState_USBDeviceHeld) 631 633 { 634 /* All right, the device is now held (due to some global 635 * filter). */ 632 636 break; 633 637 } … … 670 674 671 675 /* The VM process has a legal reason to fail (for example, incorrect 672 * usbfs permissions or out of virtual USB ports), so don't assert */ 676 * usbfs permissions or out of virtual USB ports). More over, the VM 677 * process might have been accidentially crashed and not accessible 678 * any more (so that calling an uninitialized SessionMachine returns a 679 * failure). So don't assert. */ 673 680 674 681 /// @todo we will probably want to re-run all filters on failure … … 689 696 mMachine.setNull(); 690 697 } 691 else if (wasRelease)692 {693 /* inform the VM process */694 695 /* the VM process will query the object, so leave the lock */696 AutoLock alock (this);697 alock.leave();698 699 LogFlowThisFunc (("Calling machine->onUSBDeviceDetach()...\n"));700 701 HRESULT rc = mMachine->onUSBDeviceDetach (mId, error);702 703 /* This call may expectedly fail with rc = NS_ERROR_FAILURE (on XPCOM)704 * if the VM process requests device release right before termination705 * and then terminates before onUSBDeviceDetach() is reached706 * it. Therefore, we don't assert here. On MS COM, there should be707 * something similar (with the different error code). */708 709 LogFlowThisFunc (("Done machine->onUSBDeviceDetach()=%08X\n", rc));710 711 alock.enter();712 713 if (SUCCEEDED (requestRC))714 {715 /* deassociate from the machine */716 mMachine.setNull();717 }718 }719 698 720 699 mIsStatePending = false; … … 739 718 { 740 719 case USBDeviceState_USBDeviceCaptured: 741 {742 /* reset mMachine to deassociate it from the filter and tell743 * handlePendingStateChange() what to do */744 mMachine.setNull();745 break;746 }747 case USBDeviceState_USBDeviceAvailable:748 720 { 749 721 /* reset mMachine to deassociate it from the filter and tell … … 859 831 * Compares this device with a USBDEVICE and decides which comes first. 860 832 * 861 * @return < 0 if this should come before pDev2. 862 * @return 0 if this and pDev2 are equal. 863 * @return > 0 if this should come after pDev2. 864 * 865 * @param pDev2 Device 2. 833 * If the device has a pending state request, a non-strict comparison is made 834 * (to properly detect a re-attached device). Otherwise, a strict comparison 835 * is performed. 836 * 837 * @param aDev2 Device 2. 838 * 839 * @return < 0 if this should come before aDev2. 840 * @return 0 if this and aDev2 are equal. 841 * @return > 0 if this should come after aDev2. 866 842 * 867 843 * @note Must be called from under the object write lock. 868 844 */ 869 int HostUSBDevice::compare (PCUSBDEVICE pDev2)845 int HostUSBDevice::compare (PCUSBDEVICE aDev2) 870 846 { 871 847 AssertReturn (isLockedOnCurrentThread(), -1); 872 848 873 return compare (mUsb, pDev2); 874 } 875 849 return compare (mUsb, aDev2, !isStatePending()); 850 } 876 851 877 852 /** 878 853 * Compares two USB devices and decides which comes first. 879 * 880 * @return < 0 if pDev1 should come before pDev2. 881 * @return 0 if pDev1 and pDev2 are equal. 882 * @return > 0 if pDev1 should come after pDev2. 883 * 884 * @param pDev1 Device 1. 885 * @param pDev2 Device 2. 886 */ 887 /*static*/ int HostUSBDevice::compare (PCUSBDEVICE pDev1, PCUSBDEVICE pDev2) 888 { 889 int iDiff = pDev1->idVendor - pDev2->idVendor; 854 * 855 * If @a aIsStrict is @c true then the comparison will indicate a difference 856 * even if the same physical device (represented by @a aDev1) has been just 857 * re-attached to the host computer (represented by @a aDev2) and got a 858 * different address from the host OS, etc. 859 * 860 * If @a aIsStrict is @c false, then such a re-attached device will be 861 * considered equal to the previous device definition and this function will 862 * retrun 0. 863 * 864 * @param aDev1 Device 1. 865 * @param aDev2 Device 2. 866 * @param aIsStrict @c true to do a strict check and @c false otherwise. 867 868 * @return < 0 if aDev1 should come before aDev2. 869 * @return 0 if aDev1 and aDev2 are equal. 870 * @return > 0 if aDev1 should come after aDev2. 871 */ 872 /*static*/ 873 int HostUSBDevice::compare (PCUSBDEVICE aDev1, PCUSBDEVICE aDev2, 874 bool aIsStrict /* = true */) 875 { 876 int iDiff = aDev1->idVendor - aDev2->idVendor; 890 877 if (iDiff) 891 878 return iDiff; 892 879 893 iDiff = pDev1->idProduct - pDev2->idProduct;880 iDiff = aDev1->idProduct - aDev2->idProduct; 894 881 if (iDiff) 895 882 return iDiff; 896 883 897 /** @todo Sander, will this work on windows as well? Linux won't reuse an address for quite a while. */ 898 return strcmp(pDev1->pszAddress, pDev2->pszAddress); 884 if (!aIsStrict) 885 return 0; 886 887 /* The rest is considered as a strict check. */ 888 889 return strcmp (aDev1->pszAddress, aDev2->pszAddress); 899 890 } 900 891 … … 956 947 case USBDeviceState_USBDeviceAvailable: 957 948 isImportant = false; 949 break; 958 950 default: 959 951 isImportant = true; … … 973 965 case USBDeviceState_USBDeviceAvailable: 974 966 isImportant = false; 967 break; 975 968 default: 976 969 isImportant = true; … … 997 990 case USBDeviceState_USBDeviceBusy: 998 991 isImportant = false; 992 break; 999 993 default: 1000 994 isImportant = true; -
trunk/src/VBox/Main/MachineImpl.cpp
r3007 r3034 7715 7715 7716 7716 AutoCaller autoCaller (this); 7717 AssertComRCReturn (autoCaller.rc(),autoCaller.rc());7718 7719 / / if cautureUSBDevice() fails, it must have set extended error info7717 AssertComRCReturnRC (autoCaller.rc()); 7718 7719 /* if cautureUSBDevice() fails, it must have set extended error info */ 7720 7720 return mParent->host()->captureUSBDevice (this, aId); 7721 7721 } … … 8587 8587 8588 8588 AutoCaller autoCaller (this); 8589 AssertComRCReturn (autoCaller.rc(), autoCaller.rc()); 8589 8590 /* This notification may happen after the machine object has been 8591 * uninitialized (the session was closed), so don't assert. */ 8592 CheckComRCReturnRC (autoCaller.rc()); 8590 8593 8591 8594 ComPtr <IInternalSessionControl> directControl; … … 8595 8598 } 8596 8599 8597 /* ignore notifications sent after #OnSessionEnd() is called */ 8600 /* fail on notifications sent after #OnSessionEnd() is called, it is 8601 * expected by the caller */ 8598 8602 if (!directControl) 8599 return S_OK;8603 return E_FAIL; 8600 8604 8601 8605 return directControl->OnUSBDeviceAttach (aDevice, aError); … … 8611 8615 8612 8616 AutoCaller autoCaller (this); 8613 AssertComRCReturn (autoCaller.rc(), autoCaller.rc()); 8617 8618 /* This notification may happen after the machine object has been 8619 * uninitialized (the session was closed), so don't assert. */ 8620 CheckComRCReturnRC (autoCaller.rc()); 8614 8621 8615 8622 ComPtr <IInternalSessionControl> directControl; … … 8619 8626 } 8620 8627 8621 /* ignore notifications sent after #OnSessionEnd() is called */ 8628 /* fail on notifications sent after #OnSessionEnd() is called, it is 8629 * expected by the caller */ 8622 8630 if (!directControl) 8623 return S_OK;8631 return E_FAIL; 8624 8632 8625 8633 return directControl->OnUSBDeviceDetach (aId, aError); -
trunk/src/VBox/Main/USBProxyService.cpp
r3030 r3034 218 218 DevPtr = *It; 219 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) 220 /* assert that the object is still alive (we still reference it in 221 * the collection and we're the only one who calls uninit() on it */ 222 HostUSBDevice::AutoCaller devCaller (DevPtr.isNull() ? NULL : DevPtr); 223 AssertComRC (devCaller.rc()); 223 224 224 225 /* Lock the device object since we will read/write it's … … 290 291 It = mDevices.erase (It); 291 292 mHost->onUSBDeviceDetached (DevPtr); 292 Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/ 293 Log (("USBProxyService::processChanges: detached %p\n", 294 (HostUSBDevice *)DevPtr)); /** @todo add details .*/ 295 296 /* from now on, the object is no more valid, 297 * uninitialize to avoid abuse */ 298 devCaller.release(); 299 DevPtr->uninit(); 293 300 } 294 301 else … … 321 328 ComObjPtr <HostUSBDevice> DevPtr = *It; 322 329 330 /* assert that the object is still alive (we still reference it in 331 * the collection and we're the only one who calls uninit() on it */ 332 HostUSBDevice::AutoCaller devCaller (DevPtr); 333 AssertComRC (devCaller.rc()); 334 323 335 AutoLock devLock (DevPtr); 324 336 … … 328 340 It = mDevices.erase (It); 329 341 mHost->onUSBDeviceDetached (DevPtr); 330 Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/ 342 Log (("USBProxyService::processChanges: detached %p\n", 343 (HostUSBDevice *)DevPtr)); /** @todo add details .*/ 344 345 /* from now on, the object is no more valid, 346 * uninitialize to avoid abuse */ 347 devCaller.release(); 348 DevPtr->uninit(); 331 349 } 332 350 } -
trunk/src/VBox/Main/include/ConsoleImpl.h
r3001 r3034 372 372 373 373 HRESULT attachUSBDevice (IUSBDevice *aHostDevice, PVUSBIRHCONFIG aConfig); 374 HRESULT detachUSBDevice (USBDeviceList::iterator &aIt); 374 375 375 376 static DECLCALLBACK(int) -
trunk/src/VBox/Main/include/HostImpl.h
r3001 r3034 147 147 } 148 148 149 HRESULT applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice); 149 HRESULT applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice, 150 SessionMachine *aMachine = NULL); 150 151 151 152 bool applyMachineUSBFilters (SessionMachine *aMachine, -
trunk/src/VBox/Main/include/HostUSBDeviceImpl.h
r3001 r3034 95 95 96 96 /* @note Must be called from under the object read lock. */ 97 ComObjPtr <SessionMachine , ComWeakRef> &machine() { return mMachine; }97 ComObjPtr <SessionMachine> &machine() { return mMachine; } 98 98 99 99 /* @note Must be called from under the object read lock. */ … … 117 117 bool isMatch (const USBDeviceFilter::Data &aData); 118 118 119 int compare (PCUSBDEVICE pDev2); 120 static int compare (PCUSBDEVICE pDev1, PCUSBDEVICE pDev2); 119 int compare (PCUSBDEVICE aDev2); 120 static int compare (PCUSBDEVICE aDev1, PCUSBDEVICE aDev2, 121 bool aIsStrict = true); 121 122 122 123 bool updateState (PCUSBDEVICE aDev); … … 130 131 USBDeviceState_T mState; 131 132 USBDeviceState_T mPendingState; 132 ComObjPtr <SessionMachine , ComWeakRef> mMachine;133 ComObjPtr <SessionMachine> mMachine; 133 134 bool mIsStatePending : 1; 134 135
Note:
See TracChangeset
for help on using the changeset viewer.