接続デバイスを見つける
バーコードリーダーやUSBキーボードつなげて使いたい場合、デバイスファイル/dev/input/event?
を
読む方法が良いようです。
まず接続した機器のデバイスファイルを見つけねばなりませんが、これには
# cat /proc/bus/usb/devices
でManufacturer/Productなどの詳細な情報が取得できますし、機器を接続すると/dev/input
以下に
by-id
やby-path
ディレクトリが作られて、例えば
/dev/input/by-id/usb-DELL_Dell_USB_Entry_Keyboard-event-kbd
とか
/dev/input/by-id/usb-Honeywell_Imaging___Mobility_1900_12114B1E4F-event-kbd
といった名前で/dev/input/event?
へのシンボリックリンクが作られますので
この名前で判定して参照しても良いと思います。
リード方法
デバイスファイル/dev/input/event?
をリードするとlinux/input.h
で定義されている
struct input_event
の形でイベントが上がってきますが、これはキーボードのキーコードと、
押されたか離されたかの種別、といったもので、キーコードの意味は日本語キーボードと英語キーボード
で異なります(バーコードリーダーは英語キーボードのキーコードを送ってくる様です)。
また、キーコードであって文字列そのものではないため、最低限SHIFTキーが押された状態か
否かの判断が必要になります。
これらを考慮したCコードは以下の様になりました。
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#define KT6070 "\0\0\0\0\0\0\0\0\0\0" "\0789-456+1" "230.";
#ifdef JP109
static char keytbl0[] =
"\0\03312345678" "90-^\b\tqwer" "tyuiop@[\n\0" "asdfghjkl;" ":\0\0]zxcvbn" "m,./\0*\0 \0\0"
KT6070;
static char keytbl1[] =
"\0\033!\"#$%&'(" ")_=~\b\tQWER" "TYUIOP`{\n\0" "ASDFGHJKL+" "*\0\0}ZXCVBN" "M<>?\0*\0 \0\0"
KT6070;
#else
static char keytbl0[] =
"\0\03312345678" "90-=\b\tqwer" "tyuiop[]\n\0" "asdfghjkl;" "'`\0\\zxcvbn" "m,./\0*\0 \0\0"
KT6070;
static char keytbl1[] =
"\0\033!@#$%^&*" "()_+\b\tQWER" "TYUIOP{}\n\0" "ASDFGHJKL:" "\"~\0|ZXCVBN" "M<>?\0*\0 \0\0"
KT6070;
#endif
static char rems[][3] = {
{KEY_YEN, '\\', '|'},
{KEY_RO, '\\', '_'},
{KEY_KPJPCOMMA, ',', ','},
{KEY_KPENTER, '\n', '\n'},
{KEY_KPSLASH, '/', '/'},
{KEY_KPEQUAL, '=', '='},
{KEY_KPCOMMA, ',', '='},
};
static int search_rems(int c, int shft)
{
int j;
for (j = 0; j < sizeof(rems)/sizeof(*rems); j++) {
if (rems[j][0] == c) {
return (shft) ? rems[j][2] : rems[j][1];
}
}
return -1;
}
int dev_input_read_loop(int addc)
{
int shft = 0;
for (;;) {
struct input_event ev;
if (read(0, &ev, sizeof(ev)) != sizeof(ev)) {
exit(EXIT_FAILURE);
}
/**
printf("%d.%d type=%d value=%d code=%d\n",
ev.time.tv_sec, ev.time.tv_usec,
ev.type, ev.value, ev.code);
**/
int c, v, k;
switch(ev.type) {
case EV_KEY:
c = ev.code;
v = ev.value;
if ((c == KEY_LEFTSHIFT)||(c == KEY_RIGHTSHIFT)) {
shft = v;
continue;
}
//if (v != 1) { // ignore key up and key repeat
if (v == 0) { // ignore key up
continue;
}
if ((0 < c)&&(c < sizeof(keytbl0))&&(c < sizeof(keytbl1))) {
k = shft ? keytbl1[c] : keytbl0[c];
if (k) {
putchar(k);
} else {
printf("(%d)", c);
}
} else if (0 < (k = search_rems(c, shft))) {
putchar(k);
} else {
printf("(%d)", c);
}
if (addc) {
putchar(addc);
}
break;
default:
break;
}
}
}
int main(int argc, char **argv)
{
int addc = 0;
char *argv1 = argv[1];
if ((1 < argc)&&('-' == argv1[0])&&('n' == argv1[1])) {
addc = '\n';
}
dev_input_read_loop(addc);
}
手探りで動作を見ながら修正した部分や手元の部材の関係で十分に動作確認できていない部分がありますので
ご注意ください。
-DJP109をつけてコンパイルすると日本語キーボード用になり、つけないとバーコードリーダー用になります。
♯ ./a.out < /dev/input/event?
とすると、バーコードを読み込むごと、またはキーボードでENTERを押すごとに入力内容が表示されます。
即時性が必要な場合を考えて、
♯ ./a.out -n < /dev/input/event?
とすると一行ではなく一文字入力ごとに表示される(改行を付加する)機能だけ付けたのですが、それならば
今はキーダウンしか見ていないがキーアップが必要な場合もあるのではないかとか、キーリピートが
必要な場合と不要な場合とあるだろうとか、きりがないのでこれ以上はやめました。
キーボードの場合にはどのような使い方をするのかによって個々にカスタマイズしてください。
また、pythonの場合にはstructモジュールでcの構造体データを扱えます。
参考:python – format of /dev/input/event*? – Stack Overflow
PaPeRo iのアプリに組み込む場合、この処理をスレッド化し、バーコードリーダーやキーボードから入力された
データをメッセージでメインスレッドに送るといった方法を取ることになります。