Android4.0 USB挂载内核驱动层流程分析(三)

时间:2022-05-05 08:32:44

接上篇《Android4.0 USB挂载内核驱动层流程分析(二)》
1.android_bind

static int android_bind(struct usb_composite_dev *cdev)
{
struct android_dev *dev = _android_dev; //回头看Android4.0 USB挂载内核驱动层流程分析(一),static int __init init(void) 函数中_android_dev = dev; _android_dev是一个静态结构体
struct usb_gadget*gadget = cdev->gadget;
intgcnum, id, ret;


usb_gadget_disconnect(gadget); //初始化前确保是断开的


ret = android_init_functions(dev->functions, cdev); //这里的function们就是之前包括mass_storage_function在内的功能。下边分析
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); //通过读取设备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;


/* Default strings - should be updated by userspace */
strlcpy(manufacturer_string, "Android",
sizeof(manufacturer_string) - 1); //填充一下默认的厂商和产品信息,根据说明意思是可以通过上层改变
strlcpy(product_string, "Android", sizeof(product_string) - 1);
#ifdef CONFIG_HUAWEI_KERNEL //分析的是华为的内核,所以有这样的宏定义
if(0 != usb_para_data.usb_para.usb_serial[0])
{
/* use bluetooth address as usb serial number */
strlcpy(serial_string, usb_para_data.usb_para.usb_serial, APP_USB_SERIAL_LEN); //华为的意思是使用蓝牙地址作为USB串口序列号
}
else
{
strlcpy(serial_string, USB_DEFAULT_SN, sizeof(serial_string) - 1); //如果蓝牙地址为0的话就使用默认序列号:012345789AB,下边就 bulabulabula...
/* if the usb_serial is null and the nv value is google index, init.c will set
* the ports to factory mode. so update the variable to keep consistent.
*/
if(GOOGLE_INDEX == usb_para_data.usb_para.usb_pid_index) //Google模式,25!
{
USB_PR("%s usb serial number is null in google mode. so switch to original mode\n", __func__);
usb_para_data.usb_para.usb_pid_index = ORI_INDEX;
}
}
#else
strlcpy(serial_string, "0123456789ABCDEF", sizeof(serial_string) - 1); //好吧,默认就是给0123456789ABCDEF序列号的
#endif /* CONFIG_HUAWEI_KERNEL */


id = usb_string_id(cdev);
if (id < 0)
return id;
strings_dev[STRING_SERIAL_IDX].id = id;
device_desc.iSerialNumber = id;
/* backup the serial str id */
#ifdef CONFIG_HUAWEI_KERNEL
serial_str_id = id;
#endif /* CONFIG_HUAWEI_KERNEL */


gcnum = usb_gadget_controller_number(gadget); //识别一下控制芯片,返回一个BCD值
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); //如果前边没有遇到错误return的话,那么这里就可以正常供电了
dev->cdev = cdev;


return 0;
}

2.android_init_function

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 = 0;
int index = 0;


for (; (f = *functions++); index++) {
f->dev_name = kasprintf(GFP_KERNEL, "f_%s", f->name); //拿mass_storage_function来说,dev_name就是f_mass_storage了
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) { //f->init指向mass_storage_function_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;
}

3.总结

    由于对内核不是很熟悉,有些地方分析得不太好,但是作为驱动的使用者、适配者,就像大学老师说的,不用知道怎么来的,知道怎么用就好了。所以在分析完USB挂载相关内核驱动之后,显然最最重要的地方是mass_storage_function_init函数中的参数配置过程,定好有几个LUN,各自属性是什么样子的。然后就可以在内核结构中初始化完成了,剩下的工作就是跟VOLD相关的处理。
    关于挂载,首先是由init.rc创建文件,由vold.fstab进行链接,然后只要提供给VOLD正确的参数(或默认),最终再在framework的overlay中将storage_list.xml配置好,就可以实现USB挂载没有问题了。

**可能有一些分析错的地方,如果有高手路过,还望指点一二!