xref: /OK3568_Linux_fs/kernel/drivers/usb/gadget/legacy/serial.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * serial.c -- USB gadget serial driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
6*4882a593Smuzhiyun  * Copyright (C) 2008 by David Brownell
7*4882a593Smuzhiyun  * Copyright (C) 2008 by Nokia Corporation
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/device.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/tty.h>
14*4882a593Smuzhiyun #include <linux/tty_flip.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include "u_serial.h"
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /* Defines */
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define GS_VERSION_STR			"v2.4"
22*4882a593Smuzhiyun #define GS_VERSION_NUM			0x2400
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define GS_LONG_NAME			"Gadget Serial"
25*4882a593Smuzhiyun #define GS_VERSION_NAME			GS_LONG_NAME " " GS_VERSION_STR
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
28*4882a593Smuzhiyun USB_GADGET_COMPOSITE_OPTIONS();
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /* Thanks to NetChip Technologies for donating this product ID.
31*4882a593Smuzhiyun *
32*4882a593Smuzhiyun * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
33*4882a593Smuzhiyun * Instead:  allocate your own, using normal USB-IF procedures.
34*4882a593Smuzhiyun */
35*4882a593Smuzhiyun #define GS_VENDOR_ID			0x0525	/* NetChip */
36*4882a593Smuzhiyun #define GS_PRODUCT_ID			0xa4a6	/* Linux-USB Serial Gadget */
37*4882a593Smuzhiyun #define GS_CDC_PRODUCT_ID		0xa4a7	/* ... as CDC-ACM */
38*4882a593Smuzhiyun #define GS_CDC_OBEX_PRODUCT_ID		0xa4a9	/* ... as CDC-OBEX */
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun /* string IDs are assigned dynamically */
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #define STRING_DESCRIPTION_IDX		USB_GADGET_FIRST_AVAIL_IDX
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun static struct usb_string strings_dev[] = {
45*4882a593Smuzhiyun 	[USB_GADGET_MANUFACTURER_IDX].s = "",
46*4882a593Smuzhiyun 	[USB_GADGET_PRODUCT_IDX].s = GS_VERSION_NAME,
47*4882a593Smuzhiyun 	[USB_GADGET_SERIAL_IDX].s = "",
48*4882a593Smuzhiyun 	[STRING_DESCRIPTION_IDX].s = NULL /* updated; f(use_acm) */,
49*4882a593Smuzhiyun 	{  } /* end of list */
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun static struct usb_gadget_strings stringtab_dev = {
53*4882a593Smuzhiyun 	.language	= 0x0409,	/* en-us */
54*4882a593Smuzhiyun 	.strings	= strings_dev,
55*4882a593Smuzhiyun };
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun static struct usb_gadget_strings *dev_strings[] = {
58*4882a593Smuzhiyun 	&stringtab_dev,
59*4882a593Smuzhiyun 	NULL,
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun static struct usb_device_descriptor device_desc = {
63*4882a593Smuzhiyun 	.bLength =		USB_DT_DEVICE_SIZE,
64*4882a593Smuzhiyun 	.bDescriptorType =	USB_DT_DEVICE,
65*4882a593Smuzhiyun 	/* .bcdUSB = DYNAMIC */
66*4882a593Smuzhiyun 	/* .bDeviceClass = f(use_acm) */
67*4882a593Smuzhiyun 	.bDeviceSubClass =	0,
68*4882a593Smuzhiyun 	.bDeviceProtocol =	0,
69*4882a593Smuzhiyun 	/* .bMaxPacketSize0 = f(hardware) */
70*4882a593Smuzhiyun 	.idVendor =		cpu_to_le16(GS_VENDOR_ID),
71*4882a593Smuzhiyun 	/* .idProduct =	f(use_acm) */
72*4882a593Smuzhiyun 	.bcdDevice = cpu_to_le16(GS_VERSION_NUM),
73*4882a593Smuzhiyun 	/* .iManufacturer = DYNAMIC */
74*4882a593Smuzhiyun 	/* .iProduct = DYNAMIC */
75*4882a593Smuzhiyun 	.bNumConfigurations =	1,
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun static const struct usb_descriptor_header *otg_desc[2];
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun /* Module */
83*4882a593Smuzhiyun MODULE_DESCRIPTION(GS_VERSION_NAME);
84*4882a593Smuzhiyun MODULE_AUTHOR("Al Borchers");
85*4882a593Smuzhiyun MODULE_AUTHOR("David Brownell");
86*4882a593Smuzhiyun MODULE_LICENSE("GPL");
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun static bool use_acm = true;
89*4882a593Smuzhiyun module_param(use_acm, bool, 0);
90*4882a593Smuzhiyun MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes");
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun static bool use_obex = false;
93*4882a593Smuzhiyun module_param(use_obex, bool, 0);
94*4882a593Smuzhiyun MODULE_PARM_DESC(use_obex, "Use CDC OBEX, default=no");
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun static unsigned n_ports = 1;
97*4882a593Smuzhiyun module_param(n_ports, uint, 0);
98*4882a593Smuzhiyun MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun static bool enable = true;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun static int switch_gserial_enable(bool do_enable);
103*4882a593Smuzhiyun 
enable_set(const char * s,const struct kernel_param * kp)104*4882a593Smuzhiyun static int enable_set(const char *s, const struct kernel_param *kp)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun 	bool do_enable;
107*4882a593Smuzhiyun 	int ret;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	if (!s)	/* called for no-arg enable == default */
110*4882a593Smuzhiyun 		return 0;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	ret = strtobool(s, &do_enable);
113*4882a593Smuzhiyun 	if (ret || enable == do_enable)
114*4882a593Smuzhiyun 		return ret;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	ret = switch_gserial_enable(do_enable);
117*4882a593Smuzhiyun 	if (!ret)
118*4882a593Smuzhiyun 		enable = do_enable;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	return ret;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun static const struct kernel_param_ops enable_ops = {
124*4882a593Smuzhiyun 	.set = enable_set,
125*4882a593Smuzhiyun 	.get = param_get_bool,
126*4882a593Smuzhiyun };
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun module_param_cb(enable, &enable_ops, &enable, 0644);
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun static struct usb_configuration serial_config_driver = {
133*4882a593Smuzhiyun 	/* .label = f(use_acm) */
134*4882a593Smuzhiyun 	/* .bConfigurationValue = f(use_acm) */
135*4882a593Smuzhiyun 	/* .iConfiguration = DYNAMIC */
136*4882a593Smuzhiyun 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
137*4882a593Smuzhiyun };
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static struct usb_function_instance *fi_serial[MAX_U_SERIAL_PORTS];
140*4882a593Smuzhiyun static struct usb_function *f_serial[MAX_U_SERIAL_PORTS];
141*4882a593Smuzhiyun 
serial_register_ports(struct usb_composite_dev * cdev,struct usb_configuration * c,const char * f_name)142*4882a593Smuzhiyun static int serial_register_ports(struct usb_composite_dev *cdev,
143*4882a593Smuzhiyun 		struct usb_configuration *c, const char *f_name)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	int i;
146*4882a593Smuzhiyun 	int ret;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	ret = usb_add_config_only(cdev, c);
149*4882a593Smuzhiyun 	if (ret)
150*4882a593Smuzhiyun 		goto out;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	for (i = 0; i < n_ports; i++) {
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 		fi_serial[i] = usb_get_function_instance(f_name);
155*4882a593Smuzhiyun 		if (IS_ERR(fi_serial[i])) {
156*4882a593Smuzhiyun 			ret = PTR_ERR(fi_serial[i]);
157*4882a593Smuzhiyun 			goto fail;
158*4882a593Smuzhiyun 		}
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 		f_serial[i] = usb_get_function(fi_serial[i]);
161*4882a593Smuzhiyun 		if (IS_ERR(f_serial[i])) {
162*4882a593Smuzhiyun 			ret = PTR_ERR(f_serial[i]);
163*4882a593Smuzhiyun 			goto err_get_func;
164*4882a593Smuzhiyun 		}
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 		ret = usb_add_function(c, f_serial[i]);
167*4882a593Smuzhiyun 		if (ret)
168*4882a593Smuzhiyun 			goto err_add_func;
169*4882a593Smuzhiyun 	}
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	return 0;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun err_add_func:
174*4882a593Smuzhiyun 	usb_put_function(f_serial[i]);
175*4882a593Smuzhiyun err_get_func:
176*4882a593Smuzhiyun 	usb_put_function_instance(fi_serial[i]);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun fail:
179*4882a593Smuzhiyun 	i--;
180*4882a593Smuzhiyun 	while (i >= 0) {
181*4882a593Smuzhiyun 		usb_remove_function(c, f_serial[i]);
182*4882a593Smuzhiyun 		usb_put_function(f_serial[i]);
183*4882a593Smuzhiyun 		usb_put_function_instance(fi_serial[i]);
184*4882a593Smuzhiyun 		i--;
185*4882a593Smuzhiyun 	}
186*4882a593Smuzhiyun out:
187*4882a593Smuzhiyun 	return ret;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun 
gs_bind(struct usb_composite_dev * cdev)190*4882a593Smuzhiyun static int gs_bind(struct usb_composite_dev *cdev)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun 	int			status;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	/* Allocate string descriptor numbers ... note that string
195*4882a593Smuzhiyun 	 * contents can be overridden by the composite_dev glue.
196*4882a593Smuzhiyun 	 */
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	status = usb_string_ids_tab(cdev, strings_dev);
199*4882a593Smuzhiyun 	if (status < 0)
200*4882a593Smuzhiyun 		goto fail;
201*4882a593Smuzhiyun 	device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
202*4882a593Smuzhiyun 	device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
203*4882a593Smuzhiyun 	status = strings_dev[STRING_DESCRIPTION_IDX].id;
204*4882a593Smuzhiyun 	serial_config_driver.iConfiguration = status;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	if (gadget_is_otg(cdev->gadget)) {
207*4882a593Smuzhiyun 		if (!otg_desc[0]) {
208*4882a593Smuzhiyun 			struct usb_descriptor_header *usb_desc;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 			usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
211*4882a593Smuzhiyun 			if (!usb_desc) {
212*4882a593Smuzhiyun 				status = -ENOMEM;
213*4882a593Smuzhiyun 				goto fail;
214*4882a593Smuzhiyun 			}
215*4882a593Smuzhiyun 			usb_otg_descriptor_init(cdev->gadget, usb_desc);
216*4882a593Smuzhiyun 			otg_desc[0] = usb_desc;
217*4882a593Smuzhiyun 			otg_desc[1] = NULL;
218*4882a593Smuzhiyun 		}
219*4882a593Smuzhiyun 		serial_config_driver.descriptors = otg_desc;
220*4882a593Smuzhiyun 		serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
221*4882a593Smuzhiyun 	}
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	/* register our configuration */
224*4882a593Smuzhiyun 	if (use_acm) {
225*4882a593Smuzhiyun 		status  = serial_register_ports(cdev, &serial_config_driver,
226*4882a593Smuzhiyun 				"acm");
227*4882a593Smuzhiyun 		usb_ep_autoconfig_reset(cdev->gadget);
228*4882a593Smuzhiyun 	} else if (use_obex)
229*4882a593Smuzhiyun 		status = serial_register_ports(cdev, &serial_config_driver,
230*4882a593Smuzhiyun 				"obex");
231*4882a593Smuzhiyun 	else {
232*4882a593Smuzhiyun 		status = serial_register_ports(cdev, &serial_config_driver,
233*4882a593Smuzhiyun 				"gser");
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 	if (status < 0)
236*4882a593Smuzhiyun 		goto fail1;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	usb_composite_overwrite_options(cdev, &coverwrite);
239*4882a593Smuzhiyun 	INFO(cdev, "%s\n", GS_VERSION_NAME);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	return 0;
242*4882a593Smuzhiyun fail1:
243*4882a593Smuzhiyun 	kfree(otg_desc[0]);
244*4882a593Smuzhiyun 	otg_desc[0] = NULL;
245*4882a593Smuzhiyun fail:
246*4882a593Smuzhiyun 	return status;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
gs_unbind(struct usb_composite_dev * cdev)249*4882a593Smuzhiyun static int gs_unbind(struct usb_composite_dev *cdev)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	int i;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	for (i = 0; i < n_ports; i++) {
254*4882a593Smuzhiyun 		usb_put_function(f_serial[i]);
255*4882a593Smuzhiyun 		usb_put_function_instance(fi_serial[i]);
256*4882a593Smuzhiyun 	}
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	kfree(otg_desc[0]);
259*4882a593Smuzhiyun 	otg_desc[0] = NULL;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	return 0;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun static struct usb_composite_driver gserial_driver = {
265*4882a593Smuzhiyun 	.name		= "g_serial",
266*4882a593Smuzhiyun 	.dev		= &device_desc,
267*4882a593Smuzhiyun 	.strings	= dev_strings,
268*4882a593Smuzhiyun 	.max_speed	= USB_SPEED_SUPER,
269*4882a593Smuzhiyun 	.bind		= gs_bind,
270*4882a593Smuzhiyun 	.unbind		= gs_unbind,
271*4882a593Smuzhiyun };
272*4882a593Smuzhiyun 
switch_gserial_enable(bool do_enable)273*4882a593Smuzhiyun static int switch_gserial_enable(bool do_enable)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	if (!serial_config_driver.label)
276*4882a593Smuzhiyun 		/* init() was not called, yet */
277*4882a593Smuzhiyun 		return 0;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	if (do_enable)
280*4882a593Smuzhiyun 		return usb_composite_probe(&gserial_driver);
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	usb_composite_unregister(&gserial_driver);
283*4882a593Smuzhiyun 	return 0;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
init(void)286*4882a593Smuzhiyun static int __init init(void)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun 	/* We *could* export two configs; that'd be much cleaner...
289*4882a593Smuzhiyun 	 * but neither of these product IDs was defined that way.
290*4882a593Smuzhiyun 	 */
291*4882a593Smuzhiyun 	if (use_acm) {
292*4882a593Smuzhiyun 		serial_config_driver.label = "CDC ACM config";
293*4882a593Smuzhiyun 		serial_config_driver.bConfigurationValue = 2;
294*4882a593Smuzhiyun 		device_desc.bDeviceClass = USB_CLASS_COMM;
295*4882a593Smuzhiyun 		device_desc.idProduct =
296*4882a593Smuzhiyun 				cpu_to_le16(GS_CDC_PRODUCT_ID);
297*4882a593Smuzhiyun 	} else if (use_obex) {
298*4882a593Smuzhiyun 		serial_config_driver.label = "CDC OBEX config";
299*4882a593Smuzhiyun 		serial_config_driver.bConfigurationValue = 3;
300*4882a593Smuzhiyun 		device_desc.bDeviceClass = USB_CLASS_COMM;
301*4882a593Smuzhiyun 		device_desc.idProduct =
302*4882a593Smuzhiyun 			cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
303*4882a593Smuzhiyun 	} else {
304*4882a593Smuzhiyun 		serial_config_driver.label = "Generic Serial config";
305*4882a593Smuzhiyun 		serial_config_driver.bConfigurationValue = 1;
306*4882a593Smuzhiyun 		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
307*4882a593Smuzhiyun 		device_desc.idProduct =
308*4882a593Smuzhiyun 				cpu_to_le16(GS_PRODUCT_ID);
309*4882a593Smuzhiyun 	}
310*4882a593Smuzhiyun 	strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	if (!enable)
313*4882a593Smuzhiyun 		return 0;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	return usb_composite_probe(&gserial_driver);
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun module_init(init);
318*4882a593Smuzhiyun 
cleanup(void)319*4882a593Smuzhiyun static void __exit cleanup(void)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	if (enable)
322*4882a593Smuzhiyun 		usb_composite_unregister(&gserial_driver);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun module_exit(cleanup);
325