Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc6 204 lines 5.5 kB view raw
1/* 2 * ncm.c -- NCM gadget driver 3 * 4 * Copyright (C) 2010 Nokia Corporation 5 * Contact: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> 6 * 7 * The driver borrows from ether.c which is: 8 * 9 * Copyright (C) 2003-2005,2008 David Brownell 10 * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger 11 * Copyright (C) 2008 Nokia Corporation 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 */ 18 19/* #define DEBUG */ 20/* #define VERBOSE_DEBUG */ 21 22#include <linux/kernel.h> 23#include <linux/module.h> 24#include <linux/usb/composite.h> 25 26#include "u_ether.h" 27 28#define DRIVER_DESC "NCM Gadget" 29 30/*-------------------------------------------------------------------------*/ 31 32/* 33 * Kbuild is not very cooperative with respect to linking separately 34 * compiled library objects into one module. So for now we won't use 35 * separate compilation ... ensuring init/exit sections work to shrink 36 * the runtime footprint, and giving us at least some parts of what 37 * a "gcc --combine ... part1.c part2.c part3.c ... " build would. 38 */ 39#include "f_ncm.c" 40#include "u_ether.c" 41 42/*-------------------------------------------------------------------------*/ 43 44/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! 45 * Instead: allocate your own, using normal USB-IF procedures. 46 */ 47 48/* Thanks to NetChip Technologies for donating this product ID. 49 * It's for devices with only CDC Ethernet configurations. 50 */ 51#define CDC_VENDOR_NUM 0x0525 /* NetChip */ 52#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ 53 54/*-------------------------------------------------------------------------*/ 55USB_GADGET_COMPOSITE_OPTIONS(); 56 57static struct usb_device_descriptor device_desc = { 58 .bLength = sizeof device_desc, 59 .bDescriptorType = USB_DT_DEVICE, 60 61 .bcdUSB = cpu_to_le16 (0x0200), 62 63 .bDeviceClass = USB_CLASS_COMM, 64 .bDeviceSubClass = 0, 65 .bDeviceProtocol = 0, 66 /* .bMaxPacketSize0 = f(hardware) */ 67 68 /* Vendor and product id defaults change according to what configs 69 * we support. (As does bNumConfigurations.) These values can 70 * also be overridden by module parameters. 71 */ 72 .idVendor = cpu_to_le16 (CDC_VENDOR_NUM), 73 .idProduct = cpu_to_le16 (CDC_PRODUCT_NUM), 74 /* .bcdDevice = f(hardware) */ 75 /* .iManufacturer = DYNAMIC */ 76 /* .iProduct = DYNAMIC */ 77 /* NO SERIAL NUMBER */ 78 .bNumConfigurations = 1, 79}; 80 81static struct usb_otg_descriptor otg_descriptor = { 82 .bLength = sizeof otg_descriptor, 83 .bDescriptorType = USB_DT_OTG, 84 85 /* REVISIT SRP-only hardware is possible, although 86 * it would not be called "OTG" ... 87 */ 88 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 89}; 90 91static const struct usb_descriptor_header *otg_desc[] = { 92 (struct usb_descriptor_header *) &otg_descriptor, 93 NULL, 94}; 95 96/* string IDs are assigned dynamically */ 97static struct usb_string strings_dev[] = { 98 [USB_GADGET_MANUFACTURER_IDX].s = "", 99 [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, 100 [USB_GADGET_SERIAL_IDX].s = "", 101 { } /* end of list */ 102}; 103 104static struct usb_gadget_strings stringtab_dev = { 105 .language = 0x0409, /* en-us */ 106 .strings = strings_dev, 107}; 108 109static struct usb_gadget_strings *dev_strings[] = { 110 &stringtab_dev, 111 NULL, 112}; 113 114static u8 hostaddr[ETH_ALEN]; 115 116/*-------------------------------------------------------------------------*/ 117 118static int __init ncm_do_config(struct usb_configuration *c) 119{ 120 /* FIXME alloc iConfiguration string, set it in c->strings */ 121 122 if (gadget_is_otg(c->cdev->gadget)) { 123 c->descriptors = otg_desc; 124 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 125 } 126 127 return ncm_bind_config(c, hostaddr); 128} 129 130static struct usb_configuration ncm_config_driver = { 131 /* .label = f(hardware) */ 132 .label = "CDC Ethernet (NCM)", 133 .bConfigurationValue = 1, 134 /* .iConfiguration = DYNAMIC */ 135 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 136}; 137 138/*-------------------------------------------------------------------------*/ 139 140static int __init gncm_bind(struct usb_composite_dev *cdev) 141{ 142 struct usb_gadget *gadget = cdev->gadget; 143 int status; 144 145 /* set up network link layer */ 146 status = gether_setup(cdev->gadget, hostaddr); 147 if (status < 0) 148 return status; 149 150 /* Allocate string descriptor numbers ... note that string 151 * contents can be overridden by the composite_dev glue. 152 */ 153 154 status = usb_string_ids_tab(cdev, strings_dev); 155 if (status < 0) 156 goto fail; 157 device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; 158 device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; 159 160 status = usb_add_config(cdev, &ncm_config_driver, 161 ncm_do_config); 162 if (status < 0) 163 goto fail; 164 165 usb_composite_overwrite_options(cdev, &coverwrite); 166 dev_info(&gadget->dev, "%s\n", DRIVER_DESC); 167 168 return 0; 169 170fail: 171 gether_cleanup(); 172 return status; 173} 174 175static int __exit gncm_unbind(struct usb_composite_dev *cdev) 176{ 177 gether_cleanup(); 178 return 0; 179} 180 181static __refdata struct usb_composite_driver ncm_driver = { 182 .name = "g_ncm", 183 .dev = &device_desc, 184 .strings = dev_strings, 185 .max_speed = USB_SPEED_HIGH, 186 .bind = gncm_bind, 187 .unbind = __exit_p(gncm_unbind), 188}; 189 190MODULE_DESCRIPTION(DRIVER_DESC); 191MODULE_AUTHOR("Yauheni Kaliuta"); 192MODULE_LICENSE("GPL"); 193 194static int __init init(void) 195{ 196 return usb_composite_probe(&ncm_driver); 197} 198module_init(init); 199 200static void __exit cleanup(void) 201{ 202 usb_composite_unregister(&ncm_driver); 203} 204module_exit(cleanup);