基于嵌入式Linux的USB键盘驱动设计

2022-10-19

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.

上一篇:浅谈“未来教室”的特点与构建策略下一篇:农田水利建设对现代农业的重要性分析