私は起動時に自動的に実行され、文字表示と一種のボタン配列を介してユーザーと対話するプログラムを開発する組み込みLinuxプロジェクトを進めています。単純なGPIOボタン配列を使用すると、これらのGPIOライン上のボタンを見つけるプログラムを簡単に作成できます。しかし、私たちのアイデアの1つは、USBナンバーキーパッドデバイスを使用してユーザー入力を置き換えることです。私が理解したように、これらのデバイスはオペレーティングシステムにUSBキーボードとして表示されます。このように進んでいる場合は、仮想端末やVGAモニタがないことを念頭に置いて、私のプログラムがLinuxのこのUSBキーボードで入力を見つける方法はありますか? USBキーボードが接続されたら、「/dev」にファイル記述子を開くことができるエンティティはありますか?
ベストアンサー1
/dev/input/
デバイスにというファイルがある可能性が高いですeventN
。ここで、Nはマウス、キーボード、ジャック、電源ボタンなどのさまざまなデバイスです。
ls -l /dev/input/by-{path,id}/
ヒントを与える必要があります。
また見なさい:
cat /proc/bus/input/devices
ここでSysfs
value は以下のパスです/sys
。
たとえば、これをテストできます。
cat /dev/input/event2 # if 2 is kbd.
ioctlを使用するには、デバイス+モニターを確認してください。
編集2:
わかりました、私は/dev/input/eventN
使用された仮定に基づいてこの答えを拡張します。
1つのアプローチは次のとおりです。
起動時に
event
見つかったすべてのファイルを繰り返します/dev/input/
。ioctl()
イベントビットを要求するために使用されます。ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
次に、-bitが設定されていることを確認してください
EV_KEY
。その後、IFF設定はキーを確認します。
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), &keybit);
たとえば、数字キーが面白い場合は
KEY_0
-KEY9
とKEY_KP0
to ビットがあることを確認してください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
ビットマップです。たとえば、
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 の場合、数値ロックインジケータが点灯します。ビット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
、特に。セクション5を参照してください。Documentation/input/event-codes.txt
、各種イベントの説明など下記のEV_SYN
内容を参考にしてください。SYN_DROPPED
Documentation/input
...ご希望の場合は、残りの部分もお読みください。