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.5-rc1 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#include <linux/utsname.h> 17 18/* 19 * kbuild is not very cooperative with respect to linking separately 20 * compiled library objects into one module. So for now we won't use 21 * separate compilation ... ensuring init/exit sections work to shrink 22 * the runtime footprint, and giving us at least some parts of what 23 * a "gcc --combine ... part1.c part2.c part3.c ... " build would. 24 */ 25 26#include "composite.c" 27#include "usbstring.c" 28#include "config.c" 29#include "epautoconf.c" 30 31#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS 32# if defined USB_ETH_RNDIS 33# undef USB_ETH_RNDIS 34# endif 35# ifdef CONFIG_USB_FUNCTIONFS_RNDIS 36# define USB_ETH_RNDIS y 37# endif 38 39# include "f_ecm.c" 40# include "f_subset.c" 41# ifdef USB_ETH_RNDIS 42# include "f_rndis.c" 43# include "rndis.c" 44# endif 45# include "u_ether.c" 46 47static u8 gfs_hostaddr[ETH_ALEN]; 48# ifdef CONFIG_USB_FUNCTIONFS_ETH 49static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); 50# endif 51#else 52# define gether_cleanup() do { } while (0) 53# define gether_setup(gadget, hostaddr) ((int)0) 54# define gfs_hostaddr NULL 55#endif 56 57#include "f_fs.c" 58 59#define DRIVER_NAME "g_ffs" 60#define DRIVER_DESC "USB Function Filesystem" 61#define DRIVER_VERSION "24 Aug 2004" 62 63MODULE_DESCRIPTION(DRIVER_DESC); 64MODULE_AUTHOR("Michal Nazarewicz"); 65MODULE_LICENSE("GPL"); 66 67#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */ 68#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */ 69 70#define GFS_MAX_DEVS 10 71 72struct gfs_ffs_obj { 73 const char *name; 74 bool mounted; 75 bool desc_ready; 76 struct ffs_data *ffs_data; 77}; 78 79static struct usb_device_descriptor gfs_dev_desc = { 80 .bLength = sizeof gfs_dev_desc, 81 .bDescriptorType = USB_DT_DEVICE, 82 83 .bcdUSB = cpu_to_le16(0x0200), 84 .bDeviceClass = USB_CLASS_PER_INTERFACE, 85 86 .idVendor = cpu_to_le16(GFS_VENDOR_ID), 87 .idProduct = cpu_to_le16(GFS_PRODUCT_ID), 88}; 89 90static char *func_names[GFS_MAX_DEVS]; 91static unsigned int func_num; 92 93module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644); 94MODULE_PARM_DESC(bDeviceClass, "USB Device class"); 95module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644); 96MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass"); 97module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644); 98MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol"); 99module_param_array_named(functions, func_names, charp, &func_num, 0); 100MODULE_PARM_DESC(functions, "USB Functions list"); 101 102static const struct usb_descriptor_header *gfs_otg_desc[] = { 103 (const struct usb_descriptor_header *) 104 &(const struct usb_otg_descriptor) { 105 .bLength = sizeof(struct usb_otg_descriptor), 106 .bDescriptorType = USB_DT_OTG, 107 108 /* 109 * REVISIT SRP-only hardware is possible, although 110 * it would not be called "OTG" ... 111 */ 112 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 113 }, 114 115 NULL 116}; 117 118/* String IDs are assigned dynamically */ 119static struct usb_string gfs_strings[] = { 120#ifdef CONFIG_USB_FUNCTIONFS_RNDIS 121 { .s = "FunctionFS + RNDIS" }, 122#endif 123#ifdef CONFIG_USB_FUNCTIONFS_ETH 124 { .s = "FunctionFS + ECM" }, 125#endif 126#ifdef CONFIG_USB_FUNCTIONFS_GENERIC 127 { .s = "FunctionFS" }, 128#endif 129 { } /* end of list */ 130}; 131 132static struct usb_gadget_strings *gfs_dev_strings[] = { 133 &(struct usb_gadget_strings) { 134 .language = 0x0409, /* en-us */ 135 .strings = gfs_strings, 136 }, 137 NULL, 138}; 139 140struct gfs_configuration { 141 struct usb_configuration c; 142 int (*eth)(struct usb_configuration *c, u8 *ethaddr); 143} gfs_configurations[] = { 144#ifdef CONFIG_USB_FUNCTIONFS_RNDIS 145 { 146 .eth = rndis_bind_config, 147 }, 148#endif 149 150#ifdef CONFIG_USB_FUNCTIONFS_ETH 151 { 152 .eth = eth_bind_config, 153 }, 154#endif 155 156#ifdef CONFIG_USB_FUNCTIONFS_GENERIC 157 { 158 }, 159#endif 160}; 161 162static int gfs_bind(struct usb_composite_dev *cdev); 163static int gfs_unbind(struct usb_composite_dev *cdev); 164static int gfs_do_config(struct usb_configuration *c); 165 166static struct usb_composite_driver gfs_driver = { 167 .name = DRIVER_NAME, 168 .dev = &gfs_dev_desc, 169 .strings = gfs_dev_strings, 170 .max_speed = USB_SPEED_HIGH, 171 .unbind = gfs_unbind, 172 .iProduct = DRIVER_DESC, 173}; 174 175static DEFINE_MUTEX(gfs_lock); 176static unsigned int missing_funcs; 177static bool gfs_ether_setup; 178static bool gfs_registered; 179static bool gfs_single_func; 180static struct gfs_ffs_obj *ffs_tab; 181 182static int __init gfs_init(void) 183{ 184 int i; 185 186 ENTER(); 187 188 if (!func_num) { 189 gfs_single_func = true; 190 func_num = 1; 191 } 192 193 ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL); 194 if (!ffs_tab) 195 return -ENOMEM; 196 197 if (!gfs_single_func) 198 for (i = 0; i < func_num; i++) 199 ffs_tab[i].name = func_names[i]; 200 201 missing_funcs = func_num; 202 203 return functionfs_init(); 204} 205module_init(gfs_init); 206 207static void __exit gfs_exit(void) 208{ 209 ENTER(); 210 mutex_lock(&gfs_lock); 211 212 if (gfs_registered) 213 usb_composite_unregister(&gfs_driver); 214 gfs_registered = false; 215 216 functionfs_cleanup(); 217 218 mutex_unlock(&gfs_lock); 219 kfree(ffs_tab); 220} 221module_exit(gfs_exit); 222 223static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name) 224{ 225 int i; 226 227 ENTER(); 228 229 if (gfs_single_func) 230 return &ffs_tab[0]; 231 232 for (i = 0; i < func_num; i++) 233 if (strcmp(ffs_tab[i].name, dev_name) == 0) 234 return &ffs_tab[i]; 235 236 return NULL; 237} 238 239static int functionfs_ready_callback(struct ffs_data *ffs) 240{ 241 struct gfs_ffs_obj *ffs_obj; 242 int ret; 243 244 ENTER(); 245 mutex_lock(&gfs_lock); 246 247 ffs_obj = ffs->private_data; 248 if (!ffs_obj) { 249 ret = -EINVAL; 250 goto done; 251 } 252 253 if (WARN_ON(ffs_obj->desc_ready)) { 254 ret = -EBUSY; 255 goto done; 256 } 257 ffs_obj->desc_ready = true; 258 ffs_obj->ffs_data = ffs; 259 260 if (--missing_funcs) { 261 ret = 0; 262 goto done; 263 } 264 265 if (gfs_registered) { 266 ret = -EBUSY; 267 goto done; 268 } 269 gfs_registered = true; 270 271 ret = usb_composite_probe(&gfs_driver, gfs_bind); 272 if (unlikely(ret < 0)) 273 gfs_registered = false; 274 275done: 276 mutex_unlock(&gfs_lock); 277 return ret; 278} 279 280static void functionfs_closed_callback(struct ffs_data *ffs) 281{ 282 struct gfs_ffs_obj *ffs_obj; 283 284 ENTER(); 285 mutex_lock(&gfs_lock); 286 287 ffs_obj = ffs->private_data; 288 if (!ffs_obj) 289 goto done; 290 291 ffs_obj->desc_ready = false; 292 missing_funcs++; 293 294 if (gfs_registered) 295 usb_composite_unregister(&gfs_driver); 296 gfs_registered = false; 297 298done: 299 mutex_unlock(&gfs_lock); 300} 301 302static void *functionfs_acquire_dev_callback(const char *dev_name) 303{ 304 struct gfs_ffs_obj *ffs_dev; 305 306 ENTER(); 307 mutex_lock(&gfs_lock); 308 309 ffs_dev = gfs_find_dev(dev_name); 310 if (!ffs_dev) { 311 ffs_dev = ERR_PTR(-ENODEV); 312 goto done; 313 } 314 315 if (ffs_dev->mounted) { 316 ffs_dev = ERR_PTR(-EBUSY); 317 goto done; 318 } 319 ffs_dev->mounted = true; 320 321done: 322 mutex_unlock(&gfs_lock); 323 return ffs_dev; 324} 325 326static void functionfs_release_dev_callback(struct ffs_data *ffs_data) 327{ 328 struct gfs_ffs_obj *ffs_dev; 329 330 ENTER(); 331 mutex_lock(&gfs_lock); 332 333 ffs_dev = ffs_data->private_data; 334 if (ffs_dev) 335 ffs_dev->mounted = false; 336 337 mutex_unlock(&gfs_lock); 338} 339 340/* 341 * It is assumed that gfs_bind is called from a context where gfs_lock is held 342 */ 343static int gfs_bind(struct usb_composite_dev *cdev) 344{ 345 int ret, i; 346 347 ENTER(); 348 349 if (missing_funcs) 350 return -ENODEV; 351 352 ret = gether_setup(cdev->gadget, gfs_hostaddr); 353 if (unlikely(ret < 0)) 354 goto error_quick; 355 gfs_ether_setup = true; 356 357 ret = usb_string_ids_tab(cdev, gfs_strings); 358 if (unlikely(ret < 0)) 359 goto error; 360 361 for (i = func_num; --i; ) { 362 ret = functionfs_bind(ffs_tab[i].ffs_data, cdev); 363 if (unlikely(ret < 0)) { 364 while (++i < func_num) 365 functionfs_unbind(ffs_tab[i].ffs_data); 366 goto error; 367 } 368 } 369 370 for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { 371 struct gfs_configuration *c = gfs_configurations + i; 372 373 c->c.label = gfs_strings[i].s; 374 c->c.iConfiguration = gfs_strings[i].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 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