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