root/drivers/usb/gadget/legacy/cdc2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cdc_do_config
  2. cdc_bind
  3. cdc_unbind

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * cdc2.c -- CDC Composite driver, with ECM and ACM support
   4  *
   5  * Copyright (C) 2008 David Brownell
   6  * Copyright (C) 2008 Nokia Corporation
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/module.h>
  11 
  12 #include "u_ether.h"
  13 #include "u_serial.h"
  14 #include "u_ecm.h"
  15 
  16 
  17 #define DRIVER_DESC             "CDC Composite Gadget"
  18 #define DRIVER_VERSION          "King Kamehameha Day 2008"
  19 
  20 /*-------------------------------------------------------------------------*/
  21 
  22 /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
  23  * Instead:  allocate your own, using normal USB-IF procedures.
  24  */
  25 
  26 /* Thanks to NetChip Technologies for donating this product ID.
  27  * It's for devices with only this composite CDC configuration.
  28  */
  29 #define CDC_VENDOR_NUM          0x0525  /* NetChip */
  30 #define CDC_PRODUCT_NUM         0xa4aa  /* CDC Composite: ECM + ACM */
  31 
  32 USB_GADGET_COMPOSITE_OPTIONS();
  33 
  34 USB_ETHERNET_MODULE_PARAMETERS();
  35 
  36 /*-------------------------------------------------------------------------*/
  37 
  38 static struct usb_device_descriptor device_desc = {
  39         .bLength =              sizeof device_desc,
  40         .bDescriptorType =      USB_DT_DEVICE,
  41 
  42         /* .bcdUSB = DYNAMIC */
  43 
  44         .bDeviceClass =         USB_CLASS_COMM,
  45         .bDeviceSubClass =      0,
  46         .bDeviceProtocol =      0,
  47         /* .bMaxPacketSize0 = f(hardware) */
  48 
  49         /* Vendor and product id can be overridden by module parameters.  */
  50         .idVendor =             cpu_to_le16(CDC_VENDOR_NUM),
  51         .idProduct =            cpu_to_le16(CDC_PRODUCT_NUM),
  52         /* .bcdDevice = f(hardware) */
  53         /* .iManufacturer = DYNAMIC */
  54         /* .iProduct = DYNAMIC */
  55         /* NO SERIAL NUMBER */
  56         .bNumConfigurations =   1,
  57 };
  58 
  59 static const struct usb_descriptor_header *otg_desc[2];
  60 
  61 /* string IDs are assigned dynamically */
  62 static struct usb_string strings_dev[] = {
  63         [USB_GADGET_MANUFACTURER_IDX].s = "",
  64         [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
  65         [USB_GADGET_SERIAL_IDX].s = "",
  66         {  } /* end of list */
  67 };
  68 
  69 static struct usb_gadget_strings stringtab_dev = {
  70         .language       = 0x0409,       /* en-us */
  71         .strings        = strings_dev,
  72 };
  73 
  74 static struct usb_gadget_strings *dev_strings[] = {
  75         &stringtab_dev,
  76         NULL,
  77 };
  78 
  79 /*-------------------------------------------------------------------------*/
  80 static struct usb_function *f_acm;
  81 static struct usb_function_instance *fi_serial;
  82 
  83 static struct usb_function *f_ecm;
  84 static struct usb_function_instance *fi_ecm;
  85 
  86 /*
  87  * We _always_ have both CDC ECM and CDC ACM functions.
  88  */
  89 static int cdc_do_config(struct usb_configuration *c)
  90 {
  91         int     status;
  92 
  93         if (gadget_is_otg(c->cdev->gadget)) {
  94                 c->descriptors = otg_desc;
  95                 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
  96         }
  97 
  98         f_ecm = usb_get_function(fi_ecm);
  99         if (IS_ERR(f_ecm)) {
 100                 status = PTR_ERR(f_ecm);
 101                 goto err_get_ecm;
 102         }
 103 
 104         status = usb_add_function(c, f_ecm);
 105         if (status)
 106                 goto err_add_ecm;
 107 
 108         f_acm = usb_get_function(fi_serial);
 109         if (IS_ERR(f_acm)) {
 110                 status = PTR_ERR(f_acm);
 111                 goto err_get_acm;
 112         }
 113 
 114         status = usb_add_function(c, f_acm);
 115         if (status)
 116                 goto err_add_acm;
 117         return 0;
 118 
 119 err_add_acm:
 120         usb_put_function(f_acm);
 121 err_get_acm:
 122         usb_remove_function(c, f_ecm);
 123 err_add_ecm:
 124         usb_put_function(f_ecm);
 125 err_get_ecm:
 126         return status;
 127 }
 128 
 129 static struct usb_configuration cdc_config_driver = {
 130         .label                  = "CDC Composite (ECM + ACM)",
 131         .bConfigurationValue    = 1,
 132         /* .iConfiguration = DYNAMIC */
 133         .bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
 134 };
 135 
 136 /*-------------------------------------------------------------------------*/
 137 
 138 static int cdc_bind(struct usb_composite_dev *cdev)
 139 {
 140         struct usb_gadget       *gadget = cdev->gadget;
 141         struct f_ecm_opts       *ecm_opts;
 142         int                     status;
 143 
 144         if (!can_support_ecm(cdev->gadget)) {
 145                 dev_err(&gadget->dev, "controller '%s' not usable\n",
 146                                 gadget->name);
 147                 return -EINVAL;
 148         }
 149 
 150         fi_ecm = usb_get_function_instance("ecm");
 151         if (IS_ERR(fi_ecm))
 152                 return PTR_ERR(fi_ecm);
 153 
 154         ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
 155 
 156         gether_set_qmult(ecm_opts->net, qmult);
 157         if (!gether_set_host_addr(ecm_opts->net, host_addr))
 158                 pr_info("using host ethernet address: %s", host_addr);
 159         if (!gether_set_dev_addr(ecm_opts->net, dev_addr))
 160                 pr_info("using self ethernet address: %s", dev_addr);
 161 
 162         fi_serial = usb_get_function_instance("acm");
 163         if (IS_ERR(fi_serial)) {
 164                 status = PTR_ERR(fi_serial);
 165                 goto fail;
 166         }
 167 
 168         /* Allocate string descriptor numbers ... note that string
 169          * contents can be overridden by the composite_dev glue.
 170          */
 171 
 172         status = usb_string_ids_tab(cdev, strings_dev);
 173         if (status < 0)
 174                 goto fail1;
 175         device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
 176         device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 177 
 178         if (gadget_is_otg(gadget) && !otg_desc[0]) {
 179                 struct usb_descriptor_header *usb_desc;
 180 
 181                 usb_desc = usb_otg_descriptor_alloc(gadget);
 182                 if (!usb_desc) {
 183                         status = -ENOMEM;
 184                         goto fail1;
 185                 }
 186                 usb_otg_descriptor_init(gadget, usb_desc);
 187                 otg_desc[0] = usb_desc;
 188                 otg_desc[1] = NULL;
 189         }
 190 
 191         /* register our configuration */
 192         status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
 193         if (status < 0)
 194                 goto fail2;
 195 
 196         usb_composite_overwrite_options(cdev, &coverwrite);
 197         dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
 198                         DRIVER_DESC);
 199 
 200         return 0;
 201 
 202 fail2:
 203         kfree(otg_desc[0]);
 204         otg_desc[0] = NULL;
 205 fail1:
 206         usb_put_function_instance(fi_serial);
 207 fail:
 208         usb_put_function_instance(fi_ecm);
 209         return status;
 210 }
 211 
 212 static int cdc_unbind(struct usb_composite_dev *cdev)
 213 {
 214         usb_put_function(f_acm);
 215         usb_put_function_instance(fi_serial);
 216         if (!IS_ERR_OR_NULL(f_ecm))
 217                 usb_put_function(f_ecm);
 218         if (!IS_ERR_OR_NULL(fi_ecm))
 219                 usb_put_function_instance(fi_ecm);
 220         kfree(otg_desc[0]);
 221         otg_desc[0] = NULL;
 222 
 223         return 0;
 224 }
 225 
 226 static struct usb_composite_driver cdc_driver = {
 227         .name           = "g_cdc",
 228         .dev            = &device_desc,
 229         .strings        = dev_strings,
 230         .max_speed      = USB_SPEED_SUPER,
 231         .bind           = cdc_bind,
 232         .unbind         = cdc_unbind,
 233 };
 234 
 235 module_usb_composite_driver(cdc_driver);
 236 
 237 MODULE_DESCRIPTION(DRIVER_DESC);
 238 MODULE_AUTHOR("David Brownell");
 239 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */