5.USB驱动--三:USB设备驱动程序框架

USB 总线驱动程序,在接入 USB 设备时,会帮我们构造一个新的 usb_dev 注册到“usb_bus_type”里去。这部分是内核做好的。我们要做的是,构造一个 usb_driver (驱动)结构体,注册到“usb_bus_type”中去。
在“usb_driver”结构体中有“id_table”表示他能支持哪些设备,当 USB 设备能匹配 id_table 中某一个设备时,就会调用“usb_driver”结构体中的“.probe”(自已确定在 probe 中做的事情)等函数,如当拔掉USB 设备时,就会调用其中的“.disconnect”函数。
usb_bus_type”USB 总线驱动设备模型只是提供了这一种框架而已。在".probe"函数里面,注册“字符设备”也好,注册个“input_dev”结构体也好,再或注册一个块设备也好。再或只是加了句打印也好,都可以由自已确定。

怎么写 USB 设备驱动程序?

  1. 分配/设置 usb_driver 结构体
    .name :usb_driver :驱动结构体名字
    .id_table :表示能支持的设备
    .probe :表示“USB 总线驱动程序”发现一个新设备后,就会与 usb_driver 结构体比较,若 id_table 表示能支持它,就调用.probe 函数。
    .disconnect :拔掉 USB 设备时调用这个函数。
  2. 注册
    usb_register(&usb_driver );
    例:
    /*12.usb设备驱动框架*/

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>

static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	printf("ni hao wo shi yi ge shubiao!!!\n");
	return 0;
}

static int usb_mouse_disconnect(struct usb_interface *intf)
{
	printf("bye bye123!!!\n");
}

static struct usb_device_id usb_mouse_id_table [] = {
	{USB_INTERFACE_INFO(                  //接口描述符信息
		USB_INTERFACE_CLASS_HID,           //接口类:HID类
		USB_INTERFACE_SUBCLASS_BOOT,        //子类:启动设备类
		USB_INTERFACE_PROTOCOL_MOUSE)},      //协议:鼠标协议
};     //意思是:要匹配“接口描述符”里的,接口类,子类,协议是否一致


static struct usb_driver usb_mouse = {
	.name       = "usb_mouse",
	.probe      =usb_mouse_probe,
	.disconnect = usb_mouse_disconnect,
	.id_table   = usb_mouse_id_table,
	};

static int usb_mouse_init(void)
{
	usb_register(&usb_mouse);
	return 0;
}

static void usb_mouse_exit(void)
{
	usb_deregister(&usb_mouse);
}

module_init(usb_mouse_init);
module_exit(usb_mouse_exit);
MODULE_LICENSE("GPL");

*一:id_table

static struct usb_device_id usb_mouse_id_table [] = {
	{USB_INTERFACE_INFO(                  //接口描述符信息
		USB_INTERFACE_CLASS_HID,           //接口类:HID类
		USB_INTERFACE_SUBCLASS_BOOT,        //子类:启动设备类
		USB_INTERFACE_PROTOCOL_MOUSE)},      //协议:鼠标协议
};     //意思是:要匹配“接口描述符”里的,接口类,子类,协议是否一致

发现它是通过USB_INTERFACE_INFO()这个宏定义的.该宏如下所示:

#define USB_INTERFACE_INFO(cl,sc,pr) \
       .match_flags = USB_DEVICE_ID_MATCH_INT_INFO,  \    //设置id_table的.match_flags成员
      .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
                                                         //设置id_table的3个成员,用于与匹配USB设备的3个成员

“.match_flags”:表示要匹配“设备描述符”中的哪一项。(即接口描述符)
“USB_DEVICE_ID_MATCH_INT_INFO”:INT 是接口意思,INT_INFO 就是指接口的信息。接口的信息就在“接口描述
符”里。
“.bInterfaceClass”:只要“接口描述符”里的“类”是(cl)这个东西。
“.bInterfaceSubClass”:子类是 (sc) 这个东西。
“.bInterfaceProtocol”:协议是 (pr) 这个东西。
只要这个 USB 设备里的“接口描述符”里面的“类”是“HID”类;“子类”是“BOOT”;
“协议”是“MOUSE”,那么这个 id_table 就能支持。

若是想支持“某一款”设备,即“厂家 ID”-VID,“设备 ID”-PID 这种情况:则可以这样写:

static struct usb_device_id usb_mouse_id_table [] = {
	{USB_INTERFACE_INFO(                  //接口描述符信息
		USB_INTERFACE_CLASS_HID,           //接口类:HID类
		USB_INTERFACE_SUBCLASS_BOOT,        //子类:启动设备类
		USB_INTERFACE_PROTOCOL_MOUSE)},      //协议:鼠标协议
	{USB_DEVICE(0x12d1,0x1001)},    //设备的 VID 是“0x12d1”,PID 是“0x1001”,
};     

二:probe 函数
Usb_driver" 结构体是支持 某个 “usb_interface”结构体的某个接口。
一个 USB 硬件可能有多个逻辑上的设备,这些逻辑上的设备就是用“usb_interface”结构表示的。如一块“声卡”有“录音”和“播放”两个“逻辑接口”,则要两个驱动程序。
先暂时什么也不做,只printk打印输出一下。

三:disconnect函数
拔掉 USB 设备时调用这个函数,只printk打印输出一下。

四:测试

make menuconfig 去掉原来的 USB 鼠标驱动,不然一接 USB 鼠标内核会找到原来的驱动。新注册上的驱动还轮不上使用。
-> Device Drivers
-> HID Devices
<> USB Human Interface Device (full HID) support 此项不选中先不要内核中的驱动。
使用新内核启动
1.简单测试
在开发板上接入、拔出 USB 鼠标查看是否有打印输出信息。
1
二.在 probe 函数中打印 厂家 ID 和 设备 ID:
VID 和 PID 都是在 USB“设备描述符”中的。当接入一个 USB 设备后,USB 总线驱动程序已经把这些“设备描述符”全部读了出来。直接使用即可。
1.得到“usb_device”(USB 设备)结构体

 struct usb_device *dev=interface_to_usbdev(intf);  

通过usb_ interface接口获取usb_device设备,为后面设置USB数据传输用
2.获取厂家 ID 和 设备 ID
获取厂家 ID 和 设备 ID,在USB设备描述符(usb_device_descriptor )结构体内,而USB设备描述符位于USB设备结构体usb_device中的成员descriptor中。

static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	
	printk("bcdUSB = %x\n", dev->descriptor.bcdUSB);
	printk("VID    = 0x%x\n", dev->descriptor.idVendor);
	printk("PID    = 0x%x\n", dev->descriptor.idProduct);	
	return 0;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值