s5pv210-Linux驱动之USB鼠标
来源:互联网 发布:nginx php 500错误 编辑:程序博客网 时间:2024/04/30 00:00
一、开发环境
硬件平台:我用的是TQ210核心板,板载S5PV210芯片,USB扩展接有FE1.1S芯片,是一个4端口的HUB
软件平台:开发板移植的是Linux3.10.46内核,UBOOT移植的是2014.12版本
二、资源简介
前几篇已经移植好了USB的主机控制器驱动,只要编写鼠标对应的驱动,注册到USB总线就可以了。
三、移植步骤
1、分配一个usb_driver结构体,如下
static struct usb_driver tq_usb_mouse_driver = { .name = "tq_usbmouse", .probe = tq_usb_mouse_probe, .disconnect = tq_usb_mouse_disconnect, .id_table = usb_mouse_id_table,};
2、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 */};MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);其中,USB_INTERFACE_INFO在include/linux/usb.h中定义,如下:
#define USB_INTERFACE_INFO(cl, sc, pr) \.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, \.bInterfaceClass = (cl), \.bInterfaceSubClass = (sc), \.bInterfaceProtocol = (pr)其中,USB_DEVICE_ID_MATCH_INT_INFO定义如下:
#define USB_DEVICE_ID_MATCH_INT_INFO \(USB_DEVICE_ID_MATCH_INT_CLASS | \USB_DEVICE_ID_MATCH_INT_SUBCLASS | \USB_DEVICE_ID_MATCH_INT_PROTOCOL)表示,需要完全匹这3项才可以
3、编写tq_usb_mouse_probe函数,当驱动和设备匹配成功以后,就会调用此函数:
static int tq_usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id){ int ret; int pipe, len; struct usb_device *dev = interface_to_usbdev(intf); struct usb_device_descriptor des = dev->descriptor; struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; ret = 0; printk("bcdDevice:%x \nidVender:%x \nidProduce:%x \niManufacturer:%d\n",des.bcdDevice,des.idVendor, des.idProduct,des.iManufacturer); interface = intf->cur_altsetting; // 终端描述符 endpoint = &interface->endpoint[0].desc; // 1. input 设备分配 tq_mouse_dev = input_allocate_device(); if(NULL == tq_mouse_dev){ printk("allocate input dev error.\n"); } tq_mouse_dev->name = "tqusbmouse"; set_bit(EV_KEY, tq_mouse_dev->evbit); set_bit(EV_REL, tq_mouse_dev->evbit); set_bit(BTN_LEFT, tq_mouse_dev->keybit); set_bit(BTN_RIGHT, tq_mouse_dev->keybit); set_bit(BTN_MIDDLE, tq_mouse_dev->keybit); set_bit(REL_X, tq_mouse_dev->relbit); set_bit(REL_Y, tq_mouse_dev->relbit); // 注册输入设备 ret = input_register_device(tq_mouse_dev); if(ret ) goto fail1; // 2. urb操作 // 2.1 为urb中数据缓冲区分配空间 data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &data_dma); if(NULL == data) goto fail2; // 2.2 设置管道,端点为数据流向地址,rcv为接收,int表示中断 pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); len = endpoint->wMaxPacketSize; printk("rcv data len is %d\n", len); // 2.3 为urb分配内存 urb = usb_alloc_urb(0, GFP_KERNEL); if(NULL == urb ) goto fail3; // 2.4 填充urb结构体 usb_fill_int_urb(urb, dev, pipe, data, len, report_mouse, dev, endpoint->bInterval); // dma方式传输数据 urb->transfer_dma = data_dma; urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; // 2.5 提交urb usb_submit_urb(urb, GFP_KERNEL); return 0;fail3: usb_free_urb(urb);fail2: usb_free_coherent(dev, 8, data, data_dma);fail1: input_free_device(tq_mouse_dev); input_unregister_device(tq_mouse_dev); return ret;}
些函数主要做了两件事:
注册一个input输入子系统,并设置为鼠标功能;
注册一个urb,并设置其需拟地址、DMA地址、传输长度等
当USB总线处理完成这个urb请求块时,会调用usb_fill_int_urb函数提供的回调函数report_mouse,定义如下:
void report_mouse(struct urb * urb){ // 上报数据 // 左键 input_report_key(tq_mouse_dev, BTN_LEFT, data[0] & 0x01); // 右键 input_report_key(tq_mouse_dev, BTN_LEFT, data[0] & 0x02); // 中键 input_report_key(tq_mouse_dev, BTN_LEFT, data[0] & 0x04); // 左右移动 input_report_rel(tq_mouse_dev, REL_X, data[1]); // 前后移动 input_report_rel(tq_mouse_dev, REL_Y, data[2]); // 同步信号 input_sync(tq_mouse_dev); // 再次提交urb,不可休眠 usb_submit_urb (urb, GFP_ATOMIC);}此函数会将鼠标的按键、位移信息上报系统输入子系统,然后再次提交urb请求块
5、编写tq_usb_mouse_disconnect函数,当拔出设备时就会调用此函数:
static void tq_usb_mouse_disconnect(struct usb_interface *intf){ usb_kill_urb(urb); usb_free_coherent(interface_to_usbdev(intf), 8, data, data_dma); usb_free_urb(urb); input_unregister_device(tq_mouse_dev); input_free_device(tq_mouse_dev); usb_set_intfdata(intf, NULL);}些函数就是释放一些内存等操作
四、编进内核
驱动可以作为模块加载,也可以和内核一起编译,步骤如下:
1、切换到目录drivers\usb中,把鼠标驱动文件拷贝到此目录
2、修改Kconfig,在config USB_COMMON后面添加
config USB_COMMON tristate default y depends on USB || USB_GADGETconfig TQ_USB_MOUSE bool "TQ210 usb mouse support" depends on USB || USB_GADGET ---help--- Say Y here if you wish to control a tq210 usb mouse.
3、修改Makefile,在最后一行添加obj-$(CONFIG_TQ_USB_MOUSE) += tqUsbMouse.o4、执行make menuconfig,将驱动文件编译进内核
[*] TQ210 usb mouse support5、重新编译内核,烧进开发板。
注:这种编进内核的方法,只是我试验的一种简单方法,不是很好,大家可以把驱动文件放在别的地方编译。
五、总结
USB鼠标驱动最终是通过输入子系统,向内核上报鼠标数据的,但是数据的来源是USB总线的urb请求块。注意匹配条件usb_mouse_id_table一定要编写正确,不然总线不会匹配到相应的设备,而且确保系统内没有其他驱动会匹配到设备,因为当USB设备插入系统时,USB总线采用查询的方式,当找到第一个匹配的驱动时,就不继续查找了。
- s5pv210-Linux驱动之USB鼠标
- s5pv210-Linux驱动之USB键盘
- Linux驱动之usb鼠标
- s5pv210-Linux驱动之USB-HOST主机控制器之EHCI
- s5pv210-Linux驱动之USB-HOST主机控制器之OHCI
- Linux-USB鼠标驱动
- s5pv210-Linux驱动之ME3760
- USB设备驱动之鼠标
- linux驱动之usb鼠标按键的读取
- s5pv210开发板linux系统检验USB鼠标是否能用?
- 嵌入式Linux 三星s5pv210 USB WIFI驱动的移植
- USB驱动--USB鼠标
- linux驱动-USB驱动程序之USB设备驱动程序2鼠标用作键盘
- Linux下USB模拟ps2鼠标驱动
- Linux USB鼠标驱动注解及测试
- Linux下USB鼠标驱动完全注释
- Linux USB 鼠标输入驱动详解
- s5pv210-Linux驱动之SD卡插拨识别
- JavaScript 隐式转换
- 1、JQuery——选择器
- C++ 对象模型--1小窥
- vue中关于computed的理解及其其他扩展
- 简述mybatis和hibernate的区别
- s5pv210-Linux驱动之USB鼠标
- 开始使用ABP.CORE模板 (ASP.NET Core with Angular)
- 【C++】多态机制的剖析!!!
- jpgraph
- jQuery遍历table并操作元素
- 在Android O上启动Service遇到问题记录
- 【转载保存】Ubuntu14.04安装pycharm用于Python开发环境部署,并且支持pycharm使用中文输入
- 123
- Python中reshape函数参数-1的意思