cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

serial.c (7954B)


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