linux/drivers/usb/gadget/legacy/g_ffs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * g_ffs.c -- user mode file system API for USB composite function controllers
   4 *
   5 * Copyright (C) 2010 Samsung Electronics
   6 * Author: Michal Nazarewicz <mina86@mina86.com>
   7 */
   8
   9#define pr_fmt(fmt) "g_ffs: " fmt
  10
  11#include <linux/module.h>
  12
  13#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
  14#include <linux/netdevice.h>
  15
  16#  if defined USB_ETH_RNDIS
  17#    undef USB_ETH_RNDIS
  18#  endif
  19#  ifdef CONFIG_USB_FUNCTIONFS_RNDIS
  20#    define USB_ETH_RNDIS y
  21#  endif
  22
  23#  include "u_ecm.h"
  24#  include "u_gether.h"
  25#  ifdef USB_ETH_RNDIS
  26#    include "u_rndis.h"
  27#    include "rndis.h"
  28#  endif
  29#  include "u_ether.h"
  30
  31USB_ETHERNET_MODULE_PARAMETERS();
  32
  33#  ifdef CONFIG_USB_FUNCTIONFS_ETH
  34static int eth_bind_config(struct usb_configuration *c);
  35static struct usb_function_instance *fi_ecm;
  36static struct usb_function *f_ecm;
  37static struct usb_function_instance *fi_geth;
  38static struct usb_function *f_geth;
  39#  endif
  40#  ifdef CONFIG_USB_FUNCTIONFS_RNDIS
  41static int bind_rndis_config(struct usb_configuration *c);
  42static struct usb_function_instance *fi_rndis;
  43static struct usb_function *f_rndis;
  44#  endif
  45#endif
  46
  47#include "u_fs.h"
  48
  49#define DRIVER_NAME     "g_ffs"
  50#define DRIVER_DESC     "USB Function Filesystem"
  51#define DRIVER_VERSION  "24 Aug 2004"
  52
  53MODULE_DESCRIPTION(DRIVER_DESC);
  54MODULE_AUTHOR("Michal Nazarewicz");
  55MODULE_LICENSE("GPL");
  56
  57#define GFS_VENDOR_ID   0x1d6b  /* Linux Foundation */
  58#define GFS_PRODUCT_ID  0x0105  /* FunctionFS Gadget */
  59
  60#define GFS_MAX_DEVS    10
  61
  62USB_GADGET_COMPOSITE_OPTIONS();
  63
  64static struct usb_device_descriptor gfs_dev_desc = {
  65        .bLength                = sizeof gfs_dev_desc,
  66        .bDescriptorType        = USB_DT_DEVICE,
  67
  68        /* .bcdUSB = DYNAMIC */
  69        .bDeviceClass           = USB_CLASS_PER_INTERFACE,
  70
  71        .idVendor               = cpu_to_le16(GFS_VENDOR_ID),
  72        .idProduct              = cpu_to_le16(GFS_PRODUCT_ID),
  73};
  74
  75static char *func_names[GFS_MAX_DEVS];
  76static unsigned int func_num;
  77
  78module_param_named(bDeviceClass,    gfs_dev_desc.bDeviceClass,    byte,   0644);
  79MODULE_PARM_DESC(bDeviceClass, "USB Device class");
  80module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte,   0644);
  81MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
  82module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte,   0644);
  83MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
  84module_param_array_named(functions, func_names, charp, &func_num, 0);
  85MODULE_PARM_DESC(functions, "USB Functions list");
  86
  87static const struct usb_descriptor_header *gfs_otg_desc[2];
  88
  89/* String IDs are assigned dynamically */
  90static struct usb_string gfs_strings[] = {
  91        [USB_GADGET_MANUFACTURER_IDX].s = "",
  92        [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
  93        [USB_GADGET_SERIAL_IDX].s = "",
  94#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
  95        { .s = "FunctionFS + RNDIS" },
  96#endif
  97#ifdef CONFIG_USB_FUNCTIONFS_ETH
  98        { .s = "FunctionFS + ECM" },
  99#endif
 100#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
 101        { .s = "FunctionFS" },
 102#endif
 103        {  } /* end of list */
 104};
 105
 106static struct usb_gadget_strings *gfs_dev_strings[] = {
 107        &(struct usb_gadget_strings) {
 108                .language       = 0x0409,       /* en-us */
 109                .strings        = gfs_strings,
 110        },
 111        NULL,
 112};
 113
 114struct gfs_configuration {
 115        struct usb_configuration c;
 116        int (*eth)(struct usb_configuration *c);
 117        int num;
 118};
 119
 120static struct gfs_configuration gfs_configurations[] = {
 121#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 122        {
 123                .eth            = bind_rndis_config,
 124        },
 125#endif
 126
 127#ifdef CONFIG_USB_FUNCTIONFS_ETH
 128        {
 129                .eth            = eth_bind_config,
 130        },
 131#endif
 132
 133#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
 134        {
 135        },
 136#endif
 137};
 138
 139static void *functionfs_acquire_dev(struct ffs_dev *dev);
 140static void functionfs_release_dev(struct ffs_dev *dev);
 141static int functionfs_ready_callback(struct ffs_data *ffs);
 142static void functionfs_closed_callback(struct ffs_data *ffs);
 143static int gfs_bind(struct usb_composite_dev *cdev);
 144static int gfs_unbind(struct usb_composite_dev *cdev);
 145static int gfs_do_config(struct usb_configuration *c);
 146
 147
 148static struct usb_composite_driver gfs_driver = {
 149        .name           = DRIVER_NAME,
 150        .dev            = &gfs_dev_desc,
 151        .strings        = gfs_dev_strings,
 152        .max_speed      = USB_SPEED_SUPER,
 153        .bind           = gfs_bind,
 154        .unbind         = gfs_unbind,
 155};
 156
 157static unsigned int missing_funcs;
 158static bool gfs_registered;
 159static bool gfs_single_func;
 160static struct usb_function_instance **fi_ffs;
 161static struct usb_function **f_ffs[] = {
 162#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 163        NULL,
 164#endif
 165
 166#ifdef CONFIG_USB_FUNCTIONFS_ETH
 167        NULL,
 168#endif
 169
 170#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
 171        NULL,
 172#endif
 173};
 174
 175#define N_CONF ARRAY_SIZE(f_ffs)
 176
 177static int __init gfs_init(void)
 178{
 179        struct f_fs_opts *opts;
 180        int i;
 181        int ret = 0;
 182
 183        ENTER();
 184
 185        if (func_num < 2) {
 186                gfs_single_func = true;
 187                func_num = 1;
 188        }
 189
 190        /*
 191         * Allocate in one chunk for easier maintenance
 192         */
 193        f_ffs[0] = kcalloc(func_num * N_CONF, sizeof(*f_ffs), GFP_KERNEL);
 194        if (!f_ffs[0]) {
 195                ret = -ENOMEM;
 196                goto no_func;
 197        }
 198        for (i = 1; i < N_CONF; ++i)
 199                f_ffs[i] = f_ffs[0] + i * func_num;
 200
 201        fi_ffs = kcalloc(func_num, sizeof(*fi_ffs), GFP_KERNEL);
 202        if (!fi_ffs) {
 203                ret = -ENOMEM;
 204                goto no_func;
 205        }
 206
 207        for (i = 0; i < func_num; i++) {
 208                fi_ffs[i] = usb_get_function_instance("ffs");
 209                if (IS_ERR(fi_ffs[i])) {
 210                        ret = PTR_ERR(fi_ffs[i]);
 211                        --i;
 212                        goto no_dev;
 213                }
 214                opts = to_f_fs_opts(fi_ffs[i]);
 215                if (gfs_single_func)
 216                        ret = ffs_single_dev(opts->dev);
 217                else
 218                        ret = ffs_name_dev(opts->dev, func_names[i]);
 219                if (ret)
 220                        goto no_dev;
 221                opts->dev->ffs_ready_callback = functionfs_ready_callback;
 222                opts->dev->ffs_closed_callback = functionfs_closed_callback;
 223                opts->dev->ffs_acquire_dev_callback = functionfs_acquire_dev;
 224                opts->dev->ffs_release_dev_callback = functionfs_release_dev;
 225                opts->no_configfs = true;
 226        }
 227
 228        missing_funcs = func_num;
 229
 230        return 0;
 231no_dev:
 232        while (i >= 0)
 233                usb_put_function_instance(fi_ffs[i--]);
 234        kfree(fi_ffs);
 235no_func:
 236        kfree(f_ffs[0]);
 237        return ret;
 238}
 239module_init(gfs_init);
 240
 241static void __exit gfs_exit(void)
 242{
 243        int i;
 244
 245        ENTER();
 246
 247        if (gfs_registered)
 248                usb_composite_unregister(&gfs_driver);
 249        gfs_registered = false;
 250
 251        kfree(f_ffs[0]);
 252
 253        for (i = 0; i < func_num; i++)
 254                usb_put_function_instance(fi_ffs[i]);
 255
 256        kfree(fi_ffs);
 257}
 258module_exit(gfs_exit);
 259
 260static void *functionfs_acquire_dev(struct ffs_dev *dev)
 261{
 262        if (!try_module_get(THIS_MODULE))
 263                return ERR_PTR(-ENOENT);
 264
 265        return NULL;
 266}
 267
 268static void functionfs_release_dev(struct ffs_dev *dev)
 269{
 270        module_put(THIS_MODULE);
 271}
 272
 273/*
 274 * The caller of this function takes ffs_lock
 275 */
 276static int functionfs_ready_callback(struct ffs_data *ffs)
 277{
 278        int ret = 0;
 279
 280        if (--missing_funcs)
 281                return 0;
 282
 283        if (gfs_registered)
 284                return -EBUSY;
 285
 286        gfs_registered = true;
 287
 288        ret = usb_composite_probe(&gfs_driver);
 289        if (unlikely(ret < 0)) {
 290                ++missing_funcs;
 291                gfs_registered = false;
 292        }
 293
 294        return ret;
 295}
 296
 297/*
 298 * The caller of this function takes ffs_lock
 299 */
 300static void functionfs_closed_callback(struct ffs_data *ffs)
 301{
 302        missing_funcs++;
 303
 304        if (gfs_registered)
 305                usb_composite_unregister(&gfs_driver);
 306        gfs_registered = false;
 307}
 308
 309/*
 310 * It is assumed that gfs_bind is called from a context where ffs_lock is held
 311 */
 312static int gfs_bind(struct usb_composite_dev *cdev)
 313{
 314#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
 315        struct net_device *net;
 316#endif
 317        int ret, i;
 318
 319        ENTER();
 320
 321        if (missing_funcs)
 322                return -ENODEV;
 323#if defined CONFIG_USB_FUNCTIONFS_ETH
 324        if (can_support_ecm(cdev->gadget)) {
 325                struct f_ecm_opts *ecm_opts;
 326
 327                fi_ecm = usb_get_function_instance("ecm");
 328                if (IS_ERR(fi_ecm))
 329                        return PTR_ERR(fi_ecm);
 330                ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
 331                net = ecm_opts->net;
 332        } else {
 333                struct f_gether_opts *geth_opts;
 334
 335                fi_geth = usb_get_function_instance("geth");
 336                if (IS_ERR(fi_geth))
 337                        return PTR_ERR(fi_geth);
 338                geth_opts = container_of(fi_geth, struct f_gether_opts,
 339                                         func_inst);
 340                net = geth_opts->net;
 341        }
 342#endif
 343
 344#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 345        {
 346                fi_rndis = usb_get_function_instance("rndis");
 347                if (IS_ERR(fi_rndis)) {
 348                        ret = PTR_ERR(fi_rndis);
 349                        goto error;
 350                }
 351#ifndef CONFIG_USB_FUNCTIONFS_ETH
 352                net = container_of(fi_rndis, struct f_rndis_opts,
 353                                   func_inst)->net;
 354#endif
 355        }
 356#endif
 357
 358#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
 359        gether_set_qmult(net, qmult);
 360        if (!gether_set_host_addr(net, host_addr))
 361                pr_info("using host ethernet address: %s", host_addr);
 362        if (!gether_set_dev_addr(net, dev_addr))
 363                pr_info("using self ethernet address: %s", dev_addr);
 364#endif
 365
 366#if defined CONFIG_USB_FUNCTIONFS_RNDIS && defined CONFIG_USB_FUNCTIONFS_ETH
 367        gether_set_gadget(net, cdev->gadget);
 368        ret = gether_register_netdev(net);
 369        if (ret)
 370                goto error_rndis;
 371
 372        if (can_support_ecm(cdev->gadget)) {
 373                struct f_ecm_opts *ecm_opts;
 374
 375                ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
 376                ecm_opts->bound = true;
 377        } else {
 378                struct f_gether_opts *geth_opts;
 379
 380                geth_opts = container_of(fi_geth, struct f_gether_opts,
 381                                         func_inst);
 382                geth_opts->bound = true;
 383        }
 384
 385        rndis_borrow_net(fi_rndis, net);
 386#endif
 387
 388        /* TODO: gstrings_attach? */
 389        ret = usb_string_ids_tab(cdev, gfs_strings);
 390        if (unlikely(ret < 0))
 391                goto error_rndis;
 392        gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
 393
 394        if (gadget_is_otg(cdev->gadget) && !gfs_otg_desc[0]) {
 395                struct usb_descriptor_header *usb_desc;
 396
 397                usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
 398                if (!usb_desc)
 399                        goto error_rndis;
 400                usb_otg_descriptor_init(cdev->gadget, usb_desc);
 401                gfs_otg_desc[0] = usb_desc;
 402                gfs_otg_desc[1] = NULL;
 403        }
 404
 405        for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
 406                struct gfs_configuration *c = gfs_configurations + i;
 407                int sid = USB_GADGET_FIRST_AVAIL_IDX + i;
 408
 409                c->c.label                      = gfs_strings[sid].s;
 410                c->c.iConfiguration             = gfs_strings[sid].id;
 411                c->c.bConfigurationValue        = 1 + i;
 412                c->c.bmAttributes               = USB_CONFIG_ATT_SELFPOWER;
 413
 414                c->num = i;
 415
 416                ret = usb_add_config(cdev, &c->c, gfs_do_config);
 417                if (unlikely(ret < 0))
 418                        goto error_unbind;
 419        }
 420        usb_composite_overwrite_options(cdev, &coverwrite);
 421        return 0;
 422
 423/* TODO */
 424error_unbind:
 425        kfree(gfs_otg_desc[0]);
 426        gfs_otg_desc[0] = NULL;
 427error_rndis:
 428#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 429        usb_put_function_instance(fi_rndis);
 430error:
 431#endif
 432#if defined CONFIG_USB_FUNCTIONFS_ETH
 433        if (can_support_ecm(cdev->gadget))
 434                usb_put_function_instance(fi_ecm);
 435        else
 436                usb_put_function_instance(fi_geth);
 437#endif
 438        return ret;
 439}
 440
 441/*
 442 * It is assumed that gfs_unbind is called from a context where ffs_lock is held
 443 */
 444static int gfs_unbind(struct usb_composite_dev *cdev)
 445{
 446        int i;
 447
 448        ENTER();
 449
 450
 451#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 452        usb_put_function(f_rndis);
 453        usb_put_function_instance(fi_rndis);
 454#endif
 455
 456#if defined CONFIG_USB_FUNCTIONFS_ETH
 457        if (can_support_ecm(cdev->gadget)) {
 458                usb_put_function(f_ecm);
 459                usb_put_function_instance(fi_ecm);
 460        } else {
 461                usb_put_function(f_geth);
 462                usb_put_function_instance(fi_geth);
 463        }
 464#endif
 465        for (i = 0; i < N_CONF * func_num; ++i)
 466                usb_put_function(*(f_ffs[0] + i));
 467
 468        kfree(gfs_otg_desc[0]);
 469        gfs_otg_desc[0] = NULL;
 470
 471        return 0;
 472}
 473
 474/*
 475 * It is assumed that gfs_do_config is called from a context where
 476 * ffs_lock is held
 477 */
 478static int gfs_do_config(struct usb_configuration *c)
 479{
 480        struct gfs_configuration *gc =
 481                container_of(c, struct gfs_configuration, c);
 482        int i;
 483        int ret;
 484
 485        if (missing_funcs)
 486                return -ENODEV;
 487
 488        if (gadget_is_otg(c->cdev->gadget)) {
 489                c->descriptors = gfs_otg_desc;
 490                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 491        }
 492
 493        if (gc->eth) {
 494                ret = gc->eth(c);
 495                if (unlikely(ret < 0))
 496                        return ret;
 497        }
 498
 499        for (i = 0; i < func_num; i++) {
 500                f_ffs[gc->num][i] = usb_get_function(fi_ffs[i]);
 501                if (IS_ERR(f_ffs[gc->num][i])) {
 502                        ret = PTR_ERR(f_ffs[gc->num][i]);
 503                        goto error;
 504                }
 505                ret = usb_add_function(c, f_ffs[gc->num][i]);
 506                if (ret < 0) {
 507                        usb_put_function(f_ffs[gc->num][i]);
 508                        goto error;
 509                }
 510        }
 511
 512        /*
 513         * After previous do_configs there may be some invalid
 514         * pointers in c->interface array.  This happens every time
 515         * a user space function with fewer interfaces than a user
 516         * space function that was run before the new one is run.  The
 517         * compasit's set_config() assumes that if there is no more
 518         * then MAX_CONFIG_INTERFACES interfaces in a configuration
 519         * then there is a NULL pointer after the last interface in
 520         * c->interface array.  We need to make sure this is true.
 521         */
 522        if (c->next_interface_id < ARRAY_SIZE(c->interface))
 523                c->interface[c->next_interface_id] = NULL;
 524
 525        return 0;
 526error:
 527        while (--i >= 0) {
 528                if (!IS_ERR(f_ffs[gc->num][i]))
 529                        usb_remove_function(c, f_ffs[gc->num][i]);
 530                usb_put_function(f_ffs[gc->num][i]);
 531        }
 532        return ret;
 533}
 534
 535#ifdef CONFIG_USB_FUNCTIONFS_ETH
 536
 537static int eth_bind_config(struct usb_configuration *c)
 538{
 539        int status = 0;
 540
 541        if (can_support_ecm(c->cdev->gadget)) {
 542                f_ecm = usb_get_function(fi_ecm);
 543                if (IS_ERR(f_ecm))
 544                        return PTR_ERR(f_ecm);
 545
 546                status = usb_add_function(c, f_ecm);
 547                if (status < 0)
 548                        usb_put_function(f_ecm);
 549
 550        } else {
 551                f_geth = usb_get_function(fi_geth);
 552                if (IS_ERR(f_geth))
 553                        return PTR_ERR(f_geth);
 554
 555                status = usb_add_function(c, f_geth);
 556                if (status < 0)
 557                        usb_put_function(f_geth);
 558        }
 559        return status;
 560}
 561
 562#endif
 563
 564#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 565
 566static int bind_rndis_config(struct usb_configuration *c)
 567{
 568        int status = 0;
 569
 570        f_rndis = usb_get_function(fi_rndis);
 571        if (IS_ERR(f_rndis))
 572                return PTR_ERR(f_rndis);
 573
 574        status = usb_add_function(c, f_rndis);
 575        if (status < 0)
 576                usb_put_function(f_rndis);
 577
 578        return status;
 579}
 580
 581#endif
 582