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 17431928194b36a0f88082df875e2e036da7fddf 426 lines 10 kB view raw
1#include <linux/module.h> 2#include <linux/utsname.h> 3 4 5/* 6 * kbuild is not very cooperative with respect to linking separately 7 * compiled library objects into one module. So for now we won't use 8 * separate compilation ... ensuring init/exit sections work to shrink 9 * the runtime footprint, and giving us at least some parts of what 10 * a "gcc --combine ... part1.c part2.c part3.c ... " build would. 11 */ 12 13#include "composite.c" 14#include "usbstring.c" 15#include "config.c" 16#include "epautoconf.c" 17 18#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS 19# if defined USB_ETH_RNDIS 20# undef USB_ETH_RNDIS 21# endif 22# ifdef CONFIG_USB_FUNCTIONFS_RNDIS 23# define USB_ETH_RNDIS y 24# endif 25 26# include "f_ecm.c" 27# include "f_subset.c" 28# ifdef USB_ETH_RNDIS 29# include "f_rndis.c" 30# include "rndis.c" 31# endif 32# include "u_ether.c" 33 34static u8 gfs_hostaddr[ETH_ALEN]; 35#else 36# if !defined CONFIG_USB_FUNCTIONFS_GENERIC 37# define CONFIG_USB_FUNCTIONFS_GENERIC 38# endif 39# define gether_cleanup() do { } while (0) 40# define gether_setup(gadget, hostaddr) ((int)0) 41#endif 42 43#include "f_fs.c" 44 45 46#define DRIVER_NAME "g_ffs" 47#define DRIVER_DESC "USB Function Filesystem" 48#define DRIVER_VERSION "24 Aug 2004" 49 50MODULE_DESCRIPTION(DRIVER_DESC); 51MODULE_AUTHOR("Michal Nazarewicz"); 52MODULE_LICENSE("GPL"); 53 54 55static unsigned short gfs_vendor_id = 0x0525; /* XXX NetChip */ 56static unsigned short gfs_product_id = 0xa4ac; /* XXX */ 57 58static struct usb_device_descriptor gfs_dev_desc = { 59 .bLength = sizeof gfs_dev_desc, 60 .bDescriptorType = USB_DT_DEVICE, 61 62 .bcdUSB = cpu_to_le16(0x0200), 63 .bDeviceClass = USB_CLASS_PER_INTERFACE, 64 65 /* Vendor and product id can be overridden by module parameters. */ 66 /* .idVendor = cpu_to_le16(gfs_vendor_id), */ 67 /* .idProduct = cpu_to_le16(gfs_product_id), */ 68 /* .bcdDevice = f(hardware) */ 69 /* .iManufacturer = DYNAMIC */ 70 /* .iProduct = DYNAMIC */ 71 /* NO SERIAL NUMBER */ 72 .bNumConfigurations = 1, 73}; 74 75#define GFS_MODULE_PARAM_DESC(name, field) \ 76 MODULE_PARM_DESC(name, "Value of the " #field " field of the device descriptor sent to the host. Takes effect only prior to the user-space driver registering to the FunctionFS.") 77 78module_param_named(usb_class, gfs_dev_desc.bDeviceClass, byte, 0644); 79GFS_MODULE_PARAM_DESC(usb_class, bDeviceClass); 80module_param_named(usb_subclass, gfs_dev_desc.bDeviceSubClass, byte, 0644); 81GFS_MODULE_PARAM_DESC(usb_subclass, bDeviceSubClass); 82module_param_named(usb_protocol, gfs_dev_desc.bDeviceProtocol, byte, 0644); 83GFS_MODULE_PARAM_DESC(usb_protocol, bDeviceProtocol); 84module_param_named(usb_vendor, gfs_vendor_id, ushort, 0644); 85GFS_MODULE_PARAM_DESC(usb_vendor, idVendor); 86module_param_named(usb_product, gfs_product_id, ushort, 0644); 87GFS_MODULE_PARAM_DESC(usb_product, idProduct); 88 89 90 91static const struct usb_descriptor_header *gfs_otg_desc[] = { 92 (const struct usb_descriptor_header *) 93 &(const struct usb_otg_descriptor) { 94 .bLength = sizeof(struct usb_otg_descriptor), 95 .bDescriptorType = USB_DT_OTG, 96 97 /* REVISIT SRP-only hardware is possible, although 98 * it would not be called "OTG" ... */ 99 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 100 }, 101 102 NULL 103}; 104 105/* string IDs are assigned dynamically */ 106 107enum { 108 GFS_STRING_MANUFACTURER_IDX, 109 GFS_STRING_PRODUCT_IDX, 110#ifdef CONFIG_USB_FUNCTIONFS_RNDIS 111 GFS_STRING_RNDIS_CONFIG_IDX, 112#endif 113#ifdef CONFIG_USB_FUNCTIONFS_ETH 114 GFS_STRING_ECM_CONFIG_IDX, 115#endif 116#ifdef CONFIG_USB_FUNCTIONFS_GENERIC 117 GFS_STRING_GENERIC_CONFIG_IDX, 118#endif 119}; 120 121static char gfs_manufacturer[50]; 122static const char gfs_driver_desc[] = DRIVER_DESC; 123static const char gfs_short_name[] = DRIVER_NAME; 124 125static struct usb_string gfs_strings[] = { 126 [GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer, 127 [GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc, 128#ifdef CONFIG_USB_FUNCTIONFS_RNDIS 129 [GFS_STRING_RNDIS_CONFIG_IDX].s = "FunctionFS + RNDIS", 130#endif 131#ifdef CONFIG_USB_FUNCTIONFS_ETH 132 [GFS_STRING_ECM_CONFIG_IDX].s = "FunctionFS + ECM", 133#endif 134#ifdef CONFIG_USB_FUNCTIONFS_GENERIC 135 [GFS_STRING_GENERIC_CONFIG_IDX].s = "FunctionFS", 136#endif 137 { } /* end of list */ 138}; 139 140static struct usb_gadget_strings *gfs_dev_strings[] = { 141 &(struct usb_gadget_strings) { 142 .language = 0x0409, /* en-us */ 143 .strings = gfs_strings, 144 }, 145 NULL, 146}; 147 148 149#ifdef CONFIG_USB_FUNCTIONFS_RNDIS 150static int gfs_do_rndis_config(struct usb_configuration *c); 151 152static struct usb_configuration gfs_rndis_config_driver = { 153 .label = "FunctionFS + RNDIS", 154 .bind = gfs_do_rndis_config, 155 .bConfigurationValue = 1, 156 /* .iConfiguration = DYNAMIC */ 157 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 158}; 159# define gfs_add_rndis_config(cdev) \ 160 usb_add_config(cdev, &gfs_rndis_config_driver) 161#else 162# define gfs_add_rndis_config(cdev) 0 163#endif 164 165 166#ifdef CONFIG_USB_FUNCTIONFS_ETH 167static int gfs_do_ecm_config(struct usb_configuration *c); 168 169static struct usb_configuration gfs_ecm_config_driver = { 170 .label = "FunctionFS + ECM", 171 .bind = gfs_do_ecm_config, 172 .bConfigurationValue = 1, 173 /* .iConfiguration = DYNAMIC */ 174 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 175}; 176# define gfs_add_ecm_config(cdev) \ 177 usb_add_config(cdev, &gfs_ecm_config_driver) 178#else 179# define gfs_add_ecm_config(cdev) 0 180#endif 181 182 183#ifdef CONFIG_USB_FUNCTIONFS_GENERIC 184static int gfs_do_generic_config(struct usb_configuration *c); 185 186static struct usb_configuration gfs_generic_config_driver = { 187 .label = "FunctionFS", 188 .bind = gfs_do_generic_config, 189 .bConfigurationValue = 2, 190 /* .iConfiguration = DYNAMIC */ 191 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 192}; 193# define gfs_add_generic_config(cdev) \ 194 usb_add_config(cdev, &gfs_generic_config_driver) 195#else 196# define gfs_add_generic_config(cdev) 0 197#endif 198 199 200static int gfs_bind(struct usb_composite_dev *cdev); 201static int gfs_unbind(struct usb_composite_dev *cdev); 202 203static struct usb_composite_driver gfs_driver = { 204 .name = gfs_short_name, 205 .dev = &gfs_dev_desc, 206 .strings = gfs_dev_strings, 207 .bind = gfs_bind, 208 .unbind = gfs_unbind, 209}; 210 211 212static struct ffs_data *gfs_ffs_data; 213static unsigned long gfs_registered; 214 215 216static int gfs_init(void) 217{ 218 ENTER(); 219 220 return functionfs_init(); 221} 222module_init(gfs_init); 223 224static void gfs_exit(void) 225{ 226 ENTER(); 227 228 if (test_and_clear_bit(0, &gfs_registered)) 229 usb_composite_unregister(&gfs_driver); 230 231 functionfs_cleanup(); 232} 233module_exit(gfs_exit); 234 235 236static int functionfs_ready_callback(struct ffs_data *ffs) 237{ 238 int ret; 239 240 ENTER(); 241 242 if (WARN_ON(test_and_set_bit(0, &gfs_registered))) 243 return -EBUSY; 244 245 gfs_ffs_data = ffs; 246 ret = usb_composite_register(&gfs_driver); 247 if (unlikely(ret < 0)) 248 clear_bit(0, &gfs_registered); 249 return ret; 250} 251 252static void functionfs_closed_callback(struct ffs_data *ffs) 253{ 254 ENTER(); 255 256 if (test_and_clear_bit(0, &gfs_registered)) 257 usb_composite_unregister(&gfs_driver); 258} 259 260 261static int functionfs_check_dev_callback(const char *dev_name) 262{ 263 return 0; 264} 265 266 267 268static int gfs_bind(struct usb_composite_dev *cdev) 269{ 270 int ret; 271 272 ENTER(); 273 274 if (WARN_ON(!gfs_ffs_data)) 275 return -ENODEV; 276 277 ret = gether_setup(cdev->gadget, gfs_hostaddr); 278 if (unlikely(ret < 0)) 279 goto error_quick; 280 281 gfs_dev_desc.idVendor = cpu_to_le16(gfs_vendor_id); 282 gfs_dev_desc.idProduct = cpu_to_le16(gfs_product_id); 283 284 snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s", 285 init_utsname()->sysname, init_utsname()->release, 286 cdev->gadget->name); 287 ret = usb_string_id(cdev); 288 if (unlikely(ret < 0)) 289 goto error; 290 gfs_strings[GFS_STRING_MANUFACTURER_IDX].id = ret; 291 gfs_dev_desc.iManufacturer = ret; 292 293 ret = usb_string_id(cdev); 294 if (unlikely(ret < 0)) 295 goto error; 296 gfs_strings[GFS_STRING_PRODUCT_IDX].id = ret; 297 gfs_dev_desc.iProduct = ret; 298 299#ifdef CONFIG_USB_FUNCTIONFS_RNDIS 300 ret = usb_string_id(cdev); 301 if (unlikely(ret < 0)) 302 goto error; 303 gfs_strings[GFS_STRING_RNDIS_CONFIG_IDX].id = ret; 304 gfs_rndis_config_driver.iConfiguration = ret; 305#endif 306 307#ifdef CONFIG_USB_FUNCTIONFS_ETH 308 ret = usb_string_id(cdev); 309 if (unlikely(ret < 0)) 310 goto error; 311 gfs_strings[GFS_STRING_ECM_CONFIG_IDX].id = ret; 312 gfs_ecm_config_driver.iConfiguration = ret; 313#endif 314 315#ifdef CONFIG_USB_FUNCTIONFS_GENERIC 316 ret = usb_string_id(cdev); 317 if (unlikely(ret < 0)) 318 goto error; 319 gfs_strings[GFS_STRING_GENERIC_CONFIG_IDX].id = ret; 320 gfs_generic_config_driver.iConfiguration = ret; 321#endif 322 323 ret = functionfs_bind(gfs_ffs_data, cdev); 324 if (unlikely(ret < 0)) 325 goto error; 326 327 ret = gfs_add_rndis_config(cdev); 328 if (unlikely(ret < 0)) 329 goto error_unbind; 330 331 ret = gfs_add_ecm_config(cdev); 332 if (unlikely(ret < 0)) 333 goto error_unbind; 334 335 ret = gfs_add_generic_config(cdev); 336 if (unlikely(ret < 0)) 337 goto error_unbind; 338 339 return 0; 340 341error_unbind: 342 functionfs_unbind(gfs_ffs_data); 343error: 344 gether_cleanup(); 345error_quick: 346 gfs_ffs_data = NULL; 347 return ret; 348} 349 350static int gfs_unbind(struct usb_composite_dev *cdev) 351{ 352 ENTER(); 353 354 /* We may have been called in an error recovery frem 355 * composite_bind() after gfs_unbind() failure so we need to 356 * check if gfs_ffs_data is not NULL since gfs_bind() handles 357 * all error recovery itself. I'd rather we werent called 358 * from composite on orror recovery, but what you're gonna 359 * do...? */ 360 361 if (gfs_ffs_data) { 362 gether_cleanup(); 363 functionfs_unbind(gfs_ffs_data); 364 gfs_ffs_data = NULL; 365 } 366 367 return 0; 368} 369 370 371static int __gfs_do_config(struct usb_configuration *c, 372 int (*eth)(struct usb_configuration *c, u8 *ethaddr), 373 u8 *ethaddr) 374{ 375 int ret; 376 377 if (WARN_ON(!gfs_ffs_data)) 378 return -ENODEV; 379 380 if (gadget_is_otg(c->cdev->gadget)) { 381 c->descriptors = gfs_otg_desc; 382 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 383 } 384 385 if (eth) { 386 ret = eth(c, ethaddr); 387 if (unlikely(ret < 0)) 388 return ret; 389 } 390 391 ret = functionfs_add(c->cdev, c, gfs_ffs_data); 392 if (unlikely(ret < 0)) 393 return ret; 394 395 return 0; 396} 397 398#ifdef CONFIG_USB_FUNCTIONFS_RNDIS 399static int gfs_do_rndis_config(struct usb_configuration *c) 400{ 401 ENTER(); 402 403 return __gfs_do_config(c, rndis_bind_config, gfs_hostaddr); 404} 405#endif 406 407#ifdef CONFIG_USB_FUNCTIONFS_ETH 408static int gfs_do_ecm_config(struct usb_configuration *c) 409{ 410 ENTER(); 411 412 return __gfs_do_config(c, 413 can_support_ecm(c->cdev->gadget) 414 ? ecm_bind_config : geth_bind_config, 415 gfs_hostaddr); 416} 417#endif 418 419#ifdef CONFIG_USB_FUNCTIONFS_GENERIC 420static int gfs_do_generic_config(struct usb_configuration *c) 421{ 422 ENTER(); 423 424 return __gfs_do_config(c, NULL, NULL); 425} 426#endif