分类: LINUX
2012-02-08 20:51:17
2. 源码架构
3. 枚举过程
1. 前言
Gadget,小饰品。USB Gadget,就是指所开发的电子设备以USB从设备的模式通过USB连接到主机。比如手机用USB线插入PC后,手机就是USB Gadget。本文以Mavell为例,以Gadget插入主机的全过程为主线,分析USB Gadget的架构。
2. 源码架构
USB的源码位于/drivers/usb文件夹内,其中包括核心层core,主控制器host,U盘storage,以及USB Gadget等。
gadget文件夹里存放了各芯片厂商支援的USB Gadget控制器驱动,比如支持Mavell的PXA9XX系列的USB Gadget驱动为mv_gadget.c,其架构如下图所示,
2.1 Gadget控制器驱动
设备要有gadget功能,硬件上要集成gadget控制器,软件上要具备gadget控制器驱动。
首先是该驱动的数据结构 struct mv_usb_dev,
-> struct usb_gadget, 由linux定义的gadget所需要的数据成员,其中包含了sturct usb_ep。
-> struct mv_usb_ep, 其中的struct usb_ep是由linux定义的endpoint所需要的成员,关于endpoint参看USB协议。
-> struct usb_gadget_driver, 对应该gadget设备功能的驱动,下节将作具体描述。
-> void *mv_usb_handle, 指针指向芯片控制器的数据结构。
概括地讲,gadget控制器驱动完成了五个任务,
gadget服务,即该设备所具备的gadget能力,比如reset, suspend, resume, speed,以及需要重点关注的枚举功能mv_usb_ep0_complete_service。注意到,注册服务的函数usb_device_register_service()的第一个参数mv_usb_handle用于得到底层芯片的数据,第三个参数回调函数实现具体功能。
2.2 Gadget设备驱动
需要区别gadget设备驱动与上节提到的gadget控制器驱动。gadget设备驱动,是指设备插入主机后具备的功能,该驱动被挂在到struct usb_gadget_driver下。比如手机插入PC作为U盘,那么U盘的驱动程序就是所谓的gadget设备驱动。
(*bind)绑定设备的功能,比如U盘。
(*setup)实现USB设备的枚举。
2.3 Composite
如果一个设备插入主机后拥有多个功能,比如同时有U盘和android调试功能,那么该设备称为composite复用设备。其数据结构如下,
通过(*bind)绑定设备的各个功能。
3. 枚举过程
系统初始化USB设备的过程就是枚举过程。
根据USB协议,USB设备初始化的过程为attached->powered->default->address->configured。
当设备插入主机,将等待来自主机的中断信号,通过request_irq()进入中断处理函数。
设备通过读取控制器状态寄存器的值,得到来自主机的反馈,进而执行相应的任务,枚举就是其中的一项任务,通过调用gadget控制器驱动已经注册好的枚举服务,开始枚举过程。
该枚举服务归纳为两步,
第一步,通过读取gadget控制器,得到来自主机的请求,存放至mv_ctrl_req。
第二步,通过switch(mv_ctrl_req),对具体请求作具体处理,处理类别又可分为两类。
1) 标准请求,即所有USB设备可通用的请求,具体有得到状态请求,设置/清除feature请求,设置地址请求。
2) USB设备请求,即根据具体设备,处理具体请求,通过回调函数mv_dev->driver->setup()来实现。
PS: 关于请求,参看USB协议ch9。
重点关注mv_dev->driver->setup()的枚举过程,其实质就是主机从USB设备得到描述符。
这里的mv_dev->driver就是上文2.2所提到的gadget设备驱动,通过driver->bind绑定具体的驱动功能,如果是composite复用设备,则绑定usb_composite_driver结构,通过driver->setup实现设备的枚举过程,代码如下,其中的GET_DESCRIPTOR, SET_CONFIGURATION, 以及f->setup是必要的枚举过程。