linux/drivers/usb/gadget/serial.c
<<
>>
Prefs
   1/*
   2 * serial.c -- USB gadget serial driver
   3 *
   4 * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
   5 * Copyright (C) 2008 by David Brownell
   6 * Copyright (C) 2008 by Nokia Corporation
   7 *
   8 * This software is distributed under the terms of the GNU General
   9 * Public License ("GPL") as published by the Free Software Foundation,
  10 * either version 2 of that License or (at your option) any later version.
  11 */
  12
  13#include <linux/kernel.h>
  14#include <linux/device.h>
  15#include <linux/module.h>
  16#include <linux/tty.h>
  17#include <linux/tty_flip.h>
  18
  19#include "u_serial.h"
  20#include "gadget_chips.h"
  21
  22
  23/* Defines */
  24
  25#define GS_VERSION_STR                  "v2.4"
  26#define GS_VERSION_NUM                  0x2400
  27
  28#define GS_LONG_NAME                    "Gadget Serial"
  29#define GS_VERSION_NAME                 GS_LONG_NAME " " GS_VERSION_STR
  30
  31/*-------------------------------------------------------------------------*/
  32USB_GADGET_COMPOSITE_OPTIONS();
  33
  34/* Thanks to NetChip Technologies for donating this product ID.
  35*
  36* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
  37* Instead:  allocate your own, using normal USB-IF procedures.
  38*/
  39#define GS_VENDOR_ID                    0x0525  /* NetChip */
  40#define GS_PRODUCT_ID                   0xa4a6  /* Linux-USB Serial Gadget */
  41#define GS_CDC_PRODUCT_ID               0xa4a7  /* ... as CDC-ACM */
  42#define GS_CDC_OBEX_PRODUCT_ID          0xa4a9  /* ... as CDC-OBEX */
  43
  44/* string IDs are assigned dynamically */
  45
  46#define STRING_DESCRIPTION_IDX          USB_GADGET_FIRST_AVAIL_IDX
  47
  48static struct usb_string strings_dev[] = {
  49        [USB_GADGET_MANUFACTURER_IDX].s = "",
  50        [USB_GADGET_PRODUCT_IDX].s = GS_VERSION_NAME,
  51        [USB_GADGET_SERIAL_IDX].s = "",
  52        [STRING_DESCRIPTION_IDX].s = NULL /* updated; f(use_acm) */,
  53        {  } /* end of list */
  54};
  55
  56static struct usb_gadget_strings stringtab_dev = {
  57        .language       = 0x0409,       /* en-us */
  58        .strings        = strings_dev,
  59};
  60
  61static struct usb_gadget_strings *dev_strings[] = {
  62        &stringtab_dev,
  63        NULL,
  64};
  65
  66static struct usb_device_descriptor device_desc = {
  67        .bLength =              USB_DT_DEVICE_SIZE,
  68        .bDescriptorType =      USB_DT_DEVICE,
  69        .bcdUSB =               cpu_to_le16(0x0200),
  70        /* .bDeviceClass = f(use_acm) */
  71        .bDeviceSubClass =      0,
  72        .bDeviceProtocol =      0,
  73        /* .bMaxPacketSize0 = f(hardware) */
  74        .idVendor =             cpu_to_le16(GS_VENDOR_ID),
  75        /* .idProduct = f(use_acm) */
  76        .bcdDevice = cpu_to_le16(GS_VERSION_NUM),
  77        /* .iManufacturer = DYNAMIC */
  78        /* .iProduct = DYNAMIC */
  79        .bNumConfigurations =   1,
  80};
  81
  82static struct usb_otg_descriptor otg_descriptor = {
  83        .bLength =              sizeof otg_descriptor,
  84        .bDescriptorType =      USB_DT_OTG,
  85
  86        /* REVISIT SRP-only hardware is possible, although
  87         * it would not be called "OTG" ...
  88         */
  89        .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
  90};
  91
  92static const struct usb_descriptor_header *otg_desc[] = {
  93        (struct usb_descriptor_header *) &otg_descriptor,
  94        NULL,
  95};
  96
  97/*-------------------------------------------------------------------------*/
  98
  99/* Module */
 100MODULE_DESCRIPTION(GS_VERSION_NAME);
 101MODULE_AUTHOR("Al Borchers");
 102MODULE_AUTHOR("David Brownell");
 103MODULE_LICENSE("GPL");
 104
 105static bool use_acm = true;
 106module_param(use_acm, bool, 0);
 107MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes");
 108
 109static bool use_obex = false;
 110module_param(use_obex, bool, 0);
 111MODULE_PARM_DESC(use_obex, "Use CDC OBEX, default=no");
 112
 113static unsigned n_ports = 1;
 114module_param(n_ports, uint, 0);
 115MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 116
 117/*-------------------------------------------------------------------------*/
 118
 119static struct usb_configuration serial_config_driver = {
 120        /* .label = f(use_acm) */
 121        /* .bConfigurationValue = f(use_acm) */
 122        /* .iConfiguration = DYNAMIC */
 123        .bmAttributes   = USB_CONFIG_ATT_SELFPOWER,
 124};
 125
 126static struct usb_function_instance *fi_serial[MAX_U_SERIAL_PORTS];
 127static struct usb_function *f_serial[MAX_U_SERIAL_PORTS];
 128
 129static int serial_register_ports(struct usb_composite_dev *cdev,
 130                struct usb_configuration *c, const char *f_name)
 131{
 132        int i;
 133        int ret;
 134
 135        ret = usb_add_config_only(cdev, c);
 136        if (ret)
 137                goto out;
 138
 139        for (i = 0; i < n_ports; i++) {
 140
 141                fi_serial[i] = usb_get_function_instance(f_name);
 142                if (IS_ERR(fi_serial[i])) {
 143                        ret = PTR_ERR(fi_serial[i]);
 144                        goto fail;
 145                }
 146
 147                f_serial[i] = usb_get_function(fi_serial[i]);
 148                if (IS_ERR(f_serial[i])) {
 149                        ret = PTR_ERR(f_serial[i]);
 150                        goto err_get_func;
 151                }
 152
 153                ret = usb_add_function(c, f_serial[i]);
 154                if (ret)
 155                        goto err_add_func;
 156        }
 157
 158        return 0;
 159
 160err_add_func:
 161        usb_put_function(f_serial[i]);
 162err_get_func:
 163        usb_put_function_instance(fi_serial[i]);
 164
 165fail:
 166        i--;
 167        while (i >= 0) {
 168                usb_remove_function(c, f_serial[i]);
 169                usb_put_function(f_serial[i]);
 170                usb_put_function_instance(fi_serial[i]);
 171                i--;
 172        }
 173out:
 174        return ret;
 175}
 176
 177static int __init gs_bind(struct usb_composite_dev *cdev)
 178{
 179        int                     status;
 180
 181        /* Allocate string descriptor numbers ... note that string
 182         * contents can be overridden by the composite_dev glue.
 183         */
 184
 185        status = usb_string_ids_tab(cdev, strings_dev);
 186        if (status < 0)
 187                goto fail;
 188        device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
 189        device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 190        status = strings_dev[STRING_DESCRIPTION_IDX].id;
 191        serial_config_driver.iConfiguration = status;
 192
 193        if (gadget_is_otg(cdev->gadget)) {
 194                serial_config_driver.descriptors = otg_desc;
 195                serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 196        }
 197
 198        /* register our configuration */
 199        if (use_acm) {
 200                status  = serial_register_ports(cdev, &serial_config_driver,
 201                                "acm");
 202                usb_ep_autoconfig_reset(cdev->gadget);
 203        } else if (use_obex)
 204                status = serial_register_ports(cdev, &serial_config_driver,
 205                                "obex");
 206        else {
 207                status = serial_register_ports(cdev, &serial_config_driver,
 208                                "gser");
 209        }
 210        if (status < 0)
 211                goto fail;
 212
 213        usb_composite_overwrite_options(cdev, &coverwrite);
 214        INFO(cdev, "%s\n", GS_VERSION_NAME);
 215
 216        return 0;
 217
 218fail:
 219        return status;
 220}
 221
 222static int gs_unbind(struct usb_composite_dev *cdev)
 223{
 224        int i;
 225
 226        for (i = 0; i < n_ports; i++) {
 227                usb_put_function(f_serial[i]);
 228                usb_put_function_instance(fi_serial[i]);
 229        }
 230        return 0;
 231}
 232
 233static __refdata struct usb_composite_driver gserial_driver = {
 234        .name           = "g_serial",
 235        .dev            = &device_desc,
 236        .strings        = dev_strings,
 237        .max_speed      = USB_SPEED_SUPER,
 238        .bind           = gs_bind,
 239        .unbind         = gs_unbind,
 240};
 241
 242static int __init init(void)
 243{
 244        /* We *could* export two configs; that'd be much cleaner...
 245         * but neither of these product IDs was defined that way.
 246         */
 247        if (use_acm) {
 248                serial_config_driver.label = "CDC ACM config";
 249                serial_config_driver.bConfigurationValue = 2;
 250                device_desc.bDeviceClass = USB_CLASS_COMM;
 251                device_desc.idProduct =
 252                                cpu_to_le16(GS_CDC_PRODUCT_ID);
 253        } else if (use_obex) {
 254                serial_config_driver.label = "CDC OBEX config";
 255                serial_config_driver.bConfigurationValue = 3;
 256                device_desc.bDeviceClass = USB_CLASS_COMM;
 257                device_desc.idProduct =
 258                        cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
 259        } else {
 260                serial_config_driver.label = "Generic Serial config";
 261                serial_config_driver.bConfigurationValue = 1;
 262                device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
 263                device_desc.idProduct =
 264                                cpu_to_le16(GS_PRODUCT_ID);
 265        }
 266        strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
 267
 268        return usb_composite_probe(&gserial_driver);
 269}
 270module_init(init);
 271
 272static void __exit cleanup(void)
 273{
 274        usb_composite_unregister(&gserial_driver);
 275}
 276module_exit(cleanup);
 277