接《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。