USB设备驱动之鼠标

news/2024/11/7 10:48:22/

USB设备驱动之鼠标

1.  概述

     USB鼠标驱动程序大致分为两大部分:USB设备驱动部分和输入设备驱动部分,USB设备驱动只起了挂接总线和传输数据的作用,而具体的设备类型的驱动仍然是工作的主体。

     USB设备驱动部分:负责注册USB设备驱动,实现probe和disconnect函数,初始化驱动支持的USB鼠标设备类型表(id_table);初始化和提交URB;根据HID规范,鼠标只有一个端点(不包括端点0),且属于中断传输类型。

     输入设备驱动部分:负责注册输入设备和该设备所支持的事件类型;向输入核心层上报鼠标事件。

     这里有一个概念需要注意,这里的中断传输与硬件中断那个中断是不一样的,这个中断传输实际是靠USB hostcontrol轮询usb device来实现的,而USBhost control对于CPU则是基于中断的机制。拿USB鼠标为例,USB host control对USB鼠标不断请求,这个请求的间隔是很短的,端点描述符中的bInterval域中指定的,当鼠标发生过了事件之后,鼠标会发送数据回host,这时USB host control中断通知CPU,于是usb_mouse_irq被调用,在usb_mouse_irq里,就可以读取鼠标发回来的数据,当读完之后,驱动再次调用usb_submit_urb发出请求,就这么一直重复下去,一个usb鼠标的驱动也就完成了。

     我们在进行硬件访问的时候,只需调用URB相关的接口,而不需要关心底层USB主机控制器的具体细节,因此,USB设备也变得与平台无关,同样的驱动可应用于不同的SOC。

2.代码分析

#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>/* for apple IDs */
#ifdef CONFIG_USB_HID_MODULE
#include "../hid-ids.h"
#endif/** Version Information*/
#define DRIVER_VERSION "v1.6"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
#define DRIVER_LICENSE "GPL"MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);/*  */
struct usb_mouse {char name[128];char phys[64];struct usb_device *usbdev;struct input_dev *dev;struct urb *irq;signed char *data;dma_addr_t data_dma;
};static void usb_mouse_irq(struct urb *urb)
{struct usb_mouse *mouse = urb->context; /* context 指向USB驱动 程序分 配 的 数据 块*/signed char *data = mouse->data;struct input_dev *dev = mouse->dev;int status;/* 判断传输是否成功 */switch (urb->status) {case 0:			/* success */break;case -ECONNRESET:	/* unlink */case -ENOENT:case -ESHUTDOWN:return;/* -EPIPE:  should clear the halt */default:		/* error */goto resubmit;}/* 上报事件 */input_report_key(dev, BTN_LEFT,   data[0] & 0x01);input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);input_report_key(dev, BTN_SIDE,   data[0] & 0x08);input_report_key(dev, BTN_EXTRA,  data[0] & 0x10);input_report_rel(dev, REL_X,     data[1]);input_report_rel(dev, REL_Y,     data[2]);input_report_rel(dev, REL_WHEEL, data[3]);input_sync(dev);/* 提交下次传输 */
resubmit:status = usb_submit_urb (urb, GFP_ATOMIC);if (status)err ("can't resubmit intr, %s-%s/input0, status %d",mouse->usbdev->bus->bus_name,mouse->usbdev->devpath, status);
}static int usb_mouse_open(struct input_dev *dev)
{struct usb_mouse *mouse = input_get_drvdata(dev);mouse->irq->dev = mouse->usbdev;/* 向USB核心层提交URB */if (usb_submit_urb(mouse->irq, GFP_KERNEL))return -EIO;return 0;
}static void usb_mouse_close(struct input_dev *dev)
{struct usb_mouse *mouse = input_get_drvdata(dev);usb_kill_urb(mouse->irq);
}/* USB设备与驱动匹配上时调用 */
static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{/* 设备描述 usb_device *//* 接口描述 usb_interface */struct usb_device *dev = interface_to_usbdev(intf); /* 接口设置描述 */struct usb_host_interface *interface;/* 端点描述符 */struct usb_endpoint_descriptor *endpoint;struct usb_mouse *mouse;struct input_dev *input_dev;int pipe, maxp;int error = -ENOMEM;/* 获取当前接口设置 */interface = intf->cur_altsetting;/* 根据HID规范,鼠标只有一个端点(不包含0号控制端点)*/if (interface->desc.bNumEndpoints != 1)return -ENODEV;/* 获取端点0描述符 */endpoint = &interface->endpoint[0].desc;/* 根据HID规范,鼠标唯一的端点应为中断端点 */if (!usb_endpoint_is_int_in(endpoint))return -ENODEV;/* 生成中断管道 */pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);/* 返回该端点能够传输的最大的包长度,鼠标的返回的最大数据包为4个字节。*/  maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));/* 创建input设备 */mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);input_dev = input_allocate_device();if (!mouse || !input_dev)goto fail1;/* 申请内存空间用于数据传输,data 为指向该空间的地址*/mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);if (!mouse->data)goto fail1;/* 分配URB */mouse->irq = usb_alloc_urb(0, GFP_KERNEL);if (!mouse->irq)goto fail2;mouse->usbdev = dev;mouse->dev = input_dev;if (dev->manufacturer)strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));if (dev->product) {if (dev->manufacturer)strlcat(mouse->name, " ", sizeof(mouse->name));strlcat(mouse->name, dev->product, sizeof(mouse->name));}if (!strlen(mouse->name))snprintf(mouse->name, sizeof(mouse->name),"USB HIDBP Mouse %04x:%04x",le16_to_cpu(dev->descriptor.idVendor),le16_to_cpu(dev->descriptor.idProduct));usb_make_path(dev, mouse->phys, sizeof(mouse->phys));strlcat(mouse->phys, "/input0", sizeof(mouse->phys));/* 设置输入设备的相关属性 */input_dev->name = mouse->name;input_dev->phys = mouse->phys;usb_to_input_id(dev, &input_dev->id);input_dev->dev.parent = &intf->dev;/* 设置输入设备支持的事件和事件代码 */input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |BIT_MASK(BTN_EXTRA);input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);input_set_drvdata(input_dev, mouse);input_dev->open = usb_mouse_open;input_dev->close = usb_mouse_close;/* 初始化中断URB */usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,(maxp > 8 ? 8 : maxp),usb_mouse_irq, mouse, endpoint->bInterval);mouse->irq->transfer_dma = mouse->data_dma;mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;/* 向输入核心层注册输入设备 */error = input_register_device(mouse->dev);if (error)goto fail3;usb_set_intfdata(intf, mouse);return 0;fail3:	usb_free_urb(mouse->irq);
fail2:	usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
fail1:	input_free_device(input_dev);kfree(mouse);return error;
}/* USB设备移除时调用 */
static void usb_mouse_disconnect(struct usb_interface *intf)
{struct usb_mouse *mouse = usb_get_intfdata (intf);usb_set_intfdata(intf, NULL);if (mouse) {usb_kill_urb(mouse->irq);input_unregister_device(mouse->dev);usb_free_urb(mouse->irq);usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);kfree(mouse);}
}/* USB驱动支持的鼠标类型表 */
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);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 __init usb_mouse_init(void)
{/* 注册鼠标驱动程序 */int retval = usb_register(&usb_mouse_driver);if (retval == 0)printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"DRIVER_DESC "\n");return retval;
}static void __exit usb_mouse_exit(void)
{usb_deregister(&usb_mouse_driver);
}module_init(usb_mouse_init);
module_exit(usb_mouse_exit);





http://www.ppmy.cn/news/211211.html

相关文章

usb键鼠驱动分析

一、鼠标 linux下的usb鼠标驱动在/drivers/hid/usbhid/usbmouse.c中实现 1.加载初始化过程 1.1模块入口 module_init(usb_mouse_init); 1.2初始化函数 static int __init usb_mouse_init(void) //初始化{int retval usb_register(&usb_mouse_driver); //注册usb鼠标…

USB鼠标设备驱动程序简单实现(一)

一、Linux下的USB驱动程序 分离和分层是Linux下驱动程序开发采用的最基本的形式&#xff0c;USB驱动开发在主机端主要涉及两个部分&#xff1a;主机控制器驱动和设备驱动。 主机控制器驱动主要是和具体的Soc相关的&#xff0c;它来识别USB设备&#xff0c;安装对应的设备驱动…

USB鼠标驱动

仿照drivers/hid/usbhid/usbmouse.c系统自带的USB鼠标驱动实现的USB鼠标驱动。 一、usb/usbmouse_as_key.c #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/init.h> #include <linux/usb/input.h…

编写USB鼠标驱动程序,并测试

转载自&#xff1a;https://www.cnblogs.com/lxl-lennie/p/10189188.html 8.1 编写USB鼠标驱动程序&#xff0c;并测试 学习目标&#xff1a;编写USB鼠标驱动程序&#xff0c;并测试&#xff08;将USB鼠标的左键当作L按键,将USB鼠标的右键当作S按键,中键当作回车按键&#x…

USB鼠标驱动开发流程

USB驱动开发&#xff0c;针对某一个USB设备的某个功能&#xff08;接口&#xff09;构建的驱动程序。USB驱动并不直接和USB设备进行数据交互&#xff0c;而是通过USB总线驱动程序&#xff08;USB Core和USB HCD&#xff09;来操作USB设备的。一般构建USB设备驱动的流程为&#…

USB驱动之Android usb鼠标驱动

1. 前言 HID是Human Interface Devices的缩写&#xff0c;翻译成中文即为人机交互设备。这里的人机交互设备是一个宏观上面的概念&#xff0c;任何设备只要符合HID spec都可以称之为HID设备&#xff0c;常见的HID设备有鼠标键盘&#xff0c;游戏操纵杆等等。 usb鼠标在android代…

编写USB鼠标驱动程序

编写USB鼠标驱动程序 文章目录 编写USB鼠标驱动程序参考资料&#xff1a;1. 目标2. 编程2.1 驱动框架2.2 实现usb_driver2.2.1 id_table2.2.2 probe函数 2.3 实现输入设备2.4 实现数据传输 3. 上机实验 致谢 参考资料&#xff1a; Linux内核源码&#xff1a;include\linux\usb.…

usb鼠标驱动(一)

Linux USB 鼠标驱动程序详解 注册一个usb driver&#xff0c;这个drvier不是usb设备driver&#xff0c;而是接口driver。 /* use a define to avoid include chaining to get THIS_MODULE & friends */ #define usb_register(driver) \usb_register_driver(driver, THIS_M…