想写usb键盘驱动,大概怎么写?

风筝丶
博客专家认证
2017-07-12 04:35:06
芯片是s3c2440,
Kernel板本是4.4.17.
在内核默认的配置下,插上usb键盘后,显示:
usb 1-1: new low-speed USB device number 2 using s3c2410-ohci
usb 1-1: USB disconnect, device number 2
usb 1-1: new low-speed USB device number 3 using s3c2410-ohci
usb 1-1: USB disconnect, device number 3

我该参照内核里那个文件写?
我看keyboard.c这个文件里没有
module_init(xxx_init);
module_exit( xxx_exit);这样的东西啊,连probe函数都没有,那我怎么写初始化啊什么的啊?
...全文
1330 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
jklinux 2017-07-14
  • 打赏
  • 举报
回复
你不是已经收到usb键盘的数据了吗? 接着加入汇报键码就驱动好了。不要忘了标题哦。 内核选项的依整项

  │ Symbol: USB_HID [=y]                                                                                                                    │  
  │ Type  : tristate                                                                                                                        │  
  │ Prompt: USB Human Interface Device (full HID) support                                                                                   │  
  │   Defined at drivers/hid/usbhid/Kconfig:4                                                                                               │  
  │   Depends on: HID_SUPPORT [=y] && USB [=y] && INPUT [=y]                                                                                │  
  │   Location:                                                                                                                             │  
  │     -> Device Drivers                                                                                                                   │  
  │       -> HID Devices (HID_SUPPORT [=y])                                                                                                 │  
  │   Selects: HID [=y]
风筝丶 2017-07-14
  • 打赏
  • 举报
回复
引用 17 楼 jklinux 的回复:
接上面依赖项有: HID_SUPPORT [=y] && USB [=y] && INPUT [=y]


在make menuconfig界面里按'/' 会出现查找输入框, 输入"HID_SUPPORT"可以查看对应的配置项在哪里

唉,感谢老哥,终于弄好了,就是选中USB HID transport layer即可,这个就是了
jklinux 2017-07-14
  • 打赏
  • 举报
回复
接上面依赖项有: HID_SUPPORT [=y] && USB [=y] && INPUT [=y] 在make menuconfig界面里按'/' 会出现查找输入框, 输入"HID_SUPPORT"可以查看对应的配置项在哪里
风筝丶 2017-07-14
  • 打赏
  • 举报
回复
引用 15 楼 jklinux 的回复:
[quote=引用 14 楼 Guet_Kite 的回复:]
[quote=引用 13 楼 jklinux 的回复:]
你不是已经收到usb键盘的数据了吗? 接着加入汇报键码就驱动好了。不要忘了标题哦。

内核选项的依整项

│ Symbol: USB_HID [=y] │
│ Type : tristate │
│ Prompt: USB Human Interface Device (full HID) support │
│ Defined at drivers/hid/usbhid/Kconfig:4 │
│ Depends on: HID_SUPPORT [=y] && USB [=y] && INPUT [=y] │
│ Location: │
│ -> Device Drivers │
│ -> HID Devices (HID_SUPPORT [=y]) │
│ Selects: HID [=y]
老哥,我弄好了,丢在这了:http://blog.csdn.net/guet_kite/article/details/75108178
主要是觉得每次都insmod挺麻烦的,就想直接用内核自带的,,,,顺带一提,这个图我有点看不懂啊,依整项是什么?我看得懂Location:这个是所在路径.......[/quote]

我错了, 依赖项,即内核里的配置项本身也需要选上别的项才会出现的[/quote]
是不是这两项?我觉得就这两项最像了.....
jklinux 2017-07-14
  • 打赏
  • 举报
回复
引用 14 楼 Guet_Kite 的回复:
[quote=引用 13 楼 jklinux 的回复:] 你不是已经收到usb键盘的数据了吗? 接着加入汇报键码就驱动好了。不要忘了标题哦。 内核选项的依整项

  │ Symbol: USB_HID [=y]                                                                                                                    │  
  │ Type  : tristate                                                                                                                        │  
  │ Prompt: USB Human Interface Device (full HID) support                                                                                   │  
  │   Defined at drivers/hid/usbhid/Kconfig:4                                                                                               │  
  │   Depends on: HID_SUPPORT [=y] && USB [=y] && INPUT [=y]                                                                                │  
  │   Location:                                                                                                                             │  
  │     -> Device Drivers                                                                                                                   │  
  │       -> HID Devices (HID_SUPPORT [=y])                                                                                                 │  
  │   Selects: HID [=y]
老哥,我弄好了,丢在这了:http://blog.csdn.net/guet_kite/article/details/75108178 主要是觉得每次都insmod挺麻烦的,就想直接用内核自带的,,,,顺带一提,这个图我有点看不懂啊,依整项是什么?我看得懂Location:这个是所在路径.......[/quote] 我错了, 依赖项,即内核里的配置项本身也需要选上别的项才会出现的
风筝丶 2017-07-14
  • 打赏
  • 举报
回复
引用 13 楼 jklinux 的回复:
你不是已经收到usb键盘的数据了吗? 接着加入汇报键码就驱动好了。不要忘了标题哦。 内核选项的依整项

  │ Symbol: USB_HID [=y]                                                                                                                    │  
  │ Type  : tristate                                                                                                                        │  
  │ Prompt: USB Human Interface Device (full HID) support                                                                                   │  
  │   Defined at drivers/hid/usbhid/Kconfig:4                                                                                               │  
  │   Depends on: HID_SUPPORT [=y] && USB [=y] && INPUT [=y]                                                                                │  
  │   Location:                                                                                                                             │  
  │     -> Device Drivers                                                                                                                   │  
  │       -> HID Devices (HID_SUPPORT [=y])                                                                                                 │  
  │   Selects: HID [=y]
老哥,我弄好了,丢在这了:http://blog.csdn.net/guet_kite/article/details/75108178 主要是觉得每次都insmod挺麻烦的,就想直接用内核自带的,,,,顺带一提,这个图我有点看不懂啊,依整项是什么?我看得懂Location:这个是所在路径.......
jklinux 2017-07-13
  • 打赏
  • 举报
回复
引用 4 楼 Guet_Kite 的回复:
[quote=引用 2 楼 Guet_Kite 的回复:] [quote=引用 1 楼 jklinux 的回复:] 可以考照drivers/hid/usbhid/usbmouse.c 虽然它是鼠标的,但都是用usb的中断端点的设备,除了数据不一样外,基本一样。 usbmouse.c应是内核里最简单的usb设备驱动了。
哦哦。谢谢,又是老哥你。 我照着usb鼠标的驱动,写了键盘的驱动,然后把按键盘的键值打印出来: static void keyboard_irq(struct urb *urb) { static unsigned char pre_val; int i; static int cnt = 0; printk("data cnt %d: ", ++cnt); for (i = 0; i < len; i++) { printk("%02x ", usb_buf[i]); } printk("\n"); /* 重新提交urb */ usb_submit_urb(uk_urb, GFP_KERNEL); } 在屏幕上显示, l 键按下时显示:data cnt 43: 00 00 0f 00 00 00 00 00 s键按下时显示:data cnt 49: 00 00 16 00 00 00 00 00 可是我在内核下找到的定义是: #define KEY_S 31 #define KEY_D 32 #define KEY_F 33 #define KEY_G 34 #define KEY_H 35 #define KEY_J 36 #define KEY_K 37 #define KEY_L 38 那和我之前的显示不符。 而且,不用keyboard.c里的kbd_init函数真的没事吗?? 我给下我刚刚的键盘源码吧: 唉,居然不能上传文件,.....
#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>

static int len;
static struct input_dev *uk_dev;
static char *usb_buf;
static dma_addr_t usb_buf_phys;
static struct urb *uk_urb;

static struct usb_device_id keyboard_id_table [] = {
	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
		USB_INTERFACE_PROTOCOL_KEYBOARD) },
	//{USB_DEVICE(0x1234,0x5678)},
	{ }	/* Terminating entry */
};

static void keyboard_irq(struct urb *urb)
{
	static unsigned char pre_val;
	
	int i;
	static int cnt = 0;
	printk("data cnt %d: ", ++cnt);
	for (i = 0; i < len; i++)
	{
		printk("%02x ", usb_buf[i]);
	}
	printk("\n");

	/* 重新提交urb */
	usb_submit_urb(uk_urb, GFP_KERNEL);
}

static int keyboard_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	int pipe;
	
	interface = intf->cur_altsetting;
	endpoint = &interface->endpoint[0].desc;

	/* a. 分配一个input_dev */
	uk_dev = input_allocate_device();                     
	
	/* b. 设置 */
	/* b.1 能产生哪类事件 */
	set_bit(EV_KEY, uk_dev->evbit);
	set_bit(EV_REP, uk_dev->evbit);
	
	/* b.2 能产生哪些事件 */
	set_bit(KEY_L, uk_dev->keybit);
	set_bit(KEY_S, uk_dev->keybit);
	set_bit(KEY_ENTER, uk_dev->keybit);
	
	/* c. 注册 */
	input_register_device(uk_dev);
	
	/* d. 硬件相关操作 */
	/* 数据传输3要素: 源,目的,长度 */
	/* 源: USB设备的某个端点 */
	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

	/* 长度: */
	len = endpoint->wMaxPacketSize;

	/* 目的: */
	//usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
	usb_buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &usb_buf_phys);

	/* 使用"3要素" */
	/* 分配usb request block */
	uk_urb = usb_alloc_urb(0, GFP_KERNEL);
	/* 使用"3要素设置urb" */
	usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, keyboard_irq, NULL, endpoint->bInterval);
	uk_urb->transfer_dma = usb_buf_phys;
	uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	/* 使用URB */
	usb_submit_urb(uk_urb, GFP_KERNEL);
	
	return 0;
}

/*int __init kbd_init(void) 函数是键盘代码执行的开始点,
但keyboard.c并非是一定 执行的,你必须先定义CONFIG_VT(Character devices ->nbsp;Virtual terminal)才有效,
为什 么?因为kbd_init()是在tty_io.c 的 tty_init()中被调用的*/
/*static kbd_init(void)
{
	int i;
	int error;
	for (i = 0; i < MAX_NR_CONSOLES; i++) {
		kbd_table[i].ledflagstate = kbd_defleds();
		kbd_table[i].default_ledflagstate = kbd_defleds();
		kbd_table[i].ledmode = LED_SHOW_FLAGS;
		kbd_table[i].lockstate = KBD_DEFLOCK;
		kbd_table[i].slockstate = 0;
		kbd_table[i].modeflags = KBD_DEFMODE;
		kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
	}
	kbd_init_leds();
	error = input_register_handler(&kbd_handler);
	if (error)
		return error;
	tasklet_enable(&keyboard_tasklet);
	tasklet_schedule(&keyboard_tasklet);
	return 0;
}*/

static void keyboard_disconnect(struct usb_interface *intf)
{
	struct usb_device *dev = interface_to_usbdev(intf);

	//printk("disconnect usbmouse!\n");
	usb_kill_urb(uk_urb);
	usb_free_urb(uk_urb);

	usb_free_coherent(dev, len, usb_buf, usb_buf_phys);
	input_unregister_device(uk_dev);
	input_free_device(uk_dev);
}

/* 1. 分配/设置usb_driver */
static struct usb_driver keyboard_driver = {
	.name		= "my_keyboard",
	.probe		= keyboard_probe,
	.disconnect	= keyboard_disconnect,
	.id_table	= keyboard_id_table,
};

static int keyboard_init(void)
{
	/* 2. 注册 */
	usb_register(&keyboard_driver);
	return 0;
}

static void keyboard_exit(void)
{
	usb_deregister(&keyboard_driver);	
}

module_init(keyboard_init);
module_exit(keyboard_exit);

MODULE_LICENSE("GPL");

[/quote]键盘108键呢,我要一个个上报事件report上去?我看usbkbd.c这个文件,这个是键盘的驱动吧,没有一个个上报啊,倒是有个255的数组[/quote]

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

130     for (i = 0; i < 8; i++)
131         input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
132 
133     for (i = 2; i < 8; i++) {
134 
135         if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
136             if (usb_kbd_keycode[kbd->old[i]])
137                 input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
138             else
139                 hid_info(urb->dev,
140                      "Unknown key (scancode %#x) released.\n",
141                      kbd->old[i]);
142         }
143 
144         if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
145             if (usb_kbd_keycode[kbd->new[i]])
146                 input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
147             else
148                 hid_info(urb->dev,
149                      "Unknown key (scancode %#x) released.\n",
150                      kbd->new[i]);
151         }
152     }
这些就是汇报
风筝丶 2017-07-13
  • 打赏
  • 举报
回复
引用 9 楼 jklinux 的回复:
引用 8 楼 Guet_Kite 的回复:
[quote=引用 7 楼 jklinux 的回复:] 确定下设备驱动是否编进内核里,如果已编进内核,那就在驱动的id_table里加上你键盘的usb id
怎么确认啊?我在make menuconfig里看到keyboards这个选项被选中了,不知道是不是这个?
你的usb键盘好不好,应选上: [/quote]老哥,别放弃我啊我觉得我还能再抢救一下
风筝丶 2017-07-13
  • 打赏
  • 举报
回复
USB HID support ---> 如下:
风筝丶 2017-07-13
  • 打赏
  • 举报
回复
引用 9 楼 jklinux 的回复:
引用 8 楼 Guet_Kite 的回复:
[quote=引用 7 楼 jklinux 的回复:]
确定下设备驱动是否编进内核里,如果已编进内核,那就在驱动的id_table里加上你键盘的usb id
怎么确认啊?我在make menuconfig里看到keyboards这个选项被选中了,不知道是不是这个?



你的usb键盘好不好,应选上:

[/quote]可是我没有 usb human interface device suppoort。 这个选项啊:
jklinux 2017-07-13
  • 打赏
  • 举报
回复
引用 8 楼 Guet_Kite 的回复:
引用 7 楼 jklinux 的回复:
确定下设备驱动是否编进内核里,如果已编进内核,那就在驱动的id_table里加上你键盘的usb id
怎么确认啊?我在make menuconfig里看到keyboards这个选项被选中了,不知道是不是这个?



你的usb键盘好不好,应选上:

风筝丶 2017-07-13
  • 打赏
  • 举报
回复
引用 7 楼 jklinux 的回复:
确定下设备驱动是否编进内核里,如果已编进内核,那就在驱动的id_table里加上你键盘的usb id
怎么确认啊?我在make menuconfig里看到keyboards这个选项被选中了,不知道是不是这个?
jklinux 2017-07-13
  • 打赏
  • 举报
回复
确定下设备驱动是否编进内核里,如果已编进内核,那就在驱动的id_table里加上你键盘的usb id
风筝丶 2017-07-13
  • 打赏
  • 举报
回复
引用 5 楼 jklinux 的回复:
[quote=引用 4 楼 Guet_Kite 的回复:] [quote=引用 2 楼 Guet_Kite 的回复:] [quote=引用 1 楼 jklinux 的回复:] 可以考照drivers/hid/usbhid/usbmouse.c 虽然它是鼠标的,但都是用usb的中断端点的设备,除了数据不一样外,基本一样。 usbmouse.c应是内核里最简单的usb设备驱动了。
哦哦。谢谢,又是老哥你。 我照着usb鼠标的驱动,写了键盘的驱动,然后把按键盘的键值打印出来: static void keyboard_irq(struct urb *urb) { static unsigned char pre_val; int i; static int cnt = 0; printk("data cnt %d: ", ++cnt); for (i = 0; i < len; i++) { printk("%02x ", usb_buf[i]); } printk("\n"); /* 重新提交urb */ usb_submit_urb(uk_urb, GFP_KERNEL); } 在屏幕上显示, l 键按下时显示:data cnt 43: 00 00 0f 00 00 00 00 00 s键按下时显示:data cnt 49: 00 00 16 00 00 00 00 00 可是我在内核下找到的定义是: #define KEY_S 31 #define KEY_D 32 #define KEY_F 33 #define KEY_G 34 #define KEY_H 35 #define KEY_J 36 #define KEY_K 37 #define KEY_L 38 那和我之前的显示不符。 而且,不用keyboard.c里的kbd_init函数真的没事吗?? 我给下我刚刚的键盘源码吧: 唉,居然不能上传文件,.....
#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>

static int len;
static struct input_dev *uk_dev;
static char *usb_buf;
static dma_addr_t usb_buf_phys;
static struct urb *uk_urb;

static struct usb_device_id keyboard_id_table [] = {
	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
		USB_INTERFACE_PROTOCOL_KEYBOARD) },
	//{USB_DEVICE(0x1234,0x5678)},
	{ }	/* Terminating entry */
};

static void keyboard_irq(struct urb *urb)
{
	static unsigned char pre_val;
	
	int i;
	static int cnt = 0;
	printk("data cnt %d: ", ++cnt);
	for (i = 0; i < len; i++)
	{
		printk("%02x ", usb_buf[i]);
	}
	printk("\n");

	/* 重新提交urb */
	usb_submit_urb(uk_urb, GFP_KERNEL);
}

static int keyboard_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	int pipe;
	
	interface = intf->cur_altsetting;
	endpoint = &interface->endpoint[0].desc;

	/* a. 分配一个input_dev */
	uk_dev = input_allocate_device();                     
	
	/* b. 设置 */
	/* b.1 能产生哪类事件 */
	set_bit(EV_KEY, uk_dev->evbit);
	set_bit(EV_REP, uk_dev->evbit);
	
	/* b.2 能产生哪些事件 */
	set_bit(KEY_L, uk_dev->keybit);
	set_bit(KEY_S, uk_dev->keybit);
	set_bit(KEY_ENTER, uk_dev->keybit);
	
	/* c. 注册 */
	input_register_device(uk_dev);
	
	/* d. 硬件相关操作 */
	/* 数据传输3要素: 源,目的,长度 */
	/* 源: USB设备的某个端点 */
	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

	/* 长度: */
	len = endpoint->wMaxPacketSize;

	/* 目的: */
	//usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
	usb_buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &usb_buf_phys);

	/* 使用"3要素" */
	/* 分配usb request block */
	uk_urb = usb_alloc_urb(0, GFP_KERNEL);
	/* 使用"3要素设置urb" */
	usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, keyboard_irq, NULL, endpoint->bInterval);
	uk_urb->transfer_dma = usb_buf_phys;
	uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	/* 使用URB */
	usb_submit_urb(uk_urb, GFP_KERNEL);
	
	return 0;
}

/*int __init kbd_init(void) 函数是键盘代码执行的开始点,
但keyboard.c并非是一定 执行的,你必须先定义CONFIG_VT(Character devices ->nbsp;Virtual terminal)才有效,
为什 么?因为kbd_init()是在tty_io.c 的 tty_init()中被调用的*/
/*static kbd_init(void)
{
	int i;
	int error;
	for (i = 0; i < MAX_NR_CONSOLES; i++) {
		kbd_table[i].ledflagstate = kbd_defleds();
		kbd_table[i].default_ledflagstate = kbd_defleds();
		kbd_table[i].ledmode = LED_SHOW_FLAGS;
		kbd_table[i].lockstate = KBD_DEFLOCK;
		kbd_table[i].slockstate = 0;
		kbd_table[i].modeflags = KBD_DEFMODE;
		kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
	}
	kbd_init_leds();
	error = input_register_handler(&kbd_handler);
	if (error)
		return error;
	tasklet_enable(&keyboard_tasklet);
	tasklet_schedule(&keyboard_tasklet);
	return 0;
}*/

static void keyboard_disconnect(struct usb_interface *intf)
{
	struct usb_device *dev = interface_to_usbdev(intf);

	//printk("disconnect usbmouse!\n");
	usb_kill_urb(uk_urb);
	usb_free_urb(uk_urb);

	usb_free_coherent(dev, len, usb_buf, usb_buf_phys);
	input_unregister_device(uk_dev);
	input_free_device(uk_dev);
}

/* 1. 分配/设置usb_driver */
static struct usb_driver keyboard_driver = {
	.name		= "my_keyboard",
	.probe		= keyboard_probe,
	.disconnect	= keyboard_disconnect,
	.id_table	= keyboard_id_table,
};

static int keyboard_init(void)
{
	/* 2. 注册 */
	usb_register(&keyboard_driver);
	return 0;
}

static void keyboard_exit(void)
{
	usb_deregister(&keyboard_driver);	
}

module_init(keyboard_init);
module_exit(keyboard_exit);

MODULE_LICENSE("GPL");

[/quote]键盘108键呢,我要一个个上报事件report上去?我看usbkbd.c这个文件,这个是键盘的驱动吧,没有一个个上报啊,倒是有个255的数组[/quote]

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

130     for (i = 0; i < 8; i++)
131         input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
132 
133     for (i = 2; i < 8; i++) {
134 
135         if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
136             if (usb_kbd_keycode[kbd->old[i]])
137                 input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
138             else
139                 hid_info(urb->dev,
140                      "Unknown key (scancode %#x) released.\n",
141                      kbd->old[i]);
142         }
143 
144         if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
145             if (usb_kbd_keycode[kbd->new[i]])
146                 input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
147             else
148                 hid_info(urb->dev,
149                      "Unknown key (scancode %#x) released.\n",
150                      kbd->new[i]);
151         }
152     }
这些就是汇报 [/quote]那很奇怪啊,那内核里都有完整的键盘驱动了,为什么我直接插键盘上去不能用啊。插上usb键盘后,显示: usb 1-1: new low-speed USB device number 2 using s3c2410-ohci usb 1-1: USB disconnect, device number 2 usb 1-1: new low-speed USB device number 3 using s3c2410-ohci usb 1-1: USB disconnect, device number 3
风筝丶 2017-07-12
  • 打赏
  • 举报
回复
引用 2 楼 Guet_Kite 的回复:
[quote=引用 1 楼 jklinux 的回复:] 可以考照drivers/hid/usbhid/usbmouse.c 虽然它是鼠标的,但都是用usb的中断端点的设备,除了数据不一样外,基本一样。 usbmouse.c应是内核里最简单的usb设备驱动了。
哦哦。谢谢,又是老哥你。 我照着usb鼠标的驱动,写了键盘的驱动,然后把按键盘的键值打印出来: static void keyboard_irq(struct urb *urb) { static unsigned char pre_val; int i; static int cnt = 0; printk("data cnt %d: ", ++cnt); for (i = 0; i < len; i++) { printk("%02x ", usb_buf[i]); } printk("\n"); /* 重新提交urb */ usb_submit_urb(uk_urb, GFP_KERNEL); } 在屏幕上显示, l 键按下时显示:data cnt 43: 00 00 0f 00 00 00 00 00 s键按下时显示:data cnt 49: 00 00 16 00 00 00 00 00 可是我在内核下找到的定义是: #define KEY_S 31 #define KEY_D 32 #define KEY_F 33 #define KEY_G 34 #define KEY_H 35 #define KEY_J 36 #define KEY_K 37 #define KEY_L 38 那和我之前的显示不符。 而且,不用keyboard.c里的kbd_init函数真的没事吗?? 我给下我刚刚的键盘源码吧: 唉,居然不能上传文件,.....
#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>

static int len;
static struct input_dev *uk_dev;
static char *usb_buf;
static dma_addr_t usb_buf_phys;
static struct urb *uk_urb;

static struct usb_device_id keyboard_id_table [] = {
	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
		USB_INTERFACE_PROTOCOL_KEYBOARD) },
	//{USB_DEVICE(0x1234,0x5678)},
	{ }	/* Terminating entry */
};

static void keyboard_irq(struct urb *urb)
{
	static unsigned char pre_val;
	
	int i;
	static int cnt = 0;
	printk("data cnt %d: ", ++cnt);
	for (i = 0; i < len; i++)
	{
		printk("%02x ", usb_buf[i]);
	}
	printk("\n");

	/* 重新提交urb */
	usb_submit_urb(uk_urb, GFP_KERNEL);
}

static int keyboard_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	int pipe;
	
	interface = intf->cur_altsetting;
	endpoint = &interface->endpoint[0].desc;

	/* a. 分配一个input_dev */
	uk_dev = input_allocate_device();                     
	
	/* b. 设置 */
	/* b.1 能产生哪类事件 */
	set_bit(EV_KEY, uk_dev->evbit);
	set_bit(EV_REP, uk_dev->evbit);
	
	/* b.2 能产生哪些事件 */
	set_bit(KEY_L, uk_dev->keybit);
	set_bit(KEY_S, uk_dev->keybit);
	set_bit(KEY_ENTER, uk_dev->keybit);
	
	/* c. 注册 */
	input_register_device(uk_dev);
	
	/* d. 硬件相关操作 */
	/* 数据传输3要素: 源,目的,长度 */
	/* 源: USB设备的某个端点 */
	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

	/* 长度: */
	len = endpoint->wMaxPacketSize;

	/* 目的: */
	//usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
	usb_buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &usb_buf_phys);

	/* 使用"3要素" */
	/* 分配usb request block */
	uk_urb = usb_alloc_urb(0, GFP_KERNEL);
	/* 使用"3要素设置urb" */
	usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, keyboard_irq, NULL, endpoint->bInterval);
	uk_urb->transfer_dma = usb_buf_phys;
	uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	/* 使用URB */
	usb_submit_urb(uk_urb, GFP_KERNEL);
	
	return 0;
}

/*int __init kbd_init(void) 函数是键盘代码执行的开始点,
但keyboard.c并非是一定 执行的,你必须先定义CONFIG_VT(Character devices ->nbsp;Virtual terminal)才有效,
为什 么?因为kbd_init()是在tty_io.c 的 tty_init()中被调用的*/
/*static kbd_init(void)
{
	int i;
	int error;
	for (i = 0; i < MAX_NR_CONSOLES; i++) {
		kbd_table[i].ledflagstate = kbd_defleds();
		kbd_table[i].default_ledflagstate = kbd_defleds();
		kbd_table[i].ledmode = LED_SHOW_FLAGS;
		kbd_table[i].lockstate = KBD_DEFLOCK;
		kbd_table[i].slockstate = 0;
		kbd_table[i].modeflags = KBD_DEFMODE;
		kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
	}
	kbd_init_leds();
	error = input_register_handler(&kbd_handler);
	if (error)
		return error;
	tasklet_enable(&keyboard_tasklet);
	tasklet_schedule(&keyboard_tasklet);
	return 0;
}*/

static void keyboard_disconnect(struct usb_interface *intf)
{
	struct usb_device *dev = interface_to_usbdev(intf);

	//printk("disconnect usbmouse!\n");
	usb_kill_urb(uk_urb);
	usb_free_urb(uk_urb);

	usb_free_coherent(dev, len, usb_buf, usb_buf_phys);
	input_unregister_device(uk_dev);
	input_free_device(uk_dev);
}

/* 1. 分配/设置usb_driver */
static struct usb_driver keyboard_driver = {
	.name		= "my_keyboard",
	.probe		= keyboard_probe,
	.disconnect	= keyboard_disconnect,
	.id_table	= keyboard_id_table,
};

static int keyboard_init(void)
{
	/* 2. 注册 */
	usb_register(&keyboard_driver);
	return 0;
}

static void keyboard_exit(void)
{
	usb_deregister(&keyboard_driver);	
}

module_init(keyboard_init);
module_exit(keyboard_exit);

MODULE_LICENSE("GPL");

[/quote]键盘108键呢,我要一个个上报事件report上去?我看usbkbd.c这个文件,这个是键盘的驱动吧,没有一个个上报啊,倒是有个255的数组
jklinux 2017-07-12
  • 打赏
  • 举报
回复
#define KEY_S 31 #define KEY_D 32 #define KEY_F 33 #define KEY_G 34 #define KEY_H 35 #define KEY_J 36 #define KEY_K 37 #define KEY_L 38 这些是<linux/input.h>头文件里的定义吧,这是linux系统用的键码,与硬件无关。你需要把硬件接收的数据按你的定义转换成你列出的宏作为系统的键码。 你就接收硬件数据,input_report_key(...), input_sync(..)就可以了
风筝丶 2017-07-12
  • 打赏
  • 举报
回复
引用 1 楼 jklinux 的回复:
可以考照drivers/hid/usbhid/usbmouse.c 虽然它是鼠标的,但都是用usb的中断端点的设备,除了数据不一样外,基本一样。 usbmouse.c应是内核里最简单的usb设备驱动了。
哦哦。谢谢,又是老哥你。 我照着usb鼠标的驱动,写了键盘的驱动,然后把按键盘的键值打印出来: static void keyboard_irq(struct urb *urb) { static unsigned char pre_val; int i; static int cnt = 0; printk("data cnt %d: ", ++cnt); for (i = 0; i < len; i++) { printk("%02x ", usb_buf[i]); } printk("\n"); /* 重新提交urb */ usb_submit_urb(uk_urb, GFP_KERNEL); } 在屏幕上显示, l 键按下时显示:data cnt 43: 00 00 0f 00 00 00 00 00 s键按下时显示:data cnt 49: 00 00 16 00 00 00 00 00 可是我在内核下找到的定义是: #define KEY_S 31 #define KEY_D 32 #define KEY_F 33 #define KEY_G 34 #define KEY_H 35 #define KEY_J 36 #define KEY_K 37 #define KEY_L 38 那和我之前的显示不符。 而且,不用keyboard.c里的kbd_init函数真的没事吗?? 我给下我刚刚的键盘源码吧: 唉,居然不能上传文件,.....
#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>

static int len;
static struct input_dev *uk_dev;
static char *usb_buf;
static dma_addr_t usb_buf_phys;
static struct urb *uk_urb;

static struct usb_device_id keyboard_id_table [] = {
	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
		USB_INTERFACE_PROTOCOL_KEYBOARD) },
	//{USB_DEVICE(0x1234,0x5678)},
	{ }	/* Terminating entry */
};

static void keyboard_irq(struct urb *urb)
{
	static unsigned char pre_val;
	
	int i;
	static int cnt = 0;
	printk("data cnt %d: ", ++cnt);
	for (i = 0; i < len; i++)
	{
		printk("%02x ", usb_buf[i]);
	}
	printk("\n");

	/* 重新提交urb */
	usb_submit_urb(uk_urb, GFP_KERNEL);
}

static int keyboard_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	int pipe;
	
	interface = intf->cur_altsetting;
	endpoint = &interface->endpoint[0].desc;

	/* a. 分配一个input_dev */
	uk_dev = input_allocate_device();                     
	
	/* b. 设置 */
	/* b.1 能产生哪类事件 */
	set_bit(EV_KEY, uk_dev->evbit);
	set_bit(EV_REP, uk_dev->evbit);
	
	/* b.2 能产生哪些事件 */
	set_bit(KEY_L, uk_dev->keybit);
	set_bit(KEY_S, uk_dev->keybit);
	set_bit(KEY_ENTER, uk_dev->keybit);
	
	/* c. 注册 */
	input_register_device(uk_dev);
	
	/* d. 硬件相关操作 */
	/* 数据传输3要素: 源,目的,长度 */
	/* 源: USB设备的某个端点 */
	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

	/* 长度: */
	len = endpoint->wMaxPacketSize;

	/* 目的: */
	//usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
	usb_buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &usb_buf_phys);

	/* 使用"3要素" */
	/* 分配usb request block */
	uk_urb = usb_alloc_urb(0, GFP_KERNEL);
	/* 使用"3要素设置urb" */
	usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, keyboard_irq, NULL, endpoint->bInterval);
	uk_urb->transfer_dma = usb_buf_phys;
	uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	/* 使用URB */
	usb_submit_urb(uk_urb, GFP_KERNEL);
	
	return 0;
}

/*int __init kbd_init(void) 函数是键盘代码执行的开始点,
但keyboard.c并非是一定 执行的,你必须先定义CONFIG_VT(Character devices ->nbsp;Virtual terminal)才有效,
为什 么?因为kbd_init()是在tty_io.c 的 tty_init()中被调用的*/
/*static kbd_init(void)
{
	int i;
	int error;
	for (i = 0; i < MAX_NR_CONSOLES; i++) {
		kbd_table[i].ledflagstate = kbd_defleds();
		kbd_table[i].default_ledflagstate = kbd_defleds();
		kbd_table[i].ledmode = LED_SHOW_FLAGS;
		kbd_table[i].lockstate = KBD_DEFLOCK;
		kbd_table[i].slockstate = 0;
		kbd_table[i].modeflags = KBD_DEFMODE;
		kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
	}
	kbd_init_leds();
	error = input_register_handler(&kbd_handler);
	if (error)
		return error;
	tasklet_enable(&keyboard_tasklet);
	tasklet_schedule(&keyboard_tasklet);
	return 0;
}*/

static void keyboard_disconnect(struct usb_interface *intf)
{
	struct usb_device *dev = interface_to_usbdev(intf);

	//printk("disconnect usbmouse!\n");
	usb_kill_urb(uk_urb);
	usb_free_urb(uk_urb);

	usb_free_coherent(dev, len, usb_buf, usb_buf_phys);
	input_unregister_device(uk_dev);
	input_free_device(uk_dev);
}

/* 1. 分配/设置usb_driver */
static struct usb_driver keyboard_driver = {
	.name		= "my_keyboard",
	.probe		= keyboard_probe,
	.disconnect	= keyboard_disconnect,
	.id_table	= keyboard_id_table,
};

static int keyboard_init(void)
{
	/* 2. 注册 */
	usb_register(&keyboard_driver);
	return 0;
}

static void keyboard_exit(void)
{
	usb_deregister(&keyboard_driver);	
}

module_init(keyboard_init);
module_exit(keyboard_exit);

MODULE_LICENSE("GPL");

jklinux 2017-07-12
  • 打赏
  • 举报
回复
可以考照drivers/hid/usbhid/usbmouse.c 虽然它是鼠标的,但都是用usb的中断端点的设备,除了数据不一样外,基本一样。 usbmouse.c应是内核里最简单的usb设备驱动了。

1,318

社区成员

发帖
与我相关
我的任务
社区描述
主要是开发驱动技术
社区管理员
  • 驱动程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧