linux device driver之usb驱动编程

先谈谈如何写linux驱动:
- 在驱动模块初始化函数中调用register_chrdev(),将驱动向系统注册为一个字符设备,伪装成一个文件,上层的应用可以通过访问这个文件(字符设备),来操作驱动模块。
- 驱动模块注册为字符设备后,还需要用户在命令行中敲mknod命令来创建一个对应的字符文件,上层应用就是用open, close, read, write该文件这样的方式来访问驱动模块。
- 装了udev的系统,可以让系统自动为您创建该字符文件:首先调用cdev_init()和cdev_add()来创建字符设备,然后通过调用device_create()在/dev/目录下创建对应的字符文件,
具体方法可以参考sdk8remote代码中Dib07x0RegisterDev()函数。另,需要在etc/udev/rules.d/目录下放相应的rules文件


接着谈谈usb驱动的写法,以sdk8remote项目代码为例:


- module_init(Dib07x0ModuleInit)
驱动模块初始化入口


- Dib07x0ModuleInit():模块初始化函数
调用usb_register()注册usb接口驱动


- usb_register():usb驱动接口注册函数
1. 可以在Dib07x0ModuleInit()里调用,这样insmod之后,驱动接口即被注册(设备id被注册),有相应设备插入则probe会被调用(此种做法参考LinuxKernelSdioMx28)
2. 也可以在usb设备初始化时调用,这样设备插入时,probe不会被调用,只有在usb设备初始化时,usb_register()被调用,系统才会重新检测设备id,并调用probe。(此种做法好处是,模块初始化不涉及何种设备,具有更好的通用性。参考LinuxKernelSdioMx53)

- static struct usb_driver Dib07x0UsbDriver
是usb接口驱动的结构体包括probe()函数等,如下
static struct usb_driver Dib07x0UsbDriver = 
{
#if LINUX_VERSION_CODE <=  KERNEL_VERSION(2,6,15)
   .owner      = THIS_MODULE,
#endif
   .name       = "dib07x0",
   .probe      = Dib07x0UsbProbe,
   .disconnect = Dib07x0UsbDisconnect,
   .suspend   = Dib07x0UsbSuspend,
   .resume   = Dib07x0UsbResume,
   .id_table   = Dib07x0UsbTable,
#if LINUX_VERSION_CODE >=  KERNEL_VERSION(2,6,19)
   .supports_autosuspend = 1,
#endif
};


其中.id_table很重要,它里面定义了此usb驱动模块关心的usb设备id号,只有插入的usb设备的id号和这里面定义的id对应上,系统才会调用.probe函数。


- Dib07x0UsbProbe()
系统发现设备后调用的函数,可以在这个函数里做接口和端点的设置和判断,然后调用Dib07x0RegisterDev()分别创建不同端点的字符设备。


- Dib07x0RegisterDev()
调用cdev_init()和cdev_add(),将驱动模块向系统注册为字符设备,并将操作该设备的接口函数file_operations也一起注册了。
由于一般usb设备都有多个接口和端点,而每一个端点对应一个字符设备(如control端点和data端点分别对应两个字符设备),因此注册字符设备的操作必须在probe函数里调用,
即只有在系统检测到硬件设备并发现端点时一个一个地去注册字符设备。注销字符设备,则在设备移除函数.disconnect()里调用(参考sdk8remote代码)


- struct file_operations
包含如下最基本的文件操作函数,
struct file_operations fops = 
{
.ioctl   = DibBridgeTargetModuleIoctl,                      //控制命令或数据传输
.open    = DibBridgeTargetModuleOpen,  
.read    = DibBridgeTargetModuleReadData,          //数据传输
.write = DibBridgeTargetModuleWriteData
.release = DibBridgeTargetModuleRelease, 
};


- Dib07x0UsbDisconnect()
usb设备断开时系统会调用此函数来处理


- Dib07x0UsbSuspend()
系统休眠时,会调用此函数来处理


- Dib07x0UsbResume()
系统恢复时,会调用此函数来处理


- .supports_autosuspend 
设为1时,表示此设备(或驱动)支持usb的选择性挂起(selective suspend or autosuspend):选择性挂起是指在系统不休眠的情况下,系统主动停止不工作的外设,
比如插在某一个usb口上的usb dongle等,这时系统和其他usb端口还是正常工作的,主要是为了省电。


关于USB读写操作
- 主机对USB设备的读写操作需要借助URB(Usb Request Block):usb_alloc_urb,usb_fill_bulk_urb,usb_submit_urb等。这是异步操作,URB完成之后,会回调一个completing function来做结束,在回调函数里去判断urb返回的状态。系统会负责user space和kernel space之间的数据交换。
- 还有另外一个不需要创建URB的选择,即usb_control_msg和usb_bulk_msg,这两个函数是同步函数,因此适合小批量数据传输,不适合做大批量数据传输或者在中断函数里使用。其中,usb_control_msg是顾名思义是专为contorl EP使用的,usb_bulk_msg是给其它EP用的。如果函数运行成功(读操作),需要调用copy_to_user()将读取到的数据传送到user space。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux USB设备驱动是用于在Linux操作系统中管理和控制USB设备的软件模块。USB设备驱动负责与硬件进行通信,并提供操作系统和用程序与USB设备之间的接口。 在Linux中,USB设备驱动是作为内核模块加载的。它们可以通过以下几个步骤来实现: 1. 设备识别和匹配:USB设备驱动首先需要通过USB总线进行设备识别和匹配。当插入USB设备时,内核会检测到设备的插入并分配一个唯一的设备地址。 2. 驱动注册:设备识别后,驱动程序需要向内核注册,以便内核知道如何处理该设备。这可以通过将驱动程序结构体注册到USB子系统来完成。 3. 端点配置:USB设备通常有多个端点(Endpoint),每个端点都有特定的功能。驱动程序需要配置这些端点,包括端点的方向(输入或输出)、传输类型(控制、批量、中断、等等)以及数据包的大小等参数。 4. 数据传输:一旦设备和端点配置完成,驱动程序就可以开始与USB设备进行数据传输。它可以使用内核提供的USB核心函数来发送和接收数据。 5. 销毁和注销:当USB设备被拔出时,驱动程序需要进行清理工作,并从内核中注销。 编写USB设备驱动需要了解Linux内核的USB子系统和设备模型,以及设备的硬件规格和通信协议。在Linux内核源代码树中,有一些示例驱动可供参考,帮助开发者快速入门和实现自己的USB设备驱动

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值