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

multi.c (11390B)


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