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