diff options
Diffstat (limited to 'apps/action.c')
-rw-r--r-- | apps/action.c | 153 |
1 files changed, 140 insertions, 13 deletions
diff --git a/apps/action.c b/apps/action.c index b31c4fa927..208fea4a97 100644 --- a/apps/action.c +++ b/apps/action.c @@ -34,6 +34,7 @@ #include "button.h" #include "action.h" #include "kernel.h" +#include "core_alloc.h" #include "splash.h" #include "settings.h" @@ -69,6 +70,10 @@ static action_last_t action_last = .tick = 0, .wait_for_release = false, +#ifndef DISABLE_ACTION_REMAP + .key_remap = 0, +#endif + #ifdef HAVE_TOUCHSCREEN .ts_data = 0, .ts_short_press = false, @@ -120,7 +125,7 @@ static bool is_action_filtered(int action, unsigned int mask, int context) { case ACTION_NONE: break; -/*Actions that are not mapped will not turn on the backlight option NOUNMAPPED*/ + /* Actions that are not mapped will not turn on the backlight */ case ACTION_UNKNOWN: match = has_flag(mask, SEL_ACTION_NOUNMAPPED); break; @@ -128,15 +133,15 @@ static bool is_action_filtered(int action, unsigned int mask, int context) case ACTION_FM_PLAY: match = has_flag(mask, SEL_ACTION_PLAY); break; - //case ACTION_STD_PREVREPEAT: // seek not exempted outside of WPS - //case ACTION_STD_NEXTREPEAT: + /* case ACTION_STD_PREVREPEAT:*/ /* seek not exempted outside of WPS */ + /* case ACTION_STD_NEXTREPEAT: */ case ACTION_WPS_SEEKBACK: case ACTION_WPS_SEEKFWD: case ACTION_WPS_STOPSEEK: match = has_flag(mask, SEL_ACTION_SEEK); break; - //case ACTION_STD_PREV: // skip/scrollwheel not exempted outside of WPS - //case ACTION_STD_NEXT: + /* case ACTION_STD_PREV: */ /* skip/scrollwheel not */ + /* case ACTION_STD_NEXT: */ /* exempted outside of WPS */ case ACTION_WPS_SKIPNEXT: case ACTION_WPS_SKIPPREV: case ACTION_FM_NEXT_PRESET: @@ -144,8 +149,8 @@ static bool is_action_filtered(int action, unsigned int mask, int context) match = has_flag(mask, SEL_ACTION_SKIP); break; #ifdef HAVE_VOLUME_IN_LIST - case ACTION_LIST_VOLUP: // volume exempted outside of WPS if the device supports it - case ACTION_LIST_VOLDOWN: + case ACTION_LIST_VOLUP: /* volume exempted outside of WPS */ + case ACTION_LIST_VOLDOWN: /* ( if the device supports it )*/ #endif case ACTION_WPS_VOLUP: case ACTION_WPS_VOLDOWN: @@ -499,7 +504,7 @@ static inline int action_code_worker(action_last_t *last, int *end ) { int ret = ACTION_UNKNOWN; - int i = 0; + int i = *end; unsigned int found = 0; while (cur->items[i].button_code != BUTTON_NONE) { @@ -583,21 +588,52 @@ static inline int get_next_context(const struct button_mapping *items, int i) * for a more in-depth explanation * places action into current_action */ + static inline void action_code_lookup(action_last_t *last, action_cur_t *cur) { - int action = ACTION_NONE; + int action, i; int context = cur->context; - int i = 0; - cur->is_prebutton = false; -#ifdef HAVE_LOCKED_ACTIONS +#if !defined(HAS_BUTTON_HOLD) && !defined(BOOTLOADER) /* This only applies to the first context, to allow locked contexts to * specify a fall through to their non-locked version */ if (is_keys_locked()) context |= CONTEXT_LOCKED; #endif +#ifndef DISABLE_ACTION_REMAP + /* attempt to look up the button in user supplied remap */ + if(last->key_remap && (context & CONTEXT_PLUGIN) == 0) + { + if ((cur->button & BUTTON_REMOTE) != 0) + { + context |= CONTEXT_REMOTE; + } + cur->items = core_get_data(last->key_remap); + i = 0; + action = ACTION_UNKNOWN; + /* check the lut at the beginning for the desired context */ + while (cur->items[i].button_code != BUTTON_NONE) + { + if (cur->items[i].action_code == CORE_CONTEXT_REMAP(context)) + { + i = cur->items[i].button_code; + action = action_code_worker(last, cur, &i); + if (action != ACTION_UNKNOWN) + { + cur->action = action; + return; + } + } + i++; + } + } +#endif + + i = 0; + action = ACTION_NONE; + /* attempt to look up the button in the in-built keymaps */ for(;;) { /* logf("context = %x",context); */ @@ -609,9 +645,13 @@ static inline void action_code_lookup(action_last_t *last, action_cur_t *cur) #endif if ((context & CONTEXT_PLUGIN) && cur->get_context_map) + { cur->items = cur->get_context_map(context); + } else + { cur->items = get_context_mapping(context); + } if (cur->items != NULL) { @@ -960,7 +1000,8 @@ static inline int do_backlight(action_last_t *last, action_cur_t *cur, int actio && power_input_present()); #endif /* skip if backlight on | incorrect context | SEL_ACTION_NOEXT + ext pwr */ - if ((cur->context == CONTEXT_FM || cur->context == CONTEXT_WPS) && bl_is_off) + if (bl_is_off && (cur->context == CONTEXT_FM || cur->context == CONTEXT_WPS || + cur->context == CONTEXT_MAINMENU)) { filtered = is_action_filtered(action, last->backlight_mask, cur->context); bl_activate = !is_action_discarded(cur, filtered, &last->bl_filter_tick); @@ -1150,6 +1191,92 @@ int get_action(int context, int timeout) return action; } +int action_set_keymap(struct button_mapping* core_keymap, int count) +{ +#ifdef DISABLE_ACTION_REMAP + (void)core_keymap; + (void)count; + return -1; +#else + if (count <= 0 || core_keymap == NULL) + return action_set_keymap_handle(0, 0); + + size_t keyremap_buf_size = count * sizeof(struct button_mapping); + int handle = core_alloc(keyremap_buf_size); + if (handle < 0) + return -6; + + memcpy(core_get_data(handle), core_keymap, keyremap_buf_size); + return action_set_keymap_handle(handle, count); +#endif +} + +int action_set_keymap_handle(int handle, int count) +{ +#ifdef DISABLE_ACTION_REMAP + (void)core_keymap; + (void)count; + return -1; +#else + /* free an existing remap */ + action_last.key_remap = core_free(action_last.key_remap); + + /* if clearing the remap, we're done */ + if (count <= 0 || handle <= 0) + return 0; + + /* validate the keymap */ + struct button_mapping* core_keymap = core_get_data(handle); + struct button_mapping* entry = &core_keymap[count - 1]; + if (entry->action_code != (int) CONTEXT_STOPSEARCHING || + entry->button_code != BUTTON_NONE) /* check for sentinel at end*/ + { + /* missing sentinel entry */ + return -1; + } + + /* check the lut at the beginning for invalid offsets */ + for (int i = 0; i < count; ++i) + { + entry = &core_keymap[i]; + if (entry->action_code == (int)CONTEXT_STOPSEARCHING) + break; + + if ((entry->action_code & CONTEXT_REMAPPED) == CONTEXT_REMAPPED) + { + int firstbtn = entry->button_code; + int endpos = firstbtn + entry->pre_button_code; + if (firstbtn > count || firstbtn < i || endpos > count) + { + /* offset out of bounds */ + return -2; + } + + if (core_keymap[endpos].button_code != BUTTON_NONE) + { + /* stop sentinel is not at end of action lut */ + return -3; + } + } + else + { + /* something other than a context remap in the lut */ + return -4; + } + + if (i+1 >= count) + { + /* no sentinel in the lut */ + return -5; + } + } + + /* success */ + action_last.key_remap = handle; + return count; +#endif +} + int get_custom_action(int context,int timeout, const struct button_mapping* (*get_context_map)(int)) { |