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.8-rc6 479 lines 11 kB view raw
1/* 2 * g_ffs.c -- user mode file system API for USB composite function controllers 3 * 4 * Copyright (C) 2010 Samsung Electronics 5 * Author: Michal Nazarewicz <mina86@mina86.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 */ 12 13#define pr_fmt(fmt) "g_ffs: " fmt 14 15#include <linux/module.h> 16 17/* 18 * kbuild is not very cooperative with respect to linking separately 19 * compiled library objects into one module. So for now we won't use 20 * separate compilation ... ensuring init/exit sections work to shrink 21 * the runtime footprint, and giving us at least some parts of what 22 * a "gcc --combine ... part1.c part2.c part3.c ... " build would. 23 */ 24#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS 25# if defined USB_ETH_RNDIS 26# undef USB_ETH_RNDIS 27# endif 28# ifdef CONFIG_USB_FUNCTIONFS_RNDIS 29# define USB_ETH_RNDIS y 30# endif 31 32# include "f_ecm.c" 33# include "f_subset.c" 34# ifdef USB_ETH_RNDIS 35# include "f_rndis.c" 36# include "rndis.c" 37# endif 38# include "u_ether.c" 39 40static u8 gfs_hostaddr[ETH_ALEN]; 41# ifdef CONFIG_USB_FUNCTIONFS_ETH 42static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); 43# endif 44#else 45# define gether_cleanup() do { } while (0) 46# define gether_setup(gadget, hostaddr) ((int)0) 47# define gfs_hostaddr NULL 48#endif 49 50#include "f_fs.c" 51 52#define DRIVER_NAME "g_ffs" 53#define DRIVER_DESC "USB Function Filesystem" 54#define DRIVER_VERSION "24 Aug 2004" 55 56MODULE_DESCRIPTION(DRIVER_DESC); 57MODULE_AUTHOR("Michal Nazarewicz"); 58MODULE_LICENSE("GPL"); 59 60#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */ 61#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */ 62 63#define GFS_MAX_DEVS 10 64 65struct gfs_ffs_obj { 66 const char *name; 67 bool mounted; 68 bool desc_ready; 69 struct ffs_data *ffs_data; 70}; 71 72USB_GADGET_COMPOSITE_OPTIONS(); 73 74static struct usb_device_descriptor gfs_dev_desc = { 75 .bLength = sizeof gfs_dev_desc, 76 .bDescriptorType = USB_DT_DEVICE, 77 78 .bcdUSB = cpu_to_le16(0x0200), 79 .bDeviceClass = USB_CLASS_PER_INTERFACE, 80 81 .idVendor = cpu_to_le16(GFS_VENDOR_ID), 82 .idProduct = cpu_to_le16(GFS_PRODUCT_ID), 83}; 84 85static char *func_names[GFS_MAX_DEVS]; 86static unsigned int func_num; 87 88module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644); 89MODULE_PARM_DESC(bDeviceClass, "USB Device class"); 90module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644); 91MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass"); 92module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644); 93MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol"); 94module_param_array_named(functions, func_names, charp, &func_num, 0); 95MODULE_PARM_DESC(functions, "USB Functions list"); 96 97static const struct usb_descriptor_header *gfs_otg_desc[] = { 98 (const struct usb_descriptor_header *) 99 &(const struct usb_otg_descriptor) { 100 .bLength = sizeof(struct usb_otg_descriptor), 101 .bDescriptorType = USB_DT_OTG, 102 103 /* 104 * REVISIT SRP-only hardware is possible, although 105 * it would not be called "OTG" ... 106 */ 107 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 108 }, 109 110 NULL 111}; 112 113/* String IDs are assigned dynamically */ 114static struct usb_string gfs_strings[] = { 115 [USB_GADGET_MANUFACTURER_IDX].s = "", 116 [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, 117 [USB_GADGET_SERIAL_IDX].s = "", 118#ifdef CONFIG_USB_FUNCTIONFS_RNDIS 119 { .s = "FunctionFS + RNDIS" }, 120#endif 121#ifdef CONFIG_USB_FUNCTIONFS_ETH 122 { .s = "FunctionFS + ECM" }, 123#endif 124#ifdef CONFIG_USB_FUNCTIONFS_GENERIC 125 { .s = "FunctionFS" }, 126#endif 127 { } /* end of list */ 128}; 129 130static struct usb_gadget_strings *gfs_dev_strings[] = { 131 &(struct usb_gadget_strings) { 132 .language = 0x0409, /* en-us */ 133 .strings = gfs_strings, 134 }, 135 NULL, 136}; 137 138struct gfs_configuration { 139 struct usb_configuration c; 140 int (*eth)(struct usb_configuration *c, u8 *ethaddr); 141} gfs_configurations[] = { 142#ifdef CONFIG_USB_FUNCTIONFS_RNDIS 143 { 144 .eth = rndis_bind_config, 145 }, 146#endif 147 148#ifdef CONFIG_USB_FUNCTIONFS_ETH 149 { 150 .eth = eth_bind_config, 151 }, 152#endif 153 154#ifdef CONFIG_USB_FUNCTIONFS_GENERIC 155 { 156 }, 157#endif 158}; 159 160static int gfs_bind(struct usb_composite_dev *cdev); 161static int gfs_unbind(struct usb_composite_dev *cdev); 162static int gfs_do_config(struct usb_configuration *c); 163 164static __refdata struct usb_composite_driver gfs_driver = { 165 .name = DRIVER_NAME, 166 .dev = &gfs_dev_desc, 167 .strings = gfs_dev_strings, 168 .max_speed = USB_SPEED_HIGH, 169 .bind = gfs_bind, 170 .unbind = gfs_unbind, 171}; 172 173static DEFINE_MUTEX(gfs_lock); 174static unsigned int missing_funcs; 175static bool gfs_ether_setup; 176static bool gfs_registered; 177static bool gfs_single_func; 178static struct gfs_ffs_obj *ffs_tab; 179 180static int __init gfs_init(void) 181{ 182 int i; 183 184 ENTER(); 185 186 if (!func_num) { 187 gfs_single_func = true; 188 func_num = 1; 189 } 190 191 ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL); 192 if (!ffs_tab) 193 return -ENOMEM; 194 195 if (!gfs_single_func) 196 for (i = 0; i < func_num; i++) 197 ffs_tab[i].name = func_names[i]; 198 199 missing_funcs = func_num; 200 201 return functionfs_init(); 202} 203module_init(gfs_init); 204 205static void __exit gfs_exit(void) 206{ 207 ENTER(); 208 mutex_lock(&gfs_lock); 209 210 if (gfs_registered) 211 usb_composite_unregister(&gfs_driver); 212 gfs_registered = false; 213 214 functionfs_cleanup(); 215 216 mutex_unlock(&gfs_lock); 217 kfree(ffs_tab); 218} 219module_exit(gfs_exit); 220 221static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name) 222{ 223 int i; 224 225 ENTER(); 226 227 if (gfs_single_func) 228 return &ffs_tab[0]; 229 230 for (i = 0; i < func_num; i++) 231 if (strcmp(ffs_tab[i].name, dev_name) == 0) 232 return &ffs_tab[i]; 233 234 return NULL; 235} 236 237static int functionfs_ready_callback(struct ffs_data *ffs) 238{ 239 struct gfs_ffs_obj *ffs_obj; 240 int ret; 241 242 ENTER(); 243 mutex_lock(&gfs_lock); 244 245 ffs_obj = ffs->private_data; 246 if (!ffs_obj) { 247 ret = -EINVAL; 248 goto done; 249 } 250 251 if (WARN_ON(ffs_obj->desc_ready)) { 252 ret = -EBUSY; 253 goto done; 254 } 255 ffs_obj->desc_ready = true; 256 ffs_obj->ffs_data = ffs; 257 258 if (--missing_funcs) { 259 ret = 0; 260 goto done; 261 } 262 263 if (gfs_registered) { 264 ret = -EBUSY; 265 goto done; 266 } 267 gfs_registered = true; 268 269 ret = usb_composite_probe(&gfs_driver); 270 if (unlikely(ret < 0)) 271 gfs_registered = false; 272 273done: 274 mutex_unlock(&gfs_lock); 275 return ret; 276} 277 278static void functionfs_closed_callback(struct ffs_data *ffs) 279{ 280 struct gfs_ffs_obj *ffs_obj; 281 282 ENTER(); 283 mutex_lock(&gfs_lock); 284 285 ffs_obj = ffs->private_data; 286 if (!ffs_obj) 287 goto done; 288 289 ffs_obj->desc_ready = false; 290 missing_funcs++; 291 292 if (gfs_registered) 293 usb_composite_unregister(&gfs_driver); 294 gfs_registered = false; 295 296done: 297 mutex_unlock(&gfs_lock); 298} 299 300static void *functionfs_acquire_dev_callback(const char *dev_name) 301{ 302 struct gfs_ffs_obj *ffs_dev; 303 304 ENTER(); 305 mutex_lock(&gfs_lock); 306 307 ffs_dev = gfs_find_dev(dev_name); 308 if (!ffs_dev) { 309 ffs_dev = ERR_PTR(-ENODEV); 310 goto done; 311 } 312 313 if (ffs_dev->mounted) { 314 ffs_dev = ERR_PTR(-EBUSY); 315 goto done; 316 } 317 ffs_dev->mounted = true; 318 319done: 320 mutex_unlock(&gfs_lock); 321 return ffs_dev; 322} 323 324static void functionfs_release_dev_callback(struct ffs_data *ffs_data) 325{ 326 struct gfs_ffs_obj *ffs_dev; 327 328 ENTER(); 329 mutex_lock(&gfs_lock); 330 331 ffs_dev = ffs_data->private_data; 332 if (ffs_dev) 333 ffs_dev->mounted = false; 334 335 mutex_unlock(&gfs_lock); 336} 337 338/* 339 * It is assumed that gfs_bind is called from a context where gfs_lock is held 340 */ 341static int gfs_bind(struct usb_composite_dev *cdev) 342{ 343 int ret, i; 344 345 ENTER(); 346 347 if (missing_funcs) 348 return -ENODEV; 349 350 ret = gether_setup(cdev->gadget, gfs_hostaddr); 351 if (unlikely(ret < 0)) 352 goto error_quick; 353 gfs_ether_setup = true; 354 355 ret = usb_string_ids_tab(cdev, gfs_strings); 356 if (unlikely(ret < 0)) 357 goto error; 358 gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; 359 360 for (i = func_num; --i; ) { 361 ret = functionfs_bind(ffs_tab[i].ffs_data, cdev); 362 if (unlikely(ret < 0)) { 363 while (++i < func_num) 364 functionfs_unbind(ffs_tab[i].ffs_data); 365 goto error; 366 } 367 } 368 369 for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { 370 struct gfs_configuration *c = gfs_configurations + i; 371 int sid = USB_GADGET_FIRST_AVAIL_IDX + i; 372 373 c->c.label = gfs_strings[sid].s; 374 c->c.iConfiguration = gfs_strings[sid].id; 375 c->c.bConfigurationValue = 1 + i; 376 c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER; 377 378 ret = usb_add_config(cdev, &c->c, gfs_do_config); 379 if (unlikely(ret < 0)) 380 goto error_unbind; 381 } 382 usb_composite_overwrite_options(cdev, &coverwrite); 383 return 0; 384 385error_unbind: 386 for (i = 0; i < func_num; i++) 387 functionfs_unbind(ffs_tab[i].ffs_data); 388error: 389 gether_cleanup(); 390error_quick: 391 gfs_ether_setup = false; 392 return ret; 393} 394 395/* 396 * It is assumed that gfs_unbind is called from a context where gfs_lock is held 397 */ 398static int gfs_unbind(struct usb_composite_dev *cdev) 399{ 400 int i; 401 402 ENTER(); 403 404 /* 405 * We may have been called in an error recovery from 406 * composite_bind() after gfs_unbind() failure so we need to 407 * check if gfs_ffs_data is not NULL since gfs_bind() handles 408 * all error recovery itself. I'd rather we werent called 409 * from composite on orror recovery, but what you're gonna 410 * do...? 411 */ 412 if (gfs_ether_setup) 413 gether_cleanup(); 414 gfs_ether_setup = false; 415 416 for (i = func_num; --i; ) 417 if (ffs_tab[i].ffs_data) 418 functionfs_unbind(ffs_tab[i].ffs_data); 419 420 return 0; 421} 422 423/* 424 * It is assumed that gfs_do_config is called from a context where 425 * gfs_lock is held 426 */ 427static int gfs_do_config(struct usb_configuration *c) 428{ 429 struct gfs_configuration *gc = 430 container_of(c, struct gfs_configuration, c); 431 int i; 432 int ret; 433 434 if (missing_funcs) 435 return -ENODEV; 436 437 if (gadget_is_otg(c->cdev->gadget)) { 438 c->descriptors = gfs_otg_desc; 439 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 440 } 441 442 if (gc->eth) { 443 ret = gc->eth(c, gfs_hostaddr); 444 if (unlikely(ret < 0)) 445 return ret; 446 } 447 448 for (i = 0; i < func_num; i++) { 449 ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data); 450 if (unlikely(ret < 0)) 451 return ret; 452 } 453 454 /* 455 * After previous do_configs there may be some invalid 456 * pointers in c->interface array. This happens every time 457 * a user space function with fewer interfaces than a user 458 * space function that was run before the new one is run. The 459 * compasit's set_config() assumes that if there is no more 460 * then MAX_CONFIG_INTERFACES interfaces in a configuration 461 * then there is a NULL pointer after the last interface in 462 * c->interface array. We need to make sure this is true. 463 */ 464 if (c->next_interface_id < ARRAY_SIZE(c->interface)) 465 c->interface[c->next_interface_id] = NULL; 466 467 return 0; 468} 469 470#ifdef CONFIG_USB_FUNCTIONFS_ETH 471 472static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) 473{ 474 return can_support_ecm(c->cdev->gadget) 475 ? ecm_bind_config(c, ethaddr) 476 : geth_bind_config(c, ethaddr); 477} 478 479#endif