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 = fsg_common_run_thread(opts->common);
 136        if (ret)
 137                goto put_func;
 138
 139        ret = usb_add_function(c, f_msg);
 140        if (ret)
 141                goto put_func;
 142
 143        return 0;
 144
 145put_func:
 146        usb_put_function(f_msg);
 147        return ret;
 148}
 149
 150static struct usb_configuration msg_config_driver = {
 151        .label                  = "Linux File-Backed Storage",
 152        .bConfigurationValue    = 1,
 153        .bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
 154};
 155
 156
 157/****************************** Gadget Bind ******************************/
 158
 159static int msg_bind(struct usb_composite_dev *cdev)
 160{
 161        static const struct fsg_operations ops = {
 162                .thread_exits = msg_thread_exits,
 163        };
 164        struct fsg_opts *opts;
 165        struct fsg_config config;
 166        int status;
 167
 168        fi_msg = usb_get_function_instance("mass_storage");
 169        if (IS_ERR(fi_msg))
 170                return PTR_ERR(fi_msg);
 171
 172        fsg_config_from_params(&config, &mod_data, fsg_num_buffers);
 173        opts = fsg_opts_from_func_inst(fi_msg);
 174
 175        opts->no_configfs = true;
 176        status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers);
 177        if (status)
 178                goto fail;
 179
 180        fsg_common_set_ops(opts->common, &ops);
 181
 182        status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
 183        if (status)
 184                goto fail_set_cdev;
 185
 186        fsg_common_set_sysfs(opts->common, true);
 187        status = fsg_common_create_luns(opts->common, &config);
 188        if (status)
 189                goto fail_set_cdev;
 190
 191        fsg_common_set_inquiry_string(opts->common, config.vendor_name,
 192                                      config.product_name);
 193
 194        status = usb_string_ids_tab(cdev, strings_dev);
 195        if (status < 0)
 196                goto fail_string_ids;
 197        msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 198
 199        if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
 200                struct usb_descriptor_header *usb_desc;
 201
 202                usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
 203                if (!usb_desc)
 204                        goto fail_string_ids;
 205                usb_otg_descriptor_init(cdev->gadget, usb_desc);
 206                otg_desc[0] = usb_desc;
 207                otg_desc[1] = NULL;
 208        }
 209
 210        status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
 211        if (status < 0)
 212                goto fail_otg_desc;
 213
 214        usb_composite_overwrite_options(cdev, &coverwrite);
 215        dev_info(&cdev->gadget->dev,
 216                 DRIVER_DESC ", version: " DRIVER_VERSION "\n");
 217        set_bit(0, &msg_registered);
 218        return 0;
 219
 220fail_otg_desc:
 221        kfree(otg_desc[0]);
 222        otg_desc[0] = NULL;
 223fail_string_ids:
 224        fsg_common_remove_luns(opts->common);
 225fail_set_cdev:
 226        fsg_common_free_buffers(opts->common);
 227fail:
 228        usb_put_function_instance(fi_msg);
 229        return status;
 230}
 231
 232static int msg_unbind(struct usb_composite_dev *cdev)
 233{
 234        if (!IS_ERR(f_msg))
 235                usb_put_function(f_msg);
 236
 237        if (!IS_ERR(fi_msg))
 238                usb_put_function_instance(fi_msg);
 239
 240        kfree(otg_desc[0]);
 241        otg_desc[0] = NULL;
 242
 243        return 0;
 244}
 245
 246/****************************** Some noise ******************************/
 247
 248static struct usb_composite_driver msg_driver = {
 249        .name           = "g_mass_storage",
 250        .dev            = &msg_device_desc,
 251        .max_speed      = USB_SPEED_SUPER,
 252        .needs_serial   = 1,
 253        .strings        = dev_strings,
 254        .bind           = msg_bind,
 255        .unbind         = msg_unbind,
 256};
 257
 258MODULE_DESCRIPTION(DRIVER_DESC);
 259MODULE_AUTHOR("Michal Nazarewicz");
 260MODULE_LICENSE("GPL");
 261
 262static int __init msg_init(void)
 263{
 264        return usb_composite_probe(&msg_driver);
 265}
 266module_init(msg_init);
 267
 268static void msg_cleanup(void)
 269{
 270        if (test_and_clear_bit(0, &msg_registered))
 271                usb_composite_unregister(&msg_driver);
 272}
 273module_exit(msg_cleanup);
 274