1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285 |
- /*
- * Gadget Driver for Android
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * 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 <linux/init.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/delay.h>
- #include <linux/kernel.h>
- #include <linux/utsname.h>
- #include <linux/platform_device.h>
- #include <linux/usb/ch9.h>
- #include <linux/usb/composite.h>
- #include <linux/usb/gadget.h>
- #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"
- #include "f_mass_storage.c"
- #include "u_serial.c"
- #include "f_acm.c"
- #include "f_adb.c"
- #include "f_mtp.c"
- #include "f_accessory.c"
- #define USB_ETH_RNDIS y
- #include "f_rndis.c"
- #include "rndis.c"
- #include "u_ether.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 userspace */
- #define VENDOR_ID 0x18D1
- #define PRODUCT_ID 0x0001
- struct android_usb_function {
- char *name;
- void *config;
- struct device *dev;
- char *dev_name;
- struct device_attribute **attributes;
- /* for android_dev.enabled_functions */
- struct list_head enabled_list;
- /* Optional: initialization during gadget bind */
- int (*init)(struct android_usb_function *, struct usb_composite_dev *);
- /* Optional: cleanup during gadget unbind */
- void (*cleanup)(struct android_usb_function *);
- /* Optional: called when the function is added the list of
- * enabled functions */
- void (*enable)(struct android_usb_function *);
- /* Optional: called when it is removed */
- void (*disable)(struct android_usb_function *);
- int (*bind_config)(struct android_usb_function *, struct usb_configuration *);
- /* Optional: called when the configuration is removed */
- void (*unbind_config)(struct android_usb_function *, struct usb_configuration *);
- /* Optional: handle ctrl requests before the device is configured */
- int (*ctrlrequest)(struct android_usb_function *,
- struct usb_composite_dev *,
- const struct usb_ctrlrequest *);
- };
- struct android_dev {
- struct android_usb_function **functions;
- struct list_head enabled_functions;
- struct usb_composite_dev *cdev;
- struct device *dev;
- bool enabled;
- int disable_depth;
- struct mutex mutex;
- bool connected;
- bool sw_connected;
- struct work_struct work;
- };
- static struct class *android_class;
- static struct android_dev *_android_dev;
- static int android_bind_config(struct usb_configuration *c);
- static void android_unbind_config(struct usb_configuration *c);
- /* string IDs are assigned dynamically */
- #define STRING_MANUFACTURER_IDX 0
- #define STRING_PRODUCT_IDX 1
- #define STRING_SERIAL_IDX 2
- static char manufacturer_string[256];
- static char product_string[256];
- static char serial_string[256];
- /* String Table */
- static struct usb_string strings_dev[] = {
- [STRING_MANUFACTURER_IDX].s = manufacturer_string,
- [STRING_PRODUCT_IDX].s = product_string,
- [STRING_SERIAL_IDX].s = serial_string,
- { } /* 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 usb_configuration android_config_driver = {
- .label = "android",
- .unbind = android_unbind_config,
- .bConfigurationValue = 1,
- };
- static void android_work(struct work_struct *data)
- {
- struct android_dev *dev = container_of(data, struct android_dev, work);
- struct usb_composite_dev *cdev = dev->cdev;
- char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
- char *connected[2] = { "USB_STATE=CONNECTED", NULL };
- char *configured[2] = { "USB_STATE=CONFIGURED", NULL };
- char **uevent_envp = NULL;
- unsigned long flags;
- spin_lock_irqsave(&cdev->lock, flags);
- if (cdev->config)
- uevent_envp = configured;
- else if (dev->connected != dev->sw_connected)
- uevent_envp = dev->connected ? connected : disconnected;
- dev->sw_connected = dev->connected;
- spin_unlock_irqrestore(&cdev->lock, flags);
- if (uevent_envp) {
- kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);
- pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]);
- } else {
- pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
- dev->connected, dev->sw_connected, cdev->config);
- }
- }
- static void android_enable(struct android_dev *dev)
- {
- struct usb_composite_dev *cdev = dev->cdev;
- BUG_ON(!mutex_is_locked(&dev->mutex));
- BUG_ON(!dev->disable_depth);
- if (--dev->disable_depth == 0) {
- usb_add_config(cdev, &android_config_driver,
- android_bind_config);
- usb_gadget_connect(cdev->gadget);
- }
- }
- static void android_disable(struct android_dev *dev)
- {
- struct usb_composite_dev *cdev = dev->cdev;
- BUG_ON(!mutex_is_locked(&dev->mutex));
- if (dev->disable_depth++ == 0) {
- usb_gadget_disconnect(cdev->gadget);
- /* Cancel pending control requests */
- usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
- usb_remove_config(cdev, &android_config_driver);
- }
- }
- /*-------------------------------------------------------------------------*/
- /* Supported functions initialization */
- struct adb_data {
- bool opened;
- bool enabled;
- };
- static int adb_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
- {
- f->config = kzalloc(sizeof(struct adb_data), GFP_KERNEL);
- if (!f->config)
- return -ENOMEM;
- return adb_setup();
- }
- static void adb_function_cleanup(struct android_usb_function *f)
- {
- adb_cleanup();
- kfree(f->config);
- }
- static int adb_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
- {
- return adb_bind_config(c);
- }
- static void adb_android_function_enable(struct android_usb_function *f)
- {
- struct android_dev *dev = _android_dev;
- struct adb_data *data = f->config;
- data->enabled = true;
- /* Disable the gadget until adbd is ready */
- if (!data->opened)
- android_disable(dev);
- }
- static void adb_android_function_disable(struct android_usb_function *f)
- {
- struct android_dev *dev = _android_dev;
- struct adb_data *data = f->config;
- data->enabled = false;
- /* Balance the disable that was called in closed_callback */
- if (!data->opened)
- android_enable(dev);
- }
- static struct android_usb_function adb_function = {
- .name = "adb",
- .enable = adb_android_function_enable,
- .disable = adb_android_function_disable,
- .init = adb_function_init,
- .cleanup = adb_function_cleanup,
- .bind_config = adb_function_bind_config,
- };
- static void adb_ready_callback(void)
- {
- struct android_dev *dev = _android_dev;
- struct adb_data *data = adb_function.config;
- mutex_lock(&dev->mutex);
- data->opened = true;
- if (data->enabled)
- android_enable(dev);
- mutex_unlock(&dev->mutex);
- }
- static void adb_closed_callback(void)
- {
- struct android_dev *dev = _android_dev;
- struct adb_data *data = adb_function.config;
- mutex_lock(&dev->mutex);
- data->opened = false;
- if (data->enabled)
- android_disable(dev);
- mutex_unlock(&dev->mutex);
- }
- #define MAX_ACM_INSTANCES 4
- struct acm_function_config {
- int instances;
- };
- static int acm_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
- {
- f->config = kzalloc(sizeof(struct acm_function_config), GFP_KERNEL);
- if (!f->config)
- return -ENOMEM;
- return gserial_setup(cdev->gadget, MAX_ACM_INSTANCES);
- }
- static void acm_function_cleanup(struct android_usb_function *f)
- {
- gserial_cleanup();
- kfree(f->config);
- f->config = NULL;
- }
- static int acm_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
- {
- int i;
- int ret = 0;
- struct acm_function_config *config = f->config;
- for (i = 0; i < config->instances; i++) {
- ret = acm_bind_config(c, i);
- if (ret) {
- pr_err("Could not bind acm%u config\n", i);
- break;
- }
- }
- return ret;
- }
- static ssize_t acm_instances_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct acm_function_config *config = f->config;
- return sprintf(buf, "%d\n", config->instances);
- }
- static ssize_t acm_instances_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct acm_function_config *config = f->config;
- int value;
- sscanf(buf, "%d", &value);
- if (value > MAX_ACM_INSTANCES)
- value = MAX_ACM_INSTANCES;
- config->instances = value;
- return size;
- }
- static DEVICE_ATTR(instances, S_IRUGO | S_IWUSR, acm_instances_show, acm_instances_store);
- static struct device_attribute *acm_function_attributes[] = { &dev_attr_instances, NULL };
- static struct android_usb_function acm_function = {
- .name = "acm",
- .init = acm_function_init,
- .cleanup = acm_function_cleanup,
- .bind_config = acm_function_bind_config,
- .attributes = acm_function_attributes,
- };
- static int mtp_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
- {
- return mtp_setup();
- }
- static void mtp_function_cleanup(struct android_usb_function *f)
- {
- mtp_cleanup();
- }
- static int mtp_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
- {
- return mtp_bind_config(c, false);
- }
- static int ptp_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
- {
- /* nothing to do - initialization is handled by mtp_function_init */
- return 0;
- }
- static void ptp_function_cleanup(struct android_usb_function *f)
- {
- /* nothing to do - cleanup is handled by mtp_function_cleanup */
- }
- static int ptp_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
- {
- return mtp_bind_config(c, true);
- }
- static int mtp_function_ctrlrequest(struct android_usb_function *f,
- struct usb_composite_dev *cdev,
- const struct usb_ctrlrequest *c)
- {
- return mtp_ctrlrequest(cdev, c);
- }
- static struct android_usb_function mtp_function = {
- .name = "mtp",
- .init = mtp_function_init,
- .cleanup = mtp_function_cleanup,
- .bind_config = mtp_function_bind_config,
- .ctrlrequest = mtp_function_ctrlrequest,
- };
- /* PTP function is same as MTP with slightly different interface descriptor */
- static struct android_usb_function ptp_function = {
- .name = "ptp",
- .init = ptp_function_init,
- .cleanup = ptp_function_cleanup,
- .bind_config = ptp_function_bind_config,
- };
- struct rndis_function_config {
- u8 ethaddr[ETH_ALEN];
- u32 vendorID;
- char manufacturer[256];
- bool wceis;
- };
- static int rndis_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
- {
- f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
- if (!f->config)
- return -ENOMEM;
- return 0;
- }
- static void rndis_function_cleanup(struct android_usb_function *f)
- {
- kfree(f->config);
- f->config = NULL;
- }
- static int rndis_function_bind_config(struct android_usb_function *f,
- struct usb_configuration *c)
- {
- int ret;
- struct rndis_function_config *rndis = f->config;
- if (!rndis) {
- pr_err("%s: rndis_pdata\n", __func__);
- return -1;
- }
- pr_info("%s MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", __func__,
- rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
- rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
- ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
- if (ret) {
- pr_err("%s: gether_setup failed\n", __func__);
- return ret;
- }
- if (rndis->wceis) {
- /* "Wireless" RNDIS; auto-detected by Windows */
- rndis_iad_descriptor.bFunctionClass =
- USB_CLASS_WIRELESS_CONTROLLER;
- rndis_iad_descriptor.bFunctionSubClass = 0x01;
- rndis_iad_descriptor.bFunctionProtocol = 0x03;
- rndis_control_intf.bInterfaceClass =
- USB_CLASS_WIRELESS_CONTROLLER;
- rndis_control_intf.bInterfaceSubClass = 0x01;
- rndis_control_intf.bInterfaceProtocol = 0x03;
- }
- return rndis_bind_config(c, rndis->ethaddr, rndis->vendorID,
- rndis->manufacturer);
- }
- static void rndis_function_unbind_config(struct android_usb_function *f,
- struct usb_configuration *c)
- {
- gether_cleanup();
- }
- static ssize_t rndis_manufacturer_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- return sprintf(buf, "%s\n", config->manufacturer);
- }
- static ssize_t rndis_manufacturer_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- if (size >= sizeof(config->manufacturer))
- return -EINVAL;
- if (sscanf(buf, "%s", config->manufacturer) == 1)
- return size;
- return -1;
- }
- static DEVICE_ATTR(manufacturer, S_IRUGO | S_IWUSR, rndis_manufacturer_show,
- rndis_manufacturer_store);
- static ssize_t rndis_wceis_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- return sprintf(buf, "%d\n", config->wceis);
- }
- static ssize_t rndis_wceis_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- int value;
- if (sscanf(buf, "%d", &value) == 1) {
- config->wceis = value;
- return size;
- }
- return -EINVAL;
- }
- static DEVICE_ATTR(wceis, S_IRUGO | S_IWUSR, rndis_wceis_show,
- rndis_wceis_store);
- static ssize_t rndis_ethaddr_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *rndis = f->config;
- return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
- rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
- rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
- }
- static ssize_t rndis_ethaddr_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *rndis = f->config;
- if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
- (int *)&rndis->ethaddr[0], (int *)&rndis->ethaddr[1],
- (int *)&rndis->ethaddr[2], (int *)&rndis->ethaddr[3],
- (int *)&rndis->ethaddr[4], (int *)&rndis->ethaddr[5]) == 6)
- return size;
- return -EINVAL;
- }
- static DEVICE_ATTR(ethaddr, S_IRUGO | S_IWUSR, rndis_ethaddr_show,
- rndis_ethaddr_store);
- static ssize_t rndis_vendorID_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- return sprintf(buf, "%04x\n", config->vendorID);
- }
- static ssize_t rndis_vendorID_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- int value;
- if (sscanf(buf, "%04x", &value) == 1) {
- config->vendorID = value;
- return size;
- }
- return -EINVAL;
- }
- static DEVICE_ATTR(vendorID, S_IRUGO | S_IWUSR, rndis_vendorID_show,
- rndis_vendorID_store);
- static struct device_attribute *rndis_function_attributes[] = {
- &dev_attr_manufacturer,
- &dev_attr_wceis,
- &dev_attr_ethaddr,
- &dev_attr_vendorID,
- NULL
- };
- static struct android_usb_function rndis_function = {
- .name = "rndis",
- .init = rndis_function_init,
- .cleanup = rndis_function_cleanup,
- .bind_config = rndis_function_bind_config,
- .unbind_config = rndis_function_unbind_config,
- .attributes = rndis_function_attributes,
- };
- struct mass_storage_function_config {
- struct fsg_config fsg;
- struct fsg_common *common;
- };
- static int mass_storage_function_init(struct android_usb_function *f,
- struct usb_composite_dev *cdev)
- {
- struct mass_storage_function_config *config;
- struct fsg_common *common;
- int err;
- config = kzalloc(sizeof(struct mass_storage_function_config),
- GFP_KERNEL);
- if (!config)
- return -ENOMEM;
- config->fsg.nluns = 1;
- config->fsg.luns[0].removable = 1;
- common = fsg_common_init(NULL, cdev, &config->fsg);
- if (IS_ERR(common)) {
- kfree(config);
- return PTR_ERR(common);
- }
- err = sysfs_create_link(&f->dev->kobj,
- &common->luns[0].dev.kobj,
- "lun");
- if (err) {
- kfree(config);
- return err;
- }
- config->common = common;
- f->config = config;
- return 0;
- }
- static void mass_storage_function_cleanup(struct android_usb_function *f)
- {
- kfree(f->config);
- f->config = NULL;
- }
- static int mass_storage_function_bind_config(struct android_usb_function *f,
- struct usb_configuration *c)
- {
- struct mass_storage_function_config *config = f->config;
- return fsg_bind_config(c->cdev, c, config->common);
- }
- static ssize_t mass_storage_inquiry_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct mass_storage_function_config *config = f->config;
- return sprintf(buf, "%s\n", config->common->inquiry_string);
- }
- static ssize_t mass_storage_inquiry_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct android_usb_function *f = dev_get_drvdata(dev);
- struct mass_storage_function_config *config = f->config;
- if (size >= sizeof(config->common->inquiry_string))
- return -EINVAL;
- if (sscanf(buf, "%s", config->common->inquiry_string) != 1)
- return -EINVAL;
- return size;
- }
- static DEVICE_ATTR(inquiry_string, S_IRUGO | S_IWUSR,
- mass_storage_inquiry_show,
- mass_storage_inquiry_store);
- static struct device_attribute *mass_storage_function_attributes[] = {
- &dev_attr_inquiry_string,
- NULL
- };
- static struct android_usb_function mass_storage_function = {
- .name = "mass_storage",
- .init = mass_storage_function_init,
- .cleanup = mass_storage_function_cleanup,
- .bind_config = mass_storage_function_bind_config,
- .attributes = mass_storage_function_attributes,
- };
- static int accessory_function_init(struct android_usb_function *f,
- struct usb_composite_dev *cdev)
- {
- return acc_setup();
- }
- static void accessory_function_cleanup(struct android_usb_function *f)
- {
- acc_cleanup();
- }
- static int accessory_function_bind_config(struct android_usb_function *f,
- struct usb_configuration *c)
- {
- return acc_bind_config(c);
- }
- static int accessory_function_ctrlrequest(struct android_usb_function *f,
- struct usb_composite_dev *cdev,
- const struct usb_ctrlrequest *c)
- {
- return acc_ctrlrequest(cdev, c);
- }
- static struct android_usb_function accessory_function = {
- .name = "accessory",
- .init = accessory_function_init,
- .cleanup = accessory_function_cleanup,
- .bind_config = accessory_function_bind_config,
- .ctrlrequest = accessory_function_ctrlrequest,
- };
- static struct android_usb_function *supported_functions[] = {
- &adb_function,
- &acm_function,
- &mtp_function,
- &ptp_function,
- &rndis_function,
- &mass_storage_function,
- &accessory_function,
- NULL
- };
- static int android_init_functions(struct android_usb_function **functions,
- struct usb_composite_dev *cdev)
- {
- struct android_dev *dev = _android_dev;
- struct android_usb_function *f;
- struct device_attribute **attrs;
- struct device_attribute *attr;
- int err;
- int index = 0;
- for (; (f = *functions++); index++) {
- f->dev_name = kasprintf(GFP_KERNEL, "f_%s", f->name);
- f->dev = device_create(android_class, dev->dev,
- MKDEV(0, index), f, f->dev_name);
- if (IS_ERR(f->dev)) {
- pr_err("%s: Failed to create dev %s", __func__,
- f->dev_name);
- err = PTR_ERR(f->dev);
- goto err_create;
- }
- if (f->init) {
- err = f->init(f, cdev);
- if (err) {
- pr_err("%s: Failed to init %s", __func__,
- f->name);
- goto err_out;
- }
- }
- attrs = f->attributes;
- if (attrs) {
- while ((attr = *attrs++) && !err)
- err = device_create_file(f->dev, attr);
- }
- if (err) {
- pr_err("%s: Failed to create function %s attributes",
- __func__, f->name);
- goto err_out;
- }
- }
- return 0;
- err_out:
- device_destroy(android_class, f->dev->devt);
- err_create:
- kfree(f->dev_name);
- return err;
- }
- static void android_cleanup_functions(struct android_usb_function **functions)
- {
- struct android_usb_function *f;
- while (*functions) {
- f = *functions++;
- if (f->dev) {
- device_destroy(android_class, f->dev->devt);
- kfree(f->dev_name);
- }
- if (f->cleanup)
- f->cleanup(f);
- }
- }
- static int
- android_bind_enabled_functions(struct android_dev *dev,
- struct usb_configuration *c)
- {
- struct android_usb_function *f;
- int ret;
- list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
- ret = f->bind_config(f, c);
- if (ret) {
- pr_err("%s: %s failed", __func__, f->name);
- return ret;
- }
- }
- return 0;
- }
- static void
- android_unbind_enabled_functions(struct android_dev *dev,
- struct usb_configuration *c)
- {
- struct android_usb_function *f;
- list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
- if (f->unbind_config)
- f->unbind_config(f, c);
- }
- }
- static int android_enable_function(struct android_dev *dev, char *name)
- {
- struct android_usb_function **functions = dev->functions;
- struct android_usb_function *f;
- while ((f = *functions++)) {
- if (!strcmp(name, f->name)) {
- list_add_tail(&f->enabled_list, &dev->enabled_functions);
- return 0;
- }
- }
- return -EINVAL;
- }
- /*-------------------------------------------------------------------------*/
- /* /sys/class/android_usb/android%d/ interface */
- static ssize_t
- functions_show(struct device *pdev, struct device_attribute *attr, char *buf)
- {
- struct android_dev *dev = dev_get_drvdata(pdev);
- struct android_usb_function *f;
- char *buff = buf;
- mutex_lock(&dev->mutex);
- list_for_each_entry(f, &dev->enabled_functions, enabled_list)
- buff += sprintf(buff, "%s,", f->name);
- mutex_unlock(&dev->mutex);
- if (buff != buf)
- *(buff-1) = '\n';
- return buff - buf;
- }
- static ssize_t
- functions_store(struct device *pdev, struct device_attribute *attr,
- const char *buff, size_t size)
- {
- struct android_dev *dev = dev_get_drvdata(pdev);
- char *name;
- char buf[256], *b;
- int err;
- mutex_lock(&dev->mutex);
- if (dev->enabled) {
- mutex_unlock(&dev->mutex);
- return -EBUSY;
- }
- INIT_LIST_HEAD(&dev->enabled_functions);
- strncpy(buf, buff, sizeof(buf));
- b = strim(buf);
- while (b) {
- name = strsep(&b, ",");
- if (name) {
- err = android_enable_function(dev, name);
- if (err)
- pr_err("android_usb: Cannot enable '%s'", name);
- }
- }
- mutex_unlock(&dev->mutex);
- return size;
- }
- static ssize_t enable_show(struct device *pdev, struct device_attribute *attr,
- char *buf)
- {
- struct android_dev *dev = dev_get_drvdata(pdev);
- return sprintf(buf, "%d\n", dev->enabled);
- }
- static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,
- const char *buff, size_t size)
- {
- struct android_dev *dev = dev_get_drvdata(pdev);
- struct usb_composite_dev *cdev = dev->cdev;
- struct android_usb_function *f;
- int enabled = 0;
- mutex_lock(&dev->mutex);
- sscanf(buff, "%d", &enabled);
- if (enabled && !dev->enabled) {
- /* update values in composite driver's copy of device descriptor */
- cdev->desc.idVendor = device_desc.idVendor;
- cdev->desc.idProduct = device_desc.idProduct;
- cdev->desc.bcdDevice = device_desc.bcdDevice;
- cdev->desc.bDeviceClass = device_desc.bDeviceClass;
- cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;
- cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
- list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
- if (f->enable)
- f->enable(f);
- }
- android_enable(dev);
- dev->enabled = true;
- } else if (!enabled && dev->enabled) {
- android_disable(dev);
- list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
- if (f->disable)
- f->disable(f);
- }
- dev->enabled = false;
- } else {
- pr_err("android_usb: already %s\n",
- dev->enabled ? "enabled" : "disabled");
- }
- mutex_unlock(&dev->mutex);
- return size;
- }
- static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
- char *buf)
- {
- struct android_dev *dev = dev_get_drvdata(pdev);
- struct usb_composite_dev *cdev = dev->cdev;
- char *state = "DISCONNECTED";
- unsigned long flags;
- if (!cdev)
- goto out;
- spin_lock_irqsave(&cdev->lock, flags);
- if (cdev->config)
- state = "CONFIGURED";
- else if (dev->connected)
- state = "CONNECTED";
- spin_unlock_irqrestore(&cdev->lock, flags);
- out:
- return sprintf(buf, "%s\n", state);
- }
- #define DESCRIPTOR_ATTR(field, format_string) \
- static ssize_t \
- field ## _show(struct device *dev, struct device_attribute *attr, \
- char *buf) \
- { \
- return sprintf(buf, format_string, device_desc.field); \
- } \
- static ssize_t \
- field ## _store(struct device *dev, struct device_attribute *attr, \
- const char *buf, size_t size) \
- { \
- int value; \
- if (sscanf(buf, format_string, &value) == 1) { \
- device_desc.field = value; \
- return size; \
- } \
- return -1; \
- } \
- static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
- #define DESCRIPTOR_STRING_ATTR(field, buffer) \
- static ssize_t \
- field ## _show(struct device *dev, struct device_attribute *attr, \
- char *buf) \
- { \
- return sprintf(buf, "%s", buffer); \
- } \
- static ssize_t \
- field ## _store(struct device *dev, struct device_attribute *attr, \
- const char *buf, size_t size) \
- { \
- if (size >= sizeof(buffer)) return -EINVAL; \
- if (sscanf(buf, "%s", buffer) == 1) { \
- return size; \
- } \
- return -1; \
- } \
- static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
- DESCRIPTOR_ATTR(idVendor, "%04x\n")
- DESCRIPTOR_ATTR(idProduct, "%04x\n")
- DESCRIPTOR_ATTR(bcdDevice, "%04x\n")
- DESCRIPTOR_ATTR(bDeviceClass, "%d\n")
- DESCRIPTOR_ATTR(bDeviceSubClass, "%d\n")
- DESCRIPTOR_ATTR(bDeviceProtocol, "%d\n")
- DESCRIPTOR_STRING_ATTR(iManufacturer, manufacturer_string)
- DESCRIPTOR_STRING_ATTR(iProduct, product_string)
- DESCRIPTOR_STRING_ATTR(iSerial, serial_string)
- static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show, functions_store);
- static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
- static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
- static struct device_attribute *android_usb_attributes[] = {
- &dev_attr_idVendor,
- &dev_attr_idProduct,
- &dev_attr_bcdDevice,
- &dev_attr_bDeviceClass,
- &dev_attr_bDeviceSubClass,
- &dev_attr_bDeviceProtocol,
- &dev_attr_iManufacturer,
- &dev_attr_iProduct,
- &dev_attr_iSerial,
- &dev_attr_functions,
- &dev_attr_enable,
- &dev_attr_state,
- NULL
- };
- /*-------------------------------------------------------------------------*/
- /* Composite driver */
- static int android_bind_config(struct usb_configuration *c)
- {
- struct android_dev *dev = _android_dev;
- int ret = 0;
- ret = android_bind_enabled_functions(dev, c);
- if (ret)
- return ret;
- return 0;
- }
- static void android_unbind_config(struct usb_configuration *c)
- {
- struct android_dev *dev = _android_dev;
- android_unbind_enabled_functions(dev, c);
- }
- static int android_bind(struct usb_composite_dev *cdev)
- {
- struct android_dev *dev = _android_dev;
- struct usb_gadget *gadget = cdev->gadget;
- int gcnum, id, ret;
- usb_gadget_disconnect(gadget);
- ret = android_init_functions(dev->functions, cdev);
- if (ret)
- return ret;
- /* 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;
- /* Default strings - should be updated by userspace */
- strncpy(manufacturer_string, "Android", sizeof(manufacturer_string) - 1);
- strncpy(product_string, "Android", sizeof(product_string) - 1);
- strncpy(serial_string, "0123456789ABCDEF", sizeof(serial_string) - 1);
- id = usb_string_id(cdev);
- if (id < 0)
- return id;
- strings_dev[STRING_SERIAL_IDX].id = id;
- device_desc.iSerialNumber = id;
- 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);
- }
- dev->cdev = cdev;
- return 0;
- }
- static int android_usb_unbind(struct usb_composite_dev *cdev)
- {
- struct android_dev *dev = _android_dev;
- cancel_work_sync(&dev->work);
- android_cleanup_functions(dev->functions);
- return 0;
- }
- static struct usb_composite_driver android_usb_driver = {
- .name = "android_usb",
- .dev = &device_desc,
- .strings = dev_strings,
- .unbind = android_usb_unbind,
- };
- static int
- android_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c)
- {
- struct android_dev *dev = _android_dev;
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
- struct usb_request *req = cdev->req;
- struct android_usb_function *f;
- int value = -EOPNOTSUPP;
- unsigned long flags;
- req->zero = 0;
- req->complete = composite_setup_complete;
- req->length = 0;
- gadget->ep0->driver_data = cdev;
- list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
- if (f->ctrlrequest) {
- value = f->ctrlrequest(f, cdev, c);
- if (value >= 0)
- break;
- }
- }
- /* Special case the accessory function.
- * It needs to handle control requests before it is enabled.
- */
- if (value < 0)
- value = acc_ctrlrequest(cdev, c);
- if (value < 0)
- value = composite_setup(gadget, c);
- spin_lock_irqsave(&cdev->lock, flags);
- if (!dev->connected) {
- dev->connected = 1;
- schedule_work(&dev->work);
- }
- else if (c->bRequest == USB_REQ_SET_CONFIGURATION && cdev->config) {
- schedule_work(&dev->work);
- }
- spin_unlock_irqrestore(&cdev->lock, flags);
- return value;
- }
- static void android_disconnect(struct usb_gadget *gadget)
- {
- struct android_dev *dev = _android_dev;
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
- unsigned long flags;
- composite_disconnect(gadget);
- spin_lock_irqsave(&cdev->lock, flags);
- dev->connected = 0;
- schedule_work(&dev->work);
- spin_unlock_irqrestore(&cdev->lock, flags);
- }
- static int android_create_device(struct android_dev *dev)
- {
- struct device_attribute **attrs = android_usb_attributes;
- struct device_attribute *attr;
- int err;
- dev->dev = device_create(android_class, NULL,
- MKDEV(0, 0), NULL, "android0");
- if (IS_ERR(dev->dev))
- return PTR_ERR(dev->dev);
- dev_set_drvdata(dev->dev, dev);
- while ((attr = *attrs++)) {
- err = device_create_file(dev->dev, attr);
- if (err) {
- device_destroy(android_class, dev->dev->devt);
- return err;
- }
- }
- return 0;
- }
- static int __init init(void)
- {
- struct android_dev *dev;
- int err;
- android_class = class_create(THIS_MODULE, "android_usb");
- if (IS_ERR(android_class))
- return PTR_ERR(android_class);
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
- dev->disable_depth = 1;
- dev->functions = supported_functions;
- INIT_LIST_HEAD(&dev->enabled_functions);
- INIT_WORK(&dev->work, android_work);
- mutex_init(&dev->mutex);
- err = android_create_device(dev);
- if (err) {
- class_destroy(android_class);
- kfree(dev);
- return err;
- }
- _android_dev = dev;
- /* Override composite driver functions */
- composite_driver.setup = android_setup;
- composite_driver.disconnect = android_disconnect;
- return usb_composite_probe(&android_usb_driver, android_bind);
- }
- module_init(init);
- static void __exit cleanup(void)
- {
- usb_composite_unregister(&android_usb_driver);
- class_destroy(android_class);
- kfree(_android_dev);
- _android_dev = NULL;
- }
- module_exit(cleanup);
|