- Timestamp:
- Feb 24, 2022 12:20:43 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
-
include/VBox/vusb.h (modified) (4 diffs)
-
src/VBox/Devices/USB/DevOHCI.cpp (modified) (41 diffs)
-
src/VBox/Devices/USB/DrvVUSBRootHub.cpp (modified) (18 diffs)
-
src/VBox/Devices/USB/VUSBDevice.cpp (modified) (2 diffs)
-
src/VBox/Devices/USB/VUSBInternal.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vusb.h
r93115 r93914 564 564 565 565 566 567 /**568 * VBox USB port bitmap.569 *570 * Bit 0 == Port 0, ... , Bit 127 == Port 127.571 */572 typedef struct VUSBPORTBITMAP573 {574 /** 128 bits */575 char ach[16];576 } VUSBPORTBITMAP;577 /** Pointer to a VBox USB port bitmap. */578 typedef VUSBPORTBITMAP *PVUSBPORTBITMAP;579 580 #ifndef RDESKTOP581 582 /**583 * The VUSB RootHub port interface provided by the HCI (down).584 * Pair with VUSBIROOTCONNECTOR585 */586 typedef struct VUSBIROOTHUBPORT587 {588 /**589 * Get the number of available ports in the hub.590 *591 * @returns The number of ports available.592 * @param pInterface Pointer to this structure.593 * @param pAvailable Bitmap indicating the available ports. Set bit == available port.594 */595 DECLR3CALLBACKMEMBER(unsigned, pfnGetAvailablePorts,(PVUSBIROOTHUBPORT pInterface, PVUSBPORTBITMAP pAvailable));596 597 /**598 * Gets the supported USB versions.599 *600 * @returns The mask of supported USB versions.601 * @param pInterface Pointer to this structure.602 */603 DECLR3CALLBACKMEMBER(uint32_t, pfnGetUSBVersions,(PVUSBIROOTHUBPORT pInterface));604 605 /**606 * A device is being attached to a port in the roothub.607 *608 * @param pInterface Pointer to this structure.609 * @param pDev Pointer to the device being attached.610 * @param uPort The port number assigned to the device.611 */612 DECLR3CALLBACKMEMBER(int, pfnAttach,(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigned uPort));613 614 /**615 * A device is being detached from a port in the roothub.616 *617 * @param pInterface Pointer to this structure.618 * @param pDev Pointer to the device being detached.619 * @param uPort The port number assigned to the device.620 */621 DECLR3CALLBACKMEMBER(void, pfnDetach,(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigned uPort));622 623 /**624 * Reset the root hub.625 *626 * @returns VBox status code.627 * @param pInterface Pointer to this structure.628 * @param pResetOnLinux Whether or not to do real reset on linux.629 */630 DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIROOTHUBPORT pInterface, bool fResetOnLinux));631 632 /**633 * Transfer completion callback routine.634 *635 * VUSB will call this when a transfer have been completed636 * in a one or another way.637 *638 * @param pInterface Pointer to this structure.639 * @param pUrb Pointer to the URB in question.640 */641 DECLR3CALLBACKMEMBER(void, pfnXferCompletion,(PVUSBIROOTHUBPORT pInterface, PVUSBURB urb));642 643 /**644 * Handle transfer errors.645 *646 * VUSB calls this when a transfer attempt failed. This function will respond647 * indicating whether to retry or complete the URB with failure.648 *649 * @returns Retry indicator.650 * @param pInterface Pointer to this structure.651 * @param pUrb Pointer to the URB in question.652 */653 DECLR3CALLBACKMEMBER(bool, pfnXferError,(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb));654 655 /**656 * Processes a new frame if periodic frame processing is enabled.657 *658 * @returns Flag whether there was activity which influences the frame rate.659 * @param pInterface Pointer to this structure.660 * @param u32FrameNo The frame number.661 */662 DECLR3CALLBACKMEMBER(bool, pfnStartFrame, (PVUSBIROOTHUBPORT pInterface, uint32_t u32FrameNo));663 664 /**665 * Informs the callee about a change in the frame rate due to too many idle cycles or666 * when seeing activity after some idle time.667 *668 * @returns nothing.669 * @param pInterface Pointer to this structure.670 * @param u32FrameRate The new frame rate.671 */672 DECLR3CALLBACKMEMBER(void, pfnFrameRateChanged, (PVUSBIROOTHUBPORT pInterface, uint32_t u32FrameRate));673 674 /** Alignment dummy. */675 RTR3PTR Alignment;676 677 } VUSBIROOTHUBPORT;678 /** VUSBIROOTHUBPORT interface ID. */679 # define VUSBIROOTHUBPORT_IID "6571aece-6c33-4714-a8ac-9508a3b8b429"680 681 /** Pointer to a VUSB RootHub connector interface. */682 typedef struct VUSBIROOTHUBCONNECTOR *PVUSBIROOTHUBCONNECTOR;683 /**684 * The VUSB RootHub connector interface provided by the VBox USB RootHub driver685 * (up).686 * Pair with VUSBIROOTHUBPORT.687 */688 typedef struct VUSBIROOTHUBCONNECTOR689 {690 /**691 * Sets the URB parameters for the caller.692 *693 * @returns VBox status code.694 * @param pInterface Pointer to this struct.695 * @param cbHci Size of the data private to the HCI for each URB when allocated.696 * @param cbHciTd Size of one transfer descriptor. The number of transfer descriptors697 * is given VUSBIROOTHUBCONNECTOR::pfnNewUrb for each URB to calculate the698 * final amount of memory required for the TDs.699 *700 * @note This must be called before starting to allocate any URB or otherwise there will be no701 * data available for the HCI.702 */703 DECLR3CALLBACKMEMBER(int, pfnSetUrbParams, (PVUSBIROOTHUBCONNECTOR pInterface, size_t cbHci, size_t cbHciTd));704 705 /**706 * Allocates a new URB for a transfer.707 *708 * Either submit using pfnSubmitUrb or free using VUSBUrbFree().709 *710 * @returns Pointer to a new URB.711 * @returns NULL on failure - try again later.712 * This will not fail if the device wasn't found. We'll fail it713 * at submit time, since that makes the usage of this api simpler.714 * @param pInterface Pointer to this struct.715 * @param DstAddress The destination address of the URB.716 * @param pDev Optional device pointer the URB is for.717 * @param enmType Type of the URB.718 * @param enmDir Data transfer direction.719 * @param cbData The amount of data space required.720 * @param cTds The amount of TD space.721 * @param pszTag Custom URB tag assigned by the caller, only for722 * logged builds and optional.723 *724 * @note pDev should be NULL in most cases. The only useful case is for USB3 where725 * it is required for the SET_ADDRESS request because USB3 uses unicast traffic.726 */727 DECLR3CALLBACKMEMBER(PVUSBURB, pfnNewUrb,(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, PVUSBIDEVICE pDev,728 VUSBXFERTYPE enmType, VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag));729 730 /**731 * Free an URB not submitted yet.732 *733 * @returns VBox status code.734 * @param pInterface Pointer to this struct.735 * @param pUrb Pointer to the URB to free returned by VUSBIROOTHUBCONNECTOR::pfnNewUrb.736 */737 DECLR3CALLBACKMEMBER(int, pfnFreeUrb, (PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb));738 739 /**740 * Submits a URB for transfer.741 * The transfer will do asynchronously if possible.742 *743 * @returns VBox status code.744 * @param pInterface Pointer to this struct.745 * @param pUrb Pointer to the URB returned by pfnNewUrb.746 * The URB will be freed in case of failure.747 * @param pLed Pointer to USB Status LED748 */749 DECLR3CALLBACKMEMBER(int, pfnSubmitUrb,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed));750 751 /**752 * Call to service asynchronous URB completions in a polling fashion.753 *754 * Reaped URBs will be finished by calling the completion callback,755 * thus there is no return code or input or anything from this function756 * except for potential state changes elsewhere.757 *758 * @returns VINF_SUCCESS if no URBs are pending upon return.759 * @returns VERR_TIMEOUT if one or more URBs are still in flight upon returning.760 * @returns Other VBox status code.761 *762 * @param pInterface Pointer to this struct.763 * @param pDevice Pointer to a USB device.764 * @param cMillies Number of milliseconds to poll for completion.765 */766 DECLR3CALLBACKMEMBER(void, pfnReapAsyncUrbs,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice, RTMSINTERVAL cMillies));767 768 /**769 * Cancels and completes - with CRC failure - all URBs queued on an endpoint.770 * This is done in response to guest URB cancellation.771 *772 * @returns VBox status code.773 * @param pInterface Pointer to this struct.774 * @param pUrb Pointer to a previously submitted URB.775 */776 DECLR3CALLBACKMEMBER(int, pfnCancelUrbsEp,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb));777 778 /**779 * Cancels and completes - with CRC failure - all in-flight async URBs.780 * This is typically done before saving a state.781 *782 * @param pInterface Pointer to this struct.783 */784 DECLR3CALLBACKMEMBER(void, pfnCancelAllUrbs,(PVUSBIROOTHUBCONNECTOR pInterface));785 786 /**787 * Cancels and completes - with CRC failure - all URBs queued on an endpoint.788 * This is done in response to a guest endpoint/pipe abort.789 *790 * @returns VBox status code.791 * @param pInterface Pointer to this struct.792 * @param pDevice Pointer to a USB device.793 * @param EndPt Endpoint number.794 * @param enmDir Endpoint direction.795 */796 DECLR3CALLBACKMEMBER(int, pfnAbortEp,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice, int EndPt, VUSBDIRECTION enmDir));797 798 /**799 * Attach the device to the root hub.800 * The device must not be attached to any hub for this call to succeed.801 *802 * @returns VBox status code.803 * @param pInterface Pointer to this struct.804 * @param pDevice Pointer to the device (interface) to attach.805 */806 DECLR3CALLBACKMEMBER(int, pfnAttachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice));807 808 /**809 * Detach the device from the root hub.810 * The device must already be attached for this call to succeed.811 *812 * @returns VBox status code.813 * @param pInterface Pointer to this struct.814 * @param pDevice Pointer to the device (interface) to detach.815 */816 DECLR3CALLBACKMEMBER(int, pfnDetachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice));817 818 /**819 * Sets periodic frame processing.820 *821 * @returns VBox status code.822 * @param pInterface Pointer to this struct.823 * @param uFrameRate The target frame rate in Hertz, 0 disables periodic frame processing.824 * The real frame rate might be lower if there is no activity for a certain period or825 * higher if there is a need for catching up with where the guest expects the device to be.826 */827 DECLR3CALLBACKMEMBER(int, pfnSetPeriodicFrameProcessing, (PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uFrameRate));828 829 /**830 * Returns the current frame rate for the periodic frame processing.831 *832 * @returns Frame rate for periodic frame processing.833 * @retval 0 if disabled.834 * @param pInterface Pointer to this struct.835 */836 DECLR3CALLBACKMEMBER(uint32_t, pfnGetPeriodicFrameRate, (PVUSBIROOTHUBCONNECTOR pInterface));837 838 /**839 * Updates the internally stored isochronous scheduling frame for a given840 * endpoint and returns the delta between the current and previous frame.841 *842 * @returns Delta between currently and previously scheduled frame.843 * @retval 0 if no previous frame was set.844 * @param pInterface Pointer to this struct.845 * @param pDevice Pointer to a USB device.846 * @param EndPt Endpoint number.847 * @param enmDir Endpoint direction.848 * @param uNewFrameID The frame ID of a new transfer.849 * @param uBits The number of significant bits in frame ID.850 */851 DECLR3CALLBACKMEMBER(uint32_t, pfnUpdateIsocFrameDelta, (PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice,852 int EndPt, VUSBDIRECTION enmDir, uint16_t uNewFrameID, uint8_t uBits));853 854 /** Alignment dummy. */855 RTR3PTR Alignment;856 857 } VUSBIROOTHUBCONNECTOR;858 AssertCompileSizeAlignment(VUSBIROOTHUBCONNECTOR, 8);859 /** VUSBIROOTHUBCONNECTOR interface ID. */860 # define VUSBIROOTHUBCONNECTOR_IID "662d7822-b9c6-43b5-88b6-5d59f0106e46"861 862 863 # ifdef IN_RING3864 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnSetUrbParams */865 DECLINLINE(int) VUSBIRhSetUrbParams(PVUSBIROOTHUBCONNECTOR pInterface, size_t cbHci, size_t cbHciTd)866 {867 return pInterface->pfnSetUrbParams(pInterface, cbHci, cbHciTd);868 }869 870 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnNewUrb */871 DECLINLINE(PVUSBURB) VUSBIRhNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, PVUSBIDEVICE pDev,872 VUSBXFERTYPE enmType, VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag)873 {874 return pInterface->pfnNewUrb(pInterface, DstAddress, pDev, enmType, enmDir, cbData, cTds, pszTag);875 }876 877 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnFreeUrb */878 DECLINLINE(int) VUSBIRhFreeUrb(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb)879 {880 return pInterface->pfnFreeUrb(pInterface, pUrb);881 }882 883 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnSubmitUrb */884 DECLINLINE(int) VUSBIRhSubmitUrb(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed)885 {886 return pInterface->pfnSubmitUrb(pInterface, pUrb, pLed);887 }888 889 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnReapAsyncUrbs */890 DECLINLINE(void) VUSBIRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice, RTMSINTERVAL cMillies)891 {892 pInterface->pfnReapAsyncUrbs(pInterface, pDevice, cMillies);893 }894 895 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnCancelAllUrbs */896 DECLINLINE(void) VUSBIRhCancelAllUrbs(PVUSBIROOTHUBCONNECTOR pInterface)897 {898 pInterface->pfnCancelAllUrbs(pInterface);899 }900 901 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnAttachDevice */902 DECLINLINE(int) VUSBIRhAttachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)903 {904 return pInterface->pfnAttachDevice(pInterface, pDevice);905 }906 907 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnDetachDevice */908 DECLINLINE(int) VUSBIRhDetachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)909 {910 return pInterface->pfnDetachDevice(pInterface, pDevice);911 }912 913 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnSetPeriodicFrameProcessing */914 DECLINLINE(int) VUSBIRhSetPeriodicFrameProcessing(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uFrameRate)915 {916 return pInterface->pfnSetPeriodicFrameProcessing(pInterface, uFrameRate);917 }918 919 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnGetPeriodicFrameRate */920 DECLINLINE(uint32_t) VUSBIRhGetPeriodicFrameRate(PVUSBIROOTHUBCONNECTOR pInterface)921 {922 return pInterface->pfnGetPeriodicFrameRate(pInterface);923 }924 # endif /* IN_RING3 */925 926 #endif /* ! RDESKTOP */927 928 929 566 /** 930 567 * VUSB device reset completion callback function. … … 932 569 * 933 570 * @param pDevice Pointer to the virtual USB device core. 571 * @param uPort The port of the device which completed the reset. 934 572 * @param rc The VBox status code of the reset operation. 935 573 * @param pvUser User specific argument. … … 937 575 * @thread The reset thread or EMT. 938 576 */ 939 typedef DECLCALLBACKTYPE(void, FNVUSBRESETDONE,(PVUSBIDEVICE pDevice, int rc, void *pvUser));577 typedef DECLCALLBACKTYPE(void, FNVUSBRESETDONE,(PVUSBIDEVICE pDevice, uint32_t uPort, int rc, void *pvUser)); 940 578 /** Pointer to a device reset completion callback function (FNUSBRESETDONE). */ 941 579 typedef FNVUSBRESETDONE *PFNVUSBRESETDONE; 580 942 581 943 582 /** … … 965 604 VUSB_DEVICE_STATE_32BIT_HACK = 0x7fffffff 966 605 } VUSBDEVICESTATE; 606 607 608 /** Maximum number of USB devices supported. */ 609 #define VUSB_DEVICES_MAX 128 610 /** An invalid device port. */ 611 #define VUSB_DEVICE_PORT_INVALID UINT32_MAX 612 613 /** 614 * VBox USB port bitmap. 615 * 616 * Bit 0 == Port 0, ... , Bit 127 == Port 127. 617 */ 618 typedef struct VUSBPORTBITMAP 619 { 620 /** 128 bits */ 621 char ach[VUSB_DEVICES_MAX / 8]; 622 } VUSBPORTBITMAP; 623 /** Pointer to a VBox USB port bitmap. */ 624 typedef VUSBPORTBITMAP *PVUSBPORTBITMAP; 625 AssertCompile(sizeof(VUSBPORTBITMAP) * 8 >= VUSB_DEVICES_MAX); 626 627 #ifndef RDESKTOP 628 629 /** 630 * The VUSB RootHub port interface provided by the HCI (down). 631 * Pair with VUSBIROOTCONNECTOR 632 */ 633 typedef struct VUSBIROOTHUBPORT 634 { 635 /** 636 * Get the number of available ports in the hub. 637 * 638 * @returns The number of ports available. 639 * @param pInterface Pointer to this structure. 640 * @param pAvailable Bitmap indicating the available ports. Set bit == available port. 641 */ 642 DECLR3CALLBACKMEMBER(unsigned, pfnGetAvailablePorts,(PVUSBIROOTHUBPORT pInterface, PVUSBPORTBITMAP pAvailable)); 643 644 /** 645 * Gets the supported USB versions. 646 * 647 * @returns The mask of supported USB versions. 648 * @param pInterface Pointer to this structure. 649 */ 650 DECLR3CALLBACKMEMBER(uint32_t, pfnGetUSBVersions,(PVUSBIROOTHUBPORT pInterface)); 651 652 /** 653 * A device is being attached to a port in the roothub. 654 * 655 * @param pInterface Pointer to this structure. 656 * @param uPort The port number assigned to the device. 657 * @param enmSpeed The speed of the device being attached. 658 */ 659 DECLR3CALLBACKMEMBER(int, pfnAttach,(PVUSBIROOTHUBPORT pInterface, uint32_t uPort, VUSBSPEED enmSpeed)); 660 661 /** 662 * A device is being detached from a port in the roothub. 663 * 664 * @param pInterface Pointer to this structure. 665 * @param uPort The port number assigned to the device. 666 */ 667 DECLR3CALLBACKMEMBER(void, pfnDetach,(PVUSBIROOTHUBPORT pInterface, uint32_t uPort)); 668 669 /** 670 * Reset the root hub. 671 * 672 * @returns VBox status code. 673 * @param pInterface Pointer to this structure. 674 * @param fResetOnLinux Whether or not to do real reset on linux. 675 */ 676 DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIROOTHUBPORT pInterface, bool fResetOnLinux)); 677 678 /** 679 * Transfer completion callback routine. 680 * 681 * VUSB will call this when a transfer have been completed 682 * in a one or another way. 683 * 684 * @param pInterface Pointer to this structure. 685 * @param pUrb Pointer to the URB in question. 686 */ 687 DECLR3CALLBACKMEMBER(void, pfnXferCompletion,(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb)); 688 689 /** 690 * Handle transfer errors. 691 * 692 * VUSB calls this when a transfer attempt failed. This function will respond 693 * indicating whether to retry or complete the URB with failure. 694 * 695 * @returns Retry indicator. 696 * @param pInterface Pointer to this structure. 697 * @param pUrb Pointer to the URB in question. 698 */ 699 DECLR3CALLBACKMEMBER(bool, pfnXferError,(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb)); 700 701 /** 702 * Processes a new frame if periodic frame processing is enabled. 703 * 704 * @returns Flag whether there was activity which influences the frame rate. 705 * @param pInterface Pointer to this structure. 706 * @param u32FrameNo The frame number. 707 */ 708 DECLR3CALLBACKMEMBER(bool, pfnStartFrame, (PVUSBIROOTHUBPORT pInterface, uint32_t u32FrameNo)); 709 710 /** 711 * Informs the callee about a change in the frame rate due to too many idle cycles or 712 * when seeing activity after some idle time. 713 * 714 * @returns nothing. 715 * @param pInterface Pointer to this structure. 716 * @param u32FrameRate The new frame rate. 717 */ 718 DECLR3CALLBACKMEMBER(void, pfnFrameRateChanged, (PVUSBIROOTHUBPORT pInterface, uint32_t u32FrameRate)); 719 720 /** Alignment dummy. */ 721 RTR3PTR Alignment; 722 723 } VUSBIROOTHUBPORT; 724 /** VUSBIROOTHUBPORT interface ID. */ 725 # define VUSBIROOTHUBPORT_IID "2ece01c2-4dbf-4bd5-96ca-09fc14164cd4" 726 727 /** Pointer to a VUSB RootHub connector interface. */ 728 typedef struct VUSBIROOTHUBCONNECTOR *PVUSBIROOTHUBCONNECTOR; 729 /** 730 * The VUSB RootHub connector interface provided by the VBox USB RootHub driver 731 * (up). 732 * Pair with VUSBIROOTHUBPORT. 733 */ 734 typedef struct VUSBIROOTHUBCONNECTOR 735 { 736 /** 737 * Sets the URB parameters for the caller. 738 * 739 * @returns VBox status code. 740 * @param pInterface Pointer to this struct. 741 * @param cbHci Size of the data private to the HCI for each URB when allocated. 742 * @param cbHciTd Size of one transfer descriptor. The number of transfer descriptors 743 * is given VUSBIROOTHUBCONNECTOR::pfnNewUrb for each URB to calculate the 744 * final amount of memory required for the TDs. 745 * 746 * @note This must be called before starting to allocate any URB or otherwise there will be no 747 * data available for the HCI. 748 */ 749 DECLR3CALLBACKMEMBER(int, pfnSetUrbParams, (PVUSBIROOTHUBCONNECTOR pInterface, size_t cbHci, size_t cbHciTd)); 750 751 /** 752 * Resets the roothub. 753 * 754 * @returns VBox status code. 755 * @param pInterface Pointer to this struct. 756 * @param fResetOnLinux Whether or not to do real reset on linux. 757 */ 758 DECLR3CALLBACKMEMBER(int, pfnReset, (PVUSBIROOTHUBCONNECTOR pInterface, bool fResetOnLinux)); 759 760 /** 761 * Powers on the roothub. 762 * 763 * @returns VBox status code. 764 * @param pInterface Pointer to this struct. 765 */ 766 DECLR3CALLBACKMEMBER(int, pfnPowerOn, (PVUSBIROOTHUBCONNECTOR pInterface)); 767 768 /** 769 * Power off the roothub. 770 * 771 * @returns VBox status code. 772 * @param pInterface Pointer to this struct. 773 */ 774 DECLR3CALLBACKMEMBER(int, pfnPowerOff, (PVUSBIROOTHUBCONNECTOR pInterface)); 775 776 /** 777 * Allocates a new URB for a transfer. 778 * 779 * Either submit using pfnSubmitUrb or free using VUSBUrbFree(). 780 * 781 * @returns Pointer to a new URB. 782 * @returns NULL on failure - try again later. 783 * This will not fail if the device wasn't found. We'll fail it 784 * at submit time, since that makes the usage of this api simpler. 785 * @param pInterface Pointer to this struct. 786 * @param DstAddress The destination address of the URB. 787 * @param uPort Optional port of the device the URB is for, use VUSB_DEVICE_PORT_INVALID to indicate to use the destination address. 788 * @param enmType Type of the URB. 789 * @param enmDir Data transfer direction. 790 * @param cbData The amount of data space required. 791 * @param cTds The amount of TD space. 792 * @param pszTag Custom URB tag assigned by the caller, only for 793 * logged builds and optional. 794 * 795 * @note pDev should be NULL in most cases. The only useful case is for USB3 where 796 * it is required for the SET_ADDRESS request because USB3 uses unicast traffic. 797 */ 798 DECLR3CALLBACKMEMBER(PVUSBURB, pfnNewUrb,(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, uint32_t uPort, 799 VUSBXFERTYPE enmType, VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag)); 800 801 /** 802 * Free an URB not submitted yet. 803 * 804 * @returns VBox status code. 805 * @param pInterface Pointer to this struct. 806 * @param pUrb Pointer to the URB to free returned by VUSBIROOTHUBCONNECTOR::pfnNewUrb. 807 */ 808 DECLR3CALLBACKMEMBER(int, pfnFreeUrb, (PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb)); 809 810 /** 811 * Submits a URB for transfer. 812 * The transfer will do asynchronously if possible. 813 * 814 * @returns VBox status code. 815 * @param pInterface Pointer to this struct. 816 * @param pUrb Pointer to the URB returned by pfnNewUrb. 817 * The URB will be freed in case of failure. 818 * @param pLed Pointer to USB Status LED 819 */ 820 DECLR3CALLBACKMEMBER(int, pfnSubmitUrb,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed)); 821 822 /** 823 * Call to service asynchronous URB completions in a polling fashion. 824 * 825 * Reaped URBs will be finished by calling the completion callback, 826 * thus there is no return code or input or anything from this function 827 * except for potential state changes elsewhere. 828 * 829 * @returns VINF_SUCCESS if no URBs are pending upon return. 830 * @returns VERR_TIMEOUT if one or more URBs are still in flight upon returning. 831 * @returns Other VBox status code. 832 * 833 * @param pInterface Pointer to this struct. 834 * @param uPort Port of the device to reap URBs on. 835 * @param cMillies Number of milliseconds to poll for completion. 836 */ 837 DECLR3CALLBACKMEMBER(void, pfnReapAsyncUrbs,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, RTMSINTERVAL cMillies)); 838 839 /** 840 * Cancels and completes - with CRC failure - all URBs queued on an endpoint. 841 * This is done in response to guest URB cancellation. 842 * 843 * @returns VBox status code. 844 * @param pInterface Pointer to this struct. 845 * @param pUrb Pointer to a previously submitted URB. 846 */ 847 DECLR3CALLBACKMEMBER(int, pfnCancelUrbsEp,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb)); 848 849 /** 850 * Cancels and completes - with CRC failure - all in-flight async URBs. 851 * This is typically done before saving a state. 852 * 853 * @param pInterface Pointer to this struct. 854 */ 855 DECLR3CALLBACKMEMBER(void, pfnCancelAllUrbs,(PVUSBIROOTHUBCONNECTOR pInterface)); 856 857 /** 858 * Cancels and completes - with CRC failure - all URBs queued on an endpoint. 859 * This is done in response to a guest endpoint/pipe abort. 860 * 861 * @returns VBox status code. 862 * @param pInterface Pointer to this struct. 863 * @param uPort Port of the device. 864 * @param EndPt Endpoint number. 865 * @param enmDir Endpoint direction. 866 */ 867 DECLR3CALLBACKMEMBER(int, pfnAbortEp,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, int EndPt, VUSBDIRECTION enmDir)); 868 869 /** 870 * Attach the device to the root hub. 871 * The device must not be attached to any hub for this call to succeed. 872 * 873 * @returns VBox status code. 874 * @param pInterface Pointer to this struct. 875 * @param uPort Port of the device to attach. 876 */ 877 DECLR3CALLBACKMEMBER(int, pfnAttachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)); 878 879 /** 880 * Detach the device from the root hub. 881 * The device must already be attached for this call to succeed. 882 * 883 * @returns VBox status code. 884 * @param pInterface Pointer to this struct. 885 * @param uPort Port of the device to detach. 886 */ 887 DECLR3CALLBACKMEMBER(int, pfnDetachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)); 888 889 /** 890 * Sets periodic frame processing. 891 * 892 * @returns VBox status code. 893 * @param pInterface Pointer to this struct. 894 * @param uFrameRate The target frame rate in Hertz, 0 disables periodic frame processing. 895 * The real frame rate might be lower if there is no activity for a certain period or 896 * higher if there is a need for catching up with where the guest expects the device to be. 897 */ 898 DECLR3CALLBACKMEMBER(int, pfnSetPeriodicFrameProcessing, (PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uFrameRate)); 899 900 /** 901 * Returns the current frame rate for the periodic frame processing. 902 * 903 * @returns Frame rate for periodic frame processing. 904 * @retval 0 if disabled. 905 * @param pInterface Pointer to this struct. 906 */ 907 DECLR3CALLBACKMEMBER(uint32_t, pfnGetPeriodicFrameRate, (PVUSBIROOTHUBCONNECTOR pInterface)); 908 909 /** 910 * Updates the internally stored isochronous scheduling frame for a given 911 * endpoint and returns the delta between the current and previous frame. 912 * 913 * @returns Delta between currently and previously scheduled frame. 914 * @retval 0 if no previous frame was set. 915 * @param pInterface Pointer to this struct. 916 * @param uPort Port of the device. 917 * @param EndPt Endpoint number. 918 * @param enmDir Endpoint direction. 919 * @param uNewFrameID The frame ID of a new transfer. 920 * @param uBits The number of significant bits in frame ID. 921 */ 922 DECLR3CALLBACKMEMBER(uint32_t, pfnUpdateIsocFrameDelta, (PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, 923 int EndPt, VUSBDIRECTION enmDir, uint16_t uNewFrameID, uint8_t uBits)); 924 925 /** 926 * Resets the device. 927 * 928 * Since a device reset shall take at least 10ms from the guest point of view, 929 * it must be performed asynchronously. We create a thread which performs this 930 * operation and ensures it will take at least 10ms. 931 * 932 * At times - like init - a synchronous reset is required, this can be done 933 * by passing NULL for pfnDone. 934 * 935 * -- internal stuff, move it -- 936 * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state. 937 * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful, 938 * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed. 939 * -- internal stuff, move it -- 940 * 941 * @returns VBox status code. 942 * @param pInterface Pointer to this struct. 943 * @param uPort Port of the device to reset. 944 * @param fResetOnLinux Set if we can permit a real reset and a potential logical 945 * device reconnect on linux hosts. 946 * @param pfnDone Pointer to the completion routine. If NULL a synchronous 947 * reset is performed not respecting the 10ms. 948 * @param pvUser User argument to the completion routine. 949 * @param pVM The cross context VM structure. Required if pfnDone 950 * is not NULL. 951 */ 952 DECLR3CALLBACKMEMBER(int, pfnDevReset,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, bool fResetOnLinux, 953 PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM)); 954 955 /** 956 * Powers on the device. 957 * 958 * @returns VBox status code. 959 * @param pInterface Pointer to this struct. 960 * @param uPort Port of the device to power on. 961 */ 962 DECLR3CALLBACKMEMBER(int, pfnDevPowerOn,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)); 963 964 /** 965 * Powers off the device. 966 * 967 * @returns VBox status code. 968 * @param pInterface Pointer to this struct. 969 * @param uPort Port of the device to power off. 970 */ 971 DECLR3CALLBACKMEMBER(int, pfnDevPowerOff,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)); 972 973 /** 974 * Get the state of the device. 975 * 976 * @returns Device state. 977 * @param pInterface Pointer to this struct. 978 * @param uPort Port of the device to get the state for. 979 */ 980 DECLR3CALLBACKMEMBER(VUSBDEVICESTATE, pfnDevGetState,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)); 981 982 /** 983 * Returns whether the device implements the saved state handlers 984 * and doesn't need to get detached. 985 * 986 * @returns true if the device supports saving the state, false otherwise. 987 * @param pInterface Pointer to this struct. 988 * @param uPort Port of the device to query saved state support for. 989 */ 990 DECLR3CALLBACKMEMBER(bool, pfnDevIsSavedStateSupported,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)); 991 992 /** 993 * Get the speed the device is operating at. 994 * 995 * @returns Device state. 996 * @param pInterface Pointer to this struct. 997 * @param uPort Port of the device to query the speed for. 998 */ 999 DECLR3CALLBACKMEMBER(VUSBSPEED, pfnDevGetSpeed,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)); 1000 1001 } VUSBIROOTHUBCONNECTOR; 1002 AssertCompileSizeAlignment(VUSBIROOTHUBCONNECTOR, 8); 1003 /** VUSBIROOTHUBCONNECTOR interface ID. */ 1004 # define VUSBIROOTHUBCONNECTOR_IID "662d7822-b9c6-43b5-88b6-5d59f0106e46" 1005 1006 1007 # ifdef IN_RING3 1008 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnSetUrbParams */ 1009 DECLINLINE(int) VUSBIRhSetUrbParams(PVUSBIROOTHUBCONNECTOR pInterface, size_t cbHci, size_t cbHciTd) 1010 { 1011 return pInterface->pfnSetUrbParams(pInterface, cbHci, cbHciTd); 1012 } 1013 1014 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnNewUrb */ 1015 DECLINLINE(PVUSBURB) VUSBIRhNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, uint32_t uPort, 1016 VUSBXFERTYPE enmType, VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag) 1017 { 1018 return pInterface->pfnNewUrb(pInterface, DstAddress, uPort, enmType, enmDir, cbData, cTds, pszTag); 1019 } 1020 1021 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnFreeUrb */ 1022 DECLINLINE(int) VUSBIRhFreeUrb(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb) 1023 { 1024 return pInterface->pfnFreeUrb(pInterface, pUrb); 1025 } 1026 1027 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnSubmitUrb */ 1028 DECLINLINE(int) VUSBIRhSubmitUrb(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed) 1029 { 1030 return pInterface->pfnSubmitUrb(pInterface, pUrb, pLed); 1031 } 1032 1033 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnReapAsyncUrbs */ 1034 DECLINLINE(void) VUSBIRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, RTMSINTERVAL cMillies) 1035 { 1036 pInterface->pfnReapAsyncUrbs(pInterface, uPort, cMillies); 1037 } 1038 1039 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnCancelAllUrbs */ 1040 DECLINLINE(void) VUSBIRhCancelAllUrbs(PVUSBIROOTHUBCONNECTOR pInterface) 1041 { 1042 pInterface->pfnCancelAllUrbs(pInterface); 1043 } 1044 1045 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnAttachDevice */ 1046 DECLINLINE(int) VUSBIRhAttachDevice(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1047 { 1048 return pInterface->pfnAttachDevice(pInterface, uPort); 1049 } 1050 1051 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnDetachDevice */ 1052 DECLINLINE(int) VUSBIRhDetachDevice(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1053 { 1054 return pInterface->pfnDetachDevice(pInterface, uPort); 1055 } 1056 1057 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnSetPeriodicFrameProcessing */ 1058 DECLINLINE(int) VUSBIRhSetPeriodicFrameProcessing(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uFrameRate) 1059 { 1060 return pInterface->pfnSetPeriodicFrameProcessing(pInterface, uFrameRate); 1061 } 1062 1063 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnGetPeriodicFrameRate */ 1064 DECLINLINE(uint32_t) VUSBIRhGetPeriodicFrameRate(PVUSBIROOTHUBCONNECTOR pInterface) 1065 { 1066 return pInterface->pfnGetPeriodicFrameRate(pInterface); 1067 } 1068 1069 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevReset */ 1070 DECLINLINE(int) VUSBIRhDevReset(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, bool fResetOnLinux, 1071 PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM) 1072 { 1073 return pInterface->pfnDevReset(pInterface, uPort, fResetOnLinux, pfnDone, pvUser, pVM); 1074 } 1075 1076 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevPowerOn */ 1077 DECLINLINE(int) VUSBIRhDevPowerOn(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1078 { 1079 return pInterface->pfnDevPowerOn(pInterface, uPort); 1080 } 1081 1082 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevPowerOff */ 1083 DECLINLINE(int) VUSBIRhDevPowerOff(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1084 { 1085 return pInterface->pfnDevPowerOff(pInterface, uPort); 1086 } 1087 1088 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevGetState */ 1089 DECLINLINE(VUSBDEVICESTATE) VUSBIRhDevGetState(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1090 { 1091 return pInterface->pfnDevGetState(pInterface, uPort); 1092 } 1093 1094 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevGetState */ 1095 DECLINLINE(bool) VUSBIRhDevIsSavedStateSupported(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1096 { 1097 return pInterface->pfnDevIsSavedStateSupported(pInterface, uPort); 1098 } 1099 1100 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevGetSpeed */ 1101 DECLINLINE(VUSBSPEED) VUSBIRhDevGetSpeed(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1102 { 1103 return pInterface->pfnDevGetSpeed(pInterface, uPort); 1104 } 1105 # endif /* IN_RING3 */ 1106 1107 #endif /* ! RDESKTOP */ 1108 967 1109 968 1110 #ifndef RDESKTOP -
trunk/src/VBox/Devices/USB/DevOHCI.cpp
r93115 r93914 136 136 /* Macro to query the number of currently configured ports. */ 137 137 #define OHCI_NDP_CFG(pohci) ((pohci)->RootHub.desc_a & OHCI_RHA_NDP) 138 /** Macro to convert a EHCI port index (zero based) to a VUSB roothub port ID (one based). */ 139 #define OHCI_PORT_2_VUSB_PORT(a_uPort) ((a_uPort) + 1) 138 140 139 141 /** Pointer to OHCI device data. */ … … 180 182 /** The port register. */ 181 183 uint32_t fReg; 182 #if HC_ARCH_BITS == 64 183 uint32_t Alignment0; /**< Align the pointer correctly. */ 184 #endif 185 /** The device attached to the port. */ 186 R3PTRTYPE(PVUSBIDEVICE) pDev; 184 /** Flag whether there is a device attached to the port. */ 185 bool fAttached; 186 bool afPadding[3]; 187 187 } OHCIHUBPORT; 188 #if HC_ARCH_BITS == 64189 AssertCompile(sizeof(OHCIHUBPORT) == 16); /* saved state */190 #endif191 188 /** Pointer to an OHCI hub port. */ 192 189 typedef OHCIHUBPORT *POHCIHUBPORT; … … 222 219 /** Pointer to the connector interface of the VUSB RootHub. */ 223 220 R3PTRTYPE(PVUSBIROOTHUBCONNECTOR) pIRhConn; 224 /** Pointer to the device interface of the VUSB RootHub. */225 R3PTRTYPE(PVUSBIDEVICE) pIDev;226 221 /** The base interface exposed to the roothub driver. */ 227 222 PDMIBASE IBase; … … 241 236 /** Pointer to the OHCI ring-3 root hub data. */ 242 237 typedef OHCIROOTHUBR3 *POHCIROOTHUBR3; 243 244 245 /**246 * Data used for reattaching devices on a state load.247 */248 typedef struct OHCILOAD249 {250 /** Timer used once after state load to inform the guest about new devices.251 * We do this to be sure the guest get any disconnect / reconnect on the252 * same port. */253 TMTIMERHANDLE hTimer;254 /** Number of detached devices. */255 unsigned cDevs;256 /** Array of devices which were detached. */257 PVUSBIDEVICE apDevs[OHCI_NDP_MAX];258 } OHCILOAD;259 /** Pointer to an OHCILOAD structure. */260 typedef OHCILOAD *POHCILOAD;261 238 262 239 #ifdef VBOX_WITH_OHCI_PHYS_READ_CACHE … … 283 260 uint32_t fno : 1; 284 261 262 /** Align roothub structure on a 8-byte boundary. */ 263 uint32_t u32Alignment0; 285 264 /** Root hub device, shared data. */ 286 265 OHCIROOTHUB RootHub; … … 423 402 RTCRITSECT CritSect; 424 403 425 /** Pointer to state load data. */426 R3PTRTYPE(POHCILOAD) pLoad;427 404 /** The restored periodic frame rate. */ 428 405 uint32_t uRestoredPeriodicFrameRate; … … 890 867 #ifdef IN_RING3 891 868 /* Update host controller state to reflect a device attach */ 892 static void ohciR3RhPortPower(POHCIROOTHUB pRh, unsigned iPort, bool fPowerUp);869 static void ohciR3RhPortPower(POHCIROOTHUBR3 pRh, unsigned iPort, bool fPowerUp); 893 870 static void ohciR3BusResume(PPDMDEVINS pDevIns, POHCI pOhci, POHCICC pThisCC, bool fHardware); 894 871 static void ohciR3BusStop(POHCICC pThisCC); … … 1040 1017 1041 1018 for (unsigned iPort = 0; iPort < OHCI_NDP_CFG(pThis); iPort++) 1042 if (!pThis->RootHub.aPorts[iPort]. pDev)1019 if (!pThis->RootHub.aPorts[iPort].fAttached) 1043 1020 { 1044 1021 cPorts++; … … 1064 1041 1065 1042 1066 /** 1067 * A device is being attached to a port in the roothub. 1068 * 1069 * @param pInterface Pointer to this structure. 1070 * @param pDev Pointer to the device being attached. 1071 * @param uPort The port number assigned to the device. 1072 */ 1073 static DECLCALLBACK(int) ohciR3RhAttach(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigned uPort) 1043 /** @interface_method_impl{VUSBIROOTHUBPORT,pfnAttach} */ 1044 static DECLCALLBACK(int) ohciR3RhAttach(PVUSBIROOTHUBPORT pInterface, uint32_t uPort, VUSBSPEED enmSpeed) 1074 1045 { 1075 1046 POHCICC pThisCC = VUSBIROOTHUBPORT_2_OHCI(pInterface); 1076 1047 PPDMDEVINS pDevIns = pThisCC->pDevInsR3; 1077 1048 POHCI pThis = PDMDEVINS_2_DATA(pDevIns, POHCI); 1078 VUSBSPEED enmSpeed; 1079 LogFlow(("ohciR3RhAttach: pDev=%p uPort=%u\n", pDev, uPort)); 1049 LogFlow(("ohciR3RhAttach: uPort=%u\n", uPort)); 1080 1050 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VERR_IGNORED); 1081 1051 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, pDevIns->pCritSectRoR3, rcLock); … … 1086 1056 Assert(uPort >= 1 && uPort <= OHCI_NDP_CFG(pThis)); 1087 1057 uPort--; 1088 Assert(!pThis->RootHub.aPorts[uPort].pDev); 1089 enmSpeed = pDev->pfnGetSpeed(pDev); 1058 Assert(!pThis->RootHub.aPorts[uPort].fAttached); 1090 1059 /* Only LS/FS devices should end up here. */ 1091 1060 Assert(enmSpeed == VUSB_SPEED_LOW || enmSpeed == VUSB_SPEED_FULL); … … 1097 1066 if (enmSpeed == VUSB_SPEED_LOW) 1098 1067 pThis->RootHub.aPorts[uPort].fReg |= OHCI_PORT_LSDA; 1099 pThis->RootHub.aPorts[uPort]. pDev = pDev;1100 ohciR3RhPortPower(&pThis ->RootHub, uPort, 1 /* power on */);1068 pThis->RootHub.aPorts[uPort].fAttached = true; 1069 ohciR3RhPortPower(&pThisCC->RootHub, uPort, 1 /* power on */); 1101 1070 1102 1071 ohciR3RemoteWakeup(pDevIns, pThis, pThisCC); … … 1112 1081 * 1113 1082 * @param pInterface Pointer to this structure. 1114 * @param pDev Pointer to the device being detached.1115 1083 * @param uPort The port number assigned to the device. 1116 1084 */ 1117 static DECLCALLBACK(void) ohciR3RhDetach(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigneduPort)1085 static DECLCALLBACK(void) ohciR3RhDetach(PVUSBIROOTHUBPORT pInterface, uint32_t uPort) 1118 1086 { 1119 1087 POHCICC pThisCC = VUSBIROOTHUBPORT_2_OHCI(pInterface); 1120 1088 PPDMDEVINS pDevIns = pThisCC->pDevInsR3; 1121 1089 POHCI pThis = PDMDEVINS_2_DATA(pDevIns, POHCI); 1122 RT_NOREF(pDev); 1123 LogFlow(("ohciR3RhDetach: pDev=%p uPort=%u\n", pDev, uPort)); 1090 LogFlow(("ohciR3RhDetach: uPort=%u\n", uPort)); 1124 1091 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VERR_IGNORED); 1125 1092 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, pDevIns->pCritSectRoR3, rcLock); … … 1130 1097 Assert(uPort >= 1 && uPort <= OHCI_NDP_CFG(pThis)); 1131 1098 uPort--; 1132 Assert(pThis->RootHub.aPorts[uPort]. pDev == pDev);1099 Assert(pThis->RootHub.aPorts[uPort].fAttached); 1133 1100 1134 1101 /* 1135 1102 * Detach it. 1136 1103 */ 1137 pThis->RootHub.aPorts[uPort]. pDev = NULL;1104 pThis->RootHub.aPorts[uPort].fAttached = false; 1138 1105 if (pThis->RootHub.aPorts[uPort].fReg & OHCI_PORT_PES) 1139 1106 pThis->RootHub.aPorts[uPort].fReg = OHCI_PORT_CSC | OHCI_PORT_PESC; … … 1156 1123 * 1157 1124 * @param pDev The root hub device. 1125 * @param uPort The port of the device completing the reset. 1158 1126 * @param rc The result of the operation. 1159 1127 * @param pvUser Pointer to the controller. 1160 1128 */ 1161 static DECLCALLBACK(void) ohciR3RhResetDoneOneDev(PVUSBIDEVICE pDev, int rc, void *pvUser)1129 static DECLCALLBACK(void) ohciR3RhResetDoneOneDev(PVUSBIDEVICE pDev, uint32_t uPort, int rc, void *pvUser) 1162 1130 { 1163 1131 LogRel(("OHCI: root hub reset completed with %Rrc\n", rc)); 1164 NOREF(pDev); NOREF(rc); NOREF(pvUser);1132 RT_NOREF(pDev, uPort, rc, pvUser); 1165 1133 } 1166 1134 … … 1205 1173 for (unsigned iPort = 0; iPort < OHCI_NDP_CFG(pThis); iPort++) 1206 1174 { 1207 if (pThis->RootHub.aPorts[iPort]. pDev)1175 if (pThis->RootHub.aPorts[iPort].fAttached) 1208 1176 { 1209 1177 pThis->RootHub.aPorts[iPort].fReg = OHCI_PORT_CCS | OHCI_PORT_CSC | OHCI_PORT_PPS; … … 1211 1179 { 1212 1180 PVM pVM = PDMDevHlpGetVM(pDevIns); 1213 VUSBIDevReset(pThis->RootHub.aPorts[iPort].pDev, fResetOnLinux, ohciR3RhResetDoneOneDev, pThis, pVM); 1181 VUSBIRhDevReset(pThisCC->RootHub.pIRhConn, OHCI_PORT_2_VUSB_PORT(iPort), fResetOnLinux, 1182 ohciR3RhResetDoneOneDev, pThis, pVM); 1214 1183 } 1215 1184 } … … 1310 1279 */ 1311 1280 if (fNewMode == OHCI_USB_RESET) 1312 VUSBIDevReset(pThisCC->RootHub.pIDev, fResetOnLinux, NULL, NULL, NULL);1281 pThisCC->RootHub.pIRhConn->pfnReset(pThisCC->RootHub.pIRhConn, fResetOnLinux); 1313 1282 } 1314 1283 … … 3095 3064 * Allocate and initialize a new URB. 3096 3065 */ 3097 PVUSBURB pUrb = VUSBIRhNewUrb(pThisCC->RootHub.pIRhConn, pEd->hwinfo & ED_HWINFO_FUNCTION, NULL,3066 PVUSBURB pUrb = VUSBIRhNewUrb(pThisCC->RootHub.pIRhConn, pEd->hwinfo & ED_HWINFO_FUNCTION, VUSB_DEVICE_PORT_INVALID, 3098 3067 enmType, enmDir, Buf.cbTotal, 1, NULL); 3099 3068 if (!pUrb) … … 3265 3234 * Allocate and initialize a new URB. 3266 3235 */ 3267 PVUSBURB pUrb = VUSBIRhNewUrb(pThisCC->RootHub.pIRhConn, pEd->hwinfo & ED_HWINFO_FUNCTION, NULL,3236 PVUSBURB pUrb = VUSBIRhNewUrb(pThisCC->RootHub.pIRhConn, pEd->hwinfo & ED_HWINFO_FUNCTION, VUSB_DEVICE_PORT_INVALID, 3268 3237 enmType, enmDir, cbTotal, cTds, "ohciR3ServiceTdMultiple"); 3269 3238 if (!pUrb) … … 3499 3468 * Allocate and initialize a new URB. 3500 3469 */ 3501 PVUSBURB pUrb = VUSBIRhNewUrb(pThisCC->RootHub.pIRhConn, pEd->hwinfo & ED_HWINFO_FUNCTION, NULL,3470 PVUSBURB pUrb = VUSBIRhNewUrb(pThisCC->RootHub.pIRhConn, pEd->hwinfo & ED_HWINFO_FUNCTION, VUSB_DEVICE_PORT_INVALID, 3502 3471 VUSBXFERTYPE_ISOC, enmDir, cbTotal, 1, NULL); 3503 3472 if (!pUrb) … … 4405 4374 static void ohciR3BusStart(PPDMDEVINS pDevIns, POHCI pThis, POHCICC pThisCC) 4406 4375 { 4407 VUSBIDevPowerOn(pThisCC->RootHub.pIDev);4376 pThisCC->RootHub.pIRhConn->pfnPowerOn(pThisCC->RootHub.pIRhConn); 4408 4377 pThis->dqic = 0x7; 4409 4378 … … 4423 4392 int rc = pThisCC->RootHub.pIRhConn->pfnSetPeriodicFrameProcessing(pThisCC->RootHub.pIRhConn, 0); 4424 4393 AssertRC(rc); 4425 VUSBIDevPowerOff(pThisCC->RootHub.pIDev);4394 pThisCC->RootHub.pIRhConn->pfnPowerOff(pThisCC->RootHub.pIRhConn); 4426 4395 } 4427 4396 … … 4446 4415 4447 4416 /* Power a port up or down */ 4448 static void ohciR3RhPortPower(POHCIROOTHUB pRh, unsigned iPort, bool fPowerUp)4417 static void ohciR3RhPortPower(POHCIROOTHUBR3 pRh, unsigned iPort, bool fPowerUp) 4449 4418 { 4450 4419 POHCIHUBPORT pPort = &pRh->aPorts[iPort]; … … 4456 4425 { 4457 4426 /* power up */ 4458 if (pPort-> pDev)4427 if (pPort->fAttached) 4459 4428 pPort->fReg |= OHCI_PORT_CCS; 4460 4429 if (pPort->fReg & OHCI_PORT_CCS) 4461 4430 pPort->fReg |= OHCI_PORT_PPS; 4462 if (pPort-> pDev&& !fOldPPS)4463 VUSBI DevPowerOn(pPort->pDev);4431 if (pPort->fAttached && !fOldPPS) 4432 VUSBIRhDevPowerOn(pRh->pIRhConn, OHCI_PORT_2_VUSB_PORT(iPort)); 4464 4433 } 4465 4434 else … … 4467 4436 /* power down */ 4468 4437 pPort->fReg &= ~(OHCI_PORT_PPS | OHCI_PORT_CCS | OHCI_PORT_PSS | OHCI_PORT_PRS); 4469 if (pPort-> pDev&& fOldPPS)4470 VUSBI DevPowerOff(pPort->pDev);4438 if (pPort->fAttached && fOldPPS) 4439 VUSBIRhDevPowerOff(pRh->pIRhConn, OHCI_PORT_2_VUSB_PORT(iPort)); 4471 4440 } 4472 4441 } … … 4563 4532 * that correctly in the roothub reset callback yet. check it's 4564 4533 * comments and argument for more details. */ 4565 VUSBIDevReset(pThisCC->RootHub.pIDev, false /* don't do a real reset */, NULL, NULL, NULL);4534 pThisCC->RootHub.pIRhConn->pfnReset(pThisCC->RootHub.pIRhConn, false /* don't do a real reset */); 4566 4535 break; 4567 4536 } … … 5210 5179 { 5211 5180 #ifdef IN_RING3 5181 POHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, POHCICC); 5182 5212 5183 /* log */ 5213 5184 uint32_t old = pThis->RootHub.status; … … 5231 5202 Log2(("ohci: global power up\n")); 5232 5203 for (i = 0; i < OHCI_NDP_CFG(pThis); i++) 5233 ohciR3RhPortPower(&pThis ->RootHub, i, true /* power up */);5204 ohciR3RhPortPower(&pThisCC->RootHub, i, true /* power up */); 5234 5205 } 5235 5206 … … 5240 5211 Log2(("ohci: global power down\n")); 5241 5212 for (i = 0; i < OHCI_NDP_CFG(pThis); i++) 5242 ohciR3RhPortPower(&pThis ->RootHub, i, false /* power down */);5213 ohciR3RhPortPower(&pThisCC->RootHub, i, false /* power down */); 5243 5214 } 5244 5215 … … 5296 5267 * @thread EMT. 5297 5268 */ 5298 static DECLCALLBACK(void) ohciR3PortResetDone(PVUSBIDEVICE pDev, int rc, void *pvUser) 5299 { 5300 PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser; 5301 POHCI pThis = PDMDEVINS_2_DATA(pDevIns, POHCI); 5302 5303 /* 5304 * Find the port in question 5305 */ 5306 POHCIHUBPORT pPort = NULL; 5307 unsigned iPort; 5308 for (iPort = 0; iPort < OHCI_NDP_CFG(pThis); iPort++) /* lazy bird */ 5309 if (pThis->RootHub.aPorts[iPort].pDev == pDev) 5310 { 5311 pPort = &pThis->RootHub.aPorts[iPort]; 5312 break; 5313 } 5314 if (!pPort) 5315 { 5316 Assert(pPort); /* sometimes happens because of @bugref{1510} */ 5317 return; 5318 } 5269 static DECLCALLBACK(void) ohciR3PortResetDone(PVUSBIDEVICE pDev, uint32_t uPort, int rc, void *pvUser) 5270 { 5271 RT_NOREF(pDev); 5272 5273 Assert(uPort >= 1); 5274 PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser; 5275 POHCI pThis = PDMDEVINS_2_DATA(pDevIns, POHCI); 5276 POHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, POHCICC); 5277 POHCIHUBPORT pPort = &pThis->RootHub.aPorts[uPort - 1]; 5319 5278 5320 5279 if (RT_SUCCESS(rc)) … … 5330 5289 { 5331 5290 /* desperate measures. */ 5332 if ( pPort-> pDev5333 && VUSBI DevGetState(pPort->pDev) == VUSB_DEVICE_STATE_ATTACHED)5291 if ( pPort->fAttached 5292 && VUSBIRhDevGetState(pThisCC->RootHub.pIRhConn, uPort) == VUSB_DEVICE_STATE_ATTACHED) 5334 5293 { 5335 5294 /* … … 5396 5355 #ifdef IN_RING3 5397 5356 const unsigned i = iReg - 21; 5357 POHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, POHCICC); 5398 5358 POHCIHUBPORT p = &pThis->RootHub.aPorts[i]; 5399 5359 uint32_t old_state = p->fReg; … … 5443 5403 PVM pVM = PDMDevHlpGetVM(pDevIns); 5444 5404 p->fReg &= ~OHCI_PORT_PRSC; 5445 VUSBIDevReset(p->pDev, false /* don't reset on linux */, ohciR3PortResetDone, pDevIns, pVM); 5405 VUSBIRhDevReset(pThisCC->RootHub.pIRhConn, OHCI_PORT_2_VUSB_PORT(i), false /* don't reset on linux */, 5406 ohciR3PortResetDone, pDevIns, pVM); 5446 5407 } 5447 5408 else if (p->fReg & OHCI_PORT_PRS) … … 5460 5421 */ 5461 5422 if (val & OHCI_PORT_CLRPP) 5462 ohciR3RhPortPower(&pThis ->RootHub, i, false /* power down */);5423 ohciR3RhPortPower(&pThisCC->RootHub, i, false /* power down */); 5463 5424 if (val & OHCI_PORT_PPS) 5464 ohciR3RhPortPower(&pThis ->RootHub, i, true /* power up */);5425 ohciR3RhPortPower(&pThisCC->RootHub, i, true /* power up */); 5465 5426 } 5466 5427 … … 5468 5429 if (val & OHCI_PORT_CLRSS) 5469 5430 { 5470 ohciR3RhPortPower(&pThis ->RootHub, i, true /* power up */);5431 ohciR3RhPortPower(&pThisCC->RootHub, i, true /* power up */); 5471 5432 pThis->RootHub.aPorts[i].fReg &= ~OHCI_PORT_PSS; 5472 5433 pThis->RootHub.aPorts[i].fReg |= OHCI_PORT_PSSC; … … 5614 5575 5615 5576 /** 5616 * Prepares for state saving. 5617 * All URBs needs to be canceled. 5577 * Saves the state of the OHCI device. 5618 5578 * 5619 5579 * @returns VBox status code. … … 5621 5581 * @param pSSM The handle to save the state to. 5622 5582 */ 5623 static DECLCALLBACK(int) ohciR3SavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)5624 {5625 RT_NOREF(pSSM);5626 POHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, POHCICC);5627 POHCI pThis = PDMDEVINS_2_DATA(pDevIns, POHCI);5628 LogFlow(("ohciR3SavePrep: \n"));5629 5630 /*5631 * Detach all proxied devices.5632 */5633 int rc = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VERR_IGNORED);5634 AssertRCReturn(rc, rc);5635 5636 /** @todo this won't work well when continuing after saving! */5637 for (unsigned i = 0; i < RT_ELEMENTS(pThis->RootHub.aPorts); i++)5638 {5639 PVUSBIDEVICE pDev = pThis->RootHub.aPorts[i].pDev;5640 if (pDev)5641 {5642 if (!VUSBIDevIsSavedStateSupported(pDev))5643 {5644 VUSBIRhDetachDevice(pThisCC->RootHub.pIRhConn, pDev);5645 /*5646 * Save the device pointers here so we can reattach them afterwards.5647 * This will work fine even if the save fails since the Done handler is5648 * called unconditionally if the Prep handler was called.5649 */5650 pThis->RootHub.aPorts[i].pDev = pDev;5651 }5652 }5653 }5654 5655 PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3);5656 5657 /*5658 * Kill old load data which might be hanging around.5659 */5660 if (pThisCC->pLoad)5661 {5662 PDMDevHlpTimerDestroy(pDevIns, pThisCC->pLoad->hTimer);5663 PDMDevHlpMMHeapFree(pDevIns, pThisCC->pLoad);5664 pThisCC->pLoad = NULL;5665 }5666 return VINF_SUCCESS;5667 }5668 5669 5670 /**5671 * Saves the state of the OHCI device.5672 *5673 * @returns VBox status code.5674 * @param pDevIns The device instance.5675 * @param pSSM The handle to save the state to.5676 */5677 5583 static DECLCALLBACK(int) ohciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 5678 5584 { … … 5686 5592 /* Save the periodic frame rate so we can we can tell if the bus was started or not when restoring. */ 5687 5593 return pDevIns->pHlpR3->pfnSSMPutU32(pSSM, VUSBIRhGetPeriodicFrameRate(pThisCC->RootHub.pIRhConn)); 5688 }5689 5690 5691 /**5692 * Done state save operation.5693 *5694 * @returns VBox load code.5695 * @param pDevIns Device instance of the device which registered the data unit.5696 * @param pSSM SSM operation handle.5697 */5698 static DECLCALLBACK(int) ohciR3SaveDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)5699 {5700 POHCI pThis = PDMDEVINS_2_DATA(pDevIns, POHCI);5701 POHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, POHCICC);5702 LogFlow(("ohciR3SaveDone:\n"));5703 RT_NOREF(pSSM);5704 5705 /*5706 * NULL the dev pointers.5707 */5708 POHCIROOTHUB pRh = &pThis->RootHub;5709 OHCIROOTHUB Rh = *pRh;5710 for (unsigned i = 0; i < RT_ELEMENTS(pRh->aPorts); i++)5711 {5712 if ( pRh->aPorts[i].pDev5713 && !VUSBIDevIsSavedStateSupported(pRh->aPorts[i].pDev))5714 pRh->aPorts[i].pDev = NULL;5715 }5716 5717 /*5718 * Attach the devices.5719 */5720 for (unsigned i = 0; i < RT_ELEMENTS(pRh->aPorts); i++)5721 {5722 PVUSBIDEVICE pDev = Rh.aPorts[i].pDev;5723 if ( pDev5724 && !VUSBIDevIsSavedStateSupported(pDev))5725 VUSBIRhAttachDevice(pThisCC->RootHub.pIRhConn, pDev);5726 }5727 5728 return VINF_SUCCESS;5729 }5730 5731 5732 /**5733 * Prepare loading the state of the OHCI device.5734 * This must detach the devices currently attached and save5735 * the up for reconnect after the state load have been completed5736 *5737 * @returns VBox status code.5738 * @param pDevIns The device instance.5739 * @param pSSM The handle to the saved state.5740 */5741 static DECLCALLBACK(int) ohciR3LoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)5742 {5743 POHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, POHCICC);5744 POHCI pThis = PDMDEVINS_2_DATA(pDevIns, POHCI);5745 LogFlow(("ohciR3LoadPrep:\n"));5746 RT_NOREF(pSSM);5747 5748 if (!pThisCC->pLoad)5749 {5750 /*5751 * Detach all devices which are present in this session. Save them in the load5752 * structure so we can reattach them after restoring the guest.5753 */5754 POHCIROOTHUB pRh = &pThis->RootHub;5755 OHCILOAD Load;5756 Load.hTimer = NIL_TMTIMERHANDLE;5757 Load.cDevs = 0;5758 for (unsigned i = 0; i < RT_ELEMENTS(pRh->aPorts); i++)5759 {5760 PVUSBIDEVICE pDev = pRh->aPorts[i].pDev;5761 if ( pDev5762 && !VUSBIDevIsSavedStateSupported(pDev))5763 {5764 Load.apDevs[Load.cDevs++] = pDev;5765 VUSBIRhDetachDevice(pThisCC->RootHub.pIRhConn, pDev);5766 Assert(!pRh->aPorts[i].pDev);5767 }5768 }5769 5770 /*5771 * Any devices to reattach, if so duplicate the Load struct.5772 */5773 if (Load.cDevs)5774 {5775 pThisCC->pLoad = (POHCILOAD)PDMDevHlpMMHeapAlloc(pDevIns, sizeof(Load));5776 if (!pThisCC->pLoad)5777 return VERR_NO_MEMORY;5778 *pThisCC->pLoad = Load;5779 }5780 }5781 /* else: we ASSUME no device can be attached or detach in the period5782 * between a state load and the pLoad stuff is processed. */5783 return VINF_SUCCESS;5784 5594 } 5785 5595 … … 5847 5657 5848 5658 /** 5849 * @callback_method_impl{FNTMTIMERDEV,5850 * Reattaches devices after a saved state load.}5851 */5852 static DECLCALLBACK(void) ohciR3LoadReattachDevices(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, void *pvUser)5853 {5854 POHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, POHCICC);5855 POHCILOAD pLoad = pThisCC->pLoad;5856 LogFlow(("ohciR3LoadReattachDevices:\n"));5857 Assert(hTimer == pLoad->hTimer); RT_NOREF(pvUser);5858 5859 /*5860 * Reattach devices.5861 */5862 for (unsigned i = 0; i < pLoad->cDevs; i++)5863 VUSBIRhAttachDevice(pThisCC->RootHub.pIRhConn, pLoad->apDevs[i]);5864 5865 /*5866 * Cleanup.5867 */5868 PDMDevHlpTimerDestroy(pDevIns, hTimer);5869 pLoad->hTimer = NIL_TMTIMERHANDLE;5870 PDMDevHlpMMHeapFree(pDevIns, pLoad);5871 pThisCC->pLoad = NULL;5872 }5873 5874 5875 /**5876 * Done state load operation.5877 *5878 * @returns VBox load code.5879 * @param pDevIns Device instance of the device which registered the data unit.5880 * @param pSSM SSM operation handle.5881 */5882 static DECLCALLBACK(int) ohciR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)5883 {5884 POHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, POHCICC);5885 LogFlow(("ohciR3LoadDone:\n"));5886 RT_NOREF(pSSM);5887 5888 /*5889 * Start a timer if we've got devices to reattach5890 */5891 if (pThisCC->pLoad)5892 {5893 int rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL, ohciR3LoadReattachDevices, NULL /*pvUser*/,5894 TMTIMER_FLAGS_NO_CRIT_SECT | TMTIMER_FLAGS_NO_RING0, "OHCI reattach on load",5895 &pThisCC->pLoad->hTimer);5896 if (RT_SUCCESS(rc))5897 rc = PDMDevHlpTimerSetMillies(pDevIns, pThisCC->pLoad->hTimer, 250);5898 return rc;5899 }5900 5901 return VINF_SUCCESS;5902 }5903 5904 5905 /**5906 5659 * Reset notification. 5907 5660 * … … 6153 5906 rc = PDMDevHlpSSMRegisterEx(pDevIns, OHCI_SAVED_STATE_VERSION, sizeof(*pThis), NULL, 6154 5907 NULL, NULL, NULL, 6155 ohciR3SavePrep, ohciR3SaveExec, ohciR3SaveDone,6156 ohciR3LoadPrep, ohciR3LoadExec, ohciR3LoadDone);5908 NULL, ohciR3SaveExec, NULL, 5909 NULL, ohciR3LoadExec, NULL); 6157 5910 AssertRCReturn(rc, rc); 6158 5911 … … 6169 5922 AssertMsgReturn(pThisCC->RootHub.pIRhConn, 6170 5923 ("Configuration error: The driver doesn't provide the VUSBIROOTHUBCONNECTOR interface!\n"), 6171 VERR_PDM_MISSING_INTERFACE);6172 pThisCC->RootHub.pIDev = PDMIBASE_QUERY_INTERFACE(pThisCC->RootHub.pIBase, VUSBIDEVICE);6173 AssertMsgReturn(pThisCC->RootHub.pIDev,6174 ("Configuration error: The driver doesn't provide the VUSBIDEVICE interface!\n"),6175 5924 VERR_PDM_MISSING_INTERFACE); 6176 5925 -
trunk/src/VBox/Devices/USB/DrvVUSBRootHub.cpp
r93115 r93914 220 220 221 221 222 #define VUSB_ROOTHUB_SAVED_STATE_VERSION 1 223 224 225 /** 226 * Data used for reattaching devices on a state load. 227 */ 228 typedef struct VUSBROOTHUBLOAD 229 { 230 /** Timer used once after state load to inform the guest about new devices. 231 * We do this to be sure the guest get any disconnect / reconnect on the 232 * same port. */ 233 TMTIMERHANDLE hTimer; 234 /** Number of detached devices. */ 235 unsigned cDevs; 236 /** Array of devices which were detached. */ 237 PVUSBDEV apDevs[VUSB_DEVICES_MAX]; 238 } VUSBROOTHUBLOAD; 239 240 241 /** 242 * Returns the attached VUSB device for the given port or NULL if none is attached. 243 * 244 * @returns Pointer to the VUSB device or NULL if not found. 245 * @param pThis The VUSB roothub device instance. 246 * @param uPort The port to get the device for. 247 * 248 * @note The reference count of the VUSB device structure is retained to prevent it from going away. 249 */ 250 static PVUSBDEV vusbR3RhGetVUsbDevByPortRetain(PVUSBROOTHUB pThis, uint32_t uPort) 251 { 252 PVUSBDEV pDev = NULL; 253 254 AssertReturn(uPort < RT_ELEMENTS(pThis->apDevByPort), NULL); 255 256 RTCritSectEnter(&pThis->CritSectDevices); 257 258 pDev = pThis->apDevByPort[uPort]; 259 if (RT_LIKELY(pDev)) 260 ASMAtomicIncU32(&pDev->cRefs); 261 262 RTCritSectLeave(&pThis->CritSectDevices); 263 264 return pDev; 265 } 266 222 267 223 268 /** … … 375 420 * Worker routine for vusbRhConnNewUrb(). 376 421 */ 377 static PVUSBURB vusbRhNewUrb(PVUSBROOTHUB pRh, uint8_t DstAddress, PVUSBDEV pDev, VUSBXFERTYPE enmType,422 static PVUSBURB vusbRhNewUrb(PVUSBROOTHUB pRh, uint8_t DstAddress, uint32_t uPort, VUSBXFERTYPE enmType, 378 423 VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag) 379 424 { … … 387 432 } 388 433 389 if (!pDev) 434 PVUSBDEV pDev; 435 if (uPort == VUSB_DEVICE_PORT_INVALID) 390 436 pDev = vusbRhFindDevByAddress(pRh, DstAddress); 391 437 else 392 vusbDevRetain(pDev);438 pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort); 393 439 394 440 if (pDev) … … 631 677 632 678 679 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnReset} */ 680 static DECLCALLBACK(int) vusbR3RhReset(PVUSBIROOTHUBCONNECTOR pInterface, bool fResetOnLinux) 681 { 682 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 683 return pRh->pIRhPort->pfnReset(pRh->pIRhPort, fResetOnLinux); 684 } 685 686 687 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnPowerOn} */ 688 static DECLCALLBACK(int) vusbR3RhPowerOn(PVUSBIROOTHUBCONNECTOR pInterface) 689 { 690 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 691 LogFlow(("vusR3bRhPowerOn: pRh=%p\n", pRh)); 692 693 Assert( pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_DETACHED 694 && pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_RESET); 695 696 if (pRh->Hub.Dev.enmState == VUSB_DEVICE_STATE_ATTACHED) 697 pRh->Hub.Dev.enmState = VUSB_DEVICE_STATE_POWERED; 698 699 return VINF_SUCCESS; 700 } 701 702 703 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnPowerOff} */ 704 static DECLCALLBACK(int) vusbR3RhPowerOff(PVUSBIROOTHUBCONNECTOR pInterface) 705 { 706 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 707 LogFlow(("vusbR3RhDevPowerOff: pThis=%p\n", pThis)); 708 709 Assert( pThis->Hub.Dev.enmState != VUSB_DEVICE_STATE_DETACHED 710 && pThis->Hub.Dev.enmState != VUSB_DEVICE_STATE_RESET); 711 712 /* 713 * Cancel all URBs and reap them. 714 */ 715 VUSBIRhCancelAllUrbs(&pThis->IRhConnector); 716 for (uint32_t uPort = 0; uPort < RT_ELEMENTS(pThis->apDevByPort); uPort++) 717 VUSBIRhReapAsyncUrbs(&pThis->IRhConnector, uPort, 0); 718 719 pThis->Hub.Dev.enmState = VUSB_DEVICE_STATE_ATTACHED; 720 return VINF_SUCCESS; 721 } 722 723 633 724 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnNewUrb} */ 634 static DECLCALLBACK(PVUSBURB) vusbRhConnNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, PVUSBIDEVICE pDev, VUSBXFERTYPE enmType,725 static DECLCALLBACK(PVUSBURB) vusbRhConnNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, uint32_t uPort, VUSBXFERTYPE enmType, 635 726 VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag) 636 727 { 637 728 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 638 return vusbRhNewUrb(pRh, DstAddress, (PVUSBDEV)pDev, enmType, enmDir, cbData, cTds, pszTag);729 return vusbRhNewUrb(pRh, DstAddress, uPort, enmType, enmDir, cbData, cTds, pszTag); 639 730 } 640 731 … … 760 851 761 852 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnReapAsyncUrbs} */ 762 static DECLCALLBACK(void) vusbRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice, RTMSINTERVAL cMillies)853 static DECLCALLBACK(void) vusbRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, RTMSINTERVAL cMillies) 763 854 { 764 855 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); NOREF(pRh); 765 PVUSBDEV pDev = (PVUSBDEV)pDevice; 766 767 if (RTListIsEmpty(&pDev->LstAsyncUrbs)) 856 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort); 857 858 if ( !pDev 859 || RTListIsEmpty(&pDev->LstAsyncUrbs)) 768 860 return; 769 861 … … 772 864 AssertRC(rc); 773 865 STAM_PROFILE_STOP(&pRh->StatReapAsyncUrbs, a); 866 867 vusbDevRelease(pDev); 774 868 } 775 869 … … 871 965 872 966 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnAbortEp} */ 873 static DECLCALLBACK(int) vusbRhAbortEp(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice, int EndPt, VUSBDIRECTION enmDir)967 static DECLCALLBACK(int) vusbRhAbortEp(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, int EndPt, VUSBDIRECTION enmDir) 874 968 { 875 969 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 876 if (&pRh->Hub != ((PVUSBDEV)pDevice)->pHub) 970 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort); 971 972 if (&pRh->Hub != pDev->pHub) 877 973 AssertFailedReturn(VERR_INVALID_PARAMETER); 878 974 879 RTCritSectEnter(&pRh->CritSectDevices);880 PVUSBDEV pDev = (PVUSBDEV)pDevice;881 975 vusbDevIoThreadExecSync(pDev, (PFNRT)vusbRhAbortEpWorker, 3, pDev, EndPt, enmDir); 882 RTCritSectLeave(&pRh->CritSectDevices);976 vusbDevRelease(pDev); 883 977 884 978 /* The reaper thread will take care of completing the URB. */ 885 979 886 980 return VINF_SUCCESS; 887 }888 889 890 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnAttachDevice} */891 static DECLCALLBACK(int) vusbRhAttachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)892 {893 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface);894 return vusbHubAttach(&pRh->Hub, (PVUSBDEV)pDevice);895 }896 897 898 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDetachDevice} */899 static DECLCALLBACK(int) vusbRhDetachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)900 {901 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface);902 if (&pRh->Hub != ((PVUSBDEV)pDevice)->pHub)903 AssertFailedReturn(VERR_INVALID_PARAMETER);904 return vusbDevDetach((PVUSBDEV)pDevice);905 981 } 906 982 … … 980 1056 981 1057 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnUpdateIsocFrameDelta} */ 982 static DECLCALLBACK(uint32_t) vusbRhUpdateIsocFrameDelta(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice,1058 static DECLCALLBACK(uint32_t) vusbRhUpdateIsocFrameDelta(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, 983 1059 int EndPt, VUSBDIRECTION enmDir, uint16_t uNewFrameID, uint8_t uBits) 984 1060 { 985 1061 PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 986 1062 AssertReturn(pRh, 0); 987 PVUSBDEV pDev = (PVUSBDEV)pDevice;1063 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort); AssertPtr(pDev); 988 1064 PVUSBPIPE pPipe = &pDev->aPipes[EndPt]; 989 1065 uint32_t *puLastFrame; … … 998 1074 uFrameDelta += uMaxVal; 999 1075 1076 vusbDevRelease(pDev); 1000 1077 return (uint16_t)uFrameDelta; 1001 1078 } 1002 1079 1003 /* -=-=-=-=-=- VUSB Device methods (for the root hub) -=-=-=-=-=- */ 1004 1005 1006 /** 1007 * @interface_method_impl{VUSBIDEVICE,pfnReset} 1008 */ 1009 static DECLCALLBACK(int) vusbRhDevReset(PVUSBIDEVICE pInterface, bool fResetOnLinux, 1010 PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM) 1011 { 1012 RT_NOREF(pfnDone, pvUser, pVM); 1013 PVUSBROOTHUB pRh = RT_FROM_MEMBER(pInterface, VUSBROOTHUB, Hub.Dev.IDevice); 1014 Assert(!pfnDone); 1015 return pRh->pIRhPort->pfnReset(pRh->pIRhPort, fResetOnLinux); /** @todo change rc from bool to vbox status everywhere! */ 1016 } 1017 1018 1019 /** 1020 * @interface_method_impl{VUSBIDEVICE,pfnPowerOn} 1021 */ 1022 static DECLCALLBACK(int) vusbRhDevPowerOn(PVUSBIDEVICE pInterface) 1023 { 1024 PVUSBROOTHUB pRh = RT_FROM_MEMBER(pInterface, VUSBROOTHUB, Hub.Dev.IDevice); 1025 LogFlow(("vusbRhDevPowerOn: pRh=%p\n", pRh)); 1026 1027 Assert( pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_DETACHED 1028 && pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_RESET); 1029 1030 if (pRh->Hub.Dev.enmState == VUSB_DEVICE_STATE_ATTACHED) 1031 pRh->Hub.Dev.enmState = VUSB_DEVICE_STATE_POWERED; 1032 1033 return VINF_SUCCESS; 1034 } 1035 1036 1037 /** 1038 * @interface_method_impl{VUSBIDEVICE,pfnPowerOff} 1039 */ 1040 static DECLCALLBACK(int) vusbRhDevPowerOff(PVUSBIDEVICE pInterface) 1041 { 1042 PVUSBROOTHUB pRh = RT_FROM_MEMBER(pInterface, VUSBROOTHUB, Hub.Dev.IDevice); 1043 LogFlow(("vusbRhDevPowerOff: pRh=%p\n", pRh)); 1044 1045 Assert( pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_DETACHED 1046 && pRh->Hub.Dev.enmState != VUSB_DEVICE_STATE_RESET); 1047 1048 /* 1049 * Cancel all URBs and reap them. 1050 */ 1051 VUSBIRhCancelAllUrbs(&pRh->IRhConnector); 1052 RTCritSectEnter(&pRh->CritSectDevices); 1053 PVUSBDEV pDev = pRh->pDevices; 1054 while (pDev) 1055 { 1056 VUSBIRhReapAsyncUrbs(&pRh->IRhConnector, (PVUSBIDEVICE)pDev, 0); 1057 pDev = pDev->pNext; 1058 } 1059 RTCritSectLeave(&pRh->CritSectDevices); 1060 1061 pRh->Hub.Dev.enmState = VUSB_DEVICE_STATE_ATTACHED; 1062 return VINF_SUCCESS; 1063 } 1064 1065 /** 1066 * @interface_method_impl{VUSBIDEVICE,pfnGetState} 1067 */ 1068 static DECLCALLBACK(VUSBDEVICESTATE) vusbRhDevGetState(PVUSBIDEVICE pInterface) 1069 { 1070 PVUSBROOTHUB pRh = RT_FROM_MEMBER(pInterface, VUSBROOTHUB, Hub.Dev.IDevice); 1071 return pRh->Hub.Dev.enmState; 1080 1081 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevReset} */ 1082 static DECLCALLBACK(int) vusbR3RhDevReset(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, bool fResetOnLinux, 1083 PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM) 1084 { 1085 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1086 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1087 AssertPtr(pDev); 1088 1089 int rc = VUSBIDevReset(&pDev->IDevice, fResetOnLinux, pfnDone, pvUser, pVM); 1090 vusbDevRelease(pDev); 1091 return rc; 1092 } 1093 1094 1095 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevPowerOn} */ 1096 static DECLCALLBACK(int) vusbR3RhDevPowerOn(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1097 { 1098 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1099 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1100 AssertPtr(pDev); 1101 1102 int rc = VUSBIDevPowerOn(&pDev->IDevice); 1103 vusbDevRelease(pDev); 1104 return rc; 1105 } 1106 1107 1108 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevPowerOff} */ 1109 static DECLCALLBACK(int) vusbR3RhDevPowerOff(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1110 { 1111 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1112 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1113 AssertPtr(pDev); 1114 1115 int rc = VUSBIDevPowerOff(&pDev->IDevice); 1116 vusbDevRelease(pDev); 1117 return rc; 1118 } 1119 1120 1121 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevGetState} */ 1122 static DECLCALLBACK(VUSBDEVICESTATE) vusbR3RhDevGetState(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1123 { 1124 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1125 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1126 AssertPtr(pDev); 1127 1128 VUSBDEVICESTATE enmState = VUSBIDevGetState(&pDev->IDevice); 1129 vusbDevRelease(pDev); 1130 return enmState; 1131 } 1132 1133 1134 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnIsSavedStateSupported} */ 1135 static DECLCALLBACK(bool) vusbR3RhDevIsSavedStateSupported(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1136 { 1137 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1138 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1139 AssertPtr(pDev); 1140 1141 bool fSavedStateSupported = VUSBIDevIsSavedStateSupported(&pDev->IDevice); 1142 vusbDevRelease(pDev); 1143 return fSavedStateSupported; 1144 } 1145 1146 1147 /** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnDevGetSpeed} */ 1148 static DECLCALLBACK(VUSBSPEED) vusbR3RhDevGetSpeed(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort) 1149 { 1150 PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); 1151 PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort); 1152 AssertPtr(pDev); 1153 1154 VUSBSPEED enmSpeed = pDev->IDevice.pfnGetSpeed(&pDev->IDevice); 1155 vusbDevRelease(pDev); 1156 return enmSpeed; 1072 1157 } 1073 1158 … … 1104 1189 } 1105 1190 1191 1192 /** 1193 * @callback_method_impl{FNSSMDEVSAVEPREP, All URBs needs to be canceled.} 1194 */ 1195 static DECLCALLBACK(int) vusbR3RhSavePrep(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM) 1196 { 1197 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1198 LogFlow(("vusbR3RhSavePrep:\n")); 1199 RT_NOREF(pSSM); 1200 1201 /* 1202 * Detach all proxied devices. 1203 */ 1204 RTCritSectEnter(&pThis->CritSectDevices); 1205 1206 /** @todo we a) can't tell which are proxied, and b) this won't work well when continuing after saving! */ 1207 for (unsigned i = 0; i < RT_ELEMENTS(pThis->apDevByPort); i++) 1208 { 1209 PVUSBDEV pDev = pThis->apDevByPort[i]; 1210 if (pDev) 1211 { 1212 if (!VUSBIDevIsSavedStateSupported(&pDev->IDevice)) 1213 { 1214 int rc = vusbDevDetach(pDev); 1215 AssertRC(rc); 1216 1217 /* 1218 * Save the device pointers here so we can reattach them afterwards. 1219 * This will work fine even if the save fails since the Done handler is 1220 * called unconditionally if the Prep handler was called. 1221 */ 1222 pThis->apDevByPort[i] = pDev; 1223 } 1224 } 1225 } 1226 1227 RTCritSectLeave(&pThis->CritSectDevices); 1228 1229 /* 1230 * Kill old load data which might be hanging around. 1231 */ 1232 if (pThis->pLoad) 1233 { 1234 PDMDrvHlpTimerDestroy(pDrvIns, pThis->pLoad->hTimer); 1235 pThis->pLoad->hTimer = NIL_TMTIMERHANDLE; 1236 PDMDrvHlpMMHeapFree(pDrvIns, pThis->pLoad); 1237 pThis->pLoad = NULL; 1238 } 1239 1240 return VINF_SUCCESS; 1241 } 1242 1243 1244 /** 1245 * @callback_method_impl{FNSSMDEVSAVEDONE} 1246 */ 1247 static DECLCALLBACK(int) vusbR3RhSaveDone(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM) 1248 { 1249 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1250 PVUSBDEV aPortsOld[VUSB_DEVICES_MAX]; 1251 unsigned i; 1252 LogFlow(("vusbR3RhSaveDone:\n")); 1253 RT_NOREF(pSSM); 1254 1255 /* Save the current data. */ 1256 memcpy(aPortsOld, pThis->apDevByPort, sizeof(aPortsOld)); 1257 AssertCompile(sizeof(aPortsOld) == sizeof(pThis->apDevByPort)); 1258 1259 /* 1260 * NULL the dev pointers. 1261 */ 1262 for (i = 0; i < RT_ELEMENTS(pThis->apDevByPort); i++) 1263 if (pThis->apDevByPort[i] && !VUSBIDevIsSavedStateSupported(&pThis->apDevByPort[i]->IDevice)) 1264 pThis->apDevByPort[i] = NULL; 1265 1266 /* 1267 * Attach the devices. 1268 */ 1269 for (i = 0; i < RT_ELEMENTS(pThis->apDevByPort); i++) 1270 { 1271 PVUSBDEV pDev = aPortsOld[i]; 1272 if (pDev && !VUSBIDevIsSavedStateSupported(&pDev->IDevice)) 1273 vusbHubAttach(&pThis->Hub, pDev); 1274 } 1275 1276 return VINF_SUCCESS; 1277 } 1278 1279 1280 /** 1281 * @callback_method_impl{FNSSMDEVLOADPREP, This must detach the devices 1282 * currently attached and save them for reconnect after the state load has been 1283 * completed.} 1284 */ 1285 static DECLCALLBACK(int) vusbR3RhLoadPrep(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM) 1286 { 1287 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1288 int rc = VINF_SUCCESS; 1289 LogFlow(("vusbR3RhLoadPrep:\n")); 1290 RT_NOREF(pSSM); 1291 1292 if (!pThis->pLoad) 1293 { 1294 VUSBROOTHUBLOAD Load; 1295 unsigned i; 1296 1297 /// @todo This is all bogus. 1298 /* 1299 * Detach all devices which are present in this session. Save them in the load 1300 * structure so we can reattach them after restoring the guest. 1301 */ 1302 Load.hTimer = NIL_TMTIMERHANDLE; 1303 Load.cDevs = 0; 1304 for (i = 0; i < RT_ELEMENTS(pThis->apDevByPort); i++) 1305 { 1306 PVUSBDEV pDev = pThis->apDevByPort[i]; 1307 if (pDev && !VUSBIDevIsSavedStateSupported(&pDev->IDevice)) 1308 { 1309 Load.apDevs[Load.cDevs++] = pDev; 1310 vusbDevDetach(pDev); 1311 Assert(!pThis->apDevByPort[i]); 1312 } 1313 } 1314 1315 /* 1316 * Any devices to reattach? If so, duplicate the Load struct. 1317 */ 1318 if (Load.cDevs) 1319 { 1320 pThis->pLoad = (PVUSBROOTHUBLOAD)RTMemAllocZ(sizeof(Load)); 1321 if (!pThis->pLoad) 1322 return VERR_NO_MEMORY; 1323 *pThis->pLoad = Load; 1324 } 1325 } 1326 /* else: we ASSUME no device can be attached or detached in the time 1327 * between a state load and the pLoad stuff processing. */ 1328 return rc; 1329 } 1330 1331 1332 /** 1333 * Reattaches devices after a saved state load. 1334 */ 1335 static DECLCALLBACK(void) vusbR3RhLoadReattachDevices(PPDMDRVINS pDrvIns, TMTIMERHANDLE hTimer, void *pvUser) 1336 { 1337 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1338 PVUSBROOTHUBLOAD pLoad = pThis->pLoad; 1339 LogFlow(("vusbR3RhLoadReattachDevices:\n")); 1340 Assert(hTimer == pLoad->hTimer); RT_NOREF(pvUser); 1341 1342 /* 1343 * Reattach devices. 1344 */ 1345 for (unsigned i = 0; i < pLoad->cDevs; i++) 1346 vusbHubAttach(&pThis->Hub, pLoad->apDevs[i]); 1347 1348 /* 1349 * Cleanup. 1350 */ 1351 PDMDrvHlpTimerDestroy(pDrvIns, hTimer); 1352 pLoad->hTimer = NIL_TMTIMERHANDLE; 1353 RTMemFree(pLoad); 1354 pThis->pLoad = NULL; 1355 } 1356 1357 1358 /** 1359 * @callback_method_impl{FNSSMDEVLOADDONE} 1360 */ 1361 static DECLCALLBACK(int) vusbR3RhLoadDone(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM) 1362 { 1363 PVUSBROOTHUB pThis = PDMINS_2_DATA(pDrvIns, PVUSBROOTHUB); 1364 LogFlow(("vusbR3RhLoadDone:\n")); 1365 RT_NOREF(pSSM); 1366 1367 /* 1368 * Start a timer if we've got devices to reattach 1369 */ 1370 if (pThis->pLoad) 1371 { 1372 int rc = PDMDrvHlpTMTimerCreate(pDrvIns, TMCLOCK_VIRTUAL, vusbR3RhLoadReattachDevices, NULL, 1373 TMTIMER_FLAGS_NO_CRIT_SECT | TMTIMER_FLAGS_NO_RING0, 1374 "VUSB reattach on load", &pThis->pLoad->hTimer); 1375 if (RT_SUCCESS(rc)) 1376 rc = PDMDrvHlpTimerSetMillies(pDrvIns, pThis->pLoad->hTimer, 250); 1377 return rc; 1378 } 1379 1380 return VINF_SUCCESS; 1381 } 1382 1383 1106 1384 /* -=-=-=-=-=- VUSB Hub methods -=-=-=-=-=- */ 1107 1385 … … 1136 1414 * linked into the device list of this hub. 1137 1415 */ 1138 int rc = pRh->pIRhPort->pfnAttach(pRh->pIRhPort, &pDev->IDevice, iPort); 1416 VUSBSPEED enmSpeed = pDev->IDevice.pfnGetSpeed(&pDev->IDevice); 1417 int rc = pRh->pIRhPort->pfnAttach(pRh->pIRhPort, iPort, enmSpeed); 1139 1418 if (RT_SUCCESS(rc)) 1140 1419 { … … 1142 1421 pDev->pNext = pRh->pDevices; 1143 1422 pRh->pDevices = pDev; 1423 1424 Assert(!pRh->apDevByPort[iPort]); 1425 pRh->apDevByPort[iPort] = pDev; 1426 1144 1427 RTCritSectLeave(&pRh->CritSectDevices); 1145 1428 LogRel(("VUSB: Attached '%s' to port %d on %s (%sSpeed)\n", pDev->pUsbIns->pszName, … … 1184 1467 pRh->pDevices = pDev->pNext; 1185 1468 pDev->pNext = NULL; 1469 1470 pRh->apDevByPort[pDev->i16Port] = NULL; 1186 1471 RTCritSectLeave(&pRh->CritSectDevices); 1187 1472 … … 1190 1475 */ 1191 1476 unsigned uPort = pDev->i16Port; 1192 pRh->pIRhPort->pfnDetach(pRh->pIRhPort, &pDev->IDevice,uPort);1477 pRh->pIRhPort->pfnDetach(pRh->pIRhPort, uPort); 1193 1478 LogRel(("VUSB: Detached '%s' from port %u on %s\n", pDev->pUsbIns->pszName, uPort, pHub->pszName)); 1194 1479 ASMBitSet(&pRh->Bitmap, uPort); … … 1307 1592 /* the usb device */ 1308 1593 pThis->Hub.Dev.enmState = VUSB_DEVICE_STATE_ATTACHED; 1309 pThis->Hub.Dev.u8Address = VUSB_INVALID_ADDRESS;1310 pThis->Hub.Dev.u8NewAddress = VUSB_INVALID_ADDRESS;1311 pThis->Hub.Dev.i16Port = -1;1312 1594 pThis->Hub.Dev.cRefs = 1; 1313 pThis->Hub.Dev.IDevice.pfnReset = vusbRhDevReset;1314 pThis->Hub.Dev.IDevice.pfnPowerOn = vusbRhDevPowerOn;1315 pThis->Hub.Dev.IDevice.pfnPowerOff = vusbRhDevPowerOff;1316 pThis->Hub.Dev.IDevice.pfnGetState = vusbRhDevGetState;1317 1595 /* the hub */ 1318 1596 pThis->Hub.pOps = &s_VUsbRhHubOps; … … 1326 1604 /* the connector */ 1327 1605 pThis->IRhConnector.pfnSetUrbParams = vusbRhSetUrbParams; 1606 pThis->IRhConnector.pfnReset = vusbR3RhReset; 1607 pThis->IRhConnector.pfnPowerOn = vusbR3RhPowerOn; 1608 pThis->IRhConnector.pfnPowerOff = vusbR3RhPowerOff; 1328 1609 pThis->IRhConnector.pfnNewUrb = vusbRhConnNewUrb; 1329 1610 pThis->IRhConnector.pfnFreeUrb = vusbRhConnFreeUrb; … … 1333 1614 pThis->IRhConnector.pfnCancelAllUrbs = vusbRhCancelAllUrbs; 1334 1615 pThis->IRhConnector.pfnAbortEp = vusbRhAbortEp; 1335 pThis->IRhConnector.pfnAttachDevice = vusbRhAttachDevice;1336 pThis->IRhConnector.pfnDetachDevice = vusbRhDetachDevice;1337 1616 pThis->IRhConnector.pfnSetPeriodicFrameProcessing = vusbRhSetFrameProcessing; 1338 1617 pThis->IRhConnector.pfnGetPeriodicFrameRate = vusbRhGetPeriodicFrameRate; 1339 1618 pThis->IRhConnector.pfnUpdateIsocFrameDelta = vusbRhUpdateIsocFrameDelta; 1619 pThis->IRhConnector.pfnDevReset = vusbR3RhDevReset; 1620 pThis->IRhConnector.pfnDevPowerOn = vusbR3RhDevPowerOn; 1621 pThis->IRhConnector.pfnDevPowerOff = vusbR3RhDevPowerOff; 1622 pThis->IRhConnector.pfnDevGetState = vusbR3RhDevGetState; 1623 pThis->IRhConnector.pfnDevIsSavedStateSupported = vusbR3RhDevIsSavedStateSupported; 1624 pThis->IRhConnector.pfnDevGetSpeed = vusbR3RhDevGetSpeed; 1340 1625 pThis->hSniffer = VUSBSNIFFER_NIL; 1341 1626 pThis->cbHci = 0; … … 1388 1673 if (RT_FAILURE(rc)) 1389 1674 return rc; 1675 1676 /* 1677 * Register the saved state data unit for attaching devices. 1678 */ 1679 rc = PDMDrvHlpSSMRegisterEx(pDrvIns, VUSB_ROOTHUB_SAVED_STATE_VERSION, 0, 1680 NULL, NULL, NULL, 1681 vusbR3RhSavePrep, NULL, vusbR3RhSaveDone, 1682 vusbR3RhLoadPrep, NULL, vusbR3RhLoadDone); 1683 AssertRCReturn(rc, rc); 1390 1684 1391 1685 /* -
trunk/src/VBox/Devices/USB/VUSBDevice.cpp
r93115 r93914 1433 1433 vusbDevSetAddress(pDev, VUSB_DEFAULT_ADDRESS); 1434 1434 if (pfnDone) 1435 pfnDone(&pDev->IDevice, rc, pvUser);1435 pfnDone(&pDev->IDevice, pDev->i16Port, rc, pvUser); 1436 1436 } 1437 1437 … … 1647 1647 PVUSBROOTHUB pRh = (PVUSBROOTHUB)pDev; 1648 1648 VUSBIRhCancelAllUrbs(&pRh->IRhConnector); 1649 VUSBIRhReapAsyncUrbs(&pRh->IRhConnector, p Interface, 0);1649 VUSBIRhReapAsyncUrbs(&pRh->IRhConnector, pDev->i16Port, 0); 1650 1650 } 1651 1651 -
trunk/src/VBox/Devices/USB/VUSBInternal.h
r93115 r93914 377 377 378 378 379 /** Pointer to a VUSBROOTHUBLOAD struct. */ 380 typedef struct VUSBROOTHUBLOAD *PVUSBROOTHUBLOAD; 381 379 382 /** The address hash table size. */ 380 383 #define VUSB_ADDR_HASHSZ 5 … … 391 394 /** The HUB. 392 395 * @todo remove this? */ 393 VUSBHUB Hub;396 VUSBHUB Hub; 394 397 /** Address hash table. */ 395 PVUSBDEV apAddrHash[VUSB_ADDR_HASHSZ];398 PVUSBDEV apAddrHash[VUSB_ADDR_HASHSZ]; 396 399 /** The default address. */ 397 PVUSBDEV pDefaultAddress;400 PVUSBDEV pDefaultAddress; 398 401 399 402 /** Pointer to the driver instance. */ 400 PPDMDRVINS pDrvIns;403 PPDMDRVINS pDrvIns; 401 404 /** Pointer to the root hub port interface we're attached to. */ 402 PVUSBIROOTHUBPORT pIRhPort;405 PVUSBIROOTHUBPORT pIRhPort; 403 406 /** Connector interface exposed upwards. */ 404 VUSBIROOTHUBCONNECTOR IRhConnector;407 VUSBIROOTHUBCONNECTOR IRhConnector; 405 408 406 409 /** Critical section protecting the device list. */ 407 RTCRITSECT CritSectDevices;410 RTCRITSECT CritSectDevices; 408 411 /** Chain of devices attached to this hub. */ 409 PVUSBDEV pDevices; 412 PVUSBDEV pDevices; 413 414 /** Array of pointers to USB devices indexed by the port the device is on. */ 415 PVUSBDEV apDevByPort[VUSB_DEVICES_MAX]; 416 /** Structure after a saved state load to re-attach devices. */ 417 PVUSBROOTHUBLOAD pLoad; 410 418 411 419 #if HC_ARCH_BITS == 32
Note:
See TracChangeset
for help on using the changeset viewer.

