参考以下博客:
http://blog.csdn.net/myarrow/article/details/7012230 Linux USB驱动详解
http://blog.csdn.net/myarrow/article/details/7013198 Linux USB驱动工作流程
http://www.cnblogs.com/general001/articles/2319552.html Linux下USB驱动框架分析
http://blog.csdn.net/gotosola/article/details/7473730 Linux usb驱动程序全注释
http://m.blog.csdn.net/blog/wuyuwei45/9047035 Android/Linux USB Gadget:三层架构
http://blog.chinaunix.net/uid-25909619-id-3153939.html 基于android4.0的usb gadget分析 (系列 USB 驱动分析)
http://blog.csdn.net/airk000/article/details/7887645 Android4.0 USB挂载内核驱动层流程分析(一)
http://blog.csdn.net/successcw/article/details/17137361 linux usb gadget
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
一、主机驱动(略写)
1,Linux usb设备驱动框架:
分两种,主机驱动与gadget驱动,前者控制插入其中的USB设备,后者控制USB设备(嵌入式)如何与主机通信,如下:
2.usb系统一般由三个部分组成,主机,usb hub,usb设备
在任何的usb系统中仅有一个主机
所有的usb device都连接在hub端口上
3.USB 四种传输方式
(1)控制传输模式(Control)
(2)等时传输方式(lsochronous)
(3)中断传输模式(Interrupt)
(4)批量传输模式(bulk)
4. usb设备组成
(1)一个usb设备由可以有一个或多个配置(任一时刻,只能有一个配置生效)
(2)一个配置通常可以有一个或多个接口
(3)一个接口通常可以有一个或多个端点
通常所尽的usb设备驱动是指接口驱动,即一个接口对应一个驱动。
所以Linux usb设备有四大描述符,分别为设备描述符,配置描述符,接口描述符,端点描述符
5.urb主要用于Linux host与设备进行数据传输
所有USB通讯均为请求-->响应模式,USB设备不会主动向Host发送数据。
写数据:USB设备驱动发送urb请求给USB设备,USB设备不需要回数据。
读数据:USB设备驱动发送urb请求给USB设备,USB设备需要回数据。
urb的生命周期:
(1)由usb设备驱动创建
(2)分配到usb设备的指定端点
(3)由Usb设备驱动提交到usb core
(4)由Usb core提交到usb 主机控制器
(5)由Usb主机控制器控制设备进行数据传输
(6)当urb完成的时候,usb主机控制器驱动通知usb 设备驱动
6.driver/usb/usb-skeleton.c
在Linux kernel源码目录中driver/usb/usb-skeleton.c为我们提供了一个最基础的USB驱动程序。我们称为USB骨架。通过它我们仅需要修改极少的部分,就可以完成一个USB设备的驱动,略。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
二.gadget驱动
1.Linux USB Gadget分三层架构:2.重要的结构体
struct android_dev {
const char *name;
struct android_usb_function **functions; //该android_dev支持的功能如adb,大容量存储
struct usb_composite_dev *cdev; //符合设备的dev
struct device *dev; //支持设备驱动模型的dev
bool enabled;
int disable_depth;
struct mutex mutex; //操作该结构体是用到的互斥锁
struct android_usb_platform_data *pdata;
bool connected; //记录当前的连接状态
bool sw_connected; //记录切换后的连接状态
bool suspended;
bool sw_suspended;
char pm_qos[5];
struct pm_qos_request pm_qos_req_dma;
struct work_struct work; //支持的工作队列
/* A list of struct android_configuration */
struct list_head configs;
int configs_num;
/* A list node inside the android_dev_list */
struct list_head list_item;
};
struct android_usb_function {
char *name; //该功能的名字
void *config; //该功能所依赖的配置
struct device *dev; //为设备驱动模型准备的device
char *dev_name;
struct device_attribute **attributes;
struct android_dev *android_dev;
/* 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 *); //在解除绑定时,执行清除的函数
/* Optional: called when the function is added the list of enabled functions */
void (*enable)(struct android_usb_function *);
/* Optional: called when it is removed */
void (*disable)(struct android_usb_function *);
int (*bind_config)(struct android_usb_function *, //把该function绑定到特定的配置上,此时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 *);
};
static struct usb_gadget_driver composite_driver = {
.unbind = composite_unbind,
.setup = composite_setup,
.disconnect = composite_disconnect,
.suspend = composite_suspend,
.resume = composite_resume,
.driver = {
.owner = THIS_MODULE,
},
};
struct usb_gadget {
/* readonly to gadget driver */
const struct usb_gadget_ops *ops;
struct usb_ep *ep0;
struct list_head ep_list; /* of usb_ep */
enum usb_device_speed speed;
enum usb_device_speed max_speed;
unsigned sg_supported:1;
unsigned is_otg:1;
unsigned is_a_peripheral:1;
unsigned b_hnp_enable:1;
unsigned a_hnp_support:1;
unsigned a_alt_hnp_support:1;
unsigned host_request:1;
unsigned otg_srp_reqd:1;
const char *name;
struct device dev;
u8 usb_core_id;
bool l1_supported;
bool remote_wakeup;
};
static struct android_usb_function *supported_functions[] = {
&mbim_function,
&ecm_qc_function,
#ifdef CONFIG_SND_PCM
&audio_function,
#endif
&rmnet_smd_function,
&rmnet_sdio_function,
&rmnet_smd_sdio_function,
&rmnet_function,
&gps_function,
&diag_function,
&qdss_function,
&serial_function,
&adb_function, //支持的adb功能
&ccid_function,
&acm_function,
&mtp_function,
&ptp_function,
&rndis_function, //Remote Network Driver Interface Specification,既是RemoteNDIS,既是远程网络驱动接口规范。
//基于USB实现RNDIS实际上就是TCP/IP over USB,就是在USB设备上跑TCP/IP,让USB设备看上去像一块网卡
&rndis_qc_function,
&ecm_function, //ecm
&ncm_function,
&mass_storage_function, //支持的大容量存储功能
&accessory_function,
#ifdef CONFIG_SND_PCM
&audio_source_function,
#endif
&uasp_function,
NULL
};
static struct usb_composite_driver android_usb_driver = {
.name = "android_usb", //该复合设备驱动的名称
.dev = &device_desc, //设备描述符
.strings = dev_strings,
.unbind = android_usb_unbind,
.max_speed = USB_SPEED_SUPER
};
static struct usb_device_descriptor device_desc = {
.bLength = sizeof(device_desc),
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
.idVendor = __constant_cpu_to_le16(VENDOR_ID),
.idProduct = __constant_cpu_to_le16(PRODUCT_ID),
.bcdDevice = __constant_cpu_to_le16(0xffff),
.bNumConfigurations = 1,
};
driver/usb/gadget/f_mass_storage.c
struct fsg_config {
unsigned nluns; //最大支持的LUN数量(LUN:Logical units)
struct fsg_lun_config { //每个LUN的参数
const char *filename; //此LUN的名字,如果不是可移除的(removable)则不需要
char ro; //FALSE(TRUE),设置read-only,如果是CD-ROM则不可能挂载成R/W
char removable; //TRUE(FALSE),说明此LUN可移除
char cdrom; //FALSE(TRUE),此LUN是否为CD-ROM
char nofua; //FALSE(TRUE),此LUN是否可忽略
} luns[FSG_MAX_LUNS];
const char *lun_name_format;//建议为lun%d形式,如果不只是一个LUN,可以用%d来引导,必须是整型数字,如果不符合,可能将出现不可预知的错误
const char *thread_name; //默认名字是"file_storage",是应该叫内核线程名字吧
/* 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;
};
./arch/arm/boot/dts/msm9625-v2.1.dtsi
android_usb@fe8078c8 {
compatible = "qcom,android-usb";
reg = <0xfe8078c8 0xc8>;
qcom,android-usb-swfi-latency = <100>;
};
Android.c (drivers\usb\gadget)
static int __init init(void)
composite_driver.setup = android_setup;//composite_driver 是一个全局的结构体,android.c中重新实现了它的setup和disconnect方法
composite_driver.disconnect = android_disconnect;
composite_driver.suspend = android_suspend;
composite_driver.resume = android_resume;
ret = platform_driver_register(&android_platform_driver);
static struct platform_driver android_platform_driver = {
.driver = {
.name = "android_usb",
.of_match_table = usb_android_dt_match,
},
.probe = android_probe,
.remove = android_remove,
.id_table = android_id_table,
};
static int __devinit android_probe(struct platform_device *pdev)
android_class = class_create(THIS_MODULE, "android_usb");//创建一个class,创建这个 class 的目的是支持用户空间的 udev,自动创建设备节点,/sys/devices/virtual/android_usb/
android_dev = kzalloc(sizeof(*android_dev), GFP_KERNEL);//分配一个该结构体的实例
android_dev->functions = supported_functions; //初始化该结构体的 functions 成员,supported_functions 结构体见上面
INIT_LIST_HEAD(&android_dev->configs); //初始化dev的 enabled_functions 成员链表头
INIT_WORK(&android_dev->work, android_work); //初始化dev的work成员,支持的工作队列
mutex_init(&android_dev->mutex); //初始化dev的成员mutex互斥锁
composite_driver.usb_core_id = pdata->usb_core_id;
//继续初始化 android_dev 中的成员dev ,支持动态创建设备节点,并为该设备创建属性,/sys/devices/virtual/android_usb/android0
ret = android_create_device(android_dev, composite_driver.usb_core_id); ----
ret = usb_composite_probe(&android_usb_driver, android_bind); //这个函数才是函数的开始,到里面牵涉的东西会越来越多
driver/usb/gadget/composite.c
/*将注册进来的 usb_composite_driver (这里是 android_usb_driver)与usb_gadget_driver(这里是composite_driver)联系起来,
然后调用 udc core 提供的函数: usb_gadget_probe_driver ,并提供 callback function: composite_bind 给udc core*/
int usb_composite_probe(struct usb_composite_driver *driver, int (*bind)(struct usb_composite_dev *cdev))
composite_driver.function = (char *) driver->name;
composite_driver.driver.name = driver->name;
composite_driver.max_speed = driver->max_speed;
composite = driver;
composite_gadget_bind = bind;
retval = usb_gadget_probe_driver(&composite_driver, composite_bind); //向USB设备层进行探测和注册
driver/usb/gadget/udc-core.c
//usb_gadget_probe_driver() 函数是每一个USB设备控制器驱动要实现的,这个函数与硬件紧密相关
int usb_gadget_probe_driver(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *))
ret = usb_gadget_udc_start(udc->gadget, driver);
static inline int usb_gadget_udc_start(struct usb_gadget *gadget,struct usb_gadget_driver *driver)
gadget->ops->udc_start(gadget, driver);
/*这个函数是udc core层实现的一个接口函数,具体实现在对应的 usb device controller 中,但由于不知 msm9625 是哪个 ???udc.c 故 udc_start 不分析了
将 usb_gadget_driver 和 usb_gadget 对应起来,并调用bind(这里为 composite_bind)*/
static int composite_bind(struct usb_gadget *gadget)
struct usb_composite_dev *cdev; //新建 usb_composite_dev
cdev->gadget = gadget; //建立 usb_gadget 与 usb_composite_dev 的关系
set_gadget_data(gadget, cdev);
cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); //给这个端点分配一个请求对象,ep0 usb request
cdev->driver = composite;//这里指定 usb_composite_dev 的driver为 usb_composite_probe 注册进来的 usb_composite_driver: android_usb_driver
status = composite_gadget_bind(cdev);
/*这里调用的是 usb_composite_probe 传进来的 android_bind, android_bind 会调用 usb_add_config 来添加 config
具体的每一个function的添加会在调用 usb_add_config 时传进来的 callback function 中完成
(这里是 android_bind_config , 这个函数会调用每一个需要添加的function的 bind_config, 而 bind_config 调用的是 usb_add_function)
*/
***********
/*初始化所有支持的 usb 设备类型, 继续创建 mtp,ptp, rndis, acm, ffs, mass_storage等属性结点。
保存来自 cdev 的 manufacturer_id, product_id, manufacturer_string, product_string, serial_string 信息。
设置设备自供电能力特性*/
static int android_bind(struct usb_composite_dev *cdev)
usb_gadget_disconnect(gadget); //初始化前确保是断开的
ret = android_init_functions(dev->functions, cdev);
id = usb_string_id(cdev); //通过读取设备ID来填充一下驱动参数
strlcpy(manufacturer_string, "Android", sizeof(manufacturer_string) - 1); //填充一下默认的厂商和产品信息,根据说明意思是可以通过上层改变
gcnum = usb_gadget_controller_number(gadget); //识别一下控制芯片,返回一个BCD值
static int android_init_functions(struct android_usb_function **functions, struct usb_composite_dev *cdev)
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 (f->init) //f->init指向 mass_storage_function_init,所以是在这个时候运行的
4.rndis部分
static struct android_usb_function rndis_function = {
.name = "rndis",
.init = rndis_function_init,
.cleanup = rndis_function_cleanup,
.bind_config = rndis_function_bind_config,
.unbind_config = rndis_function_unbind_config,
.attributes = rndis_function_attributes,
};
//rndis_bind_config_vendor() 是和 android usb 层沟通的桥梁函数,也是整个 f_rndis.c 文件的唯一入口函数
static int rndis_function_bind_config(struct android_usb_function *f,struct usb_configuration *c)
return rndis_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID, rndis->manufacturer);
int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],u32 vendorID, const char *manufacturer)
status = rndis_init(); //通过调用 rndis_init(),向下打通了 kernel/drivers/usb/gadget/rndis.c 层
rndis->vendorID = vendorID; //在设置好 f_rndis 成员变量,也就是分配好必须的资源
rndis->port.func.set_alt = rndis_set_alt; //对于控制id,调用 usb_ep_enable() ,对于数据id, 调用 gether_connect()
rndis->port.func.setup = rndis_setup; //使用CDC命令封装机制来实现一个 RPC调用,只检查一种 USB_DIR_OUT, 一种 USB_DIR_IN
rrndis->port.func.bind = rndis_bind;
rndis->port.func.disable = rndis_disable; //释放资源,gether_disconnect() 断开gether连接,调用 usb_ep_disable() 关闭端点
status = usb_add_function(c, &rndis->port.func);//把该usb功能加入到配置中去,对应 USB规范可知,每个 usb 配置必须包含一个或多个usb功能
//usb_add_function() 将调用 rndis->port.func.bind 函数并返回其值,实际就是调用 rndis_bind() 函数。
int usb_add_function(struct usb_configuration *config,struct usb_function *function)
value = function->bind(config, function);
return value;
//rndis_bind() 进行以太网功能驱动的初始化和绑定操作
static int rndis_bind(struct usb_configuration *c, struct usb_function *f)
status = usb_interface_id(c, f); //分配usb 未使用的接口id值,是 drivers/usb/gadget/composite.c 的通用功能函数
ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc); //分配和配置必要的 usb 端点资源
rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); //分配并返回一个 usb_request 对象指针
rndis->notify_req->complete = rndis_response_complete; //usb请求执行结束后,回调函数 rndis_response_complete() ---- 1
status = rndis_register(rndis_response_available, rndis); //rndis_response_available() 函数发送 RNDIS RESPONSE_AVAILABLE 消息到端点。
static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC); //如果 usb_request 返回状态正常,则通过 usb_ep_queue() 放入队列
f_rndis.c 沟通的下层是 drivers/usb/gadget/u_ether.c。
adb:
static struct android_usb_function adb_function = {
.name = "adb",
.enable = adb_android_function_enable,
.disable = adb_android_function_disable,
.init = adb_function_init,
.cleanup = adb_function_cleanup,
.bind_config = adb_function_bind_config,
};
static int adb_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
return adb_bind_config(c);
static int adb_bind_config(struct usb_configuration *c)
dev->cdev = c->cdev;
dev->function.name = "adb";
dev->function.descriptors = fs_adb_descs;
dev->function.hs_descriptors = hs_adb_descs;
dev->function.bind = adb_function_bind;
return usb_add_function(c, &dev->function);
int usb_add_function(struct usb_configuration *config,struct usb_function *function)
value = function->bind(config, function); ---- 即调用 adb_function_bind
static int adb_function_bind(struct usb_configuration *c, struct usb_function *f)
ret = adb_create_bulk_endpoints(dev, &adb_fullspeed_in_desc, &adb_fullspeed_out_desc);
static int adb_create_bulk_endpoints(struct adb_dev *dev,
struct usb_endpoint_descriptor *in_desc,
struct usb_endpoint_descriptor *out_desc)
ep = usb_ep_autoconfig(cdev->gadget, in_desc); ---- 分配gadget初始化注册的endpoint
req = adb_request_new(dev->ep_out, ADB_BULK_BUFFER_SIZE); ---- (主要调用 usb_ep_alloc_request)来分配对应的endpoint的request
req->complete = adb_complete_out; ---- 指定request的complete函数,这个函数会在usb device controller对应的endpoint收发中断完成之后被调用
static int mass_storage_function_init(struct android_usb_function *f,struct usb_composite_dev *cdev)
config->fsg.nluns = 2; //支持2个存储设备
config->fsg.luns[1].cdrom = 1; //支持 cdrom
config->fsg.luns[1].ro = 1; //read only
config->fsg.luns[1].removable = 0; //不可移除
name[1] = "lun0";
common = fsg_common_init(NULL, cdev, &config->fsg); //根据配置创建设备
err = sysfs_create_link(&f->dev->kobj,&common->luns[i].dev.kobj,name[i]); //创建设备链接