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

tcm_usb_gadget.c (4417B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Target based USB-Gadget
      3 *
      4 * UAS protocol handling, target callbacks, configfs handling,
      5 * BBB (USB Mass Storage Class Bulk-Only (BBB) and Transport protocol handling.
      6 *
      7 * Author: Sebastian Andrzej Siewior <bigeasy at linutronix dot de>
      8 */
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/types.h>
     12#include <linux/string.h>
     13#include <linux/configfs.h>
     14#include <linux/ctype.h>
     15#include <linux/usb/ch9.h>
     16#include <linux/usb/composite.h>
     17#include <linux/usb/gadget.h>
     18#include <linux/usb/storage.h>
     19#include <scsi/scsi_tcq.h>
     20#include <target/target_core_base.h>
     21#include <target/target_core_fabric.h>
     22#include <asm/unaligned.h>
     23
     24#include "u_tcm.h"
     25
     26USB_GADGET_COMPOSITE_OPTIONS();
     27
     28#define UAS_VENDOR_ID	0x0525	/* NetChip */
     29#define UAS_PRODUCT_ID	0xa4a5	/* Linux-USB File-backed Storage Gadget */
     30
     31static struct usb_device_descriptor usbg_device_desc = {
     32	.bLength =		sizeof(usbg_device_desc),
     33	.bDescriptorType =	USB_DT_DEVICE,
     34	/* .bcdUSB = DYNAMIC */
     35	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
     36	.idVendor =		cpu_to_le16(UAS_VENDOR_ID),
     37	.idProduct =		cpu_to_le16(UAS_PRODUCT_ID),
     38	.bNumConfigurations =   1,
     39};
     40
     41#define USB_G_STR_CONFIG USB_GADGET_FIRST_AVAIL_IDX
     42
     43static struct usb_string	usbg_us_strings[] = {
     44	[USB_GADGET_MANUFACTURER_IDX].s	= "Target Manufacturer",
     45	[USB_GADGET_PRODUCT_IDX].s	= "Target Product",
     46	[USB_GADGET_SERIAL_IDX].s	= "000000000001",
     47	[USB_G_STR_CONFIG].s		= "default config",
     48	{ },
     49};
     50
     51static struct usb_gadget_strings usbg_stringtab = {
     52	.language = 0x0409,
     53	.strings = usbg_us_strings,
     54};
     55
     56static struct usb_gadget_strings *usbg_strings[] = {
     57	&usbg_stringtab,
     58	NULL,
     59};
     60
     61static struct usb_function_instance *fi_tcm;
     62static struct usb_function *f_tcm;
     63
     64static int guas_unbind(struct usb_composite_dev *cdev)
     65{
     66	if (!IS_ERR_OR_NULL(f_tcm))
     67		usb_put_function(f_tcm);
     68
     69	return 0;
     70}
     71
     72static int tcm_do_config(struct usb_configuration *c)
     73{
     74	int status;
     75
     76	f_tcm = usb_get_function(fi_tcm);
     77	if (IS_ERR(f_tcm))
     78		return PTR_ERR(f_tcm);
     79
     80	status = usb_add_function(c, f_tcm);
     81	if (status < 0) {
     82		usb_put_function(f_tcm);
     83		return status;
     84	}
     85
     86	return 0;
     87}
     88
     89static struct usb_configuration usbg_config_driver = {
     90	.label                  = "Linux Target",
     91	.bConfigurationValue    = 1,
     92	.bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
     93};
     94
     95static int usbg_attach(struct usb_function_instance *f);
     96static void usbg_detach(struct usb_function_instance *f);
     97
     98static int usb_target_bind(struct usb_composite_dev *cdev)
     99{
    100	int ret;
    101
    102	ret = usb_string_ids_tab(cdev, usbg_us_strings);
    103	if (ret)
    104		return ret;
    105
    106	usbg_device_desc.iManufacturer =
    107		usbg_us_strings[USB_GADGET_MANUFACTURER_IDX].id;
    108	usbg_device_desc.iProduct = usbg_us_strings[USB_GADGET_PRODUCT_IDX].id;
    109	usbg_device_desc.iSerialNumber =
    110		usbg_us_strings[USB_GADGET_SERIAL_IDX].id;
    111	usbg_config_driver.iConfiguration =
    112		usbg_us_strings[USB_G_STR_CONFIG].id;
    113
    114	ret = usb_add_config(cdev, &usbg_config_driver, tcm_do_config);
    115	if (ret)
    116		return ret;
    117	usb_composite_overwrite_options(cdev, &coverwrite);
    118	return 0;
    119}
    120
    121static struct usb_composite_driver usbg_driver = {
    122	.name           = "g_target",
    123	.dev            = &usbg_device_desc,
    124	.strings        = usbg_strings,
    125	.max_speed      = USB_SPEED_SUPER,
    126	.bind		= usb_target_bind,
    127	.unbind         = guas_unbind,
    128};
    129
    130static int usbg_attach(struct usb_function_instance *f)
    131{
    132	return usb_composite_probe(&usbg_driver);
    133}
    134
    135static void usbg_detach(struct usb_function_instance *f)
    136{
    137	usb_composite_unregister(&usbg_driver);
    138}
    139
    140static int __init usb_target_gadget_init(void)
    141{
    142	struct f_tcm_opts *tcm_opts;
    143
    144	fi_tcm = usb_get_function_instance("tcm");
    145	if (IS_ERR(fi_tcm))
    146		return PTR_ERR(fi_tcm);
    147
    148	tcm_opts = container_of(fi_tcm, struct f_tcm_opts, func_inst);
    149	mutex_lock(&tcm_opts->dep_lock);
    150	tcm_opts->tcm_register_callback = usbg_attach;
    151	tcm_opts->tcm_unregister_callback = usbg_detach;
    152	tcm_opts->dependent = THIS_MODULE;
    153	tcm_opts->can_attach = true;
    154	tcm_opts->has_dep = true;
    155	mutex_unlock(&tcm_opts->dep_lock);
    156
    157	fi_tcm->set_inst_name(fi_tcm, "tcm-legacy");
    158
    159	return 0;
    160}
    161module_init(usb_target_gadget_init);
    162
    163static void __exit usb_target_gadget_exit(void)
    164{
    165	if (!IS_ERR_OR_NULL(fi_tcm))
    166		usb_put_function_instance(fi_tcm);
    167
    168}
    169module_exit(usb_target_gadget_exit);
    170
    171MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
    172MODULE_DESCRIPTION("usb-gadget fabric");
    173MODULE_LICENSE("GPL v2");