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/*-------------------------------------------------------------------------*/ 52USB_GADGET_COMPOSITE_OPTIONS(); 53 54static 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 67static 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 78static const struct usb_descriptor_header *otg_desc[] = { 79 (struct usb_descriptor_header *) &otg_descriptor, 80 NULL, 81}; 82 83static 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 90static struct usb_gadget_strings stringtab_dev = { 91 .language = 0x0409, /* en-us */ 92 .strings = strings_dev, 93}; 94 95static struct usb_gadget_strings *dev_strings[] = { 96 &stringtab_dev, 97 NULL, 98}; 99 100static struct usb_function_instance *fi_msg; 101static struct usb_function *f_msg; 102 103/****************************** Configurations ******************************/ 104 105static struct fsg_module_parameters mod_data = { 106 .stall = 1 107}; 108#ifdef CONFIG_USB_GADGET_DEBUG_FILES 109 110static 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 122FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); 123 124static unsigned long msg_registered; 125static void msg_cleanup(void); 126 127static int msg_thread_exits(struct fsg_common *common) 128{ 129 msg_cleanup(); 130 return 0; 131} 132 133static 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 = usb_add_function(c, f_msg); 150 if (ret) 151 goto put_func; 152 153 return 0; 154 155put_func: 156 usb_put_function(f_msg); 157 return ret; 158} 159 160static struct usb_configuration msg_config_driver = { 161 .label = "Linux File-Backed Storage", 162 .bConfigurationValue = 1, 163 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 164}; 165 166 167/****************************** Gadget Bind ******************************/ 168 169static int msg_bind(struct usb_composite_dev *cdev) 170{ 171 static const struct fsg_operations ops = { 172 .thread_exits = msg_thread_exits, 173 }; 174 struct fsg_opts *opts; 175 struct fsg_config config; 176 int status; 177 178 fi_msg = usb_get_function_instance("mass_storage"); 179 if (IS_ERR(fi_msg)) 180 return PTR_ERR(fi_msg); 181 182 fsg_config_from_params(&config, &mod_data, fsg_num_buffers); 183 opts = fsg_opts_from_func_inst(fi_msg); 184 185 opts->no_configfs = true; 186 status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers); 187 if (status) 188 goto fail; 189 190 fsg_common_set_ops(opts->common, &ops); 191 192 status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); 193 if (status) 194 goto fail_set_cdev; 195 196 fsg_common_set_sysfs(opts->common, true); 197 status = fsg_common_create_luns(opts->common, &config); 198 if (status) 199 goto fail_set_cdev; 200 201 fsg_common_set_inquiry_string(opts->common, config.vendor_name, 202 config.product_name); 203 204 status = usb_string_ids_tab(cdev, strings_dev); 205 if (status < 0) 206 goto fail_string_ids; 207 msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; 208 209 status = usb_add_config(cdev, &msg_config_driver, msg_do_config); 210 if (status < 0) 211 goto fail_string_ids; 212 213 usb_composite_overwrite_options(cdev, &coverwrite); 214 dev_info(&cdev->gadget->dev, 215 DRIVER_DESC ", version: " DRIVER_VERSION "\n"); 216 set_bit(0, &msg_registered); 217 return 0; 218 219fail_string_ids: 220 fsg_common_remove_luns(opts->common); 221fail_set_cdev: 222 fsg_common_free_buffers(opts->common); 223fail: 224 usb_put_function_instance(fi_msg); 225 return status; 226} 227 228static int msg_unbind(struct usb_composite_dev *cdev) 229{ 230 if (!IS_ERR(f_msg)) 231 usb_put_function(f_msg); 232 233 if (!IS_ERR(fi_msg)) 234 usb_put_function_instance(fi_msg); 235 236 return 0; 237} 238 239/****************************** Some noise ******************************/ 240 241static struct usb_composite_driver msg_driver = { 242 .name = "g_mass_storage", 243 .dev = &msg_device_desc, 244 .max_speed = USB_SPEED_SUPER, 245 .needs_serial = 1, 246 .strings = dev_strings, 247 .bind = msg_bind, 248 .unbind = msg_unbind, 249}; 250 251MODULE_DESCRIPTION(DRIVER_DESC); 252MODULE_AUTHOR("Michal Nazarewicz"); 253MODULE_LICENSE("GPL"); 254 255static int __init msg_init(void) 256{ 257 return usb_composite_probe(&msg_driver); 258} 259module_init(msg_init); 260 261static void msg_cleanup(void) 262{ 263 if (test_and_clear_bit(0, &msg_registered)) 264 usb_composite_unregister(&msg_driver); 265} 266module_exit(msg_cleanup); 267