Linuxでデバイスファイルからマウスのイベントを取得するメモ
デバイスの確認
/proc/bus/input/devices
で認識されている各デバイスを確認できる。
$ cat /proc/bus/input/devices
~前略~
I: Bus=0001 Vendor=80ee Product=cafe Version=0500
N: Name="VirtualBox mouse integration"
P: Phys=
S: Sysfs=/devices/pci0000:00/0000:00:04.0/input/input7
U: Uniq=
H: Handlers=event6 js1
B: PROP=0
B: EV=b
B: KEY=10000 0 0 0 0
B: ABS=3
上記の例だと、Handler
に記載されている event6
, js1
が、/dev/input
以下にデバイスファイルとして作成される。
入力の確認
ターミナルで出力できる文字列としては出力されないため、od
, hexdump
等を使用して内容を確認する。
マウスを動かしてみると入力が入ってくることが確認できる。
$ sudo cat /dev/input/event6 | od -t x1
0000000 66 db 86 58 00 00 00 00 68 fd 07 00 00 00 00 00
0000020 03 00 01 00 c9 69 00 00 66 db 86 58 00 00 00 00
0000040 68 fd 07 00 00 00 00 00 00 00 00 00 00 00 00 00
0000060 66 db 86 58 00 00 00 00 ca 1b 08 00 00 00 00 00
...
$ sudo hexdump /dev/input/event6
0000000 db45 5886 0000 0000 de4d 0002 0000 0000
0000010 0003 0000 6d7f 0000 db45 5886 0000 0000
0000020 de4d 0002 0000 0000 0000 0000 0000 0000
0000030 db45 5886 0000 0000 fd4d 0002 0000 0000
...
入力の確認(詳細)
上の例では何かが入力されていることはわかるが、内容はさすがに読めないのでパースしてみる。
struct input_event {
struct timeval time;
unsigned short type;
unsigned short code;
unsigned int value;
};
// 厳密にはlongでそのまま定義はされてないが、
// 最終的にはlongと考えて良い
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
}
Linux/Documentation/input/input.txt - Linux Cross Reference - Free Electrons
pythonでパースしてみる。
#!/usr/bin/env python
import struct
infile_path = "/dev/input/event6"
# struct input_event {
# struct timeval time;
# unsigned short type;
# unsigned short code;
# unsigned int value;
# };
EVENT_FORMAT = "llHHI"; # long, long, unsigned short, unsigned short, unsigned int
EVENT_SIZE = struct.calcsize(EVENT_FORMAT)
with open(infile_path, "rb") as file:
event = file.read(EVENT_SIZE)
while event:
#(tv_sec, tv_usec, type, code, value) = struct.unpack(EVENT_FORMAT, event)
print struct.unpack(EVENT_FORMAT, event)
event = file.read(EVENT_SIZE)
$ sudo python test.py
(1485235334, 542364, 3, 0, 18883)
(1485235334, 542364, 3, 1, 42469)
(1485235334, 542364, 0, 0, 0)
(1485235334, 550414, 3, 0, 18849)
(1485235334, 550414, 0, 0, 0)
(1485235334, 558122, 3, 0, 18815)
(1485235334, 558122, 3, 1, 42402)
(1485235334, 558122, 0, 0, 0)
(1485235334, 574054, 3, 0, 18781)
(1485235334, 574054, 0, 0, 0)
(1485235334, 590100, 3, 0, 18747)
(1485235334, 590100, 0, 0, 0)
(1485235334, 605869, 3, 0, 18713)
(1485235334, 605869, 3, 1, 42334)
(1485235334, 605869, 0, 0, 0)
...
タイムスタンプとデータが取得できることを確認できた。
TODO
移動は取得できたが、クリックイベントや移動データに関しての読み方を追記する
python-evdev
を利用する
上では /dev/input
以下のインプットデバイスをそのままパースしたが、
Pythonではevdev interfaceを取り扱う用に python-evdev
というパッケージがある。
参考
epics/powermate-event – Epics Users JP
Linux Input Subsystemの使い方
インプットデバイスの情報を表示する - はわわーっ
device - Getting live info from /dev/input - Stack Overflow
7.3. struct — 文字列データをパックされたバイナリデータとして解釈する — Python 2.7.x ドキュメント