1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * mass_storage.c -- Mass Storage USB Gadget 4 * 5 * Copyright (C) 2003-2008 Alan Stern 6 * Copyright (C) 2009 Samsung Electronics 7 * Author: Michal Nazarewicz <mina86@mina86.com> 8 * All rights reserved. 9 */ 10 11 12 /* 13 * The Mass Storage Gadget acts as a USB Mass Storage device, 14 * appearing to the host as a disk drive or as a CD-ROM drive. In 15 * addition to providing an example of a genuinely useful gadget 16 * driver for a USB device, it also illustrates a technique of 17 * double-buffering for increased throughput. Last but not least, it 18 * gives an easy way to probe the behavior of the Mass Storage drivers 19 * in a USB host. 20 * 21 * Since this file serves only administrative purposes and all the 22 * business logic is implemented in f_mass_storage.* file. Read 23 * comments in this file for more detailed description. 24 */ 25 26 27 #include <linux/kernel.h> 28 #include <linux/usb/ch9.h> 29 #include <linux/module.h> 30 31 /*-------------------------------------------------------------------------*/ 32 33 #define DRIVER_DESC "Mass Storage Gadget" 34 #define DRIVER_VERSION "2009/09/11" 35 36 /* 37 * Thanks to NetChip Technologies for donating this product ID. 38 * 39 * DO NOT REUSE THESE IDs with any other driver!! Ever!! 40 * Instead: allocate your own, using normal USB-IF procedures. 41 */ 42 #define FSG_VENDOR_ID 0x0525 /* NetChip */ 43 #define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ 44 45 #include "f_mass_storage.h" 46 47 /*-------------------------------------------------------------------------*/ 48 USB_GADGET_COMPOSITE_OPTIONS(); 49 50 static struct usb_device_descriptor msg_device_desc = { 51 .bLength = sizeof msg_device_desc, 52 .bDescriptorType = USB_DT_DEVICE, 53 54 /* .bcdUSB = DYNAMIC */ 55 .bDeviceClass = USB_CLASS_PER_INTERFACE, 56 57 /* Vendor and product id can be overridden by module parameters. */ 58 .idVendor = cpu_to_le16(FSG_VENDOR_ID), 59 .idProduct = cpu_to_le16(FSG_PRODUCT_ID), 60 .bNumConfigurations = 1, 61 }; 62 63 static const struct usb_descriptor_header *otg_desc[2]; 64 65 static struct usb_string strings_dev[] = { 66 [USB_GADGET_MANUFACTURER_IDX].s = "", 67 [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, 68 [USB_GADGET_SERIAL_IDX].s = "", 69 { } /* end of list */ 70 }; 71 72 static struct usb_gadget_strings stringtab_dev = { 73 .language = 0x0409, /* en-us */ 74 .strings = strings_dev, 75 }; 76 77 static struct usb_gadget_strings *dev_strings[] = { 78 &stringtab_dev, 79 NULL, 80 }; 81 82 static struct usb_function_instance *fi_msg; 83 static struct usb_function *f_msg; 84 85 /****************************** Configurations ******************************/ 86 87 static struct fsg_module_parameters mod_data = { 88 .stall = 1 89 }; 90 #ifdef CONFIG_USB_GADGET_DEBUG_FILES 91 92 static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; 93 94 #else 95 96 /* 97 * Number of buffers we will use. 98 * 2 is usually enough for good buffering pipeline 99 */ 100 #define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS 101 102 #endif /* CONFIG_USB_GADGET_DEBUG_FILES */ 103 104 FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); 105 106 static int msg_do_config(struct usb_configuration *c) 107 { 108 struct fsg_opts *opts; 109 int ret; 110 111 if (gadget_is_otg(c->cdev->gadget)) { 112 c->descriptors = otg_desc; 113 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 114 } 115 116 opts = fsg_opts_from_func_inst(fi_msg); 117 118 f_msg = usb_get_function(fi_msg); 119 if (IS_ERR(f_msg)) 120 return PTR_ERR(f_msg); 121 122 ret = usb_add_function(c, f_msg); 123 if (ret) 124 goto put_func; 125 126 return 0; 127 128 put_func: 129 usb_put_function(f_msg); 130 return ret; 131 } 132 133 static struct usb_configuration msg_config_driver = { 134 .label = "Linux File-Backed Storage", 135 .bConfigurationValue = 1, 136 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 137 }; 138 139 140 /****************************** Gadget Bind ******************************/ 141 142 static int msg_bind(struct usb_composite_dev *cdev) 143 { 144 struct fsg_opts *opts; 145 struct fsg_config config; 146 int status; 147 148 fi_msg = usb_get_function_instance("mass_storage"); 149 if (IS_ERR(fi_msg)) 150 return PTR_ERR(fi_msg); 151 152 fsg_config_from_params(&config, &mod_data, fsg_num_buffers); 153 opts = fsg_opts_from_func_inst(fi_msg); 154 155 opts->no_configfs = true; 156 status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers); 157 if (status) 158 goto fail; 159 160 status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); 161 if (status) 162 goto fail_set_cdev; 163 164 fsg_common_set_sysfs(opts->common, true); 165 status = fsg_common_create_luns(opts->common, &config); 166 if (status) 167 goto fail_set_cdev; 168 169 fsg_common_set_inquiry_string(opts->common, config.vendor_name, 170 config.product_name); 171 172 status = usb_string_ids_tab(cdev, strings_dev); 173 if (status < 0) 174 goto fail_string_ids; 175 msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; 176 177 if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) { 178 struct usb_descriptor_header *usb_desc; 179 180 usb_desc = usb_otg_descriptor_alloc(cdev->gadget); 181 if (!usb_desc) 182 goto fail_string_ids; 183 usb_otg_descriptor_init(cdev->gadget, usb_desc); 184 otg_desc[0] = usb_desc; 185 otg_desc[1] = NULL; 186 } 187 188 status = usb_add_config(cdev, &msg_config_driver, msg_do_config); 189 if (status < 0) 190 goto fail_otg_desc; 191 192 usb_composite_overwrite_options(cdev, &coverwrite); 193 dev_info(&cdev->gadget->dev, 194 DRIVER_DESC ", version: " DRIVER_VERSION "\n"); 195 return 0; 196 197 fail_otg_desc: 198 kfree(otg_desc[0]); 199 otg_desc[0] = NULL; 200 fail_string_ids: 201 fsg_common_remove_luns(opts->common); 202 fail_set_cdev: 203 fsg_common_free_buffers(opts->common); 204 fail: 205 usb_put_function_instance(fi_msg); 206 return status; 207 } 208 209 static int msg_unbind(struct usb_composite_dev *cdev) 210 { 211 if (!IS_ERR(f_msg)) 212 usb_put_function(f_msg); 213 214 if (!IS_ERR(fi_msg)) 215 usb_put_function_instance(fi_msg); 216 217 kfree(otg_desc[0]); 218 otg_desc[0] = NULL; 219 220 return 0; 221 } 222 223 /****************************** Some noise ******************************/ 224 225 static struct usb_composite_driver msg_driver = { 226 .name = "g_mass_storage", 227 .dev = &msg_device_desc, 228 .max_speed = USB_SPEED_SUPER_PLUS, 229 .needs_serial = 1, 230 .strings = dev_strings, 231 .bind = msg_bind, 232 .unbind = msg_unbind, 233 }; 234 235 MODULE_DESCRIPTION(DRIVER_DESC); 236 MODULE_AUTHOR("Michal Nazarewicz"); 237 MODULE_LICENSE("GPL"); 238 239 static int __init msg_init(void) 240 { 241 return usb_composite_probe(&msg_driver); 242 } 243 module_init(msg_init); 244 245 static void __exit msg_cleanup(void) 246 { 247 usb_composite_unregister(&msg_driver); 248 } 249 module_exit(msg_cleanup); 250