Answers:
设备很可能会获得一个/dev/input/
名为的文件,eventN
其中N是各种设备,例如鼠标,键盘,插孔,电源按钮等。
ls -l /dev/input/by-{path,id}/
应该给你一个提示。
还要看:
cat /proc/bus/input/devices
当Sysfs
值路径下/sys
。
您可以通过例如测试
cat /dev/input/event2 # if 2 is kbd.
要实现使用ioctl并检查设备+监视器。
编辑2:
好。我正在根据假设/dev/input/eventN
使用此答案。
一种方法是:
在启动循环时,在中event
找到所有文件/dev/input/
。使用ioctl()
以请求事件位:
ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
然后检查是否EV_KEY
设置了-bit。
设置IFF,然后检查密钥:
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), &keybit);
例如,如果数字键很有趣,则检查KEY_0
- KEY9
和KEY_KP0
to的位KEY_KP9
。
找到IFF密钥,然后在线程中开始监视事件文件。
回到1。
这样,您应该监视所有符合所需条件的设备。您不仅可以检查,EV_KEY
例如电源按钮是否已设置此位,但显然没有KEY_A
设置等。
已经看到了异国密钥的误报,但是对于普通密钥来说就足够了。监视没有直接危害,例如,电源按钮或插孔的事件文件,但这些不会发出有问题的事件(又称错误代码)。
下面更详细。
编辑1:
关于“解释最后的陈述……”。在stackoverflow中继续浏览 ……但是:
C语言中的一个快速而肮脏的示例。您将必须实施各种代码来检查您是否真正获得了正确的设备,转换事件类型,代码和值。通常是向下,向上,重复,按键代码等。
还没来得及添加剩余的时间(这里太多了)。
检出linux/input.h
,诸如dumpkeys
,内核代码等程序以获取映射代码。例如dumpkeys -l
无论如何:
运行例如:
# ./testprog /dev/input/event2
码:
#include <stdio.h>
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include <fcntl.h> /* open() */
#include <unistd.h> /* close() */
#include <sys/ioctl.h> /* ioctl() */
#include <linux/input.h> /* EVIOCGVERSION ++ */
#define EV_BUF_SIZE 16
int main(int argc, char *argv[])
{
int fd, sz;
unsigned i;
/* A few examples of information to gather */
unsigned version;
unsigned short id[4]; /* or use struct input_id */
char name[256] = "N/A";
struct input_event ev[EV_BUF_SIZE]; /* Read up to N events ata time */
if (argc < 2) {
fprintf(stderr,
"Usage: %s /dev/input/eventN\n"
"Where X = input device number\n",
argv[0]
);
return EINVAL;
}
if ((fd = open(argv[1], O_RDONLY)) < 0) {
fprintf(stderr,
"ERR %d:\n"
"Unable to open `%s'\n"
"%s\n",
errno, argv[1], strerror(errno)
);
}
/* Error check here as well. */
ioctl(fd, EVIOCGVERSION, &version);
ioctl(fd, EVIOCGID, id);
ioctl(fd, EVIOCGNAME(sizeof(name)), name);
fprintf(stderr,
"Name : %s\n"
"Version : %d.%d.%d\n"
"ID : Bus=%04x Vendor=%04x Product=%04x Version=%04x\n"
"----------\n"
,
name,
version >> 16,
(version >> 8) & 0xff,
version & 0xff,
id[ID_BUS],
id[ID_VENDOR],
id[ID_PRODUCT],
id[ID_VERSION]
);
/* Loop. Read event file and parse result. */
for (;;) {
sz = read(fd, ev, sizeof(struct input_event) * EV_BUF_SIZE);
if (sz < (int) sizeof(struct input_event)) {
fprintf(stderr,
"ERR %d:\n"
"Reading of `%s' failed\n"
"%s\n",
errno, argv[1], strerror(errno)
);
goto fine;
}
/* Implement code to translate type, code and value */
for (i = 0; i < sz / sizeof(struct input_event); ++i) {
fprintf(stderr,
"%ld.%06ld: "
"type=%02x "
"code=%02x "
"value=%02x\n",
ev[i].time.tv_sec,
ev[i].time.tv_usec,
ev[i].type,
ev[i].code,
ev[i].value
);
}
}
fine:
close(fd);
return errno;
}
编辑2(续):
请注意,如果您看的/proc/bus/input/devices
话,每行的开头都有一个字母。这里的B
意思是位图。例如:
B: PROP=0
B: EV=120013
B: KEY=20000 200 20 0 0 0 0 500f 2100002 3803078 f900d401 feffffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=7
这些位中的每一个对应于设备的属性。通过位图表示1表示存在一个属性,如中所定义linux/input.h
。:
B: PROP=0 => 0000 0000
B: EV=120013 => 0001 0010 0000 0000 0001 0011 (Event types sup. in this device.)
| | | ||
| | | |+-- EV_SYN (0x00)
| | | +--- EV_KEY (0x01)
| | +------- EV_MSC (0x04)
| +----------------------- EV_LED (0x11)
+--------------------------- EV_REP (0x14)
B: KEY=20... => OK, I'm not writing out this one as it is a bit huge.
B: MSC=10 => 0001 0000
|
+------- MSC_SCAN
B: LED=7 => 0000 0111 , indicates what LED's are present
|||
||+-- LED_NUML
|+--- LED_CAPSL
+---- LED_SCROLL
看看/drivers/input/input.{h,c}
内核源代码树。那里有很多好的代码。(例如,设备属性是通过此函数产生的。)
每个属性映射都可以通过获取ioctl
。例如,如果要检查可用的LED属性,请说:
ioctl(fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), &ledbit);
查看struct input_dev
in的定义以input.h
了解如何ledbit
定义。
要检查LED状态,例如:
ioctl(fd, EVIOCGLED(sizeof(ledbit)), &ledbit);
如果第1位ledbit
为1,则num-lock点亮。如果位2为1,则大写锁定点亮,依此类推。
input.h
具有各种定义。
关于事件监视的注意事项:
用于监视的伪代码可能朝着以下方向发展:
WHILE TRUE
READ input_event
IF event->type == EV_SYN THEN
IF event->code == SYN_DROPPED THEN
Discard all events including next EV_SYN
ELSE
This marks EOF current event.
FI
ELSE IF event->type == EV_KEY THEN
SWITCH ev->value
CASE 0: Key Release (act accordingly)
CASE 1: Key Press (act accordingly)
CASE 2: Key Autorepeat (act accordingly)
END SWITCH
FI
END WHILE
一些相关文件:
Documentation/input/input.txt
,尤其是 注意第5节。Documentation/input/event-codes.txt
,各种事件的描述等。请注意EV_SYN
有关“例如”的内容SYN_DROPPED
Documentation/input
...如果需要,请继续阅读。您可以通过引用轻松地做到这一点/dev/input/by-id/usb-manufacturername_*serialnumber*
。这些显示为符号链接,您可以使用它们取消引用readlink -e
以确定关联的块设备。但是,通过这些链接创建的链接udev
可能不会出现在您的嵌入式环境中。
或.. dmesg
连接USB设备后查看。它应该给您/dev
节点。
by-id
是正确的。例如,我的USB键盘可用作/dev/input/by-id/usb-_USB_Keyboard-event-kbd
和/dev/input/by-path/pci-0000:00:1d.2-usb-0:2:1.0-event-kbd
。
/dev/disk/by-id/
imho中的条目是由创建的udev
-问题是在这种特殊情况下(嵌入式平台)是否可用。