1 // SPDX-License-Identifier: GPL-2.0
2 /* Target based USB-Gadget
4 * UAS protocol handling, target callbacks, configfs handling,
5 * BBB (USB Mass Storage Class Bulk-Only (BBB) and Transport protocol handling.
7 * Author: Sebastian Andrzej Siewior <bigeasy at linutronix dot de>
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>
26 USB_GADGET_COMPOSITE_OPTIONS();
28 #define UAS_VENDOR_ID 0x0525 /* NetChip */
29 #define UAS_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */
31 static 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,
41 #define USB_G_STR_CONFIG USB_GADGET_FIRST_AVAIL_IDX
43 static 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",
51 static struct usb_gadget_strings usbg_stringtab
= {
53 .strings
= usbg_us_strings
,
56 static struct usb_gadget_strings
*usbg_strings
[] = {
61 static struct usb_function_instance
*fi_tcm
;
62 static struct usb_function
*f_tcm
;
64 static int guas_unbind(struct usb_composite_dev
*cdev
)
66 if (!IS_ERR_OR_NULL(f_tcm
))
67 usb_put_function(f_tcm
);
72 static int tcm_do_config(struct usb_configuration
*c
)
76 f_tcm
= usb_get_function(fi_tcm
);
78 return PTR_ERR(f_tcm
);
80 status
= usb_add_function(c
, f_tcm
);
82 usb_put_function(f_tcm
);
89 static struct usb_configuration usbg_config_driver
= {
90 .label
= "Linux Target",
91 .bConfigurationValue
= 1,
92 .bmAttributes
= USB_CONFIG_ATT_SELFPOWER
,
95 static int usbg_attach(struct usb_function_instance
*f
);
96 static void usbg_detach(struct usb_function_instance
*f
);
98 static int usb_target_bind(struct usb_composite_dev
*cdev
)
102 ret
= usb_string_ids_tab(cdev
, usbg_us_strings
);
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
;
114 ret
= usb_add_config(cdev
, &usbg_config_driver
, tcm_do_config
);
117 usb_composite_overwrite_options(cdev
, &coverwrite
);
121 static struct usb_composite_driver usbg_driver
= {
123 .dev
= &usbg_device_desc
,
124 .strings
= usbg_strings
,
125 .max_speed
= USB_SPEED_SUPER
,
126 .bind
= usb_target_bind
,
127 .unbind
= guas_unbind
,
130 static int usbg_attach(struct usb_function_instance
*f
)
132 return usb_composite_probe(&usbg_driver
);
135 static void usbg_detach(struct usb_function_instance
*f
)
137 usb_composite_unregister(&usbg_driver
);
140 static int __init
usb_target_gadget_init(void)
142 struct f_tcm_opts
*tcm_opts
;
144 fi_tcm
= usb_get_function_instance("tcm");
146 return PTR_ERR(fi_tcm
);
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
);
157 fi_tcm
->set_inst_name(fi_tcm
, "tcm-legacy");
161 module_init(usb_target_gadget_init
);
163 static void __exit
usb_target_gadget_exit(void)
165 if (!IS_ERR_OR_NULL(fi_tcm
))
166 usb_put_function_instance(fi_tcm
);
169 module_exit(usb_target_gadget_exit
);
171 MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
172 MODULE_DESCRIPTION("usb-gadget fabric");
173 MODULE_LICENSE("GPL v2");