USB设备的应用已经越来越广泛, 如USB键盘、鼠标等, 主要是因为USB设备与主机连接方便, 并且通信速度快。而Linux操作系统自发行以来已在越来越多的硬件平台上移植, 尤其是在嵌入式领域更是得到了广泛放入应用。因此在嵌入式Linux环境下编写USB设备驱动程序就越来越重要, 本文主要讨论嵌入式Linux环境下USB键盘驱动的设计。
1 应用平台
本文的应用平台是基于S3C2440的这款ARM920T的MCU, 它和早期的S3C2410芯片基本相同, 不过在性能与功能上都得到增强, 在这里不打算叙述它们的差别, 大部分时候可以把它当成S3C2410。S3C2440芯片包含两个USB HOST接口, USB键盘可以通过该接口连接, 而USB键盘驱动是基于Linux2.6的内核。
2 USB设备结构
在USB设备中, 包含设备、配置、接口和端点4个层次。USB是通过端点来传递数据, 一个USB端点只能在一个方向传递数据, 因此端点可以看作一个单向的管道。接口由多个端点组成, 代表一个功能, 是USB设备驱动程序控制的对象。而每个配置可以有多个接口, 在一个时刻只能激活USB设备的一个配置。
3 USB设备驱动结构
3.1 Linux USB驱动层次
在Linux系统中, USB驱动处于最底层的是USB主机控制器硬件, 运行之上的是USB主机控制器驱动, 最上层为USB设备驱动层, 它们是插入的U盘、鼠标等设备驱动。Linux下实现USB驱动包括USB主机控制器驱动和USB设备驱动, 前者控制插入其中的USB设备, 后者控制USB设备如何与主机通信。
3.2 USB设备驱动结构
Linux2.6内核中已经为S3C2410芯片编写好了相关的主机控制器的驱动, 此驱动同样对S3C2440适用, 因此只用根据不同的设备特点来编写设备驱动, USB设备驱动的结构如图1所示。
在图1中, usb_driver是我们要为各种USB设备编写的设备驱动, 它起到找到USB设备、管理USB设备连接和断开的作用, 而主机控制器驱动通过URB管理各种各样的usb_driver, 从而进一步管理各种USB设备。
3.3 URB
Linux内核中的USB代码通过urb (USB请求快) 和所有的USB设备通信。USB设备中的每个端点都处理一个urb队列, 一个urb的处理流程是:urb被一个USB设备驱动创立, 初始化后安排给一个特定的USB设备端点, 并被USB设备驱动提交给USB核心, 再由USB核心递交到特定设备的USB主控器驱动程序, 并由USB主控器驱动程序处理, 进行一次到USB设备的传递, 当urb完成, USB主机控制器驱动通知USB设备驱动。
4 编写嵌入式Linux的USB键盘驱动程序
4.1 USB键盘驱动usb_driver结构体总体结构
usb_driver结构体中的函数是USB设备驱动中USB的核心部分, 而USB只是一个总线, 真正的USB设备驱动的主题工作仍然是USB设备本身所属类型的驱动, 因此USB键盘的驱动编写主要还是归结到键盘类驱动的编写。上述提到USB驱动的关键结构体usb_driver, 它可以根据USB驱动类型加入相关的函数, 例如write () 、read () 等, 这些函数的作用与字符设备的file_operations结构体的函数作用类似, 但由于键盘类驱动主要用到中断, 所以在这里设计的usb_driver结构体只包含了最基本的函数, USB键盘驱动的usb_driver结构体kbd_driver定义如下:
在USB键盘设备驱动的模块加载和卸载函数中, 分别注册和注销结构体kbd_driver, 注册函数为usb_register (&kbd_driver) , 注销函数为usb_deregister (&kbd_driver) 。
4.2 探测函数
4.2.1 探测函数和断开函数
usb_driver结构体中, 最重要的两个函数就是探测函数kdb_probe () 和断开函数kdb_disconnect () 。探测函数探测设备的端点地址、缓冲区大小, 初始化任何可能用于控制U S B设备的数据结构, 并把以初始化数据结构的指针保存到接口设备中。当一个设备被安装而USB核心认为该驱动程序应该被处理时, 探测函数被调用。断开函数的调用发生在驱动因各种原因不在控制设备的时候, 断开函数终止已提交的urb并注销输入设备。
4.2.2 检测端点信息和urb通信
kbd_probe函数首先查看USB键盘设备端口的方向、类型, 并创建端点的管道。初始化工作完成后, 驱动程序利用urb来传递数据。键盘是中断类型的端点, 使用usb_fill_int_urb () 函数来初始化urb, 函数代码如下:
usb_fill_int_urb (urb, dev, pipe, kbd->new, maxp, kbd->irq, kbd, endpoint->b Interval) ;
在这些参数中, 最重要的就是kbd->irq, 它为键盘中断处理函数的指针, 中断处理函数负责将扫描到的键盘信息传递给urb, 当然不同的USB键盘会根据它的类型来获得按键值, 这些处理代码都在kbd_irq函数中, 函数代码如下:
static void kbd_irq (struct urb*urb, struct pt_regs*regs)
当urb得到键盘的扫描信息后, 它就被设备驱动提交给U S B核心, 使用usb_submit_urb函数提交, 代码如下:
if (usb_submit_urb (urb) ) {
kfree (kbd) ;
return NULL;}
至此, kdb_probe () 函数主要工作已经完成, 最后可利用printk函数打印设备信息, 以确定传输是否成功。kbd_probe () 函数是键盘驱动函数的最核心部分, 它完成键盘驱动的主要工作。
kbd_probe () 函数的工作流程如图2所示。
5 结语
对嵌入式Linux下的USB驱动的原理以及U S B键盘驱动的设计方法做了重点介绍, 希望本文能对各种类型的U S B键盘驱动开发有所帮助。
摘要:本文主要阐述了嵌入式Linux的USB设备驱动的结构, 并重点分析了嵌入式linux中USB键盘驱动的设计方法。
关键词:嵌入式Linux,USB驱动结构,USB键盘驱动
参考文献
[1] Jonathan Conrbet.LINUX设备驱动程序[M].北京:中国电力出版社, 2006.
[2] 宋宝华.LINUX设备驱动开发详解[M].北京:人民邮电出版社, 2007.
[3] 吴强, 周淑华, 马正新.基于USB设备的Linux网络驱动程序开发[J].微计算机信息, 2007 (1~2) :6~8.
【基于嵌入式Linux的USB键盘驱动设计】相关文章:
基于嵌入式的智能卡驱动设计和优化策略12-10
基于嵌入式的掌上点菜系统的设计12-30
基于嵌入式系统设计及应用的教学实践研究10-28
基于串口通信的嵌入式文件传输程序设计09-11
嵌入式桥式起重机安全监控仪的USB通信09-11
基于嵌入式的远程电气控制自动化系统的设计09-10