diff --git a/ReadMe.md b/ReadMe.md index 1cf7cac634c..13cd101f1e8 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -54,8 +54,6 @@ This software is for experimental purposes only and is not meant for any illegal - Updated: [ESP32-C6 Gravity (By chris-bc)](https://github.com/chris-bc/Flipper-Gravity) - UL: [Init config for external radio driver #564 (By gid9798)](https://github.com/DarkFlippers/unleashed-firmware/pull/564) - Updated: [ESP32 WIFI Mapping (By carvilsi)](https://github.com/carvilsi/flipper0-wifi-map) -- Updated: [GPIO Controller (By Lokno)](https://github.com/Lokno/gpio_controller) -- Updated: [YRM100 UHF RFID WIP (By frux-c)](https://github.com/frux-c/uhf_rfid) `Req: YRM100` - [New Patreon Animation Set](https://www.patreon.com/RogueMaster/membership): [BMO (By wrenchathome)](https://github.com/wrenchathome/flip0anims/tree/main/Animations/BMO) will be released with next Patreon release - [New Patreon Animation added to DBZ build: G0ku N3xt L3v3L (By RM)](https://www.patreon.com/RogueMaster/membership) - Added: [Rock Paper Scissors 2 v1.0 (By benwoo1110)](https://github.com/benwoo1110/rps-FlipperZero) @@ -66,15 +64,18 @@ This software is for experimental purposes only and is not meant for any illegal - OFW: [New RTC flags in device info #2884 (By Programistich)](https://github.com/flipperdevices/flipperzero-firmware/pull/2884) - OFW: [Backlight notification fix #2878 (By nminaylov)](https://github.com/flipperdevices/flipperzero-firmware/pull/2878) - Updated: [Authenticator/TOTP v3.2 (By akopachov)](https://github.com/akopachov/flipper-zero_authenticator) -- Updated: [Enhanced Sub-Ghz Chat (By twisted-pear)](https://github.com/twisted-pear/esubghz_chat) - Updated: [u-blox GPS (By liamhays)](https://github.com/liamhays/ublox) -- Updated: [ESP32 Evil Portal v0.2 (By bigbrodude6119)](https://github.com/bigbrodude6119/flipper-zero-evil-portal) [Changes By manu0466]( https://github.com/RogueMaster/flipper-zero-evil-portal/pull/1) - OFW: [Overly missed feature: Infrared: move button (change button order in a remote) #2894 (By plgcoder)](https://github.com/flipperdevices/flipperzero-firmware/pull/2894) - OFW: [External apps icounter #2928 (By Astrrra)](https://github.com/flipperdevices/flipperzero-firmware/pull/2928) Experience for every FAP! - OFW: [change FuriThreadPriorityIsr to 31 (configMAX_PRIORITIES-1) #2920 (By leommxj)](https://github.com/flipperdevices/flipperzero-firmware/pull/2920) - OFW: [Add Daikin FTXC35DV1B ac remote #2913 (By skotopes)](https://github.com/flipperdevices/flipperzero-firmware/pull/2913) - OFW: [SubGhz: change CC1101_ext TIM17 resolution to 2µs #2909 (By Skorpionm)](https://github.com/flipperdevices/flipperzero-firmware/pull/2909) - OFW: [Fix about screen #2907 (By andzhr)](https://github.com/flipperdevices/flipperzero-firmware/pull/2907) +- Updated: [Enhanced Sub-Ghz Chat (By twisted-pear)](https://github.com/twisted-pear/esubghz_chat) +- Updated: [GPIO Controller (By Lokno)](https://github.com/Lokno/gpio_controller) +- Updated: [YRM100 UHF RFID WIP (By frux-c)](https://github.com/frux-c/uhf_rfid) `Req: YRM100` +- Updated: [ESP32 Evil Portal v0.2 (By bigbrodude6119)](https://github.com/bigbrodude6119/flipper-zero-evil-portal) [Changes By manu0466]( https://github.com/RogueMaster/flipper-zero-evil-portal/pull/1) +- [Better Google Login for Evil Portal (By 8Root)](https://github.com/bigbrodude6119/flipper-zero-evil-portal/pull/56) diff --git a/applications/external/esubghz_chat/crypto_wrapper.c b/applications/external/esubghz_chat/crypto_wrapper.c index 38f7b6453b6..cf388658dec 100644 --- a/applications/external/esubghz_chat/crypto_wrapper.c +++ b/applications/external/esubghz_chat/crypto_wrapper.c @@ -65,8 +65,14 @@ bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, u #ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL return ( furi_hal_crypto_gcm_decrypt_and_verify( - ctx->key, in, in + IV_BYTES, out, in_len - MSG_OVERHEAD, in + in_len - TAG_BYTES) == - FuriHalCryptoGCMStateOk); + ctx->key, + in, + NULL, + 0, + in + IV_BYTES, + out, + in_len - MSG_OVERHEAD, + in + in_len - TAG_BYTES) == FuriHalCryptoGCMStateOk); #else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */ return ( gcm_auth_decrypt( @@ -89,7 +95,7 @@ bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, u #ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL return ( furi_hal_crypto_gcm_encrypt_and_tag( - ctx->key, out, in, out + IV_BYTES, in_len, out + IV_BYTES + in_len) == + ctx->key, out, NULL, 0, in, out + IV_BYTES, in_len, out + IV_BYTES + in_len) == FuriHalCryptoGCMStateOk); #else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */ return ( diff --git a/applications/external/evil_portal/application.fam b/applications/external/evil_portal/application.fam index 5729d40b181..3430197625c 100644 --- a/applications/external/evil_portal/application.fam +++ b/applications/external/evil_portal/application.fam @@ -1,6 +1,6 @@ App( - appid="esp32_evil_portal", - name="[ESP32] Evil Portal", + appid="evil_portal", + name="Evil Portal", apptype=FlipperAppType.EXTERNAL, entry_point="evil_portal_app", # cdefines=["APP_EVIL_PORTAL"], diff --git a/applications/external/evil_portal/evil_portal_app_i.h b/applications/external/evil_portal/evil_portal_app_i.h index 39feaf981d6..7467f5e37e9 100644 --- a/applications/external/evil_portal/evil_portal_app_i.h +++ b/applications/external/evil_portal/evil_portal_app_i.h @@ -29,7 +29,7 @@ #define RESET_CMD "reset" #define HTML_EXTENSION ".html" -#define HTML_FOLDER ANY_PATH("apps_data/esp32_evil_portal/html") +#define HTML_FOLDER ANY_PATH("apps_data/evil_portal/html") struct Evil_PortalApp { Gui* gui; diff --git a/applications/external/gpio_controller/app_defines.h b/applications/external/gpio_controller/app_defines.h new file mode 100644 index 00000000000..bca20dc27cd --- /dev/null +++ b/applications/external/gpio_controller/app_defines.h @@ -0,0 +1,135 @@ +#ifndef APP_DEFINES_H +#define APP_DEFINES_H + +#define GPIO_PIN_COUNT 8 +#define ANIMATE_FRAME_TIME_MS 133 +#define FRAME_TIME 66.666666 + +typedef void (*DrawView)(Canvas* canvas, void* ctx); +typedef void (*HandleInput)(InputEvent* event, void* ctx); + +typedef enum { MAIN_VIEW, CONFIG_MENU_VIEW } enum_view; + +typedef enum { + GPIO_MODE_INPUT, + GPIO_MODE_INPUT_PULLUP, + GPIO_MODE_OUTPUT, + GPIO_MODE_UNSET +} GpioUserMode; + +typedef enum { + GPIO_VALUE_TRUE, + GPIO_VALUE_FALSE, + GPIO_VALUE_INPUT, + GPIO_VALUE_NONE +} GpioUserValue; + +typedef enum { CONFIG_MENU_MODE, CONFIG_MENU_VALUE, CONFIG_MENU_INPUT } ConfigMenuOptions; + +typedef struct { + GpioUserMode mode; + GpioUserValue value; + int gp_idx_input; + bool changed; + GpioUserMode prev_mode; +} GPIOPinUserSelection; + +typedef struct { + int selected; + enum_view view; + int wiggle_frame; + size_t prev_frame_time; + size_t elapsed_time; + double result; + double freq_var; + double elapsed_var; + ConfigMenuOptions config_menu_selected; +} ViewerState; + +// 5V A7 A6 A4 B3 B2 C3 GND SET +// +// +// 3V SWC GND SIO TX RX C1 C0 1W GND + +typedef enum { + PIN_5V = 0, + PIN_A7, + PIN_A6, + PIN_A4, + PIN_B3, + PIN_B2, + PIN_C3, + GEARIC, + PIN_3V, + PIN_SWC, + PIN_SIO, + PIN_TX, + PIN_RX, + PIN_C1, + PIN_C0, + PIN_1W, + PIN_GND_08, + PIN_GND_11, + PIN_GND_18, + NONE +} enum_view_element; + +typedef struct { + enum_view_element element; + enum_view_element opposite; + bool selectable; + bool editable; + bool top_row; + bool pull_out; + int gp_idx; + uint8_t x_pos; + uint8_t y_pos; + const char* name; + Icon* icon; + Icon* selected_icon; +} ViewElement; + +typedef struct { + uint8_t element_idx; + const GpioPin* pin; + GpioMode mode; + GpioPull pull; + GpioSpeed speed; + double value; + const char* name; + bool unset; + bool found; + bool input; + GPIOPinUserSelection user; +} GPIOPin; + +// GPIO enums from firmware/targets/f7/furi_hal/furi_hal_gpio.h + +// /** +// * Gpio modes +// */ +// typedef enum { +// *GpioModeInput, +// *GpioModeOutputPushPull, +// GpioModeOutputOpenDrain, +// GpioModeAltFunctionPushPull, +// GpioModeAltFunctionOpenDrain, +// *GpioModeAnalog, +// GpioModeInterruptRise, +// GpioModeInterruptFall, +// GpioModeInterruptRiseFall, +// GpioModeEventRise, +// GpioModeEventFall, +// GpioModeEventRiseFall, +// } GpioMode; + +// /** +// * Gpio pull modes +// */ +// typedef enum { +// GpioPullNo, +// GpioPullUp, +// GpioPullDown, +// } GpioPull; + +#endif \ No newline at end of file diff --git a/applications/external/gpio_controller/gpio_controller.c b/applications/external/gpio_controller/gpio_controller.c index 60430b2d50b..f9d8436887f 100644 --- a/applications/external/gpio_controller/gpio_controller.c +++ b/applications/external/gpio_controller/gpio_controller.c @@ -1,6 +1,10 @@ #include #include +#include +#include +#include + #include #include @@ -8,76 +12,19 @@ * Just set fap_icon_assets in application.fam and #include {APPID}_icons.h */ #include "gpio_controller_icons.h" -#define GPIO_PIN_COUNT 8 -#define ANIMATE_FRAME_TIME_MS 133 -#define FRAME_TIME 66.666666 - -typedef struct { - int selected; - //GPIOItems* gpio_items; - int wiggle_frame; - size_t prev_frame_time; - size_t elapsed_time; -} ViewerState; - -// 5V A7 A6 A4 B3 B2 C3 GND SET -// -// -// 3V SWC GND SIO TX RX C1 C0 1W GND - -typedef enum { - PIN_5V = 0, - PIN_A7, - PIN_A6, - PIN_A4, - PIN_B3, - PIN_B2, - PIN_C3, - GEARIC, - PIN_3V, - PIN_SWC, - PIN_SIO, - PIN_TX, - PIN_RX, - PIN_C1, - PIN_C0, - PIN_1W, - PIN_GND_08, - PIN_GND_11, - PIN_GND_18, - NONE -} enum_view_element; - -typedef struct { - enum_view_element element; - enum_view_element opposite; - bool selectable; - bool editable; - bool top_row; - bool pull_out; - int gp_idx; - uint8_t x_pos; - uint8_t y_pos; - const char* name; - Icon* icon; - Icon* selected_icon; -} ViewElement; - -typedef struct { - uint8_t element_idx; - const GpioPin* pin; - GpioMode mode; - GpioPull pull; - GpioSpeed speed; - uint8_t value; - const char* name; - char* expression; - bool unset; - bool found; - bool input; -} GPIOPin; - -static ViewerState vstate = {.selected = PIN_A7, .wiggle_frame = -1}; +#include "app_defines.h" + +static void draw_main_view(Canvas* canvas, void* ctx); +static void draw_config_menu_view(Canvas* canvas, void* ctx); + +static DrawView draw_view_funcs[] = {draw_main_view, draw_config_menu_view}; + +static void handle_main_input(InputEvent* event, void* ctx); +static void handle_config_menu_input(InputEvent* event, void* ctx); + +static HandleInput input_handlers[] = {handle_main_input, handle_config_menu_input}; + +static ViewerState vstate; static int wiggle[] = {-1, 1, -1, 1}; static uint32_t wiggle_frame_count = 4; @@ -161,46 +108,22 @@ static ViewElement elements[] = { static GPIOPin gpio_pin_config[GPIO_PIN_COUNT]; -static int element_count = NONE; - -// GPIO enums from firmware/targets/f7/furi_hal/furi_hal_gpio.h - -// /** -// * Gpio modes -// */ -// typedef enum { -// *GpioModeInput, -// *GpioModeOutputPushPull, -// GpioModeOutputOpenDrain, -// GpioModeAltFunctionPushPull, -// GpioModeAltFunctionOpenDrain, -// *GpioModeAnalog, -// GpioModeInterruptRise, -// GpioModeInterruptFall, -// GpioModeInterruptRiseFall, -// GpioModeEventRise, -// GpioModeEventFall, -// GpioModeEventRiseFall, -// } GpioMode; - -// /** -// * Gpio pull modes -// */ -// typedef enum { -// GpioPullNo, -// GpioPullUp, -// GpioPullDown, -// } GpioPull; - -// /** -// * Gpio speed modes -// */ -// typedef enum { -// GpioSpeedLow, -// GpioSpeedMedium, -// GpioSpeedHigh, -// GpioSpeedVeryHigh, -// } GpioSpeed; +static int element_count = + NONE; // The NONE enum will a value equal to the number of elements defined in enum_view_element + +size_t strnlen(const char* str, size_t maxlen) { + size_t len = 0; + while(len < maxlen && str[len] != '\0') { + len++; + } + return len; +} + +static void init_state() { + vstate.selected = PIN_A7; + vstate.wiggle_frame = -1; + vstate.view = MAIN_VIEW; +} static void init_gpio() { int count = 0; @@ -215,11 +138,15 @@ static void init_gpio() { gpio_pin_config[count].speed = GpioSpeedVeryHigh; gpio_pin_config[count].value = 0; gpio_pin_config[count].name = gpio_pins[i].name; - gpio_pin_config[count].expression = NULL; gpio_pin_config[count].unset = true; gpio_pin_config[count].found = true; gpio_pin_config[count].input = false; + gpio_pin_config[count].user.mode = GPIO_MODE_UNSET; + gpio_pin_config[count].user.value = GPIO_VALUE_FALSE; + gpio_pin_config[count].user.gp_idx_input = -1; + gpio_pin_config[count].user.changed = false; + elements[j].gp_idx = i; elements[j].editable = true; @@ -229,30 +156,75 @@ static void init_gpio() { } } - // naively set all as digitial output - for(int i = 0; i < count; i++) { + vstate.result = 0; +} + +static void update_gpio() { + // read from gpio pins + for(int i = 0; i < GPIO_PIN_COUNT; i++) { GPIOPin* gpc = &gpio_pin_config[i]; - gpc->input = true; - gpc->unset = false; - furi_hal_gpio_write(gpc->pin, false); - furi_hal_gpio_init(gpc->pin, gpc->mode, gpc->pull, gpc->speed); + if(!gpc->unset) { + if(gpc->mode == GpioModeInput) { + gpc->value = furi_hal_gpio_read(gpc->pin) ? 1 : 0; + } + } } } -//static void update_gpio() -//{ -// // write to gpio pins -// -// // read frm gpio pins -//} +#define TOGGLECOLOR(state, canvas, setting, selected_col, deselected_col) \ + canvas_set_color(canvas, (state == setting) ? selected_col : deselected_col) + +const char* gpio_user_mode_strs[] = {"INPUT", "INPUT_PULLUP", "OUTPUT", "UNSET"}; +const char* gpio_user_value_strs[] = {"TRUE", "FALSE", "INPUT"}; + +static void draw_config_menu_view(Canvas* canvas, void* ctx) { + UNUSED(ctx); + + int gp_idx = elements[vstate.selected].gp_idx; + GPIOPin* gpc = &gpio_pin_config[gp_idx]; + + UNUSED(gpc); + + canvas_set_font(canvas, FontSecondary); + + canvas_set_color(canvas, ColorBlack); + canvas_draw_rframe(canvas, 1, 1, 126, 62, 0); + + TOGGLECOLOR(vstate.config_menu_selected, canvas, CONFIG_MENU_MODE, ColorBlack, ColorWhite); + canvas_draw_box(canvas, 2, 2, 124, 15); + + TOGGLECOLOR(vstate.config_menu_selected, canvas, CONFIG_MENU_MODE, ColorWhite, ColorBlack); + canvas_draw_str(canvas, 6, 12, "Mode"); + + if(gpc->user.mode > 0) canvas_draw_str(canvas, 34, 12, "<"); + + canvas_draw_str(canvas, 45, 12, gpio_user_mode_strs[gpc->user.mode]); + + if(gpc->user.mode < GPIO_MODE_UNSET) canvas_draw_str(canvas, 120, 12, ">"); + + if(gpc->user.mode == GPIO_MODE_OUTPUT) { + TOGGLECOLOR( + vstate.config_menu_selected, canvas, CONFIG_MENU_VALUE, ColorBlack, ColorWhite); + canvas_draw_box(canvas, 2, 16, 124, 15); + + TOGGLECOLOR( + vstate.config_menu_selected, canvas, CONFIG_MENU_VALUE, ColorWhite, ColorBlack); + canvas_draw_str(canvas, 6, 12 + 16, "Value"); + + if(gpc->user.value > 0) canvas_draw_str(canvas, 34, 12 + 16, "<"); + + canvas_draw_str(canvas, 45, 12 + 16, gpio_user_value_strs[gpc->user.value]); + + if(gpc->user.value < GPIO_VALUE_INPUT) canvas_draw_str(canvas, 120, 12 + 16, ">"); + } +} // TODO: Determine the lowest frame delta we can get away with. // TODO: Redraw only what changes. // - clear previous (drawn) selected pin // - clear newly selected pin -// Screen is 128x64 px -static void app_draw_callback(Canvas* canvas, void* ctx) { +static void draw_main_view(Canvas* canvas, void* ctx) { UNUSED(ctx); canvas_clear(canvas); @@ -278,6 +250,10 @@ static void app_draw_callback(Canvas* canvas, void* ctx) { vstate.elapsed_time += delta_time_ms; vstate.prev_frame_time = current_frame_time; + canvas_set_font(canvas, FontSecondary); + + char hex_string[3]; + // draw values for(int i = 0; i < GPIO_PIN_COUNT; i++) { if(!gpio_pin_config[i].unset) { @@ -291,8 +267,17 @@ static void app_draw_callback(Canvas* canvas, void* ctx) { } if(gpio_pin_config[i].mode == GpioModeAnalog) { + snprintf(hex_string, sizeof(hex_string), "%02X", (int)gpio_pin_config[i].value); + if(e.top_row) { + canvas_draw_icon(canvas, e.x_pos - 1, e.y_pos + 20, &I_analog_box); + canvas_draw_str(canvas, e.x_pos + 1, e.y_pos + 22 + 7, hex_string); + + } else { + canvas_draw_icon(canvas, e.x_pos - 1, e.y_pos - 15, &I_analog_box); + canvas_draw_str(canvas, e.x_pos + 1, e.y_pos - 6, hex_string); + } } else { - const Icon* icon = gpio_pin_config[i].value ? &I_digi_one : &I_digi_zero; + const Icon* icon = (int)gpio_pin_config[i].value ? &I_digi_one : &I_digi_zero; if(e.top_row) { canvas_draw_icon(canvas, e.x_pos + 2, e.y_pos + 20, icon); } else { @@ -321,9 +306,7 @@ static void app_draw_callback(Canvas* canvas, void* ctx) { if(vstate.elapsed_time >= ANIMATE_FRAME_TIME_MS) { vstate.wiggle_frame++; - if((unsigned int)(vstate.wiggle_frame) >= - wiggle_frame_count) //(sizeof(wiggle)/sizeof(int))) - { + if((unsigned int)(vstate.wiggle_frame) >= wiggle_frame_count) { vstate.wiggle_frame = -1; } vstate.elapsed_time = 0; @@ -334,15 +317,214 @@ static void app_draw_callback(Canvas* canvas, void* ctx) { canvas_draw_icon(canvas, x, y, icon); } + // draw arrows + for(int i = 0; i < GPIO_PIN_COUNT; i++) { + if(!gpio_pin_config[i].unset) { + ViewElement e = elements[gpio_pin_config[i].element_idx]; + + bool selected = vstate.selected == gpio_pin_config[i].element_idx; + + // draw arrow + if(e.top_row) { + int offset = selected ? 3 : 0; + const Icon* arrow_icon = gpio_pin_config[i].input ? &I_arrow_up : &I_arrow_down; + canvas_draw_icon(canvas, e.x_pos + 3, e.y_pos + 8 + offset, arrow_icon); + } else { + int offset = selected ? 0 : 3; + const Icon* arrow_icon = gpio_pin_config[i].input ? &I_arrow_down : &I_arrow_up; + canvas_draw_icon(canvas, e.x_pos + 3, e.y_pos + -1 + offset, arrow_icon); + } + } + } + canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 0, 40, elements[vstate.selected].name); + canvas_draw_str(canvas, 0, 42, elements[vstate.selected].name); } -static void app_input_callback(InputEvent* input_event, void* ctx) { - furi_assert(ctx); +static void handle_main_input(InputEvent* event, void* ctx) { + if(vstate.wiggle_frame < 0) { + furi_assert(ctx); + FuriMessageQueue* event_queue = ctx; + + // place in queue to handle backing out of app + furi_message_queue_put(event_queue, event, FuriWaitForever); + + if((event->type == InputTypePress || event->type == InputTypeRelease) && + event->key == InputKeyOk) { + if(event->type == InputTypePress && elements[vstate.selected].gp_idx < 0) { + vstate.wiggle_frame = 0; + vstate.elapsed_time = 0; + } else if( + elements[vstate.selected].gp_idx >= 0 && + (event->type == InputTypePress || event->type == InputTypeRelease)) { + int gp_idx = elements[vstate.selected].gp_idx; + gpio_pin_config[gp_idx].user.prev_mode = gpio_pin_config[gp_idx].user.mode; + + vstate.view = CONFIG_MENU_VIEW; + vstate.config_menu_selected = CONFIG_MENU_MODE; + } + } else if(event->type == InputTypePress || event->type == InputTypeRepeat) { + switch(event->key) { + case InputKeyLeft: + vstate.selected--; + if(vstate.selected == GEARIC) + vstate.selected = PIN_1W; + else if(vstate.selected < 0) + vstate.selected = GEARIC; + break; + case InputKeyRight: + if(vstate.selected <= GEARIC) { + vstate.selected++; + vstate.selected = vstate.selected > GEARIC ? PIN_5V : vstate.selected; + } else { + vstate.selected++; + vstate.selected = vstate.selected > PIN_1W ? PIN_3V : vstate.selected; + } + break; + case InputKeyUp: + case InputKeyDown: + if(elements[vstate.selected].opposite != NONE) + vstate.selected = elements[vstate.selected].opposite; + break; + default: + break; + } + } + } +} + +static void set_GPIO_pin_via_user(int gp_idx) { + GPIOPin* gpc = &gpio_pin_config[gp_idx]; + + if(gpc->user.changed) { + // update attributes + switch(gpc->user.mode) { + case GPIO_MODE_INPUT: + gpc->mode = GpioModeInput; + gpc->pull = GpioPullNo; + gpc->input = true; + break; + case GPIO_MODE_INPUT_PULLUP: + gpc->mode = GpioModeInput; + gpc->pull = GpioPullUp; + gpc->input = true; + break; + case GPIO_MODE_OUTPUT: + gpc->mode = GpioModeOutputPushPull; + gpc->pull = GpioPullNo; + gpc->input = false; + break; + default: + break; + } + + switch(gpc->user.value) { + case GPIO_VALUE_TRUE: + gpc->value = (double)1.0; + break; + case GPIO_VALUE_FALSE: + case GPIO_VALUE_INPUT: + case GPIO_VALUE_NONE: + gpc->value = (double)0.0; + break; + default: + break; + } + + furi_hal_gpio_write(gpc->pin, gpc->value != (double)0.0 ? true : false); + if(gpc->user.mode != gpc->user.prev_mode) { + furi_hal_gpio_init(gpc->pin, gpc->mode, gpc->pull, gpc->speed); + gpc->unset = false; + } + + gpc->user.changed = false; + } +} - FuriMessageQueue* event_queue = ctx; - furi_message_queue_put(event_queue, input_event, FuriWaitForever); +static void handle_config_menu_input(InputEvent* event, void* ctx) { + UNUSED(ctx); + + int gp_idx = elements[vstate.selected].gp_idx; + GPIOPin* gpc = &gpio_pin_config[gp_idx]; + + if(event->type == InputTypePress || event->type == InputTypeRepeat) { + switch(event->key) { + case InputKeyLeft: + switch(vstate.config_menu_selected) { + case CONFIG_MENU_MODE: + if(gpc->user.mode > 0) { + gpc->user.mode--; + gpc->user.changed = true; + } + break; + case CONFIG_MENU_VALUE: + if(gpc->user.value > 0) { + gpc->user.value--; + gpc->user.changed = true; + } + break; + case CONFIG_MENU_INPUT: + break; + default: + break; + } + break; + case InputKeyRight: + switch(vstate.config_menu_selected) { + case CONFIG_MENU_MODE: + if(gpc->user.mode < GPIO_MODE_UNSET) { + gpc->user.mode++; + gpc->user.changed = true; + } + break; + case CONFIG_MENU_VALUE: + if(gpc->user.value < GPIO_VALUE_FALSE) { + gpc->user.value++; + gpc->user.changed = true; + } + break; + case CONFIG_MENU_INPUT: + break; + default: + break; + } + break; + case InputKeyUp: + if(gpc->user.mode == GPIO_MODE_OUTPUT) { + if(vstate.config_menu_selected == 0) + vstate.config_menu_selected = CONFIG_MENU_VALUE; + else + vstate.config_menu_selected--; + } + break; + case InputKeyDown: + if(gpc->user.mode == GPIO_MODE_OUTPUT) { + if(vstate.config_menu_selected == CONFIG_MENU_VALUE) + vstate.config_menu_selected = 0; + else + vstate.config_menu_selected++; + } + break; + case InputKeyBack: + + // Set new pin configuration + set_GPIO_pin_via_user(gp_idx); + + vstate.view = MAIN_VIEW; + + break; + default: + break; + } + } +} + +static void app_draw_callback(Canvas* canvas, void* ctx) { + draw_view_funcs[vstate.view](canvas, ctx); +} + +static void app_input_callback(InputEvent* input_event, void* ctx) { + input_handlers[vstate.view](input_event, ctx); } int32_t gpio_controller_main(void* p) { @@ -360,6 +542,7 @@ int32_t gpio_controller_main(void* p) { InputEvent event; + init_state(); init_gpio(); vstate.prev_frame_time = furi_get_tick(); @@ -368,52 +551,18 @@ int32_t gpio_controller_main(void* p) { bool running = true; while(running) { if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) { - if(vstate.wiggle_frame < 0) { - if((event.type == InputTypePress || event.type == InputTypeRelease) && - event.key == InputKeyOk) { - if(event.type == InputTypePress && elements[vstate.selected].gp_idx < 0) { - vstate.wiggle_frame = 0; - vstate.elapsed_time = 0; - } else if( - elements[vstate.selected].gp_idx >= 0 && - (event.type == InputTypePress || event.type == InputTypeRelease)) { - int gp_idx = elements[vstate.selected].gp_idx; - furi_hal_gpio_write( - gpio_pin_config[gp_idx].pin, event.type == InputTypePress); - gpio_pin_config[gp_idx].value = event.type == InputTypePress ? 1 : 0; - } - } else if(event.type == InputTypePress || event.type == InputTypeRepeat) { - switch(event.key) { - case InputKeyLeft: - vstate.selected--; - if(vstate.selected == GEARIC) - vstate.selected = PIN_1W; - else if(vstate.selected < 0) - vstate.selected = GEARIC; - break; - case InputKeyRight: - if(vstate.selected <= GEARIC) { - vstate.selected++; - vstate.selected = vstate.selected > GEARIC ? PIN_5V : vstate.selected; - } else { - vstate.selected++; - vstate.selected = vstate.selected > PIN_1W ? PIN_3V : vstate.selected; - } - break; - case InputKeyUp: - case InputKeyDown: - if(elements[vstate.selected].opposite != NONE) - vstate.selected = elements[vstate.selected].opposite; - break; - case InputKeyBack: - running = false; - break; - default: - break; - } + if(event.type == InputTypePress || event.type == InputTypeRepeat) { + switch(event.key) { + case InputKeyBack: + running = false; + break; + default: + break; } } } + + update_gpio(); view_port_update(view_port); } diff --git a/applications/external/gpio_controller/images/analog_box.png b/applications/external/gpio_controller/images/analog_box.png index e85cb2b03d2..655810619a9 100644 Binary files a/applications/external/gpio_controller/images/analog_box.png and b/applications/external/gpio_controller/images/analog_box.png differ diff --git a/applications/external/uhf_rfid/README.md b/applications/external/uhf_rfid/README.md index c3f05d6300a..c7bf4cb60e2 100644 --- a/applications/external/uhf_rfid/README.md +++ b/applications/external/uhf_rfid/README.md @@ -8,8 +8,8 @@ This repository contains a UHF RFID application developed for FlipperZero, a ver ## Features -- [ ] Read UHF RFID tags. -- [x] Write UHF RFID tags. +- [x] Read UHF RFID tags. +- [ ] Write UHF RFID tags. - [ ] Communicate with the YRM100 module to perform UHF RFID operations. - [ ] Easy-to-use interface on FlipperZero's display. @@ -22,8 +22,14 @@ To run this application on FlipperZero, you will need: ## Installation -1. Ensure you have set up your FlipperZero device with the YRM100 module properly. -2. Clone this repository to your FlipperZero using (add the specific instructions or link to the tool used for this). +1. Ensure you have set up your FlipperZero device with the YRM100 module properly. You can also read more about how to setup the module from the [Md5Stack Docs page](http://docs.m5stack.com/en/unit/uhf_rfid). + ![wiring diagram](https://static-cdn.m5stack.com/resource/docs/products/unit/uhf_rfid/uhf_rfid_sch_01.webp) +2. Clone this repository to the `applications_user` folder of your flipper firmware of your choice +3. If you have VSCode setup with your flipper firmware. + - ### Windows + 1. Press `Ctrl+Shift+B` on vscode while in the uhf_app folder + 2. Select the `Launch App on Flipper` option. And watch as the app launches on your flipper + - If you don't have vscode setup you can use the cli command `./fbt COMPACT=1 DEBUG=0 launch APPSRC=applications_user\uhf_rfid` ## Usage @@ -45,12 +51,14 @@ This project is licensed under the [MIT License](link_to_license_file). --> - Use it at your own risk. - I am not responsible for any damage or loss caused by the usage of this app. +## Extra Resources + +- [MagicRF M100&QM100_Firmware_manual_en.pdf](assets/res/MagicRF_M100&QM100_Firmware_manual_en.pdf) + ## Contact For any inquiries or support, you can reach out to us at : + - Personal Email : [frux.infoc@gmail.com](mailto:frux.infoc@gmail.com) - Discord Server: [Flipper Zero Tutorial-Unoffical by @jamisonderek](https://discord.gg/REunuAnTX9) - Discord User: [frux.c]() - - - diff --git a/applications/external/uhf_rfid/assets/res/MagicRF_M100&QM100_Firmware_manual_en.pdf b/applications/external/uhf_rfid/assets/res/MagicRF_M100&QM100_Firmware_manual_en.pdf new file mode 100644 index 00000000000..aaa4dd77b3d Binary files /dev/null and b/applications/external/uhf_rfid/assets/res/MagicRF_M100&QM100_Firmware_manual_en.pdf differ diff --git a/applications/external/uhf_rfid/scenes/uhf_scene_card_menu.c b/applications/external/uhf_rfid/scenes/uhf_scene_card_menu.c index 08aa2d3f538..66063ed3765 100644 --- a/applications/external/uhf_rfid/scenes/uhf_scene_card_menu.c +++ b/applications/external/uhf_rfid/scenes/uhf_scene_card_menu.c @@ -5,26 +5,18 @@ enum SubmenuIndex { SubmenuIndexChangeKey, }; -void uhf_scene_card_menu_submenu_callback(void* context, uint32_t index) { - UHFApp* uhf_app = context; +void uhf_scene_card_menu_submenu_callback(void* ctx, uint32_t index) { + UHFApp* uhf_app = ctx; view_dispatcher_send_custom_event(uhf_app->view_dispatcher, index); } -void uhf_scene_card_menu_on_enter(void* context) { - UHFApp* uhf_app = context; +void uhf_scene_card_menu_on_enter(void* ctx) { + UHFApp* uhf_app = ctx; Submenu* submenu = uhf_app->submenu; submenu_add_item( submenu, "Save", SubmenuIndexSave, uhf_scene_card_menu_submenu_callback, uhf_app); - // if(picopass->dev->dev_data.pacs.record.valid) { - // submenu_add_item( - // submenu, - // "Save as LF", - // SubmenuIndexSaveAsLF, - // picopass_scene_card_menu_submenu_callback, - // picopass); - // } submenu_add_item( submenu, "Change Key", @@ -38,12 +30,11 @@ void uhf_scene_card_menu_on_enter(void* context) { view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewMenu); } -bool uhf_scene_card_menu_on_event(void* context, SceneManagerEvent event) { - UHFApp* uhf_app = context; +bool uhf_scene_card_menu_on_event(void* ctx, SceneManagerEvent event) { + UHFApp* uhf_app = ctx; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - FURI_LOG_E("LOG", "%lu", event.event); if(event.event == SubmenuIndexSave) { scene_manager_set_scene_state( uhf_app->scene_manager, UHFSceneCardMenu, SubmenuIndexSave); @@ -64,8 +55,8 @@ bool uhf_scene_card_menu_on_event(void* context, SceneManagerEvent event) { return consumed; } -void uhf_scene_card_menu_on_exit(void* context) { - UHFApp* uhf_app = context; +void uhf_scene_card_menu_on_exit(void* ctx) { + UHFApp* uhf_app = ctx; submenu_reset(uhf_app->submenu); } diff --git a/applications/external/uhf_rfid/scenes/uhf_scene_config.h b/applications/external/uhf_rfid/scenes/uhf_scene_config.h index 7a280744dba..0c0f499c2c4 100644 --- a/applications/external/uhf_rfid/scenes/uhf_scene_config.h +++ b/applications/external/uhf_rfid/scenes/uhf_scene_config.h @@ -1,3 +1,4 @@ +ADD_SCENE(uhf, verify, Verify) ADD_SCENE(uhf, start, Start) ADD_SCENE(uhf, read_tag, ReadTag) ADD_SCENE(uhf, read_tag_success, ReadTagSuccess) diff --git a/applications/external/uhf_rfid/scenes/uhf_scene_read_tag.c b/applications/external/uhf_rfid/scenes/uhf_scene_read_tag.c index e71f6e41ca9..d0a8678c6c2 100644 --- a/applications/external/uhf_rfid/scenes/uhf_scene_read_tag.c +++ b/applications/external/uhf_rfid/scenes/uhf_scene_read_tag.c @@ -12,7 +12,6 @@ void uhf_read_tag_worker_callback(UHFWorkerEvent event, void* ctx) { } void uhf_scene_read_tag_on_enter(void* ctx) { - // FURI_LOG_E("33", "uhf_scene_read_tag_on_enter was called!"); UHFApp* uhf_app = ctx; dolphin_deed(DolphinDeedNfcRead); @@ -23,7 +22,8 @@ void uhf_scene_read_tag_on_enter(void* ctx) { // Start worker view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewPopup); - uhf_worker_start(uhf_app->worker, UHFWorkerStateDetect, uhf_read_tag_worker_callback, uhf_app); + uhf_worker_start( + uhf_app->worker, UHFWorkerStateDetectSingle, uhf_read_tag_worker_callback, uhf_app); uhf_blink_start(uhf_app); } @@ -33,7 +33,6 @@ bool uhf_scene_read_tag_on_event(void* ctx, SceneManagerEvent event) { UHFApp* uhf_app = ctx; bool consumed = false; if(event.event == UHFCustomEventWorkerExit) { - FURI_LOG_E("uhf_scene_read_tag_on_event", "event was registered"); scene_manager_next_scene(uhf_app->scene_manager, UHFSceneReadTagSuccess); consumed = true; } diff --git a/applications/external/uhf_rfid/scenes/uhf_scene_read_tag_success.c b/applications/external/uhf_rfid/scenes/uhf_scene_read_tag_success.c index 8b5831c5e85..313a3540238 100644 --- a/applications/external/uhf_rfid/scenes/uhf_scene_read_tag_success.c +++ b/applications/external/uhf_rfid/scenes/uhf_scene_read_tag_success.c @@ -15,10 +15,9 @@ void uhf_scene_read_card_success_widget_callback(GuiButtonType result, InputType } void uhf_scene_read_tag_success_on_enter(void* ctx) { - // UNUSED(ctx); UHFApp* uhf_app = ctx; - const uint8_t* read_data = uhf_app->worker->data->data->data; + const uint8_t* read_data = uhf_app->worker->response_data->head->data; widget_add_string_element( uhf_app->widget, 32, 5, AlignLeft, AlignCenter, FontPrimary, "Read Success"); @@ -78,7 +77,6 @@ bool uhf_scene_read_tag_success_on_event(void* ctx, SceneManagerEvent event) { UHFApp* uhf_app = ctx; bool consumed = false; if(event.event == SceneManagerEventTypeBack) { - // FURI_LOG_E("36", "Back button was pressed"); uhf_app->worker->state = UHFWorkerStateStop; } if(event.type == SceneManagerEventTypeCustom) { @@ -101,7 +99,7 @@ void uhf_scene_read_tag_success_on_exit(void* ctx) { UHFApp* uhf_app = ctx; // // Stop worker - // uhf_worker_stop(uhf_app->worker); + uhf_worker_stop(uhf_app->worker); // Clear view popup_reset(uhf_app->popup); // clear widget diff --git a/applications/external/uhf_rfid/scenes/uhf_scene_save_name.c b/applications/external/uhf_rfid/scenes/uhf_scene_save_name.c index 41c677ee5f1..6fa79b5d084 100644 --- a/applications/external/uhf_rfid/scenes/uhf_scene_save_name.c +++ b/applications/external/uhf_rfid/scenes/uhf_scene_save_name.c @@ -45,11 +45,11 @@ void uhf_scene_save_name_on_enter(void* context) { bool uhf_scene_save_name_on_event(void* context, SceneManagerEvent event) { UHFApp* uhf_app = context; - UHFResponseData* uhf_data_save = uhf_app->worker->data; + UHFResponseData* uhf_data_save = uhf_app->worker->response_data; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == UHFCustomEventTextInputDone) { - if(uhf_save_data(uhf_data_save, uhf_app->storage, uhf_app->text_store)) { + if(uhf_save_read_data(uhf_data_save, uhf_app->storage, uhf_app->text_store)) { scene_manager_next_scene(uhf_app->scene_manager, UHFSceneSaveSuccess); consumed = true; } else { diff --git a/applications/external/uhf_rfid/scenes/uhf_scene_start.c b/applications/external/uhf_rfid/scenes/uhf_scene_start.c index cf00f764f3a..c8c419d1d14 100644 --- a/applications/external/uhf_rfid/scenes/uhf_scene_start.c +++ b/applications/external/uhf_rfid/scenes/uhf_scene_start.c @@ -27,7 +27,6 @@ bool uhf_scene_start_on_event(void* ctx, SceneManagerEvent event) { UHFApp* uhf_app = ctx; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - // FURI_LOG_E("scene_start_on_event", "%lu", event.event); if(event.event == SubmenuIndexRead) { scene_manager_set_scene_state(uhf_app->scene_manager, UHFSceneStart, SubmenuIndexRead); scene_manager_next_scene(uhf_app->scene_manager, UHFSceneReadTag); diff --git a/applications/external/uhf_rfid/scenes/uhf_scene_verify.c b/applications/external/uhf_rfid/scenes/uhf_scene_verify.c new file mode 100644 index 00000000000..2b32d79d48a --- /dev/null +++ b/applications/external/uhf_rfid/scenes/uhf_scene_verify.c @@ -0,0 +1,147 @@ +#include "../uhf_app_i.h" + +bool verify_success = false; +FuriString* temp_str; + +void uhf_scene_verify_callback_event(UHFWorkerEvent event, void* ctx) { + UNUSED(ctx); + UHFApp* uhf_app = ctx; + if(event == UHFWorkerEventSuccess) verify_success = true; + + view_dispatcher_send_custom_event(uhf_app->view_dispatcher, UHFCustomEventVerifyDone); +} + +void uhf_scene_verify_widget_callback(GuiButtonType result, InputType type, void* ctx) { + furi_assert(ctx); + UHFApp* uhf_app = ctx; + + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(uhf_app->view_dispatcher, result); + } +} + +void uhf_scene_verify_on_enter(void* ctx) { + UHFApp* uhf_app = ctx; + uhf_worker_start( + uhf_app->worker, UHFWorkerStateVerify, uhf_scene_verify_callback_event, uhf_app); + temp_str = furi_string_alloc(); + view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewWidget); +} + +bool uhf_scene_verify_on_event(void* ctx, SceneManagerEvent event) { + UHFApp* uhf_app = ctx; + bool consumed = false; + if(event.event == SceneManagerEventTypeBack) { + uhf_app->worker->state = UHFWorkerStateStop; + } else if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(uhf_app->scene_manager, UHFSceneStart); + consumed = true; + } else if(event.event == GuiButtonTypeLeft) { + if(!verify_success) { + widget_reset(uhf_app->widget); + furi_string_reset(temp_str); + uhf_worker_stop(uhf_app->worker); + uhf_worker_start( + uhf_app->worker, + UHFWorkerStateVerify, + uhf_scene_verify_callback_event, + uhf_app); + } + } else if(event.event == UHFCustomEventVerifyDone) { + if(verify_success) { + widget_reset(uhf_app->widget); + furi_string_reset(temp_str); + UHFResponseData* uhf_response_data = uhf_app->worker->response_data; + UHFData* hardware_version = uhf_response_data_get_uhf_data(uhf_response_data, 0); + UHFData* software_version = uhf_response_data_get_uhf_data(uhf_response_data, 1); + UHFData* manufacturer = uhf_response_data_get_uhf_data(uhf_response_data, 2); + uint offset = 6; + widget_add_string_element( + uhf_app->widget, 64, 5, AlignCenter, AlignCenter, FontPrimary, "Module Info"); + // hardware info + furi_string_cat_str(temp_str, "HW Version: "); + for(int i = 0; i < 10; i++) { + furi_string_cat_printf(temp_str, "%c", hardware_version->data[offset + i]); + } + widget_add_string_element( + uhf_app->widget, + 1, + 15, + AlignLeft, + AlignCenter, + FontSecondary, + furi_string_get_cstr(temp_str)); + furi_string_reset(temp_str); + // software info + furi_string_cat_str(temp_str, "SW Version: "); + for(int i = 0; i < 10; i++) { + furi_string_cat_printf(temp_str, "%c", software_version->data[offset + i]); + } + widget_add_string_element( + uhf_app->widget, + 1, + 27, + AlignLeft, + AlignCenter, + FontSecondary, + furi_string_get_cstr(temp_str)); + furi_string_reset(temp_str); + // manufacturer info + furi_string_cat_str(temp_str, "Manufacturer: "); + for(int i = 0; i < 10; i++) { + furi_string_cat_printf(temp_str, "%c", manufacturer->data[offset + i]); + } + widget_add_string_element( + uhf_app->widget, + 1, + 39, + AlignLeft, + AlignCenter, + FontSecondary, + furi_string_get_cstr(temp_str)); + + widget_add_button_element( + uhf_app->widget, + GuiButtonTypeRight, + "Continue", + uhf_scene_verify_widget_callback, + uhf_app); + } else { + widget_add_string_element( + uhf_app->widget, + 64, + 5, + AlignCenter, + AlignCenter, + FontPrimary, + "No UHF Module found"); + widget_add_button_element( + uhf_app->widget, + GuiButtonTypeLeft, + "Retry", + uhf_scene_verify_widget_callback, + uhf_app); + widget_add_button_element( + uhf_app->widget, + GuiButtonTypeRight, + "Skip", + uhf_scene_verify_widget_callback, + uhf_app); + } + } + } + return consumed; +} + +void uhf_scene_verify_on_exit(void* ctx) { + UHFApp* uhf_app = ctx; + // Clear string + furi_string_free(temp_str); + // Stop worker + uhf_worker_stop(uhf_app->worker); + // Clear view + // popup_reset(uhf_app->popup); + // clear widget + widget_reset(uhf_app->widget); +} \ No newline at end of file diff --git a/applications/external/uhf_rfid/uhf_app.c b/applications/external/uhf_rfid/uhf_app.c index a1132041daa..7a114de2976 100644 --- a/applications/external/uhf_rfid/uhf_app.c +++ b/applications/external/uhf_rfid/uhf_app.c @@ -3,6 +3,13 @@ static const char* uhf_file_header = "Flipper UHF device"; static const uint32_t uhf_file_version = 1; +// empty callback +void empty_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) { + UNUSED(event); + UNUSED(data); + UNUSED(ctx); +} + char* convertToHexString(const uint8_t* array, size_t length) { if(array == NULL || length == 0) { return NULL; @@ -26,7 +33,7 @@ char* convertToHexString(const uint8_t* array, size_t length) { return hexArray; } -bool uhf_save_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename) { +bool uhf_save_read_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename) { if(!storage_dir_exists(storage, UHF_APPS_DATA_FOLDER)) { storage_simply_mkdir(storage, UHF_APPS_DATA_FOLDER); } @@ -45,7 +52,7 @@ bool uhf_save_data(UHFResponseData* uhf_response_data, Storage* storage, const c if(!flipper_format_write_header_cstr(file, uhf_file_header, uhf_file_version)) return false; // write epc bank if(!flipper_format_write_hex( - file, "EPC", uhf_response_data->data->data, uhf_response_data->data->length)) + file, "EPC", uhf_response_data->head->data, uhf_response_data->head->length)) return false; furi_string_free(temp_str); flipper_format_free(file); @@ -170,20 +177,6 @@ void uhf_free(UHFApp* uhf_app) { free(uhf_app); } -// void uhf_text_store_set(UHFApp* uhf_app, const char* text, ...) { -// va_list args; -// va_start(args, text); - -// vsnprintf(uhf_app->text_store, sizeof(uhf_app->text_store), text, args); - -// va_end(args); -// } - -// void uhf_text_store_clear(UHFApp* uhf_app) { -// memset(uhf_app->text_store, 0, sizeof(uhf_app->text_store)); -// } - -// ================== static const NotificationSequence uhf_sequence_blink_start_cyan = { &message_blink_start_10, &message_blink_set_color_cyan, @@ -222,9 +215,19 @@ int32_t uhf_app_main(void* ctx) { UNUSED(ctx); UHFApp* uhf_app = uhf_alloc(); - scene_manager_next_scene(uhf_app->scene_manager, UHFSceneStart); + // enable 5v pin + furi_hal_power_enable_otg(); + + scene_manager_next_scene(uhf_app->scene_manager, UHFSceneVerify); view_dispatcher_run(uhf_app->view_dispatcher); + // disable 5v pin + furi_hal_power_disable_otg(); + + // set uart callback to none + furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, empty_rx_callback, NULL); + + // exit app uhf_free(uhf_app); return 0; } \ No newline at end of file diff --git a/applications/external/uhf_rfid/uhf_app_i.h b/applications/external/uhf_rfid/uhf_app_i.h index 884ea38a97f..5f8473b52aa 100644 --- a/applications/external/uhf_rfid/uhf_app_i.h +++ b/applications/external/uhf_rfid/uhf_app_i.h @@ -26,9 +26,6 @@ #include "uhf_worker.h" #include -#define UHF_FILE_HEADER \ - "Filetype: Flipper uhf data\n" \ - "Version: 1" #define UHF_TEXT_STORE_SIZE 128 #define UHF_APPS_DATA_FOLDER EXT_PATH("apps_data") #define UHF_APPS_STORAGE_FOLDER \ @@ -40,6 +37,7 @@ enum UHFCustomEvent { // Reserve first 100 events for button types and indexes, starting from 0 UHFCustomEventReserved = 100, + UHFCustomEventVerifyDone, UHFCustomEventViewExit, UHFCustomEventWorkerExit, UHFCustomEventByteInputDone, @@ -104,4 +102,4 @@ bool uhf_is_memset(const uint8_t* data, const uint8_t pattern, size_t size); char* convertToHexString(const uint8_t* array, size_t length); -bool uhf_save_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename); \ No newline at end of file +bool uhf_save_read_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename); \ No newline at end of file diff --git a/applications/external/uhf_rfid/uhf_data.c b/applications/external/uhf_rfid/uhf_data.c index 2cf6637af83..dc9c7787f43 100644 --- a/applications/external/uhf_rfid/uhf_data.c +++ b/applications/external/uhf_rfid/uhf_data.c @@ -35,33 +35,54 @@ void uhf_data_reset(UHFData* uhf_data) { } void uhf_data_free(UHFData* uhf_data) { - if(uhf_data != NULL) { - while(uhf_data != NULL) { - UHFData* next = uhf_data->next; - free(uhf_data); - uhf_data = next; - } + if(uhf_data == NULL) return; + while(uhf_data != NULL) { + UHFData* next = uhf_data->next; + free(uhf_data); + uhf_data = next; } } UHFResponseData* uhf_response_data_alloc() { UHFResponseData* uhf_response_data = (UHFResponseData*)malloc(sizeof(UHFResponseData)); - uhf_response_data->data = uhf_data_alloc(); - uhf_response_data->size = 0; + uhf_response_data->head = uhf_data_alloc(); + uhf_response_data->tail = uhf_response_data->head; + uhf_response_data->size = 1; return uhf_response_data; } -UHFData* add_uhf_data_to_uhf_response_data(UHFResponseData* uhf_response_data) { - UHFData* next = uhf_response_data->data; - while(next->next != NULL) { - next = next->next; +UHFData* uhf_response_data_add_new_uhf_data(UHFResponseData* uhf_response_data) { + UHFData* temp = uhf_response_data->head; + while(temp->next != NULL) { + temp = temp->next; } - next->next = uhf_data_alloc(); + temp->next = uhf_data_alloc(); uhf_response_data->size++; - return next->next; + uhf_response_data->tail = temp->next; + return temp->next; +} + +UHFData* uhf_response_data_get_uhf_data(UHFResponseData* uhf_response_data, uint index) { + if(uhf_response_data == NULL || uhf_response_data->size <= index) return NULL; + UHFData* uhf_data = uhf_response_data->head; + if(index == 0) return uhf_data; + while(uhf_data != NULL && index >= 1) { + uhf_data = uhf_data->next; + index--; + } + return uhf_data; +} + +void uhf_response_data_reset(UHFResponseData* uhf_response_data) { + uhf_data_reset(uhf_response_data->head); + if(uhf_response_data->size == 1) { + return; + } + uhf_data_free(uhf_response_data->head->next); + uhf_response_data->size = 1; } void uhf_response_data_free(UHFResponseData* uhf_response_data) { - uhf_data_free(uhf_response_data->data); + uhf_data_free(uhf_response_data->head); free(uhf_response_data); } \ No newline at end of file diff --git a/applications/external/uhf_rfid/uhf_data.h b/applications/external/uhf_rfid/uhf_data.h index f8d94a1f0b9..42682db1a7c 100644 --- a/applications/external/uhf_rfid/uhf_data.h +++ b/applications/external/uhf_rfid/uhf_data.h @@ -14,7 +14,8 @@ typedef struct UHFData { } UHFData; typedef struct UHFResponseData { - UHFData* data; + UHFData* head; + UHFData* tail; size_t size; } UHFResponseData; @@ -25,5 +26,7 @@ void uhf_data_reset(UHFData* uhf_data); void uhf_data_free(UHFData* uhf_data); UHFResponseData* uhf_response_data_alloc(); -UHFData* add_uhf_data_to_uhf_response_data(UHFResponseData* uhf_response_data); +UHFData* uhf_response_data_add_new_uhf_data(UHFResponseData* uhf_response_data); +UHFData* uhf_response_data_get_uhf_data(UHFResponseData* uhf_response_data, uint index); +void uhf_response_data_reset(UHFResponseData* uhf_response_data); void uhf_response_data_free(UHFResponseData* uhf_response_data); \ No newline at end of file diff --git a/applications/external/uhf_rfid/uhf_worker.c b/applications/external/uhf_rfid/uhf_worker.c index 34d02ea8ffb..a68d03ce9d8 100644 --- a/applications/external/uhf_rfid/uhf_worker.c +++ b/applications/external/uhf_rfid/uhf_worker.c @@ -1,32 +1,74 @@ #include "uhf_worker.h" #include "uhf_cmd.h" -void single_poll_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) { +// uart callback functions +void module_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) { UNUSED(event); - UHFResponseData* response_data = ctx; - UHFData* first_data = response_data->data; - uhf_data_append(first_data, data); + UHFData* uhf_data = ctx; + uhf_data_append(uhf_data, data); + // FURI_LOG_E("module_rx_callback", "%02x", data); +} + +// yrm100 module commands +UHFWorkerEvent verify_module_connected(UHFWorker* uhf_worker) { + UHFResponseData* uhf_response_data = uhf_worker->response_data; + uhf_response_data_reset(uhf_response_data); + FURI_LOG_E("log", "freeing done"); + UHFData* hardware_version = uhf_response_data->head; + UHFData* software_version = uhf_response_data_add_new_uhf_data(uhf_response_data); + UHFData* manufacturer = uhf_response_data_add_new_uhf_data(uhf_response_data); + FURI_LOG_E("log", "alloc done"); + furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUD_RATE); + // read hardware version + furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, hardware_version); + furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_HARDWARE_VERSION.cmd, CMD_HARDWARE_VERSION.length); + furi_delay_ms(150); + // read software version + furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, software_version); + furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_SOFTWARE_VERSION.cmd, CMD_SOFTWARE_VERSION.length); + furi_delay_ms(150); + // read manufacturer + furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, manufacturer); + furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_MANUFACTURERS.cmd, CMD_MANUFACTURERS.length); + furi_delay_ms(150); + FURI_LOG_E("log", "done sending tx"); + if(!hardware_version->end || !software_version->end || !manufacturer->end) { + return UHFWorkerEventFail; + } + return UHFWorkerEventSuccess; } UHFWorkerEvent read_single_card(UHFWorker* uhf_worker) { - UHFResponseData* uhf_response_data = uhf_worker->data; + UHFResponseData* uhf_response_data = uhf_worker->response_data; + UHFData* uhf_data = uhf_response_data->head; furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUD_RATE); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, single_poll_rx_callback, uhf_response_data); - UHFData* uhf_data = uhf_response_data->data; + furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, uhf_data); uhf_data_reset(uhf_data); - while(!uhf_data->end) { + while(true) { furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_SINGLE_POLLING.cmd, CMD_SINGLE_POLLING.length); furi_delay_ms(100); if(uhf_worker->state == UHFWorkerStateStop) { return UHFWorkerEventAborted; } + if(uhf_data->end) { + // before breaking, check if the response is not an error + // index 1 = response type, index 5 = parameter + if(uhf_data->data[1] == 0x01 && uhf_data->data[5] == 0x15) { + continue; + } else if(uhf_data->data[1] == 0x02) + break; // success read + } } return UHFWorkerEventSuccess; } int32_t uhf_worker_task(void* ctx) { UHFWorker* uhf_worker = ctx; - if(uhf_worker->state == UHFWorkerStateDetect) { + if(uhf_worker->state == UHFWorkerStateVerify) { + UHFWorkerEvent event = verify_module_connected(uhf_worker); + uhf_worker->callback(event, uhf_worker->ctx); + } + if(uhf_worker->state == UHFWorkerStateDetectSingle) { UHFWorkerEvent event = read_single_card(uhf_worker); uhf_worker->callback(event, uhf_worker->ctx); } @@ -36,7 +78,7 @@ int32_t uhf_worker_task(void* ctx) { UHFWorker* uhf_worker_alloc() { UHFWorker* uhf_worker = (UHFWorker*)malloc(sizeof(UHFWorker)); uhf_worker->thread = furi_thread_alloc_ex("UHFWorker", 8 * 1024, uhf_worker_task, uhf_worker); - uhf_worker->data = uhf_response_data_alloc(); + uhf_worker->response_data = uhf_response_data_alloc(); uhf_worker->callback = NULL; uhf_worker->ctx = NULL; return uhf_worker; @@ -70,6 +112,6 @@ void uhf_worker_stop(UHFWorker* uhf_worker) { void uhf_worker_free(UHFWorker* uhf_worker) { furi_assert(uhf_worker); furi_thread_free(uhf_worker->thread); - uhf_response_data_free(uhf_worker->data); + uhf_response_data_free(uhf_worker->response_data); free(uhf_worker); } \ No newline at end of file diff --git a/applications/external/uhf_rfid/uhf_worker.h b/applications/external/uhf_rfid/uhf_worker.h index fceb0a0dcad..7d4cb05331d 100644 --- a/applications/external/uhf_rfid/uhf_worker.h +++ b/applications/external/uhf_rfid/uhf_worker.h @@ -9,9 +9,10 @@ typedef enum { UHFWorkerStateNone, UHFWorkerStateBroken, UHFWorkerStateReady, + UHFWorkerStateVerify, // Main worker states - UHFWorkerStateDetect, - UHFWorkerStateWrite, + UHFWorkerStateDetectSingle, + UHFWorkerStateWriteSingle, UHFWorkerStateWriteKey, // Transition UHFWorkerStateStop, @@ -29,7 +30,7 @@ typedef void (*UHFWorkerCallback)(UHFWorkerEvent event, void* ctx); typedef struct UHFWorker { FuriThread* thread; - UHFResponseData* data; + UHFResponseData* response_data; UHFWorkerCallback callback; UHFWorkerState state; void* ctx; diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Google_Modern.html b/assets/resources/apps_data/esp32_evil_portal/html/Google_Modern.html deleted file mode 100644 index 79b96b84c6c..00000000000 --- a/assets/resources/apps_data/esp32_evil_portal/html/Google_Modern.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - diff --git a/assets/resources/apps_data/esp32_evil_portal/index.html b/assets/resources/apps_data/esp32_evil_portal/index.html deleted file mode 100644 index 50eb181e4bb..00000000000 --- a/assets/resources/apps_data/esp32_evil_portal/index.html +++ /dev/null @@ -1 +0,0 @@ -

Sign in

Use your Google Account

\ No newline at end of file diff --git a/assets/resources/apps_data/esp32_evil_portal/ap.config.txt b/assets/resources/apps_data/evil_portal/ap.config.txt similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/ap.config.txt rename to assets/resources/apps_data/evil_portal/ap.config.txt diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Alaska_Airlines.html b/assets/resources/apps_data/evil_portal/html/Alaska_Airlines.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Alaska_Airlines.html rename to assets/resources/apps_data/evil_portal/html/Alaska_Airlines.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Amazon.html b/assets/resources/apps_data/evil_portal/html/Amazon.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Amazon.html rename to assets/resources/apps_data/evil_portal/html/Amazon.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/American_Airlines.html b/assets/resources/apps_data/evil_portal/html/American_Airlines.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/American_Airlines.html rename to assets/resources/apps_data/evil_portal/html/American_Airlines.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Apple.html b/assets/resources/apps_data/evil_portal/html/Apple.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Apple.html rename to assets/resources/apps_data/evil_portal/html/Apple.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/CoxWifi.html b/assets/resources/apps_data/evil_portal/html/CoxWifi.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/CoxWifi.html rename to assets/resources/apps_data/evil_portal/html/CoxWifi.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Detla_Airlines.html b/assets/resources/apps_data/evil_portal/html/Detla_Airlines.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Detla_Airlines.html rename to assets/resources/apps_data/evil_portal/html/Detla_Airlines.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Facebook.html b/assets/resources/apps_data/evil_portal/html/Facebook.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Facebook.html rename to assets/resources/apps_data/evil_portal/html/Facebook.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/FakeHack.html b/assets/resources/apps_data/evil_portal/html/FakeHack.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/FakeHack.html rename to assets/resources/apps_data/evil_portal/html/FakeHack.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/FakeHack2.html b/assets/resources/apps_data/evil_portal/html/FakeHack2.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/FakeHack2.html rename to assets/resources/apps_data/evil_portal/html/FakeHack2.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Google_Mobile.html b/assets/resources/apps_data/evil_portal/html/Google_Mobile.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Google_Mobile.html rename to assets/resources/apps_data/evil_portal/html/Google_Mobile.html diff --git a/assets/resources/apps_data/evil_portal/html/Google_Modern.html b/assets/resources/apps_data/evil_portal/html/Google_Modern.html new file mode 100644 index 00000000000..f7267e5ca44 --- /dev/null +++ b/assets/resources/apps_data/evil_portal/html/Google_Modern.html @@ -0,0 +1 @@ +

English (United States)

Help Privacy Terms \ No newline at end of file diff --git a/assets/resources/apps_data/esp32_evil_portal/html/JetBlue.html b/assets/resources/apps_data/evil_portal/html/JetBlue.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/JetBlue.html rename to assets/resources/apps_data/evil_portal/html/JetBlue.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Matrix.html b/assets/resources/apps_data/evil_portal/html/Matrix.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Matrix.html rename to assets/resources/apps_data/evil_portal/html/Matrix.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Microsoft.html b/assets/resources/apps_data/evil_portal/html/Microsoft.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Microsoft.html rename to assets/resources/apps_data/evil_portal/html/Microsoft.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/PornHub.html b/assets/resources/apps_data/evil_portal/html/PornHub.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/PornHub.html rename to assets/resources/apps_data/evil_portal/html/PornHub.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Prank_Game.html b/assets/resources/apps_data/evil_portal/html/Prank_Game.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Prank_Game.html rename to assets/resources/apps_data/evil_portal/html/Prank_Game.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/README.md b/assets/resources/apps_data/evil_portal/html/README.md similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/README.md rename to assets/resources/apps_data/evil_portal/html/README.md diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Southwest_Airlines.html b/assets/resources/apps_data/evil_portal/html/Southwest_Airlines.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Southwest_Airlines.html rename to assets/resources/apps_data/evil_portal/html/Southwest_Airlines.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Spectrum.html b/assets/resources/apps_data/evil_portal/html/Spectrum.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Spectrum.html rename to assets/resources/apps_data/evil_portal/html/Spectrum.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/SpiritAirlines.html b/assets/resources/apps_data/evil_portal/html/SpiritAirlines.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/SpiritAirlines.html rename to assets/resources/apps_data/evil_portal/html/SpiritAirlines.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Starlink.html b/assets/resources/apps_data/evil_portal/html/Starlink.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Starlink.html rename to assets/resources/apps_data/evil_portal/html/Starlink.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/T_Mobile.html b/assets/resources/apps_data/evil_portal/html/T_Mobile.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/T_Mobile.html rename to assets/resources/apps_data/evil_portal/html/T_Mobile.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Twitch.html b/assets/resources/apps_data/evil_portal/html/Twitch.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Twitch.html rename to assets/resources/apps_data/evil_portal/html/Twitch.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Twitter.html b/assets/resources/apps_data/evil_portal/html/Twitter.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Twitter.html rename to assets/resources/apps_data/evil_portal/html/Twitter.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/United_Airlines.html b/assets/resources/apps_data/evil_portal/html/United_Airlines.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/United_Airlines.html rename to assets/resources/apps_data/evil_portal/html/United_Airlines.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/Verizon.html b/assets/resources/apps_data/evil_portal/html/Verizon.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/Verizon.html rename to assets/resources/apps_data/evil_portal/html/Verizon.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/at&t.html b/assets/resources/apps_data/evil_portal/html/at&t.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/at&t.html rename to assets/resources/apps_data/evil_portal/html/at&t.html diff --git a/assets/resources/apps_data/esp32_evil_portal/html/instagram.html b/assets/resources/apps_data/evil_portal/html/instagram.html similarity index 100% rename from assets/resources/apps_data/esp32_evil_portal/html/instagram.html rename to assets/resources/apps_data/evil_portal/html/instagram.html diff --git a/assets/resources/apps_data/evil_portal/index.html b/assets/resources/apps_data/evil_portal/index.html new file mode 100644 index 00000000000..f7267e5ca44 --- /dev/null +++ b/assets/resources/apps_data/evil_portal/index.html @@ -0,0 +1 @@ +

English (United States)

Help Privacy Terms \ No newline at end of file