aboutsummaryrefslogtreecommitdiff
path: root/platform/atm2/ATM22xx-x1x/examples/HID_remote/src/rc_mmi_vkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'platform/atm2/ATM22xx-x1x/examples/HID_remote/src/rc_mmi_vkey.c')
-rw-r--r--platform/atm2/ATM22xx-x1x/examples/HID_remote/src/rc_mmi_vkey.c751
1 files changed, 751 insertions, 0 deletions
diff --git a/platform/atm2/ATM22xx-x1x/examples/HID_remote/src/rc_mmi_vkey.c b/platform/atm2/ATM22xx-x1x/examples/HID_remote/src/rc_mmi_vkey.c
new file mode 100644
index 0000000..7211761
--- /dev/null
+++ b/platform/atm2/ATM22xx-x1x/examples/HID_remote/src/rc_mmi_vkey.c
@@ -0,0 +1,751 @@
+/*
+ *******************************************************************************
+ *
+ * @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 \ No newline at end of file