织梦CMS - 轻松建站从此开始!

罗索实验室

当前位置: 主页 > 嵌入式开发 > Android >

JoyStick for android2.3 游戏手柄功能开发

落鹤生 发布于 2012-07-25 10:31 点击:次 
买了个Logitech 的游戏手柄Gamepad F310需要移植到android系统中,所以花了两天时间详细预研一下需要主要开发的逻辑过程。可参考android4.0代码,这个版本已经完整的支持这个功能了,移植主要的eventhub.cpp文件及inputreader中的JoystickInputMapper 即可
TAG:

买了个Logitech 的游戏手柄Gamepad F310需要移植到android系统中,所以花了两天时间详细预研一下需要主要开发的逻辑过程。

1、首先在pc和linux上测试:

     pc上需要安装Logitech公司的驱动程序

     针对普通linux平台上安装情况:

ubuntu 下使用游戏手柄:
1, 安装手柄驱动:
# modprobe joydev
2. 安装手柄测试软件:
# sudo apt-get install joystick
3. 测试手柄:
# jstest /dev/js0
或者
# jstest /dev/input/js0

2、使用usb直连方式,首先必须能够检测到设备,使用linux kernel2.6.35版本,配置如下:

      make menuconfig 

      General setup --->

Device Drivers --->

Input  device support -->

主要配置如下:

最重要的配置是: JoyStick interface 

这里最重要是是X-Box gamepad support 

基本上加了如上的一些配置后,插上usb joystick 可以工作了,我的工作log如下:

修改了kernel配置,目前可以正常工作了:
$ usb 1-2.2: new full speed USB device using hiusb-ehci and address 4
usb 1-2.2: New USB device found, idVendor=046d, idProduct=c21d
usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-2.2: Product: Gamepad F310
usb 1-2.2: Manufacturer: Logitech
usb 1-2.2: SerialNumber: 991241BC
input: Generic X-Box pad as /devices/platform/hiusb-ehci.0/usb1/1-2/1-2.2/1-2.2:1.0/input/input1


插上时:
$ ls -l
crw-rw---- root     input     13,  65 1970-01-02 08:02 event1
crw-rw---- root     input     13,   0 1970-01-02 08:02 js0
crw-rw---- root     input     13,  64 1970-01-01 08:00 event0
crw-rw---- root     input     13,  32 1970-01-01 08:00 mouse0
crw-rw---- root     input     13,  63 1970-01-01 08:00 mice


拔掉以后:
$ ls -l
crw-rw---- root     input     13,  64 1970-01-01 08:00 event0
crw-rw---- root     input     13,  32 1970-01-01 08:00 mouse0
crw-rw---- root     input     13,  63 1970-01-01 08:00 mice

明显多了两个设备结点js0及event1 ,这此就是针对joystick设备的读取结点名称

在android中可以使用getevent使用getevent可以最直接地获得按键的扫描码,对于Android系统中用户输入设备的调试,可以从源头确定底层输入设备传递上来的信息。

代码在/system/core/toolbox/getevent.c代码中

# getevent
getevent
add device 1: /dev/input/event1
  name:     "Generic X-Box pad"
could not get driver version for /dev/input/js0, Invalid argument
add device 2: /dev/input/event0
  name:     "Hi3716_keypad"
could not get driver version for /dev/input/mouse0, Not a typewriter
could not get driver version for /dev/input/mice, Not a typewriter

        node       type code  value 

EV_KEY + key code + up/down
/dev/input/event1: 0001 0133 00000001   // X button
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0001 0133 00000000
/dev/input/event1: 0000 0000 00000000


/dev/input/event1: 0001 0134 00000001   // Y button
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0001 0134 00000000   
/dev/input/event1: 0000 0000 00000000


/dev/input/event1: 0001 0131 00000001 // E button
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0001 0131 00000000
/dev/input/event1: 0000 0000 00000000


/dev/input/event1: 0001 0130 00000001   // A button
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0001 0130 00000000
/dev/input/event1: 0000 0000 00000000


/dev/input/event1: 0001 0116 00000001   // Back button
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0001 0116 00000000
/dev/input/event1: 0000 0000 00000000


dev/input/event1: 0001 013b 00000001   // Start button
dev/input/event1: 0000 0000 00000000
dev/input/event1: 0001 013b 00000000
dev/input/event1: 0000 0000 00000000

EV_ABS + scan code + axis 
/dev/input/event1: 0003 0001 ffff8000   // 上
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0001 ffffff7f
/dev/input/event1: 0000 0000 00000000


/dev/input/event1: 0003 0001 00007fff   // 下
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0001 ffffff7f
/dev/input/event1: 0000 0000 00000000


/dev/input/event1: 0003 0000 ffff8000   // 左
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0000 00000080
/dev/input/event1: 0000 0000 00000000


/dev/input/event1: 0003 0000 00007fff   // 右
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0000 00000080
/dev/input/event1: 0000 0000 00000000

简音的测试case代码:

  1. #include <linux/input.h> 
  2. #include <linux/joystick.h> 
  3.  
  4. int main(void) { 
  5.     int js_fd; 
  6.     struct js_event js; 
  7.     int n, type = 0; 
  8.     int axis_value, button_value; 
  9.     int number_of_axis, number_of_buttons; 
  10.  
  11.     js_fd = open("/dev/input/js0", O_RDONLY); //打开 设备文件 
  12.     if (js_fd == NULL) { 
  13.         printf("open joystick device failed"); 
  14.         return -1; 
  15.     } 
  16.  
  17.     while (1) { 
  18.         n = read(js_fd, &js, sizeof(struct js_event)); 
  19.         if (n < 0 || n != sizeof(struct js_event)) { 
  20.             printf("read data failed"); 
  21.             usleep(10 * 1000); 
  22.             continue
  23.         } 
  24.  
  25.         type = js.type & (~JS_EVENT_INIT); 
  26.         switch (type) { 
  27.         case JS_EVENT_AXIS: 
  28.             number_of_axis = js.number; 
  29.             axis_value = js.value; 
  30.             printf("number:%2d:value:%6d\n", number_of_axis, axis_value); 
  31.             break
  32.         case JS_EVENT_BUTTON: 
  33.             number_of_buttons = js.number; 
  34.             button_value = js.value; 
  35.             printf("number:%2d:value:%2d\n", number_of_buttons, button_value); 
  36.             break
  37.         } 
  38.         usleep(10 * 1000); 
  39.     } 
  40.  
  41.     return 0; 

3、框架代码修改

      可参考android4.0代码,这个版本已经完整的支持这个功能了,移植主要的eventhub.cpp文件及inputreader中的JoystickInputMapper 即可:

如下:

    // See if this device is a joystick.
    // Assumes that joysticks always have gamepad buttons in order to distinguish them
    // from other devices such as accelerometers that also have absolute axes.
    if (haveGamepadButtons) {
        uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
        for (int i = 0; i <= ABS_MAX; i++) {
            if (test_bit(i, device->absBitmask)
                    && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
                device->classes = assumedClasses;
                break;
            }
        }
    }

 

一般的按键button走KeyboardInputMapper流程,只有对于EV_ABS的Axis() 使用这个JoystickInputMapper处理。

 

补充说明:

1、获取手柄的一些额外参数:

ioctl(fd, JSIOCGAXES, &number_of_axes);  //游戏轴数目,默认情况下轴0,1,2代表x轴,y轴,z轴

ioctl(fd, JSIOCGBUTTONS, &number_of_btns); // 游戏按扭数目

ioctl(fd, JSIOCGNAME(sizeof(js_name_str)), js_name_str); // 游戏手柄名称

 

2、数值,读取jsX时轴值:

轴值范围: -32767 ~ 32767  

比如:

  1. int *axis = NULL; 
  2. int *button = NULL; 
  3. struct js_event jse; 
  4. axis = (int*)calloc(number_of_axes,sizeof(int)); 
  5. button = (int*)calloc(number_of_btns,sizeof(int); 
  6.  
  7. read(fd,&jse,sizeof(struct js_event)); 
  8. switch(jse.type & ~JS_EVENT_INIT) 
  9. case JS_EVENT_AXIS: 
  10. if ((jse->number & 1) == 0) { 
  11. axes[jse.number / 2].x = jse.value; 
  12. else { 
  13. axes[jse.number / 2].y = jse.value; 
  14. break
  15. case JS_EVENT_BUTTON: 
  16. if (jse->value) { 
  17. buttons_state |= (1 << jse->number); 
  18. else { 
  19. buttons_state &= ~(1 << jse->number); 
  20. break
  21. default
  22. break

3、读取eventX -- 由joystick设备产生的数值:


EV_ABS + code + axis 

分析如下:

首先表示其type = EV_ABS 绝对值 , code值代表x轴(0),y轴(1),z轴值(2),value代表坐标值,这里会涉及到相应的值转换问题,走AMOTION_EVENT_ACTION_MOVE路线。

核心代码如下:

  1. switch (rawEvent->type) { 
  2.     case EV_ABS: { 
  3.         ssize_t index = mAxes.indexOfKey(rawEvent->scanCode); 
  4.         if (index >= 0) { 
  5.             Axis& axis = mAxes.editValueAt(index); 
  6.             float newValue, highNewValue; 
  7.             switch (axis.axisInfo.mode) { 
  8.             case AxisInfo::MODE_INVERT: 
  9.                 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value) 
  10.                         * axis.scale + axis.offset; 
  11.                 highNewValue = 0.0f; 
  12.                 break
  13.             case AxisInfo::MODE_SPLIT: 
  14.                 if (rawEvent->value < axis.axisInfo.splitValue) { 
  15.                     newValue = (axis.axisInfo.splitValue - rawEvent->value) 
  16.                             * axis.scale + axis.offset; 
  17.                     highNewValue = 0.0f; 
  18.                 } else if (rawEvent->value > axis.axisInfo.splitValue) { 
  19.                     newValue = 0.0f; 
  20.                     highNewValue = (rawEvent->value - axis.axisInfo.splitValue) 
  21.                             * axis.highScale + axis.highOffset; 
  22.                 } else { 
  23.                     newValue = 0.0f; 
  24.                     highNewValue = 0.0f; 
  25.                 } 
  26.                 break
  27.             default
  28.                 newValue = rawEvent->value * axis.scale + axis.offset; 
  29.                 highNewValue = 0.0f; 
  30.                 break
  31.             } 
  32.             axis.newValue = newValue; 
  33.             axis.highNewValue = highNewValue; 
  34.         } 
  35.         break
  36.     } 
  37.  
  38.     case EV_SYN: 
  39.         switch (rawEvent->scanCode) { 
  40.         case SYN_REPORT: 
  41.             sync(rawEvent->when, false /*force*/); 
  42.             break
  43.         } 
  44.         break
  45.     } 

 

(andyhuabing)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www1.rosoo.net/a/201207/16180.html]
本文出处:CSDN博客 作者:andyhuabing 原文
顶一下
(5)
100%
踩一下
(0)
0%
------分隔线----------------------------
相关文章
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容