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/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel