USB驱动----USB总线驱动程序
来源:互联网 发布:武术 知乎 编辑:程序博客网 时间:2024/03/28 17:21
usb总线驱动程序的作用
1. 识别设备
1.1 分配地址
1.2 并告诉USB设备(set address)
1.3 发出命令获取描述符
设备描述符的信息在 linux-2.6.22.6\include\linux\usb\Ch9.h
2 找到并安装对应的设备驱动
3 提供USB读写函数(不了解数据含义)
USB设备接到开发板上,看输出信息:
接上:
usb 1-1: new full speed USB device using s3c2410-ohci and address 2usb 1-1: configuration #1 chosen from 1 choice
断开:
usb 1-1: USB disconnect, address 2
再接上
usb 1-1: new full speed USB device using s3c2410-ohci and address 3usb 1-1: configuration #1 chosen from 1 choice
在内核目录(/work/system/linux-2.6.22.6/drivers)搜索
grep “USB device using ” * -nR
结果:
usb/core/hub.c:2186: "%s %s speed %sUSB device using %s and address %d\n",
通过hub.c的2186行 ,可以一步步找到总线驱动的编程思路:
hub_irq kick_khubd hub_thread hub_events hub_port_connect_change udev = usb_alloc_dev(hdev, hdev->bus, port1); dev->dev.bus = &usb_bus_type; //看结构图004 choose_address(udev) //选择地址,也就是给新的设备分配编号(地址) hub_port_init //打印usb 1-1: new full speed USB device using s3c2410-ohci and address 2 hub_set_address //把地址告诉USB设备 usb_get_device_descriptor(udev, 8 )// 获得设备描述符,8字节的含义包括usb_device_descriptor前八个描述 retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);//再次获得设备描述符 usb_new_device(udev) //新建一个USB设备 err - usb_get_configuration(udev);//把所有的描述符都读出来 usb_parse_configuration //解析 device_add//把device放入 usb_bus_type的dev链表, //从usb_bus_type的driver链表里取出usb _driver //把usb_interface和driver的id_tabe比较 //如果能匹配,调用usb _driver的probe
整体思路:
usb_bus_type / -------------\ usb_new_device(udev) usb_register / \ usb_interface usb _driver id_tabe probe
说明:
给新设备分配地址
static void choose_address(struct usb_device *udev){ int devnum; struct usb_bus *bus = udev->bus; /* If khubd ever becomes multithreaded, this will need a lock */ /* Try to allocate the next devnum beginning at bus->devnum_next. */ devnum = find_next_zero_bit(bus->devmap.devicemap, 128, bus->devnum_next); //找下一个零位,一直找到第128个,插入USB设备分配地址2,下一个分配地址3... if (devnum >= 128) devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);//如果大于128,从头开始 bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1); if (devnum < 128) { set_bit(devnum, bus->devmap.devicemap); udev->devnum = devnum; }}
新建一个usb驱动
int usb_new_device(struct usb_device *udev){ int err; /* Determine quirks */ usb_detect_quirks(udev); err = usb_get_configuration(udev);//获得它的配置 if (err < 0) { dev_err(&udev->dev, "can't read configurations, error %d\n", err); goto fail; }
接口描述符
struct usb_interface_descriptor { __u8 bLength;//设备描述符的字节数大小,为0x12 __u8 bDescriptorType;//描述符类型编号,为0x01 __u8 bInterfaceNumber;//接口的编号 __u8 bAlternateSetting;//备用的接口描述符编号 __u8 bNumEndpoints;//该接口使用端点数,不包括端点0 __u8 bInterfaceClass;//接口类型 __u8 bInterfaceSubClass;//接口子类型 __u8 bInterfaceProtocol;//接口所遵循的协议 __u8 iInterface;//描述该接口的字符串索引值 } __attribute__ ((packed));
怎样写usb设备驱动程序?
①分配/设置 USB_driver结构体
.id_tabe //支持哪些设备
.probe
.disconnect
②注册
现在使用USB鼠标用作按键 ,写一个简单usb框架:
左 :L 右:S 中:回车
① 分配input_dev
② 设置
③ 注册
④ 硬件操作
这4步在 probe 实现。
先参考内核中的usbmouse.c(drivers\hid\usbhid\usbmouse.c)
#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 usbmouse_as_key_init(void){ /* 注册 */ usb_register(&usbmouse_as_key_driver); return 0;}static void usbmouse_as_key_exit(void){ /* 注销 */ usb_deregister(&usbmouse_as_key_driver); }module_init(usbmouse_as_key_init);module_exit(usbmouse_as_key_exit);
第二部:
/* 分配/设置usb_driver */static struct usb_driver usbmouse_as_key_driver = { .name = "usbmouse_as_key_", //设备名称 .probe = usbmouse_as_key_probe, .disconnect = usbmouse_as_key_disconnect, .id_table = usbmouse_as_key_id_table,//支持的设备};
然后填充:
static struct usb_device_id usbmouse_as_key_id_table [] = { { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, USB_INTERFACE_PROTOCOL_MOUSE) }, /*支持某一款USB_DEVICE,在usb.h中的USB_DEVICE(vend,prod)*/ //{USB_DEVICE(0x1234,0x5678)}, { } /* Terminating entry */ };
static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id){ printk("found usbmouse!\n"); return 0;}
static void usbmouse_as_key_disconnect(struct usb_interface *intf){ printk("disconnect usbmouse!\n");}
分析:
①
.id_table = usbmouse_as_key_id_table,//支持的设备
②
在usbmouse.c函数中去usb_mouse_id_table的定义
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 */};
去宏 USB_INTERFACE_INFO
#define USB_INTERFACE_INFO(cl,sc,pr) \ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \ .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)/* match_flags匹配设备描述符的哪一项,INT_INFO是接口信息,cl是类,sc是子类,pr是协议。 所以,usb_mouse_id_table中,只要接口设备描述符的类是HID,子类是BOOT,协议是MOUSE 就可以支持*/
这样就实现了一个usb驱动的框架构建。
测试:
1.make menuconfig 去掉原来的usb鼠标驱动
(cd /work/system/linux-2.6.22.6)
①
②
③
④
2.make uImage 并使用新的内核启动
3.cp arch/arm/boot/uImage /work/nfs_root/uImage_nohid
4.编译USB驱动程序,拷贝到/work/nfs_root/first_fs
5.使用新的uImage启动开发板
nfs 30000000 192.168.1.102:/work/nfs_root/uImage_nohid
bootm 30000000
mount -t nfs -o nolock,vers=2 192.168.1.102:/work/nfs_root/first_fs /mnt
cd /mnt
开发板,安装驱动 insmod usbmouse_as_key.ko
插拔鼠标可以看到如下结果:
参考usbmouse.c的usb_mouse_probe,通过usb_interface(设备接口)找到
struct usb_device *dev = interface_to_usbdev(intf);
查看usb_device结构体的设备描述符
struct usb_device_descriptor { __u8 bLength;//设备描述符的字节数大小,为0x12 __u8 bDescriptorType;//描述符类型编号,为0x01 __le16 bcdUSB;//USB版本号 __u8 bDeviceClass;//USB分配的设备类代码,0x01~0xfe为标准设备类,0xff为厂商自定义类型 //0x00不是在设备描述符中定义的,如HID __u8 bDeviceSubClass;//usb分配的子类代码,同上,值由USB规定和分配的 __u8 bDeviceProtocol;//USB分配的设备协议代码,同上 __u8 bMaxPacketSize0;//端点0的最大包的大小 __le16 idVendor;//厂商编号 __le16 idProduct;//产品编号 __le16 bcdDevice;//设备出厂编号 __u8 iManufacturer;//描述厂商字符串的索引 __u8 iProduct;//描述产品字符串的索引 __u8 iSerialNumber;//描述设备序列号字符串的索引 __u8 bNumConfigurations;//可能的配置数量 } __attribute__ ((packed));
在usb驱动程序的 usbmouse_as_key_probe 添加如下
static int usbmouse_as_key_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);// dev->descriptor.bcdUSB,dev结构体里面的设备描述符 printk("VID = 0x%x\n", dev->descriptor.idVendor); printk("PID = 0x%x\n", dev->descriptor.idProduct);}
测试结果:
①
②
- USB驱动----USB总线驱动程序
- Linux驱动USB驱动程序-USB总线驱动程序
- 大话USB驱动之总线驱动程序
- USB总线驱动程序
- USB总线驱动程序
- USB驱动程序之USB总线驱动程序
- USB驱动--设备驱动程序
- USB驱动(一、概念介绍及USB总线驱动程序代码分析)
- Linux-USB驱动(1)-USB总线介绍
- USB驱动程序之USB总线驱动程序学习笔记
- USB驱动程序之USB总线驱动程序学习笔记
- Linux-USB驱动(5)-USB驱动程序设计
- Linux-USB总线驱动分析
- USB驱动程序之驱动框架
- 基于USB总线的无线网卡驱动程序
- usb 的总线驱动程序和usb设备驱动程序分析,usb interface and driver
- wince下USB总线驱动分析
- wince下USB总线驱动分析
- 阿里面试(二)
- Spring4和Hibernate4整合小结
- 索引
- linux 常用目录
- 更改Arcgis10.2布局视图标题
- USB驱动----USB总线驱动程序
- 指向常量的指针、常量指针傻傻分不清楚
- BEGAN: Boundary Equilibrium Generative Adversarial Networks阅读笔记
- C++面向对象(2)
- 大数据企业架构以及产生的相关热门职位
- char*、char[]及string的区别及相互转换
- Javascript概述
- 设计模式之组合模式
- Java实现加密与减密