Linux Audio

Check our new training course

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