diff --git a/src/drivers/usb/usbnet.c b/src/drivers/usb/usbnet.c index d18d8177..0fac00b5 100644 --- a/src/drivers/usb/usbnet.c +++ b/src/drivers/usb/usbnet.c @@ -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 ) diff --git a/src/include/ipxe/usbnet.h b/src/include/ipxe/usbnet.h index 33a8f3f5..a7276eba 100644 --- a/src/include/ipxe/usbnet.h +++ b/src/include/ipxe/usbnet.h @@ -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 );