xref: /OK3568_Linux_fs/kernel/drivers/usb/gadget/legacy/multi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * multi.c -- Multifunction Composite driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2008 David Brownell
6*4882a593Smuzhiyun  * Copyright (C) 2008 Nokia Corporation
7*4882a593Smuzhiyun  * Copyright (C) 2009 Samsung Electronics
8*4882a593Smuzhiyun  * Author: Michal Nazarewicz (mina86@mina86.com)
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/netdevice.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include "u_serial.h"
17*4882a593Smuzhiyun #if defined USB_ETH_RNDIS
18*4882a593Smuzhiyun #  undef USB_ETH_RNDIS
19*4882a593Smuzhiyun #endif
20*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_RNDIS
21*4882a593Smuzhiyun #  define USB_ETH_RNDIS y
22*4882a593Smuzhiyun #endif
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define DRIVER_DESC		"Multifunction Composite Gadget"
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
28*4882a593Smuzhiyun MODULE_AUTHOR("Michal Nazarewicz");
29*4882a593Smuzhiyun MODULE_LICENSE("GPL");
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #include "f_mass_storage.h"
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include "u_ecm.h"
35*4882a593Smuzhiyun #ifdef USB_ETH_RNDIS
36*4882a593Smuzhiyun #  include "u_rndis.h"
37*4882a593Smuzhiyun #  include "rndis.h"
38*4882a593Smuzhiyun #endif
39*4882a593Smuzhiyun #include "u_ether.h"
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun USB_GADGET_COMPOSITE_OPTIONS();
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun USB_ETHERNET_MODULE_PARAMETERS();
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /***************************** Device Descriptor ****************************/
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun #define MULTI_VENDOR_NUM	0x1d6b	/* Linux Foundation */
48*4882a593Smuzhiyun #define MULTI_PRODUCT_NUM	0x0104	/* Multifunction Composite Gadget */
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun enum {
52*4882a593Smuzhiyun 	__MULTI_NO_CONFIG,
53*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_RNDIS
54*4882a593Smuzhiyun 	MULTI_RNDIS_CONFIG_NUM,
55*4882a593Smuzhiyun #endif
56*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_CDC
57*4882a593Smuzhiyun 	MULTI_CDC_CONFIG_NUM,
58*4882a593Smuzhiyun #endif
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun static struct usb_device_descriptor device_desc = {
63*4882a593Smuzhiyun 	.bLength =		sizeof device_desc,
64*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_DEVICE,
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	/* .bcdUSB = DYNAMIC */
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	.bDeviceClass =		USB_CLASS_MISC /* 0xEF */,
69*4882a593Smuzhiyun 	.bDeviceSubClass =	2,
70*4882a593Smuzhiyun 	.bDeviceProtocol =	1,
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	/* Vendor and product id can be overridden by module parameters.  */
73*4882a593Smuzhiyun 	.idVendor =		cpu_to_le16(MULTI_VENDOR_NUM),
74*4882a593Smuzhiyun 	.idProduct =		cpu_to_le16(MULTI_PRODUCT_NUM),
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun static const struct usb_descriptor_header *otg_desc[2];
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun enum {
80*4882a593Smuzhiyun 	MULTI_STRING_RNDIS_CONFIG_IDX = USB_GADGET_FIRST_AVAIL_IDX,
81*4882a593Smuzhiyun 	MULTI_STRING_CDC_CONFIG_IDX,
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun static struct usb_string strings_dev[] = {
85*4882a593Smuzhiyun 	[USB_GADGET_MANUFACTURER_IDX].s = "",
86*4882a593Smuzhiyun 	[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
87*4882a593Smuzhiyun 	[USB_GADGET_SERIAL_IDX].s = "",
88*4882a593Smuzhiyun 	[MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS",
89*4882a593Smuzhiyun 	[MULTI_STRING_CDC_CONFIG_IDX].s   = "Multifunction with CDC ECM",
90*4882a593Smuzhiyun 	{  } /* end of list */
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun static struct usb_gadget_strings *dev_strings[] = {
94*4882a593Smuzhiyun 	&(struct usb_gadget_strings){
95*4882a593Smuzhiyun 		.language	= 0x0409,	/* en-us */
96*4882a593Smuzhiyun 		.strings	= strings_dev,
97*4882a593Smuzhiyun 	},
98*4882a593Smuzhiyun 	NULL,
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun /****************************** Configurations ******************************/
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun static struct fsg_module_parameters fsg_mod_data = { .stall = 1 };
107*4882a593Smuzhiyun #ifdef CONFIG_USB_GADGET_DEBUG_FILES
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #else
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun /*
114*4882a593Smuzhiyun  * Number of buffers we will use.
115*4882a593Smuzhiyun  * 2 is usually enough for good buffering pipeline
116*4882a593Smuzhiyun  */
117*4882a593Smuzhiyun #define fsg_num_buffers	CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun static struct usb_function_instance *fi_acm;
124*4882a593Smuzhiyun static struct usb_function_instance *fi_msg;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun /********** RNDIS **********/
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun #ifdef USB_ETH_RNDIS
129*4882a593Smuzhiyun static struct usb_function_instance *fi_rndis;
130*4882a593Smuzhiyun static struct usb_function *f_acm_rndis;
131*4882a593Smuzhiyun static struct usb_function *f_rndis;
132*4882a593Smuzhiyun static struct usb_function *f_msg_rndis;
133*4882a593Smuzhiyun 
rndis_do_config(struct usb_configuration * c)134*4882a593Smuzhiyun static int rndis_do_config(struct usb_configuration *c)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun 	int ret;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	if (gadget_is_otg(c->cdev->gadget)) {
139*4882a593Smuzhiyun 		c->descriptors = otg_desc;
140*4882a593Smuzhiyun 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	f_rndis = usb_get_function(fi_rndis);
144*4882a593Smuzhiyun 	if (IS_ERR(f_rndis))
145*4882a593Smuzhiyun 		return PTR_ERR(f_rndis);
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	ret = usb_add_function(c, f_rndis);
148*4882a593Smuzhiyun 	if (ret < 0)
149*4882a593Smuzhiyun 		goto err_func_rndis;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	f_acm_rndis = usb_get_function(fi_acm);
152*4882a593Smuzhiyun 	if (IS_ERR(f_acm_rndis)) {
153*4882a593Smuzhiyun 		ret = PTR_ERR(f_acm_rndis);
154*4882a593Smuzhiyun 		goto err_func_acm;
155*4882a593Smuzhiyun 	}
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	ret = usb_add_function(c, f_acm_rndis);
158*4882a593Smuzhiyun 	if (ret)
159*4882a593Smuzhiyun 		goto err_conf;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	f_msg_rndis = usb_get_function(fi_msg);
162*4882a593Smuzhiyun 	if (IS_ERR(f_msg_rndis)) {
163*4882a593Smuzhiyun 		ret = PTR_ERR(f_msg_rndis);
164*4882a593Smuzhiyun 		goto err_fsg;
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	ret = usb_add_function(c, f_msg_rndis);
168*4882a593Smuzhiyun 	if (ret)
169*4882a593Smuzhiyun 		goto err_run;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	return 0;
172*4882a593Smuzhiyun err_run:
173*4882a593Smuzhiyun 	usb_put_function(f_msg_rndis);
174*4882a593Smuzhiyun err_fsg:
175*4882a593Smuzhiyun 	usb_remove_function(c, f_acm_rndis);
176*4882a593Smuzhiyun err_conf:
177*4882a593Smuzhiyun 	usb_put_function(f_acm_rndis);
178*4882a593Smuzhiyun err_func_acm:
179*4882a593Smuzhiyun 	usb_remove_function(c, f_rndis);
180*4882a593Smuzhiyun err_func_rndis:
181*4882a593Smuzhiyun 	usb_put_function(f_rndis);
182*4882a593Smuzhiyun 	return ret;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
rndis_config_register(struct usb_composite_dev * cdev)185*4882a593Smuzhiyun static __ref int rndis_config_register(struct usb_composite_dev *cdev)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun 	static struct usb_configuration config = {
188*4882a593Smuzhiyun 		.bConfigurationValue	= MULTI_RNDIS_CONFIG_NUM,
189*4882a593Smuzhiyun 		.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
190*4882a593Smuzhiyun 	};
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	config.label          = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s;
193*4882a593Smuzhiyun 	config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	return usb_add_config(cdev, &config, rndis_do_config);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun #else
199*4882a593Smuzhiyun 
rndis_config_register(struct usb_composite_dev * cdev)200*4882a593Smuzhiyun static __ref int rndis_config_register(struct usb_composite_dev *cdev)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	return 0;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun #endif
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun /********** CDC ECM **********/
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_CDC
211*4882a593Smuzhiyun static struct usb_function_instance *fi_ecm;
212*4882a593Smuzhiyun static struct usb_function *f_acm_multi;
213*4882a593Smuzhiyun static struct usb_function *f_ecm;
214*4882a593Smuzhiyun static struct usb_function *f_msg_multi;
215*4882a593Smuzhiyun 
cdc_do_config(struct usb_configuration * c)216*4882a593Smuzhiyun static int cdc_do_config(struct usb_configuration *c)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	int ret;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	if (gadget_is_otg(c->cdev->gadget)) {
221*4882a593Smuzhiyun 		c->descriptors = otg_desc;
222*4882a593Smuzhiyun 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	f_ecm = usb_get_function(fi_ecm);
226*4882a593Smuzhiyun 	if (IS_ERR(f_ecm))
227*4882a593Smuzhiyun 		return PTR_ERR(f_ecm);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	ret = usb_add_function(c, f_ecm);
230*4882a593Smuzhiyun 	if (ret < 0)
231*4882a593Smuzhiyun 		goto err_func_ecm;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	/* implicit port_num is zero */
234*4882a593Smuzhiyun 	f_acm_multi = usb_get_function(fi_acm);
235*4882a593Smuzhiyun 	if (IS_ERR(f_acm_multi)) {
236*4882a593Smuzhiyun 		ret = PTR_ERR(f_acm_multi);
237*4882a593Smuzhiyun 		goto err_func_acm;
238*4882a593Smuzhiyun 	}
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	ret = usb_add_function(c, f_acm_multi);
241*4882a593Smuzhiyun 	if (ret)
242*4882a593Smuzhiyun 		goto err_conf;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	f_msg_multi = usb_get_function(fi_msg);
245*4882a593Smuzhiyun 	if (IS_ERR(f_msg_multi)) {
246*4882a593Smuzhiyun 		ret = PTR_ERR(f_msg_multi);
247*4882a593Smuzhiyun 		goto err_fsg;
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	ret = usb_add_function(c, f_msg_multi);
251*4882a593Smuzhiyun 	if (ret)
252*4882a593Smuzhiyun 		goto err_run;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	return 0;
255*4882a593Smuzhiyun err_run:
256*4882a593Smuzhiyun 	usb_put_function(f_msg_multi);
257*4882a593Smuzhiyun err_fsg:
258*4882a593Smuzhiyun 	usb_remove_function(c, f_acm_multi);
259*4882a593Smuzhiyun err_conf:
260*4882a593Smuzhiyun 	usb_put_function(f_acm_multi);
261*4882a593Smuzhiyun err_func_acm:
262*4882a593Smuzhiyun 	usb_remove_function(c, f_ecm);
263*4882a593Smuzhiyun err_func_ecm:
264*4882a593Smuzhiyun 	usb_put_function(f_ecm);
265*4882a593Smuzhiyun 	return ret;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
cdc_config_register(struct usb_composite_dev * cdev)268*4882a593Smuzhiyun static __ref int cdc_config_register(struct usb_composite_dev *cdev)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	static struct usb_configuration config = {
271*4882a593Smuzhiyun 		.bConfigurationValue	= MULTI_CDC_CONFIG_NUM,
272*4882a593Smuzhiyun 		.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
273*4882a593Smuzhiyun 	};
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	config.label          = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s;
276*4882a593Smuzhiyun 	config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	return usb_add_config(cdev, &config, cdc_do_config);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun #else
282*4882a593Smuzhiyun 
cdc_config_register(struct usb_composite_dev * cdev)283*4882a593Smuzhiyun static __ref int cdc_config_register(struct usb_composite_dev *cdev)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun 	return 0;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun #endif
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun /****************************** Gadget Bind ******************************/
293*4882a593Smuzhiyun 
multi_bind(struct usb_composite_dev * cdev)294*4882a593Smuzhiyun static int __ref multi_bind(struct usb_composite_dev *cdev)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	struct usb_gadget *gadget = cdev->gadget;
297*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_CDC
298*4882a593Smuzhiyun 	struct f_ecm_opts *ecm_opts;
299*4882a593Smuzhiyun #endif
300*4882a593Smuzhiyun #ifdef USB_ETH_RNDIS
301*4882a593Smuzhiyun 	struct f_rndis_opts *rndis_opts;
302*4882a593Smuzhiyun #endif
303*4882a593Smuzhiyun 	struct fsg_opts *fsg_opts;
304*4882a593Smuzhiyun 	struct fsg_config config;
305*4882a593Smuzhiyun 	int status;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	if (!can_support_ecm(cdev->gadget)) {
308*4882a593Smuzhiyun 		dev_err(&gadget->dev, "controller '%s' not usable\n",
309*4882a593Smuzhiyun 			gadget->name);
310*4882a593Smuzhiyun 		return -EINVAL;
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_CDC
314*4882a593Smuzhiyun 	fi_ecm = usb_get_function_instance("ecm");
315*4882a593Smuzhiyun 	if (IS_ERR(fi_ecm))
316*4882a593Smuzhiyun 		return PTR_ERR(fi_ecm);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	gether_set_qmult(ecm_opts->net, qmult);
321*4882a593Smuzhiyun 	if (!gether_set_host_addr(ecm_opts->net, host_addr))
322*4882a593Smuzhiyun 		pr_info("using host ethernet address: %s", host_addr);
323*4882a593Smuzhiyun 	if (!gether_set_dev_addr(ecm_opts->net, dev_addr))
324*4882a593Smuzhiyun 		pr_info("using self ethernet address: %s", dev_addr);
325*4882a593Smuzhiyun #endif
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun #ifdef USB_ETH_RNDIS
328*4882a593Smuzhiyun 	fi_rndis = usb_get_function_instance("rndis");
329*4882a593Smuzhiyun 	if (IS_ERR(fi_rndis)) {
330*4882a593Smuzhiyun 		status = PTR_ERR(fi_rndis);
331*4882a593Smuzhiyun 		goto fail;
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	rndis_opts = container_of(fi_rndis, struct f_rndis_opts, func_inst);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	gether_set_qmult(rndis_opts->net, qmult);
337*4882a593Smuzhiyun 	if (!gether_set_host_addr(rndis_opts->net, host_addr))
338*4882a593Smuzhiyun 		pr_info("using host ethernet address: %s", host_addr);
339*4882a593Smuzhiyun 	if (!gether_set_dev_addr(rndis_opts->net, dev_addr))
340*4882a593Smuzhiyun 		pr_info("using self ethernet address: %s", dev_addr);
341*4882a593Smuzhiyun #endif
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun #if (defined CONFIG_USB_G_MULTI_CDC && defined USB_ETH_RNDIS)
344*4882a593Smuzhiyun 	/*
345*4882a593Smuzhiyun 	 * If both ecm and rndis are selected then:
346*4882a593Smuzhiyun 	 *	1) rndis borrows the net interface from ecm
347*4882a593Smuzhiyun 	 *	2) since the interface is shared it must not be bound
348*4882a593Smuzhiyun 	 *	twice - in ecm's _and_ rndis' binds, so do it here.
349*4882a593Smuzhiyun 	 */
350*4882a593Smuzhiyun 	gether_set_gadget(ecm_opts->net, cdev->gadget);
351*4882a593Smuzhiyun 	status = gether_register_netdev(ecm_opts->net);
352*4882a593Smuzhiyun 	if (status)
353*4882a593Smuzhiyun 		goto fail0;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	rndis_borrow_net(fi_rndis, ecm_opts->net);
356*4882a593Smuzhiyun 	ecm_opts->bound = true;
357*4882a593Smuzhiyun #endif
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	/* set up serial link layer */
360*4882a593Smuzhiyun 	fi_acm = usb_get_function_instance("acm");
361*4882a593Smuzhiyun 	if (IS_ERR(fi_acm)) {
362*4882a593Smuzhiyun 		status = PTR_ERR(fi_acm);
363*4882a593Smuzhiyun 		goto fail0;
364*4882a593Smuzhiyun 	}
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	/* set up mass storage function */
367*4882a593Smuzhiyun 	fi_msg = usb_get_function_instance("mass_storage");
368*4882a593Smuzhiyun 	if (IS_ERR(fi_msg)) {
369*4882a593Smuzhiyun 		status = PTR_ERR(fi_msg);
370*4882a593Smuzhiyun 		goto fail1;
371*4882a593Smuzhiyun 	}
372*4882a593Smuzhiyun 	fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers);
373*4882a593Smuzhiyun 	fsg_opts = fsg_opts_from_func_inst(fi_msg);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	fsg_opts->no_configfs = true;
376*4882a593Smuzhiyun 	status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers);
377*4882a593Smuzhiyun 	if (status)
378*4882a593Smuzhiyun 		goto fail2;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall);
381*4882a593Smuzhiyun 	if (status)
382*4882a593Smuzhiyun 		goto fail_set_cdev;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	fsg_common_set_sysfs(fsg_opts->common, true);
385*4882a593Smuzhiyun 	status = fsg_common_create_luns(fsg_opts->common, &config);
386*4882a593Smuzhiyun 	if (status)
387*4882a593Smuzhiyun 		goto fail_set_cdev;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	fsg_common_set_inquiry_string(fsg_opts->common, config.vendor_name,
390*4882a593Smuzhiyun 				      config.product_name);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	/* allocate string IDs */
393*4882a593Smuzhiyun 	status = usb_string_ids_tab(cdev, strings_dev);
394*4882a593Smuzhiyun 	if (unlikely(status < 0))
395*4882a593Smuzhiyun 		goto fail_string_ids;
396*4882a593Smuzhiyun 	device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	if (gadget_is_otg(gadget) && !otg_desc[0]) {
399*4882a593Smuzhiyun 		struct usb_descriptor_header *usb_desc;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 		usb_desc = usb_otg_descriptor_alloc(gadget);
402*4882a593Smuzhiyun 		if (!usb_desc)
403*4882a593Smuzhiyun 			goto fail_string_ids;
404*4882a593Smuzhiyun 		usb_otg_descriptor_init(gadget, usb_desc);
405*4882a593Smuzhiyun 		otg_desc[0] = usb_desc;
406*4882a593Smuzhiyun 		otg_desc[1] = NULL;
407*4882a593Smuzhiyun 	}
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	/* register configurations */
410*4882a593Smuzhiyun 	status = rndis_config_register(cdev);
411*4882a593Smuzhiyun 	if (unlikely(status < 0))
412*4882a593Smuzhiyun 		goto fail_otg_desc;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	status = cdc_config_register(cdev);
415*4882a593Smuzhiyun 	if (unlikely(status < 0))
416*4882a593Smuzhiyun 		goto fail_otg_desc;
417*4882a593Smuzhiyun 	usb_composite_overwrite_options(cdev, &coverwrite);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	/* we're done */
420*4882a593Smuzhiyun 	dev_info(&gadget->dev, DRIVER_DESC "\n");
421*4882a593Smuzhiyun 	return 0;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	/* error recovery */
425*4882a593Smuzhiyun fail_otg_desc:
426*4882a593Smuzhiyun 	kfree(otg_desc[0]);
427*4882a593Smuzhiyun 	otg_desc[0] = NULL;
428*4882a593Smuzhiyun fail_string_ids:
429*4882a593Smuzhiyun 	fsg_common_remove_luns(fsg_opts->common);
430*4882a593Smuzhiyun fail_set_cdev:
431*4882a593Smuzhiyun 	fsg_common_free_buffers(fsg_opts->common);
432*4882a593Smuzhiyun fail2:
433*4882a593Smuzhiyun 	usb_put_function_instance(fi_msg);
434*4882a593Smuzhiyun fail1:
435*4882a593Smuzhiyun 	usb_put_function_instance(fi_acm);
436*4882a593Smuzhiyun fail0:
437*4882a593Smuzhiyun #ifdef USB_ETH_RNDIS
438*4882a593Smuzhiyun 	usb_put_function_instance(fi_rndis);
439*4882a593Smuzhiyun fail:
440*4882a593Smuzhiyun #endif
441*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_CDC
442*4882a593Smuzhiyun 	usb_put_function_instance(fi_ecm);
443*4882a593Smuzhiyun #endif
444*4882a593Smuzhiyun 	return status;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun 
multi_unbind(struct usb_composite_dev * cdev)447*4882a593Smuzhiyun static int multi_unbind(struct usb_composite_dev *cdev)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_CDC
450*4882a593Smuzhiyun 	usb_put_function(f_msg_multi);
451*4882a593Smuzhiyun #endif
452*4882a593Smuzhiyun #ifdef USB_ETH_RNDIS
453*4882a593Smuzhiyun 	usb_put_function(f_msg_rndis);
454*4882a593Smuzhiyun #endif
455*4882a593Smuzhiyun 	usb_put_function_instance(fi_msg);
456*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_CDC
457*4882a593Smuzhiyun 	usb_put_function(f_acm_multi);
458*4882a593Smuzhiyun #endif
459*4882a593Smuzhiyun #ifdef USB_ETH_RNDIS
460*4882a593Smuzhiyun 	usb_put_function(f_acm_rndis);
461*4882a593Smuzhiyun #endif
462*4882a593Smuzhiyun 	usb_put_function_instance(fi_acm);
463*4882a593Smuzhiyun #ifdef USB_ETH_RNDIS
464*4882a593Smuzhiyun 	usb_put_function(f_rndis);
465*4882a593Smuzhiyun 	usb_put_function_instance(fi_rndis);
466*4882a593Smuzhiyun #endif
467*4882a593Smuzhiyun #ifdef CONFIG_USB_G_MULTI_CDC
468*4882a593Smuzhiyun 	usb_put_function(f_ecm);
469*4882a593Smuzhiyun 	usb_put_function_instance(fi_ecm);
470*4882a593Smuzhiyun #endif
471*4882a593Smuzhiyun 	kfree(otg_desc[0]);
472*4882a593Smuzhiyun 	otg_desc[0] = NULL;
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	return 0;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun /****************************** Some noise ******************************/
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun static struct usb_composite_driver multi_driver = {
482*4882a593Smuzhiyun 	.name		= "g_multi",
483*4882a593Smuzhiyun 	.dev		= &device_desc,
484*4882a593Smuzhiyun 	.strings	= dev_strings,
485*4882a593Smuzhiyun 	.max_speed	= USB_SPEED_SUPER,
486*4882a593Smuzhiyun 	.bind		= multi_bind,
487*4882a593Smuzhiyun 	.unbind		= multi_unbind,
488*4882a593Smuzhiyun 	.needs_serial	= 1,
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun module_usb_composite_driver(multi_driver);
492