android 系统在 linux usb 模块中加入了 adb 功能,具体代码在 drivers/usb/gadget/android.c 中
1. init/exit:
static int __init init(void)
{
struct android_dev *dev;
printk(KERN_INFO "android init\n");
dev = kzalloc(sizeof(*dev), GFP_KERNEL); //分配 android_dev 内存
if (!dev)
return -ENOMEM;
/* set default values, which should be overridden by platform data */
dev->product_id = PRODUCT_ID; //product_id
_android_dev = dev; //_android_dev 是本地的全局变量
return platform_driver_register(&android_platform_driver); //注册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);
android_dev 定义:
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;
};
_android_dev 是一个本地定义的全局变量: static struct android_dev *_android_dev;
默认的 product_id 和 vendor_id 定义: /* Default vendor and product IDs, overridden by platform data */
#define VENDOR_ID 0x18D1
#define PRODUCT_ID 0x0001
struct android_platform_driver 定义: static struct platform_driver android_platform_driver = {
.driver = { .name = "android_usb", },
.probe = android_probe,
};
2. android_probe() static int android_probe(struct platform_device *pdev)
{
struct android_usb_platform_data *pdata = pdev->dev.platform_data; //从platform_data中获取内容
//platform_data中内容定义在board-xxx.c中,通过比较 .name (即android_usb) 来匹配。
struct android_dev *dev = _android_dev;
printk(KERN_INFO "android_probe pdata: %p\n", pdata);
if (pdata) {
dev->products = pdata->products; //android_usb_product
dev->num_products = pdata->num_products;
dev->functions = pdata->functions;
dev->num_functions = pdata->num_functions;
if (pdata->vendor_id)
device_desc.idVendor = //vendor_id
__constant_cpu_to_le16(pdata->vendor_id);
if (pdata->product_id) { //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_probe(&android_usb_driver, android_bind); //注册一个复杂的驱动
}
上面的 platform_data 内容定义在 board-xxx.c中: #ifdef CONFIG_USB_ANDROID //条件宏,如果没有可以不编译
#define GOOGLE_VENDOR_ID 0x18d1
#define GOOGLE_PRODUCT_ID 0x9018
#define GOOGLE_ADB_PRODUCT_ID 0x9015
static char *usb_functions_adb[] = { //所有的 function 只有一个 adb
"adb",
};
static char *usb_functions_all[] = {
"adb",
};
static struct android_usb_product usb_products[] = {
{
.product_id = GOOGLE_PRODUCT_ID,
.num_functions = ARRAY_SIZE(usb_functions_adb),
.functions = usb_functions_adb,
},
};
static struct android_usb_platform_data android_usb_pdata = {
.vendor_id = GOOGLE_VENDOR_ID,
.product_id = GOOGLE_PRODUCT_ID,
.functions = usb_functions_all,
.products = usb_products,
.version = 0x0100,
.product_name = "rowboat gadget",
.manufacturer_name = "rowboat",
.serial_number = "20100720",
.num_functions = ARRAY_SIZE(usb_functions_all),
};
static struct platform_device androidusb_device = {
.name = "android_usb", //这个名字是device名字,和上面的driver名字必须一样,用来匹配。
.id = -1,
.dev = {
.platform_data = &android_usb_pdata, //这个就是上面的platform_data
},
};
static void omap3evm_android_gadget_init(void)
{
platform_device_register(&androidusb_device); //上面定义,这里注册 platform_device 设备
}
#endif
3. usb_composite_probe(&android_usb_driver, android_bind);
/**
* usb_composite_probe() - register a composite driver
* @driver: the driver to register
* @bind: the callback used to allocate resources that are shared across the
* whole device, such as string IDs, and add its configurations using
* @usb_add_config(). This may fail by returning a negative errno
* value; it should return zero on successful initialization.
* Context: single threaded during gadget setup
*
* This function is used to register drivers using the composite driver
* framework. The return value is zero, or a negative errno value.
* Those values normally come from the driver's @bind method, which does
* all the work of setting up the driver to match the hardware.
*
* On successful return, the gadget is ready to respond to requests from
* the host, unless one of its components invokes usb_gadget_disconnect()
* while it was binding. That would usually be done in order to wait for
* some userspace participation.
*/
extern int usb_composite_probe(struct usb_composite_driver *driver,
int (*bind)(struct usb_composite_dev *cdev))
{
if (!driver || !driver->dev || !bind || composite)
return -EINVAL;
if (!driver->iProduct)
driver->iProduct = driver->name;
if (!driver->name)
driver->name = "composite";
composite_driver.function = (char *) driver->name;
composite_driver.driver.name = driver->name;
composite = driver;
composite_gadget_bind = bind;
driver->class = class_create(THIS_MODULE, "usb_composite"); //建立一新类 usb_composite
if (IS_ERR(driver->class))
return PTR_ERR(driver->class);
driver->class->dev_uevent = composite_uevent;
return usb_gadget_probe_driver(&composite_driver, composite_bind); //这里调到了musb模块
}
4. usb_gadget_probe_driver(&composite_driver, composite_bind);
这里继续分析android_usb_driver 和 android_bind。
1. android_usb_driver
static struct usb_composite_driver android_usb_driver = {
.name = "android_usb", //driver名
.dev = &device_desc, //usb_device_descriptor 内容
.strings = dev_strings,
.enable_function = android_enable_function,
};
a. usb_composite_driver 数据结构原型定义在 include/linux/usb/composite.h 中
/**
* struct usb_composite_driver - groups configurations into a gadget
* @name: For diagnostics, identifies the driver.
* @iProduct: Used as iProduct override if @dev->iProduct is not set.
* If NULL value of @name is taken.
* @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is
* not set. If NULL a default " with " value
* will be used.
* @dev: Template descriptor for the device, including default device
* identifiers.
* @strings: tables of strings, keyed by identifiers assigned during bind()
* and language IDs provided in control requests
* @needs_serial: set to 1 if the gadget needs userspace to provide
* a serial number. If one is not provided, warning will be printed.
* @unbind: Reverses bind; called as a side effect of unregistering
* this driver.
* @disconnect: optional driver disconnect method
* @suspend: Notifies when the host stops sending USB traffic,
* after function notifications
* @resume: Notifies configuration when the host restarts USB traffic,
* before function notifications
*
* Devices default to reporting self powered operation. Devices which rely
* on bus powered operation should report this in their @bind() method.
*
* Before returning from bind, various fields in the template descriptor
* may be overridden. These include the idVendor/idProduct/bcdDevice values
* normally to bind the appropriate host side driver, and the three strings
* (iManufacturer, iProduct, iSerialNumber) normally used to provide user
* meaningful device identifiers. (The strings will not be defined unless
* they are defined in @dev and @strings.) The correct ep0 maxpacket size
* is also reported, as defined by the underlying controller driver.
*/
struct usb_composite_driver {
const char *name;
const char *iProduct;
const char *iManufacturer;
const struct usb_device_descriptor *dev;
struct usb_gadget_strings **strings;
unsigned needs_serial:1;
struct class *class;
atomic_t function_count;
int (*unbind)(struct usb_composite_dev *);
void (*disconnect)(struct usb_composite_dev *);
/* global suspend hooks */
void (*suspend)(struct usb_composite_dev *);
void (*resume)(struct usb_composite_dev *);
void (*enable_function)(struct usb_function *f, int enable);
};
b. device_desc 设备描述声明:
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,
};
c. dev_strings 设备的字符内容 声明:
static struct usb_gadget_strings *dev_strings[] = { //多个usb_gadget_string集合
&stringtab_dev, //具体一个usb_gadget_string
NULL,
};
static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
.strings = strings_dev,
};
/* 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 */
};
2. android_enable_function() :
void android_enable_function(struct usb_function *f, int enable)
{
struct android_dev *dev = _android_dev; //获得全局变量 _android_dev
int disable = !enable;
int product_id;
if (!!f->disabled != disable) {
usb_function_set_enabled(f, !disable); //使能usb function.
#ifdef CONFIG_USB_ANDROID_RNDIS
if (!strcmp(f->name, "rndis")) {
struct usb_function *func;
/* Windows does not support other interfaces when RNDIS is enabled,
* so we disable UMS and MTP when RNDIS is on.
*/
list_for_each_entry(func, &android_config_driver.functions, list) {
if (!strcmp(func->name, "usb_mass_storage")
|| !strcmp(func->name, "mtp")) {
usb_function_set_enabled(func, !enable);
}
}
}
#endif
update_dev_desc(dev); //更新设备描述
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;
usb_composite_force_reset(dev->cdev); //reset
}
}
a. usb_function_set_enabled():
void usb_function_set_enabled(struct usb_function *f, int enabled)
{
f->disabled = !enabled;
kobject_uevent(&f->dev->kobj, KOBJ_CHANGE);
}
b. update_dev_desc() : 更新设备描述符
void update_dev_desc(struct android_dev *dev)
{
struct usb_function *f;
struct usb_function *last_enabled_f = NULL;
int num_enabled = 0;
int has_iad = 0;
dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;
dev->cdev->desc.bDeviceSubClass = 0x00;
dev->cdev->desc.bDeviceProtocol = 0x00;
list_for_each_entry(f, &android_config_driver.functions, list) {
if (!f->disabled) {
num_enabled++;
last_enabled_f = f;
if (f->descriptors[0]->bDescriptorType ==
USB_DT_INTERFACE_ASSOCIATION)
has_iad = 1;
}
if (num_enabled > 1 && has_iad) {
dev->cdev->desc.bDeviceClass = USB_CLASS_MISC;
dev->cdev->desc.bDeviceSubClass = 0x02;
dev->cdev->desc.bDeviceProtocol = 0x01;
break;
}
}
if (num_enabled == 1) {
#ifdef CONFIG_USB_ANDROID_RNDIS
if (!strcmp(last_enabled_f->name, "rndis")) {
#ifdef CONFIG_USB_ANDROID_RNDIS_WCEIS
dev->cdev->desc.bDeviceClass =
USB_CLASS_WIRELESS_CONTROLLER;
#else
dev->cdev->desc.bDeviceClass = USB_CLASS_COMM;
#endif
}
#endif
}
}
c. usb_composite_force_reset(): 重置usb gadget.
void usb_composite_force_reset(struct usb_composite_dev *cdev)
{
unsigned long flags;
spin_lock_irqsave(&cdev->lock, flags);
/* force reenumeration */
if (cdev && cdev->gadget && cdev->gadget->speed != USB_SPEED_UNKNOWN) {
spin_unlock_irqrestore(&cdev->lock, flags);
usb_gadget_disconnect(cdev->gadget);
msleep(10);
usb_gadget_connect(cdev->gadget);
} else {
spin_unlock_irqrestore(&cdev->lock, flags);
}
}
3. android_bind():
static int 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); //allocate an unused string ID
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;
/* register our configuration */
ret = usb_add_config(cdev, &android_config_driver, android_bind_config); //add a configuration to a device.
if (ret) {
printk(KERN_ERR "usb_add_config failed\n");
return ret;
}
gcnum = usb_gadget_controller_number(gadget); //support bcdDevice id convention.
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;
}
a. usb_string_id() :
/**
* usb_string_id() - allocate an unused string ID
* @cdev: the device whose string descriptor IDs are being allocated
* Context: single threaded during gadget setup
*
* @usb_string_id() is called from bind() callbacks to allocate
* string IDs. Drivers for functions, configurations, or gadgets will
* then store that ID in the appropriate descriptors and string table.
*
* All string identifier should be allocated using this,
* @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure
* that for example different functions don't wrongly assign different
* meanings to the same identifier.
*/
int usb_string_id(struct usb_composite_dev *cdev)
{
if (cdev->next_string_id < 254) {
/* string id 0 is reserved by USB spec for list of
* supported languages */
/* 255 reserved as well? -- mina86 */
cdev->next_string_id++;
return cdev->next_string_id;
}
return -ENODEV;
}
b. usb_add_config()
/**
* usb_add_config() - add a configuration to a device.
* @cdev: wraps the USB gadget
* @config: the configuration, with bConfigurationValue assigned
* @bind: the configuration's bind function
* Context: single threaded during gadget setup
*
* One of the main tasks of a composite @bind() routine is to
* add each of the configurations it supports, using this routine.
*
* This function returns the value of the configuration's @bind(), which
* is zero for success else a negative errno value. Binding configurations
* assigns global resources including string IDs, and per-configuration
* resources such as interface IDs and endpoints.
*/
int usb_add_config(struct usb_composite_dev *cdev,
struct usb_configuration *config,
int (*bind)(struct usb_configuration *))
{
int status = -EINVAL;
struct usb_configuration *c;
DBG(cdev, "adding config #%u '%s'/%p\n",
config->bConfigurationValue,
config->label, config);
if (!config->bConfigurationValue || !bind)
goto done;
/* Prevent duplicate configuration identifiers */
list_for_each_entry(c, &cdev->configs, list) {
if (c->bConfigurationValue == config->bConfigurationValue) {
status = -EBUSY;
goto done;
}
}
config->cdev = cdev;
list_add_tail(&config->list, &cdev->configs);
INIT_LIST_HEAD(&config->functions);
config->next_interface_id = 0;
status = bind(config);
if (status < 0) {
list_del(&config->list);
config->cdev = NULL;
} else {
unsigned i;
DBG(cdev, "cfg %d/%p speeds:%s%s\n",
config->bConfigurationValue, config,
config->highspeed ? " high" : "",
config->fullspeed
? (gadget_is_dualspeed(cdev->gadget)
? " full"
: " full/low")
: "");
for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
struct usb_function *f = config->interface[i];
if (!f)
continue;
DBG(cdev, " interface %d = %s/%p\n",
i, f->name, f);
}
}
/* set_alt(), or next bind(), sets up
* ep->driver_data as needed.
*/
usb_ep_autoconfig_reset(cdev->gadget);
done:
if (status)
DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
config->bConfigurationValue, status);
return status;
}
c. usb_gadget_controller_number() : support bcdDevice id convention.
/**
* usb_gadget_controller_number - support bcdDevice id convention
* @gadget: the controller being driven
*
* Return a 2-digit BCD value associated with the peripheral controller,
* suitable for use as part of a bcdDevice value, or a negative error code.
*
* NOTE: this convention is purely optional, and has no meaning in terms of
* any USB specification. If you want to use a different convention in your
* gadget driver firmware -- maybe a more formal revision ID -- feel free.
*
* Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
* to change their behavior accordingly. For example it might help avoiding
* some chip bug.
*/
static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
{
if (gadget_is_net2280(gadget))
return 0x01;
else if (gadget_is_dummy(gadget))
return 0x02;
else if (gadget_is_pxa(gadget))
return 0x03;
else if (gadget_is_goku(gadget))
return 0x06;
else if (gadget_is_omap(gadget))
return 0x08;
else if (gadget_is_lh7a40x(gadget))
return 0x09;
else if (gadget_is_pxa27x(gadget))
return 0x11;
else if (gadget_is_s3c2410(gadget))
return 0x12;
else if (gadget_is_at91(gadget))
return 0x13;
else if (gadget_is_imx(gadget))
return 0x14;
else if (gadget_is_musbhdrc(gadget))
return 0x16;
else if (gadget_is_atmel_usba(gadget))
return 0x18;
else if (gadget_is_fsl_usb2(gadget))
return 0x19;
else if (gadget_is_amd5536udc(gadget))
return 0x20;
else if (gadget_is_m66592(gadget))
return 0x21;
else if (gadget_is_fsl_qe(gadget))
return 0x22;
else if (gadget_is_ci13xxx(gadget))
return 0x23;
else if (gadget_is_langwell(gadget))
return 0x24;
else if (gadget_is_r8a66597(gadget))
return 0x25;
else if (gadget_is_s3c_hsotg(gadget))
return 0x26;
return -ENOENT;
}
d. usb_gadget_set_selfpowered()
/**
* usb_gadget_set_selfpowered - sets the device selfpowered feature.
* @gadget:the device being declared as self-powered
*
* this affects the device status reported by the hardware driver
* to reflect that it now has a local power supply.
*
* returns zero on success, else negative errno.
*/
static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget)
{
if (!gadget->ops->set_selfpowered)
return -EOPNOTSUPP;
return gadget->ops->set_selfpowered(gadget, 1);
}
4. android_config_driver
static struct usb_configuration android_config_driver = {
.label = "android",
.setup = android_setup_config,
.bConfigurationValue = 1,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = 0xFA, /* 500ma */
};
android_setup_config()
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;
}
5. android_bind_config()
static int android_bind_config(struct usb_configuration *c)
{
struct android_dev *dev = _android_dev;
printk(KERN_DEBUG "android_bind_config\n");
dev->config = c;
if (should_bind_functions(dev))
bind_functions(dev);
return 0;
}