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

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

1.supported_functions

static struct android_usb_function *supported_functions[] = {
	&rmnet_smd_function,
	&rmnet_sdio_function,
	&rmnet_smd_sdio_function,
	&rmnet_function,
	&diag_function,
	&serial_function,
	&adb_function,
	&ccid_function,
//	&acm_function,
	&mtp_function,
	&ptp_function,
	&rndis_function,
	&mass_storage_function,
	&accessory_function,
	NULL
};

既然是分析USB挂载流程,那就不看别的功能函数,直接跳向mass_storage_function。

2.mass_storage_function

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,
};

包括功能名、初始化、清理、绑定配置、属性。

关于android_usb_function结构体:

struct android_usb_function {
	char *name;    //"mass_storage"
	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 *);

	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 *);
};

init函数:mass_storage_function_init

在分析mass_storage_function_init函数之前,先要了解一个很重要的结构体:

struct fsg_config {
	unsigned nluns;
	struct fsg_lun_config {
		const char *filename;
		char ro;
		char removable;
		char cdrom;
		char nofua;
	} luns[FSG_MAX_LUNS];

	const char		*lun_name_format;
	const char		*thread_name;

	/* Callback functions. */
	const struct fsg_operations	*ops;
	/* Gadget's private data. */
	void			*private_data;

	const char *vendor_name;		/*  8 characters or less */
	const char *product_name;		/* 16 characters or less */
	u16 release;

	char			can_stall;
};
上边这个结构体在f_mass_storage.c中,在C文件开头就对这个结构体有详细的介绍:

nluns    最大支持的LUN数量(LUN:Logical units)

luns      每个LUN的参数,如下

-->filename    此LUN的名字,如果不是可移除的(removable)则不需要

-->ro              FALSE(TRUE),设置read-only,如果是CD-ROM则不可能挂载成R/W

-->removable    TRUE(FALSE),说明此LUN可移除

-->cdrom      FALSE(TRUE),此LUN是否为CD-ROM

-->nofua       FALSE(TRUE),此LUN是否可忽略

还有lun_name_format  建议为lun%d形式,如果不只是一个LUN,可以用%d来引导,必须是整型数字,如果不符合,可能将出现不可预知的错误。

thread_name    默认名字是"file_storage",是应该叫内核线程名字吧


了解了这个结构体后,看mass_storage_function_init函数:

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;
        int i;
	config = kzalloc(sizeof(struct mass_storage_function_config),
								GFP_KERNEL);
	if (!config)
		return -ENOMEM;

    /* support multi luns and ro of ench lun is set to 0 to allow
     * opening "filename" in R/W mode. If the file is read-only,
     * the ro will be set to 1 automatically.
     */
    config->fsg.nluns = USB_MAX_LUNS;    //USB_MAX_LUNS=3,说明支持三个存储设备。
	for (i = 0; i < USB_MAX_LUNS; i++) {    //三个设备都可以移除,可以忽略,可以挂载为R/W,没有一个是CD-ROM
        config->fsg.luns[i].removable = 1;
        config->fsg.luns[i].nofua = 1;     
	}   

	common = fsg_common_init(NULL, cdev, &config->fsg);  //交给fsg_common_init去根据配置创建设备,具体实现在f_mass_storage.c中
	if (IS_ERR(common)) {
		kfree(config);
		return PTR_ERR(common);
	}

    /* create a symlink for each lun */
	for (i = 0; i < USB_MAX_LUNS; i++)
    {
        err = sysfs_create_link(&f->dev->kobj,    
                    &common->luns[i].dev.kobj,
                    dev_name(&common->luns[i].dev));    //创建设备链接
        if (err)
        {
    		fsg_common_release(&common->ref);
            kfree(config);
            return err;
        }
    }

	config->common = common;
	f->config = config;
	return 0;
}
至此基本的结构也就初始化完成了。配置很重要,一定不能错。明天再分析android_bind。



你可能感兴趣的:(Android4.0 USB挂载内核驱动层流程分析(二))