usb: Update USB hub code to support super speed hubs
Super speed hubs (usb3 spec) have specific initialization requirements. Add the code necessary to detect and initialize these hubs. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
ed675ad419
commit
73fe49aef4
|
@ -17,12 +17,27 @@ get_hub_desc(struct usb_pipe *pipe, struct usb_hub_descriptor *desc)
|
|||
struct usb_ctrlrequest req;
|
||||
req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE;
|
||||
req.bRequest = USB_REQ_GET_DESCRIPTOR;
|
||||
req.wValue = USB_DT_HUB<<8;
|
||||
if (pipe->speed == USB_SUPERSPEED)
|
||||
req.wValue = USB_DT_HUB3<<8;
|
||||
else
|
||||
req.wValue = USB_DT_HUB<<8;
|
||||
req.wIndex = 0;
|
||||
req.wLength = sizeof(*desc);
|
||||
return usb_send_default_control(pipe, &req, desc);
|
||||
}
|
||||
|
||||
static int
|
||||
set_hub_depth(struct usb_pipe *pipe, u16 depth)
|
||||
{
|
||||
struct usb_ctrlrequest req;
|
||||
req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE;
|
||||
req.bRequest = HUB_REQ_SET_HUB_DEPTH;
|
||||
req.wValue = depth;
|
||||
req.wIndex = 0;
|
||||
req.wLength = 0;
|
||||
return usb_send_default_control(pipe, &req, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
set_port_feature(struct usbhub_s *hub, int port, int feature)
|
||||
{
|
||||
|
@ -105,7 +120,9 @@ usb_hub_reset(struct usbhub_s *hub, u32 port)
|
|||
ret = get_port_status(hub, port, &sts);
|
||||
if (ret)
|
||||
goto fail;
|
||||
if (!(sts.wPortStatus & USB_PORT_STAT_RESET))
|
||||
if (!(sts.wPortStatus & USB_PORT_STAT_RESET)
|
||||
&& (hub->usbdev->speed != USB_SUPERSPEED
|
||||
|| !(sts.wPortStatus & USB_PORT_STAT_LINK_MASK)))
|
||||
break;
|
||||
if (timer_check(end)) {
|
||||
warn_timeout();
|
||||
|
@ -119,6 +136,8 @@ usb_hub_reset(struct usbhub_s *hub, u32 port)
|
|||
// Device no longer present
|
||||
return -1;
|
||||
|
||||
if (hub->usbdev->speed == USB_SUPERSPEED)
|
||||
return USB_SUPERSPEED;
|
||||
return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK)
|
||||
>> USB_PORT_STAT_SPEED_SHIFT);
|
||||
|
||||
|
@ -154,6 +173,19 @@ usb_hub_setup(struct usbdevice_s *usbdev)
|
|||
hub.portcount = desc.bNbrPorts;
|
||||
hub.op = &HubOp;
|
||||
|
||||
if (usbdev->speed == USB_SUPERSPEED) {
|
||||
int depth = 0;
|
||||
struct usbdevice_s *parent = usbdev->hub->usbdev;
|
||||
while (parent) {
|
||||
depth++;
|
||||
parent = parent->hub->usbdev;
|
||||
}
|
||||
|
||||
ret = set_hub_depth(usbdev->defpipe, depth);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Turn on power to ports.
|
||||
int port;
|
||||
for (port=0; port<desc.bNbrPorts; port++) {
|
||||
|
|
|
@ -11,6 +11,9 @@ int usb_hub_setup(struct usbdevice_s *usbdev);
|
|||
****************************************************************/
|
||||
|
||||
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
|
||||
#define USB_DT_HUB3 (USB_TYPE_CLASS | 0x0a)
|
||||
|
||||
#define HUB_REQ_SET_HUB_DEPTH 0x0C
|
||||
|
||||
struct usb_hub_descriptor {
|
||||
u8 bDescLength;
|
||||
|
@ -48,7 +51,8 @@ struct usb_port_status {
|
|||
#define USB_PORT_STAT_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_RESET 0x0010
|
||||
#define USB_PORT_STAT_L1 0x0020
|
||||
#define USB_PORT_STAT_LINK_SHIFT 5
|
||||
#define USB_PORT_STAT_LINK_MASK (0x7 << USB_PORT_STAT_LINK_SHIFT)
|
||||
#define USB_PORT_STAT_POWER 0x0100
|
||||
#define USB_PORT_STAT_SPEED_SHIFT 9
|
||||
#define USB_PORT_STAT_SPEED_MASK (0x3 << USB_PORT_STAT_SPEED_SHIFT)
|
||||
|
|
Loading…
Reference in New Issue