Các thiết bị rất có thể nhận được một tệp /dev/input/
có tên eventN
N trong đó các thiết bị khác nhau như chuột, bàn phím, giắc cắm, nút nguồn, v.v.
ls -l /dev/input/by-{path,id}/
sẽ cho bạn một gợi ý.
Cũng nhìn vào:
cat /proc/bus/input/devices
Trong đó Sysfs
giá trị là đường dẫn dưới /sys
.
Bạn có thể kiểm tra bằng ví dụ
cat /dev/input/event2 # if 2 is kbd.
Để thực hiện sử dụng ioctl và kiểm tra thiết bị + màn hình.
EDIT 2:
ĐỒNG Ý. Tôi đang mở rộng câu trả lời này dựa trên giả định /dev/input/eventN
được sử dụng.
Một cách có thể là:
Tại vòng lặp khởi động tất cả event
các tập tin được tìm thấy trong /dev/input/
. Sử dụng ioctl()
để yêu cầu bit sự kiện:
ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
sau đó kiểm tra xem EV_KEY
-bit có được đặt không.
IFF đặt sau đó kiểm tra các khóa:
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), &keybit);
Ví dụ: nếu các phím số thú vị, thì hãy kiểm tra xem các bit cho KEY_0
- KEY9
và KEY_KP0
đến KEY_KP9
.
Các khóa IFF được tìm thấy sau đó bắt đầu theo dõi tệp sự kiện trong chuỗi.
Quay lại 1.
Bằng cách này, bạn sẽ có được để theo dõi tất cả các thiết bị đáp ứng các tiêu chí mong muốn. Bạn không thể chỉ kiểm tra EV_KEY
ví dụ như nút nguồn sẽ có bộ bit này, nhưng rõ ràng là nó sẽ không được KEY_A
đặt.
Đã thấy dương tính giả cho các khóa kỳ lạ, nhưng đối với các khóa bình thường thì điều này là đủ. Không có tác hại trực tiếp nào trong việc giám sát, ví dụ như tệp sự kiện cho nút nguồn hoặc giắc cắm, nhưng bạn sẽ không phát ra các sự kiện trong câu hỏi (hay còn gọi là mã xấu).
Chi tiết hơn dưới đây.
CHỈNH SỬA 1:
Liên quan đến "Giải thích rằng tuyên bố cuối cùng" . Đi qua vùng đất stackoverflow tại đây nhưng:
Một mẫu nhanh và bẩn trong C. Bạn sẽ phải triển khai nhiều mã khác nhau để kiểm tra xem bạn có thực sự nhận được đúng thiết bị, dịch loại sự kiện, mã và giá trị. Điển hình là khóa xuống, khóa phím, lặp lại khóa, mã khóa, v.v.
Không có thời gian, (và quá nhiều ở đây), để thêm phần còn lại.
Kiểm tra linux/input.h
, các chương trình như dumpkeys
, mã hạt nhân, vv để biết mã bản đồ. Ví dụdumpkeys -l
Dù sao đi nữa:
Chạy như ví dụ:
# ./testprog /dev/input/event2
Mã số:
#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;
}
EDIT 2 (tiếp theo):
Lưu ý rằng nếu bạn nhìn vào /proc/bus/input/devices
bạn có một chữ cái ở đầu mỗi dòng. Ở đây B
có nghĩa là bản đồ bit. Đó là ví dụ:
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
Mỗi bit đó tương ứng với một thuộc tính của thiết bị. Theo ý nghĩa của bit-map, 1 chỉ ra một thuộc tính, như được định nghĩa trong 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
Có một cái nhìn /drivers/input/input.{h,c}
trong cây nguồn kernel. Rất nhiều mã tốt ở đó. (Ví dụ: các thuộc tính của thiết bị được tạo bởi chức năng này .)
Mỗi bản đồ tài sản có thể đạt được bởi ioctl
. Ví dụ: nếu bạn muốn kiểm tra các thuộc tính LED nào có sẵn, hãy nói:
ioctl(fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), &ledbit);
Nhìn vào định nghĩa struct input_dev
trong input.h
làm thế nào ledbit
được xác định.
Để kiểm tra trạng thái cho đèn LED:
ioctl(fd, EVIOCGLED(sizeof(ledbit)), &ledbit);
Nếu bit 1 in ledbit
là 1 thì num-lock sẽ sáng. Nếu bit 2 là 1 thì nắp khóa được bật sáng, v.v.
input.h
có định nghĩa khác nhau.
Lưu ý khi theo dõi sự kiện:
Mã giả để theo dõi có thể là một cái gì đó theo hướng:
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
Một số tài liệu liên quan:
Documentation/input/input.txt
, đặc biệt lưu ý phần 5.
Documentation/input/event-codes.txt
, mô tả về các sự kiện khác nhau, vv Hãy lưu ý đến những gì được đề cập dưới đây, ví dụ như EV_SYN
vềSYN_DROPPED
Documentation/input
... Đọc phần còn lại nếu bạn muốn.
/dev/disk/by-id/
imho được tạo bởiudev
- câu hỏi là liệu điều này có sẵn trong trường hợp này không (nền tảng nhúng).