diff --git a/applications/main/subghz/helpers/subghz_button_labels.c b/applications/main/subghz/helpers/subghz_button_labels.c new file mode 100644 index 00000000..43c69c49 --- /dev/null +++ b/applications/main/subghz/helpers/subghz_button_labels.c @@ -0,0 +1,100 @@ +#include "subghz_button_labels.h" + +#include +#include +#include + +static const char* const button_default_labels[SUBGHZ_BUTTON_LABEL_COUNT] = { + "Original", + "Up", + "Down", + "Left", + "Right", + "Button 5", + "Button 6", + "Button 7", +}; + +typedef struct { + const char* protocol; + const char* labels[SUBGHZ_BUTTON_LABEL_COUNT]; +} SubGhzProtocolButtonLabels; + +static const SubGhzProtocolButtonLabels protocol_button_labels[] = { + {"VAG GROUP", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, + {"Porsche AG", {"Original", "Lock", "Unlock", "Trunk", "Open"}}, + {"FORD V0", {"Original", "Lock", "Unlock", "Trunk"}}, + {"Ford V2", {"Unlock", "Lock", "Trunk", "Panic", "Remote Start"}}, + {"PSA GROUP", {"Original", "Lock", "Unlock", "Trunk", "Trunk"}}, + {"PSA OLD", {"Original", "Lock", "Unlock", "Trunk", "Trunk"}}, + {"KIA/HYU V0", {"Original", "Lock", "Unlock", "Trunk", "Horn"}}, + {"KIA/HYU V1", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, + {"KIA/HYU V2", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, + {"KIA/HYU V3", {"Original", "Lock", "Unlock", "Trunk", "Panic", "Horn"}}, + {"KIA/HYU V4", {"Original", "Lock", "Unlock", "Trunk", "Panic", "Horn"}}, + {"KIA/HYU V3/V4", {"Original", "Lock", "Unlock", "Trunk", "Panic", "Horn"}}, + {"KIA/HYU V5", {"Original", "Unlock", "Lock", "Trunk", "Horn"}}, + {"KIA/HYU V6", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, + {"SUBARU", {"Original", "Lock", "Unlock", "Trunk", "Panic", "Extra"}}, + {"SUZUKI", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, + {"Star Line", {"Original", "Lock", "Unlock", "Trunk", "Start"}}, + {"Scher-Khan", {"Original", "Lock", "Unlock", "Trunk", "Start"}}, + {"Sheriff CFM", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, + {"Nice FloR-S", {"Original", "Btn 1", "Btn 2", "Btn 3", "Btn 4"}}, + {"CAME Atomo", {"Original", "Btn 1", "Btn 2", "Btn 3"}}, + {"Alutech AT-4N", {"Original", "Btn 1", "Btn 2", "Btn 3", "Btn 4"}}, + {"KeeLoq", {"Original", "Btn 1", "Btn 2", "Btn 3", "Btn 4"}}, + {"Phoenix_V2", {"Original", "Btn 1", "Btn 2", "Btn 3", "Btn 4"}}, + {"Beninca ARC", {"Original", "Btn 1", "Btn 2"}}, + {"GangQi", {"Original", "Btn 1", "Btn 2", "Btn 3"}}, + {"Hay21", {"Original", "Btn 1", "Btn 2"}}, + {"Hollarm", {"Original", "Btn 1", "Btn 2", "Btn 3"}}, + {"Jarolift", {"Original", "Btn 1", "Btn 2", "Btn 3"}}, + {"KingGates Stylo4k", {"Original", "Btn 1", "Btn 2", "Btn 3"}}, + {"Princeton", {"Original", "Btn 1", "Btn 2", "Btn 3", "Btn 4"}}, + {"Roger", {"Original", "Btn 1", "Btn 2", "Btn 3"}}, + {"Security+ 2.0", {"Original", "Btn 1", "Btn 2", "Btn 3", "Btn 4"}}, + {"Somfy Telis", {"Original", "Btn 1", "Btn 2", "Btn 3"}}, + {"Faac SLH", {"Original", "Btn 1"}}, +}; + +void subghz_button_labels_reset(const char* labels[SUBGHZ_BUTTON_LABEL_COUNT]) { + for(uint8_t i = 0; i < SUBGHZ_BUTTON_LABEL_COUNT; i++) { + labels[i] = button_default_labels[i]; + } +} + +void subghz_button_labels_apply_protocol( + const char* protocol, + const char* labels[SUBGHZ_BUTTON_LABEL_COUNT]) { + if(!protocol) return; + + for(uint8_t i = 0; i < COUNT_OF(protocol_button_labels); i++) { + if(strcmp(protocol, protocol_button_labels[i].protocol) == 0) { + for(uint8_t btn = 0; btn < SUBGHZ_BUTTON_LABEL_COUNT; btn++) { + if(protocol_button_labels[i].labels[btn]) { + labels[btn] = protocol_button_labels[i].labels[btn]; + } + } + break; + } + } +} + +const char* subghz_button_labels_get( + const char* const labels[SUBGHZ_BUTTON_LABEL_COUNT], + uint8_t custom_btn_id, + uint8_t original_custom_btn) { + if(custom_btn_id == SUBGHZ_CUSTOM_BTN_OK) { + if((original_custom_btn != SUBGHZ_CUSTOM_BTN_OK) && + (original_custom_btn < SUBGHZ_BUTTON_LABEL_COUNT)) { + return labels[original_custom_btn]; + } + } + + if(custom_btn_id < SUBGHZ_BUTTON_LABEL_COUNT) { + return labels[custom_btn_id]; + } + + return "Button"; +} diff --git a/applications/main/subghz/helpers/subghz_button_labels.h b/applications/main/subghz/helpers/subghz_button_labels.h new file mode 100644 index 00000000..3bd0ca93 --- /dev/null +++ b/applications/main/subghz/helpers/subghz_button_labels.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SUBGHZ_BUTTON_LABEL_COUNT 8 + +void subghz_button_labels_reset(const char* labels[SUBGHZ_BUTTON_LABEL_COUNT]); + +void subghz_button_labels_apply_protocol( + const char* protocol, + const char* labels[SUBGHZ_BUTTON_LABEL_COUNT]); + +const char* subghz_button_labels_get( + const char* const labels[SUBGHZ_BUTTON_LABEL_COUNT], + uint8_t custom_btn_id, + uint8_t original_custom_btn); + +#ifdef __cplusplus +} +#endif diff --git a/applications/main/subghz/scenes/subghz_scene_car_emulate.c b/applications/main/subghz/scenes/subghz_scene_car_emulate.c index 53ae3265..df1f0b43 100644 --- a/applications/main/subghz/scenes/subghz_scene_car_emulate.c +++ b/applications/main/subghz/scenes/subghz_scene_car_emulate.c @@ -9,6 +9,7 @@ */ #include "../subghz_i.h" #include "../views/subghz_car_emulate.h" +#include "../helpers/subghz_button_labels.h" #include "../helpers/subghz_custom_event.h" #include #include @@ -36,6 +37,7 @@ typedef struct { /* Resolved custom button repeated while the physical key is held */ uint8_t pending_button; + uint8_t max_custom_button; } CarEmulateState; static CarEmulateState* s_state = NULL; @@ -202,7 +204,7 @@ static void car_emulate_read_freq_preset(SubGhz* subghz, CarEmulateState* st) { } /** Update Btn and Cnt fields in fff_data so the transmitter re-serialises them. */ -static void car_emulate_apply_button(SubGhz* subghz, InputKey key) { +static bool car_emulate_apply_button(SubGhz* subghz, InputKey key) { UNUSED(subghz); uint8_t custom_btn_id; @@ -215,7 +217,11 @@ static void car_emulate_apply_button(SubGhz* subghz, InputKey key) { default: custom_btn_id = SUBGHZ_CUSTOM_BTN_OK; break; } - subghz_custom_btn_set(custom_btn_id); + if(custom_btn_id > s_state->max_custom_button) { + return false; + } + + return subghz_custom_btn_set(custom_btn_id); } @@ -367,13 +373,33 @@ void subghz_scene_car_emulate_on_enter(void* context) { flipper_format_rewind(fff); } - subghz_car_emulate_view_set_labels( + s_state->max_custom_button = + subghz_custom_btn_is_allowed() ? subghz_custom_btn_get_max() : SUBGHZ_CUSTOM_BTN_OK; + + const char* button_labels[SUBGHZ_BUTTON_LABEL_COUNT]; + subghz_button_labels_reset(button_labels); + subghz_button_labels_apply_protocol(s_state->protocol_name, button_labels); + + subghz_car_emulate_view_set_labels( subghz->car_emulate_view, - "UNLOCK", /* OK */ - "LOCK", /* Up */ - "TRUNK", /* Down */ - "PANIC", /* Left */ - "START" /* Right */ + subghz_button_labels_get( + button_labels, SUBGHZ_CUSTOM_BTN_OK, subghz_custom_btn_get_original()), + s_state->max_custom_button >= SUBGHZ_CUSTOM_BTN_UP ? + subghz_button_labels_get( + button_labels, SUBGHZ_CUSTOM_BTN_UP, subghz_custom_btn_get_original()) : + "", + s_state->max_custom_button >= SUBGHZ_CUSTOM_BTN_DOWN ? + subghz_button_labels_get( + button_labels, SUBGHZ_CUSTOM_BTN_DOWN, subghz_custom_btn_get_original()) : + "", + s_state->max_custom_button >= SUBGHZ_CUSTOM_BTN_LEFT ? + subghz_button_labels_get( + button_labels, SUBGHZ_CUSTOM_BTN_LEFT, subghz_custom_btn_get_original()) : + "", + s_state->max_custom_button >= SUBGHZ_CUSTOM_BTN_RIGHT ? + subghz_button_labels_get( + button_labels, SUBGHZ_CUSTOM_BTN_RIGHT, subghz_custom_btn_get_original()) : + "" ); car_emulate_read_freq_preset(subghz, s_state); @@ -407,14 +433,18 @@ bool subghz_scene_car_emulate_on_event(void* context, SceneManagerEvent event) { car_emulate_stop_tx(subghz); } - /* Bump counter */ - s_state->current_counter++; - /* Set the custom button BEFORE deserialize() is called inside * subghz_tx_start() → subghz_txrx_tx_start(). * The protocol's deserialize() will call subghz_custom_btn_get() * to pick the right button code. */ - car_emulate_apply_button(subghz, key); + if(!car_emulate_apply_button(subghz, key)) { + notification_message(subghz->notifications, &sequence_error); + car_emulate_refresh_view(subghz); + return true; + } + + /* Bump counter */ + s_state->current_counter++; /* Only update the counter in fff_data; the protocol handles Btn. */ car_emulate_update_fff(subghz, s_state->current_counter); diff --git a/applications/main/subghz/scenes/subghz_scene_signal_settings.c b/applications/main/subghz/scenes/subghz_scene_signal_settings.c index be9745df..336cdb1b 100644 --- a/applications/main/subghz/scenes/subghz_scene_signal_settings.c +++ b/applications/main/subghz/scenes/subghz_scene_signal_settings.c @@ -1,5 +1,6 @@ #include "../subghz_i.h" #include "subghz/types.h" +#include "../helpers/subghz_button_labels.h" #include "../helpers/subghz_custom_event.h" #include #include @@ -81,18 +82,7 @@ static const uint8_t button_value[] = { 7, }; -#define BUTTON_VALUE_COUNT (sizeof(button_value) / sizeof(button_value[0])) - -static const char* const button_default_labels[BUTTON_VALUE_COUNT] = { - "Original", - "Up", - "Down", - "Left", - "Right", - "Button 5", - "Button 6", - "Button 7", -}; +#define BUTTON_VALUE_COUNT SUBGHZ_BUTTON_LABEL_COUNT static const char* button_labels[BUTTON_VALUE_COUNT] = { "Original", @@ -105,30 +95,6 @@ static const char* button_labels[BUTTON_VALUE_COUNT] = { "Button 7", }; -typedef struct { - const char* protocol; - const char* labels[BUTTON_VALUE_COUNT]; -} ProtocolButtonLabels; - -static const ProtocolButtonLabels protocol_button_labels[] = { - {"VAG GROUP", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, - {"Porsche AG", {"Original", "Lock", "Unlock", "Trunk", "Open"}}, - {"FORD V0", {"Original", "Lock", "Unlock", "Trunk"}}, - {"Ford V2", {"Unlock", "Lock", "Trunk", "Panic", "Remote Start"}}, - {"PSA GROUP", {"Original", "Lock", "Unlock", "Trunk", "Trunk"}}, - {"KIA/HYU V0", {"Original", "Lock", "Unlock", "Trunk", "Horn"}}, - {"KIA/HYU V1", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, - {"KIA/HYU V2", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, - {"KIA/HYU V3/V4", {"Original", "Lock", "Unlock", "Trunk", "Panic", "Horn"}}, - {"KIA/HYU V5", {"Original", "Unlock", "Lock", "Trunk", "Horn"}}, - {"KIA/HYU V6", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, - {"SUBARU", {"Original", "Lock", "Unlock", "Trunk", "Panic", "Extra"}}, - {"SUZUKI", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, - {"Star Line", {"Original", "Lock", "Unlock", "Trunk", "Start"}}, - {"Scher-Khan", {"Original", "Lock", "Unlock", "Trunk", "Start"}}, - {"Sheriff CFM", {"Original", "Lock", "Unlock", "Trunk", "Panic"}}, -}; - typedef struct { char* name; uint8_t mode_count; @@ -146,35 +112,16 @@ static Protocols protocols[] = { #define PROTOCOLS_COUNT (sizeof(protocols) / sizeof(Protocols)) static void subghz_scene_signal_settings_reset_button_labels(void) { - for(uint8_t i = 0; i < BUTTON_VALUE_COUNT; i++) { - button_labels[i] = button_default_labels[i]; - } + subghz_button_labels_reset(button_labels); } static void subghz_scene_signal_settings_apply_button_labels(const char* protocol) { - for(uint8_t i = 0; i < COUNT_OF(protocol_button_labels); i++) { - if(strcmp(protocol, protocol_button_labels[i].protocol) == 0) { - for(uint8_t btn = 0; btn < BUTTON_VALUE_COUNT; btn++) { - if(protocol_button_labels[i].labels[btn]) { - button_labels[btn] = protocol_button_labels[i].labels[btn]; - } - } - break; - } - } + subghz_button_labels_apply_protocol(protocol, button_labels); } static const char* subghz_scene_signal_settings_get_button_label(uint8_t custom_btn_id) { - if(custom_btn_id == SUBGHZ_CUSTOM_BTN_OK) { - uint8_t original = subghz_custom_btn_get_original(); - if((original != SUBGHZ_CUSTOM_BTN_OK) && (original < BUTTON_VALUE_COUNT)) { - return button_labels[original]; - } - } - if(custom_btn_id < BUTTON_VALUE_COUNT) { - return button_labels[custom_btn_id]; - } - return "Button"; + return subghz_button_labels_get( + button_labels, custom_btn_id, subghz_custom_btn_get_original()); } static bool subghz_scene_signal_settings_update_uint32_field( diff --git a/applications/main/subghz/views/subghz_car_emulate.c b/applications/main/subghz/views/subghz_car_emulate.c index 82e9afb4..0a3ce341 100644 --- a/applications/main/subghz/views/subghz_car_emulate.c +++ b/applications/main/subghz/views/subghz_car_emulate.c @@ -17,11 +17,11 @@ typedef struct { char preset[12]; bool is_transmitting; uint8_t anim_frame; - char label_ok[12]; - char label_up[12]; - char label_down[12]; - char label_left[12]; - char label_right[12]; + char label_ok[16]; + char label_up[16]; + char label_down[16]; + char label_left[16]; + char label_right[16]; } SubGhzCarEmulateViewModel; /* ── Handle ─────────────────────────────────────────────────────────────── */ @@ -79,7 +79,7 @@ static void subghz_car_emulate_view_draw(Canvas* canvas, void* model_ptr) { const uint8_t font_h = canvas_current_font_height(canvas); /* Centre → UNLOCK (OK button) */ - { + if(m->label_ok[0]) { const char* lbl = m->label_ok; uint8_t w = (uint8_t)(canvas_string_width(canvas, lbl) + 8U); canvas_draw_rbox(canvas, 64 - w / 2, 45 - font_h / 2, w, font_h, 3); @@ -89,7 +89,7 @@ static void subghz_car_emulate_view_draw(Canvas* canvas, void* model_ptr) { } /* Up → LOCK */ - { + if(m->label_up[0]) { const char* lbl = m->label_up; uint8_t w = (uint8_t)(canvas_string_width(canvas, lbl) + 8U); canvas_draw_rbox(canvas, 64 - w / 2, 33 - font_h / 2, w, font_h, 3); @@ -99,7 +99,7 @@ static void subghz_car_emulate_view_draw(Canvas* canvas, void* model_ptr) { } /* Left → PANIC */ - { + if(m->label_left[0]) { const char* lbl = m->label_left; uint8_t w = (uint8_t)(canvas_string_width(canvas, lbl) + 8U); canvas_draw_rbox(canvas, 0, 46 - font_h / 2, w, font_h, 3); @@ -109,7 +109,7 @@ static void subghz_car_emulate_view_draw(Canvas* canvas, void* model_ptr) { } /* Right → generic extra */ - { + if(m->label_right[0]) { const char* lbl = m->label_right; uint8_t w = (uint8_t)(canvas_string_width(canvas, lbl) + 8U); canvas_draw_rbox(canvas, 127 - w, 46 - font_h / 2, w, font_h, 3); @@ -119,7 +119,7 @@ static void subghz_car_emulate_view_draw(Canvas* canvas, void* model_ptr) { } /* Down → BOOT */ - { + if(m->label_down[0]) { const char* lbl = m->label_down; uint8_t w = (uint8_t)(canvas_string_width(canvas, lbl) + 8U); canvas_draw_rbox(canvas, 64 - w / 2, 57 - font_h / 2, w, font_h, 3); @@ -259,6 +259,11 @@ void subghz_car_emulate_view_set_labels( strncpy(m->label_down, down ? down : "", sizeof(m->label_down) - 1); strncpy(m->label_left, left ? left : "", sizeof(m->label_left) - 1); strncpy(m->label_right, right ? right : "", sizeof(m->label_right) - 1); + m->label_ok[sizeof(m->label_ok) - 1] = '\0'; + m->label_up[sizeof(m->label_up) - 1] = '\0'; + m->label_down[sizeof(m->label_down) - 1] = '\0'; + m->label_left[sizeof(m->label_left) - 1] = '\0'; + m->label_right[sizeof(m->label_right) - 1] = '\0'; }, true); }