linux/drivers/usb/gadget/legacy/mass_storage.c
<<
>>
Prefs
   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 = DYNAMIC */
  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 const struct usb_descriptor_header *otg_desc[2];
  68
  69static struct usb_string strings_dev[] = {
  70        [USB_GADGET_MANUFACTURER_IDX].s = "",
  71        [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
  72        [USB_GADGET_SERIAL_IDX].s = "",
  73        {  } /* end of list */
  74};
  75
  76static struct usb_gadget_strings stringtab_dev = {
  77        .language       = 0x0409,       /* en-us */
  78        .strings        = strings_dev,
  79};
  80
  81static struct usb_gadget_strings *dev_strings[] = {
  82        &stringtab_dev,
  83        NULL,
  84};
  85
  86static struct usb_function_instance *fi_msg;
  87static struct usb_function *f_msg;
  88
  89/****************************** Configurations ******************************/
  90
  91static struct fsg_module_parameters mod_data = {
  92        .stall = 1
  93};
  94#ifdef CONFIG_USB_GADGET_DEBUG_FILES
  95
  96static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
  97
  98#else
  99
 100/*
 101 * Number of buffers we will use.
 102 * 2 is usually enough for good buffering pipeline
 103 */
 104#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
 105
 106#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 107
 108FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
 109
 110static unsigned long msg_registered;
 111static void msg_cleanup(void);
 112
 113static int msg_thread_exits(struct fsg_common *common)
 114{
 115        msg_cleanup();
 116        return 0;
 117}
 118
 119static int msg_do_config(struct usb_configuration *c)
 120{
 121        struct fsg_opts *opts;
 122        int ret;
 123
 124        if (gadget_is_otg(c->cdev->gadget)) {
 125                c->descriptors = otg_desc;
 126                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 127        }
 128
 129        opts = fsg_opts_from_func_inst(fi_msg);
 130
 131        f_msg = usb_get_function(fi_msg);
 132        if (IS_ERR(f_msg))
 133                return PTR_ERR(f_msg);
 134
 135        ret = usb_add_function(c, f_msg);
 136        if (ret)
 137                goto put_func;
 138
 139        return 0;
 140
 141put_func:
 142        usb_put_function(f_msg);
 143        return ret;
 144}
 145
 146static struct usb_configuration msg_config_driver = {
 147        .label                  = "Linux File-Backed Storage",
 148        .bConfigurationValue    = 1,
 149        .bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
 150};
 151
 152
 153/****************************** Gadget Bind ******************************/
 154
 155static int msg_bind(struct usb_composite_dev *cdev)
 156{
 157        static const struct fsg_operations ops = {
 158                .thread_exits = msg_thread_exits,
 159        };
 160        struct fsg_opts *opts;
 161        struct fsg_config config;
 162        int status;
 163
 164        fi_msg = usb_get_function_instance("mass_storage");
 165        if (IS_ERR(fi_msg))
 166                return PTR_ERR(fi_msg);
 167
 168        fsg_config_from_params(&config, &mod_data, fsg_num_buffers);
 169        opts = fsg_opts_from_func_inst(fi_msg);
 170
 171        opts->no_configfs = true;
 172        status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers);
 173        if (status)
 174                goto fail;
 175
 176        fsg_common_set_ops(opts->common, &ops);
 177
 178        status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
 179        if (status)
 180                goto fail_set_cdev;
 181
 182        fsg_common_set_sysfs(opts->common, true);
 183        status = fsg_common_create_luns(opts->common, &config);
 184        if (status)
 185                goto fail_set_cdev;
 186
 187        fsg_common_set_inquiry_string(opts->common, config.vendor_name,
 188                                      config.product_name);
 189
 190        status = usb_string_ids_tab(cdev, strings_dev);
 191        if (status < 0)
 192                goto fail_string_ids;
 193        msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 194
 195        if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
 196                struct usb_descriptor_header *usb_desc;
 197
 198                usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
 199                if (!usb_desc)
 200                        goto fail_string_ids;
 201                usb_otg_descriptor_init(cdev->gadget, usb_desc);
 202                otg_desc[0] = usb_desc;
 203                otg_desc[1] = NULL;
 204        }
 205
 206        status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
 207        if (status < 0)
 208                goto fail_otg_desc;
 209
 210        usb_composite_overwrite_options(cdev, &coverwrite);
 211        dev_info(&cdev->gadget->dev,
 212                 DRIVER_DESC ", version: " DRIVER_VERSION "\n");
 213        set_bit(0, &msg_registered);
 214        return 0;
 215
 216fail_otg_desc:
 217        kfree(otg_desc[0]);
 218        otg_desc[0] = NULL;
 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        kfree(otg_desc[0]);
 237        otg_desc[0] = NULL;
 238
 239        return 0;
 240}
 241
 242/****************************** Some noise ******************************/
 243
 244static struct usb_composite_driver msg_driver = {
 245        .name           = "g_mass_storage",
 246        .dev            = &msg_device_desc,
 247        .max_speed      = USB_SPEED_SUPER,
 248        .needs_serial   = 1,
 249        .strings        = dev_strings,
 250        .bind           = msg_bind,
 251        .unbind         = msg_unbind,
 252};
 253
 254MODULE_DESCRIPTION(DRIVER_DESC);
 255MODULE_AUTHOR("Michal Nazarewicz");
 256MODULE_LICENSE("GPL");
 257
 258static int __init msg_init(void)
 259{
 260        return usb_composite_probe(&msg_driver);
 261}
 262module_init(msg_init);
 263
 264static void msg_cleanup(void)
 265{
 266        if (test_and_clear_bit(0, &msg_registered))
 267                usb_composite_unregister(&msg_driver);
 268}
 269module_exit(msg_cleanup);
 270