2.3.7. 吃鸡王座

  • 本案例主要用于吃鸡王座的实现,开手机蓝牙连接设备,将键盘鼠标分别接到usb 0 usb1。 枚举成功后键鼠的灯会亮。 也可使用AOA有线模式连接安卓手机,此时需要两个芯片,使用一个双usb芯片解析键鼠,通过串口发送键鼠数据给另一个芯片,系统框图如下

    如果不需要有线模式,可以省略芯片2,增加一个模拟开关用于激活MTK平台的手机。

  • 吃鸡王座SDK。支持默认布局的和平精英游戏。按键映射如下:

    • F1 连发模式开关

    • F2 压枪开关

    • F3 加快开枪速度

    • F4 降低开枪速度

    • F5 增加压枪力度

    • F6 降低压枪力度

  • 支持板级:bd19 、br23 支持芯片:AC6328、AC6321A

2.3.7.1. 吃鸡王座case使用

  • 打开/fw-AC63_BT_SDK-ac63_bt_sdk_release_vx.x.x/apps/hid/board/bd19下的AC632N_hid.cbp即可打开工程

  • 使用快捷键Alt + g 打开app_config.h,配置CONFIG_APP_GAMEBOX使能

//app case 选择,只选1,要配置对应的board_config.h
#define CONFIG_APP_GAMEBOX                  1//吃鸡王座
  • 使用快捷键Alt + g 打开board_config.h,板级选择CONFIG_BOARD_AC635N_DEMO

/*
 *  板级配置选择
 */

#define CONFIG_BOARD_AC632N_DEMO
  • 按照 :HID DEMO说明 编译下载代码、接线(接线参考下列)、复位设备,再使用手机搜索设备进行连接。

    USB 配置: (board_ac632n_demo_cfg.h)。

    //********************************************************************//
    USB 配置12. #define TCFG_PC_ENABLE DISABLE_THIS_MOUDLE //PC 模块使能
    #define TCFG_UDISK_ENABLE DISABLE_THIS_MOUDLE //U 盘模块使能
    #define TCFG_HID_HOST_ENABLE ENABLE_THIS_MOUDLE//游戏盒子模式
    #define TCFG_ADB_ENABLE ENABLE_THIS_MOUDLE
    #define TCFG_AOA_ENABLE ENABLE_THIS_MOUDLE
    
  • 开发者在具有吃鸡王座样机(可以是一块bd19开发板)并在烧录代码后通过两个USB分别连接鼠标和键盘之后,再打开手机蓝牙搜索连接吃鸡王座样机即可进行相应操作。

2.3.7.2. 主要代码说明

事件的处理:

  • 本案例中主要的事件处理包括 usb 拔插,MTK 普通 adb 激活模式手机拔插事件。鼠标移动点击, 键盘按键。

    • usb事件处理(gamebox.c)

    static void usb_event_handler(struct sys_event *event, void *priv)
    {
        const char *usb_msg;
        usb_dev usb_id;
    
        switch ((u32)event->arg) {
        case DEVICE_EVENT_FROM_OTG:
            usb_msg = (const char *)event->u.dev.value;
            usb_id = usb_msg[2] - '0';
    
            log_debug("usb event : %d DEVICE_EVENT_FROM_OTG %s",
                      event->u.dev.event, usb_msg);
    
            if (usb_msg[0] == 'h') {
                if (event->u.dev.event == DEVICE_EVENT_IN) {
                    log_info("usb %c online", usb_msg[2]);
                    if (usb_host_mount(usb_id, 3, 20, 250)) {
                        usb_h_force_reset(usb_id);
                        usb_otg_suspend(usb_id, OTG_UNINSTALL);
                        usb_otg_resume(usb_id);
                    }
                } else if (event->u.dev.event == DEVICE_EVENT_OUT) {
                    log_info("usb %c offline", usb_msg[2]);
                    set_phone_connect_status(0);
                    usb_host_unmount(usb_id);
                }
            } else if (usb_msg[0] == 's') {
    #if TCFG_PC_ENABLE
                if (event->u.dev.event == DEVICE_EVENT_IN) {
                    usb_start(usb_id);
                } else {
                    usb_stop(usb_id);
                }
    #endif
            }
            break;
        case DEVICE_EVENT_FROM_USB_HOST:
            log_debug("host_event %x", event->u.dev.event);
            if ((event->u.dev.event == DEVICE_EVENT_IN) ||
                (event->u.dev.event == DEVICE_EVENT_CHANGE)) {
                int err = os_taskq_post_msg(TASK_NAME, 2, DEVICE_EVENT_IN, event->u.dev.value);
                if (err) {
                    r_printf("err %x ", err);
                }
            } else if (event->u.dev.event == DEVICE_EVENT_OUT) {
                log_error("device out %x", event->u.dev.value);
            }
            break;
        }
    }
    
    • 鼠标事件处理:处理中间键消息, 指针模式,触摸模式切换。(gamebox.c)

    void mouse_route(const struct mouse_data_t *p)
    {
        if (get_run_mode() != UART_MODE) {
            if (mouse_filter((void *)p) == 0) {
                return;
            }
        }
        /* log_info("btn: %x x-y %d %d wheel %d ac_pan %d",  */
        /*         p->btn, p->x, p->y, p->wheel, p->ac_pan); */
        switch (get_run_mode()) {
        case UART_MODE ://在USB中断函数调用
            send2uart(MOUSE_POINT_MODE, p);
            break;
        case BT_MODE ://在uart中断 或者usb中断函数调用
        case USB_MODE://在串口中断调用
            if (is_mouse_point_mode) {
                send2phone(MOUSE_POINT_MODE, p);
            } else {
                mouse_mapping(p);
                send2phone(TOUCH_SCREEN_MODE, p);
            }
            break;
        case MAPPING_MODE:
            send2phone(MOUSE_POINT_MODE + 1, p);
            break;
        default :
            log_info("btn: %x x-y %d %d wheel %d ac_pan %d",
                     p->btn, p->x, p->y, p->wheel, p->ac_pan);
            break;
        }
    }
    
    • 键盘数据处理。(gamebox.c)

    void keyboard_route(const u8 *p)
    {
        /* log_info("keyboard:"); */
        /* printf_buf(p, 8); */
        if (keyboard_filter((struct keyboard_data_t *)p) == 0) {
            return;
        }
    
        switch (get_run_mode()) {
        case UART_MODE ://在USB中断函数调用
            send2uart(KEYBOARD_MODE, p);
            break;
        case BT_MODE ://在uart接收事件 或者usb中断函数调用
        case USB_MODE://在串口事件调用
            key_mapping((const void *)p);
            send2phone(TOUCH_SCREEN_MODE, p);
            break;
        case MAPPING_MODE:
            send2phone(KEYBOARD_MODE, p);
            break;
        default :
            printf_buf((u8 *)p, 8);
            break;
        }
    }
    

Adb 激活 MTK 手机:

#define     APP_ACTIVITY_PATH   "com.zh-jieli.gmaeCenter/com.zh-jieli.gameCenter.activity.guide.SplashActivity\n"
#define     APP_WEBSITE         "http://www.zh-jieli.com\n"
#define     APP_BASH_IN_PATH    "/sdcard/jilei/active.bash"
#define     APP_BASH_OUT_PATH   "/data/local/tmp/active.bash"

u32 adb_game_active()
{
    log_info("%s() %d\n", __func__, __LINE__);
    u32 max_len = adb.max_len;;
    u8 *adb_buffer = adb.buffer;
    //1,启动app
    adb_ex_cmd("am start -n " APP_ACTIVITY_PATH, adb_buffer, max_len);
    puts((char *)adb_buffer);
    //查找Error字符串,如果找到跳转网页下载app,否则执行adb指令
    if (strstr((const char *)adb_buffer, "Error") != NULL) {
        adb_ex_cmd("am start -a android.intent.action.VIEW -d " APP_WEBSITE, adb_buffer, max_len);
        puts((char *)adb_buffer);
    } else {
        adb_ex_cmd("dd if=" APP_BASH_IN_PATH " of=" APP_BASH_OUT_PATH "\n", adb_buffer, max_len);
        puts((char *)adb_buffer);
        adb_ex_cmd("chown shell " APP_BASH_OUT_PATH";chmod 777 "APP_BASH_OUT_PATH "\n", adb_buffer, max_len);
        puts((char *)adb_buffer);
        adb_ex_cmd("trap \"\" HUP;sh "APP_BASH_OUT_PATH "&\n", adb_buffer, max_len);
        puts((char *)adb_buffer);
    }

    return 0;
}

按键映射

  • 在这个函数里面处理按键映射(gamebox.c)。

    void key_mapping(const struct keyboard_data_t *k)
    {
        if (get_phone_connect_status() == 0) {
            return;
        }