อุปกรณ์ที่มีแนวโน้มมากที่สุดจะได้รับไฟล์ใน/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
มีการตั้งค่าบิต
IFF ตั้งค่าแล้วตรวจสอบคีย์:
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), &keybit);
เช่นถ้าจำนวนคีย์เป็นที่น่าสนใจแล้วตรวจสอบว่าบิตKEY_0
- KEY9
และเพื่อKEY_KP0
KEY_KP9
พบคีย์ IFF จากนั้นเริ่มการตรวจสอบไฟล์เหตุการณ์ในเธรด
กลับไปที่ 1
วิธีนี้คุณควรไปตรวจสอบอุปกรณ์ทั้งหมดที่ตรงตามเกณฑ์ที่ต้องการ คุณไม่สามารถตรวจสอบได้EV_KEY
อย่างเช่นปุ่มเปิดปิดเครื่องจะมีชุดบิตนี้ แต่แน่นอนว่ามันจะไม่มีKEY_A
ชุดอื่น ๆ
เคยเห็นผลบวกผิด ๆ สำหรับคีย์แปลกใหม่ แต่สำหรับคีย์ปกติสิ่งนี้น่าจะพอเพียง ไม่มีอันตรายโดยตรงในการตรวจสอบเช่นไฟล์เหตุการณ์สำหรับปุ่มเปิดปิดหรือแจ็ค แต่คุณจะไม่ปล่อยเหตุการณ์ที่เป็นปัญหา (รหัสที่ไม่ดี)
รายละเอียดเพิ่มเติมด้านล่าง
แก้ไข 1:
ในเรื่องที่เกี่ยวกับ"อธิบายว่าคำสั่งสุดท้าย ..." จะไปในดินแดนซ้อนทับที่นี่ ... แต่:
ตัวอย่างที่รวดเร็วและสกปรกใน 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
หมายถึง bit-map นั่นคือตัวอย่าง:
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
ในinput.h
สำหรับวิธีการledbit
ที่กำหนดไว้
ในการตรวจสอบสถานะของ LED ว่า:
ioctl(fd, EVIOCGLED(sizeof(ledbit)), &ledbit);
ถ้า bit 1 in ledbit
เป็น 1 ดังนั้น num-lock จะติดสว่าง ถ้า bit 2 เป็น 1 จะทำให้ Caps Lock ติดสว่างเป็นต้น
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
, esp. หมายเหตุมาตรา 5
Documentation/input/event-codes.txt
คำอธิบายของเหตุการณ์ต่าง ๆ ฯลฯ จดบันทึกสิ่งที่กล่าวถึงภายใต้เช่นEV_SYN
เกี่ยวกับSYN_DROPPED
Documentation/input
... อ่านที่เหลือถ้าคุณต้องการ
/dev/disk/by-id/
เป็น imho สร้างขึ้นโดยudev
- คำถามคือว่านี้มีอยู่ในกรณีอนุภาค (แพลตฟอร์มฝัง)