1、Linux设备驱动
设备驱动时操作系统内核和机器硬件之间的接口,为应用程序屏蔽了硬件的细节,由一组函数和一些私有数据组成,结构体内包含设备驱动所需要的所有资源,即驱动器对象所拥有的属性及成员。应用程序看待硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它主要完成以下功能:对设备进行初始化,使设备投入运行和退出服务;把设备从内核传送到设备和从设备中接受数据;以及检测设备出现的错误。
设备分为:字符、块、网络设备。字符设备是指存取时没有缓存的设备;块设备的读写都有缓存来支持,并且能够随机存取;网络设备在Linux里做专门的处理,基于BSD unix的socket机制,支持对发送数据和接收数据的缓存,提供流量控制机制以及对多协议的支持。
2、USB设备驱动
USB接口标准支持主机和外部设备之前的数据传送,主机预定了各种类型外部设备的总线带宽。每个USB设备会有一个或者多个逻辑连接点,每个连接点称为端口。每个端口有控制方式、等时方式、中断方式和批量大量方式。主机和设备端口连接称为管道。USB主机驱动由3部分组成:USB主机控制器驱动(HCD)、USB核心驱动(USBD)和不同种类的USB设备类驱动,USB驱动设备通过协议软件的抽象处理来完成与设备的不同功能接口之间的通信。 在Linux USB子系统中,HCD是直接和硬件进行交互的软件模块,是USB协议栈的最底层部分,是USB主机控制器硬件和数据传输的一种抽象。USBD部分是整个USB主机驱动的核心,主要实现的功能有:USB总线管理;USB总线设备管理、USB总线带宽管理、USB的4种类型数据传输、USB HUB驱动、为USB设备驱动提供相关接口、提供应用程序访问USB系统的文件接口等。其中USB HUB作为一类特殊的USB设备,其驱动程序被包含在USBD层。
USB设备驱动框架流程:插入设备->引起中断,驱动总线发现设备->为新设备分配地址(choose_address(udev))->告诉USB设备(usb_set_address),发出命令捕获描述符(usb_get_device_descriptor、usb_get_configuration)->device_add,将设备加入usb_bus_type的dev链中。遵循设备模型——总线、设备、驱动,usb设备驱动主要结构体struct usb_driver,他们向USB核心代码描述USB驱动程序。USB的驱动分为两块,一块是USB的bus驱动,形象得说,USB的bus驱动相当于铺出一条路来,让所有的信息都可以通过这条USB通道到达该到的地方,这部分工作由usb_core来完成。当USB设备接到USB控制器接口时,usb_core就检测该设备的一些信息,例如生产厂商ID和产品的ID,或者是设备所属的class、subclass跟protocol,以便确定应该调用哪一个驱动处理该设备。我们要做的是另一块工作——usb的设备驱动。也就是说,我们就等着usb_core告诉我们要工作了,我们才工作。主要是分配/设置usb_driver结构体,做好.probe函数。
在嵌入式Linux系统中,已经包含HCD模块和USB核心驱动USBD,不需要用户重新编写,用户仅仅需要完成USB设备类驱动即可。
3、主体结构体分析
3.1 usb驱动的骨架usb-skel(drivers/usb/usb-skeleton.c):
struct usb_skel {
struct usb_device *udev; /* the usb device for this device */
struct usb_interface *interface; /* the interface for this device */
struct semaphore limit_sem; /* limiting the number of writes in progress */
struct usb_anchor submitted; /* in case we need to retract our submissions */
struct urb *bulk_in_urb; /* the urb to read data with */
unsigned char *bulk_in_buffer; /* the buffer to receive data */
size_t bulk_in_size; /* the size of the receive buffer */
size_t bulk_in_filled; /* number of bytes in the buffer */
size_t bulk_in_copied; /* already copied to user space */
__u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
__u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
int errors; /* the last request tanked */
bool ongoing_read; /* a read is going on */
spinlock_t err_lock; /* lock for errors */
struct kref kref;
struct mutex io_mutex; /* synchronize I/O with disconnect */
wait_queue_head_t bulk_in_wait; /* to wait for an ongoing read */
};
Usb_skel:拥有描述usb设备的结构体udev,一个接口interface,用于并发控制的semaphore信号量limit_sem,用于接收数据缓存的bulk_in_buffer以及尺寸bulk_in_size,批量输入输出端口地址的bulk_in_endpointAddr、bulk_out_endpointAddr,内核使用的引用计数器kref。
3.2 描述usb设备的结构体usb_device(include/linux/usb.h):
/**
* struct usb_device - kernel's representation of a USB device