diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index 64bc4516f0..f06712d1de 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -335,6 +335,21 @@ Hub::Explore(change_item **changeList) USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, i + 1, 0, NULL, 0, NULL); } + + if (fPortStatus[i].change & PORT_CHANGE_LINK_STATE) { + TRACE_ALWAYS("port %" B_PRId32 " link state changed\n", i); + DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, + USB_REQUEST_CLEAR_FEATURE, C_PORT_LINK_STATE, i + 1, + 0, NULL, 0, NULL); + } + + if (fPortStatus[i].change & PORT_CHANGE_BH_PORT_RESET) { + TRACE_ALWAYS("port %" B_PRId32 " was warm reset\n", i); + DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, + USB_REQUEST_CLEAR_FEATURE, C_PORT_BH_PORT_RESET, i + 1, + 0, NULL, 0, NULL); + } + } // explore down the tree if we have hubs connected diff --git a/src/add-ons/kernel/bus_managers/usb/usbspec_private.h b/src/add-ons/kernel/bus_managers/usb/usbspec_private.h index 8123389e8a..c9ca3686b7 100644 --- a/src/add-ons/kernel/bus_managers/usb/usbspec_private.h +++ b/src/add-ons/kernel/bus_managers/usb/usbspec_private.h @@ -102,7 +102,7 @@ struct usb_port_status #define PORT_STATUS_HIGH_SPEED 0x0400 #define PORT_STATUS_TEST 0x0800 #define PORT_STATUS_INDICATOR 0x1000 -// USB 3.0 spec table 10-11 +// USB 3.0 spec table 10-10 #define PORT_STATUS_SS_LINK_STATE 0x01e0 #define PORT_STATUS_SS_POWER 0x0200 #define PORT_STATUS_SS_SPEED 0x1c00 @@ -135,5 +135,8 @@ struct usb_port_status #define C_PORT_BH_PORT_RESET 29 #define PORT_FORCE_LINKPM_STATE 30 +// USB 3.0 spec table 10-11 +#define PORT_CHANGE_BH_PORT_RESET 0x0020 +#define PORT_CHANGE_LINK_STATE 0x0040 #endif // _USBSPEC_PRIVATE_H diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp b/src/add-ons/kernel/busses/usb/xhci.cpp index b70b51c4fb..ea81660619 100644 --- a/src/add-ons/kernel/busses/usb/xhci.cpp +++ b/src/add-ons/kernel/busses/usb/xhci.cpp @@ -1789,9 +1789,9 @@ XHCI::GetPortStatus(uint8 index, usb_port_status* status) if (fPortSpeeds[index] == USB_SPEED_SUPER) { if (portStatus & PS_PLC) - status->change |= PORT_LINK_STATE; + status->change |= PORT_CHANGE_LINK_STATE; if (portStatus & PS_WRC) - status->change |= PORT_BH_PORT_RESET; + status->change |= PORT_CHANGE_BH_PORT_RESET; } return B_OK; @@ -1874,6 +1874,12 @@ XHCI::ClearPortFeature(uint8 index, uint16 feature) case C_PORT_RESET: WriteOpReg(portRegister, portStatus | PS_PRC); break; + case C_PORT_BH_PORT_RESET: + WriteOpReg(portRegister, portStatus | PS_WRC); + break; + case C_PORT_LINK_STATE: + WriteOpReg(portRegister, portStatus | PS_PLC); + break; default: return B_BAD_VALUE; }