| /* |
| ******************************************************************************* |
| * |
| * @file rc_mmi_vkey.c |
| * |
| * @brief VKEY application part. |
| * |
| * Copyright (C) Atmosic 2020-2022 |
| * |
| ******************************************************************************* |
| */ |
| |
| #include <inttypes.h> |
| #include "app_config.h" |
| #include "rc_hogp.h" |
| |
| #ifdef CFG_VOHID |
| #include "rc_hidau.h" |
| #else |
| #include "rc_atvv.h" |
| #endif |
| #include "rc_gap.h" |
| #include "rc_mmi.h" |
| #include "rc_mmi_vkey.h" |
| #include "led_blink.h" |
| #include "rc_pdm.h" |
| #include "rc_ir.h" |
| #include "atm_debug.h" |
| #include "keyboard.h" |
| #include "co_utils.h" |
| #include "atm_asm.h" |
| #include "atm_vkey.h" |
| #include "atm_pm.h" |
| #if defined(CFG_ATVRC_CUSTOM) && defined(CFG_ATVRC_WAKEUP) |
| #include "atvrc_custom.h" |
| #endif |
| #ifdef LED_UART_MUX |
| #include "timer.h" |
| #include "at_wrpr.h" |
| #include "at_pinmux.h" |
| #include "pinmux.h" |
| #endif |
| #ifdef CFG_EN_GHOSTKEY |
| #include "keyboard_ghostkey.h" |
| #endif |
| #include "rc_keycode.h" |
| #include STR(VKEY_MAP_FILE) |
| |
| #ifdef CFG_ATVRC_FIND_ME |
| #include "buzzer.h" |
| #endif |
| |
| #ifdef CFG_ATVRC_MMI |
| #include "timer.h" |
| #include "sw_timer.h" |
| static sw_timer_id_t tid_delay_reset; |
| #define VK_MIC VK_ASST |
| #define VK_OK VK_CENTER |
| static bool wait_comb_key; |
| #endif |
| |
| STATIC_ASSERT(ARRAY_LEN(bt_keycode) <= ATM_VKEY_MAX, |
| "Vkey number exceeds ATM_VKEY_MAX"); |
| |
| #ifndef CFG_VKEY_BUF |
| static uint32_t mmi_saved_key; |
| #endif |
| static pm_lock_id_t rc_vk_lock_hiber; |
| |
| enum { |
| VKEY_TABLE_HID_NOT_READY, |
| VKEY_TABLE_HID_READY, |
| VKEY_TABLE_RF_TEST, |
| VKEY_TABLE_MAX |
| }; |
| |
| typedef struct { |
| void *handle[VKEY_TABLE_MAX]; |
| uint8_t cur_state; |
| uint8_t cur_hdl_idx; |
| } rc_mmi_vkey_ctx_t; |
| |
| #ifdef CFG_RC_IR |
| #define RC_IR_DELAY_CS 9 |
| #define RC_IR_DELAY_ON_HID_CS 6 |
| #endif |
| |
| // Time for led on while key down |
| #define KEY_DOWN_LED_INTERVAL_CS 10 |
| |
| // VKEY_DOWN_FIRST => send key down |
| static void send_rpt(atm_vk_idx_t vkey, void const *ctx) |
| { |
| rc_mmi_vkey_ctx_t const *context = ctx; |
| |
| rc_mmi_idle_timer(MMI_TOUT_START); |
| led_blink(LED_0, KEY_DOWN_LED_INTERVAL_CS, 0, 0x1); |
| if (bt_keycode[vkey] == BT_MIC) { |
| #ifdef CFG_VOHID |
| if (context->cur_state == MMI_S_HID_READY) { |
| rc_gap_local_slave_latency(true); |
| rc_hidau_start_search(); |
| } else if (context->cur_state == MMI_S_HID_STREAMING) { |
| rc_hidau_stop_search(); |
| } |
| #else // CFG_VOHID |
| // Dealing with ATVV (only allowed in ATVV ready) |
| if ((context->cur_state == MMI_S_HID_ATVV) || |
| #ifdef CFG_ATVV_VER_100 |
| (context->cur_state == MMI_S_ATVVING) || |
| #endif |
| (context->cur_state == MMI_S_ATVV_ONLY)) { |
| rc_gap_local_slave_latency(true); |
| rc_atvv_start_search(); |
| } else if (context->cur_state != MMI_S_ATVVING) { |
| DEBUG_TRACE("Peer didn't enable ATVV"); |
| } |
| if (rc_atvv_is_legacy_model()) { |
| rc_hogp_send_single_key(BT_MIC); |
| rc_hogp_send_single_key(CSM(0)); |
| #ifdef CFG_ATVRC_MMI |
| led_on(LED_0); |
| #endif |
| } else if (rc_atvv_is_htt_model()) { |
| led_on(LED_0); |
| } |
| #ifdef CFG_ATVRC_MMI |
| else { |
| led_blink(LED_0, 50, 50, 0xffff); |
| } |
| #endif |
| #endif // CFG_VOHID |
| } else { |
| #ifdef CFG_ATVRC_UNI_IR |
| if (rc_ir_check_uni_key(atv_keycode[vkey])) { |
| led_blink(LED_0, ATVRC_LED_KEY_CS, 0, ATVRC_LED_KEY_BLINK); |
| led_blink(LED_1, ATVRC_LED_KEY_CS, 0, ATVRC_LED_KEY_BLINK); |
| return; |
| } |
| #endif |
| rc_hogp_send_single_key(bt_keycode[vkey]); |
| #ifndef CFG_VOHID |
| if (bt_keycode[vkey] == BT_OK) { |
| rc_atvv_dpad_select(); |
| } |
| #endif |
| #ifdef CFG_RC_IR_ON_HID |
| rc_ir_send(ir_addr[vkey], ir_cmd[vkey], |
| RC_IR_DELAY_ON_HID_CS); |
| #endif |
| } |
| return; |
| } |
| |
| static void rc_send_rpt(atm_vk_dnup_evt_t const *evt, void const *ctx) |
| { |
| #ifdef CFG_ATVRC_FIND_ME |
| buzzer_stop(); |
| #endif |
| send_rpt(evt->top.vkey, ctx); |
| } |
| |
| static bool comb_rpt_sent; |
| static void rc_send_comb_rpt(atm_vk_dnup_inter_evt_t const *evt, |
| void const *ctx) |
| { |
| if (comb_rpt_sent) { |
| // No more combined reports until release all keys. |
| return; |
| } |
| send_rpt(evt->top.vkey, ctx); |
| comb_rpt_sent = true; |
| } |
| |
| static void rc_sent_up_(atm_vk_dnup_inter_evt_t const *evt, void const *ctx) |
| { |
| rc_mmi_idle_timer(MMI_TOUT_START); |
| rc_hogp_send_single_key(bt_keycode[evt->top.vkey] & ~0xFFFF); |
| #ifdef CFG_RC_IR_ON_HID |
| rc_ir_repeat_end(); |
| #endif |
| return; |
| } |
| |
| // VKEY_UP_LAST => send key up |
| static void rc_sent_up(atm_vk_dnup_evt_t const *evt, void const *ctx) |
| { |
| comb_rpt_sent = false; |
| rc_mmi_idle_timer(MMI_TOUT_START); |
| rc_hogp_send_single_key(bt_keycode[evt->top.vkey] & ~0xFFFF); |
| #ifdef CFG_RC_IR_ON_HID |
| rc_ir_repeat_end(); |
| #endif |
| #ifdef CFG_ATVRC_UNI_IR |
| rc_ir_repeat_end(); |
| #endif |
| #ifdef CFG_ATVRC_MMI |
| // static LED during voice search |
| if ((bt_keycode[evt->top.vkey] == BT_MIC) && !rc_atvv_is_htt_model()) { |
| return; |
| } |
| #endif |
| led_off(LED_0); |
| return; |
| } |
| |
| static void rc_mic_up(atm_vk_dnup_evt_t const *evt, void const *ctx) |
| { |
| #ifdef CFG_ATVV_VER_100 |
| if (!rc_atvv_is_htt_model()) { |
| return; |
| } |
| rc_mmi_vkey_ctx_t const *context = ctx; |
| if (context->cur_state == MMI_S_ATVVING) { |
| rc_atvv_stop_search(); |
| } |
| #endif |
| } |
| |
| #ifdef CFG_RC_IR |
| static void rc_save_key_up(atm_vk_dnup_evt_t const *evt, void const *ctx) |
| { |
| rc_ir_repeat_end(); |
| return; |
| } |
| #endif |
| |
| static bool rc_hold_test(atm_vk_hd_evt_t const *evt, void const *ctx) |
| { |
| return evt->time_ms < 4000; |
| } |
| |
| #ifdef CFG_RC_TEST_MODE |
| #include "rc_test_mode.h" |
| static void rc_ok_up(atm_vk_dnup_evt_t const *evt, void const *ctx) |
| { |
| rc_test_mode_control(RC_TEST_CANCEL); |
| } |
| |
| static void rc_ok_click(atm_vk_hc_evt_t const *evt, void const *ctx) |
| { |
| switch (evt->top.u8vkey) { |
| case VK_UP: |
| case VK_DOWN: |
| case VK_RIGHT: |
| case VK_LEFT: { |
| rc_test_input_t num; |
| if (evt->top.u8vkey == VK_UP) { |
| num = RC_TEST_U_GOT; |
| } else if (evt->top.u8vkey == VK_DOWN) { |
| num = RC_TEST_D_GOT; |
| } else if (evt->top.u8vkey == VK_RIGHT) { |
| num = RC_TEST_R_GOT; |
| } else if (evt->top.u8vkey == VK_LEFT) { |
| num = RC_TEST_L_GOT; |
| } else { |
| num = RC_TEST_CANCEL; |
| } |
| rc_test_mode_control(num); |
| } break; |
| default: |
| rc_test_mode_control(RC_TEST_CANCEL); |
| break; |
| } |
| } |
| |
| static bool rc_ok_back(atm_vk_hd_evt_t const *evt, void const *ctx) |
| { |
| return false; |
| } |
| |
| static void rc_ok_back_sts(bool pressed, void const *ctx) |
| { |
| if (pressed) { |
| rc_test_mode_control(RC_TEST_CANCEL); |
| } |
| } |
| |
| #endif |
| |
| static bool rc_del_bond(atm_vk_hd_evt_t const *evt, void const *ctx) |
| { |
| #ifdef CFG_ATVRC_MMI |
| if (sw_timer_active(tid_delay_reset)) { |
| return true; |
| } |
| #endif |
| rc_gap_remove_all_bond(); |
| led_off(LED_0); |
| #ifdef CFG_ATVRC_UNI_IR |
| rc_ir_clear_uni_codes(); |
| #endif |
| #ifdef CFG_ATVRC_MMI |
| atm_timer_mdelay(100); |
| led_blink(LED_0, ATVRC_LED_CFM_CS, ATVRC_LED_CFM_CS, ATVRC_LED_CFM_BLINK); |
| wait_comb_key = false; |
| #define ATVRC_LED_CFM_DELAY_CS (ATVRC_LED_CFM_CS * 5) |
| sw_timer_set(tid_delay_reset, ATVRC_LED_CFM_DELAY_CS); |
| #else |
| platform_reset(RESET_NO_ERROR); |
| #endif |
| return true; |
| } |
| |
| static bool rc_pair_mode(atm_vk_hd_evt_t const *evt, void const *ctx) |
| { |
| rc_gap_enter_pairing_next_boot(true); |
| led_off(LED_0); |
| platform_reset(RESET_NO_ERROR); |
| return true; |
| } |
| |
| #ifdef CFG_ATVRC_MMI |
| static void rc_comb_key_led_ctl(bool pressed) |
| { |
| if (pressed && !wait_comb_key) { |
| wait_comb_key = true; |
| led_on(LED_0); |
| } else if (!pressed && wait_comb_key) { |
| wait_comb_key = false; |
| led_off(LED_0); |
| } |
| } |
| |
| static bool rc_bug_report(atm_vk_hd_evt_t const *evt, void const *ctx) |
| { |
| DEBUG_TRACE("BUG_REPORT"); |
| wait_comb_key = false; |
| led_blink(LED_0, KEY_DOWN_LED_INTERVAL_CS, KEY_DOWN_LED_INTERVAL_CS, 2); |
| #ifdef CFG_RC_IR |
| rc_ir_send(IR_ADDR, IR_BUGR, RC_IR_DELAY_CS); |
| #endif |
| return false; |
| } |
| |
| static bool rc_access_shortcut(atm_vk_hd_evt_t const *evt, void const *ctx) |
| { |
| DEBUG_TRACE("ACCESS_SHORTCUT"); |
| wait_comb_key = false; |
| return false; |
| } |
| #endif // CFG_ATVRC_MMI |
| |
| static void rc_atvv_test(atm_vk_hc_evt_t const *evt, void const *ctx) |
| { |
| if (evt->top.u8vkey == VK_VOLUP) { |
| rc_pdm_gain_adjust(true); |
| } else if (evt->top.u8vkey == VK_VOLDN) { |
| rc_pdm_gain_adjust(false); |
| } else if (evt->top.u8vkey == VK_MIC) { |
| #ifndef CFG_VOHID |
| rc_mmi_enter_test(MMI_TEST_ATVV); |
| #endif |
| } |
| return; |
| } |
| |
| static void rc_reset(atm_vk_hc_evt_t const *evt, void const *ctx) |
| { |
| platform_reset(RESET_NO_ERROR); |
| return; |
| } |
| |
| static void rc_keytest(atm_vk_hc_evt_t const *evt, void const *ctx) |
| { |
| rc_mmi_enter_test(MMI_TEST_KEY); |
| return; |
| } |
| |
| static void rc_disconnect(atm_vk_hc_evt_t const *evt, void const *ctx) |
| { |
| rc_mmi_idle_timer(MMI_TOUT_FORCE); |
| led_off(LED_0); |
| return; |
| } |
| |
| static void rc_enter_rftest(atm_vk_hc_evt_t const *evt, void const *ctx) |
| { |
| rc_mmi_enter_test(MMI_TEST_RF); |
| return; |
| } |
| |
| #ifdef CFG_VKEY_BUF |
| #include "co_list.h" |
| #include "ke_mem.h" |
| |
| /// Report buffer |
| static struct co_list vk_buf; |
| |
| /// Vkey buffer element |
| typedef struct { |
| /// list element header |
| struct co_list_hdr hdr; |
| /// report |
| atm_vk_idx_t vkey; |
| /// ctx |
| void const *ctx; |
| } vk_elmt_t; |
| |
| static vk_elmt_t *rc_mmi_vkey_pop_from_buf(void) |
| { |
| return (vk_elmt_t *)co_list_pop_front(&vk_buf); |
| } |
| |
| void rc_mmi_vkey_free_buf(void) |
| { |
| vk_elmt_t *val; |
| |
| while((val = rc_mmi_vkey_pop_from_buf()) != NULL) { |
| ke_free(val); |
| } |
| } |
| |
| static void rc_mmi_vkey_push_to_buf(atm_vk_idx_t vkey, void const *ctx) |
| { |
| if (bt_keycode[vkey] == BT_MIC) { |
| return; |
| } |
| #define VKEY_BUF_MAX 20 |
| if (co_list_size(&vk_buf) > VKEY_BUF_MAX) { |
| rc_mmi_vkey_free_buf(); |
| DEBUG_TRACE("Buf-Overflow"); |
| } else { |
| vk_elmt_t *val = ke_malloc(sizeof(vk_elmt_t), KE_MEM_ENV); |
| |
| val->vkey = vkey; |
| val->ctx = ctx; |
| co_list_push_back(&vk_buf, &val->hdr); |
| } |
| } |
| |
| static vk_elmt_t *rc_mmi_vkey_peek_from_buf(void) |
| { |
| return (vk_elmt_t *)(vk_buf.first); |
| } |
| |
| void rc_mmi_vkey_flush_buf(void) |
| { |
| DEBUG_TRACE("%s size: %d", __func__, co_list_size(&vk_buf)); |
| for (vk_elmt_t *val = rc_mmi_vkey_peek_from_buf(); val; |
| val = rc_mmi_vkey_peek_from_buf()) { |
| send_rpt(val->vkey, val->ctx); |
| ke_free(rc_mmi_vkey_pop_from_buf()); |
| } |
| } |
| #endif |
| |
| #ifdef LED_UART_MUX |
| static uint32_t rc_mmi_vkey_init_ms; |
| #endif |
| |
| static void rc_save_key(atm_vk_dnup_evt_t const *evt, void const *ctx) |
| { |
| #ifdef CFG_ATVRC_FIND_ME |
| buzzer_stop(); |
| #endif |
| DEBUG_TRACE("%s key: %d", __func__, evt->top.u8vkey); |
| rc_mmi_vkey_ctx_t const *context = ctx; |
| #ifdef LED_UART_MUX |
| if ((evt->top.u8vkey == VK_RICE) && (atm_lpc_to_ms(atm_get_sys_time()) |
| - rc_mmi_vkey_init_ms < 1000)) { |
| PINMUX_UART_SET(1, TX); |
| } |
| #endif |
| #if defined(CFG_ATVRC_CUSTOM) && defined(CFG_ATVRC_WAKEUP) |
| if ((context->cur_state == MMI_S_INITING) || (context->cur_state == |
| MMI_S_RECONNING) || (context->cur_state == MMI_S_IDLE)) { |
| uint8_t id = atvrc_custom_check_wake_key(bt_keycode[evt->top.u8vkey]); |
| if (id) { |
| rc_gap_set_wake(id); |
| } |
| } |
| #endif |
| #ifdef CFG_ATVRC_UNI_IR |
| if (rc_ir_check_uni_key(atv_keycode[evt->top.u8vkey])) { |
| led_blink(LED_0, ATVRC_LED_KEY_CS, 0, ATVRC_LED_KEY_BLINK); |
| led_blink(LED_1, ATVRC_LED_KEY_CS, 0, ATVRC_LED_KEY_BLINK); |
| return; |
| } |
| #endif |
| #ifdef CFG_ATVRC_CUSTOM |
| if ((context->cur_state == MMI_S_PAIRING) && |
| (bt_keycode[evt->top.u8vkey] == BT_BACK)) { |
| DEBUG_TRACE("Stop pairing"); |
| rc_gap_discoverable(false); |
| } |
| led_blink(LED_1, ATVRC_LED_KEY_CS, 0, ATVRC_LED_KEY_BLINK); |
| #else |
| if (context->cur_state == MMI_S_IDLE) { |
| rc_gap_discoverable(true); |
| } |
| #endif |
| #ifdef CFG_RC_IR |
| rc_ir_send(ir_addr[evt->top.vkey], ir_cmd[evt->top.vkey], |
| RC_IR_DELAY_CS); |
| #endif |
| #ifdef CFG_ATVRC_CUSTOM |
| if (!atvrc_custom_is_cache_pwr() && (evt->top.u8vkey == VK_POWER)) { |
| return; |
| } |
| #endif |
| #ifdef CFG_VKEY_BUF |
| rc_mmi_vkey_push_to_buf(evt->top.vkey, ctx); |
| #else |
| mmi_saved_key = bt_keycode[evt->top.vkey]; |
| #endif |
| return; |
| } |
| |
| static void rc_rftest(atm_vk_dnup_evt_t const *evt, void const *ctx) |
| { |
| switch (bt_keycode[evt->top.vkey]) { |
| case BT_UP: { |
| rc_gap_rf_test_adjust(true, RC_RFTEST_CH); |
| } break; |
| case BT_DOWN: { |
| rc_gap_rf_test_adjust(false, RC_RFTEST_CH); |
| } break; |
| case BT_VOLU: { |
| rc_gap_rf_test_adjust(true, RC_RFTEST_PWR); |
| } break; |
| case BT_VOLD: { |
| rc_gap_rf_test_adjust(false, RC_RFTEST_PWR); |
| } break; |
| default: |
| break; |
| } |
| return; |
| } |
| |
| static void rc_hold_key_status_ind(bool pressed, void const *ctx) |
| { |
| if (pressed) { |
| atm_pm_lock(rc_vk_lock_hiber); |
| return; |
| } |
| atm_pm_unlock(rc_vk_lock_hiber); |
| } |
| |
| #ifdef CFG_ATVRC_MMI |
| static void rc_hold_key_status_ind_ex(bool pressed, void const *ctx) |
| { |
| rc_hold_key_status_ind(pressed, ctx); |
| rc_comb_key_led_ctl(pressed); |
| } |
| #endif |
| |
| #define INVOKE(fm, ...) fm(__VA_ARGS__) |
| #ifdef CFG_ATVRC_MMI |
| #define VK_RICE VK_MUTE |
| #define VK_MENU VK_GUIDE |
| #define DEL_BOND_CB_KEY VK_CENTER, VK_MUTE |
| #define PAIR_MODE_CB_KEY VK_HOME, VK_BACK |
| #define SPEC_FUNC_CB_KEY VK_APP03, VK_APP04 |
| #else |
| #define DEL_BOND_CB_KEY VK_OK, VK_MENU |
| #define PAIR_MODE_CB_KEY VK_OK, VK_VOLDN |
| #define SPEC_FUNC_CB_KEY VK_FW, VK_BW |
| #endif |
| |
| // Key events in HID ready - VKEY_TABLE_HID_READY |
| static atm_vk_reg_t const rc_key_event_hid_ready[] = { |
| VKEY_DOWN_FIRST(rc_send_rpt, atm_vk_any), |
| VKEY_DOWN_MORE(rc_send_comb_rpt, atm_vk_any), |
| VKEY_UP_INTER(rc_sent_up_, atm_vk_any), |
| VKEY_UP_LAST(rc_sent_up, atm_vk_any), |
| VKEY_UP_LAST(rc_mic_up, VK_MIC), |
| VKEY_HOLD_1KEY(rc_hold_test, NULL, 2000, VK_RICE), |
| VKEY_HOLD_1KEY_CLICK(rc_atvv_test, atm_vk_any, VK_RICE), |
| #ifdef CFG_ATVRC_MMI |
| INVOKE(VKEY_HOLD_2KEY, rc_pair_mode, rc_hold_key_status_ind_ex, 4000, |
| PAIR_MODE_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY, rc_del_bond, rc_hold_key_status_ind_ex, 4000, |
| DEL_BOND_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY, rc_bug_report, rc_hold_key_status_ind_ex, 1000, |
| VK_CENTER, VK_BACK), |
| INVOKE(VKEY_HOLD_2KEY, rc_access_shortcut, rc_hold_key_status_ind, 1000, |
| VK_DOWN, VK_BACK), |
| #else |
| INVOKE(VKEY_HOLD_2KEY, rc_del_bond, rc_hold_key_status_ind, 4000, |
| DEL_BOND_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY, rc_pair_mode, rc_hold_key_status_ind, 2000, |
| PAIR_MODE_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY, rc_pair_mode, rc_hold_key_status_ind, 4000, VK_HOME, |
| VK_BACK), |
| #endif |
| INVOKE(VKEY_HOLD_2KEY_CLICK, rc_reset, VK_MENU, SPEC_FUNC_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY_CLICK, rc_disconnect, VK_VOLUP, SPEC_FUNC_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY_CLICK, rc_keytest, VK_OK, SPEC_FUNC_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY_CLICK, rc_enter_rftest, VK_VOLDN, SPEC_FUNC_CB_KEY), |
| |
| }; |
| |
| // Key events in HID non-ready - VKEY_TABLE_HID_NOT_READY |
| static atm_vk_reg_t const rc_key_event_hid_not_ready[] = { |
| VKEY_DOWN_FIRST(rc_save_key, atm_vk_any), |
| #ifdef CFG_RC_IR |
| VKEY_UP_LAST(rc_save_key_up, atm_vk_any), |
| #endif // CFG_RC_IR |
| #ifdef CFG_ATVRC_MMI |
| INVOKE(VKEY_HOLD_2KEY, rc_bug_report, rc_hold_key_status_ind_ex, 1000, |
| VK_CENTER, VK_BACK), |
| INVOKE(VKEY_HOLD_2KEY, rc_pair_mode, rc_hold_key_status_ind_ex, 4000, |
| PAIR_MODE_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY, rc_del_bond, rc_hold_key_status_ind_ex, 4000, |
| DEL_BOND_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY, rc_access_shortcut, rc_hold_key_status_ind, 1000, |
| VK_DOWN, VK_BACK), |
| #else |
| INVOKE(VKEY_HOLD_2KEY, rc_del_bond, rc_hold_key_status_ind, 4000, |
| DEL_BOND_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY, rc_pair_mode, rc_hold_key_status_ind, 2000, |
| PAIR_MODE_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY, rc_pair_mode, rc_hold_key_status_ind, 4000, VK_HOME, |
| VK_BACK), |
| #endif |
| INVOKE(VKEY_HOLD_2KEY_CLICK, rc_reset, VK_MENU, SPEC_FUNC_CB_KEY), |
| INVOKE(VKEY_HOLD_2KEY_CLICK, rc_enter_rftest, VK_VOLDN, SPEC_FUNC_CB_KEY), |
| #ifdef CFG_RC_TEST_MODE |
| INVOKE(VKEY_HOLD_2KEY, rc_ok_back, rc_ok_back_sts, 0, VK_OK, VK_BACK), |
| VKEY_UP_LAST(rc_ok_up, VK_OK), |
| VKEY_HOLD_1KEY_CLICK(rc_ok_click, atm_vk_any, VK_OK), |
| #endif |
| }; |
| |
| // Key events in RF test - VKEY_TABLE_RF_TEST |
| static atm_vk_reg_t const rc_key_event_rf_test[] = { |
| INVOKE(VKEY_HOLD_2KEY_CLICK, rc_reset, VK_MENU, SPEC_FUNC_CB_KEY), |
| VKEY_UP_LAST(rc_rftest, atm_vk_any), |
| }; |
| |
| static void keyboard_callback(ksm_event_t event, uint32_t idx, void const *ctx) |
| { |
| rc_mmi_vkey_ctx_t const *context = ctx; |
| bool pressed = (event == KSM_PRESS); |
| if (context->cur_hdl_idx != VKEY_TABLE_MAX) { |
| atm_vkey_feed(context->handle[context->cur_hdl_idx], idx, pressed); |
| } |
| } |
| |
| #ifdef CFG_ATVRC_MMI |
| static void rc_mmi_vkey_delay_reset(sw_timer_id_t idx, void const *ctx) |
| { |
| platform_reset(RESET_NO_ERROR); |
| } |
| #endif |
| |
| void rc_mmi_vkey_state_change_notify(uint8_t next_state) |
| { |
| // enclose the context |
| static rc_mmi_vkey_ctx_t context = {.cur_hdl_idx = VKEY_TABLE_MAX}; |
| context.cur_state = next_state; |
| |
| switch (next_state) { |
| case MMI_S_INITING: { |
| // key scan driver init |
| #ifdef CFG_EN_GHOSTKEY |
| keyboard_run_with_ghostkey_filter(keyboard_callback, &context); |
| #else |
| keyboard_run(keyboard_callback, &context); |
| #endif |
| // vkey modeling |
| rc_vk_lock_hiber = atm_pm_alloc(PM_LOCK_HIBERNATE); |
| context.handle[VKEY_TABLE_HID_NOT_READY] = |
| atm_vkey_add_table(rc_key_event_hid_not_ready, |
| ARRAY_LEN(rc_key_event_hid_not_ready), &context); |
| context.handle[VKEY_TABLE_HID_READY] = |
| atm_vkey_add_table(rc_key_event_hid_ready, |
| ARRAY_LEN(rc_key_event_hid_ready), &context); |
| context.handle[VKEY_TABLE_RF_TEST] = |
| atm_vkey_add_table(rc_key_event_rf_test, |
| ARRAY_LEN(rc_key_event_rf_test), &context); |
| #ifdef LED_UART_MUX |
| rc_mmi_vkey_init_ms = atm_lpc_to_ms(atm_get_sys_time()); |
| #endif |
| #ifdef CFG_ATVRC_MMI |
| tid_delay_reset = sw_timer_alloc(rc_mmi_vkey_delay_reset, NULL); |
| #endif |
| } |
| case MMI_S_BOOTED: |
| case MMI_S_IDLE: |
| case MMI_S_PAIRING: |
| case MMI_S_RECONNING: |
| #ifndef CFG_VOHID |
| case MMI_S_ATVV_ONLY: |
| #endif |
| case MMI_S_CONNECTED: { |
| context.cur_hdl_idx = VKEY_TABLE_HID_NOT_READY; |
| } break; |
| #ifdef CFG_VOHID |
| case MMI_S_HID_READY: |
| case MMI_S_HID_STREAMING: |
| #else |
| case MMI_S_HID_ONLY: |
| case MMI_S_HID_ATVV: |
| case MMI_S_ATVVING: |
| #endif |
| { |
| context.cur_hdl_idx = VKEY_TABLE_HID_READY; |
| } break; |
| case MMI_S_RF_TEST: { |
| context.cur_hdl_idx = VKEY_TABLE_RF_TEST; |
| } break; |
| case MMI_S_DISCONNING: |
| default: { |
| context.cur_hdl_idx = VKEY_TABLE_MAX; |
| } break; |
| } |
| } |
| |
| #ifndef CFG_VKEY_BUF |
| uint32_t rc_mmi_vkey_get_saved(void) |
| { |
| uint32_t key = mmi_saved_key; |
| DEBUG_TRACE("save key = %" PRIu32, mmi_saved_key); |
| |
| return key; |
| } |
| |
| void rc_mmi_vkey_clear_saved(void) |
| { |
| mmi_saved_key = 0; |
| } |
| #endif |
| |
| #ifdef CFG_ATVRC_CUSTOM |
| void rc_mmi_vkey_update_ui(uint8_t ui) |
| { |
| #define UI_LAYOUT_B0_SETT_MASK 0x01 |
| #define UI_LAYOUT_B1_LIVE_MASK 0x02 |
| #define UI_LAYOUT_B3_PROF_MASK 0x08 |
| #define UI_LAYOUT_B4_ALAP_MASK 0x10 |
| #define UI_LAYOUT_B3_B4_MASK (UI_LAYOUT_B3_PROF_MASK | UI_LAYOUT_B4_ALAP_MASK) |
| if (ui & UI_LAYOUT_B0_SETT_MASK) { |
| bt_keycode[VK_DASHB] = BT_SETT; |
| ir_cmd[VK_DASHB] = IR_SETT; |
| } |
| if (ui & UI_LAYOUT_B1_LIVE_MASK) { |
| bt_keycode[VK_GUIDE] = BT_LIVE; |
| ir_cmd[VK_GUIDE] = IR_LIVE; |
| } |
| if ((ui & UI_LAYOUT_B3_B4_MASK) == UI_LAYOUT_B3_PROF_MASK) { |
| bt_keycode[VK_BKMK] = BT_PROF; |
| ir_cmd[VK_BKMK] = IR_PROF; |
| } |
| if ((ui & UI_LAYOUT_B3_B4_MASK) == UI_LAYOUT_B4_ALAP_MASK) { |
| bt_keycode[VK_BKMK] = BT_ALAP; |
| ir_cmd[VK_BKMK] = IR_ALAP; |
| } |
| } |
| #endif |