/usr/include/linux/joystick.hを見るとだいたいのことは書いてある。
- /dev/input/js*を普通にopenで開く(fopenはバッファしちゃうのでダメ)
- js_event構造体へ8bytes読む(sizeofで比較してもいいけどsizeofは符号なし)
- 状態に何も変化がないとデータは出て来なくてreadはブロックされるのでselectかpoll使うなりpthread使うなり(個人的にはpthreadの方がいいと思う)
- タイムスタンプについては省略
- .typeメンバがイベントタイプ
- アナログスティックの時は.typeがJS_EVENT_AXISで.numberメンバに軸番号が、.valueメンバに16bits符号付き整数で値が入ってる
- ボタンの時は.typeがJS_EVENT_BUTTONで.numberメンバにボタン番号が、.valueメンバに状態が入ってる
ただし!
.typeメンバにはJS_EVENT_INITがorされている。
このビットマスクは最初の値の時にorされるのだが、リラティブデータでなければ要らないので~JS_EVENT_INITをandして除去する。でないと.typeをswitchかなんかで比較してるとスティックを動かすまで入力がうまく認識されないことがある。これ、Wineがやらかしてるのよな。
実際のコードはこんな感じ。 https://github.com/tarosuke/toolbox に置いてあるものの一部(ライセンスはGPL3)。
joystick.cc
void JOYSTICK::JSThread(){
for(;; pthread_testcancel()){
struct js_event ev;
if(8 == read(device, &ev, sizeof(ev))){
switch(ev.type & ~JS_EVENT_INIT){
case JS_EVENT_AXIS :
if(ev.number < maxAxis){
axis[ev.number] = ev.value;
}
break;
case JS_EVENT_BUTTON :
if(ev.value){
buttons |= 1U << ev.number;
}else{
buttons &= ~(1U << ev.number);
}
break;
}
}
}
}