EDN China > 技术文章 > 通信 > 正文
?

Linux环境下USB的原理、驱动和配置

来源:CSDN/作者:北京中科红旗软件技术有限公司 嵌入式工程师 梁国军?? 2007年10月26日 ?? 收藏0

  USB驱动程序如何应用

  了解了上述理论后,我们就可以动手写驱动程序,如果你基本功好,而且写过linux下的硬件驱动,USB的硬件驱动和pci_driver很类似,那么写USB的驱动就比较简单了,如果你只是大体了解了linux的硬件驱动,那也不要紧,因为在linux的内核源码中有一个框架程序可以拿来借用一下,这个框架程序在/usr/src/~(你的内核版本,以下同)/drivers/usb下,文件名为usb-skeleton.c。写一个USB的驱动程序最基本的要做四件事:驱动程序要支持的设备、注册USB驱动程序、探测和断开、提交和控制urb(USB请求块)(当然也可以不用urb来传输数据,下文我们会说到)。

  驱动程序支持的设备:有一个结构体struct usb_device_id,这个结构体提供了一列不同类型的该驱动程序支持的USB设备,对于一个只控制一个特定的USB设备的驱动程序来说,struct usb_device_id表被定义为:

  /* 驱动程序支持的设备列表 */

  static struct usb_device_id skel_table [] = {

  ?????? { USB_DEVICE(USB_SKEL_VEN DOR_ID, USB_SKEL_PRODUCT_ID) },

  ?????? { }?????????????????????????????? /* 终止入口 */

  };

  ??????? MODULE_DEVICE_TABLE (usb, skel_table);

  对于PC驱动程序,MODULE_DEVICE_TABLE是必需的,而且usb必需为该宏的第一个值,而USB_SKEL_VENDOR_ID和USB_SKEL_PRODUCT_ID就是这个特殊设备的制造商和产品的ID了,我们在程序中把定义的值改为我们这款USB的,如:

  /* 定义制造商和产品的ID号 */

  #define USB_SKEL_VENDOR_ID?????? 0x1234

  #define USB_SKEL_PRODUCT_ID???? 0x2345

  这两个值可以通过命令lsusb,当然你得先把USB设备先插到主机上了。或者查看厂商的USB设备的手册也能得到,在我机器上运行lsusb是这样的结果:

  Bus 004 Device 001: ID 0000:0000?

  Bus 003 Device 002: ID 1234:2345? Abc? Corp.

  Bus 002 Device 001: ID 0000:0000?

  Bus 001 Device 001: ID 0000:0000

  得到这两个值后把它定义到程序里就可以了。

  注册USB驱动程序:所有的USB驱动程序都必须创建的结构体是struct usb_driver。这个结构体必须由USB驱动程序来填写,包括许多回调函数和变量,它们向USB核心代码描述USB驱动程序。创建一个有效的struct usb_driver结构体,只须要初始化五个字段就可以了,在框架程序中是这样的:

  static struct usb_driver skel_driver = {

  ?????? .owner = THIS_MODULE,

  ?????? .name =????????? "skeleton",

  ?????? .probe =? skel_probe,

  ?????? .disconnect =? skel_disconnect,

  ?????? .id_table =????? skel_table,

  };

  ??????? struct module *owner :指向该驱动程序的模块所有者的批针。USB核心使用它来正确地对该USB驱动程序进行引用计数,使它不会在不合适的时刻被卸载掉,这个变量应该被设置为THIS_MODULE宏。

  ??????? const char *name:指向驱动程序名字的指针,在内核的所有USB驱动程序中它必须是唯一的,通常被设置为和驱动程序模块名相同的名字。

  ??????? int (*probe) (struct usb_interface *intf,const struct usb_device_id *id):这个是指向USB驱动程序中的探测函数的指针。当USB核心认为它有一个接口(usb_interface)可以由该驱动程序处理时,这个函数被调用。

  ??????? void (disconnect)(struct usb_interface *intf):指向USB驱动程序中的断开函数的指针,当一个USB接口(usb_interface)被从系统中移除或者驱动程序正在从USB核心中卸载时,USB核心将调用这个函数。

  ??????? const struct usb_device_id *id_table:指向ID设备表的指针,这个表包含了一列该驱动程序可以支持的USB设备,如果没有设置这个变量,USB驱动程序中的探测回调函数就不会被调用。

  在这个结构体中还有其它的几个回调函数不是很常用,这里就不一一说明了。以struct usb_driver 指针为参数的usb_register_driver函数调用把struct usb_driver注册到USB核心。一般是在USB驱动程序的模块初始化代码中完成这个工作的:

  static int __init usb_skel_init(void)

  {

  ?????? int result;

  ?

  ?????? /* 驱动程序注册到USB子系统中*/

  ?????? result = usb_register(&skel_driver);

  ?????? if (result)

  ????????????? err("usb_register failed. Error number %d", result);

  ?

  ?????? return result;

  }


?? ?? ??


打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮

1.扫描左侧二维码
2.点击右上角的分享按钮
3.选择分享给朋友
?? ??

USB? 原理? 驱动?

相关文章

我来评论
美国的游客
美国的游客 ??? (您将以游客身份发表,请登录 | 注册)
?
有问题请反馈