ChangeSet 1.1608.84.25, 2004/03/10 13:30:20-08:00, david-b@pacbell.net [PATCH] USB gadget: dualspeed {run,compile}-time flags This is the first several autoconfig patches; please merge. This particular one abstracts dual-speed (high and full) support. 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 needed by gadget drivers. drivers/usb/gadget/Kconfig | 8 ++++++++ drivers/usb/gadget/ether.c | 28 +++++++++++++++------------- drivers/usb/gadget/net2280.c | 1 + include/linux/usb_gadget.h | 3 +++ 4 files changed, 27 insertions(+), 13 deletions(-) diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig --- a/drivers/usb/gadget/Kconfig Tue Mar 16 15:02:13 2004 +++ b/drivers/usb/gadget/Kconfig Tue Mar 16 15:02:13 2004 @@ -52,6 +52,7 @@ config USB_GADGET_NET2280 boolean "NetChip 2280" depends on PCI + select USB_GADGET_DUALSPEED help NetChip 2280 is a PCI based USB peripheral controller which supports both full and high speed USB 2.0 data transfers. @@ -135,6 +136,13 @@ endchoice +config USB_GADGET_DUALSPEED + bool + depends on USB_GADGET + default n + help + Means that gadget drivers should include extra descriptors + and code to handle dual-speed controllers. # # USB Gadget Drivers diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c --- a/drivers/usb/gadget/ether.c Tue Mar 16 15:02:13 2004 +++ b/drivers/usb/gadget/ether.c Tue Mar 16 15:02:13 2004 @@ -124,7 +124,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 * @@ -162,7 +161,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); @@ -311,7 +309,7 @@ #define DEFAULT_QLEN 2 /* double buffering by default */ #endif -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED static unsigned qmult = 5; module_param (qmult, uint, S_IRUGO|S_IWUSR); @@ -324,7 +322,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 @@ -626,7 +624,7 @@ 0, }; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED /* * usb 2.0 devices need to expose both high speed and full speed @@ -707,7 +705,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 */ /*-------------------------------------------------------------------------*/ @@ -744,7 +742,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) @@ -969,7 +967,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; @@ -1140,15 +1138,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, @@ -1652,7 +1654,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) @@ -1775,7 +1777,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 @@ -1871,7 +1873,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 Tue Mar 16 15:02:13 2004 +++ b/drivers/usb/gadget/net2280.c Tue Mar 16 15:02:13 2004 @@ -2736,6 +2736,7 @@ spin_lock_init (&dev->lock); dev->pdev = pdev; dev->gadget.ops = &net2280_ops; + dev->gadget.is_dualspeed = 1; /* the "gadget" abstracts/virtualizes the controller */ strcpy (dev->gadget.dev.bus_id, "gadget"); diff -Nru a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h --- a/include/linux/usb_gadget.h Tue Mar 16 15:02:13 2004 +++ b/include/linux/usb_gadget.h Tue Mar 16 15:02:13 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 device dev; };