]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[usb] Allow for USB network devices with no interrupt endpoint
authorMichael Brown <mcb30@ipxe.org>
Thu, 18 May 2017 14:18:25 +0000 (15:18 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 14 Jun 2017 11:14:54 +0000 (12:14 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/usb/usbnet.c
src/include/ipxe/usbnet.h

index d18d81772306e9f9f4f50043c8aed8b6c19504e2..0fac00b56b4926192e9a19fec19e8a6011e6be80 100644 (file)
@@ -35,11 +35,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  * USB network devices use a variety of packet formats and interface
  * descriptors, but tend to have several features in common:
  *
- *  - a single interrupt endpoint using the generic refill mechanism
+ *  - a single bulk OUT endpoint
  *
  *  - a single bulk IN endpoint using the generic refill mechanism
  *
- *  - a single bulk OUT endpoint
+ *  - an optional interrupt endpoint using the generic refill mechanism
  *
  *  - optional use of an alternate setting to enable the data interface
  *
@@ -55,15 +55,17 @@ int usbnet_open ( struct usbnet_device *usbnet ) {
        struct usb_device *usb = usbnet->func->usb;
        int rc;
 
-       /* Open interrupt endpoint */
-       if ( ( rc = usb_endpoint_open ( &usbnet->intr ) ) != 0 ) {
+       /* Open interrupt endpoint, if applicable */
+       if ( usbnet_has_intr ( usbnet ) &&
+            ( rc = usb_endpoint_open ( &usbnet->intr ) ) != 0 ) {
                DBGC ( usbnet, "USBNET %s could not open interrupt: %s\n",
                       usbnet->func->name, strerror ( rc ) );
                goto err_open_intr;
        }
 
-       /* Refill interrupt endpoint */
-       if ( ( rc = usb_refill ( &usbnet->intr ) ) != 0 ) {
+       /* Refill interrupt endpoint, if applicable */
+       if ( usbnet_has_intr ( usbnet ) &&
+            ( rc = usb_refill ( &usbnet->intr ) ) != 0 ) {
                DBGC ( usbnet, "USBNET %s could not refill interrupt: %s\n",
                       usbnet->func->name, strerror ( rc ) );
                goto err_refill_intr;
@@ -111,7 +113,8 @@ int usbnet_open ( struct usbnet_device *usbnet ) {
                usb_set_interface ( usb, usbnet->data, 0 );
  err_set_interface:
  err_refill_intr:
-       usb_endpoint_close ( &usbnet->intr );
+       if ( usbnet_has_intr ( usbnet ) )
+               usb_endpoint_close ( &usbnet->intr );
  err_open_intr:
        return rc;
 }
@@ -134,8 +137,9 @@ void usbnet_close ( struct usbnet_device *usbnet ) {
        if ( usbnet->alternate )
                usb_set_interface ( usb, usbnet->data, 0 );
 
-       /* Close interrupt endpoint */
-       usb_endpoint_close ( &usbnet->intr );
+       /* Close interrupt endpoint, if applicable */
+       if ( usbnet_has_intr ( usbnet ) )
+               usb_endpoint_close ( &usbnet->intr );
 }
 
 /**
@@ -151,9 +155,11 @@ int usbnet_refill ( struct usbnet_device *usbnet ) {
        if ( ( rc = usb_refill ( &usbnet->in ) ) != 0 )
                return rc;
 
-       /* Refill interrupt endpoint */
-       if ( ( rc = usb_refill ( &usbnet->intr ) ) != 0 )
+       /* Refill interrupt endpoint, if applicable */
+       if ( usbnet_has_intr ( usbnet ) &&
+            ( rc = usb_refill ( &usbnet->intr ) ) != 0 ) {
                return rc;
+       }
 
        return 0;
 }
@@ -272,9 +278,11 @@ int usbnet_describe ( struct usbnet_device *usbnet,
                      struct usb_configuration_descriptor *config ) {
        int rc;
 
-       /* Describe communications interface */
-       if ( ( rc = usbnet_comms_describe ( usbnet, config ) ) != 0 )
+       /* Describe communications interface, if applicable */
+       if ( usbnet_has_intr ( usbnet ) &&
+            ( rc = usbnet_comms_describe ( usbnet, config ) ) != 0 ) {
                return rc;
+       }
 
        /* Describe data interface */
        if ( ( rc = usbnet_data_describe ( usbnet, config ) ) != 0 )
index 33a8f3f587cafe569d8d96d9dc9e8bb81611aba3..a7276eba590c2e7cbef926309a6fd8261b024bb8 100644 (file)
@@ -36,7 +36,7 @@ struct usbnet_device {
  *
  * @v usbnet           USB network device
  * @v func             USB function
- * @v intr             Interrupt endpoint operations
+ * @v intr             Interrupt endpoint operations, or NULL
  * @v in               Bulk IN endpoint operations
  * @v out              Bulk OUT endpoint operations
  */
@@ -53,6 +53,18 @@ usbnet_init ( struct usbnet_device *usbnet, struct usb_function *func,
        usb_endpoint_init ( &usbnet->out, usb, out );
 }
 
+/**
+ * Check if USB network device has an interrupt endpoint
+ *
+ * @v usbnet           USB network device
+ * @ret has_intr       Device has an interrupt endpoint
+ */
+static inline __attribute__ (( always_inline )) int
+usbnet_has_intr ( struct usbnet_device *usbnet ) {
+
+       return ( usbnet->intr.driver != NULL );
+}
+
 extern int usbnet_open ( struct usbnet_device *usbnet );
 extern void usbnet_close ( struct usbnet_device *usbnet );
 extern int usbnet_refill ( struct usbnet_device *usbnet );