新产品(一款android智能机顶盒)需要支持2.4G无线游戏手柄,这款游戏手柄是一个接收头、双手柄的配置。客户反馈游戏摇杆的按键有问题,两个手柄同时将摇杆拉到上方,应用程序的onKeyDown事件中KEYCODE_UP有丢失。对游戏手柄一无所知,从头了解。
先用ubuntu调试。先把2.4g接收头插入PC上的usb接口,dmesg发现这是个hidraw设备,有两个设备节点被创建了:/dev/input/js0,/dev/input/js1。google下“linux游戏手柄驱动”,果然发现大把示例代码。到网上下载游戏手柄的驱动程序。编译成可执行文件,cc -o my_joystick my_joystick.c listop.c -lm。运行./my_joystick,开始验证,可以收到按键和摇杆的事件。下载地址(http://download.csdn.net/detail/special_lin/6286457)。
手柄驱动的关键代码:
rc = ioctl(fd, JSIOCGAXES, &number_of_axes); //获取手柄摇杆轴数
rc = ioctl(fd, JSIOCGBUTTONS, &number_of_btns); //获取手柄摇杆按键个数
i4_rd_bytes = read(i4_fd, &jse, sizeof(struct js_event)); //读手柄输入数据
if (jse.type == JS_EVENT_BUTTON){ //按键事件
// ...
}
else if (jse.type == JS_EVENT_AXIS) { //摇杆事件
//...
}
看驱动代码大致了解了手柄的工作原理。我们使用的Android系统的linux kernel中一般会集成主流设备的驱动程序。以JS_EVENT_AXIS为线索,果然找到了内核选项INPUT_JOYSTICK。也就是这个选项打开的时候,内核已经支持手柄设备了。
再看Framework中的InputReader,有一个专门处理手柄的类,JoystickInputMapper。当InputEvent 发上来数据的时候,交由JoystickInputMapper处理,JoystickInputMapper在sync的时候,将摇杆事件包装成为Android的motion事件。当motion事件没有被用户处理到的时候,才会被转换为key event。如何转换的,这部分代码还没有看,转换的逻辑应该有一些问题,导致有些Key事件发不出来。但是可以确定的是,需要在onGenericMotionEvent处理手柄摇杆事件。
时间紧张,只能简单记录。有时键再来回头详细看这个问题。