/* * Gadget Driver for Android * * Copyright (C) 2008 Google, Inc. * Author: Mike Lockwood * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ /* #define DEBUG */ /* #define VERBOSE_DEBUG */ #include #include #include #include #include #include #include #include #include #include #include #include "gadget_chips.h" /* * Kbuild is not very cooperative with respect to linking separately * compiled library objects into one module. So for now we won't use * separate compilation ... ensuring init/exit sections work to shrink * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "usbstring.c" #include "config.c" #include "epautoconf.c" #include "composite.c" MODULE_AUTHOR("Mike Lockwood"); MODULE_DESCRIPTION("Android Composite USB Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0"); static const char longname[] = "Gadget Android"; /* Default vendor and product IDs, overridden by platform data */ #define VENDOR_ID 0x18D1 #define PRODUCT_ID 0x0001 struct android_dev { struct usb_composite_dev *cdev; struct usb_configuration *config; int num_products; struct android_usb_product *products; int num_functions; char **functions; int product_id; int version; }; static struct android_dev *_android_dev; /* string IDs are assigned dynamically */ #define STRING_MANUFACTURER_IDX 0 #define STRING_PRODUCT_IDX 1 #define STRING_SERIAL_IDX 2 /* String Table */ static struct usb_string strings_dev[] = { /* These dummy values should be overridden by platform data */ [STRING_MANUFACTURER_IDX].s = "Android", [STRING_PRODUCT_IDX].s = "Android", [STRING_SERIAL_IDX].s = "0123456789ABCDEF", { } /* end of list */ }; static struct usb_gadget_strings stringtab_dev = { .language = 0x0409, /* en-us */ .strings = strings_dev, }; static struct usb_gadget_strings *dev_strings[] = { &stringtab_dev, NULL, }; static struct usb_device_descriptor device_desc = { .bLength = sizeof(device_desc), .bDescriptorType = USB_DT_DEVICE, .bcdUSB = __constant_cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, .idVendor = __constant_cpu_to_le16(VENDOR_ID), .idProduct = __constant_cpu_to_le16(PRODUCT_ID), .bcdDevice = __constant_cpu_to_le16(0xffff), .bNumConfigurations = 1, }; static struct list_head _functions = LIST_HEAD_INIT(_functions); static int _registered_function_count = 0; void android_usb_set_connected(int connected) { if (_android_dev && _android_dev->cdev && _android_dev->cdev->gadget) { if (connected) usb_gadget_connect(_android_dev->cdev->gadget); else usb_gadget_disconnect(_android_dev->cdev->gadget); } } static struct android_usb_function *get_function(const char *name) { struct android_usb_function *f; list_for_each_entry(f, &_functions, list) { if (!strcmp(name, f->name)) return f; } return 0; } static void bind_functions(struct android_dev *dev) { struct android_usb_function *f; char **functions = dev->functions; int i; for (i = 0; i < dev->num_functions; i++) { char *name = *functions++; f = get_function(name); if (f) f->bind_config(dev->config); else printk(KERN_ERR "function %s not found in bind_functions\n", name); } } static int __init android_bind_config(struct usb_configuration *c) { struct android_dev *dev = _android_dev; printk(KERN_DEBUG "android_bind_config\n"); dev->config = c; /* bind our functions if they have all registered */ if (_registered_function_count == dev->num_functions) bind_functions(dev); return 0; } static int android_setup_config(struct usb_configuration *c, const struct usb_ctrlrequest *ctrl); static struct usb_configuration android_config_driver = { .label = "android", .bind = android_bind_config, .setup = android_setup_config, .bConfigurationValue = 1, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, .bMaxPower = 0xFA, /* 500ma */ }; static int android_setup_config(struct usb_configuration *c, const struct usb_ctrlrequest *ctrl) { int i; int ret = -EOPNOTSUPP; for (i = 0; i < android_config_driver.next_interface_id; i++) { if (android_config_driver.interface[i]->setup) { ret = android_config_driver.interface[i]->setup( android_config_driver.interface[i], ctrl); if (ret >= 0) return ret; } } return ret; } static int product_has_function(struct android_usb_product *p, struct usb_function *f) { char **functions = p->functions; int count = p->num_functions; const char *name = f->name; int i; for (i = 0; i < count; i++) { if (!strcmp(name, *functions++)) return 1; } return 0; } static int product_matches_functions(struct android_usb_product *p) { struct usb_function *f; list_for_each_entry(f, &android_config_driver.functions, list) { if (product_has_function(p, f) == !!f->hidden) return 0; } return 1; } static int get_product_id(struct android_dev *dev) { struct android_usb_product *p = dev->products; int count = dev->num_products; int i; if (p) { for (i = 0; i < count; i++, p++) { if (product_matches_functions(p)) return p->product_id; } } /* use default product ID */ return dev->product_id; } static int __init android_bind(struct usb_composite_dev *cdev) { struct android_dev *dev = _android_dev; struct usb_gadget *gadget = cdev->gadget; int gcnum, id, product_id, ret; printk(KERN_INFO "android_bind\n"); /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ id = usb_string_id(cdev); if (id < 0) return id; strings_dev[STRING_MANUFACTURER_IDX].id = id; device_desc.iManufacturer = id; id = usb_string_id(cdev); if (id < 0) return id; strings_dev[STRING_PRODUCT_IDX].id = id; device_desc.iProduct = id; id = usb_string_id(cdev); if (id < 0) return id; strings_dev[STRING_SERIAL_IDX].id = id; device_desc.iSerialNumber = id; if (gadget->ops->wakeup) android_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; /* register our configuration */ ret = usb_add_config(cdev, &android_config_driver); if (ret) { printk(KERN_ERR "usb_add_config failed\n"); return ret; } gcnum = usb_gadget_controller_number(gadget); if (gcnum >= 0) device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); else { /* gadget zero is so simple (for now, no altsettings) that * it SHOULD NOT have problems with bulk-capable hardware. * so just warn about unrcognized controllers -- don't panic. * * things like configuration and altsetting numbering * can need hardware-specific attention though. */ pr_warning("%s: controller '%s' not recognized\n", longname, gadget->name); device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); } usb_gadget_set_selfpowered(gadget); dev->cdev = cdev; product_id = get_product_id(dev); device_desc.idProduct = __constant_cpu_to_le16(product_id); cdev->desc.idProduct = device_desc.idProduct; return 0; } static struct usb_composite_driver android_usb_driver = { .name = "android_usb", .dev = &device_desc, .strings = dev_strings, .bind = android_bind, }; void android_register_function(struct android_usb_function *f) { struct android_dev *dev = _android_dev; printk(KERN_INFO "android_register_function\n"); list_add_tail(&f->list, &_functions); _registered_function_count++; /* bind our functions if they have all registered * and the main driver has bound. */ if (dev->config && _registered_function_count == dev->num_functions) bind_functions(dev); } void android_enable_function(struct usb_function *f, int enable) { struct android_dev *dev = _android_dev; int disable = !enable; int product_id; if (!!f->hidden != disable) { f->hidden = disable; product_id = get_product_id(dev); device_desc.idProduct = __constant_cpu_to_le16(product_id); if (dev->cdev) dev->cdev->desc.idProduct = device_desc.idProduct; /* force reenumeration */ if (dev->cdev && dev->cdev->gadget && dev->cdev->gadget->speed != USB_SPEED_UNKNOWN) { usb_gadget_disconnect(dev->cdev->gadget); msleep(10); usb_gadget_connect(dev->cdev->gadget); } } } static int __init android_probe(struct platform_device *pdev) { struct android_usb_platform_data *pdata = pdev->dev.platform_data; struct android_dev *dev = _android_dev; printk(KERN_INFO "android_probe pdata: %p\n", pdata); if (pdata) { dev->products = pdata->products; dev->num_products = pdata->num_products; dev->functions = pdata->functions; dev->num_functions = pdata->num_functions; if (pdata->vendor_id) device_desc.idVendor = __constant_cpu_to_le16(pdata->vendor_id); if (pdata->product_id) { dev->product_id = pdata->product_id; device_desc.idProduct = __constant_cpu_to_le16(pdata->product_id); } if (pdata->version) dev->version = pdata->version; if (pdata->product_name) strings_dev[STRING_PRODUCT_IDX].s = pdata->product_name; if (pdata->manufacturer_name) strings_dev[STRING_MANUFACTURER_IDX].s = pdata->manufacturer_name; if (pdata->serial_number) strings_dev[STRING_SERIAL_IDX].s = pdata->serial_number; } return usb_composite_register(&android_usb_driver); } static struct platform_driver android_platform_driver = { .driver = { .name = "android_usb", }, .probe = android_probe, }; static int __init init(void) { struct android_dev *dev; printk(KERN_INFO "android init\n"); dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; /* set default values, which should be overridden by platform data */ dev->product_id = PRODUCT_ID; _android_dev = dev; return platform_driver_register(&android_platform_driver); } module_init(init); static void __exit cleanup(void) { usb_composite_unregister(&android_usb_driver); platform_driver_unregister(&android_platform_driver); kfree(_android_dev); _android_dev = NULL; } module_exit(cleanup);