linux设备驱动之usb下载,《Linux设备驱动程序》——USB驱动程序

一、概论

1、从拓扑上来看,一个USB子系统并不是以总线的方式来不止的:踏实一颗由几个点对点的链接构造而成的树。这些链接是连接设备和集线器(hub)的四线电缆(地线、电

源 线和两根信号线)。

2、USB总线在技术层面是一个单主方式的实现,在此方式下,主机轮询各种不同的外围设备。此外USB另一个重要特性是它只担当设备和主控制器之间通信的角色,对它所

发送的数据没有任何特殊的内容和结构上的要求。

3、USB协议规范定义了一套任何特定类型的设备都可以遵循的标准。如果一个设备遵循该标准,就不需要一个特殊的驱动程序。

4、Linux支持两种主要类型的USB驱动程序:宿主(host)系统上的驱动程序和设备(device)上的驱动程序。

5、USB驱动程序概观。(P325  图13-1)

二、USB设备基础

一)、端点

1、USB通信最基本的形式是通过一个为端点的东西。USB端点只能往一个方向传输数据,从主机到设备(称为输出端点)或者从设备到主机(称为输入端点)。

2、USB端点有四种不同的类型,分别具有不同的传送数据的方式:

1)、控制:控制端点用来控制对USB设备不同部分的访问。

2)、中断:每当USB宿主要求设备传输数据时,中断端点就以一个固定的速率来传送少量的数据。

3)、批量:批量端点传输大量数据。

4)、等时:等时端点同样可以传送大批量的数据,但数据是否到达是没有保证的。

3、内核中用struct  usb_host_endpoint结构体来描述USB端点。该结构体在另一个名为struct  usb_endpoint_descriptor的结构体中包含了真正的端点信息:

1)、bEndpointAddress:特定端点的USB地址。

2)、bmAttributes:端点的类型。

3)、wMaxPacketSize:该端点一次可以处理的最大字节数。

4)、bInterval:如果端点是中断类型,该值是端点的间隔设置。

二)、接口

1、USB端点被捆绑为接口。USB接口只处理一种USB逻辑链接。一些USB设备具有多个接口。USB接口可以有其他的设置,这些适合接口的参数不同的选择。

2、内核使用struct  usb_interface结构体来描述USB接口。USB核心把该结构体传递给USB驱动程序,之后由USB驱动程序来负责控制该结构体。

1)、struct  usb_host_interface  *altsetting:一个接口结构体数组,包含了所有可能用于该接口的可选设置。

2)、unsigned  num_altsetting:altsetting指针所指向的可选设置的数量。

3)、struct  usb_host_interface  *cur_altsetting:指向altsetting数组内部的指针,表示该接口的当前活动设置。

4)、int  minor:如果绑定到该接口的USB驱动程序使用USB主设备号,这个变量包含USB核心分配给该接口的次设备号。

三)、配置

1、USB接口本身被捆绑为配置。一个USB设备可以有多个配置,而且可以在配置之间切换以改变设备的状态。

2、Linux使用struct  usb_host_config结构体来描述USB配置,使用struct  usb_devices结构体来描述整个USB设备。

3、USB设备非常复杂,它由许多不同的逻辑单元组成。这些逻辑单元之间关系可以简单地描述如下:

1)、设备通常具有一个或更多的配置。

2)、配置经常具有一个或更多的接口。

3)、接口通常具有一个或者更多的设置。

4)、接口没有或者具有一个以上的端点。

三、USB和Sysfs

1、无论是物理USB设备(用struct  usb_device表示)还是单独的USB接口(用struct  usb_interface表示),在sysfs中表示为单独的设备。

2、内核如何分类USB设备

1)、第一个USB设备是一个根集线器(root  hub)。所有的根集线器都由USB核心分配了一个独特的编号。

2)、USB总线上的每个设备都以根集线器的编号作为其名字中的第一个号码。该号码随后是一个横杆字符和设备插入的端口号。

3)、在后面是一个冒号加配置的编号加横杆随后是一个接口号。

3、USB  sysfs设备命名方案为:

根集线器 - 集线器端口号:配置 . 接口

1)、对于两层的树:根集线器 - 集线器端口号- 集线器端口号:配置 . 接口

4、sysfs并没有展示USB设备所有的不同部分,它只限于接口级别。

四、USB  urb

一)、相关简介

1、Linux内核中的USB代码通过一个称为urb的东西和所有的USB设备通信。这个请求快使用struct  urb结构体来描述。

1)、urb被用来以一种异步的方式往/从特定的USB设备上的特定USB端点发送/接受数据。

2)、USB设备驱动程序可能会为单个端点分配速度哦urb,也可能对许多不同的端点重用单个urb,这取决于驱动程序的需要。

3)、设备中的每个端点都可以处理一个urb队列,所以多个urb可以在队列为空之前发送到同一端点。

2、一个urb典型生命周期。

二)、struct  urb

1、struct  urb结构体中USB设备驱动程序需要关心的字段(P332-P338)。

三)、创建和销毁urb

1、struct  urb结构体不能在驱动程序中或者另一个结构体中静态创建。它必须使用以下函数创建:

struct  urb  *usb_alloc_urb(int  iso_packets,  int  mem_flags);

1)、当一个urb被创建之后,在它可以被USB核心使用之前必须被正确地初始化。

2、驱动程序必须调用以下函数告诉USB核心驱动程序已经用完urb:

void  usb_free_urb(struct  urb  *urb);

四)、中断urb

1、以下函数用来正确的初始化即将被发送到USB设备的中断端点的urb:

void  usb_fill_int_urb(struct  urb  *urb,  struct  usb_device  *dev,

unsigned  int  pipe,  void  *transfer_buffer,

int  buffer_length,  usb_complete_t  complete,

void  *context,  int  interval);

2、函数参数。

五)、批量urb

1、批量urb的初始化所使用的函数如下:

void  usb_fill_bulk_urb(struct  urb  *urb,  struct  usb_device  *dev,

unsigned  int  pipe,  void  *transfer_buffer,

int  buffer_length,  usb_complete_t  complete,

void  *context);

2、函数参数。

六)、控制urb

1、控制urb的初始化方法用以下函数:

void  usb_fill_control_urb(struct  urb  *urb,  struct  usb_device  *dev,

unsigned  int  pipe,  unsigned  char  *setup_packet,

void  *transfer_buffer, int  buffer_length,

usb_complete_t  complete,void  *context);

2、函数参数。

七)、等时urb

1、等时urb没有和中断、控制和批量urb类似的初始化函数。

八)、提交urb

1、一旦被USB驱动程序正确地创建和初始化之后,就可以提交到USB核心以发送到USB设备:

int  usb_submit_urb(struct  urb  *urb,  int  mem_flags);

2、函数参数。

九)、结束urb:结束回调处理例程

1、如果usb_submit_urb成功,把对urb的控制权转交给USB核心,该函数返回0;否则,返回负的错误编号。如果函数调用成功,当urb结束的时候urb的结束处理例程正好被

调用一次。当该函数被调用时,USB核心结束了对URB的处理,此刻对它的控制被返回给设备驱动程序。

2、只有三种结束urb和调用结束函数的情形。

十)、取消urb

1、应该调用以下两个函数来终止一个已经被提交到USB核心的urb:

int  usb_kill_urb(struct  urb  *urb);

int  usb_unlink_urb(struct  urb  *urb);

五、编写USB驱动程序

一)、驱动程序支持那些设备

1、struct  usb_device_id结构体提供了一系列不同类型的该驱动程序支持的USB设备。USB核心使用该列表来判断对于一个设备该使用哪一个驱动程序,热插拔脚本使用它来

来确定当一个特定的设备插入到系统时该自动装载哪一个驱动程序。

2、struct  usb_device_id结构体包括的字段(P343)。

3、对于PCI设备,有许多用来初始化该结构体的宏(P344)。

二)、注册USB驱动程序

1、所有USB驱动程序都必须创建的主要结构体struct  usb_driver。该结构体必须由USB驱动程序来填写,包括许多回调函数和变量,它们像USB核心代码描述了USB驱动程

序。(P344-P345)

2、struct  usb_driver还包含了几个回调函数。(P345-P346)

3、以struct  usb_driver指针为参数的usb_register_driver函数调用把struct  usb_driver注册到USB核心。

4、当USB驱动程序将要被卸载时,需要把struct  usb_driver从内核中注销。通过调用usb_deregister_driver来完成该工作。

三)、探测和断开的细节

1、当一个设备被安装而USB核心认为该驱动程序应该处理时,探测函数被调用;探测函数应该检查传递给它的设备信息,确定驱动程序是否真的适合该设备。当驱动程序因

为某种原因不应控制设备时,断开函数被调用,它可以做一些清理的工作。

2、探测和断开回调函数都是在USB集线器内核线程的上下文中被调用的,因此在其中睡眠是合法的。

3、在探测函数中,USN驱动程序应该初始化任何可能用于控制USN设备的局部结构体,它还应该把所需的任何设备相关信息保存到局部结构体中,因为在此时该工作是比较

容易的。

4、struct  usb_class-driver用于定义许多不同的参数,在注册一个设备号时USB驱动程序需要USB核心知道这些函数。(P349-P340)

四)、提交和控制urb

六、不使用urb的usb传输

一)、usb_bulk_msg

1、usb_bulk_msg创建一个USB批量urb,把它发送到指定的设备,然后在返回调用者之前等待它的结束

int  usb_bulk_msg(struct  usb_device  *usb_dev,  unsigned  int  pipe,

void  *data,  int  len,  int  &actual_length.  int  timeout);

2、函数参数。

3、不能在一个中断上下文或者在持有自旋锁的情况下调用usb_bulk_msg函数。同样,该函数不能被任何其他函数取消,因此使用它的时候要小心;确保驱动程序的断开函数

了解足够的信息;在允许自身从内存中被卸载之前等待该调用的结束。

二)、usb_control_msg

1、除了允许驱动程序发送和接受USB控制消息之处,usb_control_msg函数的运作和usb_bulk_msg函数类似:

int  usb_control_msg(struct  usb_device  *dev,  unsigned  int  pipe,

__u8  request,  __u8  requesttype,

__u16  value,  __16  index,

void  *data,  __u16  size,  int  timeout);

2、函数参数。

3、不能在一个中断上下文或者在持有自旋锁的情况下调用usb_bulk_msg函数。同样,该函数不能被任何其他函数取消,因此使用它的时候要小心;确保驱动程序的断开函数

了解足够的信息;在允许自身从内存中被卸载之前等待该调用的结束。

三)、其他USB数据函数

1、usb_get_descriptor函数从指定的设备获取指定的USB描述符。

int  usb_get_descriptor(struct  usb_device  *dev,  unsigned  char  type,

unsigned  char  index,  void  &duf,  int  size);

1)、USB驱动程序可使用该函数来从struct  usb_device结构体中获取任何没有存在于已有的struct  usb_device和struct  usb_interface结构体中的设备描述符。

2)、函数参数。

2、usb_get_string(struct  usb_device  *dev,  unsigned  short  langid,

unsigned  char  index,  void  *buf,  int  size);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux下,编写USB设备驱动程序的过程可以分为以下几个步骤: 1. 确定驱动程序的框架:一般情况下,驱动程序需要使用Linux内核提供的USB子系统进行通信。可以选择使用USB核心驱动框架,如usbcore或者usbfs,这取决于驱动程序的需求和功能。 2. 编写设备识别和初始化函数:USB设备Linux系统中由Vendor ID(厂商ID)和Product ID(产品ID)唯一标识。在驱动程序中,需要编写设备识别函数,通过与系统中的已知设备进行匹配,确定设备的类型和特性。然后,初始化设备的状态和资源。 3. 实现设备的控制和数据传输:USB设备通常具有多个接口和端点,每个端点的功能和方向都不同。驱动程序需要实现设备的控制和数据传输功能,包括读取设备的描述符、配置设备、发送和接收数据等。 4. 处理中断和事件:某些USB设备可能会产生中断或者其他事件,这需要驱动程序对这些事件进行处理。可以注册中断处理程序或事件处理程序,并根据设备的需求进行响应。 5. 编写设备文件操作函数:Linux系统将USB设备作为设备文件进行管理。驱动程序需要编写打开、关闭、读取、写入等操作函数,将应用程序的请求传递给对应的设备。 6. 编译和加载驱动程序:完成驱动程序的编写后,需要将其编译成模块或者内核。通过insmod命令将驱动程序模块加载到内核中,然后可以通过udev等工具进行设备的管理和配置。 编写USB设备驱动程序需要对Linux内核有一定的了解,了解USB协议和接口规范,掌握Linux内核编程的基本知识。同时,还需要通过查阅文档和示例代码来学习和理解USB设备驱动程序的编写方法和技巧。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值