This patch adds some features that allow the ether gadget to work as a usb_function module.
Signed-off-by: Felipe Balbi <[EMAIL PROTECTED]> Signed-off-by: Ragner Magalhaes <[EMAIL PROTECTED]> :100644 100644 1dd8b57... dd0867f... M drivers/usb/gadget/ether.c diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 1dd8b57..dd0867f 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -49,6 +49,7 @@ #include <linux/usb/ch9.h> #include <linux/usb/cdc.h> #include <linux/usb_gadget.h> +#include <linux/usb/composite.h> #include <linux/random.h> #include <linux/netdevice.h> @@ -118,6 +119,7 @@ static const char driver_desc [] = DRIVER_DESC; struct eth_dev { spinlock_t lock; struct usb_gadget *gadget; + struct usb_function *f; struct usb_request *req; /* for control responses */ struct usb_request *stat_req; /* for cdc & rndis status */ @@ -145,6 +147,8 @@ struct eth_dev { u8 host_mac [ETH_ALEN]; }; +static struct usb_function eth_driver; + /* This version autoconfigures as much as possible at run-time. * * It also ASSUMES a self-powered device, without remote wakeup, @@ -417,14 +421,15 @@ static inline int BITRATE(struct usb_gadget *g) #define STRING_MANUFACTURER 1 #define STRING_PRODUCT 2 -#define STRING_ETHADDR 3 -#define STRING_DATA 4 -#define STRING_CONTROL 5 +#define STRING_SERIALNUMBER 3 +#define STRING_CDC 4 +#define STRING_RNDIS 5 + #define STRING_RNDIS_CONTROL 6 -#define STRING_CDC 7 +#define STRING_DATA 7 #define STRING_SUBSET 8 -#define STRING_RNDIS 9 -#define STRING_SERIALNUMBER 10 +#define STRING_CONTROL 9 +#define STRING_ETHADDR 10 /* holds our biggest descriptor (or RNDIS response) */ #define USB_BUFSIZ 256 @@ -982,7 +987,7 @@ static struct usb_gadget_strings stringtab = { * complications: class descriptors, and an altsetting. */ static int -config_buf (enum usb_device_speed speed, +config_buf (struct eth_dev *dev, u8 *buf, u8 type, unsigned index, int is_otg) { @@ -990,7 +995,7 @@ config_buf (enum usb_device_speed speed, const struct usb_config_descriptor *config; const struct usb_descriptor_header **function; #ifdef CONFIG_USB_GADGET_DUALSPEED - int hs = (speed == USB_SPEED_HIGH); + int hs = (dev->gadget->speed == USB_SPEED_HIGH); if (type == USB_DT_OTHER_SPEED_CONFIG) hs = !hs; @@ -1017,9 +1022,16 @@ config_buf (enum usb_device_speed speed, } /* for now, don't advertise srp-only devices */ - if (!is_otg) + if (!is_otg || is_composite()) function++; + if (is_composite()) { + dev->f->config[index] = config; + buf += dev->req->length; + len = USB_BUFSIZ - dev->req->length; + return usb_descriptor_fillbuf(buf, len, function); + } + len = usb_gadget_config_buf (config, buf, USB_BUFSIZ, function); if (len < 0) return len; @@ -1323,14 +1335,6 @@ static void issue_start_status (struct eth_dev *dev) /*-------------------------------------------------------------------------*/ -static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - DEBUG ((struct eth_dev *) ep->driver_data, - "setup complete --> %d, %d/%d\n", - req->status, req->actual, req->length); -} - #ifdef CONFIG_USB_ETH_RNDIS static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req) @@ -1370,7 +1374,7 @@ static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req) static int eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) { - struct eth_dev *dev = get_gadget_data (gadget); + struct eth_dev *dev = get_usb_function_data (gadget); struct usb_request *req = dev->req; int value = -EOPNOTSUPP; u16 wIndex = le16_to_cpu(ctrl->wIndex); @@ -1380,7 +1384,6 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) /* descriptors just go into the pre-allocated ep0 buffer, * while config change events may enable network traffic. */ - req->complete = eth_setup_complete; switch (ctrl->bRequest) { case USB_REQ_GET_DESCRIPTOR: @@ -1406,7 +1409,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) // FALLTHROUGH #endif /* CONFIG_USB_GADGET_DUALSPEED */ case USB_DT_CONFIG: - value = config_buf (gadget->speed, req->buf, + value = config_buf (dev, req->buf, wValue >> 8, wValue & 0xff, gadget->is_otg); @@ -1422,7 +1425,6 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) break; } break; - case USB_REQ_SET_CONFIGURATION: if (ctrl->bRequestType != 0) break; @@ -1521,9 +1523,10 @@ done_set_intf: /* for CDC, iff carrier is on, data interface is active. */ if (rndis_active(dev) || wIndex != 1) - *(u8 *)req->buf = 0; + *(u8 *)req->buf = INTRF_FUNC2COMPOSITE(dev->f,0); else - *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0; + *(u8 *)req->buf = INTRF_FUNC2COMPOSITE(dev->f, + netif_carrier_ok (dev->net) ? 1 : 0); value = min (wLength, (u16) 1); break; @@ -1599,19 +1602,6 @@ done_set_intf: wValue, wIndex, wLength); } - /* respond with data transfer before status phase? */ - if (value >= 0) { - req->length = value; - req->zero = value < wLength - && (value % gadget->ep0->maxpacket) == 0; - value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); - if (value < 0) { - DEBUG (dev, "ep_queue --> %d\n", value); - req->status = 0; - eth_setup_complete (gadget->ep0, req); - } - } - /* host either stalls (value < 0) or reports success */ return value; } @@ -1619,7 +1609,7 @@ done_set_intf: static void eth_disconnect (struct usb_gadget *gadget) { - struct eth_dev *dev = get_gadget_data (gadget); + struct eth_dev *dev = get_usb_function_data (gadget); unsigned long flags; spin_lock_irqsave (&dev->lock, flags); @@ -2218,17 +2208,19 @@ eth_req_free (struct usb_ep *ep, struct usb_request *req) static void /* __init_or_exit */ eth_unbind (struct usb_gadget *gadget) { - struct eth_dev *dev = get_gadget_data (gadget); + struct eth_dev *dev = get_usb_function_data (gadget); DEBUG (dev, "unbind\n"); + + if (is_composite()) + eth_reset_config (dev); + rndis_deregister (dev->rndis_config); rndis_exit (); /* we've already been disconnected ... no i/o is active */ - if (dev->req) { - eth_req_free (gadget->ep0, dev->req); + if (dev->req) dev->req = NULL; - } if (dev->stat_req) { eth_req_free (dev->status_ep, dev->stat_req); dev->stat_req = NULL; @@ -2239,7 +2231,6 @@ eth_unbind (struct usb_gadget *gadget) /* assuming we used keventd, it must quiesce too */ flush_scheduled_work (); - set_gadget_data (gadget, NULL); } static u8 __devinit nibble (unsigned char c) @@ -2377,7 +2368,6 @@ eth_bind (struct usb_gadget *gadget) } /* all we really need is bulk IN/OUT */ - usb_ep_autoconfig_reset (gadget); in_ep = usb_ep_autoconfig (gadget, &fs_source_desc); if (!in_ep) { autoconf_fail: @@ -2521,10 +2511,7 @@ autoconf_fail: SET_ETHTOOL_OPS(net, &ops); /* preallocate control message data and buffer */ - dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ, GFP_KERNEL); - if (!dev->req) - goto fail; - dev->req->complete = eth_setup_complete; + dev->req = get_usb_gadget_request (gadget); /* ... and maybe likewise for status transfer */ #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) @@ -2532,7 +2519,6 @@ autoconf_fail: dev->stat_req = eth_req_alloc (dev->status_ep, STATUS_BYTECOUNT, GFP_KERNEL); if (!dev->stat_req) { - eth_req_free (gadget->ep0, dev->req); goto fail; } dev->stat_req->context = NULL; @@ -2541,8 +2527,10 @@ autoconf_fail: /* finish hookup to lower layer ... */ dev->gadget = gadget; - set_gadget_data (gadget, dev); - gadget->ep0->driver_data = dev; + dev->f = get_usb_function(gadget); + set_usb_function_data (dev->f, dev); + + dev->f->num_conf = rndis ? 2 : 1; /* two kinds of host-initiated state changes: * - iff DATA transfer is active, carrier is "on" @@ -2615,7 +2603,7 @@ fail: static void eth_suspend (struct usb_gadget *gadget) { - struct eth_dev *dev = get_gadget_data (gadget); + struct eth_dev *dev = get_usb_function_data (gadget); DEBUG (dev, "suspend\n"); dev->suspended = 1; @@ -2624,7 +2612,7 @@ eth_suspend (struct usb_gadget *gadget) static void eth_resume (struct usb_gadget *gadget) { - struct eth_dev *dev = get_gadget_data (gadget); + struct eth_dev *dev = get_usb_function_data (gadget); DEBUG (dev, "resume\n"); dev->suspended = 0; @@ -2632,10 +2620,10 @@ eth_resume (struct usb_gadget *gadget) /*-------------------------------------------------------------------------*/ -static struct usb_gadget_driver eth_driver = { - .speed = DEVSPEED, +static struct usb_function eth_driver = { + .name = (char *) shortname, + .strings = &stringtab, - .function = (char *) driver_desc, .bind = eth_bind, .unbind = eth_unbind, @@ -2644,11 +2632,6 @@ static struct usb_gadget_driver eth_driver = { .suspend = eth_suspend, .resume = eth_resume, - - .driver = { - .name = (char *) shortname, - .owner = THIS_MODULE, - }, }; MODULE_DESCRIPTION (DRIVER_DESC); @@ -2658,13 +2641,13 @@ MODULE_LICENSE ("GPL"); static int __init init (void) { - return usb_gadget_register_driver (ð_driver); + return usb_func_register(ð_driver); } module_init (init); static void __exit cleanup (void) { - usb_gadget_unregister_driver (ð_driver); + usb_func_unregister(ð_driver); } module_exit (cleanup); -- 1.5.0.4.501.gb08b ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel