Linux 驱动USB键盘驱动入门demo

1 需要内核配置文件禁用CONFIG_USB_HID,不然下面的驱动不会被探测到。
2 以下模块打印了8个控制按键是否被按下,
另外如果A按键按下,也会有打印。

#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>

/**


 *
 */

#define USB_VENDOR_ID   0x413c
#define USB_PRODUCT_ID  0x2113

#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");                                                  \
}

static const unsigned char usb_kbd_keycode[256] = {
	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
	115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
	122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
	150,158,159,128,136,177,178,176,142,152,173,140
};

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) {
	int i;
//	pr_info("usb_mouse_irq \n");
//	pr_info("BTN_LEFT %x \n", (*buffer) & 0x01);

	if((buffer[0] >> 0) & 1){
		pr_info("left ctrl pressed\n");
i=0;
pr_info("keycode = %d\n",usb_kbd_keycode[i + 224]);

	}
	if((buffer[0] >> 1) & 1){
		i=1;
			pr_info("left shift pressed\n");
			pr_info("keycode = %d\n",usb_kbd_keycode[i + 224]);



		}
	if((buffer[0] >> 2) & 1){
				pr_info("left alt pressed\n");
				i=2;
				pr_info("keycode = %d\n",usb_kbd_keycode[i + 224]);
			}
	if((buffer[0] >> 3) & 1){
					pr_info("KEY_LEFTMETA pressed\n");
					i=3;
					pr_info("keycode = %d\n",usb_kbd_keycode[i + 224]);

				}

	if((buffer[0] >> 4) & 1){
						pr_info("right ctrl  pressed\n");
						i=4;
						pr_info("keycode = %d\n",usb_kbd_keycode[i + 224]);
					}

	if((buffer[0] >> 5) & 1){
							pr_info("right shift  pressed\n");
							i=5;
							pr_info("keycode = %d\n",usb_kbd_keycode[i + 224]);
						}

	if((buffer[0] >> 6) & 1){
								pr_info("right alt  pressed\n");
								i=6;
								pr_info("keycode = %d\n",usb_kbd_keycode[i + 224]);
							}

	for (i = 0; i < 8; i++){
//		pr_info("BTN_LEFT %x \n", (buffer[0] >> i) & 1);
	}
//			input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);


	for (i = 2; i < 8; i++) {
	if (buffer[i] > 3 ) {
			pr_info("i = %d\n",i);
				if (usb_kbd_keycode[buffer[i]]){
					pr_info("keycode = %d\n",usb_kbd_keycode[buffer[i]]);
					if(usb_kbd_keycode[buffer[i]] == KEY_A){
						pr_info("A pressed\n");
					}

				}

	}
			}


	 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,
//0, 0) }, { } };

//static struct usb_device_id usb_mouse_id_table[] = { { USB_DEVICE(USB_VENDOR_ID,
//USB_PRODUCT_ID) }, { } };

static struct usb_device_id usb_kbd_id_table [] = {
	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
		USB_INTERFACE_PROTOCOL_KEYBOARD) },
	{ }						/* Terminating entry */
};


MODULE_DEVICE_TABLE(usb, usb_kbd_id_table);


static struct usb_driver usb_mouse_driver  = { .name = "andy_mouse_driver", .probe =
		usb_mouse_probe, .disconnect = usb_mouse_disconnect, .id_table =
				usb_kbd_id_table, };

module_usb_driver( usb_mouse_driver );

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andy");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Linux驱动程序示例,它创建了一个名为“hello”的字符设备,并实现了读取和写入设备的功能: ```c #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #define DEVICE_NAME "hello" #define BUF_LEN 80 MODULE_LICENSE("GPL"); static int major; // 设备号 static char msg[BUF_LEN]; // 设备缓冲区 static char *msg_ptr; static int hello_open(struct inode *inode, struct file *file) { msg_ptr = msg; return 0; } static ssize_t hello_read(struct file *file, char *buf, size_t count, loff_t *pos) { int bytes_read = 0; while (count && *msg_ptr) { put_user(*(msg_ptr++), buf++); count--; bytes_read++; } return bytes_read; } static ssize_t hello_write(struct file *file, const char *buf, size_t count, loff_t *pos) { int i; for (i = 0; i < count && i < BUF_LEN; i++) { get_user(msg[i], buf + i); } msg_ptr = msg; return i; } static const struct file_operations fops = { .owner = THIS_MODULE, .read = hello_read, .write = hello_write, .open = hello_open, }; static int __init hello_init(void) { major = register_chrdev(0, DEVICE_NAME, &fops); if (major < 0) { printk(KERN_ALERT "Failed to register device\n"); return major; } printk(KERN_INFO "Hello device registered, major = %d\n", major); return 0; } static void __exit hello_exit(void) { unregister_chrdev(major, DEVICE_NAME); printk(KERN_INFO "Goodbye\n"); } module_init(hello_init); module_exit(hello_exit); ``` 在此示例中,我们定义了一个名为“hello”的字符设备,并实现了读取和写入设备的功能。我们使用`register_chrdev`函数注册设备,并在`hello_read`和`hello_write`函数中实现读取和写入设备的功能。最后,我们使用`module_init`和`module_exit`函数来初始化和退出驱动程序。 该示例只是一个简单的Linux驱动程序示例,它可以作为了解驱动程序开发的起点。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值