嵌入式Linux下USB蓝牙设备驱动

2010-07-13 06:01郑春芳郑灵翔石江宏
电子设计工程 2010年2期
关键词:驱动程序中断蓝牙

郑春芳,郑灵翔,石江宏

(厦门大学 信息科学与技术学院 ATR实验室,福建 厦门 361005)

随着无线技术的不断发展,蓝牙产品逐渐走入人们的生活。目前蓝牙在PC端支持良好,应用比较广泛。但在嵌入式系统中,由于蓝牙接口的兼容性问题,使其在嵌入式领域的应用大打折扣。因此,如何在嵌入式系统中支持蓝牙设备成为当前嵌入式领域的研究热点。

作为通用串行总线标准,USB接口以其连接方便、兼容性好和传输速度快等特点被更多的硬件系统支持。针对USB蓝牙适配器在嵌入式Linux下的应用,开发其驱动程序,为蓝牙设备在嵌入式Linux下进一步应用提供前提条件。本文详细阐述USB蓝牙设备的HCI传输层,给出实现方案中关键的函数和数据结构,并在MP2530上实现。

1 系统设计简介

该嵌入系统采用Linux-2.6.20内核版本,采用在X86架构的PC机端上交叉编译,在目标板MP2530上运行。目标板MP2530是专门为嵌入式多媒体处理器MMSP2+设计的开发平台,其内部集成有ARM926EJ和ARM946E的双核,带有2D和3D的图形加速器。此外,MP2530还提供丰富的外围数据接口,包含6路UART通道,USB主机 、USB设备2.0、SD卡读写通道、以太网控制器等。MP2530支持基于通用串行总线1.1版本和开放式主机控制器1.0版本,支持高、低速USB设备。

2 蓝牙协议栈

2.1 蓝牙协议体系结构

按照蓝牙协议的逻辑功能,整个蓝牙协议栈分为3个部分[1],如图1所示。

图1 蓝牙协议栈体系结构

底层硬件实块包括射频 RF(Rodio Fraquency)、基带BB(Base Band)和链路管理 LMP(Link Manager Protocol);中间层协议包括逻辑链路控制和适应协议L2CAP(Logical Link Control and Adaptation Layer protocol)、服务发现协议 SDP(Service Discovery Protocol)、串口仿真协议 RFCOMM和电话通信协议TCS-BIN;高层应用包括拨号网络、耳机、局域网访问、文件传输等,分别对应一种应用模式。

在BB与LMP上和L2CAP之间还有一个主机控制接口HCI(Host Controller Interface)层,它提供对下层基带控制器、链路管理器的命令接口,以及对硬件状态和控制注册成员的访问。该接口还提供对蓝牙基带的统一访问模式。

2.2 BlueZ组织结构[2]

Linux蓝牙协议栈又称BlueZ,是一个开放性的协议。BlueZ采用模块化设计,其组织结构如图2所示。它包含内核和用户态2大模块。其中内核模块是由设备驱动层、蓝牙核心及主机控制接口 HCI(Host Control Interface)层、Bluetooth协议核心、逻辑链路控制和适配协议L2CAP(Logical Link Control and Adaptation Protocol)、SCO 音频层、其他Bluetooth服务组成。而用户态模块则包括BlueZ工具集和蓝牙应用程序。

图2 BlueZ组织结构

3 USB蓝牙设备的HCI传输层[3-4]

对于USB设备,其传输层即USB传输子层是介于主机和主控制器之间,负责主机与主控制器间的数据传输。

从蓝牙的协议层模型可以看出HCI位于蓝牙系统的上层(L2CAP,SDP 和 RFCOMM)和链路管理层(LMP)及基带之间,它为这些上层提供进行LM和BB的统一接口方式。USB蓝牙设备通过模块内的USB设备控制器和总线与主机控制器相连,负责与主机的数据交换,它在USB固件的控制下,将接收到的HCI协议分组交给HCI固件处理或将来自链路管理器和基带控制器的数据传送至主机。HCI固件负责解释从主机接收到的HCI分组并交给链路管理器和基带控制器处理,或采集蓝牙模块各部件的状态信息并递交给主机。主机与蓝牙USB模块关系如图3所示。

1)HCI终端要求 USB蓝牙设备可看作高速设备,其固件配置由2个接口组成。接口0为固定设置,包含BULK和中断终端;接口1提供可扩展的同步带宽占用方式。接口1提供4种设置,以提供基于同步带宽需求的占用方式。其缺省接口为空,可使设备支持非同步带宽。当通过选择接口呼叫调整同步带宽占用方式时,终端可自由选择2种接口,因此任何未处理的BULK或中断事务都无需中止或重新提交。

图3 主机与蓝牙USB模块关系

2)控制终端要求 任何USB蓝牙设备都有一个用于配置和控制该设备控制终端—终端0。终端0允许主机向主控制器发送HCI指令。当USB固件在具有蓝牙类别码的终端上接收一个分组时,它应将该分组视为一个HCI指令分组。

3)BULK终端要求 BULK终端用来传输ACL数据,由于数据完整性及带宽请求,因此需用到BULK终端。BULK具有检错和纠错能力。Linux下的蓝牙设备允许连接多个ACL链路,因此经过此通道的数据流可能来自或发往1个或多个设备数据。为避免阻塞,主控制器采用类似于共享终端模型的流控制模型。默认状态下,BULK最大分组尺寸为64字节,因此BULK通过总线1 ms传输1个或多个64字节的分组帧。

4)中断终端要求 中断终端能够保证事件以可预测并及时的方式传递。事件分组可在一定允许延时条件下通过USB发送。对于蓝牙设备,中断终端的时间间隔为1 ms。USB软件和固件无需对传送到主控制器的事件充分了解。

5)同步终端要求 同步终端用于传递SCO数据,主要是音视频数据。时间是该数据类型的重要因素。它允许数据损坏或丢失,但必须保证有恒定的数据流。USB固件以固定速率将数据内容传递到主控制器的SCO先进先出队列(FIFO)。如果FIFO满,则新数据将覆盖原有数据。蓝牙设备可以支持3个64 kb/s语音信道,可以接收不同编码方式的数据―8 bit或16 bit的线性音频编码。默认状态下,同步终端的最大分组尺寸为64字节。如果无需支持3条16 bit编码的语音信道,最大分组尺寸为32字节。

4 Linux下蓝牙USB设备驱动实现

4.1 重要数据结构[5-6]

4.1.1 结构体hci_dev

在嵌入式Linux系统中,任何一种设备在HCI层都被抽象为hci_dev结构体。当蓝牙设备接入系统时,不论以何种方式接入,都要向HCI层或蓝牙核心层注册为一个hci_dev设备。hci_dev结构体主要包含:

1)设备名称(name)、设备地址(bdaddr)、设备标志(flags)、设备类型(type)等设备属性;

2)分组类型(pkt_type)、链接策略(link_policy)、链接模式(link_mode);

3)3 种类型任务队列:CMD任务、发送任务、接收任务;

4)7 种设备操作, 包括 open,close,flush,send,destruct,notify 和 ioctl。

另外还有设备查询状态、查询返回结果、设备锁等。

4.1.2 结构体hci_usb

hci_usb结构体定义了指向hci_dev和usb_device的2个指针。usb_device定义蓝牙usb设备,这样通过这2个指针可将HCI层与蓝牙设备联系起来。hci_usb还定义HCI操作USB设备时所用到的其他数据,诸如数据缓存大小、USB接口、主机端的端点描述符和队列等。

4.1.3 结构体bt_usb_data

结构体bt_usb_data描述USB接口蓝牙模块的数据结构,包含传送数据的缓冲区、I/O端点、消息队列以及缓冲区的消息串和消息串读写位置索引、传送缓冲区的指针以及表示设备是否被激活、是否存在、是否打开等状态标志位。

4.2 驱动程序的注册

在嵌入式Linux系统中,所有设备驱动程序,都必须向内核注册其设备驱动。对于蓝牙USB设备驱动注册,该过程首先创建一个指向usb_dirvier类型的结构体hci_usb_driver,具体内容包括指定驱动程序的名字(hci_usb)、探测函数(hci_usb_probe)、断开函数(hci_usb_disconnect)、 中断函数 (hci_usb_suspend)、 恢复函数(hci_usb_resume)、所支持蓝牙设备列表(bluetooth_ids)。 并由函数module_init、hci_usb_init、usb_register 依次 执 行 ,usb_register最 终 调 用usb_register_driver完成驱动向内核注册。

4.3 驱动程序的注销

当卸载驱动程序时,要在内核中注销驱动程序,释放其占有的资源。该过 程 与 驱 动 注 册 类 似 , 由 module_exit、hci_usb_exit、usb_deregister依次执行,最终 usb_deregister调用usb_deregister_driver完成驱动注销。

4.4 hci_usb_probe过程

当USB设备插入主机时,主机控制器HCI使用控制通道枚举,并给其分配唯一设备地址(1~127),同时读取该设备的class,subclass和protocol等设备描述符。

如果读取到的设备描述符信息与hci_usb驱动程序注册到USB核心的信息相匹配,则将设备与相应的驱动程序进行绑定。调用hci_usb_driver中指定的探测函数hci_usb_probe,初始化结构体hci_usb中部分数据,并注册HCI设备。蓝牙设备探测函数hci_usb_probe具体探测过程如图4所示。

4.5 设备的断开

当蓝牙设备断开连接时,通过调用hci_usb_driver中指定的断开函数hci_usb_disconnect完成。其过程主要包括清空设备的驱动数据,关闭设备,释放与设备相关的资源,并注销内核中相应的HCI设备及释放所占用的资源。

4.6 设备中断与恢复

如果要中断蓝牙设备连接 (只是暂时中断,未释放资源),则通过调用中断函数hci_usb_suspend来完成。其过程是保存hci_dev数据信息,中断HCI与设备连接,互斥访问设备等待队列并把数据信息加入设备等待队列的尾部。如果要恢复被中断过的蓝牙设备的连接,可通过调用恢复函数hci_usb_resume来完成。其过程是互斥访问设备等待队列,取出队列头的hci_dev数据,恢复HCI与设备的连接。若错误,则返回I/O error。

5 实验结果

把交叉编译过的蓝牙USB设备驱动程序以及必要的程序和库移到根文件系统中,启动开发板,在板上USB接口处插上USB蓝牙设备。

加载USB蓝牙驱动,执行hciconfig,可以看到当然蓝牙USB设备使用状态,如图5所示。

图5 加载后USB蓝牙设备状态

6 结束语

本文在硬件平台MP2530上开发实现嵌入式Linux下蓝牙USB设备驱动程序。实验结果显示,基于该驱动的USB蓝牙设备可与其他蓝牙设备正常通讯,其速度比以K单位计算的串口要快得多。USB蓝牙设备驱动程序的开发,为蓝牙设备与其他硬件设备的连接提供了一种高效便捷的途径,同时大大拓展了蓝牙设备的应用。

[1]金 纯,许光辰,孙 睿.蓝牙技术[M].北京:电子工业出版社,2001.

[2]梁军学,郁 滨.Linux蓝牙协议栈的USB设备驱动[J].计算机工程,2008(5):274-275.

[3]钱志鸿,杨 帆,周求湛.蓝牙技术原理、开发与应用[M].北京:北京航空航天大学出版社,2006.

[4]吴艳玮,任长明.蓝牙HCI USB传输层规范[J].计算机工程,2002(2):235-236.

[5]梁正平,毋国庆,肖 敬.Linux中USB设备驱动程序研究[J].计算机应用研究,2004,21(6):70-72.

[6]巍 骛,张焕强,方贵明.基于Linux的USB驱动程序实现[J].计算机应用,2002,22(8):17-19.

猜你喜欢
驱动程序中断蓝牙
蓝牙音箱的直线之美
简单、易用,可玩性强Q AcousticsBT3蓝牙音箱
计算机硬件设备驱动程序分析
适合自己的才是最好的 德生(TECSUN) BT-50蓝牙耳机放大器
跟踪导练(二)(5)
千里移防,卫勤保障不中断
紧急:蓝牙指尖陀螺自燃!安全隐患频出
基于MPC8280的CPU单元与内部总线驱动程序设计
AT89C51与中断有关的寄存器功能表解
FPGA内嵌PowerPC的中断响应分析