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