ChangeSet 1.1290.15.24, 2004/03/17 15:07:34-08:00, david-b@pacbell.net [PATCH] USB: usb gadget, dualspeed {run,compile}-time flags Support some more autoconfiguration for gadget drivers. Run-time: * Add gadget->is_dualspeed flag for controllers to set. * Tested by "ethernet" gadget, to decide whether certain operations are errors or not. * Turned on by net2280. Compile-time * Generic CONFIG_USB_GADGET_DUALSPEED, not net2280-specific. * Used by "ethernet" gadget, to decide whether to include extra code and data for dual-speed support. * Turned on by net2280. The basic idea behind this, and other autoconfig patches yet to come, is minimizing the controller-specific compile-time configuration that gadget drivers need to know about. drivers/usb/gadget/Config.in | 3 +++ drivers/usb/gadget/ether.c | 28 +++++++++++++++------------- drivers/usb/gadget/net2280.c | 1 + include/linux/usb_gadget.h | 3 +++ 4 files changed, 22 insertions(+), 13 deletions(-) diff -Nru a/drivers/usb/gadget/Config.in b/drivers/usb/gadget/Config.in --- a/drivers/usb/gadget/Config.in Wed Mar 17 15:48:17 2004 +++ b/drivers/usb/gadget/Config.in Wed Mar 17 15:48:17 2004 @@ -31,6 +31,9 @@ define_tristate CONFIG_USB_GADGET_CONTROLLER $CONFIG_USB_GOKU fi + # or any other controller that supports high speed transfers ... + define_bool CONFIG_USB_GADGET_DUALSPEED $CONFIG_USB_GADGET_NET2280 + if [ "$CONFIG_USB_GADGET_CONTROLLER" = "y" -o "$CONFIG_USB_GADGET_CONTROLLER" = "m" ] ; then # diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c --- a/drivers/usb/gadget/ether.c Wed Mar 17 15:48:17 2004 +++ b/drivers/usb/gadget/ether.c Wed Mar 17 15:48:17 2004 @@ -136,7 +136,6 @@ * DRIVER_VERSION_NUM ... alerts the host side driver to differences * EP_*_NAME ... which endpoints do we use for which purpose? * EP_*_NUM ... numbers for them (often limited by hardware) - * HIGHSPEED ... define if ep0 and descriptors need high speed support * WAKEUP ... if hardware supports remote wakeup AND we will issue the * usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP * @@ -174,7 +173,6 @@ #define EP_IN_NUM 2 static const char EP_STATUS_NAME [] = "ep-f"; #define EP_STATUS_NUM 3 -#define HIGHSPEED /* supports remote wakeup, but this driver doesn't */ extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); @@ -323,7 +321,7 @@ #define DEFAULT_QLEN 2 /* double buffering by default */ #endif -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED static unsigned qmult = 5; MODULE_PARM (qmult, "i"); @@ -336,7 +334,7 @@ /* also defer IRQs on highspeed TX */ #define TX_DELAY DEFAULT_QLEN -#else /* !HIGHSPEED ... full speed: */ +#else /* full speed (low speed doesn't do bulk) */ #define qlen(gadget) DEFAULT_QLEN #endif @@ -638,7 +636,7 @@ 0, }; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED /* * usb 2.0 devices need to expose both high speed and full speed @@ -719,7 +717,7 @@ /* if there's no high speed support, maxpacket doesn't change. */ #define ep_desc(g,hs,fs) fs -#endif /* !HIGHSPEED */ +#endif /* !CONFIG_USB_GADGET_DUALSPEED */ /*-------------------------------------------------------------------------*/ @@ -756,7 +754,7 @@ { int len; const struct usb_descriptor_header **function = fs_function; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED int hs = (speed == USB_SPEED_HIGH); if (type == USB_DT_OTHER_SPEED_CONFIG) @@ -981,7 +979,7 @@ switch (gadget->speed) { case USB_SPEED_FULL: speed = "full"; break; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_SPEED_HIGH: speed = "high"; break; #endif default: speed = "?"; break; @@ -1152,15 +1150,19 @@ value = min (ctrl->wLength, (u16) sizeof device_desc); memcpy (req->buf, &device_desc, value); break; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_DT_DEVICE_QUALIFIER: + if (!gadget->is_dualspeed) + break; value = min (ctrl->wLength, (u16) sizeof dev_qualifier); memcpy (req->buf, &dev_qualifier, value); break; case USB_DT_OTHER_SPEED_CONFIG: + if (!gadget->is_dualspeed) + break; // FALLTHROUGH -#endif /* HIGHSPEED */ +#endif /* CONFIG_USB_GADGET_DUALSPEED */ case USB_DT_CONFIG: value = config_buf (gadget->speed, req->buf, ctrl->wValue >> 8, @@ -1664,7 +1666,7 @@ #endif req->length = length; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED /* throttle highspeed IRQ rate back slightly */ req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) ? ((atomic_read (&dev->tx_qlen) % TX_DELAY) != 0) @@ -1787,7 +1789,7 @@ #endif device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED /* assumes ep0 uses the same value for both speeds ... */ dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; #endif @@ -1883,7 +1885,7 @@ /*-------------------------------------------------------------------------*/ static struct usb_gadget_driver eth_driver = { -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED .speed = USB_SPEED_HIGH, #else .speed = USB_SPEED_FULL, diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c --- a/drivers/usb/gadget/net2280.c Wed Mar 17 15:48:17 2004 +++ b/drivers/usb/gadget/net2280.c Wed Mar 17 15:48:17 2004 @@ -2718,6 +2718,7 @@ spin_lock_init (&dev->lock); dev->pdev = pdev; dev->gadget.ops = &net2280_ops; + dev->gadget.is_dualspeed = 1; dev->gadget.dev.bus_id = pdev->slot_name; dev->gadget.name = driver_name; diff -Nru a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h --- a/include/linux/usb_gadget.h Wed Mar 17 15:48:17 2004 +++ b/include/linux/usb_gadget.h Wed Mar 17 15:48:17 2004 @@ -465,6 +465,8 @@ * driver setup() requests * @ep_list: List of other endpoints supported by the device. * @speed: Speed of current connection to USB host. + * @is_dualspeed: True if the controller supports both high and full speed + * operation. If it does, the gadget driver must also support both. * @name: Identifies the controller hardware type. Used in diagnostics * and sometimes configuration. * @dev: Driver model state for this abstract device. @@ -488,6 +490,7 @@ struct usb_ep *ep0; struct list_head ep_list; /* of usb_ep */ enum usb_device_speed speed; + unsigned is_dualspeed:1; const char *name; struct __gadget_device {