at v3.0 370 lines 8.2 kB view raw
1/* 2 * multi.c -- Multifunction Composite driver 3 * 4 * Copyright (C) 2008 David Brownell 5 * Copyright (C) 2008 Nokia Corporation 6 * Copyright (C) 2009 Samsung Electronics 7 * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24 25#include <linux/kernel.h> 26#include <linux/utsname.h> 27#include <linux/module.h> 28 29 30#if defined USB_ETH_RNDIS 31# undef USB_ETH_RNDIS 32#endif 33#ifdef CONFIG_USB_G_MULTI_RNDIS 34# define USB_ETH_RNDIS y 35#endif 36 37 38#define DRIVER_DESC "Multifunction Composite Gadget" 39 40MODULE_DESCRIPTION(DRIVER_DESC); 41MODULE_AUTHOR("Michal Nazarewicz"); 42MODULE_LICENSE("GPL"); 43 44 45/***************************** All the files... *****************************/ 46 47/* 48 * kbuild is not very cooperative with respect to linking separately 49 * compiled library objects into one module. So for now we won't use 50 * separate compilation ... ensuring init/exit sections work to shrink 51 * the runtime footprint, and giving us at least some parts of what 52 * a "gcc --combine ... part1.c part2.c part3.c ... " build would. 53 */ 54 55#include "composite.c" 56#include "usbstring.c" 57#include "config.c" 58#include "epautoconf.c" 59 60#include "f_mass_storage.c" 61 62#include "u_serial.c" 63#include "f_acm.c" 64 65#include "f_ecm.c" 66#include "f_subset.c" 67#ifdef USB_ETH_RNDIS 68# include "f_rndis.c" 69# include "rndis.c" 70#endif 71#include "u_ether.c" 72 73 74 75/***************************** Device Descriptor ****************************/ 76 77#define MULTI_VENDOR_NUM 0x1d6b /* Linux Foundation */ 78#define MULTI_PRODUCT_NUM 0x0104 /* Multifunction Composite Gadget */ 79 80 81enum { 82 __MULTI_NO_CONFIG, 83#ifdef CONFIG_USB_G_MULTI_RNDIS 84 MULTI_RNDIS_CONFIG_NUM, 85#endif 86#ifdef CONFIG_USB_G_MULTI_CDC 87 MULTI_CDC_CONFIG_NUM, 88#endif 89}; 90 91 92static struct usb_device_descriptor device_desc = { 93 .bLength = sizeof device_desc, 94 .bDescriptorType = USB_DT_DEVICE, 95 96 .bcdUSB = cpu_to_le16(0x0200), 97 98 .bDeviceClass = USB_CLASS_MISC /* 0xEF */, 99 .bDeviceSubClass = 2, 100 .bDeviceProtocol = 1, 101 102 /* Vendor and product id can be overridden by module parameters. */ 103 .idVendor = cpu_to_le16(MULTI_VENDOR_NUM), 104 .idProduct = cpu_to_le16(MULTI_PRODUCT_NUM), 105}; 106 107 108static const struct usb_descriptor_header *otg_desc[] = { 109 (struct usb_descriptor_header *) &(struct usb_otg_descriptor){ 110 .bLength = sizeof(struct usb_otg_descriptor), 111 .bDescriptorType = USB_DT_OTG, 112 113 /* 114 * REVISIT SRP-only hardware is possible, although 115 * it would not be called "OTG" ... 116 */ 117 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 118 }, 119 NULL, 120}; 121 122 123enum { 124#ifdef CONFIG_USB_G_MULTI_RNDIS 125 MULTI_STRING_RNDIS_CONFIG_IDX, 126#endif 127#ifdef CONFIG_USB_G_MULTI_CDC 128 MULTI_STRING_CDC_CONFIG_IDX, 129#endif 130}; 131 132static struct usb_string strings_dev[] = { 133#ifdef CONFIG_USB_G_MULTI_RNDIS 134 [MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS", 135#endif 136#ifdef CONFIG_USB_G_MULTI_CDC 137 [MULTI_STRING_CDC_CONFIG_IDX].s = "Multifunction with CDC ECM", 138#endif 139 { } /* end of list */ 140}; 141 142static struct usb_gadget_strings *dev_strings[] = { 143 &(struct usb_gadget_strings){ 144 .language = 0x0409, /* en-us */ 145 .strings = strings_dev, 146 }, 147 NULL, 148}; 149 150 151 152 153/****************************** Configurations ******************************/ 154 155static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; 156FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); 157 158static struct fsg_common fsg_common; 159 160static u8 hostaddr[ETH_ALEN]; 161 162 163/********** RNDIS **********/ 164 165#ifdef USB_ETH_RNDIS 166 167static __init int rndis_do_config(struct usb_configuration *c) 168{ 169 int ret; 170 171 if (gadget_is_otg(c->cdev->gadget)) { 172 c->descriptors = otg_desc; 173 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 174 } 175 176 ret = rndis_bind_config(c, hostaddr); 177 if (ret < 0) 178 return ret; 179 180 ret = acm_bind_config(c, 0); 181 if (ret < 0) 182 return ret; 183 184 ret = fsg_bind_config(c->cdev, c, &fsg_common); 185 if (ret < 0) 186 return ret; 187 188 return 0; 189} 190 191static int rndis_config_register(struct usb_composite_dev *cdev) 192{ 193 static struct usb_configuration config = { 194 .bConfigurationValue = MULTI_RNDIS_CONFIG_NUM, 195 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 196 }; 197 198 config.label = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s; 199 config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id; 200 201 return usb_add_config(cdev, &config, rndis_do_config); 202} 203 204#else 205 206static int rndis_config_register(struct usb_composite_dev *cdev) 207{ 208 return 0; 209} 210 211#endif 212 213 214/********** CDC ECM **********/ 215 216#ifdef CONFIG_USB_G_MULTI_CDC 217 218static __init int cdc_do_config(struct usb_configuration *c) 219{ 220 int ret; 221 222 if (gadget_is_otg(c->cdev->gadget)) { 223 c->descriptors = otg_desc; 224 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 225 } 226 227 ret = ecm_bind_config(c, hostaddr); 228 if (ret < 0) 229 return ret; 230 231 ret = acm_bind_config(c, 0); 232 if (ret < 0) 233 return ret; 234 235 ret = fsg_bind_config(c->cdev, c, &fsg_common); 236 if (ret < 0) 237 return ret; 238 239 return 0; 240} 241 242static int cdc_config_register(struct usb_composite_dev *cdev) 243{ 244 static struct usb_configuration config = { 245 .bConfigurationValue = MULTI_CDC_CONFIG_NUM, 246 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 247 }; 248 249 config.label = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s; 250 config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id; 251 252 return usb_add_config(cdev, &config, cdc_do_config); 253} 254 255#else 256 257static int cdc_config_register(struct usb_composite_dev *cdev) 258{ 259 return 0; 260} 261 262#endif 263 264 265 266/****************************** Gadget Bind ******************************/ 267 268 269static int __ref multi_bind(struct usb_composite_dev *cdev) 270{ 271 struct usb_gadget *gadget = cdev->gadget; 272 int status, gcnum; 273 274 if (!can_support_ecm(cdev->gadget)) { 275 dev_err(&gadget->dev, "controller '%s' not usable\n", 276 gadget->name); 277 return -EINVAL; 278 } 279 280 /* set up network link layer */ 281 status = gether_setup(cdev->gadget, hostaddr); 282 if (status < 0) 283 return status; 284 285 /* set up serial link layer */ 286 status = gserial_setup(cdev->gadget, 1); 287 if (status < 0) 288 goto fail0; 289 290 /* set up mass storage function */ 291 { 292 void *retp; 293 retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); 294 if (IS_ERR(retp)) { 295 status = PTR_ERR(retp); 296 goto fail1; 297 } 298 } 299 300 /* set bcdDevice */ 301 gcnum = usb_gadget_controller_number(gadget); 302 if (gcnum >= 0) { 303 device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); 304 } else { 305 WARNING(cdev, "controller '%s' not recognized\n", gadget->name); 306 device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); 307 } 308 309 /* allocate string IDs */ 310 status = usb_string_ids_tab(cdev, strings_dev); 311 if (unlikely(status < 0)) 312 goto fail2; 313 314 /* register configurations */ 315 status = rndis_config_register(cdev); 316 if (unlikely(status < 0)) 317 goto fail2; 318 319 status = cdc_config_register(cdev); 320 if (unlikely(status < 0)) 321 goto fail2; 322 323 /* we're done */ 324 dev_info(&gadget->dev, DRIVER_DESC "\n"); 325 fsg_common_put(&fsg_common); 326 return 0; 327 328 329 /* error recovery */ 330fail2: 331 fsg_common_put(&fsg_common); 332fail1: 333 gserial_cleanup(); 334fail0: 335 gether_cleanup(); 336 return status; 337} 338 339static int __exit multi_unbind(struct usb_composite_dev *cdev) 340{ 341 gserial_cleanup(); 342 gether_cleanup(); 343 return 0; 344} 345 346 347/****************************** Some noise ******************************/ 348 349 350static struct usb_composite_driver multi_driver = { 351 .name = "g_multi", 352 .dev = &device_desc, 353 .strings = dev_strings, 354 .unbind = __exit_p(multi_unbind), 355 .iProduct = DRIVER_DESC, 356 .needs_serial = 1, 357}; 358 359 360static int __init multi_init(void) 361{ 362 return usb_composite_probe(&multi_driver, multi_bind); 363} 364module_init(multi_init); 365 366static void __exit multi_exit(void) 367{ 368 usb_composite_unregister(&multi_driver); 369} 370module_exit(multi_exit);