1 需要 禁用掉 CONFIG_USB_HID,不然下面的驱动不会被探测。
2 下面的驱动模块代码只打印了鼠标左键是否被按下,左键没有被按下打印0,左键被按下打印1.
3 参考了这里
4 内核版本 4.4.194.
5 处理流程:
irq = usb_alloc_urb(0, GFP_KERNEL);
usb_fill_int_urb(irq, usb_dev, pipe, buffer,
(maxp > 8 ? 8 : maxp),
usb_mouse_irq, NULL, endpoint.bInterval);
usb_submit_urb(irq,GFP_ATOMIC);
然后如果有鼠标事件,则执行:
static void usb_mouse_irq(struct urb *urb) {
pr_info("usb_mouse_irq \n");
pr_info("BTN_LEFT %x \n", (*buffer) & 0x01);
usb_submit_urb(urb,GFP_ATOMIC);
}
在 usb_mouse_irq 里面通过 :
usb_submit_urb(urb,GFP_ATOMIC);
会再次请求下一次的鼠标事件,
这样就会一直接受到鼠标事件了 。
后续可以在 usb_mouse_irq 函数里面把事件通过input子系统上报给上层。
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/usb/storage.h>
#include <scsi/scsi_proto.h>
#include <asm-generic/errno-base.h>
#include <uapi/asm-generic/errno.h>
#include <uapi/linux/cciss_defs.h>
#include <linux/usb/input.h>
#include <linux/hid.h>
/**
New USB device found, idVendor=093a, idProduct=2510
*
*/
#define USB_VENDOR_ID 0x093a
#define USB_PRODUCT_ID 0x2510
#define PRINT_USB_ENDPOINT_DESCRIPTOR( i ) \
{ \
pr_info("USB_INTERFACE_DESCRIPTOR:\n"); \
pr_info("-----------------------------\n"); \
pr_info("bLength: 0x%x\n", i.bLength); \
pr_info("bDescriptorType: 0x%x\n", i.bDescriptorType); \
pr_info("bInterfaceNumber: 0x%x\n", i.bInterfaceNumber); \
pr_info("bAlternateSetting: 0x%x\n", i.bAlternateSetting); \
pr_info("bNumEndpoints: 0x%x\n", i.bNumEndpoints); \
pr_info("bInterfaceClass: 0x%x\n", i.bInterfaceClass); \
pr_info("bInterfaceSubClass: 0x%x\n", i.bInterfaceSubClass); \
pr_info("bInterfaceProtocol: 0x%x\n", i.bInterfaceProtocol); \
pr_info("iInterface: 0x%x\n", i.iInterface); \
pr_info("\n"); \
}
struct usb_device *usb_dev;
struct vdsk_dev {
unsigned long size;
u8 *data;
spinlock_t lock;
struct gendisk *mydisk;
struct request_queue *queue;
};
u8 *buffer;
static void usb_mouse_irq(struct urb *urb) {
pr_info("usb_mouse_irq \n");
pr_info("BTN_LEFT %x \n", (*buffer) & 0x01);
usb_submit_urb(urb,GFP_ATOMIC);
}
struct vdsk_dev *dev;
int usb_mouse_probe(struct usb_interface *interface,
const struct usb_device_id *id) {
struct urb *irq;
int endpoint_int_in_addr;
unsigned int i;
unsigned int endpoints_count;
int endpoint_type;
struct usb_endpoint_descriptor endpoint;
int interfaceClass;
int interfaceSubClass;
int interfaceProtocol;
int pipe, maxp;
struct usb_host_interface *iface_desc = interface->cur_altsetting;
usb_dev = interface_to_usbdev(interface);
buffer = kmalloc(8,GFP_KERNEL);
dev_info(&interface->dev, "myprobe start\n");
dev_info(&interface->dev, "idVendor = %x\n", id->idVendor);
dev_info(&interface->dev, "idProduct = %x\n", id->idProduct);
endpoints_count = iface_desc->desc.bNumEndpoints;
dev_info(&interface->dev, "endpoints_count = %d\n", endpoints_count);
interfaceClass = iface_desc->desc.bInterfaceClass;
interfaceSubClass = iface_desc->desc.bInterfaceSubClass;
interfaceProtocol = iface_desc->desc.bInterfaceProtocol;
dev_info(&interface->dev, "bInterfaceClass = 0x%x\n", interfaceClass);
dev_info(&interface->dev, "interfaceSubClass = 0x%x\n", interfaceSubClass);
dev_info(&interface->dev, "interfaceProtocol = 0x%x\n", interfaceProtocol);
if (iface_desc->desc.bNumEndpoints < 1)
return -ENODEV;
switch (interfaceClass) {
case USB_CLASS_HID:
dev_info(&interface->dev, "interfaceClass: USB_CLASS_HID\n");
break;
case USB_CLASS_MASS_STORAGE:
dev_info(&interface->dev, "interfaceClass: USB_CLASS_MASS_STORAGE\n");
break;
default:
dev_info(&interface->dev, "never \n");
break;
}
switch (interfaceSubClass) {
case USB_SC_SCSI:
dev_info(&interface->dev, "interfaceSubClass: USB_SC_SCSI\n");
break;
default:
dev_info(&interface->dev, "never \n");
break;
}
switch (interfaceProtocol) {
case USB_PR_BULK:
dev_info(&interface->dev, "interfaceProtocol: USB_PR_BULK\n");
break;
default:
dev_info(&interface->dev, "never \n");
break;
}
endpoint = iface_desc->endpoint[0].desc;
if (usb_endpoint_is_int_in(&endpoint)) {
endpoint_int_in_addr = endpoint.bEndpointAddress;
}
dev_info(&interface->dev, "endpoint %d bDescriptorType = %d\n", i,
endpoint.bDescriptorType);
dev_info(&interface->dev, "endpoint %d bEndpointAddress = %d\n", i,
endpoint.bEndpointAddress);
dev_info(&interface->dev, "endpoint %d bInterval = %d\n", i,
endpoint.bInterval);
pipe = usb_rcvintpipe(usb_dev, endpoint.bEndpointAddress);
maxp = usb_maxpacket(usb_dev, pipe,0);
endpoint_type = endpoint.bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK;
switch (endpoint_type) {
case USB_ENDPOINT_XFER_CONTROL:
dev_info(&interface->dev, "control endpoint\n");
break;
case USB_ENDPOINT_XFER_ISOC:
dev_info(&interface->dev, "ISOCHRONOUS endpoint\n");
break;
case USB_ENDPOINT_XFER_BULK:
dev_info(&interface->dev, "bulk endpoint\n");
break;
case USB_ENDPOINT_XFER_INT:
dev_info(&interface->dev, "Interrupt endpoint\n");
break;
default:
dev_info(&interface->dev, "never \n");
break;
}
dev_info(&interface->dev, "myprobe end\n");
irq = usb_alloc_urb(0, GFP_KERNEL);
usb_fill_int_urb(irq, usb_dev, pipe, buffer,
(maxp > 8 ? 8 : maxp),
usb_mouse_irq, NULL, endpoint.bInterval);
usb_submit_urb(irq,GFP_ATOMIC);
return 0;
}
void usb_mouse_disconnect(struct usb_interface *intf) {
dev_info(&intf->dev, "mydisconnect\n");
}
static struct usb_device_id usb_mouse_id_table[] = { { USB_INTERFACE_INFO(
USB_CLASS_HID,
1, 2) }, { } };
//static struct usb_device_id usb_mouse_id_table[] = { { USB_DEVICE(USB_VENDOR_ID,
//USB_PRODUCT_ID) }, { } };
MODULE_DEVICE_TABLE(usb, usb_mouse_id_table);
static struct usb_driver usb_mouse_driver = { .name = "andy_mouse_driver", .probe =
usb_mouse_probe, .disconnect = usb_mouse_disconnect, .id_table =
usb_mouse_id_table, };
module_usb_driver( usb_mouse_driver );
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andy");