linux/drivers/usb/gadget/g_ffs.c
<<
>>
Prefs
   1/*
   2 * g_ffs.c -- user mode file system API for USB composite function controllers
   3 *
   4 * Copyright (C) 2010 Samsung Electronics
   5 * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20 */
  21
  22#define pr_fmt(fmt) "g_ffs: " fmt
  23
  24#include <linux/module.h>
  25#include <linux/utsname.h>
  26
  27/*
  28 * kbuild is not very cooperative with respect to linking separately
  29 * compiled library objects into one module.  So for now we won't use
  30 * separate compilation ... ensuring init/exit sections work to shrink
  31 * the runtime footprint, and giving us at least some parts of what
  32 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  33 */
  34
  35#include "composite.c"
  36#include "usbstring.c"
  37#include "config.c"
  38#include "epautoconf.c"
  39
  40#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
  41#  if defined USB_ETH_RNDIS
  42#    undef USB_ETH_RNDIS
  43#  endif
  44#  ifdef CONFIG_USB_FUNCTIONFS_RNDIS
  45#    define USB_ETH_RNDIS y
  46#  endif
  47
  48#  include "f_ecm.c"
  49#  include "f_subset.c"
  50#  ifdef USB_ETH_RNDIS
  51#    include "f_rndis.c"
  52#    include "rndis.c"
  53#  endif
  54#  include "u_ether.c"
  55
  56static u8 gfs_hostaddr[ETH_ALEN];
  57#  ifdef CONFIG_USB_FUNCTIONFS_ETH
  58static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
  59#  endif
  60#else
  61#  define gether_cleanup() do { } while (0)
  62#  define gether_setup(gadget, hostaddr)   ((int)0)
  63#  define gfs_hostaddr NULL
  64#endif
  65
  66#include "f_fs.c"
  67
  68#define DRIVER_NAME     "g_ffs"
  69#define DRIVER_DESC     "USB Function Filesystem"
  70#define DRIVER_VERSION  "24 Aug 2004"
  71
  72MODULE_DESCRIPTION(DRIVER_DESC);
  73MODULE_AUTHOR("Michal Nazarewicz");
  74MODULE_LICENSE("GPL");
  75
  76#define GFS_VENDOR_ID   0x1d6b  /* Linux Foundation */
  77#define GFS_PRODUCT_ID  0x0105  /* FunctionFS Gadget */
  78
  79static struct usb_device_descriptor gfs_dev_desc = {
  80        .bLength                = sizeof gfs_dev_desc,
  81        .bDescriptorType        = USB_DT_DEVICE,
  82
  83        .bcdUSB                 = cpu_to_le16(0x0200),
  84        .bDeviceClass           = USB_CLASS_PER_INTERFACE,
  85
  86        .idVendor               = cpu_to_le16(GFS_VENDOR_ID),
  87        .idProduct              = cpu_to_le16(GFS_PRODUCT_ID),
  88};
  89
  90module_param_named(bDeviceClass,    gfs_dev_desc.bDeviceClass,    byte,   0644);
  91MODULE_PARM_DESC(bDeviceClass, "USB Device class");
  92module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte,   0644);
  93MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
  94module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte,   0644);
  95MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
  96
  97static const struct usb_descriptor_header *gfs_otg_desc[] = {
  98        (const struct usb_descriptor_header *)
  99        &(const struct usb_otg_descriptor) {
 100                .bLength                = sizeof(struct usb_otg_descriptor),
 101                .bDescriptorType        = USB_DT_OTG,
 102
 103                /*
 104                 * REVISIT SRP-only hardware is possible, although
 105                 * it would not be called "OTG" ...
 106                 */
 107                .bmAttributes           = USB_OTG_SRP | USB_OTG_HNP,
 108        },
 109
 110        NULL
 111};
 112
 113/* String IDs are assigned dynamically */
 114static struct usb_string gfs_strings[] = {
 115#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 116        { .s = "FunctionFS + RNDIS" },
 117#endif
 118#ifdef CONFIG_USB_FUNCTIONFS_ETH
 119        { .s = "FunctionFS + ECM" },
 120#endif
 121#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
 122        { .s = "FunctionFS" },
 123#endif
 124        {  } /* end of list */
 125};
 126
 127static struct usb_gadget_strings *gfs_dev_strings[] = {
 128        &(struct usb_gadget_strings) {
 129                .language       = 0x0409,       /* en-us */
 130                .strings        = gfs_strings,
 131        },
 132        NULL,
 133};
 134
 135struct gfs_configuration {
 136        struct usb_configuration c;
 137        int (*eth)(struct usb_configuration *c, u8 *ethaddr);
 138} gfs_configurations[] = {
 139#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 140        {
 141                .eth            = rndis_bind_config,
 142        },
 143#endif
 144
 145#ifdef CONFIG_USB_FUNCTIONFS_ETH
 146        {
 147                .eth            = eth_bind_config,
 148        },
 149#endif
 150
 151#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
 152        {
 153        },
 154#endif
 155};
 156
 157static int gfs_bind(struct usb_composite_dev *cdev);
 158static int gfs_unbind(struct usb_composite_dev *cdev);
 159static int gfs_do_config(struct usb_configuration *c);
 160
 161static struct usb_composite_driver gfs_driver = {
 162        .name           = DRIVER_NAME,
 163        .dev            = &gfs_dev_desc,
 164        .strings        = gfs_dev_strings,
 165        .unbind         = gfs_unbind,
 166        .iProduct       = DRIVER_DESC,
 167};
 168
 169static struct ffs_data *gfs_ffs_data;
 170static unsigned long gfs_registered;
 171
 172static int  gfs_init(void)
 173{
 174        ENTER();
 175
 176        return functionfs_init();
 177}
 178module_init(gfs_init);
 179
 180static void  gfs_exit(void)
 181{
 182        ENTER();
 183
 184        if (test_and_clear_bit(0, &gfs_registered))
 185                usb_composite_unregister(&gfs_driver);
 186
 187        functionfs_cleanup();
 188}
 189module_exit(gfs_exit);
 190
 191static int functionfs_ready_callback(struct ffs_data *ffs)
 192{
 193        int ret;
 194
 195        ENTER();
 196
 197        if (WARN_ON(test_and_set_bit(0, &gfs_registered)))
 198                return -EBUSY;
 199
 200        gfs_ffs_data = ffs;
 201        ret = usb_composite_probe(&gfs_driver, gfs_bind);
 202        if (unlikely(ret < 0))
 203                clear_bit(0, &gfs_registered);
 204        return ret;
 205}
 206
 207static void functionfs_closed_callback(struct ffs_data *ffs)
 208{
 209        ENTER();
 210
 211        if (test_and_clear_bit(0, &gfs_registered))
 212                usb_composite_unregister(&gfs_driver);
 213}
 214
 215static int functionfs_check_dev_callback(const char *dev_name)
 216{
 217        return 0;
 218}
 219
 220static int gfs_bind(struct usb_composite_dev *cdev)
 221{
 222        int ret, i;
 223
 224        ENTER();
 225
 226        if (WARN_ON(!gfs_ffs_data))
 227                return -ENODEV;
 228
 229        ret = gether_setup(cdev->gadget, gfs_hostaddr);
 230        if (unlikely(ret < 0))
 231                goto error_quick;
 232
 233        ret = usb_string_ids_tab(cdev, gfs_strings);
 234        if (unlikely(ret < 0))
 235                goto error;
 236
 237        ret = functionfs_bind(gfs_ffs_data, cdev);
 238        if (unlikely(ret < 0))
 239                goto error;
 240
 241        for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
 242                struct gfs_configuration *c = gfs_configurations + i;
 243
 244                c->c.label                      = gfs_strings[i].s;
 245                c->c.iConfiguration             = gfs_strings[i].id;
 246                c->c.bConfigurationValue        = 1 + i;
 247                c->c.bmAttributes               = USB_CONFIG_ATT_SELFPOWER;
 248
 249                ret = usb_add_config(cdev, &c->c, gfs_do_config);
 250                if (unlikely(ret < 0))
 251                        goto error_unbind;
 252        }
 253
 254        return 0;
 255
 256error_unbind:
 257        functionfs_unbind(gfs_ffs_data);
 258error:
 259        gether_cleanup();
 260error_quick:
 261        gfs_ffs_data = NULL;
 262        return ret;
 263}
 264
 265static int gfs_unbind(struct usb_composite_dev *cdev)
 266{
 267        ENTER();
 268
 269        /*
 270         * We may have been called in an error recovery from
 271         * composite_bind() after gfs_unbind() failure so we need to
 272         * check if gfs_ffs_data is not NULL since gfs_bind() handles
 273         * all error recovery itself.  I'd rather we werent called
 274         * from composite on orror recovery, but what you're gonna
 275         * do...?
 276         */
 277        if (gfs_ffs_data) {
 278                gether_cleanup();
 279                functionfs_unbind(gfs_ffs_data);
 280                gfs_ffs_data = NULL;
 281        }
 282
 283        return 0;
 284}
 285
 286static int gfs_do_config(struct usb_configuration *c)
 287{
 288        struct gfs_configuration *gc =
 289                container_of(c, struct gfs_configuration, c);
 290        int ret;
 291
 292        if (WARN_ON(!gfs_ffs_data))
 293                return -ENODEV;
 294
 295        if (gadget_is_otg(c->cdev->gadget)) {
 296                c->descriptors = gfs_otg_desc;
 297                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 298        }
 299
 300        if (gc->eth) {
 301                ret = gc->eth(c, gfs_hostaddr);
 302                if (unlikely(ret < 0))
 303                        return ret;
 304        }
 305
 306        ret = functionfs_bind_config(c->cdev, c, gfs_ffs_data);
 307        if (unlikely(ret < 0))
 308                return ret;
 309
 310        /*
 311         * After previous do_configs there may be some invalid
 312         * pointers in c->interface array.  This happens every time
 313         * a user space function with fewer interfaces than a user
 314         * space function that was run before the new one is run.  The
 315         * compasit's set_config() assumes that if there is no more
 316         * then MAX_CONFIG_INTERFACES interfaces in a configuration
 317         * then there is a NULL pointer after the last interface in
 318         * c->interface array.  We need to make sure this is true.
 319         */
 320        if (c->next_interface_id < ARRAY_SIZE(c->interface))
 321                c->interface[c->next_interface_id] = NULL;
 322
 323        return 0;
 324}
 325
 326#ifdef CONFIG_USB_FUNCTIONFS_ETH
 327
 328static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 329{
 330        return can_support_ecm(c->cdev->gadget)
 331                ? ecm_bind_config(c, ethaddr)
 332                : geth_bind_config(c, ethaddr);
 333}
 334
 335#endif
 336