xref: /OK3568_Linux_fs/kernel/drivers/usb/gadget/function/f_ecm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * f_ecm.c -- USB CDC Ethernet (ECM) link function driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2003-2005,2008 David Brownell
6*4882a593Smuzhiyun  * Copyright (C) 2008 Nokia Corporation
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun /* #define VERBOSE_DEBUG */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/device.h>
15*4882a593Smuzhiyun #include <linux/etherdevice.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include "u_ether.h"
18*4882a593Smuzhiyun #include "u_ether_configfs.h"
19*4882a593Smuzhiyun #include "u_ecm.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun /*
23*4882a593Smuzhiyun  * This function is a "CDC Ethernet Networking Control Model" (CDC ECM)
24*4882a593Smuzhiyun  * Ethernet link.  The data transfer model is simple (packets sent and
25*4882a593Smuzhiyun  * received over bulk endpoints using normal short packet termination),
26*4882a593Smuzhiyun  * and the control model exposes various data and optional notifications.
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  * ECM is well standardized and (except for Microsoft) supported by most
29*4882a593Smuzhiyun  * operating systems with USB host support.  It's the preferred interop
30*4882a593Smuzhiyun  * solution for Ethernet over USB, at least for firmware based solutions.
31*4882a593Smuzhiyun  * (Hardware solutions tend to be more minimalist.)  A newer and simpler
32*4882a593Smuzhiyun  * "Ethernet Emulation Model" (CDC EEM) hasn't yet caught on.
33*4882a593Smuzhiyun  *
34*4882a593Smuzhiyun  * Note that ECM requires the use of "alternate settings" for its data
35*4882a593Smuzhiyun  * interface.  This means that the set_alt() method has real work to do,
36*4882a593Smuzhiyun  * and also means that a get_alt() method is required.
37*4882a593Smuzhiyun  */
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun enum ecm_notify_state {
41*4882a593Smuzhiyun 	ECM_NOTIFY_NONE,		/* don't notify */
42*4882a593Smuzhiyun 	ECM_NOTIFY_CONNECT,		/* issue CONNECT next */
43*4882a593Smuzhiyun 	ECM_NOTIFY_SPEED,		/* issue SPEED_CHANGE next */
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun struct f_ecm {
47*4882a593Smuzhiyun 	struct gether			port;
48*4882a593Smuzhiyun 	u8				ctrl_id, data_id;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	char				ethaddr[14];
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	struct usb_ep			*notify;
53*4882a593Smuzhiyun 	struct usb_request		*notify_req;
54*4882a593Smuzhiyun 	u8				notify_state;
55*4882a593Smuzhiyun 	atomic_t			notify_count;
56*4882a593Smuzhiyun 	bool				is_open;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	/* FIXME is_open needs some irq-ish locking
59*4882a593Smuzhiyun 	 * ... possibly the same as port.ioport
60*4882a593Smuzhiyun 	 */
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun 
func_to_ecm(struct usb_function * f)63*4882a593Smuzhiyun static inline struct f_ecm *func_to_ecm(struct usb_function *f)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	return container_of(f, struct f_ecm, port.func);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun /* peak (theoretical) bulk transfer rate in bits-per-second */
ecm_bitrate(struct usb_gadget * g)69*4882a593Smuzhiyun static inline unsigned ecm_bitrate(struct usb_gadget *g)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
72*4882a593Smuzhiyun 		return 13 * 1024 * 8 * 1000 * 8;
73*4882a593Smuzhiyun 	else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
74*4882a593Smuzhiyun 		return 13 * 512 * 8 * 1000 * 8;
75*4882a593Smuzhiyun 	else
76*4882a593Smuzhiyun 		return 19 * 64 * 1 * 1000 * 8;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun /*
82*4882a593Smuzhiyun  * Include the status endpoint if we can, even though it's optional.
83*4882a593Smuzhiyun  *
84*4882a593Smuzhiyun  * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
85*4882a593Smuzhiyun  * packet, to simplify cancellation; and a big transfer interval, to
86*4882a593Smuzhiyun  * waste less bandwidth.
87*4882a593Smuzhiyun  *
88*4882a593Smuzhiyun  * Some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
89*4882a593Smuzhiyun  * if they ignore the connect/disconnect notifications that real aether
90*4882a593Smuzhiyun  * can provide.  More advanced cdc configurations might want to support
91*4882a593Smuzhiyun  * encapsulated commands (vendor-specific, using control-OUT).
92*4882a593Smuzhiyun  */
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun #define ECM_STATUS_INTERVAL_MS		32
95*4882a593Smuzhiyun #define ECM_STATUS_BYTECOUNT		16	/* 8 byte header + data */
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun /* interface descriptor: */
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun static struct usb_interface_assoc_descriptor
101*4882a593Smuzhiyun ecm_iad_descriptor = {
102*4882a593Smuzhiyun 	.bLength =		sizeof ecm_iad_descriptor,
103*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_INTERFACE_ASSOCIATION,
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	/* .bFirstInterface =	DYNAMIC, */
106*4882a593Smuzhiyun 	.bInterfaceCount =	2,	/* control + data */
107*4882a593Smuzhiyun 	.bFunctionClass =	USB_CLASS_COMM,
108*4882a593Smuzhiyun 	.bFunctionSubClass =	USB_CDC_SUBCLASS_ETHERNET,
109*4882a593Smuzhiyun 	.bFunctionProtocol =	USB_CDC_PROTO_NONE,
110*4882a593Smuzhiyun 	/* .iFunction =		DYNAMIC */
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun static struct usb_interface_descriptor ecm_control_intf = {
115*4882a593Smuzhiyun 	.bLength =		sizeof ecm_control_intf,
116*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_INTERFACE,
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	/* .bInterfaceNumber = DYNAMIC */
119*4882a593Smuzhiyun 	/* status endpoint is optional; this could be patched later */
120*4882a593Smuzhiyun 	.bNumEndpoints =	1,
121*4882a593Smuzhiyun 	.bInterfaceClass =	USB_CLASS_COMM,
122*4882a593Smuzhiyun 	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ETHERNET,
123*4882a593Smuzhiyun 	.bInterfaceProtocol =	USB_CDC_PROTO_NONE,
124*4882a593Smuzhiyun 	/* .iInterface = DYNAMIC */
125*4882a593Smuzhiyun };
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun static struct usb_cdc_header_desc ecm_header_desc = {
128*4882a593Smuzhiyun 	.bLength =		sizeof ecm_header_desc,
129*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_CS_INTERFACE,
130*4882a593Smuzhiyun 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	.bcdCDC =		cpu_to_le16(0x0110),
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun static struct usb_cdc_union_desc ecm_union_desc = {
136*4882a593Smuzhiyun 	.bLength =		sizeof(ecm_union_desc),
137*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_CS_INTERFACE,
138*4882a593Smuzhiyun 	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
139*4882a593Smuzhiyun 	/* .bMasterInterface0 =	DYNAMIC */
140*4882a593Smuzhiyun 	/* .bSlaveInterface0 =	DYNAMIC */
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun static struct usb_cdc_ether_desc ecm_desc = {
144*4882a593Smuzhiyun 	.bLength =		sizeof ecm_desc,
145*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_CS_INTERFACE,
146*4882a593Smuzhiyun 	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	/* this descriptor actually adds value, surprise! */
149*4882a593Smuzhiyun 	/* .iMACAddress = DYNAMIC */
150*4882a593Smuzhiyun 	.bmEthernetStatistics =	cpu_to_le32(0), /* no statistics */
151*4882a593Smuzhiyun 	.wMaxSegmentSize =	cpu_to_le16(ETH_FRAME_LEN),
152*4882a593Smuzhiyun 	.wNumberMCFilters =	cpu_to_le16(0),
153*4882a593Smuzhiyun 	.bNumberPowerFilters =	0,
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun /* the default data interface has no endpoints ... */
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun static struct usb_interface_descriptor ecm_data_nop_intf = {
159*4882a593Smuzhiyun 	.bLength =		sizeof ecm_data_nop_intf,
160*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_INTERFACE,
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	.bInterfaceNumber =	1,
163*4882a593Smuzhiyun 	.bAlternateSetting =	0,
164*4882a593Smuzhiyun 	.bNumEndpoints =	0,
165*4882a593Smuzhiyun 	.bInterfaceClass =	USB_CLASS_CDC_DATA,
166*4882a593Smuzhiyun 	.bInterfaceSubClass =	0,
167*4882a593Smuzhiyun 	.bInterfaceProtocol =	0,
168*4882a593Smuzhiyun 	/* .iInterface = DYNAMIC */
169*4882a593Smuzhiyun };
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun /* ... but the "real" data interface has two bulk endpoints */
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun static struct usb_interface_descriptor ecm_data_intf = {
174*4882a593Smuzhiyun 	.bLength =		sizeof ecm_data_intf,
175*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_INTERFACE,
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	.bInterfaceNumber =	1,
178*4882a593Smuzhiyun 	.bAlternateSetting =	1,
179*4882a593Smuzhiyun 	.bNumEndpoints =	2,
180*4882a593Smuzhiyun 	.bInterfaceClass =	USB_CLASS_CDC_DATA,
181*4882a593Smuzhiyun 	.bInterfaceSubClass =	0,
182*4882a593Smuzhiyun 	.bInterfaceProtocol =	0,
183*4882a593Smuzhiyun 	/* .iInterface = DYNAMIC */
184*4882a593Smuzhiyun };
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun /* full speed support: */
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun static struct usb_endpoint_descriptor fs_ecm_notify_desc = {
189*4882a593Smuzhiyun 	.bLength =		USB_DT_ENDPOINT_SIZE,
190*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_ENDPOINT,
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	.bEndpointAddress =	USB_DIR_IN,
193*4882a593Smuzhiyun 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
194*4882a593Smuzhiyun 	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
195*4882a593Smuzhiyun 	.bInterval =		ECM_STATUS_INTERVAL_MS,
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun static struct usb_endpoint_descriptor fs_ecm_in_desc = {
199*4882a593Smuzhiyun 	.bLength =		USB_DT_ENDPOINT_SIZE,
200*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_ENDPOINT,
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	.bEndpointAddress =	USB_DIR_IN,
203*4882a593Smuzhiyun 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
204*4882a593Smuzhiyun };
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun static struct usb_endpoint_descriptor fs_ecm_out_desc = {
207*4882a593Smuzhiyun 	.bLength =		USB_DT_ENDPOINT_SIZE,
208*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_ENDPOINT,
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	.bEndpointAddress =	USB_DIR_OUT,
211*4882a593Smuzhiyun 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
212*4882a593Smuzhiyun };
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun static struct usb_descriptor_header *ecm_fs_function[] = {
215*4882a593Smuzhiyun 	/* CDC ECM control descriptors */
216*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_iad_descriptor,
217*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_control_intf,
218*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_header_desc,
219*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_union_desc,
220*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_desc,
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	/* NOTE: status endpoint might need to be removed */
223*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &fs_ecm_notify_desc,
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	/* data interface, altsettings 0 and 1 */
226*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_data_nop_intf,
227*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_data_intf,
228*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &fs_ecm_in_desc,
229*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &fs_ecm_out_desc,
230*4882a593Smuzhiyun 	NULL,
231*4882a593Smuzhiyun };
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun /* high speed support: */
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
236*4882a593Smuzhiyun 	.bLength =		USB_DT_ENDPOINT_SIZE,
237*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_ENDPOINT,
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	.bEndpointAddress =	USB_DIR_IN,
240*4882a593Smuzhiyun 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
241*4882a593Smuzhiyun 	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
242*4882a593Smuzhiyun 	.bInterval =		USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
243*4882a593Smuzhiyun };
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun static struct usb_endpoint_descriptor hs_ecm_in_desc = {
246*4882a593Smuzhiyun 	.bLength =		USB_DT_ENDPOINT_SIZE,
247*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_ENDPOINT,
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	.bEndpointAddress =	USB_DIR_IN,
250*4882a593Smuzhiyun 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
251*4882a593Smuzhiyun 	.wMaxPacketSize =	cpu_to_le16(512),
252*4882a593Smuzhiyun };
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun static struct usb_endpoint_descriptor hs_ecm_out_desc = {
255*4882a593Smuzhiyun 	.bLength =		USB_DT_ENDPOINT_SIZE,
256*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_ENDPOINT,
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	.bEndpointAddress =	USB_DIR_OUT,
259*4882a593Smuzhiyun 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
260*4882a593Smuzhiyun 	.wMaxPacketSize =	cpu_to_le16(512),
261*4882a593Smuzhiyun };
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun static struct usb_descriptor_header *ecm_hs_function[] = {
264*4882a593Smuzhiyun 	/* CDC ECM control descriptors */
265*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_iad_descriptor,
266*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_control_intf,
267*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_header_desc,
268*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_union_desc,
269*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_desc,
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	/* NOTE: status endpoint might need to be removed */
272*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &hs_ecm_notify_desc,
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	/* data interface, altsettings 0 and 1 */
275*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_data_nop_intf,
276*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_data_intf,
277*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &hs_ecm_in_desc,
278*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &hs_ecm_out_desc,
279*4882a593Smuzhiyun 	NULL,
280*4882a593Smuzhiyun };
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun /* super speed support: */
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
285*4882a593Smuzhiyun 	.bLength =		USB_DT_ENDPOINT_SIZE,
286*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_ENDPOINT,
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	.bEndpointAddress =	USB_DIR_IN,
289*4882a593Smuzhiyun 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
290*4882a593Smuzhiyun 	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
291*4882a593Smuzhiyun 	.bInterval =		USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
292*4882a593Smuzhiyun };
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
295*4882a593Smuzhiyun 	.bLength =		sizeof ss_ecm_intr_comp_desc,
296*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	/* the following 3 values can be tweaked if necessary */
299*4882a593Smuzhiyun 	/* .bMaxBurst =		0, */
300*4882a593Smuzhiyun 	/* .bmAttributes =	0, */
301*4882a593Smuzhiyun 	.wBytesPerInterval =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
302*4882a593Smuzhiyun };
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun static struct usb_endpoint_descriptor ss_ecm_in_desc = {
305*4882a593Smuzhiyun 	.bLength =		USB_DT_ENDPOINT_SIZE,
306*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_ENDPOINT,
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	.bEndpointAddress =	USB_DIR_IN,
309*4882a593Smuzhiyun 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
310*4882a593Smuzhiyun 	.wMaxPacketSize =	cpu_to_le16(1024),
311*4882a593Smuzhiyun };
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun static struct usb_endpoint_descriptor ss_ecm_out_desc = {
314*4882a593Smuzhiyun 	.bLength =		USB_DT_ENDPOINT_SIZE,
315*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_ENDPOINT,
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	.bEndpointAddress =	USB_DIR_OUT,
318*4882a593Smuzhiyun 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
319*4882a593Smuzhiyun 	.wMaxPacketSize =	cpu_to_le16(1024),
320*4882a593Smuzhiyun };
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
323*4882a593Smuzhiyun 	.bLength =		sizeof ss_ecm_bulk_comp_desc,
324*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	/* the following 2 values can be tweaked if necessary */
327*4882a593Smuzhiyun 	/* .bMaxBurst =		0, */
328*4882a593Smuzhiyun 	/* .bmAttributes =	0, */
329*4882a593Smuzhiyun };
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun static struct usb_descriptor_header *ecm_ss_function[] = {
332*4882a593Smuzhiyun 	/* CDC ECM control descriptors */
333*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_iad_descriptor,
334*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_control_intf,
335*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_header_desc,
336*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_union_desc,
337*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_desc,
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	/* NOTE: status endpoint might need to be removed */
340*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ss_ecm_notify_desc,
341*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ss_ecm_intr_comp_desc,
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	/* data interface, altsettings 0 and 1 */
344*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_data_nop_intf,
345*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ecm_data_intf,
346*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ss_ecm_in_desc,
347*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
348*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ss_ecm_out_desc,
349*4882a593Smuzhiyun 	(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
350*4882a593Smuzhiyun 	NULL,
351*4882a593Smuzhiyun };
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun /* string descriptors: */
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun static struct usb_string ecm_string_defs[] = {
356*4882a593Smuzhiyun 	[0].s = "CDC Ethernet Control Model (ECM)",
357*4882a593Smuzhiyun 	[1].s = "",
358*4882a593Smuzhiyun 	[2].s = "CDC Ethernet Data",
359*4882a593Smuzhiyun 	[3].s = "CDC ECM",
360*4882a593Smuzhiyun 	{  } /* end of list */
361*4882a593Smuzhiyun };
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun static struct usb_gadget_strings ecm_string_table = {
364*4882a593Smuzhiyun 	.language =		0x0409,	/* en-us */
365*4882a593Smuzhiyun 	.strings =		ecm_string_defs,
366*4882a593Smuzhiyun };
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun static struct usb_gadget_strings *ecm_strings[] = {
369*4882a593Smuzhiyun 	&ecm_string_table,
370*4882a593Smuzhiyun 	NULL,
371*4882a593Smuzhiyun };
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
374*4882a593Smuzhiyun 
ecm_do_notify(struct f_ecm * ecm)375*4882a593Smuzhiyun static void ecm_do_notify(struct f_ecm *ecm)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun 	struct usb_request		*req = ecm->notify_req;
378*4882a593Smuzhiyun 	struct usb_cdc_notification	*event;
379*4882a593Smuzhiyun 	struct usb_composite_dev	*cdev = ecm->port.func.config->cdev;
380*4882a593Smuzhiyun 	__le32				*data;
381*4882a593Smuzhiyun 	int				status;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	/* notification already in flight? */
384*4882a593Smuzhiyun 	if (atomic_read(&ecm->notify_count))
385*4882a593Smuzhiyun 		return;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	event = req->buf;
388*4882a593Smuzhiyun 	switch (ecm->notify_state) {
389*4882a593Smuzhiyun 	case ECM_NOTIFY_NONE:
390*4882a593Smuzhiyun 		return;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	case ECM_NOTIFY_CONNECT:
393*4882a593Smuzhiyun 		event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
394*4882a593Smuzhiyun 		if (ecm->is_open)
395*4882a593Smuzhiyun 			event->wValue = cpu_to_le16(1);
396*4882a593Smuzhiyun 		else
397*4882a593Smuzhiyun 			event->wValue = cpu_to_le16(0);
398*4882a593Smuzhiyun 		event->wLength = 0;
399*4882a593Smuzhiyun 		req->length = sizeof *event;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 		DBG(cdev, "notify connect %s\n",
402*4882a593Smuzhiyun 				ecm->is_open ? "true" : "false");
403*4882a593Smuzhiyun 		ecm->notify_state = ECM_NOTIFY_SPEED;
404*4882a593Smuzhiyun 		break;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	case ECM_NOTIFY_SPEED:
407*4882a593Smuzhiyun 		event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
408*4882a593Smuzhiyun 		event->wValue = cpu_to_le16(0);
409*4882a593Smuzhiyun 		event->wLength = cpu_to_le16(8);
410*4882a593Smuzhiyun 		req->length = ECM_STATUS_BYTECOUNT;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 		/* SPEED_CHANGE data is up/down speeds in bits/sec */
413*4882a593Smuzhiyun 		data = req->buf + sizeof *event;
414*4882a593Smuzhiyun 		data[0] = cpu_to_le32(ecm_bitrate(cdev->gadget));
415*4882a593Smuzhiyun 		data[1] = data[0];
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 		DBG(cdev, "notify speed %d\n", ecm_bitrate(cdev->gadget));
418*4882a593Smuzhiyun 		ecm->notify_state = ECM_NOTIFY_NONE;
419*4882a593Smuzhiyun 		break;
420*4882a593Smuzhiyun 	}
421*4882a593Smuzhiyun 	event->bmRequestType = 0xA1;
422*4882a593Smuzhiyun 	event->wIndex = cpu_to_le16(ecm->ctrl_id);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	atomic_inc(&ecm->notify_count);
425*4882a593Smuzhiyun 	status = usb_ep_queue(ecm->notify, req, GFP_ATOMIC);
426*4882a593Smuzhiyun 	if (status < 0) {
427*4882a593Smuzhiyun 		atomic_dec(&ecm->notify_count);
428*4882a593Smuzhiyun 		DBG(cdev, "notify --> %d\n", status);
429*4882a593Smuzhiyun 	}
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
ecm_notify(struct f_ecm * ecm)432*4882a593Smuzhiyun static void ecm_notify(struct f_ecm *ecm)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun 	/* NOTE on most versions of Linux, host side cdc-ethernet
435*4882a593Smuzhiyun 	 * won't listen for notifications until its netdevice opens.
436*4882a593Smuzhiyun 	 * The first notification then sits in the FIFO for a long
437*4882a593Smuzhiyun 	 * time, and the second one is queued.
438*4882a593Smuzhiyun 	 */
439*4882a593Smuzhiyun 	ecm->notify_state = ECM_NOTIFY_CONNECT;
440*4882a593Smuzhiyun 	ecm_do_notify(ecm);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun 
ecm_notify_complete(struct usb_ep * ep,struct usb_request * req)443*4882a593Smuzhiyun static void ecm_notify_complete(struct usb_ep *ep, struct usb_request *req)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun 	struct f_ecm			*ecm = req->context;
446*4882a593Smuzhiyun 	struct usb_composite_dev	*cdev = ecm->port.func.config->cdev;
447*4882a593Smuzhiyun 	struct usb_cdc_notification	*event = req->buf;
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	switch (req->status) {
450*4882a593Smuzhiyun 	case 0:
451*4882a593Smuzhiyun 		/* no fault */
452*4882a593Smuzhiyun 		atomic_dec(&ecm->notify_count);
453*4882a593Smuzhiyun 		break;
454*4882a593Smuzhiyun 	case -ECONNRESET:
455*4882a593Smuzhiyun 	case -ESHUTDOWN:
456*4882a593Smuzhiyun 		atomic_set(&ecm->notify_count, 0);
457*4882a593Smuzhiyun 		ecm->notify_state = ECM_NOTIFY_NONE;
458*4882a593Smuzhiyun 		break;
459*4882a593Smuzhiyun 	default:
460*4882a593Smuzhiyun 		DBG(cdev, "event %02x --> %d\n",
461*4882a593Smuzhiyun 			event->bNotificationType, req->status);
462*4882a593Smuzhiyun 		atomic_dec(&ecm->notify_count);
463*4882a593Smuzhiyun 		break;
464*4882a593Smuzhiyun 	}
465*4882a593Smuzhiyun 	ecm_do_notify(ecm);
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun 
ecm_setup(struct usb_function * f,const struct usb_ctrlrequest * ctrl)468*4882a593Smuzhiyun static int ecm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	struct f_ecm		*ecm = func_to_ecm(f);
471*4882a593Smuzhiyun 	struct usb_composite_dev *cdev = f->config->cdev;
472*4882a593Smuzhiyun 	struct usb_request	*req = cdev->req;
473*4882a593Smuzhiyun 	int			value = -EOPNOTSUPP;
474*4882a593Smuzhiyun 	u16			w_index = le16_to_cpu(ctrl->wIndex);
475*4882a593Smuzhiyun 	u16			w_value = le16_to_cpu(ctrl->wValue);
476*4882a593Smuzhiyun 	u16			w_length = le16_to_cpu(ctrl->wLength);
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	/* composite driver infrastructure handles everything except
479*4882a593Smuzhiyun 	 * CDC class messages; interface activation uses set_alt().
480*4882a593Smuzhiyun 	 */
481*4882a593Smuzhiyun 	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
482*4882a593Smuzhiyun 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
483*4882a593Smuzhiyun 			| USB_CDC_SET_ETHERNET_PACKET_FILTER:
484*4882a593Smuzhiyun 		/* see 6.2.30: no data, wIndex = interface,
485*4882a593Smuzhiyun 		 * wValue = packet filter bitmap
486*4882a593Smuzhiyun 		 */
487*4882a593Smuzhiyun 		if (w_length != 0 || w_index != ecm->ctrl_id)
488*4882a593Smuzhiyun 			goto invalid;
489*4882a593Smuzhiyun 		DBG(cdev, "packet filter %02x\n", w_value);
490*4882a593Smuzhiyun 		/* REVISIT locking of cdc_filter.  This assumes the UDC
491*4882a593Smuzhiyun 		 * driver won't have a concurrent packet TX irq running on
492*4882a593Smuzhiyun 		 * another CPU; or that if it does, this write is atomic...
493*4882a593Smuzhiyun 		 */
494*4882a593Smuzhiyun 		ecm->port.cdc_filter = w_value;
495*4882a593Smuzhiyun 		value = 0;
496*4882a593Smuzhiyun 		break;
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	/* and optionally:
499*4882a593Smuzhiyun 	 * case USB_CDC_SEND_ENCAPSULATED_COMMAND:
500*4882a593Smuzhiyun 	 * case USB_CDC_GET_ENCAPSULATED_RESPONSE:
501*4882a593Smuzhiyun 	 * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
502*4882a593Smuzhiyun 	 * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
503*4882a593Smuzhiyun 	 * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
504*4882a593Smuzhiyun 	 * case USB_CDC_GET_ETHERNET_STATISTIC:
505*4882a593Smuzhiyun 	 */
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	default:
508*4882a593Smuzhiyun invalid:
509*4882a593Smuzhiyun 		DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
510*4882a593Smuzhiyun 			ctrl->bRequestType, ctrl->bRequest,
511*4882a593Smuzhiyun 			w_value, w_index, w_length);
512*4882a593Smuzhiyun 	}
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	/* respond with data transfer or status phase? */
515*4882a593Smuzhiyun 	if (value >= 0) {
516*4882a593Smuzhiyun 		DBG(cdev, "ecm req%02x.%02x v%04x i%04x l%d\n",
517*4882a593Smuzhiyun 			ctrl->bRequestType, ctrl->bRequest,
518*4882a593Smuzhiyun 			w_value, w_index, w_length);
519*4882a593Smuzhiyun 		req->zero = 0;
520*4882a593Smuzhiyun 		req->length = value;
521*4882a593Smuzhiyun 		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
522*4882a593Smuzhiyun 		if (value < 0)
523*4882a593Smuzhiyun 			ERROR(cdev, "ecm req %02x.%02x response err %d\n",
524*4882a593Smuzhiyun 					ctrl->bRequestType, ctrl->bRequest,
525*4882a593Smuzhiyun 					value);
526*4882a593Smuzhiyun 	}
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	/* device either stalls (value < 0) or reports success */
529*4882a593Smuzhiyun 	return value;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 
ecm_set_alt(struct usb_function * f,unsigned intf,unsigned alt)533*4882a593Smuzhiyun static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun 	struct f_ecm		*ecm = func_to_ecm(f);
536*4882a593Smuzhiyun 	struct usb_composite_dev *cdev = f->config->cdev;
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	/* Control interface has only altsetting 0 */
539*4882a593Smuzhiyun 	if (intf == ecm->ctrl_id) {
540*4882a593Smuzhiyun 		if (alt != 0)
541*4882a593Smuzhiyun 			goto fail;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 		VDBG(cdev, "reset ecm control %d\n", intf);
544*4882a593Smuzhiyun 		usb_ep_disable(ecm->notify);
545*4882a593Smuzhiyun 		if (!(ecm->notify->desc)) {
546*4882a593Smuzhiyun 			VDBG(cdev, "init ecm ctrl %d\n", intf);
547*4882a593Smuzhiyun 			if (config_ep_by_speed(cdev->gadget, f, ecm->notify))
548*4882a593Smuzhiyun 				goto fail;
549*4882a593Smuzhiyun 		}
550*4882a593Smuzhiyun 		usb_ep_enable(ecm->notify);
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	/* Data interface has two altsettings, 0 and 1 */
553*4882a593Smuzhiyun 	} else if (intf == ecm->data_id) {
554*4882a593Smuzhiyun 		if (alt > 1)
555*4882a593Smuzhiyun 			goto fail;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 		if (ecm->port.in_ep->enabled) {
558*4882a593Smuzhiyun 			DBG(cdev, "reset ecm\n");
559*4882a593Smuzhiyun 			gether_disconnect(&ecm->port);
560*4882a593Smuzhiyun 		}
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 		if (!ecm->port.in_ep->desc ||
563*4882a593Smuzhiyun 		    !ecm->port.out_ep->desc) {
564*4882a593Smuzhiyun 			DBG(cdev, "init ecm\n");
565*4882a593Smuzhiyun 			if (config_ep_by_speed(cdev->gadget, f,
566*4882a593Smuzhiyun 					       ecm->port.in_ep) ||
567*4882a593Smuzhiyun 			    config_ep_by_speed(cdev->gadget, f,
568*4882a593Smuzhiyun 					       ecm->port.out_ep)) {
569*4882a593Smuzhiyun 				ecm->port.in_ep->desc = NULL;
570*4882a593Smuzhiyun 				ecm->port.out_ep->desc = NULL;
571*4882a593Smuzhiyun 				goto fail;
572*4882a593Smuzhiyun 			}
573*4882a593Smuzhiyun 		}
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 		/* CDC Ethernet only sends data in non-default altsettings.
576*4882a593Smuzhiyun 		 * Changing altsettings resets filters, statistics, etc.
577*4882a593Smuzhiyun 		 */
578*4882a593Smuzhiyun 		if (alt == 1) {
579*4882a593Smuzhiyun 			struct net_device	*net;
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 			/* Enable zlps by default for ECM conformance;
582*4882a593Smuzhiyun 			 * override for musb_hdrc (avoids txdma ovhead).
583*4882a593Smuzhiyun 			 */
584*4882a593Smuzhiyun 			ecm->port.is_zlp_ok =
585*4882a593Smuzhiyun 				gadget_is_zlp_supported(cdev->gadget);
586*4882a593Smuzhiyun 			ecm->port.cdc_filter = DEFAULT_FILTER;
587*4882a593Smuzhiyun 			DBG(cdev, "activate ecm\n");
588*4882a593Smuzhiyun 			net = gether_connect(&ecm->port);
589*4882a593Smuzhiyun 			if (IS_ERR(net))
590*4882a593Smuzhiyun 				return PTR_ERR(net);
591*4882a593Smuzhiyun 		}
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 		/* NOTE this can be a minor disagreement with the ECM spec,
594*4882a593Smuzhiyun 		 * which says speed notifications will "always" follow
595*4882a593Smuzhiyun 		 * connection notifications.  But we allow one connect to
596*4882a593Smuzhiyun 		 * follow another (if the first is in flight), and instead
597*4882a593Smuzhiyun 		 * just guarantee that a speed notification is always sent.
598*4882a593Smuzhiyun 		 */
599*4882a593Smuzhiyun 		ecm_notify(ecm);
600*4882a593Smuzhiyun 	} else
601*4882a593Smuzhiyun 		goto fail;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	return 0;
604*4882a593Smuzhiyun fail:
605*4882a593Smuzhiyun 	return -EINVAL;
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun /* Because the data interface supports multiple altsettings,
609*4882a593Smuzhiyun  * this ECM function *MUST* implement a get_alt() method.
610*4882a593Smuzhiyun  */
ecm_get_alt(struct usb_function * f,unsigned intf)611*4882a593Smuzhiyun static int ecm_get_alt(struct usb_function *f, unsigned intf)
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun 	struct f_ecm		*ecm = func_to_ecm(f);
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	if (intf == ecm->ctrl_id)
616*4882a593Smuzhiyun 		return 0;
617*4882a593Smuzhiyun 	return ecm->port.in_ep->enabled ? 1 : 0;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun 
ecm_disable(struct usb_function * f)620*4882a593Smuzhiyun static void ecm_disable(struct usb_function *f)
621*4882a593Smuzhiyun {
622*4882a593Smuzhiyun 	struct f_ecm		*ecm = func_to_ecm(f);
623*4882a593Smuzhiyun 	struct usb_composite_dev *cdev = f->config->cdev;
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	DBG(cdev, "ecm deactivated\n");
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	if (ecm->port.in_ep->enabled) {
628*4882a593Smuzhiyun 		gether_disconnect(&ecm->port);
629*4882a593Smuzhiyun 	} else {
630*4882a593Smuzhiyun 		ecm->port.in_ep->desc = NULL;
631*4882a593Smuzhiyun 		ecm->port.out_ep->desc = NULL;
632*4882a593Smuzhiyun 	}
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	usb_ep_disable(ecm->notify);
635*4882a593Smuzhiyun 	ecm->notify->desc = NULL;
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun /*
641*4882a593Smuzhiyun  * Callbacks let us notify the host about connect/disconnect when the
642*4882a593Smuzhiyun  * net device is opened or closed.
643*4882a593Smuzhiyun  *
644*4882a593Smuzhiyun  * For testing, note that link states on this side include both opened
645*4882a593Smuzhiyun  * and closed variants of:
646*4882a593Smuzhiyun  *
647*4882a593Smuzhiyun  *   - disconnected/unconfigured
648*4882a593Smuzhiyun  *   - configured but inactive (data alt 0)
649*4882a593Smuzhiyun  *   - configured and active (data alt 1)
650*4882a593Smuzhiyun  *
651*4882a593Smuzhiyun  * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and
652*4882a593Smuzhiyun  * SET_INTERFACE (altsetting).  Remember also that "configured" doesn't
653*4882a593Smuzhiyun  * imply the host is actually polling the notification endpoint, and
654*4882a593Smuzhiyun  * likewise that "active" doesn't imply it's actually using the data
655*4882a593Smuzhiyun  * endpoints for traffic.
656*4882a593Smuzhiyun  */
657*4882a593Smuzhiyun 
ecm_open(struct gether * geth)658*4882a593Smuzhiyun static void ecm_open(struct gether *geth)
659*4882a593Smuzhiyun {
660*4882a593Smuzhiyun 	struct f_ecm		*ecm = func_to_ecm(&geth->func);
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	DBG(ecm->port.func.config->cdev, "%s\n", __func__);
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	ecm->is_open = true;
665*4882a593Smuzhiyun 	ecm_notify(ecm);
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun 
ecm_close(struct gether * geth)668*4882a593Smuzhiyun static void ecm_close(struct gether *geth)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun 	struct f_ecm		*ecm = func_to_ecm(&geth->func);
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	DBG(ecm->port.func.config->cdev, "%s\n", __func__);
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	ecm->is_open = false;
675*4882a593Smuzhiyun 	ecm_notify(ecm);
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun /* ethernet function driver setup/binding */
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun static int
ecm_bind(struct usb_configuration * c,struct usb_function * f)683*4882a593Smuzhiyun ecm_bind(struct usb_configuration *c, struct usb_function *f)
684*4882a593Smuzhiyun {
685*4882a593Smuzhiyun 	struct usb_composite_dev *cdev = c->cdev;
686*4882a593Smuzhiyun 	struct f_ecm		*ecm = func_to_ecm(f);
687*4882a593Smuzhiyun 	struct usb_string	*us;
688*4882a593Smuzhiyun 	int			status;
689*4882a593Smuzhiyun 	struct usb_ep		*ep;
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	struct f_ecm_opts	*ecm_opts;
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	if (!can_support_ecm(cdev->gadget))
694*4882a593Smuzhiyun 		return -EINVAL;
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	ecm_opts = container_of(f->fi, struct f_ecm_opts, func_inst);
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	/*
699*4882a593Smuzhiyun 	 * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
700*4882a593Smuzhiyun 	 * configurations are bound in sequence with list_for_each_entry,
701*4882a593Smuzhiyun 	 * in each configuration its functions are bound in sequence
702*4882a593Smuzhiyun 	 * with list_for_each_entry, so we assume no race condition
703*4882a593Smuzhiyun 	 * with regard to ecm_opts->bound access
704*4882a593Smuzhiyun 	 */
705*4882a593Smuzhiyun 	if (!ecm_opts->bound) {
706*4882a593Smuzhiyun 		mutex_lock(&ecm_opts->lock);
707*4882a593Smuzhiyun 		gether_set_gadget(ecm_opts->net, cdev->gadget);
708*4882a593Smuzhiyun 		status = gether_register_netdev(ecm_opts->net);
709*4882a593Smuzhiyun 		mutex_unlock(&ecm_opts->lock);
710*4882a593Smuzhiyun 		if (status)
711*4882a593Smuzhiyun 			return status;
712*4882a593Smuzhiyun 		ecm_opts->bound = true;
713*4882a593Smuzhiyun 	}
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	ecm_string_defs[1].s = ecm->ethaddr;
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	us = usb_gstrings_attach(cdev, ecm_strings,
718*4882a593Smuzhiyun 				 ARRAY_SIZE(ecm_string_defs));
719*4882a593Smuzhiyun 	if (IS_ERR(us))
720*4882a593Smuzhiyun 		return PTR_ERR(us);
721*4882a593Smuzhiyun 	ecm_control_intf.iInterface = us[0].id;
722*4882a593Smuzhiyun 	ecm_data_intf.iInterface = us[2].id;
723*4882a593Smuzhiyun 	ecm_desc.iMACAddress = us[1].id;
724*4882a593Smuzhiyun 	ecm_iad_descriptor.iFunction = us[3].id;
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	/* allocate instance-specific interface IDs */
727*4882a593Smuzhiyun 	status = usb_interface_id(c, f);
728*4882a593Smuzhiyun 	if (status < 0)
729*4882a593Smuzhiyun 		goto fail;
730*4882a593Smuzhiyun 	ecm->ctrl_id = status;
731*4882a593Smuzhiyun 	ecm_iad_descriptor.bFirstInterface = status;
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	ecm_control_intf.bInterfaceNumber = status;
734*4882a593Smuzhiyun 	ecm_union_desc.bMasterInterface0 = status;
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	status = usb_interface_id(c, f);
737*4882a593Smuzhiyun 	if (status < 0)
738*4882a593Smuzhiyun 		goto fail;
739*4882a593Smuzhiyun 	ecm->data_id = status;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	ecm_data_nop_intf.bInterfaceNumber = status;
742*4882a593Smuzhiyun 	ecm_data_intf.bInterfaceNumber = status;
743*4882a593Smuzhiyun 	ecm_union_desc.bSlaveInterface0 = status;
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	status = -ENODEV;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	/* allocate instance-specific endpoints */
748*4882a593Smuzhiyun 	ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_in_desc);
749*4882a593Smuzhiyun 	if (!ep)
750*4882a593Smuzhiyun 		goto fail;
751*4882a593Smuzhiyun 	ecm->port.in_ep = ep;
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
754*4882a593Smuzhiyun 	if (!ep)
755*4882a593Smuzhiyun 		goto fail;
756*4882a593Smuzhiyun 	ecm->port.out_ep = ep;
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 	/* NOTE:  a status/notification endpoint is *OPTIONAL* but we
759*4882a593Smuzhiyun 	 * don't treat it that way.  It's simpler, and some newer CDC
760*4882a593Smuzhiyun 	 * profiles (wireless handsets) no longer treat it as optional.
761*4882a593Smuzhiyun 	 */
762*4882a593Smuzhiyun 	ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_notify_desc);
763*4882a593Smuzhiyun 	if (!ep)
764*4882a593Smuzhiyun 		goto fail;
765*4882a593Smuzhiyun 	ecm->notify = ep;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	status = -ENOMEM;
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	/* allocate notification request and buffer */
770*4882a593Smuzhiyun 	ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
771*4882a593Smuzhiyun 	if (!ecm->notify_req)
772*4882a593Smuzhiyun 		goto fail;
773*4882a593Smuzhiyun 	ecm->notify_req->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL);
774*4882a593Smuzhiyun 	if (!ecm->notify_req->buf)
775*4882a593Smuzhiyun 		goto fail;
776*4882a593Smuzhiyun 	ecm->notify_req->context = ecm;
777*4882a593Smuzhiyun 	ecm->notify_req->complete = ecm_notify_complete;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	/* support all relevant hardware speeds... we expect that when
780*4882a593Smuzhiyun 	 * hardware is dual speed, all bulk-capable endpoints work at
781*4882a593Smuzhiyun 	 * both speeds
782*4882a593Smuzhiyun 	 */
783*4882a593Smuzhiyun 	hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
784*4882a593Smuzhiyun 	hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
785*4882a593Smuzhiyun 	hs_ecm_notify_desc.bEndpointAddress =
786*4882a593Smuzhiyun 		fs_ecm_notify_desc.bEndpointAddress;
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	ss_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
789*4882a593Smuzhiyun 	ss_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
790*4882a593Smuzhiyun 	ss_ecm_notify_desc.bEndpointAddress =
791*4882a593Smuzhiyun 		fs_ecm_notify_desc.bEndpointAddress;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
794*4882a593Smuzhiyun 			ecm_ss_function, ecm_ss_function);
795*4882a593Smuzhiyun 	if (status)
796*4882a593Smuzhiyun 		goto fail;
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	/* NOTE:  all that is done without knowing or caring about
799*4882a593Smuzhiyun 	 * the network link ... which is unavailable to this code
800*4882a593Smuzhiyun 	 * until we're activated via set_alt().
801*4882a593Smuzhiyun 	 */
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	ecm->port.open = ecm_open;
804*4882a593Smuzhiyun 	ecm->port.close = ecm_close;
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
807*4882a593Smuzhiyun 			gadget_is_superspeed(c->cdev->gadget) ? "super" :
808*4882a593Smuzhiyun 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
809*4882a593Smuzhiyun 			ecm->port.in_ep->name, ecm->port.out_ep->name,
810*4882a593Smuzhiyun 			ecm->notify->name);
811*4882a593Smuzhiyun 	return 0;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun fail:
814*4882a593Smuzhiyun 	if (ecm->notify_req) {
815*4882a593Smuzhiyun 		kfree(ecm->notify_req->buf);
816*4882a593Smuzhiyun 		usb_ep_free_request(ecm->notify, ecm->notify_req);
817*4882a593Smuzhiyun 	}
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	return status;
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun 
to_f_ecm_opts(struct config_item * item)824*4882a593Smuzhiyun static inline struct f_ecm_opts *to_f_ecm_opts(struct config_item *item)
825*4882a593Smuzhiyun {
826*4882a593Smuzhiyun 	return container_of(to_config_group(item), struct f_ecm_opts,
827*4882a593Smuzhiyun 			    func_inst.group);
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun /* f_ecm_item_ops */
831*4882a593Smuzhiyun USB_ETHERNET_CONFIGFS_ITEM(ecm);
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun /* f_ecm_opts_dev_addr */
834*4882a593Smuzhiyun USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(ecm);
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun /* f_ecm_opts_host_addr */
837*4882a593Smuzhiyun USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(ecm);
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun /* f_ecm_opts_qmult */
840*4882a593Smuzhiyun USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ecm);
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun /* f_ecm_opts_ifname */
843*4882a593Smuzhiyun USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ecm);
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun static struct configfs_attribute *ecm_attrs[] = {
846*4882a593Smuzhiyun 	&ecm_opts_attr_dev_addr,
847*4882a593Smuzhiyun 	&ecm_opts_attr_host_addr,
848*4882a593Smuzhiyun 	&ecm_opts_attr_qmult,
849*4882a593Smuzhiyun 	&ecm_opts_attr_ifname,
850*4882a593Smuzhiyun 	NULL,
851*4882a593Smuzhiyun };
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun static const struct config_item_type ecm_func_type = {
854*4882a593Smuzhiyun 	.ct_item_ops	= &ecm_item_ops,
855*4882a593Smuzhiyun 	.ct_attrs	= ecm_attrs,
856*4882a593Smuzhiyun 	.ct_owner	= THIS_MODULE,
857*4882a593Smuzhiyun };
858*4882a593Smuzhiyun 
ecm_free_inst(struct usb_function_instance * f)859*4882a593Smuzhiyun static void ecm_free_inst(struct usb_function_instance *f)
860*4882a593Smuzhiyun {
861*4882a593Smuzhiyun 	struct f_ecm_opts *opts;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	opts = container_of(f, struct f_ecm_opts, func_inst);
864*4882a593Smuzhiyun 	if (opts->bound)
865*4882a593Smuzhiyun 		gether_cleanup(netdev_priv(opts->net));
866*4882a593Smuzhiyun 	else
867*4882a593Smuzhiyun 		free_netdev(opts->net);
868*4882a593Smuzhiyun 	kfree(opts);
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun 
ecm_alloc_inst(void)871*4882a593Smuzhiyun static struct usb_function_instance *ecm_alloc_inst(void)
872*4882a593Smuzhiyun {
873*4882a593Smuzhiyun 	struct f_ecm_opts *opts;
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun 	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
876*4882a593Smuzhiyun 	if (!opts)
877*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
878*4882a593Smuzhiyun 	mutex_init(&opts->lock);
879*4882a593Smuzhiyun 	opts->func_inst.free_func_inst = ecm_free_inst;
880*4882a593Smuzhiyun 	opts->net = gether_setup_default();
881*4882a593Smuzhiyun 	if (IS_ERR(opts->net)) {
882*4882a593Smuzhiyun 		struct net_device *net = opts->net;
883*4882a593Smuzhiyun 		kfree(opts);
884*4882a593Smuzhiyun 		return ERR_CAST(net);
885*4882a593Smuzhiyun 	}
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	config_group_init_type_name(&opts->func_inst.group, "", &ecm_func_type);
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 	return &opts->func_inst;
890*4882a593Smuzhiyun }
891*4882a593Smuzhiyun 
ecm_free(struct usb_function * f)892*4882a593Smuzhiyun static void ecm_free(struct usb_function *f)
893*4882a593Smuzhiyun {
894*4882a593Smuzhiyun 	struct f_ecm *ecm;
895*4882a593Smuzhiyun 	struct f_ecm_opts *opts;
896*4882a593Smuzhiyun 
897*4882a593Smuzhiyun 	ecm = func_to_ecm(f);
898*4882a593Smuzhiyun 	opts = container_of(f->fi, struct f_ecm_opts, func_inst);
899*4882a593Smuzhiyun 	kfree(ecm);
900*4882a593Smuzhiyun 	mutex_lock(&opts->lock);
901*4882a593Smuzhiyun 	opts->refcnt--;
902*4882a593Smuzhiyun 	mutex_unlock(&opts->lock);
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun 
ecm_unbind(struct usb_configuration * c,struct usb_function * f)905*4882a593Smuzhiyun static void ecm_unbind(struct usb_configuration *c, struct usb_function *f)
906*4882a593Smuzhiyun {
907*4882a593Smuzhiyun 	struct f_ecm		*ecm = func_to_ecm(f);
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	DBG(c->cdev, "ecm unbind\n");
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun 	usb_free_all_descriptors(f);
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 	if (atomic_read(&ecm->notify_count)) {
914*4882a593Smuzhiyun 		usb_ep_dequeue(ecm->notify, ecm->notify_req);
915*4882a593Smuzhiyun 		atomic_set(&ecm->notify_count, 0);
916*4882a593Smuzhiyun 	}
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	kfree(ecm->notify_req->buf);
919*4882a593Smuzhiyun 	usb_ep_free_request(ecm->notify, ecm->notify_req);
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun 
ecm_alloc(struct usb_function_instance * fi)922*4882a593Smuzhiyun static struct usb_function *ecm_alloc(struct usb_function_instance *fi)
923*4882a593Smuzhiyun {
924*4882a593Smuzhiyun 	struct f_ecm	*ecm;
925*4882a593Smuzhiyun 	struct f_ecm_opts *opts;
926*4882a593Smuzhiyun 	int status;
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun 	/* allocate and initialize one new instance */
929*4882a593Smuzhiyun 	ecm = kzalloc(sizeof(*ecm), GFP_KERNEL);
930*4882a593Smuzhiyun 	if (!ecm)
931*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	opts = container_of(fi, struct f_ecm_opts, func_inst);
934*4882a593Smuzhiyun 	mutex_lock(&opts->lock);
935*4882a593Smuzhiyun 	opts->refcnt++;
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	/* export host's Ethernet address in CDC format */
938*4882a593Smuzhiyun 	status = gether_get_host_addr_cdc(opts->net, ecm->ethaddr,
939*4882a593Smuzhiyun 					  sizeof(ecm->ethaddr));
940*4882a593Smuzhiyun 	if (status < 12) {
941*4882a593Smuzhiyun 		kfree(ecm);
942*4882a593Smuzhiyun 		mutex_unlock(&opts->lock);
943*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
944*4882a593Smuzhiyun 	}
945*4882a593Smuzhiyun 
946*4882a593Smuzhiyun 	ecm->port.ioport = netdev_priv(opts->net);
947*4882a593Smuzhiyun 	mutex_unlock(&opts->lock);
948*4882a593Smuzhiyun 	ecm->port.cdc_filter = DEFAULT_FILTER;
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	ecm->port.func.name = "cdc_ethernet";
951*4882a593Smuzhiyun 	/* descriptors are per-instance copies */
952*4882a593Smuzhiyun 	ecm->port.func.bind = ecm_bind;
953*4882a593Smuzhiyun 	ecm->port.func.unbind = ecm_unbind;
954*4882a593Smuzhiyun 	ecm->port.func.set_alt = ecm_set_alt;
955*4882a593Smuzhiyun 	ecm->port.func.get_alt = ecm_get_alt;
956*4882a593Smuzhiyun 	ecm->port.func.setup = ecm_setup;
957*4882a593Smuzhiyun 	ecm->port.func.disable = ecm_disable;
958*4882a593Smuzhiyun 	ecm->port.func.free_func = ecm_free;
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun 	return &ecm->port.func;
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc);
964*4882a593Smuzhiyun MODULE_LICENSE("GPL");
965*4882a593Smuzhiyun MODULE_AUTHOR("David Brownell");
966