2010/11/30 Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>: > From: John Youn <John.Youn@xxxxxxxxxxxx> > > Update the USB core to deal with USB 3.0 hubs. These hubs have a slightly > different hub descriptor than USB 2.0 hubs, with a fixed (rather than > variable length) size. Change the USB core's hub descriptor to have a > union for the last fields that differ. Change the host controller drivers > that access those last fields (DeviceRemovable and PortPowerCtrlMask) to > use the union. > > Translate the new version of the hub port status field into the old > version that khubd understands. (Note: we need to fix it to translate the > roothub's port status once we stop converting it to USB 2.0 hub status > internally.) > > Add new code to handle link state change status. Send out new control > messages that are needed for USB 3.0 hubs, like Set Hub Depth. > > This patch is a modified version of the original patch submitted by John > Youn. John's original hub patch made the change to struct > usb_hub_descriptor to make part of it into a union. There's a few more > drivers in the 2.6.37 tree that need their accesses updated for this > change: the USB IP driver in staging, and the dummy HCD gadget driver. > > Signed-off-by: John Youn <johnyoun@xxxxxxxxxxxx> > Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> > --- > drivers/staging/usbip/vhci_hcd.c | 4 +- > drivers/usb/core/hub.c | 73 +++++++++++++++++++++++++++++++++---- > drivers/usb/gadget/dummy_hcd.c | 4 +- > drivers/usb/host/ehci-hub.c | 4 +- > drivers/usb/host/imx21-hcd.c | 4 +- > drivers/usb/host/isp116x-hcd.c | 4 +- > drivers/usb/host/isp1362-hcd.c | 4 +- > drivers/usb/host/isp1760-hcd.c | 4 +- > drivers/usb/host/ohci-hub.c | 10 +++--- > drivers/usb/host/oxu210hp-hcd.c | 4 +- > drivers/usb/host/r8a66597-hcd.c | 4 +- > drivers/usb/host/sl811-hcd.c | 4 +- > drivers/usb/host/u132-hcd.c | 10 +++--- > drivers/usb/host/xhci-hub.c | 4 +- > drivers/usb/wusbcore/rh.c | 4 +- > include/linux/usb/ch11.h | 41 +++++++++++++++++++-- drivers/usb/musb/musb_virthub.c is missed. > 16 files changed, 136 insertions(+), 46 deletions(-) > > diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c > index 832608d..7ec3e74 100644 > --- a/drivers/staging/usbip/vhci_hcd.c > +++ b/drivers/staging/usbip/vhci_hcd.c > @@ -257,8 +257,8 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc) > desc->wHubCharacteristics = (__force __u16) > (__constant_cpu_to_le16(0x0001)); > desc->bNbrPorts = VHCI_NPORTS; > - desc->bitmap[0] = 0xff; > - desc->bitmap[1] = 0xff; > + desc->u.hs.bitmap[0] = 0xff; > + desc->u.hs.bitmap[1] = 0xff; Maybe redefining bitmap as u.hs.bitmap is cleverer fix, isn't it? > } > > static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, > diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c > index b98efae..d9e7973 100644 > --- a/drivers/usb/core/hub.c > +++ b/drivers/usb/core/hub.c > @@ -82,6 +82,10 @@ struct usb_hub { > void **port_owners; > }; > > +static inline int hub_is_superspeed(struct usb_device *hdev) > +{ > + return (hdev->descriptor.bDeviceProtocol == 3); > +} > > /* Protect struct usb_device->state and ->children members > * Note: Both are also protected by ->dev.sem, except that ->state can > @@ -172,14 +176,23 @@ static struct usb_hub *hdev_to_hub(struct usb_device *hdev) > } > > /* USB 2.0 spec Section 11.24.4.5 */ > -static int get_hub_descriptor(struct usb_device *hdev, void *data, int size) > +static int get_hub_descriptor(struct usb_device *hdev, void *data) > { > - int i, ret; > + int i, ret, size; > + unsigned dtype; > + > + if (hub_is_superspeed(hdev)) { > + dtype = USB_DT_SS_HUB; > + size = USB_DT_SS_HUB_SIZE; > + } else { > + dtype = USB_DT_HUB; > + size = sizeof(struct usb_hub_descriptor); > + } > > for (i = 0; i < 3; i++) { > ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), > USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, > - USB_DT_HUB << 8, 0, data, size, > + dtype << 8, 0, data, size, > USB_CTRL_GET_TIMEOUT); > if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) > return ret; > @@ -365,6 +378,19 @@ static int hub_port_status(struct usb_hub *hub, int port1, > } else { > *status = le16_to_cpu(hub->status->port.wPortStatus); > *change = le16_to_cpu(hub->status->port.wPortChange); > + > + if ((hub->hdev->parent != NULL) && > + hub_is_superspeed(hub->hdev)) { > + /* Translate the USB 3 port status */ > + u16 tmp = *status & USB_SS_PORT_STAT_MASK; > + if (*status & USB_SS_PORT_STAT_POWER) > + tmp |= USB_PORT_STAT_POWER; > + if ((*status & USB_SS_PORT_STAT_SPEED) == > + USB_PORT_STAT_SPEED_5GBPS) > + tmp |= USB_PORT_STAT_SUPER_SPEED; > + *status = tmp; > + } > + > ret = 0; > } > mutex_unlock(&hub->status_mutex); > @@ -607,7 +633,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) > if (hdev->children[port1-1] && set_state) > usb_set_device_state(hdev->children[port1-1], > USB_STATE_NOTATTACHED); > - if (!hub->error) > + if (!hub->error && !hub_is_superspeed(hub->hdev)) > ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); > if (ret) > dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", > @@ -774,6 +800,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) > clear_port_feature(hub->hdev, port1, > USB_PORT_FEAT_C_ENABLE); > } > + if (portchange & USB_PORT_STAT_C_LINK_STATE) { > + need_debounce_delay = true; > + clear_port_feature(hub->hdev, port1, > + USB_PORT_FEAT_C_PORT_LINK_STATE); > + } > > /* We can forget about a "removed" device when there's a > * physical disconnect or the connect status changes. > @@ -943,12 +974,23 @@ static int hub_configure(struct usb_hub *hub, > goto fail; > } > > + if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) { > + ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), > + HUB_SET_DEPTH, USB_RT_HUB, > + hdev->level - 1, 0, NULL, 0, > + USB_CTRL_SET_TIMEOUT); > + > + if (ret < 0) { > + message = "can't set hub depth"; > + goto fail; > + } > + } > + > /* Request the entire hub descriptor. > * hub->descriptor can handle USB_MAXCHILDREN ports, > * but the hub can/will return fewer bytes here. > */ > - ret = get_hub_descriptor(hdev, hub->descriptor, > - sizeof(*hub->descriptor)); > + ret = get_hub_descriptor(hdev, hub->descriptor); > if (ret < 0) { > message = "can't read hub descriptor"; > goto fail; > @@ -970,12 +1012,14 @@ static int hub_configure(struct usb_hub *hub, > > wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); > > - if (wHubCharacteristics & HUB_CHAR_COMPOUND) { > + /* FIXME for USB 3.0, skip for now */ > + if ((wHubCharacteristics & HUB_CHAR_COMPOUND) && > + !(hub_is_superspeed(hdev))) { > int i; > char portstr [USB_MAXCHILDREN + 1]; > > for (i = 0; i < hdev->maxchild; i++) > - portstr[i] = hub->descriptor->DeviceRemovable > + portstr[i] = hub->descriptor->u.hs.DeviceRemovable > [((i + 1) / 8)] & (1 << ((i + 1) % 8)) > ? 'F' : 'R'; > portstr[hdev->maxchild] = 0; > @@ -2000,6 +2044,8 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, > udev->speed = USB_SPEED_HIGH; > else if (portstatus & USB_PORT_STAT_LOW_SPEED) > udev->speed = USB_SPEED_LOW; > + else if (portstatus & USB_PORT_STAT_SUPER_SPEED) > + udev->speed = USB_SPEED_SUPER; > else > udev->speed = USB_SPEED_FULL; > return 0; > @@ -3401,6 +3447,17 @@ static void hub_events(void) > clear_port_feature(hdev, i, > USB_PORT_FEAT_C_RESET); > } > + if (portchange & USB_PORT_STAT_C_LINK_STATE) { > + clear_port_feature(hub->hdev, i, > + USB_PORT_FEAT_C_PORT_LINK_STATE); > + } > + if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) { > + dev_warn(hub_dev, > + "config error on port %d\n", > + i); > + clear_port_feature(hub->hdev, i, > + USB_PORT_FEAT_C_PORT_CONFIG_ERROR); > + } > > if (connect_change) > hub_port_connect_change(hub, i, > diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c > index 13b9f47..aec9de5 100644 > --- a/drivers/usb/gadget/dummy_hcd.c > +++ b/drivers/usb/gadget/dummy_hcd.c > @@ -1593,8 +1593,8 @@ hub_descriptor (struct usb_hub_descriptor *desc) > desc->bDescLength = 9; > desc->wHubCharacteristics = cpu_to_le16(0x0001); > desc->bNbrPorts = 1; > - desc->bitmap [0] = 0xff; > - desc->bitmap [1] = 0xff; > + desc->u.hs.bitmap[0] = 0xff; > + desc->u.hs.bitmap[1] = 0xff; > } > > static int dummy_hub_control ( > diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c > index 796ea0c..c8d82b3 100644 > --- a/drivers/usb/host/ehci-hub.c > +++ b/drivers/usb/host/ehci-hub.c > @@ -688,8 +688,8 @@ ehci_hub_descriptor ( > desc->bDescLength = 7 + 2 * temp; > > /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ > - memset (&desc->bitmap [0], 0, temp); > - memset (&desc->bitmap [temp], 0xff, temp); > + memset(&desc->u.hs.bitmap[0], 0, temp); > + memset(&desc->u.hs.bitmap[temp], 0xff, temp); > > temp = 0x0008; /* per-port overcurrent reporting */ > if (HCS_PPC (ehci->hcs_params)) > diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c > index e49b75a..6e22530 100644 > --- a/drivers/usb/host/imx21-hcd.c > +++ b/drivers/usb/host/imx21-hcd.c > @@ -1471,8 +1471,8 @@ static int get_hub_descriptor(struct usb_hcd *hcd, > 0x0010 | /* No over current protection */ > 0); > > - desc->bitmap[0] = 1 << 1; > - desc->bitmap[1] = ~0; > + desc->u.hs.bitmap[0] = 1 << 1; > + desc->u.hs.bitmap[1] = ~0; > return 0; > } > > diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c > index 0da7fc0..084e3c6 100644 > --- a/drivers/usb/host/isp116x-hcd.c > +++ b/drivers/usb/host/isp116x-hcd.c > @@ -952,8 +952,8 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x, > desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f)); > desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff); > /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ > - desc->bitmap[0] = 0; > - desc->bitmap[1] = ~0; > + desc->u.hs.bitmap[0] = 0; > + desc->u.hs.bitmap[1] = ~0; > } > > /* Perform reset of a given port. > diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c > index 8196fa1..c9b1434 100644 > --- a/drivers/usb/host/isp1362-hcd.c > +++ b/drivers/usb/host/isp1362-hcd.c > @@ -1557,8 +1557,8 @@ static void isp1362_hub_descriptor(struct isp1362_hcd *isp1362_hcd, > DBG(0, "%s: hubcharacteristics = %02x\n", __func__, cpu_to_le16((reg >> 8) & 0x1f)); > desc->bPwrOn2PwrGood = (reg >> 24) & 0xff; > /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ > - desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; > - desc->bitmap[1] = ~0; > + desc->u.hs.bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; > + desc->u.hs.bitmap[1] = ~0; > > DBG(3, "%s: exit\n", __func__); > } > diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c > index bdba8c5..c7c5370 100644 > --- a/drivers/usb/host/isp1760-hcd.c > +++ b/drivers/usb/host/isp1760-hcd.c > @@ -1845,8 +1845,8 @@ static void isp1760_hub_descriptor(struct isp1760_hcd *priv, > desc->bDescLength = 7 + 2 * temp; > > /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ > - memset(&desc->bitmap[0], 0, temp); > - memset(&desc->bitmap[temp], 0xff, temp); > + memset(&desc->u.hs.bitmap[0], 0, temp); > + memset(&desc->u.hs.bitmap[temp], 0xff, temp); > > /* per-port overcurrent reporting */ > temp = 0x0008; > diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c > index cddcda9..8a0924d 100644 > --- a/drivers/usb/host/ohci-hub.c > +++ b/drivers/usb/host/ohci-hub.c > @@ -582,13 +582,13 @@ ohci_hub_descriptor ( > > /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ > rh = roothub_b (ohci); > - memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); > - desc->bitmap [0] = rh & RH_B_DR; > + memset(desc->u.hs.bitmap, 0xff, sizeof(desc->u.hs.bitmap)); > + desc->u.hs.bitmap[0] = rh & RH_B_DR; > if (ohci->num_ports > 7) { > - desc->bitmap [1] = (rh & RH_B_DR) >> 8; > - desc->bitmap [2] = 0xff; > + desc->u.hs.bitmap[1] = (rh & RH_B_DR) >> 8; > + desc->u.hs.bitmap[2] = 0xff; > } else > - desc->bitmap [1] = 0xff; > + desc->u.hs.bitmap[1] = 0xff; > } > > /*-------------------------------------------------------------------------*/ > diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c > index 32149be..1104c4d 100644 > --- a/drivers/usb/host/oxu210hp-hcd.c > +++ b/drivers/usb/host/oxu210hp-hcd.c > @@ -452,8 +452,8 @@ static void ehci_hub_descriptor(struct oxu_hcd *oxu, > desc->bDescLength = 7 + 2 * temp; > > /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ > - memset(&desc->bitmap[0], 0, temp); > - memset(&desc->bitmap[temp], 0xff, temp); > + memset(&desc->u.hs.bitmap[0], 0, temp); > + memset(&desc->u.hs.bitmap[temp], 0xff, temp); > > temp = 0x0008; /* per-port overcurrent reporting */ > if (HCS_PPC(oxu->hcs_params)) > diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c > index 3076b1c..102dc54 100644 > --- a/drivers/usb/host/r8a66597-hcd.c > +++ b/drivers/usb/host/r8a66597-hcd.c > @@ -2150,8 +2150,8 @@ static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597, > desc->bDescLength = 9; > desc->bPwrOn2PwrGood = 0; > desc->wHubCharacteristics = cpu_to_le16(0x0011); > - desc->bitmap[0] = ((1 << r8a66597->max_root_hub) - 1) << 1; > - desc->bitmap[1] = ~0; > + desc->u.hs.bitmap[0] = ((1 << r8a66597->max_root_hub) - 1) << 1; > + desc->u.hs.bitmap[1] = ~0; > } > > static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, > diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c > index 990f06b..45317ea 100644 > --- a/drivers/usb/host/sl811-hcd.c > +++ b/drivers/usb/host/sl811-hcd.c > @@ -1111,8 +1111,8 @@ sl811h_hub_descriptor ( > desc->wHubCharacteristics = cpu_to_le16(temp); > > /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ > - desc->bitmap[0] = 0 << 1; > - desc->bitmap[1] = ~0; > + desc->u.hs.bitmap[0] = 0 << 1; > + desc->u.hs.bitmap[1] = ~0; > } > > static void > diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c > index fab7649..9a2b71f 100644 > --- a/drivers/usb/host/u132-hcd.c > +++ b/drivers/usb/host/u132-hcd.c > @@ -2604,13 +2604,13 @@ static int u132_roothub_descriptor(struct u132 *u132, > retval = u132_read_pcimem(u132, roothub.b, &rh_b); > if (retval) > return retval; > - memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); > - desc->bitmap[0] = rh_b & RH_B_DR; > + memset(desc->u.hs.bitmap, 0xff, sizeof(desc->u.hs.bitmap)); > + desc->u.hs.bitmap[0] = rh_b & RH_B_DR; > if (u132->num_ports > 7) { > - desc->bitmap[1] = (rh_b & RH_B_DR) >> 8; > - desc->bitmap[2] = 0xff; > + desc->u.hs.bitmap[1] = (rh_b & RH_B_DR) >> 8; > + desc->u.hs.bitmap[2] = 0xff; > } else > - desc->bitmap[1] = 0xff; > + desc->u.hs.bitmap[1] = 0xff; > return 0; > } > > diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c > index fef5a1f..c242d18 100644 > --- a/drivers/usb/host/xhci-hub.c > +++ b/drivers/usb/host/xhci-hub.c > @@ -46,8 +46,8 @@ static void xhci_hub_descriptor(struct xhci_hcd *xhci, > desc->bDescLength = 7 + 2 * temp; > > /* Why does core/hcd.h define bitmap? It's just confusing. */ > - memset(&desc->DeviceRemovable[0], 0, temp); > - memset(&desc->DeviceRemovable[temp], 0xff, temp); > + memset(&desc->u.hs.DeviceRemovable[0], 0, temp); > + memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); > > /* Ugh, these should be #defines, FIXME */ > /* Using table 11-13 in USB 2.0 spec. */ > diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c > index a68ad7a..248017a 100644 > --- a/drivers/usb/wusbcore/rh.c > +++ b/drivers/usb/wusbcore/rh.c > @@ -184,8 +184,8 @@ static int wusbhc_rh_get_hub_descr(struct wusbhc *wusbhc, u16 wValue, > descr->bPwrOn2PwrGood = 0; > descr->bHubContrCurrent = 0; > /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ > - memset(&descr->bitmap[0], 0, temp); > - memset(&descr->bitmap[temp], 0xff, temp); > + memset(&descr->u.hs.bitmap[0], 0, temp); > + memset(&descr->u.hs.bitmap[temp], 0xff, temp); > return 0; > } > > diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h > index 10ec069..8618ee6 100644 > --- a/include/linux/usb/ch11.h > +++ b/include/linux/usb/ch11.h > @@ -26,6 +26,7 @@ > #define HUB_RESET_TT 9 > #define HUB_GET_TT_STATE 10 > #define HUB_STOP_TT 11 > +#define HUB_SET_DEPTH 12 > > /* > * Hub class additional requests defined by USB 3.0 spec > @@ -61,6 +62,12 @@ > #define USB_PORT_FEAT_TEST 21 > #define USB_PORT_FEAT_INDICATOR 22 > #define USB_PORT_FEAT_C_PORT_L1 23 > +#define USB_PORT_FEAT_C_PORT_LINK_STATE 25 > +#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26 > +#define USB_PORT_FEAT_PORT_REMOTE_WAKE_MASK 27 > +#define USB_PORT_FEAT_BH_PORT_RESET 28 > +#define USB_PORT_FEAT_C_BH_PORT_RESET 29 > +#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30 > > /* > * Port feature selectors added by USB 3.0 spec. > @@ -110,8 +117,14 @@ struct usb_port_status { > */ > #define USB_PORT_STAT_LINK_STATE 0x01e0 > #define USB_SS_PORT_STAT_POWER 0x0200 > +#define USB_SS_PORT_STAT_SPEED 0x1c00 > #define USB_PORT_STAT_SPEED_5GBPS 0x0000 > /* Valid only if port is enabled */ > +/* Bits that are the same from USB 2.0 */ > +#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION | \ > + USB_PORT_STAT_ENABLE | \ > + USB_PORT_STAT_OVERCURRENT | \ > + USB_PORT_STAT_RESET) > > /* > * Definitions for PORT_LINK_STATE values > @@ -141,6 +154,13 @@ struct usb_port_status { > #define USB_PORT_STAT_C_OVERCURRENT 0x0008 > #define USB_PORT_STAT_C_RESET 0x0010 > #define USB_PORT_STAT_C_L1 0x0020 > +/* > + * USB 3.0 wPortChange bit fields > + * See USB 3.0 spec Table 10-11 > + */ > +#define USB_PORT_STAT_C_BH_RESET 0x0020 > +#define USB_PORT_STAT_C_LINK_STATE 0x0040 > +#define USB_PORT_STAT_C_CONFIG_ERROR 0x0080 > > /* > * wHubCharacteristics (masks) > @@ -175,7 +195,9 @@ struct usb_hub_status { > */ > > #define USB_DT_HUB (USB_TYPE_CLASS | 0x09) > +#define USB_DT_SS_HUB (USB_TYPE_CLASS | 0x0a) > #define USB_DT_HUB_NONVAR_SIZE 7 > +#define USB_DT_SS_HUB_SIZE 12 > > struct usb_hub_descriptor { > __u8 bDescLength; > @@ -184,11 +206,22 @@ struct usb_hub_descriptor { > __le16 wHubCharacteristics; > __u8 bPwrOn2PwrGood; > __u8 bHubContrCurrent; > - /* add 1 bit for hub status change; round to bytes */ > - __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; > - __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; > -} __attribute__ ((packed)); > > + /* 2.0 and 3.0 hubs differ here */ > + union { > + struct { > + /* add 1 bit for hub status change; round to bytes */ > + __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; > + __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; > + } __attribute__ ((packed)) hs; > + > + struct { > + __u8 bHubHdrDecLat; > + __u16 wHubDelay; > + __u16 DeviceRemovable; > + } __attribute__ ((packed)) ss; > + } u; > +} __attribute__ ((packed)); > > /* port indicator status selectors, tables 11-7 and 11-25 */ > #define HUB_LED_AUTO 0 > -- > 1.6.3.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-usb" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- Lei Ming -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html