您的位置:首页 > 移动开发 > Android开发

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

2012-08-21 15:59 316 查看
接上篇《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;
	int			gcnum, 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挂载没有问题了。

**可能有一些分析错的地方,如果有高手路过,还望指点一二!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: