Changeset 3566 in vbox for trunk/src/VBox/Main/HostUSBDeviceImpl.cpp
- Timestamp:
- Jul 11, 2007 11:15:44 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/HostUSBDeviceImpl.cpp
r3415 r3566 20 20 */ 21 21 22 #include <iprt/types.h> /* for UINT64_C */ 23 22 24 #include "HostUSBDeviceImpl.h" 23 25 #include "MachineImpl.h" … … 108 110 109 111 mPendingState = mState; 112 mPendingStateEx = kNothingPending; 110 113 111 114 /* Other data members */ … … 381 384 382 385 mIsStatePending = true; 386 mPendingSince = 0; 383 387 384 388 /* the VM process will query the object, so leave the lock */ … … 401 405 402 406 mIsStatePending = false; 407 mPendingStateEx = kNothingPending; 403 408 404 409 if (SUCCEEDED (rc)) … … 414 419 mIsStatePending = true; 415 420 mPendingState = USBDeviceState_USBDeviceCaptured; 421 mPendingStateEx = kNothingPending; 422 mPendingSince = RTTimeNanoTS(); 416 423 mMachine = aMachine; 417 424 … … 448 455 mIsStatePending = true; 449 456 mPendingState = USBDeviceState_USBDeviceAvailable; 457 mPendingStateEx = kNothingPending; 458 mPendingSince = RTTimeNanoTS(); 450 459 451 460 mUSBProxyService->releaseDevice (this); … … 482 491 mIsStatePending = true; 483 492 mPendingState = USBDeviceState_USBDeviceHeld; 493 mPendingStateEx = kNothingPending; 494 mPendingSince = RTTimeNanoTS(); 484 495 485 496 mUSBProxyService->captureDevice (this); … … 513 524 * @note Must be called from under the object write lock. 514 525 */ 515 void HostUSBDevice:: reset()526 void HostUSBDevice::onDetachedPhys() 516 527 { 517 528 LogFlowThisFunc (("\n")); … … 524 535 525 536 mIsStatePending = true; 537 mPendingSince = 0; 526 538 527 539 /* the VM process will query the object, so leave the lock */ … … 547 559 alock.enter(); 548 560 549 /* Reset all fields. T the object should have been561 /* Reset all fields. The object should have been 550 562 * uninitialized after this method returns, so it doesn't really 551 563 * matter what state we put it in. */ 552 564 mIsStatePending = false; 553 565 mState = mPendingState = USBDeviceState_USBDeviceNotSupported; 566 mPendingStateEx = kNothingPending; 554 567 mMachine.setNull(); 555 568 } … … 569 582 570 583 AssertReturnVoid (mIsStatePending == true); 571 AssertReturnVoid (mState != USBDeviceState_USBDeviceCaptured );584 AssertReturnVoid (mState != USBDeviceState_USBDeviceCaptured || mPendingStateEx != kNothingPending); 572 585 573 586 bool wasCapture = false; … … 576 589 Bstr errorText; 577 590 578 switch (mPendingState) 579 { 580 case USBDeviceState_USBDeviceCaptured: 581 { 582 if (mState == USBDeviceState_USBDeviceHeld) 591 switch (mPendingStateEx) 592 { 593 case kNothingPending: 594 switch (mPendingState) 583 595 { 584 if (!mMachine.isNull()) 585 wasCapture = true; 586 else 596 case USBDeviceState_USBDeviceCaptured: 587 597 { 588 /* it is a canceled capture request. Give the device back 589 * to the host. */ 590 mPendingState = USBDeviceState_USBDeviceAvailable; 591 mUSBProxyService->releaseDevice (this); 598 if (mState == USBDeviceState_USBDeviceHeld) 599 { 600 if (!mMachine.isNull()) 601 wasCapture = true; 602 else 603 { 604 /* it is a canceled capture request. Give the device back 605 * to the host. */ 606 mPendingState = USBDeviceState_USBDeviceAvailable; 607 mUSBProxyService->releaseDevice (this); 608 } 609 } 610 else 611 { 612 /* couldn't capture the device, will report an error */ 613 wasCapture = true; 614 615 Assert (!mMachine.isNull()); 616 617 /// @todo more detailed error message depending on the state? 618 // probably need some error code/string from the USB proxy itself 619 620 requestRC = E_FAIL; 621 errorText = Utf8StrFmt ( 622 tr ("USB device '%s' with UUID {%Vuuid} is being accessed by the host " 623 "computer and cannot be attached to the virtual machine." 624 "Please try later"), 625 name().raw(), id().raw()); 626 } 627 break; 592 628 } 629 case USBDeviceState_USBDeviceAvailable: 630 { 631 Assert (mMachine.isNull()); 632 633 if (mState == USBDeviceState_USBDeviceHeld) 634 { 635 /* couldn't release the device (give it back to the host). 636 * there is nobody to report an error to (the machine has 637 * already been deassociated because VMM has already detached 638 * the device before requesting a release). */ 639 } 640 else 641 { 642 /* it is a canceled release request. Leave at the host */ 643 /// @todo we may want to re-run all filters in this case 644 } 645 break; 646 } 647 case USBDeviceState_USBDeviceHeld: 648 { 649 if (mState == USBDeviceState_USBDeviceHeld) 650 { 651 /* All right, the device is now held (due to some global 652 * filter). */ 653 break; 654 } 655 else 656 { 657 /* couldn't capture the device requested by the global 658 * filter, there is nobody to report an error to. */ 659 } 660 break; 661 } 662 default: 663 AssertFailed(); 593 664 } 594 else 595 { 596 /* couldn't capture the device, will report an error */ 597 wasCapture = true; 598 599 Assert (!mMachine.isNull()); 600 601 /// @todo more detailed error message depending on the state? 602 // probably need some error code/string from the USB proxy itself 603 604 requestRC = E_FAIL; 605 errorText = Utf8StrFmt ( 606 tr ("USB device '%s' with UUID {%Vuuid} is being accessed by the host " 607 "computer and cannot be attached to the virtual machine." 608 "Please try later"), 609 name().raw(), id().raw()); 610 } 611 break; 612 } 613 case USBDeviceState_USBDeviceAvailable: 614 { 615 Assert (mMachine.isNull()); 616 617 if (mState == USBDeviceState_USBDeviceHeld) 618 { 619 /* couldn't release the device (give it back to the host). 620 * there is nobody to report an error to (the machine has 621 * already been deassociated because VMM has already detached 622 * the device before requesting a release). */ 623 } 624 else 625 { 626 /* it is a canceled release request. Leave at the host */ 627 /// @todo we may want to re-run all filters in this case 628 } 629 break; 630 } 631 case USBDeviceState_USBDeviceHeld: 632 { 633 if (mState == USBDeviceState_USBDeviceHeld) 634 { 635 /* All right, the device is now held (due to some global 636 * filter). */ 637 break; 638 } 639 else 640 { 641 /* couldn't capture the device requested by the global 642 * filter, there is nobody to report an error to. */ 643 } 644 break; 645 } 665 break; 666 667 /* 668 * The device has reappeared, the caller (Host) will (maybe) reapply filters, 669 * since we don't quite know we set the machine to NULL. 670 */ 671 case kDetachingPendingAttachFilters: 672 mMachine.setNull(); 673 break; 674 675 /* 676 * The device has reappeared while the detach operation is still in 677 * progress, just clear the pending operation and leave the machine as is. 678 */ 679 case kDetachingPendingAttach: 680 break; 681 682 case kDetachingPendingDetach: 683 case kDetachingPendingDetachFilters: 646 684 default: 647 AssertFailed(); 685 AssertMsgFailed(("%d\n", mPendingStateEx)); 686 return; 648 687 } 649 688 … … 690 729 mIsStatePending = false; 691 730 mState = mPendingState = USBDeviceState_USBDeviceCaptured; 731 mPendingStateEx = kNothingPending; 692 732 return; 693 733 } … … 700 740 mIsStatePending = false; 701 741 mPendingState = mState; 702 } 703 704 /** 705 * Cancels pending state change due to machine termination. 742 mPendingStateEx = kNothingPending; 743 } 744 745 /** 746 * Cancels pending state change due to machine termination or timeout. 706 747 * 707 748 * @note Must be called from under the object write lock. 708 */ 709 void HostUSBDevice::cancelPendingState() 749 * @param aTimeout Whether this is a timeout or not. 750 */ 751 void HostUSBDevice::cancelPendingState(bool aTimeout /*= false*/) 710 752 { 711 753 LogFlowThisFunc (("\n")); … … 714 756 715 757 AssertReturnVoid (mIsStatePending == true); 716 AssertReturnVoid (!mMachine.isNull()); 717 718 switch (mPendingState) 719 { 720 case USBDeviceState_USBDeviceCaptured: 721 { 722 /* reset mMachine to deassociate it from the filter and tell 723 * handlePendingStateChange() what to do */ 758 AssertReturnVoid (aTimeout || !mMachine.isNull()); 759 760 switch (mPendingStateEx) 761 { 762 case kNothingPending: 763 switch (mPendingState) 764 { 765 case USBDeviceState_USBDeviceCaptured: 766 /* reset mMachine to deassociate it from the filter and tell 767 * handlePendingStateChange() what to do */ 768 mMachine.setNull(); 769 if (!aTimeout) 770 break; 771 case USBDeviceState_USBDeviceAvailable: 772 case USBDeviceState_USBDeviceHeld: 773 if (aTimeout) 774 { 775 mPendingStateEx = kNothingPending; 776 mIsStatePending = false; 777 break; 778 } 779 /* fall thru */ 780 default: 781 AssertFailed(); 782 } 783 break; 784 785 case kDetachingPendingDetach: 786 case kDetachingPendingDetachFilters: 787 case kDetachingPendingAttach: 788 case kDetachingPendingAttachFilters: 724 789 mMachine.setNull(); 725 break; 726 } 790 mPendingStateEx = kNothingPending; 791 mIsStatePending = false; 792 break; 793 727 794 default: 728 AssertFailed(); 795 AssertMsgFailed(("%d\n", mPendingStateEx)); 796 break; 729 797 } 730 798 } … … 848 916 AssertReturn (isLockedOnCurrentThread(), -1); 849 917 850 #ifdef __WIN__851 918 return compare (mUsb, aDev2, !isStatePending()); 852 #else853 /* Since we fake the requests anyway, there is no need to unnecessarily854 expose ourselves to trouble the non-strict compare may cause on855 release/capture/unplug/plug/similar-devices. */856 return compare (mUsb, aDev2, true /* strict */);857 #endif858 919 } 859 920 … … 882 943 bool aIsStrict /* = true */) 883 944 { 945 /* The non-strict checks tries as best as it can to distiguish between 946 different physical devices of the same product. Unfortunately this 947 isn't always possible and we might end up a bit confused in rare cases... */ 948 884 949 int iDiff = aDev1->idVendor - aDev2->idVendor; 885 950 if (iDiff) … … 890 955 return iDiff; 891 956 957 iDiff = aDev1->bcdDevice - aDev2->bcdDevice; 958 if (iDiff) 959 return iDiff; 960 961 if (aDev1->u64SerialHash != aDev2->u64SerialHash) 962 return aDev1->u64SerialHash < aDev2->u64SerialHash ? -1 : 1; 963 892 964 if (!aIsStrict) 893 965 return 0; 894 966 895 /* The rest is considered as a strict check . */896 967 /* The rest is considered as a strict check since it includes bits that 968 may vary on logical reconnects (or whatever you wish to call it). */ 897 969 return strcmp (aDev1->pszAddress, aDev2->pszAddress); 898 970 } … … 957 1029 */ 958 1030 959 LogFlowThisFunc (("aDev->enmState=%d mState=%d mPendingState=%d \n",960 aDev->enmState, mState, mPendingState ));1031 LogFlowThisFunc (("aDev->enmState=%d mState=%d mPendingState=%d mPendingStateEx=%d\n", 1032 aDev->enmState, mState, mPendingState, mPendingStateEx)); 961 1033 962 1034 switch (aDev->enmState) … … 966 1038 case USBDEVICESTATE_UNSUPPORTED: 967 1039 Assert (mState == USBDeviceState_USBDeviceNotSupported); 968 return false; 1040 switch (mState) 1041 { 1042 case USBDeviceState_USBDeviceCaptured: 1043 isImportant = mIsStatePending; 1044 break; 1045 } 1046 return isImportant; 969 1047 970 1048 case USBDEVICESTATE_USED_BY_HOST: … … 1000 1078 isImportant = false; 1001 1079 break; 1080 case USBDeviceState_USBDeviceCaptured: 1002 1081 #ifndef __WIN__ /* Only Windows really knows whether the device is busy or captured. */ 1003 case USBDeviceState_USBDeviceCaptured:1004 1082 if (!mIsStatePending) 1005 1083 return false; 1084 #endif 1085 /* Remain in the captured state if it's an async detach. */ 1086 if (mPendingStateEx != kNothingPending) 1087 { 1088 LogFlowThisFunc (("USBDeviceCaptured - async detach completed (%d)\n", mPendingStateEx)); 1089 return true; 1090 } 1006 1091 /* fall thru */ 1007 #endif1008 1092 default: 1009 1093 /* USBDeviceState_USBDeviceUnavailable: The device has become capturable, re-run filters. */ … … 1065 1149 1066 1150 case USBDEVICESTATE_USED_BY_GUEST: 1067 /* @todo USBDEVICESTATE_USED_BY_GUEST seems not to be used1151 /** @todo USBDEVICESTATE_USED_BY_GUEST seems not to be used 1068 1152 * anywhere in the proxy code; it's quite logical because the 1069 1153 * proxy doesn't know anything about guest VMs. */ … … 1091 1175 } 1092 1176 1177 /** 1178 * Checks for timeout of any pending async operation. 1179 * 1180 * The caller must write lock the object prior to calling 1181 * this method. 1182 */ 1183 void HostUSBDevice::checkForAsyncTimeout() 1184 { 1185 AssertReturnVoid (isLockedOnCurrentThread()); 1186 1187 #ifndef __WIN__ /* no timeouts on windows yet since I don't have all the details here... */ 1188 if (isStatePending() && mPendingSince) 1189 { 1190 uint64_t elapsedNanoseconds = RTTimeNanoTS() - mPendingSince; 1191 if (elapsedNanoseconds > UINT64_C (60000000000) ) /* 60 seconds */ 1192 { 1193 LogRel (("USB: Async operation timed out; mPendingState=%d mPendingStateEx=%d idVendor=%04x (%s) idProduct=%04x (%s) bcdDevice=%04x\n", 1194 mPendingState, mPendingStateEx, mUsb->idVendor, mUsb->pszManufacturer, mUsb->idProduct, mUsb->pszProduct, mUsb->bcdDevice)); 1195 1196 cancelPendingState (true); 1197 } 1198 } 1199 #endif 1200 } 1201 1202 /** 1203 * This method is called by the USB proxy and Host to work the 1204 * logical reconnection operation. 1205 * 1206 * @param aStage kDeatchingPendingDetach, kDeatchingPendingDetachFilters, 1207 * kDetachingPendingAttach or kDetachingPendingAttachFilters. 1208 * 1209 * @returns Success indicator. 1210 */ 1211 bool HostUSBDevice::setLogicalReconnect (InternalState aStage) 1212 { 1213 AssertReturn (isLockedOnCurrentThread(), false); 1214 1215 switch (aStage) 1216 { 1217 case kDetachingPendingDetach: 1218 AssertReturn (!mIsStatePending, false); 1219 mPendingState = mState; 1220 mIsStatePending = true; 1221 mPendingSince = RTTimeNanoTS(); 1222 break; 1223 1224 case kDetachingPendingDetachFilters: 1225 AssertReturn (mIsStatePending, false); 1226 AssertReturn (mPendingStateEx == kDetachingPendingDetach, false); 1227 break; 1228 1229 case kDetachingPendingAttach: 1230 AssertReturn (mIsStatePending, false); 1231 AssertReturn (mPendingStateEx == kDetachingPendingDetach, false); 1232 break; 1233 1234 case kDetachingPendingAttachFilters: 1235 AssertReturn (mIsStatePending, false); 1236 AssertReturn ( mPendingStateEx == kDetachingPendingAttach 1237 || mPendingStateEx == kDetachingPendingDetachFilters, false); 1238 break; 1239 1240 default: 1241 AssertFailedReturn (false); 1242 } 1243 mPendingStateEx = aStage; 1244 return true; 1245 } 1246
Note:
See TracChangeset
for help on using the changeset viewer.