linux编写usb驱动程序,usb驱动编写笔记(Linux)

编写USB驱动程序步骤:

1所有usb驱动都必须创建主要结构体struct usb_driver

struct usb_driver

->struct module *owner

(有他可正确对该驱动程序引用计数,应为THIS_MODULE)

->const char *name

(驱动名字,运行时可在查看 /sys/bus/usb/drivers/)

->const struct usb_device_id *id_table

(包含该驱动可支持的所有不同类型的驱动设备,没添探测回调函数不会被调用)

->int (*probe)(struct usb_interface *intf,const struct usb_device_id *id)

(usb驱动探测函数,确认后struct usb_interface 应恰当初始化,然后返0,如果出错则返负值)

->void(*disconnect)(struct usb_interface *intf)

(当struct usb_interface 被从系统中移除或驱动正从usb核心中卸载时,usb核心将调用此函数)

代码实例:

static struct usb_driver skel_driver={

.owner = THIS_MODULE,

.name = "skeleton",

.id_table = skel_table,

.probe = skel_probe,

.disconnect = skel_disconnect,

};

2usb_register()注册将struct usb_driver 注册到usb核心,传统是在usb驱动程序模块初始化代码中完成该工作的

static int __init usb_skel_init(void)

{

...

usb_register(&skel_driver);

...

}

3struct usb_device_id usb核心用该表判断哪个设备该使用哪个驱动程序,热插拔脚本使用它来确定当一个特定的设备插入到系统时该自动装载哪个驱动程序。

->__u16 match_flags(确定设备和结构体中下列字段中哪一个相匹配)

->__u16 idVendor(设备的usb制造商id)

->__u16 idProduct(设备的usb产品id)

4USB骨架程序的关键几点如下:

1. USB驱动的注册和注销

Usb驱动程序在注册时会发送一个命令给usb_register,通常在驱动程序的初始化函数里。

当要从系统卸载驱动程序时,需要注销usb子系统。即需要usb_unregister 函数处理。

2 当usb设备插入时,为了使linux-hotplug(Linux中PCI、USB等设备热插拔支持)系统自动装载驱动程序,你需要创建一个MODULE_DEVICE_TABLE。代码如下(这个模块仅支持某一特定设备):

static struct usb_device_id skel_table [] = {

{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },

{ } /* Terminating entry */};

MODULE_DEVICE_TABLE (usb, skel_table);

USB_DEVICE宏利用厂商ID和产品ID为我们提供了一个设备的唯一标识。当系统插入一个ID匹配的USB设备到USB总线时,驱动会在USB

core中注册。驱动程序中probe 函数也就会被调用。usb_device 结构指针、接口号和接口ID都会被传递到函数中。

3 static void * skel_probe(struct usb_device *dev,unsigned int ifnum, const struct usb_device_id *id)

驱动程序需要确认插入的设备是否可以被接受,如果不接受,或者在初始化的过程中发生任何错误,probe函数返回一个NULL值。否则返回一个含有设备驱动程序状态的指针。通过这个指针,就可以访问所有结构中的回调函数。

4 在骨架驱动程序里,最后一点是我们要注册devfs。我们创建一个缓冲用来保存那些被发送给usb设备的数据和那些从设备上接受的数据,同时USB urb 被初始化,并且我们在devfs子系统中注册设备,允许devfs用户访问我们的设备。注册过程如下:

/* initialize the devfs node for this device and register it */sprintf(name, "skel%d", skel->;minor);

skel->devfs = devfs_register (usb_devfs_handle, name,DEVFS_FL_DEFAULT, USB_MAJOR,USB_SKEL_MINOR_BASE + skel->minor,

S_IFCHR | S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP | S_IROTH, &skel_fops, NULL);

如果devfs_register函数失败,不用担心,devfs子系统会将此情况报告给用户。

当然最后,如果设备从usb总线拔掉,设备指针会调用disconnect 函数。驱动程序就需要清除那些被分配了的所有私有数据、关闭urbs,并且从devfs上注销调自己。

/* remove our devfs node */devfs_unregister(skel->;devfs);

5其他

1 struct usb_host_endpoint(描述usb端点)

→(包含) struct usb_endpoint_descriptor(含真正端点信息,数据格式,是真正驱动关心的字段)

端点描述符:

bEndpointAddress = 81(in)(第8位为1是输入设备)(usb的端点地址,包含端点方向)

bmAttibutes = 03(interrupt)(端点类型,为中断传输)

wMaxPacketSize = 0008(每次传8个字节)(端点每次可处理最大字节长度)

bInterval = 08(8ms)(如端点为中断,该值为轮询间隔)

2 usb端点捆绑为接口,usb接口只处理一种usb逻辑连接,如鼠标键盘等.

一个usb设备可有多接口,usb扬声器:一个usb键盘用于按键,一个usb音频流,则需两个不同的驱动程序。

usb驱动 通常将struct usb_interface 转成 struct usb_device 用函数 interface_to_usbdev转

3 struct usb_interface 描述usb接口

→struct usb_host_interface * altsetting(接口结构体数组,包含所有可能用于该接口的可选设置)

→struct usb_host_endpoint

→unsigned num_altsetting(可选设置的数量)

→struct usb_host_interface * cur_altsetting(接口当前活动设置)

→int minor(usb核心分配给接口的次设备号,成功调用usb_register_dev有效)

4 usb设备非常复杂,由许多不同逻辑单元组成,简单关系如下:

设备通常有一个以上的配置

配置经常有一个以上接口

接口通常有一个以上设置

接口通常有一个以上端点

设备描述-》配置描述-》接口描述-》端点描述

5 usb sysfs设备命名方案

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

对于usb hub树中层次更高的字树命名方案

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

6 linux内核的代码通过一个成为urb(usb请求块)和所有usb设备通信.    用struct urb描述(include/linux/usb.h中定义)

->urb用异步同usb设备特定usb端点发送/接收数据,使用类似网络代码中的struct skbuff

-> urb 被动态创建,随时可被驱动程序或usb核心取消,内部有引用计数,可被多次调用,使他们可在最后一个使用者释放他们时自动地销毁

-> urb使得流处理或其他复杂的重叠的通信成为可能,获得高数据传输速度。

->usb_alloc_urb() 创建urb包 usb_free_urb() 释放urb包

->usb_fill_int_urb()正确初始化将发送到usb设备的中断端点urb

usb_fill_bulk_urb() .. .. .. ... 批量传输端点urb

usb_fill_control_urb() .. .. .. ... 控制端点urb

等时urb在提交给核心时必须手动初始化(很不幸,没函数)

->usb_submit_urb()urb被usb驱动正确创建和初始化后,就可提交到usb核心,发送到usb设备上了,如果调用成功,函数返0,urb控制权转给usb核心

->usb_kill_urb() or usb_unlink_urb()取消已经被提交给核心的urb

阅读(1397) | 评论(0) | 转发(6) |

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux设备驱动程序是用于控制和管理硬件设备的软件模块。学习Linux设备驱动程序可以帮助开发人员理解和掌握Linux内核的工作原理,以及如何编写和调试设备驱动程序。 以下是一些学习Linux设备驱动程序笔记和建议: 1. 理解Linux设备模型:Linux设备模型是一种用于管理设备的框架,它提供了一种统一的方式来表示和操作设备。学习Linux设备模型可以帮助你理解设备的注册、初始化和销毁过程。 2. 学习字符设备驱动程序:字符设备是一种以字节为单位进行读的设备,如串口、终端等。学习字符设备驱动程序可以帮助你了解字符设备的打开、关闭、读等操作,并学习如何实现设备文件的注册和操作。 3. 学习块设备驱动程序:块设备是一种以块为单位进行读的设备,如硬盘、闪存等。学习块设备驱动程序可以帮助你了解块设备的分区、缓存、IO调度等操作,并学习如何实现块设备的注册和操作。 4. 学习中断处理:中断是设备向处理器发送信号的一种机制,用于通知处理器设备的状态变化。学习中断处理可以帮助你了解中断的注册、处理和释放过程,并学习如何编写中断处理程序。 5. 学习设备驱动程序的调试技巧:设备驱动程序的调试是一个重要的技能,可以帮助你快速定位和解决问题。学习设备驱动程序的调试技巧可以帮助你理解和使用调试工具,如 printk、kprobe等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值