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);
这个函数定义在 drivers/usb/musb/musb_gadget.c 中.
musb是am3715中集成的usb模块,这usb模块好象是从Mentor Graphic Corporation公司买去的。
这个留到musb模块里去讨论了。
/*
* Register the gadget driver. Used by gadget drivers when
* registering themselves with the controller.
*
* -EINVAL something went wrong (not driver)
* -EBUSY another gadget is already using the controller
* -ENOMEM no memory to perform the operation
*
* @param driver the gadget driver
* @param bind the driver's bind function
* @return <0 if error, 0 if everything is fine
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
int retval;
unsigned long flags;
struct musb *musb = the_gadget;
D_ENTER
printk(KERN_INFO "xxha: --- enter musb");
if (!driver
|| driver->speed != USB_SPEED_HIGH
|| !bind || !driver->setup)
return -EINVAL;
/* driver must be initialized to support peripheral mode */
if (!musb) {
DBG(1, "%s, no dev??\n", __func__);
return -ENODEV;
}
DBG(3, "registering driver %s\n", driver->function);
spin_lock_irqsave(&musb->lock, flags);
if (musb->gadget_driver) {
DBG(1, "%s is already bound to %s\n",
musb_driver_name,
musb->gadget_driver->driver.name);
retval = -EBUSY;
} else {
musb->gadget_driver = driver;
musb->g.dev.driver = &driver->driver;
driver->driver.bus = NULL;
musb->softconnect = 1;
retval = 0;
}
spin_unlock_irqrestore(&musb->lock, flags);
if (retval == 0) {
retval = bind(&musb->g);
if (retval != 0) {
DBG(3, "bind to driver %s failed --> %d\n",
driver->driver.name, retval);
musb->gadget_driver = NULL;
musb->g.dev.driver = NULL;
}
spin_lock_irqsave(&musb->lock, flags);
otg_set_peripheral(musb->xceiv, &musb->g);
musb->xceiv->state = OTG_STATE_B_IDLE;
musb->is_active = 1;
/* FIXME this ignores the softconnect flag. Drivers are
* allowed hold the peripheral inactive until for example
* userspace hooks up printer hardware or DSP codecs, so
* hosts only see fully functional devices.
*/
if (!is_otg_enabled(musb))
musb_start(musb);
otg_set_peripheral(musb->xceiv, &musb->g);
spin_unlock_irqrestore(&musb->lock, flags);
if (is_otg_enabled(musb)) {
struct usb_hcd *hcd = musb_to_hcd(musb);
DBG(3, "OTG startup...\n");
/* REVISIT: funcall to other code, which also
* handles power budgeting ... this way also
* ensures HdrcStart is indirectly called.
*/
retval = usb_add_hcd(musb_to_hcd(musb), -1, 0);
if (retval < 0) {
DBG(1, "add_hcd failed, %d\n", retval);
spin_lock_irqsave(&musb->lock, flags);
otg_set_peripheral(musb->xceiv, NULL);
musb->gadget_driver = NULL;
musb->g.dev.driver = NULL;
spin_unlock_irqrestore(&musb->lock, flags);
} else {
hcd->self.uses_pio_for_control = 1;
}
}
}
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);