《嵌入式设备驱动程序基础笔记》第25期

《嵌入式设备驱动程序基础笔记》第25期接着上期讲驱动程序支持哪些设备?struct usb_device_id 结构提供了此驱动程序支持的不同类型的usb设备的列表。USB核心使用

大家好,欢迎来到IT知识分享网。
《嵌入式设备驱动程序基础笔记》第25期"

接着上期讲

驱动程序支持哪些设备?

struct usb_device_id 结构提供了此驱动程序支持的不同类型的usb设备的列表。USB核心使用此列表决定将设备提供给哪个驱动程序,热插拔脚本使用此列表决定在将特定设备插入系统时自动加载哪个驱动程序。

struct usb_device_id 结构由以下字段定义:

match_flags 确定应与设备匹配的结构中的以下哪些字段 idVendor 设备的USB供应商ID idProduct 设备的USB产品ID

有许多宏用于初始化此结构:

  • USB_DEVICE(vendor, product):创建一个struct usb_device_id ,该id只能用于匹配指定的供应商和产品id值。这是非常常用的USB设备,需要一个特定的驱动程序。
  • USB_DEVICE_VER(vendor, product, lo, hi) : 创建一个struct usb_device_id ,可用于在版本范围内仅匹配指定的供应商和产品id值。
  • USB_DEVICE_INFO(class, subclass, protocol):创建可用于匹配特定类别usb设备的结构usb_device_id
  • USB_INTERFACE_INFO(class, subclass, protocol):创建可用于匹配特定usb接口类的结构usb_device_id

因此,对于仅控制单个供应商的单个USB设备的简单USB设备驱动程序,struct usb_device_id 表将定义为:

static struct usb_device_id skel_table [ ] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, { } /* Terminating entry */ };

注册USB驱动程序

所有USB驱动程序必须创建的主要结构是struct usb_driver驱动程序。此结构必须由USB驱动程序填写,并由许多函数回调和变量组成,这些变量将USB驱动程序描述为USB核心代码:

1,struct module *owner 指向此驱动程序的模块所有者的指针。USB核心使用它来正确引用这个USB驱动程序,这样它就不会在不合适的时候被卸载。该变量应设置为THIS_MODULE 宏。

2,const char *name 指向驱动程序名称的指针。它在内核中的所有USB驱动程序中必须是唯一的,并且通常设置为与驱动程序的模块名相同的名称。当驱动程序在内核中时,它显示在/sys/bus/usb/drivers/下的sysfs中。

3,const struct usb_device_id *id_table 指向struct usb_device_id 表的指针,该表包含此驱动程序可以接受的所有不同类型的usb设备的列表。如果未设置此变量,则永远不会调用USB驱动程序中的探测函数(probe)回调。如果希望系统中的每个USB设备始终调用驱动程序,请创建一个仅设置驱动程序信息字段的条目:

static struct usb_device_id usb_ids[ ] = { {.driver_info = 42}, { } };

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

指向USB驱动程序中探测函数的指针。这个函数是由USB核心调用的,当它认为它有一个struct usb_interface 接口,这个驱动程序可以处理。一个指向结构struct usb_device_id的指针,usb核心用来做这个决定,这个指针也被传递给这个函数。如果USB驱动程序声明传递给它的struct usb_interface接口,它应该正确初始化设备并返回0。如果驱动程序不想声明设备,或者发生错误,它应该返回负的错误值。

当安装了USB核心认为该驱动程序应该处理的设备时,将调用probe函数probe函数应该检查传递给它的关于该设备的信息,并确定驱动程序是否真的适合该设备。当驱动程序由于某种原因不再控制设备并且可以进行清理时,将调用disconnect函数。

5,void (*disconnect) (struct usb_interface *intf)

指向USB驱动程序中断开连接功能的指针。当struct usb_interface接口已从系统中移除或驱动程序正在从USB core卸载时,USB core将调用此函数

注册:

使用函数 usb_register_driver 将struct usb_driver序注册到usb core

备注:我们使用的是usb_register 去注册(此函数就会调用usb_register_driver

怎么写USB设备驱动程序?

总体步骤:

1. 分配/设置usb_driver结构体

  • .id_table
  • .probe
  • .disconnect

2. 注册usb_driver

3,进行相关操作(在probe函数中进行)

  • (1)分配一个input_dev结构体
  • (2)设置能产生哪类事件及产生这类事件中具体哪一种
  • (3)设置数据长度,数据源和目的
  • (4)分配一个usb_buffer
  • (5)分配一个usb_urb
  • (6)填充一个usb_urb
  • (7)提交usb_urb

驱动程序源码

#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> #include <linux/module.h> #include <linux/kmod.h> #include <linux/init.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/workqueue.h> #include <linux/mii.h> #include <linux/usb.h> #include <linux/crc32.h> static struct input_dev *usb_mouse_dev; static char *usb_mouse_buf; static dma_addr_t usb_mouse_dma_phy; static int buf_length; static struct urb *usb_mouse_urb; //函数声明 static void display_information(struct usb_device *dev ); static void usb_mouse_irq(struct urb *urb); static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) { //printk("doubixiaohanhan usb_mouse_probe "); struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; int pipe; display_information(dev); usb_mouse_dev = input_allocate_device();//分配input_dev 结构体 set_bit(EV_KEY,usb_mouse_dev->evbit); set_bit(EV_REP,usb_mouse_dev->evbit); set_bit(KEY_L,usb_mouse_dev->keybit); set_bit(KEY_S,usb_mouse_dev->keybit); set_bit(KEY_ENTER,usb_mouse_dev->keybit); input_register_device(usb_mouse_dev);//注册 //硬件操作 interface = intf->cur_altsetting; if (interface->desc.bNumEndpoints != 1) return -ENODEV; endpoint = &interface->endpoint[0].desc; if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);//源 buf_length = endpoint->wMaxPacketSize;//长度 usb_mouse_buf = usb_buffer_alloc(dev, buf_length, GFP_ATOMIC, &usb_mouse_dma_phy);//目的 //分配URB usb_mouse_urb = usb_alloc_urb(0, GFP_KERNEL); //initialize a interrupt urb usb_fill_int_urb(usb_mouse_urb, dev, pipe, usb_mouse_buf,buf_length, usb_mouse_irq, NULL, endpoint->bInterval); usb_mouse_urb->transfer_dma = usb_mouse_dma_phy; usb_mouse_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_submit_urb (usb_mouse_urb, GFP_ATOMIC); return 0; } static void usb_mouse_irq(struct urb *urb) { int i; static unsigned char pre_val; static int count = 0; printk("data count %d: ",count); for(i = 0;i < buf_length;i ++) { printk("%02x: ",usb_mouse_buf[i]); } printk("\n"); if((pre_val & (1 << 0) ) != ( (usb_mouse_buf[0]) & (1 << 0))) { input_event(usb_mouse_dev,EV_KEY,KEY_L,( (usb_mouse_buf[0]) & (1 << 0)) ? 1:0 ); input_sync(usb_mouse_dev); } else if((pre_val & (1 << 1) ) != ( (usb_mouse_buf[0]) & (1 << 1))) { input_event(usb_mouse_dev,EV_KEY,KEY_S,( (usb_mouse_buf[0]) & (1 << 1)) ? 1:0 ); input_sync(usb_mouse_dev); } else if((pre_val & (1 << 2) ) != ( (usb_mouse_buf[0]) & (1 << 2))) { input_event(usb_mouse_dev,EV_KEY,KEY_ENTER,( (usb_mouse_buf[0]) & (1 << 2)) ? 1:0 ); input_sync(usb_mouse_dev); } else; pre_val = usb_mouse_buf[0]; usb_submit_urb (usb_mouse_urb, GFP_ATOMIC); } static void usb_mouse_disconnect(struct usb_interface *intf) { struct usb_device *dev = interface_to_usbdev(intf); usb_kill_urb(usb_mouse_urb); usb_free_urb(usb_mouse_urb); usb_buffer_free(dev, buf_length, usb_mouse_buf, usb_mouse_dma_phy); input_unregister_device(usb_mouse_dev); input_free_device(usb_mouse_dev); } static struct usb_device_id usb_mouse_id_table [] = { { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, USB_INTERFACE_PROTOCOL_MOUSE) }, { } /* Terminating entry */ }; static struct usb_driver usb_mouse_driver = { .name = "usbmouse", .probe = usb_mouse_probe, .disconnect = usb_mouse_disconnect, .id_table = usb_mouse_id_table, }; static int usb_driver_init(void) { int retval = usb_register(&usb_mouse_driver); if (retval == 0) printk("usb driver device register successful"); return retval; } static void usb_driver_exit(void) { usb_deregister(&usb_mouse_driver); } static void display_information(struct usb_device *dev ) { printk(" bcdUSB = %x\n ",dev->descriptor.bcdUSB); printk(" idVendor = %x\n ",dev->descriptor.idVendor); printk(" idProduct = %x\n ",dev->descriptor.idProduct); printk(" iManufacturer = %x\n ",dev->descriptor.iManufacturer); printk(" iProduct = %x\n ",dev->descriptor.iProduct); printk(" iSerialNumber = %x\n ",dev->descriptor.iSerialNumber); } module_init(usb_driver_init); module_exit(usb_driver_exit); MODULE_LICENSE("GPL"); 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/57981.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信