33.驱动--usb

usb驱动的写法

19.Linux-USB总线驱动分析 - 诺谦 - 博客园

20.Linux-USB鼠标驱动 - 诺谦 - 博客园

21.Linux-写USB键盘驱动(详解) - 诺谦 - 博客园

usb驱动的一些概念帖子

Linux设备驱动之usb设备驱动详解_chenjin_zhong的博客-CSDN博客

USB_4大描述符 - 诺谦 - 博客园

USB中的端点详细了解_go_str的博客-CSDN博客_usb 端点

USB设备---URB请求块 - 隔壁王叔叔a - 博客园

Linux usb驱动开发(基础)_zuodenghuakai的博客-CSDN博客_linux usb驱动

linux中的USB驱动理解-Acikee-ChinaUnix博客

目录

第一步:

第二步:

第三步:

第四步:

 其他:


        看了好多帖子,按自己的理解写写加深印象

        内核usb驱动分三个,一是usb总线和usb_device,这两个是内核自带,自动运行,二是usb_dirive驱动,这是用户自己的写

usb驱动使用platform机制,所以会有usb_driver和usb_device两部分,两部分配对上的话,就会调用prob函数,跟普通platform机制不同的是,usb总线驱动不是用name进行匹配,而是使用id_table进行匹配。

匹配上,内核会自动运行usb_device部分,注册usb_device结构体,分配地址,初始化端口建立连接,建立新设备节点,匹配对应的驱动。这部分是内核自动执行,细节就不想写了,知道咋回事就行。

详细了解如何写的usb_device驱动部分就好。

        既然usb使用platform机制,usb_driver驱动部分写法跟普通的device写法就差别不大。

第一步:

分配并设置usb_driver结构体,name不重要,匹配使用的是id_table

id_table[]是一个数组,可以有很多个设备的ID,每个设备使用USB_INTERFACE_INFO()这个宏定义来定义。

参数根据设备的实际天填写

 当我们插上USB设备时,系统就会获取USB设备的设备、配置、接口、端点的数据,

第二步:

注册分配的usb_driver结构体,通知内核。内核会自动匹配,匹配上就会调用prob函数。

第三步:

完善prob函数,完成usb设备的功能

一个完整的usb设备,从上往下,包括设备描述符,配置描述符,接口描述符,端点描述符。

 一个USB设备可以有多个配置,并可在它们之间转换以改变设备的状态。

一个配置可以有多个接口, 一个USB接口代表一个基本功能,每个USB驱动控制一个接口

端点可被看作一个单向的管道。4 种不同类型:控制(CONTROL)传输、批量(BULK)传输(U盘)、中断(INTERRUPT)传输(定时轮询如小数据量:鼠标键盘)、等时(ISOCHRONOUS)传输(类似UDP 不可靠大量数据的轮询:音频和视频设备)。

USB请求块urb是USB设备驱动中用来描述与usb设备通信所用的基本载体和核心数据结构体,类似于网络驱动的sk_buff。包括”源,长度,目标“三部分。用户需要根据设备、配置、接口、端点的信息构造一个urb块,用于传输。

1)获取设备、接口、端点的信息

关于设备描述结构体、配置描述结构体、接口描述结构体以及端口描述结构体看该文章:USB_4大描述符 - 诺谦 - 博客园

interface_to_usbdev()函数可以通过一个接口返回一个usb设备的详细信息

2)构造urb块

关于urb块的详细看该文章: USB设备---URB请求块 - 隔壁王叔叔a - 博客园

 usb端点分为控制(初始化等)、中断(鼠标、键盘等)、等时()以及批量()模式

端点的传输方式:

1:控制control:用于配置设备,获取设备信息,发送命令到设备,usb协议保证有足够的带宽传输数据到设备

2:中断int:中断端点以一个固定的速录传输少量的数据,鼠标、键盘等

3:批量bulk:传输大量数据(可确保传输数据,不确保传输时间,eg:存储设备)

4:等时:传输大量数据(确保传输时间,不确保传输内容,eg:摄像头)

        2.1)创建一个urb结构体

创建URB:struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)

分配一个urb数据结构体, 分配成功返回一个urb结构体

iso_packets:表示iso类型的包个数,这里我们不是iso类型包,直接填0

mem_flags:分配内存的参数,这里填入GFP_KERNEL,正常分配

void *usb_alloc_urb(struct urb)//释放

         2.2)构造urb块需要的源,长度,目的三要素,然后初始化分配的urb块,把三要素放进urb块里

        通过buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma)分配缓冲区空间

        len = endpoint->wMaxPacketSize;获取端点内数据的长度

        pipe的构造和urb块要根据具体的端点模式使用不同的函数构造

        2.2.1)

中断urb的创建:static inline 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_fn, void *context,int interval))

参数含义如下:

Urb:是要初始化的urb

Dev:表示消息要被发送到的USB设备

Pipe:表示消息被发送到的端点

transfer_buffer:表示发送数据的缓冲区

length:就是transfer_buffer所表示的缓冲区大小

context:完成处理函数的上下文

complete_fn:传输完了之后要调用的函数.(这需要用户自己完善)

usb_fill_control_urb()的setup_packet:即将被发送到端点的设备数据包

usb_fill_int_urb()中的interval:这个urb应该被调度的间隔.

函数的pipe使用通过usb_sndintpipe()或者usb_rcvintpipe()创建。
 

        2.2.2)

批量urb初始化:static inline 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_fn,void *context)

函数的pipe使用通过usb_sndbulkpipe()或者usb_rcvbulkpipe()创建

        2.2.3)

控制urb:static inline void usb_fill_control_urb(struct urb *urb,//urb指针
                    struct usb_device *dev, //要被发送到的USB设备结构
                    unsigned int pipe,//特定端点
                    unsigned char *setup_packet, //指向即将被发送到端点的设置数据包
                    void *transfer_buffer,
                    int buffer_length,
                    usb_complete_t complete_fn,
                    void *context)()

函数的pipe使用通过usb_sndcontrolpipe()或者usb_rcvcontrolpipe()创建
        2.2.4)

等时urb,没有初始化函数的接口,我们只能手动初始化urb,然后提交给usb核心。

 3)使用usb_submit_urb()函数提交urb块

在提交urb到usb的核心后,知道完成函数被调用之前,不要访问URB中的任何成员。如果提交成功,即urb的控制权被移交给USB的核心。被主机控制器处理,进行一次到usb设备的传送,URB完成,usb主机驱动控制器通知usb设备驱动。

对于complete_fn参数,传输完了之后要调用的函数内,末尾都要重新提交一次

 以下是传输完了之后要调用的函数的例子

第四步:

完善disconnect函数,usb被拔出等退出操作会自动执行,在这里把前面分配注册的所有资源全部删除

 其他:

都是些概念,直接复制粘贴就好

现象:把USB设备接到PC
1. 右下角弹出"发现android phone"
2. 跳出一个对话框,提示你安装驱动程序

问1. 既然还没有"驱动程序",为何能知道是"android phone"
答1. windows里已经有了USB的总线驱动程序,接入USB设备后,是"总线驱动程序"知道你是"android phone"
     提示你安装的是"设备驱动程序"
     
     USB总线驱动程序负责:识别USB设备, 给USB设备找到对应的驱动程序

问2. USB设备种类非常多,为什么一接入电脑,就能识别出来?
答2. PC和USB设备都得遵守一些规范。
     比如:USB设备接入电脑后,PC机会发出"你是什么"?
           USB设备就必须回答"我是xxx", 并且回答的语言必须是中文
     USB总线驱动程序会发出某些命令想获取设备信息(描述符),
     USB设备必须返回"描述符"给PC
     
问3. PC机上接有非常多的USB设备,怎么分辨它们?
     USB接口只有4条线: 5V,GND,D-,D+
答3. 每一个USB设备接入PC时,USB总线驱动程序都会给它分配一个编号
     接在USB总线上的每一个USB设备都有自己的编号(地址)
     PC机想访问某个USB设备时,发出的命令都含有对应的编号(地址)

问4. USB设备刚接入PC时,还没有编号;那么PC怎么把"分配的编号"告诉它?
答4. 新接入的USB设备的默认编号是0,在未分配新编号前,PC使用0编号和它通信。

问5. 为什么一接入USB设备,PC机就能发现它?
答5. PC的USB口内部,D-和D+接有15K的下拉电阻,未接USB设备时为低电平
     USB设备的USB口内部,D-或D+接有1.5K的上拉电阻;它一接入PC,就会把PC USB口的D-或D+拉高,从硬件的角度通知PC有新设备接入

其他概念:
1. USB是主从结构的
   所有的USB传输,都是从USB主机这方发起;USB设备没有"主动"通知USB主机的能力。
   例子:USB鼠标滑动一下立刻产生数据,但是它没有能力通知PC机来读数据,只能被动地等得PC机来读。

2. USB的传输类型:
a. 控制传输:可靠,时间有保证,比如:USB设备的识别过程
b. 批量传输: 可靠, 时间没有保证, 比如:U盘
c. 中断传输:可靠,实时,比如:USB鼠标
d. 实时传输:不可靠,实时,比如:USB摄像头

3. USB传输的对象:端点(endpoint)
   我们说"读U盘"、"写U盘",可以细化为:把数据写到U盘的端点1,从U盘的端点2里读出数据
   除了端点0外,每一个端点只支持一个方向的数据传输
   端点0用于控制传输,既能输出也能输入
   
4. 每一个端点都有传输类型,传输方向

5. 术语里、程序里说的输入(IN)、输出(OUT) "都是" 基于USB主机的立场说的。
   比如鼠标的数据是从鼠标传到PC机, 对应的端点称为"输入端点"
     
6. USB总线驱动程序的作用
a. 识别USB设备
b. 查找并安装对应的设备驱动程序
c. 提供USB读写函数


USB驱动程序框架:

app:   
-------------------------------------------
          USB设备驱动程序      // 知道数据含义
内核 --------------------------------------
          USB总线驱动程序      // 1. 识别, 2. 找到匹配的设备驱动, 3. 提供USB读写函数 (它不知道数据含义)
-------------------------------------------
           USB主机控制器
           UHCI OHCI EHCI
硬件        -----------
              USB设备

UHCI: intel,     低速(1.5Mbps)/全速(12Mbps)
OHCI: microsoft  低速/全速
EHCI:            高速(480Mbps)

USB总线驱动程序的作用
1. 识别USB设备
1.1 分配地址
1.2 并告诉USB设备(set address)
1.3 发出命令获取描述符
描述符的信息可以在include\linux\usb\Ch9.h看到


2. 查找并安装对应的设备驱动程序

3. 提供USB读写函数

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值