Linux USB鼠标驱动入门以及处理流程

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");

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux USB设备驱动是用于在Linux操作系统中管理和控制USB设备的软件模块。USB设备驱动负责与硬件进行通信,并提供操作系统和用程序与USB设备之间的接口。 在Linux中,USB设备驱动是作为内核模块加载的。它们可以通过以下几个步骤来实现: 1. 设备识别和匹配:USB设备驱动首先需要通过USB总线进行设备识别和匹配。当插入USB设备时,内核会检测到设备的插入并分配一个唯一的设备地址。 2. 驱动注册:设备识别后,驱动程序需要向内核注册,以便内核知道如何处理该设备。这可以通过将驱动程序结构体注册到USB子系统来完成。 3. 端点配置:USB设备通常有多个端点(Endpoint),每个端点都有特定的功能。驱动程序需要配置这些端点,包括端点的方向(输入或输出)、传输类型(控制、批量、中断、等等)以及数据包的大小等参数。 4. 数据传输:一旦设备和端点配置完成,驱动程序就可以开始与USB设备进行数据传输。它可以使用内核提供的USB核心函数来发送和接收数据。 5. 销毁和注销:当USB设备被拔出时,驱动程序需要进行清理工作,并从内核中注销。 编写USB设备驱动需要了解Linux内核的USB子系统和设备模型,以及设备的硬件规格和通信协议。在Linux内核源代码树中,有一些示例驱动可供参考,帮助开发者快速入门和实现自己的USB设备驱动

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值