2.3.6. 翻页器
本 APP 基于 HID 开发,主要用于浏览当下火爆的抖音等小视频的上下翻页、左右菜单切换、暂 停等操作。首先选择需要用到的应用本案例选择,然后进行对应的支持板级选择,具体参考下文的 步骤。通过软件编译下载到对应的开发板,打开手机蓝牙进行连接,进入视频浏览界面操作对应按 键即可。
支持的板级: br25、br23、bd19、br34 支持的芯片: AC636N、AC635N、AC638N
2.3.6.1. 翻页器case使用
使用快捷键Alt + g 打开app_config.h,配置CONFIG_APP_KEYFOB使能
//app case 选择,只选1,要配置对应的board_config.h #define CONFIG_APP_KEYPAGE 1//翻页器
使用快捷键Alt + g 打开board_config.h,板级选择CONFIG_BOARD_AC632N_DEMO
#define CONFIG_BOARD_AC632N_DEMO // CONFIG_APP_KEYBOARD,CONFIG_APP_PAGE_TURNER // #define CONFIG_BOARD_AC6321A_MOUSE // CONFIG_APP_MOUSE
按照 :HID DEMO说明 编译下载代码、接线、复位设备,再使用手机搜索设备进行连接。
开发者可以操作板子AD key实现蓝牙翻页器的功能。
2.3.6.2. 主要代码说明
APP注册运行(函数位于apps/hid/app_keypage.c):
在系统进行初始化的过程中,根据以下信息进行APP注册。执行的大致流程为:REGISTER_APPLICATION—>state_machine—>app_start()—>sys_key_event_enable();这条流程主要进行设备的初始化设置以及一些功能使能。
REGISTER_APPLICATION—>event_handler—>app_key_event_handler()—>app_key_deal_test();这条流程在event_handler之下有多个case,上述选择按键事件的处理流程进行代码流说明,主要展示按键事件发生时,程序的处理流程。
REGISTER_LP_TARGET(app_hid_lp_target) = { .name = "app_keypage", .is_idle = app_hid_idle_query, }; static const struct application_operation app_hid_ops = { .state_machine = state_machine, .event_handler = event_handler, }; * 注册模式 REGISTER_APPLICATION(app_hid) = { .name = "keypage", .action = ACTION_KEYPAGE, .ops = &app_hid_ops, .state = APP_STA_DESTROY, };
APP状态机:
状态机有create,start,pause,resume,stop,destory状态,根据不同的状态执行对应的分支。APP注册后进行初始运行,进入APP_STA_START分支,开始APP运行。
static int state_machine(struct application *app, enum app_state state, struct intent *it) { switch (state) { case APP_STA_CREATE: break; case APP_STA_START: if (!it) { break; } switch (it->action) { case ACTION_TOUCHSCREEN: app_start();
进入app_start()函数后进行对应的初始化,时钟初始化,模式选择,低功耗初始化,以及外部事件使能。
static void app_start() { log_info("======================================="); log_info("-----------------------------KEYPAGE------------------------"); log_info("=======================================");
APP 事件处理机制:
事件的定义(代码位于Headersinclude_libsystemeven.h中)
struct sys_event { u16 type; u8 consumed; void *arg; union { struct key_event key; struct axis_event axis; struct codesw_event codesw;
事件的产生(include_libsystemevent.h)
void sys_event_notify(struct sys_event *e);事件通知函数,系统有事件发生时调用此函数。
事件的处理(app_keypage.c)
函数执行的大致流程为:evevt_handler()—>app_key_event_handler()—>app_key_deal_test().
static int keypage_event_handler(struct application *app, struct sys_event *event) { #if (TCFG_HID_AUTO_SHUTDOWN_TIME) //重置无操作定时计数 sys_timer_modify(g_auto_shutdown_timer, TCFG_HID_AUTO_SHUTDOWN_TIME * 1000); #endif static void keypage_key_event_handler(struct sys_event *event) { /* u16 cpi = 0; */ u8 event_type = 0; u8 key_value = 0; if (event->arg == (void *)DEVICE_EVENT_FROM_KEY) { event_type = event->u.key.event; key_value = event->u.key.value; printf("app_key_evnet: %d,%d\n", event_type, key_value); app_key_deal_test(event_type, key_value); } } static void keypage_app_key_deal_test(u8 key_type, u8 key_value) { u16 key_msg = 0; void (*hid_data_send_pt)(u8 report_id, u8 * data, u16 len) = NULL; log_info("app_key_evnet: %d,%d\n", key_type, key_value); }
数据发送:
当APP注册运行后,有按键事件发生时,会进行对应的数据发送,由于是HID设备,所以数据的发送形式从对应的HID设备的描述符产生。用户如需要对设备进行功能自定义,可以结合HID官方文档对下述描述符进行修改。部分描述符如下:(app_keypage.c)
static const u8 hid_report_map[] = { // 119 bytes 0x05, 0x0D, // Usage Page (Digitizer) 0x09, 0x02, // Usage (Pen) 0xA1, 0x01, // Collection (Application) 0x85, 0x01, // Report ID (1) 0x09, 0x22, // Usage (Finger) 0xA1, 0x02, // Collection (Logical) 0x09, 0x42, // Usage (Tip Switch) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x01, // Report Count (1) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x09, 0x32, // Usage (In Range) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x06, // Report Count (6) 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x75, 0x08, // Report Size (8) 0x09, 0x51, // Usage (0x51) 0x95, 0x01, // Report Count (1) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) static const u8 pp_press[7] = {0x07,0x07,0x70,0x07,0x70,0x07,0x01}; //暂定按键对应的HID发送数据包 static const u8 pp_null[7]= {0x00,0x07,0x70,0x07,0x70,0x07,0x00};
上列为暂停按键对应的HID设备发送数据包,通过下面的hid_data_send_pt()进行数据传输(app_keypage.c)。
log_info("point: %d,%d", point_cnt, point_len); if (point_cnt) { for (int cnt = 0; cnt < point_cnt; cnt++) { hid_data_send_pt(1, key_data, point_len); key_data += point_len; KEY_DELAY_TIME(); } }由描述符可知,设备一共有5个输入实体Input,一共组成7byte的数据,所以对应的暂停按键数据包由7byte的数据组成,前2byte表示识别是否有触摸输入,中间2个2byte分别表示y坐标和x坐标,最后1byte表示contact count,不同的按键事件对应不同的数据包,数据通过hid_data_send_dt函数发送至设备。对应的按键事件通过事件处理机制和数据发送实现对应的功能。
增加处理公共消息
跟据识别不同的手机系统,来切换描述符(app_keypage.c)。
static int keypage_common_event_handler(struct bt_event *bt) { log_info("--------keypage_common_event_handler: %02x %02x", bt->event, bt->value); switch (bt->event) { case COMMON_EVENT_EDR_REMOTE_TYPE: log_info(" COMMON_EVENT_EDR_REMOTE_TYPE \n"); connect_remote_type = bt->value; if (connect_remote_type == REMOTE_DEV_IOS) { user_hid_set_ReportMap(hid_report_map_ios, sizeof(hid_report_map_ios)); } else { user_hid_set_ReportMap(hid_report_map, sizeof(hid_report_map)); } break; case COMMON_EVENT_BLE_REMOTE_TYPE: log_info(" COMMON_EVENT_BLE_REMOTE_TYPE \n"); connect_remote_type = bt->value;