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.10-rc3 279 lines 7.1 kB view raw
1/* 2 * nokia.c -- Nokia Composite Gadget Driver 3 * 4 * Copyright (C) 2008-2010 Nokia Corporation 5 * Contact: Felipe Balbi <felipe.balbi@nokia.com> 6 * 7 * This gadget driver borrows from serial.c which is: 8 * 9 * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) 10 * Copyright (C) 2008 by David Brownell 11 * Copyright (C) 2008 by Nokia Corporation 12 * 13 * This software is distributed under the terms of the GNU General 14 * Public License ("GPL") as published by the Free Software Foundation, 15 * version 2 of that License. 16 */ 17 18#include <linux/kernel.h> 19#include <linux/device.h> 20 21#include "u_serial.h" 22#include "u_ether.h" 23#include "u_phonet.h" 24#include "gadget_chips.h" 25 26/* Defines */ 27 28#define NOKIA_VERSION_NUM 0x0211 29#define NOKIA_LONG_NAME "N900 (PC-Suite Mode)" 30 31/*-------------------------------------------------------------------------*/ 32 33/* 34 * Kbuild is not very cooperative with respect to linking separately 35 * compiled library objects into one module. So for now we won't use 36 * separate compilation ... ensuring init/exit sections work to shrink 37 * the runtime footprint, and giving us at least some parts of what 38 * a "gcc --combine ... part1.c part2.c part3.c ... " build would. 39 */ 40#define USBF_OBEX_INCLUDED 41#include "f_ecm.c" 42#include "f_obex.c" 43#include "f_phonet.c" 44#include "u_ether.c" 45 46/*-------------------------------------------------------------------------*/ 47USB_GADGET_COMPOSITE_OPTIONS(); 48 49#define NOKIA_VENDOR_ID 0x0421 /* Nokia */ 50#define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */ 51 52/* string IDs are assigned dynamically */ 53 54#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX 55 56static char manufacturer_nokia[] = "Nokia"; 57static const char product_nokia[] = NOKIA_LONG_NAME; 58static const char description_nokia[] = "PC-Suite Configuration"; 59 60static struct usb_string strings_dev[] = { 61 [USB_GADGET_MANUFACTURER_IDX].s = manufacturer_nokia, 62 [USB_GADGET_PRODUCT_IDX].s = NOKIA_LONG_NAME, 63 [USB_GADGET_SERIAL_IDX].s = "", 64 [STRING_DESCRIPTION_IDX].s = description_nokia, 65 { } /* end of list */ 66}; 67 68static struct usb_gadget_strings stringtab_dev = { 69 .language = 0x0409, /* en-us */ 70 .strings = strings_dev, 71}; 72 73static struct usb_gadget_strings *dev_strings[] = { 74 &stringtab_dev, 75 NULL, 76}; 77 78static struct usb_device_descriptor device_desc = { 79 .bLength = USB_DT_DEVICE_SIZE, 80 .bDescriptorType = USB_DT_DEVICE, 81 .bcdUSB = __constant_cpu_to_le16(0x0200), 82 .bDeviceClass = USB_CLASS_COMM, 83 .idVendor = __constant_cpu_to_le16(NOKIA_VENDOR_ID), 84 .idProduct = __constant_cpu_to_le16(NOKIA_PRODUCT_ID), 85 .bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM), 86 /* .iManufacturer = DYNAMIC */ 87 /* .iProduct = DYNAMIC */ 88 .bNumConfigurations = 1, 89}; 90 91/*-------------------------------------------------------------------------*/ 92 93/* Module */ 94MODULE_DESCRIPTION("Nokia composite gadget driver for N900"); 95MODULE_AUTHOR("Felipe Balbi"); 96MODULE_LICENSE("GPL"); 97 98/*-------------------------------------------------------------------------*/ 99static struct usb_function *f_acm_cfg1; 100static struct usb_function *f_acm_cfg2; 101static u8 hostaddr[ETH_ALEN]; 102static struct eth_dev *the_dev; 103 104enum { 105 TTY_PORT_OBEX0, 106 TTY_PORT_OBEX1, 107 TTY_PORTS_MAX, 108}; 109 110static unsigned char tty_lines[TTY_PORTS_MAX]; 111 112static struct usb_configuration nokia_config_500ma_driver = { 113 .label = "Bus Powered", 114 .bConfigurationValue = 1, 115 /* .iConfiguration = DYNAMIC */ 116 .bmAttributes = USB_CONFIG_ATT_ONE, 117 .MaxPower = 500, 118}; 119 120static struct usb_configuration nokia_config_100ma_driver = { 121 .label = "Self Powered", 122 .bConfigurationValue = 2, 123 /* .iConfiguration = DYNAMIC */ 124 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, 125 .MaxPower = 100, 126}; 127 128static struct usb_function_instance *fi_acm; 129 130static int __init nokia_bind_config(struct usb_configuration *c) 131{ 132 struct usb_function *f_acm; 133 int status = 0; 134 135 status = phonet_bind_config(c); 136 if (status) 137 printk(KERN_DEBUG "could not bind phonet config\n"); 138 139 status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]); 140 if (status) 141 printk(KERN_DEBUG "could not bind obex config %d\n", 0); 142 143 status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]); 144 if (status) 145 printk(KERN_DEBUG "could not bind obex config %d\n", 0); 146 147 f_acm = usb_get_function(fi_acm); 148 if (IS_ERR(f_acm)) 149 return PTR_ERR(f_acm); 150 151 status = usb_add_function(c, f_acm); 152 if (status) 153 goto err_conf; 154 155 status = ecm_bind_config(c, hostaddr, the_dev); 156 if (status) { 157 pr_debug("could not bind ecm config %d\n", status); 158 goto err_ecm; 159 } 160 if (c == &nokia_config_500ma_driver) 161 f_acm_cfg1 = f_acm; 162 else 163 f_acm_cfg2 = f_acm; 164 165 return status; 166err_ecm: 167 usb_remove_function(c, f_acm); 168err_conf: 169 usb_put_function(f_acm); 170 return status; 171} 172 173static int __init nokia_bind(struct usb_composite_dev *cdev) 174{ 175 struct usb_gadget *gadget = cdev->gadget; 176 int status; 177 int cur_line; 178 179 status = gphonet_setup(cdev->gadget); 180 if (status < 0) 181 goto err_phonet; 182 183 for (cur_line = 0; cur_line < TTY_PORTS_MAX; cur_line++) { 184 status = gserial_alloc_line(&tty_lines[cur_line]); 185 if (status) 186 goto err_ether; 187 } 188 189 the_dev = gether_setup(cdev->gadget, hostaddr); 190 if (IS_ERR(the_dev)) { 191 status = PTR_ERR(the_dev); 192 goto err_ether; 193 } 194 195 status = usb_string_ids_tab(cdev, strings_dev); 196 if (status < 0) 197 goto err_usb; 198 device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; 199 device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; 200 status = strings_dev[STRING_DESCRIPTION_IDX].id; 201 nokia_config_500ma_driver.iConfiguration = status; 202 nokia_config_100ma_driver.iConfiguration = status; 203 204 if (!gadget_supports_altsettings(gadget)) 205 goto err_usb; 206 207 fi_acm = usb_get_function_instance("acm"); 208 if (IS_ERR(fi_acm)) 209 goto err_usb; 210 211 /* finally register the configuration */ 212 status = usb_add_config(cdev, &nokia_config_500ma_driver, 213 nokia_bind_config); 214 if (status < 0) 215 goto err_acm_inst; 216 217 status = usb_add_config(cdev, &nokia_config_100ma_driver, 218 nokia_bind_config); 219 if (status < 0) 220 goto err_put_cfg1; 221 222 usb_composite_overwrite_options(cdev, &coverwrite); 223 dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME); 224 225 return 0; 226 227err_put_cfg1: 228 usb_put_function(f_acm_cfg1); 229err_acm_inst: 230 usb_put_function_instance(fi_acm); 231err_usb: 232 gether_cleanup(the_dev); 233err_ether: 234 cur_line--; 235 while (cur_line >= 0) 236 gserial_free_line(tty_lines[cur_line--]); 237 238 gphonet_cleanup(); 239err_phonet: 240 return status; 241} 242 243static int __exit nokia_unbind(struct usb_composite_dev *cdev) 244{ 245 int i; 246 247 usb_put_function(f_acm_cfg1); 248 usb_put_function(f_acm_cfg2); 249 usb_put_function_instance(fi_acm); 250 gphonet_cleanup(); 251 252 for (i = 0; i < TTY_PORTS_MAX; i++) 253 gserial_free_line(tty_lines[i]); 254 255 gether_cleanup(the_dev); 256 257 return 0; 258} 259 260static __refdata struct usb_composite_driver nokia_driver = { 261 .name = "g_nokia", 262 .dev = &device_desc, 263 .strings = dev_strings, 264 .max_speed = USB_SPEED_HIGH, 265 .bind = nokia_bind, 266 .unbind = __exit_p(nokia_unbind), 267}; 268 269static int __init nokia_init(void) 270{ 271 return usb_composite_probe(&nokia_driver); 272} 273module_init(nokia_init); 274 275static void __exit nokia_cleanup(void) 276{ 277 usb_composite_unregister(&nokia_driver); 278} 279module_exit(nokia_cleanup);