嵌入式Linux驱动程序开发(五)-基于libusb的USB驱动开发

姓名:薛绍宏     学号:19020100016    学院:电子工程学院

转自:https://blog.csdn.net/su1041168096/article/details/78989835?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162722361816780265466801%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162722361816780265466801&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-18-78989835.pc_search_result_control_group&utm_term=%E5%B5%8C%E5%85%A5%E5%BC%8Flinux%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91&spm=1018.2226.3001.4449

【嵌牛导读】本文介绍了嵌入式Linux基于libusb的USB驱动开发

【嵌牛鼻子】嵌入式Linux驱动程序开发

【嵌牛提问】嵌入式Linux的USB驱动如何基于libusb进行开发?

【嵌牛正文】

由于usb设备的普遍性及其多样性,大量的usb设备的驱动开发也就成为开发者做的最多的事情。Linux平台上,内核驱动的开发由于内核的复杂和版本问题,初学者难以入手,驱动程序也不易升级和维护。本文主要介绍Linux平台下使用libusb库基于usb文件系统的驱动开发,并将其应用到嵌入式系统中,可显著降低开发难度,提高工作效率

1.前言

Linux内核经过开发人员的不断努力,已经变得十分地完善和强大。其中,设备驱动占据了内核的很大一部分,内核都能够高效、稳定地驱动大部分设备。而另外一些设备,注入自己设计的硬件产品。这些驱动就需要驱动工程师开发出相关的内核设备驱动了。内核驱动有他的优点,然而在内核驱动开发过程中会遇到如下的一些问题:

对于不用的Linux内核版本,驱动程序也会有不同的版本。不利于升级和维护。

Linux自带的驱动程序开发,需要对内核的重新编译,而且开发出来的驱动模块比较大。

所以,如果我们能够找到一个为用户空间提供与内核版本无关的通用接口的方法,就能够不必重新改变编译好的内核,也不必为内核版本兼容性问题而头痛,只需在用户空间开发程序。这样就极大地提高了开发效率,缩短了开发周期。

USB协议是目前使用最广泛的外部总线协议,Linux对usb控制器、usb核心和常用的usb设备驱动有了比较完善的支持。但由于usb所支持的设备的多样性,一些特殊的usb设备的驱动还需要开发人员自行编写。而libusb为开发人员提供了在用户空间操作usb设备的API函数库,使usb驱动开发变得极为方便。

2.实现原理

2.1USB简介

usb(Universal Serial Bus)是用于将适用usb的外围设备连接到主机的外部总线结构。目前usb接口规范主要有:USB1.1(低速1.5Mb/s,全速12Mb/s)和USB2.0(高速480Mb/s),能够满足大部分外围设备的传输速度要求。usb同时又是一种通信协议,他支持主系统(host)和usb的外围设备(device)之间的数据传输。当前流行的USB Host规范有:OHCI、UHCI和EHCI。嵌入式系统主要是使用OHCI规范。

usb驱动分为usb主机端驱动程序和usb设备端驱动程序,本文重点分析usb主机端驱动程序的开发过程。USB主机(host)驱动结构如图:

开发人员主要关注usb设备驱动部分。usb设备的逻辑组织中,包含设备(device)、配置(config)、接口(interface)和端口(endpoint)四个层次:

每个usb设备可以有一个或多个配置,但一次只能选中其中一个。接口经捆绑为配置。接口代表了一个基本功能。

每个usb驱动程序控制一个接口,而一个接口有不同的设置(setting),但同一时间只能有一种活跃配置(cur_altsetting)。设备接口是端点的集合(collection),端点是usb通信的最基本形式。usb主机(host)通过端点与usb设备进行通信。

usb端点有以下四种传输方式:控制(Control),等待(iso)、中断(interrupt)、批量(bulk)。控制和批量端点用于异步的少量数据传输,而批量和等时端点是周期性的。控制和中断端点是用于少量数据传输,而批量和等时端点用于大量数据传输。

控制端点同城用于配置设备、获取设备信息、发送命令到设备、或者获取设备的状态报告,“端点0”为默认的控制端点,usb核心使用该端点在设备插入时进行设备的配置。批量端点它要求数据传输的准确性,但不保证固定时间内的完成。中断端点是例如usb键盘和鼠标所使用的的主要传输方式。libusb主要提供控制、批量和中断的传输方式的API函数。

2.2usb文件系统(usbfs)

Linux内核提供了usb文件系统,他需要编写内核时选中相关编译选项。并在系统启动运行时动态挂载。可在/etc/fstab文件中添加如下一行:

nonc /proc/bus/usb usbfs defaults 0 0

或者输入命令:

mount -t usbfs none /proc/bus/usb

usbfs动态跟踪总线上插入和移除的设备,通过它可以查看系统中usb的设备信息,包括拓扑、带宽、设备描述符、产品ID、配置描述符、接口描述符、端点描述符等。usbfs还允许用户空间的程序直接访问usb设备,这使得容易维护和调试。

usbfs也至此各种ioctl的调用。有了这些ioctl我们就可以编写用户空间的usb驱动程序,而libusb做的工作就是把这些ioctl开发成一个库。

3.libusb实现驱动开发

3.1libusb简介

libusb是一种高级别的API,它封装了低级别的内核与USB模块的交互,并提供了一系列适合在用户空间进行usb驱动开发的函数。libusb基于usb文件系统提供的usb接口,端点等信息,与usb设备进行通信。显然,只要开发平台上的内核支持usb文件系统,我们就可以利用libusb进行usb驱动开发。

libusb可以跨平台实现,开发的程序很容易在不同操作系统上一直。对于Linux操作系统,也很容易在不同的CPU架构间进行移植,而且不低担心内核版本造成的种种问题。相对于Linux内核驱动开发,libusb无疑是一种省时省力而又行之有效的开发工具。

libusb定义了struct usb_bus,struct usb_device 和usb_xxx_descriptor来对usb总线、设备、配置和端点等进行描述。

一般可通过libusb提供的一些初始化函数,在usb文件系统中查找先关的总线和设备,并保存在几个对应的数据结构中:

usb_init()函数检查环境变量USB_DEVFS_PATH,目录/dev/bus/usb或目录/proc/bus/usb,若指定路径下含有usb文件系统信息,则将路径保存在全局变量usb_path[PATH_MAX+1]中。

usb_find_busses()函数会根据usb_path[]找到系统中所有的usb bus,并组成链表,由全局结构指针usb_busses指向。

usb_find_devices()函数则遍历usb_busses指向的链表,寻找所有bus上的所有usb设备。每个bus上的所有devices列表由usb_bus结构成员struct usb_device *devices指向。

我们可用两层的for循环,遍历usb_busses指向的链表,找到与指定描述符相符的usb_device。如通常是通过IDVender和IDProduct查找。

usb_dev_handle是一个十分重要的句柄结构,如果要对usb设备、接口、端点等操作,都离不开它,结构如下:

struct usb_dev_handle{

int fd;

struct usb_bus *bus;

struct usb_device *device;

int config;

int interface;

int altsetting;

void *impl_info;

1

2

3

4

5

6

7

8

域fd为文件描述符,与文件系统关联:域bus和device则指向要处理的usb设备。

开发人员可以使用usb_open(),打开指定的usb设备Dev,并返回相应的句柄结构:

usb_dev_handle *dev_handle = usb_open(dev);

之后,dev_handle便贯穿于对应usb设备的操作过程中,直至最后调用usb_close()关闭指定的usb设备,释放该句柄。

开放人员可使用usb_set_configuration(),usb_setaltinterface()等函数对usb设备的配置,接口和端点等进行设定。然后调用usb_control_msg()进行控制传输,或usb_bulk_write(),usb_bulk_read()进行大批量的端点读写。

3.2开发实例

libusb要应用到嵌入式系统中,需要交叉编译;开发代码中要包含libusb的头文件usb.h,并在编译时,要是用-I和-L选项指定libusb的头文件和库文件的路径,和-lusb指定libusb.a静态库文件。

下面的伪代码在系统中按厂商号和产品号找到usb图像采集设备并读bulk端点到缓冲中,

int main(void)

{

    //...一些初始化工作

    dev_usbdev_probe();//找到usb设备

    dev_hanle = usb_open(dev); //打开设备

    //发送控制信息,请求传输

    usb_control_msg(dev_handle,0x40,0xb5,2,0,buffer,sizeof(buffer),1000);

    if(dev_handle){

    //若请求成功,从端点6传输数据到image_buffer中

        usb_bulk_read(dev_handle,6,&image_buffer[64],64,1000);

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

4.总结

本文实现基础是usbfs允许用户空间的程序直接访问usb设备,这使得许多内核驱动程序可以迁移到用户空间,通过libusb库提供的API函数实现嵌入式Linux驱动开发的方法,使得开发人员无需被底层的usb协议所困,无需区分不同版本内核驱动开发,从而使得usb的驱动开发更容易维护和调试,从而可以提高开发效率并缩短开发周期。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容