blob: 4e595324c614f6c8578055f8c577ad7a818b3e99 [file] [log] [blame]
David Brownellda741b82008-06-19 18:19:46 -07001/*
2 * f_ecm.c -- USB CDC Ethernet (ECM) link function driver
3 *
4 * Copyright (C) 2003-2005,2008 David Brownell
5 * Copyright (C) 2008 Nokia Corporation
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22/* #define VERBOSE_DEBUG */
23
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090024#include <linux/slab.h>
David Brownellda741b82008-06-19 18:19:46 -070025#include <linux/kernel.h>
26#include <linux/device.h>
27#include <linux/etherdevice.h>
28
29#include "u_ether.h"
30
31
32/*
33 * This function is a "CDC Ethernet Networking Control Model" (CDC ECM)
34 * Ethernet link. The data transfer model is simple (packets sent and
35 * received over bulk endpoints using normal short packet termination),
36 * and the control model exposes various data and optional notifications.
37 *
38 * ECM is well standardized and (except for Microsoft) supported by most
39 * operating systems with USB host support. It's the preferred interop
40 * solution for Ethernet over USB, at least for firmware based solutions.
41 * (Hardware solutions tend to be more minimalist.) A newer and simpler
42 * "Ethernet Emulation Model" (CDC EEM) hasn't yet caught on.
43 *
44 * Note that ECM requires the use of "alternate settings" for its data
45 * interface. This means that the set_alt() method has real work to do,
46 * and also means that a get_alt() method is required.
47 */
48
49struct ecm_ep_descs {
50 struct usb_endpoint_descriptor *in;
51 struct usb_endpoint_descriptor *out;
52 struct usb_endpoint_descriptor *notify;
53};
54
55enum ecm_notify_state {
56 ECM_NOTIFY_NONE, /* don't notify */
57 ECM_NOTIFY_CONNECT, /* issue CONNECT next */
58 ECM_NOTIFY_SPEED, /* issue SPEED_CHANGE next */
59};
60
61struct f_ecm {
62 struct gether port;
63 u8 ctrl_id, data_id;
64
65 char ethaddr[14];
66
David Brownellda741b82008-06-19 18:19:46 -070067 struct ecm_ep_descs fs;
David Brownellda741b82008-06-19 18:19:46 -070068 struct ecm_ep_descs hs;
69
70 struct usb_ep *notify;
71 struct usb_endpoint_descriptor *notify_desc;
72 struct usb_request *notify_req;
73 u8 notify_state;
74 bool is_open;
75
76 /* FIXME is_open needs some irq-ish locking
77 * ... possibly the same as port.ioport
78 */
79};
80
81static inline struct f_ecm *func_to_ecm(struct usb_function *f)
82{
83 return container_of(f, struct f_ecm, port.func);
84}
85
86/* peak (theoretical) bulk transfer rate in bits-per-second */
David Brownell33376c12008-08-18 17:45:07 -070087static inline unsigned ecm_bitrate(struct usb_gadget *g)
David Brownellda741b82008-06-19 18:19:46 -070088{
89 if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
90 return 13 * 512 * 8 * 1000 * 8;
91 else
92 return 19 * 64 * 1 * 1000 * 8;
93}
94
95/*-------------------------------------------------------------------------*/
96
97/*
98 * Include the status endpoint if we can, even though it's optional.
99 *
100 * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
101 * packet, to simplify cancellation; and a big transfer interval, to
102 * waste less bandwidth.
103 *
104 * Some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
105 * if they ignore the connect/disconnect notifications that real aether
106 * can provide. More advanced cdc configurations might want to support
107 * encapsulated commands (vendor-specific, using control-OUT).
108 */
109
110#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
David Brownell33376c12008-08-18 17:45:07 -0700111#define ECM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
David Brownellda741b82008-06-19 18:19:46 -0700112
113
114/* interface descriptor: */
115
116static struct usb_interface_descriptor ecm_control_intf __initdata = {
117 .bLength = sizeof ecm_control_intf,
118 .bDescriptorType = USB_DT_INTERFACE,
119
120 /* .bInterfaceNumber = DYNAMIC */
121 /* status endpoint is optional; this could be patched later */
122 .bNumEndpoints = 1,
123 .bInterfaceClass = USB_CLASS_COMM,
124 .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
125 .bInterfaceProtocol = USB_CDC_PROTO_NONE,
126 /* .iInterface = DYNAMIC */
127};
128
David Brownell33376c12008-08-18 17:45:07 -0700129static struct usb_cdc_header_desc ecm_header_desc __initdata = {
130 .bLength = sizeof ecm_header_desc,
David Brownellda741b82008-06-19 18:19:46 -0700131 .bDescriptorType = USB_DT_CS_INTERFACE,
132 .bDescriptorSubType = USB_CDC_HEADER_TYPE,
133
Harvey Harrison551509d2009-02-11 14:11:36 -0800134 .bcdCDC = cpu_to_le16(0x0110),
David Brownellda741b82008-06-19 18:19:46 -0700135};
136
137static struct usb_cdc_union_desc ecm_union_desc __initdata = {
138 .bLength = sizeof(ecm_union_desc),
139 .bDescriptorType = USB_DT_CS_INTERFACE,
140 .bDescriptorSubType = USB_CDC_UNION_TYPE,
141 /* .bMasterInterface0 = DYNAMIC */
142 /* .bSlaveInterface0 = DYNAMIC */
143};
144
David Brownell33376c12008-08-18 17:45:07 -0700145static struct usb_cdc_ether_desc ecm_desc __initdata = {
146 .bLength = sizeof ecm_desc,
David Brownellda741b82008-06-19 18:19:46 -0700147 .bDescriptorType = USB_DT_CS_INTERFACE,
148 .bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
149
150 /* this descriptor actually adds value, surprise! */
151 /* .iMACAddress = DYNAMIC */
Harvey Harrison551509d2009-02-11 14:11:36 -0800152 .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */
153 .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN),
154 .wNumberMCFilters = cpu_to_le16(0),
David Brownellda741b82008-06-19 18:19:46 -0700155 .bNumberPowerFilters = 0,
156};
157
158/* the default data interface has no endpoints ... */
159
160static struct usb_interface_descriptor ecm_data_nop_intf __initdata = {
161 .bLength = sizeof ecm_data_nop_intf,
162 .bDescriptorType = USB_DT_INTERFACE,
163
164 .bInterfaceNumber = 1,
165 .bAlternateSetting = 0,
166 .bNumEndpoints = 0,
167 .bInterfaceClass = USB_CLASS_CDC_DATA,
168 .bInterfaceSubClass = 0,
169 .bInterfaceProtocol = 0,
170 /* .iInterface = DYNAMIC */
171};
172
173/* ... but the "real" data interface has two bulk endpoints */
174
175static struct usb_interface_descriptor ecm_data_intf __initdata = {
176 .bLength = sizeof ecm_data_intf,
177 .bDescriptorType = USB_DT_INTERFACE,
178
179 .bInterfaceNumber = 1,
180 .bAlternateSetting = 1,
181 .bNumEndpoints = 2,
182 .bInterfaceClass = USB_CLASS_CDC_DATA,
183 .bInterfaceSubClass = 0,
184 .bInterfaceProtocol = 0,
185 /* .iInterface = DYNAMIC */
186};
187
188/* full speed support: */
189
David Brownell33376c12008-08-18 17:45:07 -0700190static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
David Brownellda741b82008-06-19 18:19:46 -0700191 .bLength = USB_DT_ENDPOINT_SIZE,
192 .bDescriptorType = USB_DT_ENDPOINT,
193
194 .bEndpointAddress = USB_DIR_IN,
195 .bmAttributes = USB_ENDPOINT_XFER_INT,
Harvey Harrison551509d2009-02-11 14:11:36 -0800196 .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
David Brownellda741b82008-06-19 18:19:46 -0700197 .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
198};
199
David Brownell33376c12008-08-18 17:45:07 -0700200static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = {
David Brownellda741b82008-06-19 18:19:46 -0700201 .bLength = USB_DT_ENDPOINT_SIZE,
202 .bDescriptorType = USB_DT_ENDPOINT,
203
204 .bEndpointAddress = USB_DIR_IN,
205 .bmAttributes = USB_ENDPOINT_XFER_BULK,
206};
207
David Brownell33376c12008-08-18 17:45:07 -0700208static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = {
David Brownellda741b82008-06-19 18:19:46 -0700209 .bLength = USB_DT_ENDPOINT_SIZE,
210 .bDescriptorType = USB_DT_ENDPOINT,
211
212 .bEndpointAddress = USB_DIR_OUT,
213 .bmAttributes = USB_ENDPOINT_XFER_BULK,
214};
215
David Brownell33376c12008-08-18 17:45:07 -0700216static struct usb_descriptor_header *ecm_fs_function[] __initdata = {
David Brownellda741b82008-06-19 18:19:46 -0700217 /* CDC ECM control descriptors */
218 (struct usb_descriptor_header *) &ecm_control_intf,
David Brownell33376c12008-08-18 17:45:07 -0700219 (struct usb_descriptor_header *) &ecm_header_desc,
David Brownellda741b82008-06-19 18:19:46 -0700220 (struct usb_descriptor_header *) &ecm_union_desc,
David Brownell33376c12008-08-18 17:45:07 -0700221 (struct usb_descriptor_header *) &ecm_desc,
David Brownellda741b82008-06-19 18:19:46 -0700222 /* NOTE: status endpoint might need to be removed */
David Brownell33376c12008-08-18 17:45:07 -0700223 (struct usb_descriptor_header *) &fs_ecm_notify_desc,
David Brownellda741b82008-06-19 18:19:46 -0700224 /* data interface, altsettings 0 and 1 */
225 (struct usb_descriptor_header *) &ecm_data_nop_intf,
226 (struct usb_descriptor_header *) &ecm_data_intf,
David Brownell33376c12008-08-18 17:45:07 -0700227 (struct usb_descriptor_header *) &fs_ecm_in_desc,
228 (struct usb_descriptor_header *) &fs_ecm_out_desc,
David Brownellda741b82008-06-19 18:19:46 -0700229 NULL,
230};
231
232/* high speed support: */
233
David Brownell33376c12008-08-18 17:45:07 -0700234static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
David Brownellda741b82008-06-19 18:19:46 -0700235 .bLength = USB_DT_ENDPOINT_SIZE,
236 .bDescriptorType = USB_DT_ENDPOINT,
237
238 .bEndpointAddress = USB_DIR_IN,
239 .bmAttributes = USB_ENDPOINT_XFER_INT,
Harvey Harrison551509d2009-02-11 14:11:36 -0800240 .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
David Brownellda741b82008-06-19 18:19:46 -0700241 .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
242};
David Brownell33376c12008-08-18 17:45:07 -0700243static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
David Brownellda741b82008-06-19 18:19:46 -0700244 .bLength = USB_DT_ENDPOINT_SIZE,
245 .bDescriptorType = USB_DT_ENDPOINT,
246
247 .bEndpointAddress = USB_DIR_IN,
248 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Harvey Harrison551509d2009-02-11 14:11:36 -0800249 .wMaxPacketSize = cpu_to_le16(512),
David Brownellda741b82008-06-19 18:19:46 -0700250};
251
David Brownell33376c12008-08-18 17:45:07 -0700252static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
David Brownellda741b82008-06-19 18:19:46 -0700253 .bLength = USB_DT_ENDPOINT_SIZE,
254 .bDescriptorType = USB_DT_ENDPOINT,
255
256 .bEndpointAddress = USB_DIR_OUT,
257 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Harvey Harrison551509d2009-02-11 14:11:36 -0800258 .wMaxPacketSize = cpu_to_le16(512),
David Brownellda741b82008-06-19 18:19:46 -0700259};
260
David Brownell33376c12008-08-18 17:45:07 -0700261static struct usb_descriptor_header *ecm_hs_function[] __initdata = {
David Brownellda741b82008-06-19 18:19:46 -0700262 /* CDC ECM control descriptors */
263 (struct usb_descriptor_header *) &ecm_control_intf,
David Brownell33376c12008-08-18 17:45:07 -0700264 (struct usb_descriptor_header *) &ecm_header_desc,
David Brownellda741b82008-06-19 18:19:46 -0700265 (struct usb_descriptor_header *) &ecm_union_desc,
David Brownell33376c12008-08-18 17:45:07 -0700266 (struct usb_descriptor_header *) &ecm_desc,
David Brownellda741b82008-06-19 18:19:46 -0700267 /* NOTE: status endpoint might need to be removed */
David Brownell33376c12008-08-18 17:45:07 -0700268 (struct usb_descriptor_header *) &hs_ecm_notify_desc,
David Brownellda741b82008-06-19 18:19:46 -0700269 /* data interface, altsettings 0 and 1 */
270 (struct usb_descriptor_header *) &ecm_data_nop_intf,
271 (struct usb_descriptor_header *) &ecm_data_intf,
David Brownell33376c12008-08-18 17:45:07 -0700272 (struct usb_descriptor_header *) &hs_ecm_in_desc,
273 (struct usb_descriptor_header *) &hs_ecm_out_desc,
David Brownellda741b82008-06-19 18:19:46 -0700274 NULL,
275};
276
277/* string descriptors: */
278
279static struct usb_string ecm_string_defs[] = {
280 [0].s = "CDC Ethernet Control Model (ECM)",
281 [1].s = NULL /* DYNAMIC */,
282 [2].s = "CDC Ethernet Data",
283 { } /* end of list */
284};
285
286static struct usb_gadget_strings ecm_string_table = {
287 .language = 0x0409, /* en-us */
288 .strings = ecm_string_defs,
289};
290
291static struct usb_gadget_strings *ecm_strings[] = {
292 &ecm_string_table,
293 NULL,
294};
295
296/*-------------------------------------------------------------------------*/
297
298static void ecm_do_notify(struct f_ecm *ecm)
299{
300 struct usb_request *req = ecm->notify_req;
301 struct usb_cdc_notification *event;
302 struct usb_composite_dev *cdev = ecm->port.func.config->cdev;
303 __le32 *data;
304 int status;
305
306 /* notification already in flight? */
307 if (!req)
308 return;
309
310 event = req->buf;
311 switch (ecm->notify_state) {
312 case ECM_NOTIFY_NONE:
313 return;
314
315 case ECM_NOTIFY_CONNECT:
316 event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
317 if (ecm->is_open)
318 event->wValue = cpu_to_le16(1);
319 else
320 event->wValue = cpu_to_le16(0);
321 event->wLength = 0;
322 req->length = sizeof *event;
323
324 DBG(cdev, "notify connect %s\n",
325 ecm->is_open ? "true" : "false");
326 ecm->notify_state = ECM_NOTIFY_SPEED;
327 break;
328
329 case ECM_NOTIFY_SPEED:
330 event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
331 event->wValue = cpu_to_le16(0);
332 event->wLength = cpu_to_le16(8);
David Brownell33376c12008-08-18 17:45:07 -0700333 req->length = ECM_STATUS_BYTECOUNT;
David Brownellda741b82008-06-19 18:19:46 -0700334
335 /* SPEED_CHANGE data is up/down speeds in bits/sec */
336 data = req->buf + sizeof *event;
David Brownell33376c12008-08-18 17:45:07 -0700337 data[0] = cpu_to_le32(ecm_bitrate(cdev->gadget));
David Brownellda741b82008-06-19 18:19:46 -0700338 data[1] = data[0];
339
David Brownell33376c12008-08-18 17:45:07 -0700340 DBG(cdev, "notify speed %d\n", ecm_bitrate(cdev->gadget));
David Brownellda741b82008-06-19 18:19:46 -0700341 ecm->notify_state = ECM_NOTIFY_NONE;
342 break;
343 }
344 event->bmRequestType = 0xA1;
345 event->wIndex = cpu_to_le16(ecm->ctrl_id);
346
347 ecm->notify_req = NULL;
348 status = usb_ep_queue(ecm->notify, req, GFP_ATOMIC);
349 if (status < 0) {
350 ecm->notify_req = req;
351 DBG(cdev, "notify --> %d\n", status);
352 }
353}
354
355static void ecm_notify(struct f_ecm *ecm)
356{
357 /* NOTE on most versions of Linux, host side cdc-ethernet
358 * won't listen for notifications until its netdevice opens.
359 * The first notification then sits in the FIFO for a long
360 * time, and the second one is queued.
361 */
362 ecm->notify_state = ECM_NOTIFY_CONNECT;
363 ecm_do_notify(ecm);
364}
365
366static void ecm_notify_complete(struct usb_ep *ep, struct usb_request *req)
367{
368 struct f_ecm *ecm = req->context;
369 struct usb_composite_dev *cdev = ecm->port.func.config->cdev;
370 struct usb_cdc_notification *event = req->buf;
371
372 switch (req->status) {
373 case 0:
374 /* no fault */
375 break;
376 case -ECONNRESET:
377 case -ESHUTDOWN:
378 ecm->notify_state = ECM_NOTIFY_NONE;
379 break;
380 default:
381 DBG(cdev, "event %02x --> %d\n",
382 event->bNotificationType, req->status);
383 break;
384 }
385 ecm->notify_req = req;
386 ecm_do_notify(ecm);
387}
388
389static int ecm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
390{
391 struct f_ecm *ecm = func_to_ecm(f);
392 struct usb_composite_dev *cdev = f->config->cdev;
393 struct usb_request *req = cdev->req;
394 int value = -EOPNOTSUPP;
395 u16 w_index = le16_to_cpu(ctrl->wIndex);
396 u16 w_value = le16_to_cpu(ctrl->wValue);
397 u16 w_length = le16_to_cpu(ctrl->wLength);
398
399 /* composite driver infrastructure handles everything except
400 * CDC class messages; interface activation uses set_alt().
401 */
402 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
403 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
404 | USB_CDC_SET_ETHERNET_PACKET_FILTER:
405 /* see 6.2.30: no data, wIndex = interface,
406 * wValue = packet filter bitmap
407 */
408 if (w_length != 0 || w_index != ecm->ctrl_id)
409 goto invalid;
410 DBG(cdev, "packet filter %02x\n", w_value);
411 /* REVISIT locking of cdc_filter. This assumes the UDC
412 * driver won't have a concurrent packet TX irq running on
413 * another CPU; or that if it does, this write is atomic...
414 */
415 ecm->port.cdc_filter = w_value;
416 value = 0;
417 break;
418
419 /* and optionally:
420 * case USB_CDC_SEND_ENCAPSULATED_COMMAND:
421 * case USB_CDC_GET_ENCAPSULATED_RESPONSE:
422 * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
423 * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
424 * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
425 * case USB_CDC_GET_ETHERNET_STATISTIC:
426 */
427
428 default:
429invalid:
430 DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
431 ctrl->bRequestType, ctrl->bRequest,
432 w_value, w_index, w_length);
433 }
434
435 /* respond with data transfer or status phase? */
436 if (value >= 0) {
437 DBG(cdev, "ecm req%02x.%02x v%04x i%04x l%d\n",
438 ctrl->bRequestType, ctrl->bRequest,
439 w_value, w_index, w_length);
440 req->zero = 0;
441 req->length = value;
442 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
443 if (value < 0)
444 ERROR(cdev, "ecm req %02x.%02x response err %d\n",
445 ctrl->bRequestType, ctrl->bRequest,
446 value);
447 }
448
449 /* device either stalls (value < 0) or reports success */
450 return value;
451}
452
453
454static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
455{
456 struct f_ecm *ecm = func_to_ecm(f);
457 struct usb_composite_dev *cdev = f->config->cdev;
458
459 /* Control interface has only altsetting 0 */
460 if (intf == ecm->ctrl_id) {
461 if (alt != 0)
462 goto fail;
463
464 if (ecm->notify->driver_data) {
465 VDBG(cdev, "reset ecm control %d\n", intf);
466 usb_ep_disable(ecm->notify);
467 } else {
468 VDBG(cdev, "init ecm ctrl %d\n", intf);
469 ecm->notify_desc = ep_choose(cdev->gadget,
470 ecm->hs.notify,
471 ecm->fs.notify);
472 }
473 usb_ep_enable(ecm->notify, ecm->notify_desc);
474 ecm->notify->driver_data = ecm;
475
476 /* Data interface has two altsettings, 0 and 1 */
477 } else if (intf == ecm->data_id) {
478 if (alt > 1)
479 goto fail;
480
481 if (ecm->port.in_ep->driver_data) {
482 DBG(cdev, "reset ecm\n");
483 gether_disconnect(&ecm->port);
484 }
485
486 if (!ecm->port.in) {
487 DBG(cdev, "init ecm\n");
488 ecm->port.in = ep_choose(cdev->gadget,
489 ecm->hs.in, ecm->fs.in);
490 ecm->port.out = ep_choose(cdev->gadget,
491 ecm->hs.out, ecm->fs.out);
492 }
493
494 /* CDC Ethernet only sends data in non-default altsettings.
495 * Changing altsettings resets filters, statistics, etc.
496 */
497 if (alt == 1) {
498 struct net_device *net;
499
500 /* Enable zlps by default for ECM conformance;
Christoph Egger90f79762010-02-05 13:24:12 +0100501 * override for musb_hdrc (avoids txdma ovhead).
David Brownellda741b82008-06-19 18:19:46 -0700502 */
Christoph Egger90f79762010-02-05 13:24:12 +0100503 ecm->port.is_zlp_ok = !(gadget_is_musbhdrc(cdev->gadget)
David Brownellda741b82008-06-19 18:19:46 -0700504 );
505 ecm->port.cdc_filter = DEFAULT_FILTER;
506 DBG(cdev, "activate ecm\n");
507 net = gether_connect(&ecm->port);
508 if (IS_ERR(net))
509 return PTR_ERR(net);
510 }
511
512 /* NOTE this can be a minor disagreement with the ECM spec,
513 * which says speed notifications will "always" follow
514 * connection notifications. But we allow one connect to
515 * follow another (if the first is in flight), and instead
516 * just guarantee that a speed notification is always sent.
517 */
518 ecm_notify(ecm);
519 } else
520 goto fail;
521
522 return 0;
523fail:
524 return -EINVAL;
525}
526
527/* Because the data interface supports multiple altsettings,
528 * this ECM function *MUST* implement a get_alt() method.
529 */
530static int ecm_get_alt(struct usb_function *f, unsigned intf)
531{
532 struct f_ecm *ecm = func_to_ecm(f);
533
534 if (intf == ecm->ctrl_id)
535 return 0;
536 return ecm->port.in_ep->driver_data ? 1 : 0;
537}
538
539static void ecm_disable(struct usb_function *f)
540{
541 struct f_ecm *ecm = func_to_ecm(f);
542 struct usb_composite_dev *cdev = f->config->cdev;
543
544 DBG(cdev, "ecm deactivated\n");
545
546 if (ecm->port.in_ep->driver_data)
547 gether_disconnect(&ecm->port);
548
549 if (ecm->notify->driver_data) {
550 usb_ep_disable(ecm->notify);
551 ecm->notify->driver_data = NULL;
552 ecm->notify_desc = NULL;
553 }
554}
555
556/*-------------------------------------------------------------------------*/
557
558/*
559 * Callbacks let us notify the host about connect/disconnect when the
560 * net device is opened or closed.
561 *
562 * For testing, note that link states on this side include both opened
563 * and closed variants of:
564 *
565 * - disconnected/unconfigured
566 * - configured but inactive (data alt 0)
567 * - configured and active (data alt 1)
568 *
569 * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and
570 * SET_INTERFACE (altsetting). Remember also that "configured" doesn't
571 * imply the host is actually polling the notification endpoint, and
572 * likewise that "active" doesn't imply it's actually using the data
573 * endpoints for traffic.
574 */
575
576static void ecm_open(struct gether *geth)
577{
578 struct f_ecm *ecm = func_to_ecm(&geth->func);
579
580 DBG(ecm->port.func.config->cdev, "%s\n", __func__);
581
582 ecm->is_open = true;
583 ecm_notify(ecm);
584}
585
586static void ecm_close(struct gether *geth)
587{
588 struct f_ecm *ecm = func_to_ecm(&geth->func);
589
590 DBG(ecm->port.func.config->cdev, "%s\n", __func__);
591
592 ecm->is_open = false;
593 ecm_notify(ecm);
594}
595
596/*-------------------------------------------------------------------------*/
597
598/* ethernet function driver setup/binding */
599
600static int __init
601ecm_bind(struct usb_configuration *c, struct usb_function *f)
602{
603 struct usb_composite_dev *cdev = c->cdev;
604 struct f_ecm *ecm = func_to_ecm(f);
605 int status;
606 struct usb_ep *ep;
607
608 /* allocate instance-specific interface IDs */
609 status = usb_interface_id(c, f);
610 if (status < 0)
611 goto fail;
612 ecm->ctrl_id = status;
613
614 ecm_control_intf.bInterfaceNumber = status;
615 ecm_union_desc.bMasterInterface0 = status;
616
617 status = usb_interface_id(c, f);
618 if (status < 0)
619 goto fail;
620 ecm->data_id = status;
621
622 ecm_data_nop_intf.bInterfaceNumber = status;
623 ecm_data_intf.bInterfaceNumber = status;
624 ecm_union_desc.bSlaveInterface0 = status;
625
626 status = -ENODEV;
627
628 /* allocate instance-specific endpoints */
David Brownell33376c12008-08-18 17:45:07 -0700629 ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_in_desc);
David Brownellda741b82008-06-19 18:19:46 -0700630 if (!ep)
631 goto fail;
632 ecm->port.in_ep = ep;
633 ep->driver_data = cdev; /* claim */
634
David Brownell33376c12008-08-18 17:45:07 -0700635 ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
David Brownellda741b82008-06-19 18:19:46 -0700636 if (!ep)
637 goto fail;
638 ecm->port.out_ep = ep;
639 ep->driver_data = cdev; /* claim */
640
641 /* NOTE: a status/notification endpoint is *OPTIONAL* but we
642 * don't treat it that way. It's simpler, and some newer CDC
643 * profiles (wireless handsets) no longer treat it as optional.
644 */
David Brownell33376c12008-08-18 17:45:07 -0700645 ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_notify_desc);
David Brownellda741b82008-06-19 18:19:46 -0700646 if (!ep)
647 goto fail;
648 ecm->notify = ep;
649 ep->driver_data = cdev; /* claim */
650
651 status = -ENOMEM;
652
653 /* allocate notification request and buffer */
654 ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
655 if (!ecm->notify_req)
656 goto fail;
David Brownell33376c12008-08-18 17:45:07 -0700657 ecm->notify_req->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL);
David Brownellda741b82008-06-19 18:19:46 -0700658 if (!ecm->notify_req->buf)
659 goto fail;
660 ecm->notify_req->context = ecm;
661 ecm->notify_req->complete = ecm_notify_complete;
662
663 /* copy descriptors, and track endpoint copies */
David Brownell33376c12008-08-18 17:45:07 -0700664 f->descriptors = usb_copy_descriptors(ecm_fs_function);
David Brownellda741b82008-06-19 18:19:46 -0700665 if (!f->descriptors)
666 goto fail;
667
David Brownell33376c12008-08-18 17:45:07 -0700668 ecm->fs.in = usb_find_endpoint(ecm_fs_function,
669 f->descriptors, &fs_ecm_in_desc);
670 ecm->fs.out = usb_find_endpoint(ecm_fs_function,
671 f->descriptors, &fs_ecm_out_desc);
672 ecm->fs.notify = usb_find_endpoint(ecm_fs_function,
673 f->descriptors, &fs_ecm_notify_desc);
David Brownellda741b82008-06-19 18:19:46 -0700674
675 /* support all relevant hardware speeds... we expect that when
676 * hardware is dual speed, all bulk-capable endpoints work at
677 * both speeds
678 */
679 if (gadget_is_dualspeed(c->cdev->gadget)) {
David Brownell33376c12008-08-18 17:45:07 -0700680 hs_ecm_in_desc.bEndpointAddress =
681 fs_ecm_in_desc.bEndpointAddress;
682 hs_ecm_out_desc.bEndpointAddress =
683 fs_ecm_out_desc.bEndpointAddress;
684 hs_ecm_notify_desc.bEndpointAddress =
685 fs_ecm_notify_desc.bEndpointAddress;
David Brownellda741b82008-06-19 18:19:46 -0700686
687 /* copy descriptors, and track endpoint copies */
David Brownell33376c12008-08-18 17:45:07 -0700688 f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
David Brownellda741b82008-06-19 18:19:46 -0700689 if (!f->hs_descriptors)
690 goto fail;
691
David Brownell33376c12008-08-18 17:45:07 -0700692 ecm->hs.in = usb_find_endpoint(ecm_hs_function,
693 f->hs_descriptors, &hs_ecm_in_desc);
694 ecm->hs.out = usb_find_endpoint(ecm_hs_function,
695 f->hs_descriptors, &hs_ecm_out_desc);
696 ecm->hs.notify = usb_find_endpoint(ecm_hs_function,
697 f->hs_descriptors, &hs_ecm_notify_desc);
David Brownellda741b82008-06-19 18:19:46 -0700698 }
699
700 /* NOTE: all that is done without knowing or caring about
701 * the network link ... which is unavailable to this code
702 * until we're activated via set_alt().
703 */
704
705 ecm->port.open = ecm_open;
706 ecm->port.close = ecm_close;
707
708 DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
709 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
710 ecm->port.in_ep->name, ecm->port.out_ep->name,
711 ecm->notify->name);
712 return 0;
713
714fail:
715 if (f->descriptors)
716 usb_free_descriptors(f->descriptors);
717
718 if (ecm->notify_req) {
719 kfree(ecm->notify_req->buf);
720 usb_ep_free_request(ecm->notify, ecm->notify_req);
721 }
722
723 /* we might as well release our claims on endpoints */
724 if (ecm->notify)
725 ecm->notify->driver_data = NULL;
726 if (ecm->port.out)
727 ecm->port.out_ep->driver_data = NULL;
728 if (ecm->port.in)
729 ecm->port.in_ep->driver_data = NULL;
730
731 ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
732
733 return status;
734}
735
736static void
737ecm_unbind(struct usb_configuration *c, struct usb_function *f)
738{
739 struct f_ecm *ecm = func_to_ecm(f);
740
741 DBG(c->cdev, "ecm unbind\n");
742
743 if (gadget_is_dualspeed(c->cdev->gadget))
744 usb_free_descriptors(f->hs_descriptors);
745 usb_free_descriptors(f->descriptors);
746
747 kfree(ecm->notify_req->buf);
748 usb_ep_free_request(ecm->notify, ecm->notify_req);
749
750 ecm_string_defs[1].s = NULL;
751 kfree(ecm);
752}
753
754/**
755 * ecm_bind_config - add CDC Ethernet network link to a configuration
756 * @c: the configuration to support the network link
757 * @ethaddr: a buffer in which the ethernet address of the host side
758 * side of the link was recorded
759 * Context: single threaded during gadget setup
760 *
761 * Returns zero on success, else negative errno.
762 *
763 * Caller must have called @gether_setup(). Caller is also responsible
764 * for calling @gether_cleanup() before module unload.
765 */
766int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
767{
768 struct f_ecm *ecm;
769 int status;
770
771 if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
772 return -EINVAL;
773
774 /* maybe allocate device-global string IDs */
775 if (ecm_string_defs[0].id == 0) {
776
777 /* control interface label */
778 status = usb_string_id(c->cdev);
779 if (status < 0)
780 return status;
781 ecm_string_defs[0].id = status;
782 ecm_control_intf.iInterface = status;
783
784 /* data interface label */
785 status = usb_string_id(c->cdev);
786 if (status < 0)
787 return status;
788 ecm_string_defs[2].id = status;
789 ecm_data_intf.iInterface = status;
790
791 /* MAC address */
792 status = usb_string_id(c->cdev);
793 if (status < 0)
794 return status;
795 ecm_string_defs[1].id = status;
David Brownell33376c12008-08-18 17:45:07 -0700796 ecm_desc.iMACAddress = status;
David Brownellda741b82008-06-19 18:19:46 -0700797 }
798
799 /* allocate and initialize one new instance */
800 ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
801 if (!ecm)
802 return -ENOMEM;
803
804 /* export host's Ethernet address in CDC format */
805 snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
806 "%02X%02X%02X%02X%02X%02X",
807 ethaddr[0], ethaddr[1], ethaddr[2],
808 ethaddr[3], ethaddr[4], ethaddr[5]);
809 ecm_string_defs[1].s = ecm->ethaddr;
810
811 ecm->port.cdc_filter = DEFAULT_FILTER;
812
813 ecm->port.func.name = "cdc_ethernet";
814 ecm->port.func.strings = ecm_strings;
815 /* descriptors are per-instance copies */
816 ecm->port.func.bind = ecm_bind;
817 ecm->port.func.unbind = ecm_unbind;
818 ecm->port.func.set_alt = ecm_set_alt;
819 ecm->port.func.get_alt = ecm_get_alt;
820 ecm->port.func.setup = ecm_setup;
821 ecm->port.func.disable = ecm_disable;
822
823 status = usb_add_function(c, &ecm->port.func);
824 if (status) {
825 ecm_string_defs[1].s = NULL;
826 kfree(ecm);
827 }
828 return status;
829}