]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[usb] Parse endpoint descriptor bInterval field
authorMichael Brown <mcb30@ipxe.org>
Mon, 9 Feb 2015 23:50:35 +0000 (23:50 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 10 Feb 2015 01:14:22 +0000 (01:14 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/bus/usb.c
src/drivers/usb/xhci.c
src/drivers/usb/xhci.h
src/include/ipxe/usb.h

index 97c2e3fcf940fafc1d9ae44f7caf8a1774f48439..5a338a5e0da534157d599a359d36a2dc3f6fd0c7 100644 (file)
@@ -227,10 +227,13 @@ int usb_endpoint_described ( struct usb_endpoint *ep,
                             struct usb_configuration_descriptor *config,
                             struct usb_interface_descriptor *interface,
                             unsigned int type, unsigned int index ) {
+       struct usb_device *usb = ep->usb;
+       struct usb_port *port = usb->port;
        struct usb_endpoint_descriptor *desc;
        struct usb_endpoint_companion_descriptor *descx;
        unsigned int sizes;
        unsigned int burst;
+       unsigned int interval;
        size_t mtu;
 
        /* Locate endpoint descriptor */
@@ -246,9 +249,23 @@ int usb_endpoint_described ( struct usb_endpoint *ep,
        mtu = USB_ENDPOINT_MTU ( sizes );
        burst = ( descx ? descx->burst : USB_ENDPOINT_BURST ( sizes ) );
 
+       /* Calculate interval */
+       if ( type == USB_INTERRUPT ) {
+               if ( port->speed >= USB_SPEED_HIGH ) {
+                       /* 2^(desc->interval-1) is a microframe count */
+                       interval = ( 1 << ( desc->interval - 1 ) );
+               } else {
+                       /* desc->interval is a (whole) frame count */
+                       interval = ( desc->interval << 3 );
+               }
+       } else {
+               /* desc->interval is a microframe count */
+               interval = desc->interval;
+       }
+
        /* Describe endpoint */
        usb_endpoint_describe ( ep, desc->endpoint, desc->attributes,
-                               mtu, burst );
+                               mtu, burst, interval );
        return 0;
 }
 
@@ -286,8 +303,9 @@ int usb_endpoint_open ( struct usb_endpoint *ep ) {
        }
        ep->open = 1;
 
-       DBGC2 ( usb, "USB %s %s opened with MTU %zd (burst %d)\n", usb->name,
-               usb_endpoint_name ( ep->address ), ep->mtu, ep->burst );
+       DBGC2 ( usb, "USB %s %s opened with MTU %zd, burst %d, interval %d\n",
+               usb->name, usb_endpoint_name ( ep->address ), ep->mtu,
+               ep->burst, ep->interval );
        return 0;
 
        ep->open = 0;
@@ -1147,7 +1165,8 @@ static int register_usb ( struct usb_device *usb ) {
        /* Describe control endpoint */
        mtu = USB_EP0_DEFAULT_MTU ( port->speed );
        usb_endpoint_describe ( &usb->control, USB_EP0_ADDRESS,
-                               USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST );
+                               USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST,
+                               USB_EP0_INTERVAL );
 
        /* Open control endpoint */
        if ( ( rc = usb_endpoint_open ( &usb->control ) ) != 0 )
index cdebc47da2d42f326f21b35f11f96176e33effae..49901275d4d66ebc6e0afd200024752cb73679a5 100644 (file)
@@ -1986,6 +1986,7 @@ static void xhci_configure_endpoint_input ( struct xhci_device *xhci,
 
        /* Populate endpoint context */
        ep_ctx = ( input + xhci_input_context_offset ( xhci, endpoint->ctx ) );
+       ep_ctx->interval = endpoint->interval;
        ep_ctx->type = endpoint->type;
        ep_ctx->burst = endpoint->ep->burst;
        ep_ctx->mtu = cpu_to_le16 ( endpoint->ep->mtu );
@@ -2252,6 +2253,7 @@ static int xhci_endpoint_open ( struct usb_endpoint *ep ) {
        struct xhci_endpoint *endpoint;
        unsigned int ctx;
        unsigned int type;
+       unsigned int interval;
        int rc;
 
        /* Calculate context index */
@@ -2265,6 +2267,13 @@ static int xhci_endpoint_open ( struct usb_endpoint *ep ) {
        if ( ep->address & USB_DIR_IN )
                type |= XHCI_EP_TYPE_IN;
 
+       /* Calculate interval */
+       if ( type & XHCI_EP_TYPE_PERIODIC ) {
+               interval = ( fls ( ep->interval ) - 1 );
+       } else {
+               interval = ep->interval;
+       }
+
        /* Allocate and initialise structure */
        endpoint = zalloc ( sizeof ( *endpoint ) );
        if ( ! endpoint ) {
@@ -2278,6 +2287,7 @@ static int xhci_endpoint_open ( struct usb_endpoint *ep ) {
        endpoint->ep = ep;
        endpoint->ctx = ctx;
        endpoint->type = type;
+       endpoint->interval = interval;
        endpoint->context = ( ( ( void * ) slot->context ) +
                              xhci_device_context_offset ( xhci, ctx ) );
 
index 7f768aa0a090b62f3a1589d224cbe0946b78142d..186ff27d00c23c67df16a82f7d38f1bcc487d55a 100644 (file)
@@ -806,6 +806,9 @@ enum xhci_endpoint_state {
 /** Input endpoint type */
 #define XHCI_EP_TYPE_IN XHCI_EP_TYPE ( 4 )
 
+/** Periodic endpoint type */
+#define XHCI_EP_TYPE_PERIODIC XHCI_EP_TYPE ( 1 )
+
 /** Endpoint dequeue cycle state */
 #define XHCI_EP_DCS 0x00000001UL
 
@@ -1078,6 +1081,8 @@ struct xhci_endpoint {
        unsigned int ctx;
        /** Endpoint type */
        unsigned int type;
+       /** Endpoint interval */
+       unsigned int interval;
        /** Endpoint context */
        struct xhci_endpoint_context *context;
        /** Transfer ring */
index acc8391f71261e00d78aa7f5c57907442843ec74..e21ca1c432c4f615e72933e17609d7d74fbcd72f 100644 (file)
@@ -372,6 +372,8 @@ struct usb_endpoint {
        size_t mtu;
        /** Maximum burst size */
        unsigned int burst;
+       /** Interval (in microframes) */
+       unsigned int interval;
 
        /** Endpoint is open */
        int open;
@@ -462,6 +464,9 @@ struct usb_endpoint_driver_operations {
 /** Control endpoint maximum burst size */
 #define USB_EP0_BURST 0
 
+/** Control endpoint interval */
+#define USB_EP0_INTERVAL 0
+
 /** Maximum endpoint number */
 #define USB_ENDPOINT_MAX 0x0f
 
@@ -496,16 +501,18 @@ usb_endpoint_init ( struct usb_endpoint *ep, struct usb_device *usb,
  * @v attributes       Attributes
  * @v mtu              Maximum packet size
  * @v burst            Maximum burst size
+ * @v interval         Interval (in microframes)
  */
 static inline __attribute__ (( always_inline )) void
 usb_endpoint_describe ( struct usb_endpoint *ep, unsigned int address,
                        unsigned int attributes, size_t mtu,
-                       unsigned int burst ) {
+                       unsigned int burst, unsigned int interval ) {
 
        ep->address = address;
        ep->attributes = attributes;
        ep->mtu = mtu;
        ep->burst = burst;
+       ep->interval = interval;
 }
 
 /**