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 int ret; 109 110 if (gadget_is_otg(c->cdev->gadget)) { 111 c->descriptors = otg_desc; 112 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 113 } 114 115 f_msg = usb_get_function(fi_msg); 116 if (IS_ERR(f_msg)) 117 return PTR_ERR(f_msg); 118 119 ret = usb_add_function(c, f_msg); 120 if (ret) 121 goto put_func; 122 123 return 0; 124 125 put_func: 126 usb_put_function(f_msg); 127 return ret; 128 } 129 130 static struct usb_configuration msg_config_driver = { 131 .label = "Linux File-Backed Storage", 132 .bConfigurationValue = 1, 133 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 134 }; 135 136 137 /****************************** Gadget Bind ******************************/ 138 139 static int msg_bind(struct usb_composite_dev *cdev) 140 { 141 struct fsg_opts *opts; 142 struct fsg_config config; 143 int status; 144 145 fi_msg = usb_get_function_instance("mass_storage"); 146 if (IS_ERR(fi_msg)) 147 return PTR_ERR(fi_msg); 148 149 fsg_config_from_params(&config, &mod_data, fsg_num_buffers); 150 opts = fsg_opts_from_func_inst(fi_msg); 151 152 opts->no_configfs = true; 153 status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers); 154 if (status) 155 goto fail; 156 157 status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); 158 if (status) 159 goto fail_set_cdev; 160 161 fsg_common_set_sysfs(opts->common, true); 162 status = fsg_common_create_luns(opts->common, &config); 163 if (status) 164 goto fail_set_cdev; 165 166 fsg_common_set_inquiry_string(opts->common, config.vendor_name, 167 config.product_name); 168 169 status = usb_string_ids_tab(cdev, strings_dev); 170 if (status < 0) 171 goto fail_string_ids; 172 msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; 173 174 if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) { 175 struct usb_descriptor_header *usb_desc; 176 177 usb_desc = usb_otg_descriptor_alloc(cdev->gadget); 178 if (!usb_desc) 179 goto fail_string_ids; 180 usb_otg_descriptor_init(cdev->gadget, usb_desc); 181 otg_desc[0] = usb_desc; 182 otg_desc[1] = NULL; 183 } 184 185 status = usb_add_config(cdev, &msg_config_driver, msg_do_config); 186 if (status < 0) 187 goto fail_otg_desc; 188 189 usb_composite_overwrite_options(cdev, &coverwrite); 190 dev_info(&cdev->gadget->dev, 191 DRIVER_DESC ", version: " DRIVER_VERSION "\n"); 192 return 0; 193 194 fail_otg_desc: 195 kfree(otg_desc[0]); 196 otg_desc[0] = NULL; 197 fail_string_ids: 198 fsg_common_remove_luns(opts->common); 199 fail_set_cdev: 200 fsg_common_free_buffers(opts->common); 201 fail: 202 usb_put_function_instance(fi_msg); 203 return status; 204 } 205 206 static int msg_unbind(struct usb_composite_dev *cdev) 207 { 208 if (!IS_ERR(f_msg)) 209 usb_put_function(f_msg); 210 211 if (!IS_ERR(fi_msg)) 212 usb_put_function_instance(fi_msg); 213 214 kfree(otg_desc[0]); 215 otg_desc[0] = NULL; 216 217 return 0; 218 } 219 220 /****************************** Some noise ******************************/ 221 222 static struct usb_composite_driver msg_driver = { 223 .name = "g_mass_storage", 224 .dev = &msg_device_desc, 225 .max_speed = USB_SPEED_SUPER_PLUS, 226 .needs_serial = 1, 227 .strings = dev_strings, 228 .bind = msg_bind, 229 .unbind = msg_unbind, 230 }; 231 232 module_usb_composite_driver(msg_driver); 233 234 MODULE_DESCRIPTION(DRIVER_DESC); 235 MODULE_AUTHOR("Michal Nazarewicz"); 236 MODULE_LICENSE("GPL"); 237