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; }