diff --git a/.gitignore b/.gitignore index f598b674b..eacfec1e4 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,7 @@ bindings/ Brewfile.lock.json # Visual Studio Code -.vscode/ +/.vscode/ # Kate .kateproject diff --git a/CHANGELOG.md b/CHANGELOG.md index 63d36c013..f84b0985b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,23 @@ ### New changes -* **SubGHz: Keyboard lock fixed** -### Previous changes -* SubGHz: AN-Motors AT4 - Add manually fixes -* SubGHz: StarLine ignore option (in Read -> Config) (by @gid9798 | PR #410) -* Plugins: Fix `Repeat: 200` bug in SubGHz Remote and Bruteforcer -* Plugins: Update **TOTP (Authenticator)** [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) (Steam guard support) -* Plugins: Update **UART Terminal** [(by cool4uma)](https://github.com/cool4uma/UART_Terminal/tree/main) (AT commands support) -* Plugins: Add IR Scope app. (by @kallanreed | PR #407) -* OFW: scripts: sconsdist: added stub file artifact for older ufbt -* OFW: Graphics cleanup and icon rotation -* OFW: Moved ufbt to fbt codebase -* OFW: SD Driver: do not cache sd status. -* OFW: Furi: more gpio checks in HAL -* OFW: WeatherStation: fix protocol TX141TH-BV2 +* If you have copied apps into `apps` folder - remove `apps` folder on your microSD before installing this release to avoid issues! +* SubGHz: (Bug that I decided to keep as a feature) You can change default button (Ok) for remote by holding custom button and pressing back at same time (same can be used to restore your button if you changed it accidentally) - Be careful, it might be unstable, I will make proper option to change button in next releases +* SubGHz: Fixes for custom button bugs in SubGHz Remote app +* SubGHz: Add alutech table to enviroment alloc and free +* Docs: Fix and update docs - thanks to @lesterrry +* Plugins: Bluetooth Remote - implemented YouTube Shorts Remote (may be unstable) +* Plugins: Bluetooth Remote - improvements and fixes for TikTok remote (by @krolchonok | PR #420) +* Plugins: Implement an array for baudrates on GPS UART app (+ add 19200 baud) (by @p0ns | PR #416) +* Plugins: Remove UART Echo from releases since it is locked on 115200 baud, and we have **UART Terminal** with ability to set baudrate +* Plugins: Update **TOTP (Authenticator)** [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) +* Plugins: Update **UART Terminal** [(by cool4uma)](https://github.com/cool4uma/UART_Terminal/tree/main) +* OFW: Deep Sleep Idle - **Improves battery usage!!!** -> **Breaking API change, api was changed from 21.x to 22.x** +* OFW: FuriHal: pwr pulls for some pins +* OFW: Bugfix: ISP Programmer and SubGhz +* OFW: AVR_ISP: fix NULL pointer dereference +* OFW: Fix gpio state isp programmer +* OFW: ufbt: project & debugging updates +* OFW: FuriHal: fix gpio naming and add explicit pulls for vibro, speaker and ir_tx -> **Breaking API change, api was changed from 20.x to 21.x** +**(this will make your manually copied plugins not work, update them in same way you installed them, or delete `apps` folder and then install firmware, if you using extra pack builds (with `e` in version) all apps in _Extra will be updated automatically)** #### [🎲 Download latest extra apps pack](https://github.com/xMasterX/all-the-plugins/archive/refs/heads/main.zip) diff --git a/ReadMe.md b/ReadMe.md index dbe0e5bb6..ec188293d 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -10,7 +10,7 @@
-Our goal is to make all features possible on this device without any limitations! +Most stable custom firmware focused on new features and improvements of original firmware components, with almost no UI changes
@@ -103,7 +103,7 @@ Encoders made by @assasinfil & @xMasterX: ## Please support development of the project The majority of this project is developed and maintained by me, @xMasterX. -I'm unemployed because of the war, and the only income I receive is from your donations. +I'm unemployed, and the only income I receive is from your donations. Our team is small and the guys are working on this project as much as they can solely based on the enthusiasm they have for this project and the community. - @assasinfil - SubGHz - @Svaarich - UI design and animations diff --git a/applications/debug/accessor/accessor_app.cpp b/applications/debug/accessor/accessor_app.cpp index 337437d0e..2e40b3c35 100644 --- a/applications/debug/accessor/accessor_app.cpp +++ b/applications/debug/accessor/accessor_app.cpp @@ -34,7 +34,7 @@ void AccessorApp::run(void) { AccessorApp::AccessorApp() : text_store{0} { notification = static_cast(furi_record_open(RECORD_NOTIFICATION)); - onewire_host = onewire_host_alloc(&ibutton_gpio); + onewire_host = onewire_host_alloc(&gpio_ibutton); furi_hal_power_enable_otg(); } diff --git a/applications/debug/uart_echo/application.fam b/applications/debug/uart_echo/application.fam index 4ad14e6c3..fce9ac809 100644 --- a/applications/debug/uart_echo/application.fam +++ b/applications/debug/uart_echo/application.fam @@ -1,12 +1,12 @@ App( appid="UART_Echo", name="UART Echo", - apptype=FlipperAppType.EXTERNAL, + apptype=FlipperAppType.DEBUG, entry_point="uart_echo_app", cdefines=["APP_UART_ECHO"], requires=["gui"], stack_size=2 * 1024, order=70, fap_icon="uart_10px.png", - fap_category="GPIO", + fap_category="Debug", ) diff --git a/applications/examples/example_thermo/README.md b/applications/examples/example_thermo/README.md index fa00264dc..08240a1f8 100644 --- a/applications/examples/example_thermo/README.md +++ b/applications/examples/example_thermo/README.md @@ -33,10 +33,10 @@ It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it - gpio_ext_pa4 - gpio_ext_pa6 - gpio_ext_pa7 - - ibutton_gpio + - gpio_ibutton */ -#define THERMO_GPIO_PIN (ibutton_gpio) +#define THERMO_GPIO_PIN (gpio_ibutton) ``` Do not forget about the external pull-up resistor as these pins do not have one built-in. diff --git a/applications/examples/example_thermo/example_thermo.c b/applications/examples/example_thermo/example_thermo.c index 4241cb59d..5cb8863a4 100644 --- a/applications/examples/example_thermo/example_thermo.c +++ b/applications/examples/example_thermo/example_thermo.c @@ -43,10 +43,10 @@ - gpio_ext_pa4 - gpio_ext_pa6 - gpio_ext_pa7 - - ibutton_gpio + - gpio_ibutton */ -#define THERMO_GPIO_PIN (ibutton_gpio) +#define THERMO_GPIO_PIN (gpio_ibutton) /* Flags which the reader thread responds to */ typedef enum { diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c index 76e0a80b0..283c17bfd 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.c @@ -152,6 +152,12 @@ bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { } } } + + if(instance->spi) { + avr_isp_spi_sw_free(instance->spi); + instance->spi = NULL; + } + return false; } diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index f586e1645..209551a47 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -198,9 +198,10 @@ bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance) { } avr_isp_end_pmode(instance->avr_isp); - furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4); - } while(0); + + furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4); + if(instance->callback) { if(instance->chip_arr_ind > avr_isp_chip_arr_size) { instance->callback(instance->context, "No detect", instance->chip_detect, 0); diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c index b457e4c27..0f46872dd 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -196,7 +196,7 @@ static void avr_isp_prog_set_cfg(AvrIspProg* instance) { instance->cfg->lockbytes = instance->buff[6]; instance->cfg->fusebytes = instance->buff[7]; instance->cfg->flashpoll = instance->buff[8]; - // ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as “flashpoll” + // ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as �flashpoll� instance->cfg->eeprompoll = instance->buff[10] << 8 | instance->buff[11]; instance->cfg->pagesize = instance->buff[12] << 8 | instance->buff[13]; instance->cfg->eepromsize = instance->buff[14] << 8 | instance->buff[15]; @@ -317,6 +317,12 @@ static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { } } } + + if(instance->spi) { + avr_isp_spi_sw_free(instance->spi); + instance->spi = NULL; + } + return false; } diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c index f60850c84..c6d9d54c8 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c @@ -18,7 +18,6 @@ struct AvrIspSpiSw { AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed) { AvrIspSpiSw* instance = malloc(sizeof(AvrIspSpiSw)); instance->speed_wait_time = speed; - instance->miso = AVR_ISP_SPI_SW_MISO; instance->mosi = AVR_ISP_SPI_SW_MOSI; instance->sck = AVR_ISP_SPI_SW_SCK; @@ -40,7 +39,6 @@ void avr_isp_spi_sw_free(AvrIspSpiSw* instance) { furi_hal_gpio_init(instance->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(instance->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(instance->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - free(instance); } diff --git a/applications/external/gps_nmea_uart/gps.c b/applications/external/gps_nmea_uart/gps.c index 0f4a7a1d5..a0c6ead03 100644 --- a/applications/external/gps_nmea_uart/gps.c +++ b/applications/external/gps_nmea_uart/gps.c @@ -139,20 +139,14 @@ int32_t gps_app(void* p) { switch(event.input.key) { case InputKeyUp: gps_uart_deinit_thread(gps_uart); - switch(gps_uart->baudrate) { - case GPS_BAUDRATE_9k: - gps_uart->baudrate = GPS_BAUDRATE_57k; - break; - case GPS_BAUDRATE_57k: - gps_uart->baudrate = GPS_BAUDRATE_115k; - break; - case GPS_BAUDRATE_115k: - gps_uart->baudrate = GPS_BAUDRATE_9k; - break; - - default: - break; + const int baudrate_length = + sizeof(gps_baudrates) / sizeof(gps_baudrates[0]); + current_gps_baudrate++; + if(current_gps_baudrate >= baudrate_length) { + current_gps_baudrate = 0; } + gps_uart->baudrate = gps_baudrates[current_gps_baudrate]; + gps_uart_init_thread(gps_uart); gps_uart->changing_baudrate = true; view_port_update(view_port); diff --git a/applications/external/gps_nmea_uart/gps_uart.c b/applications/external/gps_nmea_uart/gps_uart.c index 39538b74b..4e66aa284 100644 --- a/applications/external/gps_nmea_uart/gps_uart.c +++ b/applications/external/gps_nmea_uart/gps_uart.c @@ -169,7 +169,7 @@ GpsUart* gps_uart_enable() { gps_uart->notifications = furi_record_open(RECORD_NOTIFICATION); - gps_uart->baudrate = GPS_BAUDRATE_57k; + gps_uart->baudrate = gps_baudrates[current_gps_baudrate]; gps_uart_init_thread(gps_uart); diff --git a/applications/external/gps_nmea_uart/gps_uart.h b/applications/external/gps_nmea_uart/gps_uart.h index 5a42b9c58..152f4cd7f 100644 --- a/applications/external/gps_nmea_uart/gps_uart.h +++ b/applications/external/gps_nmea_uart/gps_uart.h @@ -3,11 +3,11 @@ #include #include -#define GPS_BAUDRATE_9k 9600 -#define GPS_BAUDRATE_57k 57600 -#define GPS_BAUDRATE_115k 115200 #define RX_BUF_SIZE 1024 +static const int gps_baudrates[5] = {9600, 19200, 38400, 57600, 115200}; +static int current_gps_baudrate = 3; + typedef struct { bool valid; float latitude; diff --git a/applications/external/hid_app/assets/Pause_icon_9x9.png b/applications/external/hid_app/assets/Pause_icon_9x9.png new file mode 100644 index 000000000..d72d712bb Binary files /dev/null and b/applications/external/hid_app/assets/Pause_icon_9x9.png differ diff --git a/applications/external/hid_app/hid.c b/applications/external/hid_app/hid.c index 949ff63b3..b679c395c 100644 --- a/applications/external/hid_app/hid.c +++ b/applications/external/hid_app/hid.c @@ -10,6 +10,7 @@ enum HidDebugSubmenuIndex { HidSubmenuIndexKeyboard, HidSubmenuIndexMedia, HidSubmenuIndexTikTok, + HidSubmenuIndexYTShorts, HidSubmenuIndexMouse, HidSubmenuIndexMouseJiggler, }; @@ -32,6 +33,9 @@ static void hid_submenu_callback(void* context, uint32_t index) { } else if(index == HidSubmenuIndexTikTok) { app->view_id = BtHidViewTikTok; view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok); + } else if(index == HidSubmenuIndexYTShorts) { + app->view_id = BtHidViewYTShorts; + view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewYTShorts); } else if(index == HidSubmenuIndexMouseJiggler) { app->view_id = HidViewMouseJiggler; view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseJiggler); @@ -55,6 +59,7 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con hid_mouse_set_connected_status(hid->hid_mouse, connected); hid_mouse_jiggler_set_connected_status(hid->hid_mouse_jiggler, connected); hid_tiktok_set_connected_status(hid->hid_tiktok, connected); + hid_ytshorts_set_connected_status(hid->hid_ytshorts, connected); } static void hid_dialog_callback(DialogExResult result, void* context) { @@ -113,6 +118,12 @@ Hid* hid_alloc(HidTransport transport) { HidSubmenuIndexTikTok, hid_submenu_callback, app); + submenu_add_item( + app->device_type_submenu, + "YT Shorts Controller", + HidSubmenuIndexYTShorts, + hid_submenu_callback, + app); } submenu_add_item( app->device_type_submenu, @@ -166,6 +177,12 @@ Hid* hid_app_alloc_view(void* context) { view_dispatcher_add_view( app->view_dispatcher, BtHidViewTikTok, hid_tiktok_get_view(app->hid_tiktok)); + // YTShorts view + app->hid_ytshorts = hid_ytshorts_alloc(app); + view_set_previous_callback(hid_ytshorts_get_view(app->hid_ytshorts), hid_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, BtHidViewYTShorts, hid_ytshorts_get_view(app->hid_ytshorts)); + // Mouse view app->hid_mouse = hid_mouse_alloc(app); view_set_previous_callback(hid_mouse_get_view(app->hid_mouse), hid_exit_confirm_view); @@ -209,6 +226,8 @@ void hid_free(Hid* app) { hid_mouse_jiggler_free(app->hid_mouse_jiggler); view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok); hid_tiktok_free(app->hid_tiktok); + view_dispatcher_remove_view(app->view_dispatcher, BtHidViewYTShorts); + hid_ytshorts_free(app->hid_ytshorts); view_dispatcher_free(app->view_dispatcher); // Close records diff --git a/applications/external/hid_app/hid.h b/applications/external/hid_app/hid.h index 8ed1664a3..1ff42c940 100644 --- a/applications/external/hid_app/hid.h +++ b/applications/external/hid_app/hid.h @@ -22,6 +22,7 @@ #include "views/hid_mouse.h" #include "views/hid_mouse_jiggler.h" #include "views/hid_tiktok.h" +#include "views/hid_ytshorts.h" #define HID_BT_KEYS_STORAGE_NAME ".bt_hid.keys" @@ -45,6 +46,7 @@ struct Hid { HidMouse* hid_mouse; HidMouseJiggler* hid_mouse_jiggler; HidTikTok* hid_tiktok; + HidYTShorts* hid_ytshorts; HidTransport transport; uint32_t view_id; diff --git a/applications/external/hid_app/views.h b/applications/external/hid_app/views.h index 2a44832e1..14cfa126f 100644 --- a/applications/external/hid_app/views.h +++ b/applications/external/hid_app/views.h @@ -6,5 +6,6 @@ typedef enum { HidViewMouse, HidViewMouseJiggler, BtHidViewTikTok, + BtHidViewYTShorts, HidViewExitConfirm, } HidView; \ No newline at end of file diff --git a/applications/external/hid_app/views/hid_mouse.c b/applications/external/hid_app/views/hid_mouse.c index 30a9d9d06..ca299c463 100644 --- a/applications/external/hid_app/views/hid_mouse.c +++ b/applications/external/hid_app/views/hid_mouse.c @@ -93,17 +93,23 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) { // Ok if(model->left_mouse_pressed) { - canvas_draw_icon(canvas, 81, 25, &I_Ok_btn_pressed_13x13); - } else { - canvas_draw_icon(canvas, 83, 27, &I_Left_mouse_icon_9x9); + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 81, 25, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); } + canvas_draw_icon(canvas, 83, 27, &I_Left_mouse_icon_9x9); + canvas_set_color(canvas, ColorBlack); // Back if(model->right_mouse_pressed) { - canvas_draw_icon(canvas, 108, 48, &I_Ok_btn_pressed_13x13); - } else { - canvas_draw_icon(canvas, 110, 50, &I_Right_mouse_icon_9x9); + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 108, 48, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); } + canvas_draw_icon(canvas, 110, 50, &I_Right_mouse_icon_9x9); + canvas_set_color(canvas, ColorBlack); } static void hid_mouse_process(HidMouse* hid_mouse, InputEvent* event) { diff --git a/applications/external/hid_app/views/hid_tiktok.c b/applications/external/hid_app/views/hid_tiktok.c index e1f9f4bed..3b48d32cb 100644 --- a/applications/external/hid_app/views/hid_tiktok.c +++ b/applications/external/hid_app/views/hid_tiktok.c @@ -19,6 +19,7 @@ typedef struct { bool ok_pressed; bool connected; bool is_cursor_set; + bool back_mouse_pressed; HidTransport transport; } HidTikTokModel; @@ -40,53 +41,63 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) { canvas_set_font(canvas, FontSecondary); // Keypad circles - canvas_draw_icon(canvas, 76, 8, &I_Circles_47x47); + canvas_draw_icon(canvas, 66, 8, &I_Circles_47x47); + + // Pause + if(model->back_mouse_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 106, 46, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 108, 48, &I_Pause_icon_9x9); + canvas_set_color(canvas, ColorBlack); // Up if(model->up_pressed) { canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 93, 9, &I_Pressed_Button_13x13); + canvas_draw_icon(canvas, 83, 9, &I_Pressed_Button_13x13); canvas_set_bitmap_mode(canvas, 0); canvas_set_color(canvas, ColorWhite); } - canvas_draw_icon(canvas, 96, 11, &I_Arr_up_7x9); + canvas_draw_icon(canvas, 86, 11, &I_Arr_up_7x9); canvas_set_color(canvas, ColorBlack); // Down if(model->down_pressed) { canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 93, 41, &I_Pressed_Button_13x13); + canvas_draw_icon(canvas, 83, 41, &I_Pressed_Button_13x13); canvas_set_bitmap_mode(canvas, 0); canvas_set_color(canvas, ColorWhite); } - canvas_draw_icon(canvas, 96, 44, &I_Arr_dwn_7x9); + canvas_draw_icon(canvas, 86, 44, &I_Arr_dwn_7x9); canvas_set_color(canvas, ColorBlack); // Left if(model->left_pressed) { canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 77, 25, &I_Pressed_Button_13x13); + canvas_draw_icon(canvas, 67, 25, &I_Pressed_Button_13x13); canvas_set_bitmap_mode(canvas, 0); canvas_set_color(canvas, ColorWhite); } - canvas_draw_icon(canvas, 81, 29, &I_Voldwn_6x6); + canvas_draw_icon(canvas, 71, 29, &I_Voldwn_6x6); canvas_set_color(canvas, ColorBlack); // Right if(model->right_pressed) { canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 109, 25, &I_Pressed_Button_13x13); + canvas_draw_icon(canvas, 99, 25, &I_Pressed_Button_13x13); canvas_set_bitmap_mode(canvas, 0); canvas_set_color(canvas, ColorWhite); } - canvas_draw_icon(canvas, 111, 29, &I_Volup_8x6); + canvas_draw_icon(canvas, 101, 29, &I_Volup_8x6); canvas_set_color(canvas, ColorBlack); // Ok if(model->ok_pressed) { - canvas_draw_icon(canvas, 91, 23, &I_Like_pressed_17x17); + canvas_draw_icon(canvas, 81, 23, &I_Like_pressed_17x17); } else { - canvas_draw_icon(canvas, 94, 27, &I_Like_def_11x9); + canvas_draw_icon(canvas, 84, 27, &I_Like_def_11x9); } // Exit canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8); @@ -102,7 +113,8 @@ static void hid_tiktok_reset_cursor(HidTikTok* hid_tiktok) { furi_delay_ms(50); } // Move cursor from the corner - hid_hal_mouse_move(hid_tiktok->hid, 20, 120); + hid_hal_mouse_move(hid_tiktok->hid, 40, 120); + hid_hal_mouse_move(hid_tiktok->hid, 0, 120); furi_delay_ms(50); } @@ -120,6 +132,8 @@ static void hid_hal_consumer_key_press(hid_tiktok->hid, HID_CONSUMER_VOLUME_INCREMENT); } else if(event->key == InputKeyOk) { model->ok_pressed = true; + } else if(event->key == InputKeyBack) { + model->back_mouse_pressed = true; } } @@ -137,6 +151,8 @@ static void hid_hal_consumer_key_release(hid_tiktok->hid, HID_CONSUMER_VOLUME_INCREMENT); } else if(event->key == InputKeyOk) { model->ok_pressed = false; + } else if(event->key == InputKeyBack) { + model->back_mouse_pressed = false; } } @@ -169,24 +185,26 @@ static bool hid_tiktok_input_callback(InputEvent* event, void* context) { furi_delay_ms(50); hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_LEFT); consumed = true; - } else if(event->key == InputKeyUp) { - // Emulate up swipe - hid_hal_mouse_scroll(hid_tiktok->hid, -6); - hid_hal_mouse_scroll(hid_tiktok->hid, -12); - hid_hal_mouse_scroll(hid_tiktok->hid, -19); - hid_hal_mouse_scroll(hid_tiktok->hid, -12); - hid_hal_mouse_scroll(hid_tiktok->hid, -6); - consumed = true; } else if(event->key == InputKeyDown) { - // Emulate down swipe + // Swipe to new video hid_hal_mouse_scroll(hid_tiktok->hid, 6); hid_hal_mouse_scroll(hid_tiktok->hid, 12); hid_hal_mouse_scroll(hid_tiktok->hid, 19); hid_hal_mouse_scroll(hid_tiktok->hid, 12); hid_hal_mouse_scroll(hid_tiktok->hid, 6); consumed = true; + } else if(event->key == InputKeyUp) { + // Swipe to previous video + hid_hal_mouse_scroll(hid_tiktok->hid, -6); + hid_hal_mouse_scroll(hid_tiktok->hid, -12); + hid_hal_mouse_scroll(hid_tiktok->hid, -19); + hid_hal_mouse_scroll(hid_tiktok->hid, -12); + hid_hal_mouse_scroll(hid_tiktok->hid, -6); + consumed = true; } else if(event->key == InputKeyBack) { - hid_hal_consumer_key_release_all(hid_tiktok->hid); + // Pause + hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_RIGHT); + hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_RIGHT); consumed = true; } } else if(event->type == InputTypeLong) { diff --git a/applications/external/hid_app/views/hid_ytshorts.c b/applications/external/hid_app/views/hid_ytshorts.c new file mode 100644 index 000000000..44ad02ff0 --- /dev/null +++ b/applications/external/hid_app/views/hid_ytshorts.c @@ -0,0 +1,268 @@ +#include "hid_ytshorts.h" +#include "../hid.h" +#include + +#include "hid_icons.h" + +#define TAG "HidYTShorts" + +struct HidYTShorts { + View* view; + Hid* hid; +}; + +typedef struct { + bool left_pressed; + bool up_pressed; + bool right_pressed; + bool down_pressed; + bool ok_pressed; + bool connected; + bool is_cursor_set; + bool back_mouse_pressed; + HidTransport transport; +} HidYTShortsModel; + +static void hid_ytshorts_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + HidYTShortsModel* model = context; + + // Header + if(model->transport == HidTransportBle) { + if(model->connected) { + canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); + } else { + canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + } + } + + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Shorts"); + canvas_set_font(canvas, FontSecondary); + + // Keypad circles + canvas_draw_icon(canvas, 66, 8, &I_Circles_47x47); + + // Pause + if(model->back_mouse_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 106, 46, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 108, 48, &I_Pause_icon_9x9); + canvas_set_color(canvas, ColorBlack); + + // Up + if(model->up_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 83, 9, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 86, 11, &I_Arr_up_7x9); + canvas_set_color(canvas, ColorBlack); + + // Down + if(model->down_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 83, 41, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 86, 44, &I_Arr_dwn_7x9); + canvas_set_color(canvas, ColorBlack); + + // Left + if(model->left_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 67, 25, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 71, 29, &I_Voldwn_6x6); + canvas_set_color(canvas, ColorBlack); + + // Right + if(model->right_pressed) { + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 99, 25, &I_Pressed_Button_13x13); + canvas_set_bitmap_mode(canvas, 0); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_icon(canvas, 101, 29, &I_Volup_8x6); + canvas_set_color(canvas, ColorBlack); + + // Ok + if(model->ok_pressed) { + canvas_draw_icon(canvas, 81, 23, &I_Like_pressed_17x17); + } else { + canvas_draw_icon(canvas, 84, 27, &I_Like_def_11x9); + } + // Exit + canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8); + canvas_set_font(canvas, FontSecondary); + elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit"); +} + +static void hid_ytshorts_reset_cursor(HidYTShorts* hid_ytshorts) { + // Set cursor to the phone's left up corner + // Delays to guarantee one packet per connection interval + for(size_t i = 0; i < 8; i++) { + hid_hal_mouse_move(hid_ytshorts->hid, -127, -127); + furi_delay_ms(50); + } + // Move cursor from the corner + hid_hal_mouse_move(hid_ytshorts->hid, 40, 120); + hid_hal_mouse_move(hid_ytshorts->hid, 0, 120); + furi_delay_ms(50); +} + +static void hid_ytshorts_process_press( + HidYTShorts* hid_ytshorts, + HidYTShortsModel* model, + InputEvent* event) { + if(event->key == InputKeyUp) { + model->up_pressed = true; + } else if(event->key == InputKeyDown) { + model->down_pressed = true; + } else if(event->key == InputKeyLeft) { + model->left_pressed = true; + hid_hal_consumer_key_press(hid_ytshorts->hid, HID_CONSUMER_VOLUME_DECREMENT); + } else if(event->key == InputKeyRight) { + model->right_pressed = true; + hid_hal_consumer_key_press(hid_ytshorts->hid, HID_CONSUMER_VOLUME_INCREMENT); + } else if(event->key == InputKeyOk) { + model->ok_pressed = true; + } else if(event->key == InputKeyBack) { + model->back_mouse_pressed = true; + } +} + +static void hid_ytshorts_process_release( + HidYTShorts* hid_ytshorts, + HidYTShortsModel* model, + InputEvent* event) { + if(event->key == InputKeyUp) { + model->up_pressed = false; + } else if(event->key == InputKeyDown) { + model->down_pressed = false; + } else if(event->key == InputKeyLeft) { + model->left_pressed = false; + hid_hal_consumer_key_release(hid_ytshorts->hid, HID_CONSUMER_VOLUME_DECREMENT); + } else if(event->key == InputKeyRight) { + model->right_pressed = false; + hid_hal_consumer_key_release(hid_ytshorts->hid, HID_CONSUMER_VOLUME_INCREMENT); + } else if(event->key == InputKeyOk) { + model->ok_pressed = false; + } else if(event->key == InputKeyBack) { + model->back_mouse_pressed = false; + } +} + +static bool hid_ytshorts_input_callback(InputEvent* event, void* context) { + furi_assert(context); + HidYTShorts* hid_ytshorts = context; + bool consumed = false; + + with_view_model( + hid_ytshorts->view, + HidYTShortsModel * model, + { + if(event->type == InputTypePress) { + hid_ytshorts_process_press(hid_ytshorts, model, event); + if(model->connected && !model->is_cursor_set) { + hid_ytshorts_reset_cursor(hid_ytshorts); + model->is_cursor_set = true; + } + consumed = true; + } else if(event->type == InputTypeRelease) { + hid_ytshorts_process_release(hid_ytshorts, model, event); + consumed = true; + } else if(event->type == InputTypeShort) { + if(event->key == InputKeyOk) { + hid_hal_mouse_press(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT); + furi_delay_ms(50); + hid_hal_mouse_release(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT); + furi_delay_ms(50); + hid_hal_mouse_press(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT); + furi_delay_ms(50); + hid_hal_mouse_release(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT); + consumed = true; + } else if(event->key == InputKeyDown) { + // Swipe to new video + hid_hal_mouse_scroll(hid_ytshorts->hid, 6); + hid_hal_mouse_scroll(hid_ytshorts->hid, 8); + hid_hal_mouse_scroll(hid_ytshorts->hid, 10); + hid_hal_mouse_scroll(hid_ytshorts->hid, 8); + hid_hal_mouse_scroll(hid_ytshorts->hid, 6); + consumed = true; + } else if(event->key == InputKeyUp) { + // Swipe to previous video + hid_hal_mouse_scroll(hid_ytshorts->hid, -6); + hid_hal_mouse_scroll(hid_ytshorts->hid, -8); + hid_hal_mouse_scroll(hid_ytshorts->hid, -10); + hid_hal_mouse_scroll(hid_ytshorts->hid, -8); + hid_hal_mouse_scroll(hid_ytshorts->hid, -6); + consumed = true; + } else if(event->key == InputKeyBack) { + // Pause + hid_hal_mouse_press(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT); + furi_delay_ms(50); + hid_hal_mouse_release(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT); + furi_delay_ms(50); + consumed = true; + } + } else if(event->type == InputTypeLong) { + if(event->key == InputKeyBack) { + hid_hal_consumer_key_release_all(hid_ytshorts->hid); + model->is_cursor_set = false; + consumed = false; + } + } + }, + true); + + return consumed; +} + +HidYTShorts* hid_ytshorts_alloc(Hid* bt_hid) { + HidYTShorts* hid_ytshorts = malloc(sizeof(HidYTShorts)); + hid_ytshorts->hid = bt_hid; + hid_ytshorts->view = view_alloc(); + view_set_context(hid_ytshorts->view, hid_ytshorts); + view_allocate_model(hid_ytshorts->view, ViewModelTypeLocking, sizeof(HidYTShortsModel)); + view_set_draw_callback(hid_ytshorts->view, hid_ytshorts_draw_callback); + view_set_input_callback(hid_ytshorts->view, hid_ytshorts_input_callback); + + with_view_model( + hid_ytshorts->view, + HidYTShortsModel * model, + { model->transport = bt_hid->transport; }, + true); + + return hid_ytshorts; +} + +void hid_ytshorts_free(HidYTShorts* hid_ytshorts) { + furi_assert(hid_ytshorts); + view_free(hid_ytshorts->view); + free(hid_ytshorts); +} + +View* hid_ytshorts_get_view(HidYTShorts* hid_ytshorts) { + furi_assert(hid_ytshorts); + return hid_ytshorts->view; +} + +void hid_ytshorts_set_connected_status(HidYTShorts* hid_ytshorts, bool connected) { + furi_assert(hid_ytshorts); + with_view_model( + hid_ytshorts->view, + HidYTShortsModel * model, + { + model->connected = connected; + model->is_cursor_set = false; + }, + true); +} diff --git a/applications/external/hid_app/views/hid_ytshorts.h b/applications/external/hid_app/views/hid_ytshorts.h new file mode 100644 index 000000000..03264dd36 --- /dev/null +++ b/applications/external/hid_app/views/hid_ytshorts.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +typedef struct Hid Hid; +typedef struct HidYTShorts HidYTShorts; + +HidYTShorts* hid_ytshorts_alloc(Hid* bt_hid); + +void hid_ytshorts_free(HidYTShorts* hid_ytshorts); + +View* hid_ytshorts_get_view(HidYTShorts* hid_ytshorts); + +void hid_ytshorts_set_connected_status(HidYTShorts* hid_ytshorts, bool connected); diff --git a/applications/external/totp/cli/commands/pin/pin.c b/applications/external/totp/cli/commands/pin/pin.c index 92c9c59c4..9b9038ae7 100644 --- a/applications/external/totp/cli/commands/pin/pin.c +++ b/applications/external/totp/cli/commands/pin/pin.c @@ -121,6 +121,19 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl memset(&new_pin[0], 0, TOTP_IV_SIZE); } + char* backup_path = totp_config_file_backup(); + if(backup_path != NULL) { + TOTP_CLI_PRINTF_WARNING("Backup conf file %s has been created\r\n", backup_path); + TOTP_CLI_PRINTF_WARNING( + "Once you make sure everything is fine and works as expected, please delete this backup file\r\n"); + free(backup_path); + } else { + memset_s(&new_pin[0], TOTP_IV_SIZE, 0, TOTP_IV_SIZE); + TOTP_CLI_PRINTF_ERROR( + "An error has occurred during taking backup of config file\r\n"); + break; + } + if(plugin_state->current_scene == TotpSceneGenerateToken) { totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL); load_generate_token_scene = true; diff --git a/applications/external/totp/cli/commands/reset/reset.c b/applications/external/totp/cli/commands/reset/reset.c index c7928db31..cd2d1bf46 100644 --- a/applications/external/totp/cli/commands/reset/reset.c +++ b/applications/external/totp/cli/commands/reset/reset.c @@ -1,7 +1,7 @@ #include "reset.h" #include -#include +#include #include "../../cli_helpers.h" #include "../../../services/config/config.h" diff --git a/applications/external/totp/lib/base32/base32.h b/applications/external/totp/lib/base32/base32.h index 8cb9bddcb..a0ec86e82 100644 --- a/applications/external/totp/lib/base32/base32.h +++ b/applications/external/totp/lib/base32/base32.h @@ -27,7 +27,7 @@ #pragma once -#include +#include #include /** diff --git a/applications/external/totp/lib/base64/base64.c b/applications/external/totp/lib/base64/base64.c index 1dfcf8814..dd0a12b5e 100644 --- a/applications/external/totp/lib/base64/base64.c +++ b/applications/external/totp/lib/base64/base64.c @@ -22,14 +22,14 @@ static const uint8_t dtable[] = {0x3e, 0x80, 0x80, 0x80, 0x3f, 0x34, 0x35, 0x36, 0x80, 0x80, 0x80, 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33}; -// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + static uint8_t get_dtable_value(uint8_t index) { return (index < 43 || index > 122) ? 0x80 : dtable[index - 43]; } uint8_t* base64_decode(const uint8_t* src, size_t len, size_t* out_len, size_t* out_size) { - uint8_t *out; - uint8_t *pos; + uint8_t* out; + uint8_t* pos; uint8_t in[4]; uint8_t block[4]; uint8_t tmp; diff --git a/applications/external/totp/lib/polyfills/strnlen.h b/applications/external/totp/lib/polyfills/strnlen.h index 7dcef3a18..4fe0d540c 100644 --- a/applications/external/totp/lib/polyfills/strnlen.h +++ b/applications/external/totp/lib/polyfills/strnlen.h @@ -1,3 +1,6 @@ +#pragma once +#pragma weak strnlen + #include size_t strnlen(const char* s, size_t maxlen); \ No newline at end of file diff --git a/applications/external/totp/services/config/config.c b/applications/external/totp/services/config/config.c index adc85cbe5..0453338d3 100644 --- a/applications/external/totp/services/config/config.c +++ b/applications/external/totp/services/config/config.c @@ -9,7 +9,7 @@ #define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("authenticator") #define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf" -#define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup" +#define CONFIG_FILE_BACKUP_BASE_PATH CONFIG_FILE_PATH ".backup" #define CONFIG_FILE_TEMP_PATH CONFIG_FILE_PATH ".tmp" #define CONFIG_FILE_ORIG_PATH CONFIG_FILE_PATH ".orig" #define CONFIG_FILE_PATH_PREVIOUS EXT_PATH("apps/Misc") "/totp.conf" @@ -39,6 +39,34 @@ static void totp_close_config_file(FlipperFormat* file) { flipper_format_free(file); } +/** + * @brief Tries to take a config file backup + * @param storage storage record + * @return backup path if backup successfully taken; \c NULL otherwise + */ +static char* totp_config_file_backup_i(Storage* storage) { + uint8_t backup_path_size = sizeof(CONFIG_FILE_BACKUP_BASE_PATH) + 5; + char* backup_path = malloc(backup_path_size); + furi_check(backup_path != NULL); + memcpy(backup_path, CONFIG_FILE_BACKUP_BASE_PATH, sizeof(CONFIG_FILE_BACKUP_BASE_PATH)); + uint16_t i = 1; + bool backup_file_exists; + while((backup_file_exists = storage_common_exists(storage, backup_path)) && i <= 9999) { + snprintf(backup_path, backup_path_size, CONFIG_FILE_BACKUP_BASE_PATH ".%" PRIu16, i); + i++; + } + + if(backup_file_exists || + storage_common_copy(storage, CONFIG_FILE_PATH, backup_path) != FSE_OK) { + FURI_LOG_E(LOGGING_TAG, "Unable to take a backup"); + free(backup_path); + return NULL; + } + + FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", backup_path); + return backup_path; +} + /** * @brief Opens or creates TOTP application standard config file * @param storage storage record to use @@ -250,6 +278,13 @@ static TotpConfigFileUpdateResult return update_result; } +char* totp_config_file_backup() { + Storage* storage = totp_open_storage(); + char* result = totp_config_file_backup_i(storage); + totp_close_storage(); + return result; +} + TotpConfigFileUpdateResult totp_config_file_save_new_token(const TokenInfo* token_info) { Storage* cfg_storage = totp_open_storage(); FlipperFormat* file; @@ -513,20 +548,16 @@ TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_st CONFIG_FILE_ACTUAL_VERSION); totp_close_config_file(fff_data_file); - if(storage_common_stat(storage, CONFIG_FILE_BACKUP_PATH, NULL) == FSE_OK) { - storage_simply_remove(storage, CONFIG_FILE_BACKUP_PATH); - } + char* backup_path = totp_config_file_backup_i(storage); - if(storage_common_copy(storage, CONFIG_FILE_PATH, CONFIG_FILE_BACKUP_PATH) == FSE_OK) { - FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", CONFIG_FILE_BACKUP_PATH); + if(backup_path != NULL) { if(totp_open_config_file(storage, &fff_data_file) != TotpConfigFileOpenSuccess) { result = TotpConfigFileOpenError; break; } FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage); - if(!flipper_format_file_open_existing( - fff_backup_data_file, CONFIG_FILE_BACKUP_PATH)) { + if(!flipper_format_file_open_existing(fff_backup_data_file, backup_path)) { flipper_format_file_close(fff_backup_data_file); flipper_format_free(fff_backup_data_file); result = TotpConfigFileOpenError; @@ -551,12 +582,12 @@ TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_st flipper_format_file_close(fff_backup_data_file); flipper_format_free(fff_backup_data_file); flipper_format_rewind(fff_data_file); + free(backup_path); } else { FURI_LOG_E( LOGGING_TAG, - "An error occurred during taking backup of %s into %s before migration", - CONFIG_FILE_PATH, - CONFIG_FILE_BACKUP_PATH); + "An error occurred during taking backup of %s before migration", + CONFIG_FILE_PATH); result = TotpConfigFileOpenError; break; } diff --git a/applications/external/totp/services/config/config.h b/applications/external/totp/services/config/config.h index 3d325368d..5bd169525 100644 --- a/applications/external/totp/services/config/config.h +++ b/applications/external/totp/services/config/config.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include "../../types/plugin_state.h" #include "../../types/token_info.h" #include "constants.h" @@ -60,6 +59,12 @@ enum TotpConfigFileUpdateResults { TotpConfigFileUpdateError }; +/** + * @brief Tries to take a config file backup + * @return backup path if backup successfully taken; \c NULL otherwise + */ +char* totp_config_file_backup(); + /** * @brief Saves all the settings and tokens to an application config file * @param plugin_state application state diff --git a/applications/external/totp/services/config/constants.h b/applications/external/totp/services/config/constants.h index 9924aefe2..7137e2374 100644 --- a/applications/external/totp/services/config/constants.h +++ b/applications/external/totp/services/config/constants.h @@ -1,7 +1,7 @@ #pragma once #define CONFIG_FILE_HEADER "Flipper TOTP plugin config file" -#define CONFIG_FILE_ACTUAL_VERSION 4 +#define CONFIG_FILE_ACTUAL_VERSION (4) #define TOTP_CONFIG_KEY_TIMEZONE "Timezone" #define TOTP_CONFIG_KEY_TOKEN_NAME "TokenName" diff --git a/applications/external/totp/services/crypto/crypto.c b/applications/external/totp/services/crypto/crypto.c index ed4775dfb..00f5ab0a8 100644 --- a/applications/external/totp/services/crypto/crypto.c +++ b/applications/external/totp/services/crypto/crypto.c @@ -1,14 +1,15 @@ #include "crypto.h" -#include -#include +#include +#include +#include #include "../config/config.h" #include "../../types/common.h" #include "memset_s.h" -#define CRYPTO_KEY_SLOT 2 +#define CRYPTO_KEY_SLOT (2) #define CRYPTO_VERIFY_KEY "FFF_Crypto_pass" -#define CRYPTO_VERIFY_KEY_LENGTH 16 -#define CRYPTO_ALIGNMENT_FACTOR 16 +#define CRYPTO_VERIFY_KEY_LENGTH (16) +#define CRYPTO_ALIGNMENT_FACTOR (16) uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, diff --git a/applications/external/totp/services/hmac/hmac_common.h b/applications/external/totp/services/hmac/hmac_common.h index 9c5b5828f..0cd56ed99 100644 --- a/applications/external/totp/services/hmac/hmac_common.h +++ b/applications/external/totp/services/hmac/hmac_common.h @@ -9,11 +9,7 @@ #define _GLHMAC_CONCAT_(prefix, suffix) prefix##suffix #define _GLHMAC_CONCAT(prefix, suffix) _GLHMAC_CONCAT_(prefix, suffix) -#if GL_HMAC_NAME == 5 -#define HMAC_ALG md5 -#else #define HMAC_ALG _GLHMAC_CONCAT(sha, GL_HMAC_NAME) -#endif #define GL_HMAC_CTX _GLHMAC_CONCAT(HMAC_ALG, _ctx) #define GL_HMAC_FN _GLHMAC_CONCAT(hmac_, HMAC_ALG) diff --git a/applications/external/totp/services/totp/totp.c b/applications/external/totp/services/totp/totp.c index f6e0401e6..45a283b06 100644 --- a/applications/external/totp/services/totp/totp.c +++ b/applications/external/totp/services/totp/totp.c @@ -1,15 +1,13 @@ #include "totp.h" -#include #include #include -#include #include +#include #include "../hmac/hmac_sha1.h" #include "../hmac/hmac_sha256.h" #include "../hmac/hmac_sha512.h" #include "../hmac/byteswap.h" -#include "../../lib/timezone_utils/timezone_utils.h" #define HMAC_MAX_RESULT_SIZE HMAC_SHA512_RESULT_SIZE diff --git a/applications/external/totp/totp_app.c b/applications/external/totp/totp_app.c index 74ec52f2c..0b70167a2 100644 --- a/applications/external/totp/totp_app.c +++ b/applications/external/totp/totp_app.c @@ -1,10 +1,7 @@ -#include -#include #include #include #include #include -#include #include #include #include @@ -21,7 +18,7 @@ #include "services/crypto/crypto.h" #include "cli/cli.h" -#define IDLE_TIMEOUT 60000 +#define IDLE_TIMEOUT (60000) static void render_callback(Canvas* const canvas, void* ctx) { furi_assert(ctx); @@ -97,6 +94,7 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { plugin_state->gui = furi_record_open(RECORD_GUI); plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION); plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); + memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE); if(totp_config_file_load_base(plugin_state) != TotpConfigFileOpenSuccess) { totp_dialogs_config_loading_error(plugin_state); @@ -104,10 +102,6 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { } plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(plugin_state->mutex == NULL) { - FURI_LOG_E(LOGGING_TAG, "Cannot create mutex\r\n"); - return false; - } #ifdef TOTP_BADBT_TYPE_ENABLED if(plugin_state->automation_method & AutomationMethodBadBt) { @@ -162,7 +156,7 @@ int32_t totp_app() { } TotpCliContext* cli_context = totp_cli_register_command_handler(plugin_state, event_queue); - totp_scene_director_init_scenes(plugin_state); + if(!totp_activate_initial_scene(plugin_state)) { FURI_LOG_E(LOGGING_TAG, "An error ocurred during activating initial scene\r\n"); totp_plugin_state_free(plugin_state); @@ -210,7 +204,6 @@ int32_t totp_app() { totp_cli_unregister_command_handler(cli_context); totp_scene_director_deactivate_active_scene(plugin_state); - totp_scene_director_dispose(plugin_state); view_port_enabled_set(view_port, false); gui_remove_view_port(plugin_state->gui, view_port); diff --git a/applications/external/totp/types/plugin_state.h b/applications/external/totp/types/plugin_state.h index b1d34a662..cacf68426 100644 --- a/applications/external/totp/types/plugin_state.h +++ b/applications/external/totp/types/plugin_state.h @@ -12,7 +12,7 @@ #include "../workers/bt_type_code/bt_type_code.h" #endif -#define TOTP_IV_SIZE 16 +#define TOTP_IV_SIZE (16) /** * @brief Application state structure diff --git a/applications/external/totp/types/token_info.c b/applications/external/totp/types/token_info.c index b8196c56b..5b85de719 100644 --- a/applications/external/totp/types/token_info.c +++ b/applications/external/totp/types/token_info.c @@ -1,9 +1,7 @@ #include "token_info.h" -#include #include #include #include -#include #include "common.h" #include "../services/crypto/crypto.h" diff --git a/applications/external/totp/types/token_info.h b/applications/external/totp/types/token_info.h index 688e8028d..21968553f 100644 --- a/applications/external/totp/types/token_info.h +++ b/applications/external/totp/types/token_info.h @@ -2,15 +2,15 @@ #include #include -#include +#include -#define TOTP_TOKEN_DURATION_DEFAULT 30 +#define TOTP_TOKEN_DURATION_DEFAULT (30) #define TOTP_TOKEN_ALGO_SHA1_NAME "sha1" #define TOTP_TOKEN_ALGO_STEAM_NAME "steam" #define TOTP_TOKEN_ALGO_SHA256_NAME "sha256" #define TOTP_TOKEN_ALGO_SHA512_NAME "sha512" -#define TOTP_TOKEN_MAX_LENGTH 255 +#define TOTP_TOKEN_MAX_LENGTH (255) #define PLAIN_TOKEN_ENCODING_BASE32_NAME "base32" #define PLAIN_TOKEN_ENCODING_BASE64_NAME "base64" @@ -95,12 +95,23 @@ enum TokenAutomationFeatures { TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER = 0b100 }; +/** + * @brief Plain token secret encodings. + */ enum PlainTokenSecretEncodings { + + /** + * @brief Base32 encoding + */ PLAIN_TOKEN_ENCODING_BASE32 = 0, + + /** + * @brief Base64 encoding + */ PLAIN_TOKEN_ENCODING_BASE64 = 1 }; -#define TOTP_TOKEN_DIGITS_MAX_COUNT 8 +#define TOTP_TOKEN_DIGITS_MAX_COUNT (8) /** * @brief TOTP token information diff --git a/applications/external/totp/ui/constants.h b/applications/external/totp/ui/constants.h index 9caf90c4e..81c2edf92 100644 --- a/applications/external/totp/ui/constants.h +++ b/applications/external/totp/ui/constants.h @@ -1,6 +1,6 @@ #pragma once -#define SCREEN_WIDTH 128 -#define SCREEN_HEIGHT 64 +#define SCREEN_WIDTH (128) +#define SCREEN_HEIGHT (64) #define SCREEN_WIDTH_CENTER (SCREEN_WIDTH >> 1) #define SCREEN_HEIGHT_CENTER (SCREEN_HEIGHT >> 1) diff --git a/applications/external/totp/ui/fonts/mode-nine/mode_nine.c b/applications/external/totp/ui/fonts/mode-nine/mode_nine.c index add4f47ef..ca2191789 100644 --- a/applications/external/totp/ui/fonts/mode-nine/mode_nine.c +++ b/applications/external/totp/ui/fonts/mode-nine/mode_nine.c @@ -1,4 +1,5 @@ #include "mode_nine.h" +#include /* GENERATED BY https://github.com/pavius/the-dot-factory */ diff --git a/applications/external/totp/ui/fonts/mode-nine/mode_nine.h b/applications/external/totp/ui/fonts/mode-nine/mode_nine.h index 67fa33afe..516e261f8 100644 --- a/applications/external/totp/ui/fonts/mode-nine/mode_nine.h +++ b/applications/external/totp/ui/fonts/mode-nine/mode_nine.h @@ -3,7 +3,6 @@ /* GENERATED BY https://github.com/pavius/the-dot-factory */ #include "../font_info.h" -#include /* Font data for ModeNine 15pt */ extern const FONT_INFO modeNine_15ptFontInfo; diff --git a/applications/external/totp/ui/scene_director.c b/applications/external/totp/ui/scene_director.c index c77e88ab4..c6f709006 100644 --- a/applications/external/totp/ui/scene_director.c +++ b/applications/external/totp/ui/scene_director.c @@ -62,14 +62,6 @@ void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state } } -void totp_scene_director_init_scenes(PluginState* const plugin_state) { - totp_scene_authenticate_init(plugin_state); - totp_scene_generate_token_init(plugin_state); - totp_scene_add_new_token_init(plugin_state); - totp_scene_token_menu_init(plugin_state); - totp_scene_app_settings_init(plugin_state); -} - void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state) { switch(plugin_state->current_scene) { case TotpSceneGenerateToken: @@ -94,14 +86,6 @@ void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_ } } -void totp_scene_director_dispose(const PluginState* const plugin_state) { - totp_scene_generate_token_free(plugin_state); - totp_scene_authenticate_free(plugin_state); - totp_scene_add_new_token_free(plugin_state); - totp_scene_token_menu_free(plugin_state); - totp_scene_app_settings_free(plugin_state); -} - bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state) { bool processing = true; switch(plugin_state->current_scene) { diff --git a/applications/external/totp/ui/scene_director.h b/applications/external/totp/ui/scene_director.h index 541a63f1c..71709978f 100644 --- a/applications/external/totp/ui/scene_director.h +++ b/applications/external/totp/ui/scene_director.h @@ -22,12 +22,6 @@ void totp_scene_director_activate_scene( */ void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state); -/** - * @brief Initializes all the available scenes - * @param plugin_state application state - */ -void totp_scene_director_init_scenes(PluginState* const plugin_state); - /** * @brief Renders current scene * @param canvas canvas to render at @@ -35,12 +29,6 @@ void totp_scene_director_init_scenes(PluginState* const plugin_state); */ void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state); -/** - * @brief Disposes all the available scenes - * @param plugin_state application state - */ -void totp_scene_director_dispose(const PluginState* const plugin_state); - /** * @brief Handles application event for the current scene * @param event event to be handled diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c index 6956ec1ad..bbe0b7726 100644 --- a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c +++ b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c @@ -1,6 +1,5 @@ #include "totp_input_text.h" #include -#include "../../../lib/polyfills/strnlen.h" void view_draw(View* view, Canvas* canvas) { furi_assert(view); diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.h b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.h index 145e8904d..ffbfde692 100644 --- a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.h +++ b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.h @@ -6,6 +6,8 @@ #include "../../../types/plugin_state.h" #include "../../../types/plugin_event.h" +#define INPUT_BUFFER_SIZE (255) + typedef struct { char* user_input; size_t user_input_length; @@ -20,8 +22,6 @@ typedef struct { void* callback_data; } InputTextSceneContext; -#define INPUT_BUFFER_SIZE 255 - typedef struct { TextInput* text_input; View* text_input_view; diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c index 800d7e672..3f8e4fd93 100644 --- a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c +++ b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c @@ -44,10 +44,6 @@ typedef struct { FuriString* duration_text; } SceneState; -void totp_scene_add_new_token_init(const PluginState* plugin_state) { - UNUSED(plugin_state); -} - static void on_token_name_user_comitted(InputTextSceneCallbackResult* result) { SceneState* scene_state = result->callback_data; free(scene_state->token_name); @@ -354,7 +350,3 @@ void totp_scene_add_new_token_deactivate(PluginState* plugin_state) { free(plugin_state->current_scene_state); plugin_state->current_scene_state = NULL; } - -void totp_scene_add_new_token_free(const PluginState* plugin_state) { - UNUSED(plugin_state); -} diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.h b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.h index c412e5f0f..e05a95dbd 100644 --- a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.h +++ b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.h @@ -1,8 +1,6 @@ #pragma once #include -#include -#include #include "../../../types/plugin_state.h" #include "../../../types/plugin_event.h" @@ -10,11 +8,9 @@ typedef struct { uint16_t current_token_index; } TokenAddEditSceneContext; -void totp_scene_add_new_token_init(const PluginState* plugin_state); void totp_scene_add_new_token_activate( PluginState* plugin_state, const TokenAddEditSceneContext* context); void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_state); bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state); void totp_scene_add_new_token_deactivate(PluginState* plugin_state); -void totp_scene_add_new_token_free(const PluginState* plugin_state); diff --git a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c index 93fd3d915..d2cf629d2 100644 --- a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c @@ -44,10 +44,6 @@ typedef struct { Control selected_control; } SceneState; -void totp_scene_app_settings_init(const PluginState* plugin_state) { - UNUSED(plugin_state); -} - void totp_scene_app_settings_activate( PluginState* plugin_state, const AppSettingsSceneContext* context) { @@ -332,7 +328,3 @@ void totp_scene_app_settings_deactivate(PluginState* plugin_state) { free(plugin_state->current_scene_state); plugin_state->current_scene_state = NULL; } - -void totp_scene_app_settings_free(const PluginState* plugin_state) { - UNUSED(plugin_state); -} \ No newline at end of file diff --git a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.h b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.h index 1721186ed..a0e408b00 100644 --- a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.h +++ b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.h @@ -8,7 +8,6 @@ typedef struct { uint16_t current_token_index; } AppSettingsSceneContext; -void totp_scene_app_settings_init(const PluginState* plugin_state); void totp_scene_app_settings_activate( PluginState* plugin_state, const AppSettingsSceneContext* context); @@ -16,5 +15,4 @@ void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plu bool totp_scene_app_settings_handle_event( const PluginEvent* const event, PluginState* plugin_state); -void totp_scene_app_settings_deactivate(PluginState* plugin_state); -void totp_scene_app_settings_free(const PluginState* plugin_state); \ No newline at end of file +void totp_scene_app_settings_deactivate(PluginState* plugin_state); \ No newline at end of file diff --git a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c index 17beb64c6..c0a0b5744 100644 --- a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c +++ b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c @@ -18,10 +18,6 @@ typedef struct { uint8_t code_length; } SceneState; -void totp_scene_authenticate_init(PluginState* plugin_state) { - memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE); -} - void totp_scene_authenticate_activate(PluginState* plugin_state) { SceneState* scene_state = malloc(sizeof(SceneState)); furi_check(scene_state != NULL); @@ -162,7 +158,3 @@ void totp_scene_authenticate_deactivate(PluginState* plugin_state) { free(plugin_state->current_scene_state); plugin_state->current_scene_state = NULL; } - -void totp_scene_authenticate_free(const PluginState* plugin_state) { - UNUSED(plugin_state); -} diff --git a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.h b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.h index b8fe174ae..5ddd44a4a 100644 --- a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.h +++ b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.h @@ -4,11 +4,9 @@ #include "../../../types/plugin_state.h" #include "../../../types/plugin_event.h" -void totp_scene_authenticate_init(PluginState* plugin_state); void totp_scene_authenticate_activate(PluginState* plugin_state); void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state); bool totp_scene_authenticate_handle_event( const PluginEvent* const event, PluginState* plugin_state); void totp_scene_authenticate_deactivate(PluginState* plugin_state); -void totp_scene_authenticate_free(const PluginState* plugin_state); diff --git a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c index f27b24835..92a45eb4a 100644 --- a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c @@ -2,39 +2,44 @@ #include #include #include +#include #include "totp_scene_generate_token.h" #include "../../../types/token_info.h" #include "../../../types/common.h" #include "../../constants.h" -#include "../../../services/totp/totp.h" #include "../../../services/config/config.h" -#include "../../../services/crypto/crypto.h" -#include "../../../services/convert/convert.h" -#include "../../../lib/polyfills/memset_s.h" -#include "../../../lib/roll_value/roll_value.h" #include "../../scene_director.h" #include "../token_menu/totp_scene_token_menu.h" #include "../../../features_config.h" +#include "../../../workers/generate_totp_code/generate_totp_code.h" #include "../../../workers/usb_type_code/usb_type_code.h" #ifdef TOTP_BADBT_TYPE_ENABLED #include "../../../workers/bt_type_code/bt_type_code.h" #endif #include "../../fonts/mode-nine/mode_nine.h" -static const char* STEAM_ALGO_ALPHABET = "23456789BCDFGHJKMNPQRTVWXY"; -static const uint8_t PROGRESS_BAR_MARGIN = 3; -static const uint8_t PROGRESS_BAR_HEIGHT = 4; +#define PROGRESS_BAR_MARGIN (3) +#define PROGRESS_BAR_HEIGHT (4) + +typedef struct { + uint8_t progress_bar_x; + uint8_t progress_bar_width; + uint8_t code_total_length; + uint8_t code_offset_x; + uint8_t code_offset_x_inc; + uint8_t code_offset_y; +} UiPrecalculatedDimensions; typedef struct { uint16_t current_token_index; char last_code[TOTP_TOKEN_DIGITS_MAX_COUNT + 1]; - bool need_token_update; TokenInfo* current_token; - uint32_t last_token_gen_time; TotpUsbTypeCodeWorkerContext* usb_type_code_worker_context; NotificationMessage const** notification_sequence_new_token; - NotificationMessage const** notification_sequence_badusb; + NotificationMessage const** notification_sequence_automation; FuriMutex* last_code_update_sync; + TotpGenerateCodeWorkerContext* generate_code_worker_context; + UiPrecalculatedDimensions ui_precalculated_dimensions; } SceneState; static const NotificationSequence* @@ -80,7 +85,7 @@ static const NotificationSequence* static const NotificationSequence* get_notification_sequence_automation(const PluginState* plugin_state, SceneState* scene_state) { - if(scene_state->notification_sequence_badusb == NULL) { + if(scene_state->notification_sequence_automation == NULL) { uint8_t i = 0; uint8_t length = 3; if(plugin_state->notification_method & NotificationMethodVibro) { @@ -91,110 +96,100 @@ static const NotificationSequence* length += 6; } - scene_state->notification_sequence_badusb = malloc(sizeof(void*) * length); - furi_check(scene_state->notification_sequence_badusb != NULL); + scene_state->notification_sequence_automation = malloc(sizeof(void*) * length); + furi_check(scene_state->notification_sequence_automation != NULL); - scene_state->notification_sequence_badusb[i++] = &message_blue_255; + scene_state->notification_sequence_automation[i++] = &message_blue_255; if(plugin_state->notification_method & NotificationMethodVibro) { - scene_state->notification_sequence_badusb[i++] = &message_vibro_on; + scene_state->notification_sequence_automation[i++] = &message_vibro_on; } if(plugin_state->notification_method & NotificationMethodSound) { - scene_state->notification_sequence_badusb[i++] = &message_note_d5; //-V525 - scene_state->notification_sequence_badusb[i++] = &message_delay_50; - scene_state->notification_sequence_badusb[i++] = &message_note_e4; - scene_state->notification_sequence_badusb[i++] = &message_delay_50; - scene_state->notification_sequence_badusb[i++] = &message_note_f3; + scene_state->notification_sequence_automation[i++] = &message_note_d5; //-V525 + scene_state->notification_sequence_automation[i++] = &message_delay_50; + scene_state->notification_sequence_automation[i++] = &message_note_e4; + scene_state->notification_sequence_automation[i++] = &message_delay_50; + scene_state->notification_sequence_automation[i++] = &message_note_f3; } - scene_state->notification_sequence_badusb[i++] = &message_delay_50; + scene_state->notification_sequence_automation[i++] = &message_delay_50; if(plugin_state->notification_method & NotificationMethodVibro) { - scene_state->notification_sequence_badusb[i++] = &message_vibro_off; + scene_state->notification_sequence_automation[i++] = &message_vibro_off; } if(plugin_state->notification_method & NotificationMethodSound) { - scene_state->notification_sequence_badusb[i++] = &message_sound_off; + scene_state->notification_sequence_automation[i++] = &message_sound_off; } - scene_state->notification_sequence_badusb[i++] = NULL; + scene_state->notification_sequence_automation[i++] = NULL; } - return (NotificationSequence*)scene_state->notification_sequence_badusb; -} - -static void - int_token_to_str(uint64_t i_token_code, char* str, TokenDigitsCount len, TokenHashAlgo algo) { - if(i_token_code == OTP_ERROR) { - memset(&str[0], '-', len); - } else { - if(algo == STEAM) { - for(uint8_t i = 0; i < len; i++) { - str[i] = STEAM_ALGO_ALPHABET[i_token_code % 26]; - i_token_code = i_token_code / 26; - } - } else { - for(int8_t i = len - 1; i >= 0; i--) { - str[i] = CONVERT_DIGIT_TO_CHAR(i_token_code % 10); - i_token_code = i_token_code / 10; - } - } - } - - str[len] = '\0'; -} - -static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { - switch(algo) { - case SHA1: - case STEAM: - return TOTP_ALGO_SHA1; - case SHA256: - return TOTP_ALGO_SHA256; - case SHA512: - return TOTP_ALGO_SHA512; - default: - break; - } - - return NULL; + return (NotificationSequence*)scene_state->notification_sequence_automation; } static void update_totp_params(PluginState* const plugin_state) { SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; if(scene_state->current_token_index < plugin_state->tokens_count) { - TokenInfo* tokenInfo = + scene_state->current_token = list_element_at(plugin_state->tokens_list, scene_state->current_token_index)->data; - - scene_state->need_token_update = true; - scene_state->current_token = tokenInfo; + totp_generate_code_worker_notify( + scene_state->generate_code_worker_context, TotpGenerateCodeWorkerEventForceUpdate); } } static void draw_totp_code(Canvas* const canvas, const SceneState* const scene_state) { uint8_t code_length = scene_state->current_token->digits; + uint8_t offset_x = scene_state->ui_precalculated_dimensions.code_offset_x; uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width; - uint8_t total_length = code_length * (char_width + modeNine_15ptFontInfo.spacePixels); - uint8_t offset_x = (SCREEN_WIDTH - total_length) >> 1; - uint8_t offset_y = SCREEN_HEIGHT_CENTER - (modeNine_15ptFontInfo.height >> 1); + uint8_t offset_x_inc = scene_state->ui_precalculated_dimensions.code_offset_x_inc; for(uint8_t i = 0; i < code_length; i++) { char ch = scene_state->last_code[i]; - uint8_t char_index = ch - modeNine_15ptFontInfo.startChar; - canvas_draw_xbm( - canvas, - offset_x, - offset_y, - char_width, - modeNine_15ptFontInfo.height, - &modeNine_15ptFontInfo.data[modeNine_15ptFontInfo.charInfo[char_index].offset]); + if(ch >= modeNine_15ptFontInfo.startChar && ch <= modeNine_15ptFontInfo.endChar) { + uint8_t char_index = ch - modeNine_15ptFontInfo.startChar; + canvas_draw_xbm( + canvas, + offset_x, + scene_state->ui_precalculated_dimensions.code_offset_y, + char_width, + modeNine_15ptFontInfo.height, + &modeNine_15ptFontInfo.data[modeNine_15ptFontInfo.charInfo[char_index].offset]); + } - offset_x += char_width + modeNine_15ptFontInfo.spacePixels; + offset_x += offset_x_inc; } } -void totp_scene_generate_token_init(const PluginState* plugin_state) { - UNUSED(plugin_state); +static void on_new_token_code_generated(bool time_left, void* context) { + const PluginState* plugin_state = context; + SceneState* scene_state = plugin_state->current_scene_state; + uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width; + scene_state->ui_precalculated_dimensions.code_total_length = + scene_state->current_token->digits * (char_width + modeNine_15ptFontInfo.spacePixels); + scene_state->ui_precalculated_dimensions.code_offset_x = + (SCREEN_WIDTH - scene_state->ui_precalculated_dimensions.code_total_length) >> 1; + scene_state->ui_precalculated_dimensions.code_offset_x_inc = + char_width + modeNine_15ptFontInfo.spacePixels; + scene_state->ui_precalculated_dimensions.code_offset_y = + SCREEN_HEIGHT_CENTER - (modeNine_15ptFontInfo.height >> 1); + + if(time_left) { + notification_message( + plugin_state->notification_app, + get_notification_sequence_new_token(plugin_state, plugin_state->current_scene_state)); + } +} + +static void on_code_lifetime_updated_generated(float code_lifetime_percent, void* context) { + SceneState* scene_state = context; + scene_state->ui_precalculated_dimensions.progress_bar_width = + (uint8_t)((float)(SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1)) * code_lifetime_percent); + scene_state->ui_precalculated_dimensions.progress_bar_x = + ((SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1) - + scene_state->ui_precalculated_dimensions.progress_bar_width) >> + 1) + + PROGRESS_BAR_MARGIN; } void totp_scene_generate_token_activate( @@ -234,15 +229,14 @@ void totp_scene_generate_token_activate( } else { scene_state->current_token_index = context->current_token_index; } - scene_state->need_token_update = true; + plugin_state->current_scene_state = scene_state; FURI_LOG_D(LOGGING_TAG, "Timezone set to: %f", (double)plugin_state->timezone_offset); - update_totp_params(plugin_state); scene_state->last_code_update_sync = furi_mutex_alloc(FuriMutexTypeNormal); if(plugin_state->automation_method & AutomationMethodBadUsb) { scene_state->usb_type_code_worker_context = totp_usb_type_code_worker_start( - &scene_state->last_code[0], + scene_state->last_code, TOTP_TOKEN_DIGITS_MAX_COUNT + 1, scene_state->last_code_update_sync); } @@ -255,11 +249,28 @@ void totp_scene_generate_token_activate( } totp_bt_type_code_worker_start( plugin_state->bt_type_code_worker_context, - &scene_state->last_code[0], + scene_state->last_code, TOTP_TOKEN_DIGITS_MAX_COUNT + 1, scene_state->last_code_update_sync); } #endif + + scene_state->generate_code_worker_context = totp_generate_code_worker_start( + scene_state->last_code, + &scene_state->current_token, + scene_state->last_code_update_sync, + plugin_state->timezone_offset, + plugin_state->iv); + + totp_generate_code_worker_set_code_generated_handler( + scene_state->generate_code_worker_context, &on_new_token_code_generated, plugin_state); + + totp_generate_code_worker_set_lifetime_changed_handler( + scene_state->generate_code_worker_context, + &on_code_lifetime_updated_generated, + scene_state); + + update_totp_params(plugin_state); } void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state) { @@ -281,54 +292,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ return; } - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - FuriHalRtcDateTime curr_dt; - furi_hal_rtc_get_datetime(&curr_dt); - uint32_t curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt); - - bool is_new_token_time = curr_ts % scene_state->current_token->duration == 0; - if(is_new_token_time && scene_state->last_token_gen_time != curr_ts) { - scene_state->need_token_update = true; - } - - if(scene_state->need_token_update) { - scene_state->need_token_update = false; - scene_state->last_token_gen_time = curr_ts; - - const TokenInfo* tokenInfo = scene_state->current_token; - - if(tokenInfo->token != NULL && tokenInfo->token_length > 0) { - furi_mutex_acquire(scene_state->last_code_update_sync, FuriWaitForever); - size_t key_length; - uint8_t* key = totp_crypto_decrypt( - tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length); - - int_token_to_str( - totp_at( - get_totp_algo_impl(tokenInfo->algo), - key, - key_length, - curr_ts, - plugin_state->timezone_offset, - tokenInfo->duration), - scene_state->last_code, - tokenInfo->digits, - tokenInfo->algo); - memset_s(key, key_length, 0, key_length); - free(key); - } else { - furi_mutex_acquire(scene_state->last_code_update_sync, FuriWaitForever); - int_token_to_str(0, scene_state->last_code, tokenInfo->digits, tokenInfo->algo); - } - - furi_mutex_release(scene_state->last_code_update_sync); - - if(is_new_token_time) { - notification_message( - plugin_state->notification_app, - get_notification_sequence_new_token(plugin_state, scene_state)); - } - } + const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; canvas_set_font(canvas, FontPrimary); uint16_t token_name_width = canvas_string_width(canvas, scene_state->current_token->name); @@ -356,17 +320,11 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ draw_totp_code(canvas, scene_state); - const uint8_t TOKEN_LIFETIME = scene_state->current_token->duration; - float percentDone = (float)(TOKEN_LIFETIME - curr_ts % TOKEN_LIFETIME) / (float)TOKEN_LIFETIME; - uint8_t barWidth = (uint8_t)((float)(SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1)) * percentDone); - uint8_t barX = - ((SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1) - barWidth) >> 1) + PROGRESS_BAR_MARGIN; - canvas_draw_box( canvas, - barX, + scene_state->ui_precalculated_dimensions.progress_bar_x, SCREEN_HEIGHT - PROGRESS_BAR_MARGIN - PROGRESS_BAR_HEIGHT, - barWidth, + scene_state->ui_precalculated_dimensions.progress_bar_width, PROGRESS_BAR_HEIGHT); if(plugin_state->tokens_count > 1) { @@ -496,6 +454,8 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) { if(plugin_state->current_scene_state == NULL) return; SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + totp_generate_code_worker_stop(scene_state->generate_code_worker_context); + if(plugin_state->automation_method & AutomationMethodBadUsb) { totp_usb_type_code_worker_stop(scene_state->usb_type_code_worker_context); } @@ -509,8 +469,8 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) { free(scene_state->notification_sequence_new_token); } - if(scene_state->notification_sequence_badusb != NULL) { - free(scene_state->notification_sequence_badusb); + if(scene_state->notification_sequence_automation != NULL) { + free(scene_state->notification_sequence_automation); } furi_mutex_free(scene_state->last_code_update_sync); @@ -518,7 +478,3 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) { free(scene_state); plugin_state->current_scene_state = NULL; } - -void totp_scene_generate_token_free(const PluginState* plugin_state) { - UNUSED(plugin_state); -} diff --git a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.h b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.h index 44a3b1c0f..e183f53d2 100644 --- a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.h +++ b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.h @@ -8,7 +8,6 @@ typedef struct { uint16_t current_token_index; } GenerateTokenSceneContext; -void totp_scene_generate_token_init(const PluginState* plugin_state); void totp_scene_generate_token_activate( PluginState* plugin_state, const GenerateTokenSceneContext* context); @@ -17,4 +16,3 @@ bool totp_scene_generate_token_handle_event( const PluginEvent* const event, PluginState* plugin_state); void totp_scene_generate_token_deactivate(PluginState* plugin_state); -void totp_scene_generate_token_free(const PluginState* plugin_state); diff --git a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c index 6c6986c65..7b00f0a1b 100644 --- a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c +++ b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c @@ -24,10 +24,6 @@ typedef struct { TotpNullable_uint16_t current_token_index; } SceneState; -void totp_scene_token_menu_init(const PluginState* plugin_state) { - UNUSED(plugin_state); -} - void totp_scene_token_menu_activate( PluginState* plugin_state, const TokenMenuSceneContext* context) { @@ -204,7 +200,3 @@ void totp_scene_token_menu_deactivate(PluginState* plugin_state) { free(plugin_state->current_scene_state); plugin_state->current_scene_state = NULL; } - -void totp_scene_token_menu_free(const PluginState* plugin_state) { - UNUSED(plugin_state); -} diff --git a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.h b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.h index 059b8e571..f9d4b4cbf 100644 --- a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.h +++ b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.h @@ -8,11 +8,9 @@ typedef struct { uint16_t current_token_index; } TokenMenuSceneContext; -void totp_scene_token_menu_init(const PluginState* plugin_state); void totp_scene_token_menu_activate( PluginState* plugin_state, const TokenMenuSceneContext* context); void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state); bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state); void totp_scene_token_menu_deactivate(PluginState* plugin_state); -void totp_scene_token_menu_free(const PluginState* plugin_state); diff --git a/applications/external/totp/ui/ui_controls.c b/applications/external/totp/ui/ui_controls.c index af029dd9f..d5e86aa58 100644 --- a/applications/external/totp/ui/ui_controls.c +++ b/applications/external/totp/ui/ui_controls.c @@ -2,8 +2,8 @@ #include #include "constants.h" -#define TEXT_BOX_HEIGHT 13 -#define TEXT_BOX_MARGIN 4 +#define TEXT_BOX_HEIGHT (13) +#define TEXT_BOX_MARGIN (4) void ui_control_text_box_render( Canvas* const canvas, diff --git a/applications/external/totp/workers/bt_type_code/bt_type_code.c b/applications/external/totp/workers/bt_type_code/bt_type_code.c index ec4c1619d..5a1f56298 100644 --- a/applications/external/totp/workers/bt_type_code/bt_type_code.c +++ b/applications/external/totp/workers/bt_type_code/bt_type_code.c @@ -1,10 +1,11 @@ #include "bt_type_code.h" #include +#include #include #include #include "../../types/common.h" #include "../../types/token_info.h" -#include "../common.h" +#include "../type_code_common.h" #define HID_BT_KEYS_STORAGE_PATH EXT_PATH("authenticator/.bt_hid.keys") @@ -16,15 +17,15 @@ static inline bool totp_type_code_worker_stop_requested() { static void totp_type_code_worker_bt_set_app_mac(uint8_t* mac) { uint8_t max_i; size_t uid_size = furi_hal_version_uid_size(); - if(uid_size < 6) { + if(uid_size < TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN) { max_i = uid_size; } else { - max_i = 6; + max_i = TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN; } const uint8_t* uid = furi_hal_version_uid(); memcpy(mac, uid, max_i); - for(uint8_t i = max_i; i < 6; i++) { + for(uint8_t i = max_i; i < TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN; i++) { mac[i] = 0; } @@ -39,23 +40,21 @@ static void totp_type_code_worker_type_code(TotpBtTypeCodeWorkerContext* context i++; } while(!context->is_connected && i < 100 && !totp_type_code_worker_stop_requested()); - if(context->is_connected && furi_mutex_acquire(context->string_sync, 500) == FuriStatusOk) { + if(context->is_connected && + furi_mutex_acquire(context->code_buffer_sync, 500) == FuriStatusOk) { totp_type_code_worker_execute_automation( &furi_hal_bt_hid_kb_press, &furi_hal_bt_hid_kb_release, - context->string, - context->string_length, + context->code_buffer, + context->code_buffer_size, context->flags); - furi_mutex_release(context->string_sync); + furi_mutex_release(context->code_buffer_sync); } } static int32_t totp_type_code_worker_callback(void* context) { furi_check(context); FuriMutex* context_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(context_mutex == NULL) { - return 251; - } TotpBtTypeCodeWorkerContext* bt_context = context; @@ -92,13 +91,13 @@ static void connection_status_changed_callback(BtStatus status, void* context) { void totp_bt_type_code_worker_start( TotpBtTypeCodeWorkerContext* context, - char* code_buf, - uint8_t code_buf_length, - FuriMutex* code_buf_update_sync) { + char* code_buffer, + uint8_t code_buffer_size, + FuriMutex* code_buffer_sync) { furi_check(context != NULL); - context->string = code_buf; - context->string_length = code_buf_length; - context->string_sync = code_buf_update_sync; + context->code_buffer = code_buffer; + context->code_buffer_size = code_buffer_size; + context->code_buffer_sync = code_buffer_sync; context->thread = furi_thread_alloc(); furi_thread_set_name(context->thread, "TOTPBtHidWorker"); furi_thread_set_stack_size(context->thread, 1024); @@ -137,7 +136,6 @@ TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init() { bt_keys_storage_set_storage_path(context->bt, HID_BT_KEYS_STORAGE_PATH); #if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME - totp_type_code_worker_bt_set_app_mac(&context->bt_mac[0]); memcpy( &context->previous_bt_name[0], furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard), @@ -148,8 +146,10 @@ TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init() { TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN); char new_name[TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN]; snprintf(new_name, sizeof(new_name), "%s TOTP Auth", furi_hal_version_get_name_ptr()); + uint8_t new_bt_mac[TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN]; + totp_type_code_worker_bt_set_app_mac(new_bt_mac); furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, new_name); - furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, context->bt_mac); + furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, new_bt_mac); #endif if(!bt_set_profile(context->bt, BtProfileHidKeyboard)) { diff --git a/applications/external/totp/workers/bt_type_code/bt_type_code.h b/applications/external/totp/workers/bt_type_code/bt_type_code.h index edbe52e14..6c7e502c6 100644 --- a/applications/external/totp/workers/bt_type_code/bt_type_code.h +++ b/applications/external/totp/workers/bt_type_code/bt_type_code.h @@ -1,49 +1,50 @@ #pragma once #include -#include -#include +#include +#include +#include +#include #include #include "../../features_config.h" #if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME -#define TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN 18 +#define TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN FURI_HAL_BT_ADV_NAME_LENGTH #define TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN GAP_MAC_ADDR_SIZE #endif typedef uint8_t TotpBtTypeCodeWorkerEvent; typedef struct { - char* string; - uint8_t string_length; + char* code_buffer; + uint8_t code_buffer_size; uint8_t flags; FuriThread* thread; - FuriMutex* string_sync; + FuriMutex* code_buffer_sync; Bt* bt; bool is_advertising; bool is_connected; #if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME - uint8_t bt_mac[TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN]; - char previous_bt_name[TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN + 1]; + char previous_bt_name[TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN]; uint8_t previous_bt_mac[TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN]; #endif } TotpBtTypeCodeWorkerContext; enum TotpBtTypeCodeWorkerEvents { - TotpBtTypeCodeWorkerEventReserved = 0b0000, - TotpBtTypeCodeWorkerEventStop = 0b0100, - TotpBtTypeCodeWorkerEventType = 0b1000 + TotpBtTypeCodeWorkerEventReserved = 0b00, + TotpBtTypeCodeWorkerEventStop = 0b01, + TotpBtTypeCodeWorkerEventType = 0b10 }; TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init(); void totp_bt_type_code_worker_free(TotpBtTypeCodeWorkerContext* context); void totp_bt_type_code_worker_start( TotpBtTypeCodeWorkerContext* context, - char* code_buf, - uint8_t code_buf_length, - FuriMutex* code_buf_update_sync); + char* code_buffer, + uint8_t code_buffer_size, + FuriMutex* code_buffer_sync); void totp_bt_type_code_worker_stop(TotpBtTypeCodeWorkerContext* context); void totp_bt_type_code_worker_notify( TotpBtTypeCodeWorkerContext* context, TotpBtTypeCodeWorkerEvent event, - uint8_t flags); \ No newline at end of file + uint8_t flags); diff --git a/applications/external/totp/workers/generate_totp_code/generate_totp_code.c b/applications/external/totp/workers/generate_totp_code/generate_totp_code.c new file mode 100644 index 000000000..4919cf942 --- /dev/null +++ b/applications/external/totp/workers/generate_totp_code/generate_totp_code.c @@ -0,0 +1,181 @@ +#include "generate_totp_code.h" +#include "../../services/crypto/crypto.h" +#include "../../services/totp/totp.h" +#include "../../services/convert/convert.h" +#include +#include + +#define ONE_SEC_MS (1000) + +static const char* STEAM_ALGO_ALPHABET = "23456789BCDFGHJKMNPQRTVWXY"; + +static void + int_token_to_str(uint64_t i_token_code, char* str, TokenDigitsCount len, TokenHashAlgo algo) { + str[len] = '\0'; + if(i_token_code == OTP_ERROR) { + memset(&str[0], '-', len); + } else { + if(algo == STEAM) { + for(uint8_t i = 0; i < len; i++) { + str[i] = STEAM_ALGO_ALPHABET[i_token_code % 26]; + i_token_code = i_token_code / 26; + } + } else { + for(int8_t i = len - 1; i >= 0; i--) { + str[i] = CONVERT_DIGIT_TO_CHAR(i_token_code % 10); + i_token_code = i_token_code / 10; + } + } + } +} + +static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { + switch(algo) { + case SHA1: + case STEAM: + return TOTP_ALGO_SHA1; + case SHA256: + return TOTP_ALGO_SHA256; + case SHA512: + return TOTP_ALGO_SHA512; + default: + break; + } + + return NULL; +} + +static void generate_totp_code( + TotpGenerateCodeWorkerContext* context, + const TokenInfo* token_info, + uint32_t current_ts) { + if(token_info->token != NULL && token_info->token_length > 0) { + size_t key_length; + uint8_t* key = totp_crypto_decrypt( + token_info->token, token_info->token_length, context->iv, &key_length); + + int_token_to_str( + totp_at( + get_totp_algo_impl(token_info->algo), + key, + key_length, + current_ts, + context->timezone_offset, + token_info->duration), + context->code_buffer, + token_info->digits, + token_info->algo); + memset_s(key, key_length, 0, key_length); + free(key); + } else { + int_token_to_str(0, context->code_buffer, token_info->digits, token_info->algo); + } +} + +static int32_t totp_generate_worker_callback(void* context) { + furi_check(context); + + TotpGenerateCodeWorkerContext* t_context = context; + + while(true) { + uint32_t flags = furi_thread_flags_wait( + TotpGenerateCodeWorkerEventStop | TotpGenerateCodeWorkerEventForceUpdate, + FuriFlagWaitAny, + ONE_SEC_MS); + + if(flags == + (uint32_t) + FuriFlagErrorTimeout) { // If timeout, consider as no error, as we expect this and can handle gracefully + flags = 0; + } + + furi_check((flags & FuriFlagError) == 0); //-V562 + + if(flags & TotpGenerateCodeWorkerEventStop) break; + + const TokenInfo* token_info = *(t_context->token_info); + if(token_info == NULL) { + continue; + } + + uint32_t curr_ts = furi_hal_rtc_get_timestamp(); + + bool time_left = false; + if(flags & TotpGenerateCodeWorkerEventForceUpdate || + (time_left = (curr_ts % token_info->duration) == 0)) { + if(furi_mutex_acquire(t_context->code_buffer_sync, FuriWaitForever) == FuriStatusOk) { + generate_totp_code(t_context, token_info, curr_ts); + curr_ts = furi_hal_rtc_get_timestamp(); + furi_mutex_release(t_context->code_buffer_sync); + if(t_context->on_new_code_generated_handler != NULL) { + (*(t_context->on_new_code_generated_handler))( + time_left, t_context->on_new_code_generated_handler_context); + } + } + } + + if(t_context->on_code_lifetime_changed_handler != NULL) { + (*(t_context->on_code_lifetime_changed_handler))( + (float)(token_info->duration - curr_ts % token_info->duration) / + (float)token_info->duration, + t_context->on_code_lifetime_changed_handler_context); + } + } + + return 0; +} + +TotpGenerateCodeWorkerContext* totp_generate_code_worker_start( + char* code_buffer, + TokenInfo** token_info, + FuriMutex* code_buffer_sync, + float timezone_offset, + uint8_t* iv) { + TotpGenerateCodeWorkerContext* context = malloc(sizeof(TotpGenerateCodeWorkerContext)); + furi_check(context != NULL); + context->code_buffer = code_buffer; + context->token_info = token_info; + context->code_buffer_sync = code_buffer_sync; + context->timezone_offset = timezone_offset; + context->iv = iv; + context->thread = furi_thread_alloc(); + furi_thread_set_name(context->thread, "TOTPGenerateWorker"); + furi_thread_set_stack_size(context->thread, 2048); + furi_thread_set_context(context->thread, context); + furi_thread_set_callback(context->thread, totp_generate_worker_callback); + furi_thread_start(context->thread); + return context; +} + +void totp_generate_code_worker_stop(TotpGenerateCodeWorkerContext* context) { + furi_check(context != NULL); + furi_thread_flags_set(furi_thread_get_id(context->thread), TotpGenerateCodeWorkerEventStop); + furi_thread_join(context->thread); + furi_thread_free(context->thread); + free(context); +} + +void totp_generate_code_worker_notify( + TotpGenerateCodeWorkerContext* context, + TotpGenerateCodeWorkerEvent event) { + furi_check(context != NULL); + furi_thread_flags_set(furi_thread_get_id(context->thread), event); +} + +void totp_generate_code_worker_set_code_generated_handler( + TotpGenerateCodeWorkerContext* context, + TOTP_NEW_CODE_GENERATED_HANDLER on_new_code_generated_handler, + void* on_new_code_generated_handler_context) { + furi_check(context != NULL); + context->on_new_code_generated_handler = on_new_code_generated_handler; + context->on_new_code_generated_handler_context = on_new_code_generated_handler_context; +} + +void totp_generate_code_worker_set_lifetime_changed_handler( + TotpGenerateCodeWorkerContext* context, + TOTP_CODE_LIFETIME_CHANGED_HANDLER on_code_lifetime_changed_handler, + void* on_code_lifetime_changed_handler_context) { + furi_check(context != NULL); + context->on_code_lifetime_changed_handler = on_code_lifetime_changed_handler; + context->on_code_lifetime_changed_handler_context = on_code_lifetime_changed_handler_context; +} \ No newline at end of file diff --git a/applications/external/totp/workers/generate_totp_code/generate_totp_code.h b/applications/external/totp/workers/generate_totp_code/generate_totp_code.h new file mode 100644 index 000000000..c7a93dc95 --- /dev/null +++ b/applications/external/totp/workers/generate_totp_code/generate_totp_code.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include "../../types/token_info.h" + +typedef uint8_t TotpGenerateCodeWorkerEvent; + +typedef void (*TOTP_NEW_CODE_GENERATED_HANDLER)(bool time_left, void* context); +typedef void (*TOTP_CODE_LIFETIME_CHANGED_HANDLER)(float code_lifetime_percent, void* context); + +typedef struct { + char* code_buffer; + FuriThread* thread; + FuriMutex* code_buffer_sync; + TokenInfo** token_info; + float timezone_offset; + uint8_t* iv; + TOTP_NEW_CODE_GENERATED_HANDLER on_new_code_generated_handler; + void* on_new_code_generated_handler_context; + TOTP_CODE_LIFETIME_CHANGED_HANDLER on_code_lifetime_changed_handler; + void* on_code_lifetime_changed_handler_context; +} TotpGenerateCodeWorkerContext; + +enum TotGenerateCodeWorkerEvents { + TotpGenerateCodeWorkerEventReserved = 0b00, + TotpGenerateCodeWorkerEventStop = 0b01, + TotpGenerateCodeWorkerEventForceUpdate = 0b10 +}; + +TotpGenerateCodeWorkerContext* totp_generate_code_worker_start( + char* code_buffer, + TokenInfo** token_info, + FuriMutex* code_buffer_sync, + float timezone_offset, + uint8_t* iv); +void totp_generate_code_worker_stop(TotpGenerateCodeWorkerContext* context); +void totp_generate_code_worker_notify( + TotpGenerateCodeWorkerContext* context, + TotpGenerateCodeWorkerEvent event); +void totp_generate_code_worker_set_code_generated_handler( + TotpGenerateCodeWorkerContext* context, + TOTP_NEW_CODE_GENERATED_HANDLER on_new_code_generated_handler, + void* on_new_code_generated_handler_context); +void totp_generate_code_worker_set_lifetime_changed_handler( + TotpGenerateCodeWorkerContext* context, + TOTP_CODE_LIFETIME_CHANGED_HANDLER on_code_lifetime_changed_handler, + void* on_code_lifetime_changed_handler_context); \ No newline at end of file diff --git a/applications/external/totp/workers/common.c b/applications/external/totp/workers/type_code_common.c similarity index 88% rename from applications/external/totp/workers/common.c rename to applications/external/totp/workers/type_code_common.c index 8ad0c2b46..fa5e7290f 100644 --- a/applications/external/totp/workers/common.c +++ b/applications/external/totp/workers/type_code_common.c @@ -1,6 +1,6 @@ -#include "common.h" -#include -#include +#include "type_code_common.h" +#include +#include #include "../../services/convert/convert.h" static const uint8_t hid_number_keys[] = { @@ -42,18 +42,18 @@ static void totp_type_code_worker_press_key( void totp_type_code_worker_execute_automation( TOTP_AUTOMATION_KEY_HANDLER key_press_fn, TOTP_AUTOMATION_KEY_HANDLER key_release_fn, - const char* string, - uint8_t string_length, + const char* code_buffer, + uint8_t code_buffer_size, TokenAutomationFeature features) { furi_delay_ms(500); uint8_t i = 0; totp_type_code_worker_press_key( HID_KEYBOARD_CAPS_LOCK, key_press_fn, key_release_fn, features); - while(i < string_length && string[i] != 0) { - uint8_t char_index = CONVERT_CHAR_TO_DIGIT(string[i]); + while(i < code_buffer_size && code_buffer[i] != 0) { + uint8_t char_index = CONVERT_CHAR_TO_DIGIT(code_buffer[i]); if(char_index > 9) { - char_index = string[i] - 0x41 + 10; + char_index = code_buffer[i] - 0x41 + 10; } if(char_index > 35) break; diff --git a/applications/external/totp/workers/common.h b/applications/external/totp/workers/type_code_common.h similarity index 83% rename from applications/external/totp/workers/common.h rename to applications/external/totp/workers/type_code_common.h index 5e3a2006e..1516928cf 100644 --- a/applications/external/totp/workers/common.h +++ b/applications/external/totp/workers/type_code_common.h @@ -7,6 +7,6 @@ typedef bool (*TOTP_AUTOMATION_KEY_HANDLER)(uint16_t key); void totp_type_code_worker_execute_automation( TOTP_AUTOMATION_KEY_HANDLER key_press_fn, TOTP_AUTOMATION_KEY_HANDLER key_release_fn, - const char* string, - uint8_t string_length, + const char* code_buffer, + uint8_t code_buffer_size, TokenAutomationFeature features); \ No newline at end of file diff --git a/applications/external/totp/workers/usb_type_code/usb_type_code.c b/applications/external/totp/workers/usb_type_code/usb_type_code.c index 5f7ccddf8..10034907d 100644 --- a/applications/external/totp/workers/usb_type_code/usb_type_code.c +++ b/applications/external/totp/workers/usb_type_code/usb_type_code.c @@ -1,7 +1,8 @@ #include "usb_type_code.h" +#include #include "../../services/convert/convert.h" #include "../../types/token_info.h" -#include "../common.h" +#include "../type_code_common.h" static void totp_type_code_worker_restore_usb_mode(TotpUsbTypeCodeWorkerContext* context) { if(context->usb_mode_prev != NULL) { @@ -25,14 +26,14 @@ static void totp_type_code_worker_type_code(TotpUsbTypeCodeWorkerContext* contex } while(!furi_hal_hid_is_connected() && i < 100 && !totp_type_code_worker_stop_requested()); if(furi_hal_hid_is_connected() && - furi_mutex_acquire(context->string_sync, 500) == FuriStatusOk) { + furi_mutex_acquire(context->code_buffer_sync, 500) == FuriStatusOk) { totp_type_code_worker_execute_automation( &furi_hal_hid_kb_press, &furi_hal_hid_kb_release, - context->string, - context->string_length, + context->code_buffer, + context->code_buffer_size, context->flags); - furi_mutex_release(context->string_sync); + furi_mutex_release(context->code_buffer_sync); furi_delay_ms(100); } @@ -43,9 +44,6 @@ static void totp_type_code_worker_type_code(TotpUsbTypeCodeWorkerContext* contex static int32_t totp_type_code_worker_callback(void* context) { furi_check(context); FuriMutex* context_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(context_mutex == NULL) { - return 251; - } while(true) { uint32_t flags = furi_thread_flags_wait( @@ -70,14 +68,14 @@ static int32_t totp_type_code_worker_callback(void* context) { } TotpUsbTypeCodeWorkerContext* totp_usb_type_code_worker_start( - char* code_buf, - uint8_t code_buf_length, - FuriMutex* code_buf_update_sync) { + char* code_buffer, + uint8_t code_buffer_size, + FuriMutex* code_buffer_sync) { TotpUsbTypeCodeWorkerContext* context = malloc(sizeof(TotpUsbTypeCodeWorkerContext)); furi_check(context != NULL); - context->string = code_buf; - context->string_length = code_buf_length; - context->string_sync = code_buf_update_sync; + context->code_buffer = code_buffer; + context->code_buffer_size = code_buffer_size; + context->code_buffer_sync = code_buffer_sync; context->thread = furi_thread_alloc(); context->usb_mode_prev = NULL; furi_thread_set_name(context->thread, "TOTPUsbHidWorker"); diff --git a/applications/external/totp/workers/usb_type_code/usb_type_code.h b/applications/external/totp/workers/usb_type_code/usb_type_code.h index d0ea600ce..21213f4d4 100644 --- a/applications/external/totp/workers/usb_type_code/usb_type_code.h +++ b/applications/external/totp/workers/usb_type_code/usb_type_code.h @@ -1,17 +1,20 @@ #pragma once #include -#include -#include +#include +#include +#include +#include +#include typedef uint8_t TotpUsbTypeCodeWorkerEvent; typedef struct { - char* string; - uint8_t string_length; + char* code_buffer; + uint8_t code_buffer_size; uint8_t flags; FuriThread* thread; - FuriMutex* string_sync; + FuriMutex* code_buffer_sync; FuriHalUsbInterface* usb_mode_prev; } TotpUsbTypeCodeWorkerContext; @@ -22,9 +25,9 @@ enum TotpUsbTypeCodeWorkerEvents { }; TotpUsbTypeCodeWorkerContext* totp_usb_type_code_worker_start( - char* code_buf, - uint8_t code_buf_length, - FuriMutex* code_buf_update_sync); + char* code_buffer, + uint8_t code_buffer_size, + FuriMutex* code_buffer_sync); void totp_usb_type_code_worker_stop(TotpUsbTypeCodeWorkerContext* context); void totp_usb_type_code_worker_notify( TotpUsbTypeCodeWorkerContext* context, diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c b/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c index 38a5a20e4..6988c42de 100644 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c +++ b/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c @@ -114,13 +114,9 @@ void uart_terminal_scene_console_output_on_enter(void* context) { // Send command with CR+LF or newline '\n' if(app->is_command && app->selected_tx_string) { if(app->TERMINAL_MODE == 1) { - // char buffer[240]; - // snprintf(buffer, 240, "%s\r\n", (app->selected_tx_string)); - // uart_terminal_uart_tx((unsigned char *)buffer, strlen(buffer)); uart_terminal_uart_tx( (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); - uart_terminal_uart_tx((uint8_t*)("\r"), 1); - uart_terminal_uart_tx((uint8_t*)("\n"), 1); + uart_terminal_uart_tx((uint8_t*)("\r\n"), 2); } else { uart_terminal_uart_tx( (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); @@ -149,9 +145,4 @@ void uart_terminal_scene_console_output_on_exit(void* context) { // Unregister rx callback uart_terminal_uart_set_handle_rx_data_cb(app->uart, NULL); - - // Automatically logut when exiting view - //if(app->is_command) { - // uart_terminal_uart_tx((uint8_t*)("exit\n"), strlen("exit\n")); - //} } \ No newline at end of file diff --git a/applications/external/unitemp/Sensors.c b/applications/external/unitemp/Sensors.c index 30419a929..666438bfa 100644 --- a/applications/external/unitemp/Sensors.c +++ b/applications/external/unitemp/Sensors.c @@ -45,7 +45,7 @@ static const GPIO GPIOList[] = { {14, "14 (RX)", &RX_14}, {15, "15 (C1)", &gpio_ext_pc1}, {16, "16 (C0)", &gpio_ext_pc0}, - {17, "17 (1W)", &ibutton_gpio}}; + {17, "17 (1W)", &gpio_ibutton}}; //СпиÑок интерфейÑов, которые прикреплены к GPIO (определÑетÑÑ Ð¸Ð½Ð´ÐµÐºÑом) //NULL - порт Ñвободен, указатель на Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ - порт занÑÑ‚ Ñтим интерфейÑом diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index f4f2550da..47dd9cf5e 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -1,6 +1,7 @@ #include "fap_loader_app.h" #include +#include #include #include @@ -23,8 +24,6 @@ struct FapLoader { Loading* loading; }; -volatile bool fap_loader_debug_active = false; - bool fap_loader_load_name_and_icon( FuriString* path, Storage* storage, @@ -134,7 +133,7 @@ static bool fap_loader_run_selected_app(FapLoader* loader, bool ignore_mismatch) FuriThread* thread = flipper_application_spawn(loader->app, NULL); /* This flag is set by the debugger - to break on app start */ - if(fap_loader_debug_active) { + if(furi_hal_debug_is_gdb_session_active()) { FURI_LOG_W(TAG, "Triggering BP for debugger"); /* After hitting this, you can set breakpoints in your .fap's code * Note that you have to toggle breakpoints that were set before */ diff --git a/applications/main/onewire/onewire_cli.c b/applications/main/onewire/onewire_cli.c index 4c16fb389..5f6cdc670 100644 --- a/applications/main/onewire/onewire_cli.c +++ b/applications/main/onewire/onewire_cli.c @@ -25,7 +25,7 @@ static void onewire_cli_print_usage() { static void onewire_cli_search(Cli* cli) { UNUSED(cli); - OneWireHost* onewire = onewire_host_alloc(&ibutton_gpio); + OneWireHost* onewire = onewire_host_alloc(&gpio_ibutton); uint8_t address[8]; bool done = false; diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 1e3d6a9c0..0c692e000 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -239,7 +239,11 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { if(!subghz_tx_start(subghz, subghz->txrx->fff_data)) { subghz->txrx->rx_key_state = SubGhzRxKeyStateBack; - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); + subghz_read_raw_set_status( + subghz->subghz_read_raw, + SubGhzReadRAWStatusIDLE, + "", + subghz->txrx->raw_threshold_rssi); } else { if(scene_manager_has_previous_scene( subghz->scene_manager, SubGhzSceneSaved) || diff --git a/applications/main/subghz/scenes/subghz_scene_transmitter.c b/applications/main/subghz/scenes/subghz_scene_transmitter.c index 7895d8bc3..4ee3854da 100644 --- a/applications/main/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/main/subghz/scenes/subghz_scene_transmitter.c @@ -74,9 +74,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { } if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) || (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { - if(!subghz_tx_start(subghz, subghz->txrx->fff_data)) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); - } else { + if(subghz_tx_start(subghz, subghz->txrx->fff_data)) { subghz->state_notifications = SubGhzNotificationStateTx; subghz_scene_transmitter_update_data_show(subghz); DOLPHIN_DEED(DolphinDeedSubGhzSend); diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 579a16520..dd0160213 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -106,9 +106,11 @@ static bool subghz_tx(SubGhz* subghz, uint32_t frequency) { furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); furi_hal_gpio_init( furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - subghz_speaker_on(subghz); bool ret = furi_hal_subghz_tx(); - subghz->txrx->txrx_state = SubGhzTxRxStateTx; + if(ret) { + subghz_speaker_on(subghz); + subghz->txrx->txrx_state = SubGhzTxRxStateTx; + } return ret; } @@ -116,6 +118,7 @@ void subghz_idle(SubGhz* subghz) { furi_assert(subghz); furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep); furi_hal_subghz_idle(); + subghz_speaker_off(subghz); subghz->txrx->txrx_state = SubGhzTxRxStateIDLE; } @@ -611,7 +614,7 @@ void subghz_hopper_update(SubGhz* subghz) { void subghz_speaker_on(SubGhz* subghz) { if(subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&ibutton_gpio); + furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); } if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) { @@ -656,7 +659,7 @@ void subghz_speaker_mute(SubGhz* subghz) { void subghz_speaker_unmute(SubGhz* subghz) { if(subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&ibutton_gpio); + furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); } if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) { if(furi_hal_speaker_is_mine()) { diff --git a/applications/main/subghz/views/transmitter.c b/applications/main/subghz/views/transmitter.c index e8c53d1ed..2bec77690 100644 --- a/applications/main/subghz/views/transmitter.c +++ b/applications/main/subghz/views/transmitter.c @@ -137,6 +137,7 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) { true); if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) { + subghz_custom_btn_set(0); with_view_model( subghz_transmitter->view, SubGhzViewTransmitterModel * model, diff --git a/applications/main/subghz_remote/subghz_remote_app.c b/applications/main/subghz_remote/subghz_remote_app.c index 040273838..a6225e1b5 100644 --- a/applications/main/subghz_remote/subghz_remote_app.c +++ b/applications/main/subghz_remote/subghz_remote_app.c @@ -354,6 +354,8 @@ bool subghz_remote_key_load( bool res = false; + subghz_custom_btn_set(0); + do { // load frequency from file if(!flipper_format_read_uint32(fff_file, "Frequency", &preset->frequency, 1)) { diff --git a/applications/settings/power_settings_app/views/battery_info.c b/applications/settings/power_settings_app/views/battery_info.c index 7394fd3c5..0956cae4f 100644 --- a/applications/settings/power_settings_app/views/battery_info.c +++ b/applications/settings/power_settings_app/views/battery_info.c @@ -4,8 +4,8 @@ #include #include -#define LOW_CHARGE_THRESHOLD 10 -#define HIGH_DRAIN_CURRENT_THRESHOLD 100 +#define LOW_CHARGE_THRESHOLD (10) +#define HIGH_DRAIN_CURRENT_THRESHOLD (-100) struct BatteryInfo { View* view; @@ -25,14 +25,13 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { char header[20] = {}; char value[20] = {}; - int32_t drain_current = data->gauge_current * (-1000); - uint32_t charge_current = data->gauge_current * 1000; + int32_t current = 1000.0f * data->gauge_current; // Draw battery canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28); - if(charge_current > 0) { + if(current > 0) { canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14); - } else if(drain_current > HIGH_DRAIN_CURRENT_THRESHOLD) { + } else if(current < HIGH_DRAIN_CURRENT_THRESHOLD) { canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14); } else if(data->charge < LOW_CHARGE_THRESHOLD) { canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14); @@ -44,7 +43,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { elements_bubble(canvas, 53, 0, 71, 39); // Set text - if(charge_current > 0) { + if(current > 0) { snprintf(emote, sizeof(emote), "%s", "Yummy!"); snprintf(header, sizeof(header), "%s", "Charging at"); snprintf( @@ -53,34 +52,36 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { "%lu.%luV %lumA", (uint32_t)(data->vbus_voltage), (uint32_t)(data->vbus_voltage * 10) % 10, - charge_current); - } else if(drain_current > 0) { + current); + } else if(current < 0) { snprintf( emote, sizeof(emote), "%s", - drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!"); + current < HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!"); snprintf(header, sizeof(header), "%s", "Consumption is"); snprintf( value, sizeof(value), "%ld %s", - drain_current, - drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA"); - } else if(drain_current != 0) { - snprintf(header, 20, "..."); - } else if(data->charge_voltage_limit < 4.2) { - // Non-default battery charging limit, mention it - snprintf(emote, sizeof(emote), "Charged!"); - snprintf(header, sizeof(header), "Limited to"); - snprintf( - value, - sizeof(value), - "%lu.%luV", - (uint32_t)(data->charge_voltage_limit), - (uint32_t)(data->charge_voltage_limit * 10) % 10); + ABS(current), + current < HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA"); + } else if(data->vbus_voltage > 0) { + if(data->charge_voltage_limit < 4.2) { + // Non-default battery charging limit, mention it + snprintf(emote, sizeof(emote), "Charged!"); + snprintf(header, sizeof(header), "Limited to"); + snprintf( + value, + sizeof(value), + "%lu.%luV", + (uint32_t)(data->charge_voltage_limit), + (uint32_t)(data->charge_voltage_limit * 10) % 10); + } else { + snprintf(header, sizeof(header), "Charged!"); + } } else { - snprintf(header, sizeof(header), "Charged!"); + snprintf(header, sizeof(header), "Napping..."); } canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote); diff --git a/applications/settings/system/system_settings.c b/applications/settings/system/system_settings.c index 868f87bb3..8cbe62da8 100644 --- a/applications/settings/system/system_settings.c +++ b/applications/settings/system/system_settings.c @@ -141,6 +141,21 @@ static void hand_orient_changed(VariableItem* item) { loader_update_menu(); } +const char* const sleep_method[] = { + "Default", + "Legacy", +}; + +static void sleep_method_changed(VariableItem* item) { + uint8_t index = variable_item_get_current_value_index(item); + variable_item_set_current_value_text(item, sleep_method[index]); + if(index) { + furi_hal_rtc_set_flag(FuriHalRtcFlagLegacySleep); + } else { + furi_hal_rtc_reset_flag(FuriHalRtcFlagLegacySleep); + } +} + static uint32_t system_settings_exit(void* context) { UNUSED(context); return VIEW_NONE; @@ -218,6 +233,12 @@ SystemSettings* system_settings_alloc() { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, heap_trace_mode_text[value_index]); + item = variable_item_list_add( + app->var_item_list, "Sleep Method", COUNT_OF(sleep_method), sleep_method_changed, app); + value_index = furi_hal_rtc_is_flag_set(FuriHalRtcFlagLegacySleep) ? 1 : 0; + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, sleep_method[value_index]); + view_set_previous_callback( variable_item_list_get_view(app->var_item_list), system_settings_exit); view_dispatcher_add_view( diff --git a/debug/flipperapps.py b/debug/flipperapps.py index 1dc5ebd04..90582c1e4 100644 --- a/debug/flipperapps.py +++ b/debug/flipperapps.py @@ -135,6 +135,7 @@ class FlipperAppStateHelper: self.app_list_ptr = None self.app_list_entry_type = None self._current_apps: list[AppState] = [] + self.set_debug_mode(True) def _walk_app_list(self, list_head): while list_head: @@ -195,7 +196,7 @@ class FlipperAppStateHelper: self.set_debug_mode(False) def set_debug_mode(self, mode: bool) -> None: - gdb.execute(f"set variable fap_loader_debug_active = {int(mode)}") + gdb.execute(f"set variable furi_hal_debug_gdb_session_active = {int(mode)}") # Init additional 'fap-set-debug-elf-root' command and set up hooks diff --git a/documentation/FuriHalDebuging.md b/documentation/FuriHalDebuging.md new file mode 100644 index 000000000..8ff770163 --- /dev/null +++ b/documentation/FuriHalDebuging.md @@ -0,0 +1,26 @@ +# Furi HAL Debugging + +Some Furi subsystem got additional debugging features that can be enabled by adding additional defines to firmware compilation. +Usually they are used for low level tracing and profiling or signal redirection/duplication. + + +## FuriHalOs + +`--extra-define=FURI_HAL_OS_DEBUG` enables tick, tick suppression, idle and time flow. + +There are 3 signals that will be exposed to external GPIO pins: + +- `AWAKE` - `PA7` - High when system is busy with computations, low when sleeping. Can be used to track transitions to sleep mode. +- `TICK` - `PA6` - Flipped on system tick, only flips when no tick suppression in progress. Can be used to track tick skew and abnormal task scheduling. +- `SECOND` - `PA4` - Flipped each second. Can be used for tracing RT issue: time flow disturbance means system doesn't conforms Hard RT. + + + +## FuriHalPower + +`--extra-define=FURI_HAL_POWER_DEBUG` enables power subsystem mode transitions tracing. + +There are 2 signals that will be exposed to external GPIO pins: + +- `WFI` - `PB2` - Light sleep (wait for interrupt) used. Basically this is lightest and most non-breaking things power save mode. All function and debug should work correctly in this mode. +- `STOP` - `PC3` - STOP mode used. Platform deep sleep mode. Extremely fragile mode where most of the silicon is disabled or in unusable state. Debugging MCU in this mode is nearly impossible. \ No newline at end of file diff --git a/documentation/HowToBuild.md b/documentation/HowToBuild.md index 92bd4e418..bc0084e9a 100644 --- a/documentation/HowToBuild.md +++ b/documentation/HowToBuild.md @@ -7,7 +7,6 @@ For development: - Git -- Python3 - VSCode ## Clone the Repository @@ -16,15 +15,24 @@ You should clone with ```shell $ git clone --recursive https://github.com/DarkFlippers/unleashed-firmware.git ``` +## VSCode integration + +`fbt` includes basic development environment configuration for VS Code. Run `./fbt vscode_dist` to deploy it. That will copy the initial environment configuration to the `.vscode` folder. After that, you can use that configuration by starting VS Code and choosing the firmware root folder in the "File > Open Folder" menu. # Build on Linux/macOS Check out `documentation/fbt.md` for details on building and flashing firmware. +### Compile plugin and run it on connected flipper + +```sh +./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=applications_user/yourplugin +``` + ### Compile everything for development ```sh -./fbt +./fbt FIRMWARE_APP_SET=debug_pack updater_package ``` ### Compile everything for release + get updater package to update from microSD card @@ -35,7 +43,7 @@ Check out `documentation/fbt.md` for details on building and flashing firmware. Check `dist/` for build outputs. -Use **`flipper-z-{target}-full-{suffix}.dfu`** to flash your device. +Use **`flipper-z-{target}-update-{suffix}.tgz`** to flash your device. # Build on Windows @@ -45,7 +53,7 @@ Check out `documentation/fbt.md` for details on building and flashing firmware. ### Compile everything for development ```sh -.\fbt.cmd +.\fbt.cmd FIRMWARE_APP_SET=debug_pack updater_package ``` ### Compile everything for release + get updater package to update from microSD card @@ -56,7 +64,7 @@ Check out `documentation/fbt.md` for details on building and flashing firmware. Check `dist/` for build outputs. -Use **`flipper-z-{target}-full-{suffix}.dfu`** to flash your device. +Use **`flipper-z-{target}-update-{suffix}.tgz`** to flash your device. diff --git a/documentation/fbt.md b/documentation/fbt.md index 14d63e9ce..23b2e2b55 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -105,6 +105,7 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio - `--options optionfile.py` (default value `fbt_options.py`) - load a file with multiple configuration values - `--extra-int-apps=app1,app2,appN` - force listed apps to be built as internal with the `firmware` target - `--extra-ext-apps=app1,app2,appN` - force listed apps to be built as external with the `firmware_extapps` target +- `--extra-define=A --extra-define=B=C ` - extra global defines that will be passed to the C/C++ compiler, can be specified multiple times - `--proxy-env=VAR1,VAR2` - additional environment variables to expose to subprocesses spawned by `fbt`. By default, `fbt` sanitizes the execution environment and doesn't forward all inherited environment variables. You can find the list of variables that are always forwarded in the `environ.scons` file. ## Configuration diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 3806ac47b..493f59634 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,20.1,, +Version,+,22.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -901,6 +901,7 @@ Function,+,furi_hal_crypto_verify_enclave,_Bool,"uint8_t*, uint8_t*" Function,+,furi_hal_crypto_verify_key,_Bool,uint8_t Function,+,furi_hal_debug_disable,void, Function,+,furi_hal_debug_enable,void, +Function,+,furi_hal_debug_is_gdb_session_active,_Bool, Function,-,furi_hal_deinit_early,void, Function,-,furi_hal_flash_erase,void,uint8_t Function,-,furi_hal_flash_get_base,size_t, @@ -983,7 +984,6 @@ Function,-,furi_hal_os_init,void, Function,+,furi_hal_os_tick,void, Function,+,furi_hal_power_check_otg_status,void, Function,+,furi_hal_power_debug_get,void,"PropertyValueCallback, void*" -Function,+,furi_hal_power_deep_sleep_available,_Bool, Function,+,furi_hal_power_disable_external_3_3v,void, Function,+,furi_hal_power_disable_otg,void, Function,+,furi_hal_power_enable_external_3_3v,void, @@ -1059,6 +1059,7 @@ Function,+,furi_hal_rtc_set_locale_units,void,FuriHalRtcLocaleUnits Function,+,furi_hal_rtc_set_log_level,void,uint8_t Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t" +Function,+,furi_hal_rtc_sync_shadow,void, Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime* Function,+,furi_hal_speaker_acquire,_Bool,uint32_t Function,-,furi_hal_speaker_deinit,void, @@ -2149,6 +2150,8 @@ Variable,+,gpio_ext_pd0,const GpioPin, Variable,+,gpio_ext_pe4,const GpioPin, Variable,+,gpio_i2c_power_scl,const GpioPin, Variable,+,gpio_i2c_power_sda,const GpioPin, +Variable,+,gpio_ibutton,const GpioPin, +Variable,+,gpio_periph_power,const GpioPin, Variable,+,gpio_pins,const GpioPinRecord[], Variable,+,gpio_pins_count,const size_t, Variable,+,gpio_sdcard_cd,const GpioPin, @@ -2157,11 +2160,13 @@ Variable,+,gpio_speaker,const GpioPin, Variable,+,gpio_spi_d_miso,const GpioPin, Variable,+,gpio_spi_d_mosi,const GpioPin, Variable,+,gpio_spi_d_sck,const GpioPin, +Variable,+,gpio_swclk,const GpioPin, +Variable,+,gpio_swdio,const GpioPin, Variable,+,gpio_usart_rx,const GpioPin, Variable,+,gpio_usart_tx,const GpioPin, Variable,+,gpio_usb_dm,const GpioPin, Variable,+,gpio_usb_dp,const GpioPin, -Variable,+,ibutton_gpio,const GpioPin, +Variable,+,gpio_vibro,const GpioPin, Variable,+,input_pins,const InputPin[], Variable,+,input_pins_count,const size_t, Variable,+,message_blink_set_color_blue,const NotificationMessage, @@ -2309,7 +2314,6 @@ Variable,+,message_red_255,const NotificationMessage, Variable,+,message_sound_off,const NotificationMessage, Variable,+,message_vibro_off,const NotificationMessage, Variable,+,message_vibro_on,const NotificationMessage, -Variable,+,periph_power,const GpioPin, Variable,+,sequence_audiovisual_alert,const NotificationSequence, Variable,+,sequence_blink_blue_10,const NotificationSequence, Variable,+,sequence_blink_blue_100,const NotificationSequence, @@ -2364,4 +2368,3 @@ Variable,+,usb_cdc_single,FuriHalUsbInterface, Variable,+,usb_hid,FuriHalUsbInterface, Variable,+,usb_hid_u2f,FuriHalUsbInterface, Variable,+,usbd_devfs,const usbd_driver, -Variable,+,vibro_gpio,const GpioPin, diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.c b/firmware/targets/f18/furi_hal/furi_hal_resources.c index abb258cb1..6db483dbc 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f18/furi_hal/furi_hal_resources.c @@ -6,8 +6,11 @@ #define TAG "FuriHalResources" -const GpioPin vibro_gpio = {.port = GPIOA, .pin = LL_GPIO_PIN_8}; -const GpioPin ibutton_gpio = {.port = GPIOB, .pin = LL_GPIO_PIN_14}; +const GpioPin gpio_swdio = {.port = GPIOA, .pin = LL_GPIO_PIN_13}; +const GpioPin gpio_swclk = {.port = GPIOA, .pin = LL_GPIO_PIN_14}; + +const GpioPin gpio_vibro = {.port = GPIOA, .pin = LL_GPIO_PIN_8}; +const GpioPin gpio_ibutton = {.port = GPIOB, .pin = LL_GPIO_PIN_14}; const GpioPin gpio_display_cs = {.port = GPIOC, .pin = LL_GPIO_PIN_11}; const GpioPin gpio_display_rst_n = {.port = GPIOB, .pin = LL_GPIO_PIN_0}; @@ -57,7 +60,7 @@ const GpioPin gpio_i2c_power_scl = {.port = GPIOA, .pin = LL_GPIO_PIN_9}; const GpioPin gpio_speaker = {.port = GPIOB, .pin = LL_GPIO_PIN_8}; -const GpioPin periph_power = {.port = GPIOA, .pin = LL_GPIO_PIN_3}; +const GpioPin gpio_periph_power = {.port = GPIOA, .pin = LL_GPIO_PIN_3}; const GpioPin gpio_usb_dm = {.port = GPIOA, .pin = LL_GPIO_PIN_11}; const GpioPin gpio_usb_dp = {.port = GPIOA, .pin = LL_GPIO_PIN_12}; @@ -118,8 +121,8 @@ void furi_hal_resources_init_early() { furi_hal_resources_init_input_pins(GpioModeInput); // SD Card stepdown control - furi_hal_gpio_write(&periph_power, 1); - furi_hal_gpio_init(&periph_power, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_periph_power, 1); + furi_hal_gpio_init(&gpio_periph_power, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); // Display pins furi_hal_gpio_write(&gpio_display_rst_n, 1); @@ -165,6 +168,11 @@ void furi_hal_resources_init() { // Button pins furi_hal_resources_init_input_pins(GpioModeInterruptRiseFall); + // Explicit pulls pins + LL_PWR_EnablePUPDCfg(); + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_8); // gpio_speaker + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_A, LL_PWR_GPIO_BIT_8); // gpio_vibro + // Display pins furi_hal_gpio_init(&gpio_display_rst_n, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); furi_hal_gpio_write(&gpio_display_rst_n, 0); @@ -176,9 +184,7 @@ void furi_hal_resources_init() { furi_hal_gpio_init(&gpio_sdcard_cd, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_gpio_write(&gpio_sdcard_cd, 0); - furi_hal_gpio_init(&vibro_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - - furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ibutton, GpioModeAnalog, GpioPullNo, GpioSpeedLow); NVIC_SetPriority(EXTI0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(EXTI0_IRQn); @@ -222,7 +228,7 @@ int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) { return 15; else if(gpio == &gpio_ext_pc0) return 16; - else if(gpio == &ibutton_gpio) + else if(gpio == &gpio_ibutton) return 17; else return -1; diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.h b/firmware/targets/f18/furi_hal/furi_hal_resources.h index a24afbf94..7d2caab36 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f18/furi_hal/furi_hal_resources.h @@ -50,8 +50,11 @@ extern const size_t input_pins_count; extern const GpioPinRecord gpio_pins[]; extern const size_t gpio_pins_count; -extern const GpioPin vibro_gpio; -extern const GpioPin ibutton_gpio; +extern const GpioPin gpio_swdio; +extern const GpioPin gpio_swclk; + +extern const GpioPin gpio_vibro; +extern const GpioPin gpio_ibutton; extern const GpioPin gpio_display_cs; extern const GpioPin gpio_display_rst_n; @@ -100,7 +103,7 @@ extern const GpioPin gpio_i2c_power_scl; extern const GpioPin gpio_speaker; -extern const GpioPin periph_power; +extern const GpioPin gpio_periph_power; extern const GpioPin gpio_usb_dm; extern const GpioPin gpio_usb_dp; diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 10cf2ccd1..59b8c2e8d 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,20.1,, +Version,+,22.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1106,6 +1106,7 @@ Function,+,furi_hal_crypto_verify_enclave,_Bool,"uint8_t*, uint8_t*" Function,+,furi_hal_crypto_verify_key,_Bool,uint8_t Function,+,furi_hal_debug_disable,void, Function,+,furi_hal_debug_enable,void, +Function,+,furi_hal_debug_is_gdb_session_active,_Bool, Function,-,furi_hal_deinit_early,void, Function,-,furi_hal_flash_erase,void,uint8_t Function,-,furi_hal_flash_get_base,size_t, @@ -1238,7 +1239,6 @@ Function,-,furi_hal_os_init,void, Function,+,furi_hal_os_tick,void, Function,+,furi_hal_power_check_otg_status,void, Function,+,furi_hal_power_debug_get,void,"PropertyValueCallback, void*" -Function,+,furi_hal_power_deep_sleep_available,_Bool, Function,+,furi_hal_power_disable_external_3_3v,void, Function,+,furi_hal_power_disable_otg,void, Function,+,furi_hal_power_enable_external_3_3v,void, @@ -1338,6 +1338,7 @@ Function,+,furi_hal_rtc_set_locale_units,void,FuriHalRtcLocaleUnits Function,+,furi_hal_rtc_set_log_level,void,uint8_t Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t" +Function,+,furi_hal_rtc_sync_shadow,void, Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime* Function,+,furi_hal_speaker_acquire,_Bool,uint32_t Function,-,furi_hal_speaker_deinit,void, @@ -4736,10 +4737,12 @@ Variable,+,gpio_ext_pc1,const GpioPin, Variable,+,gpio_ext_pc3,const GpioPin, Variable,+,gpio_i2c_power_scl,const GpioPin, Variable,+,gpio_i2c_power_sda,const GpioPin, +Variable,+,gpio_ibutton,const GpioPin, Variable,+,gpio_infrared_rx,const GpioPin, Variable,+,gpio_infrared_tx,const GpioPin, Variable,+,gpio_nfc_cs,const GpioPin, Variable,+,gpio_nfc_irq_rfid_pull,const GpioPin, +Variable,+,gpio_periph_power,const GpioPin, Variable,+,gpio_pins,const GpioPinRecord[], Variable,+,gpio_pins_count,const size_t, Variable,+,gpio_rf_sw_0,const GpioPin, @@ -4760,11 +4763,13 @@ Variable,+,gpio_spi_r_sck,const GpioPin, Variable,+,gpio_spi_r_sck_ext,const GpioPin, Variable,+,gpio_subghz_cs,const GpioPin, Variable,+,gpio_subghz_cs_ext,const GpioPin, +Variable,+,gpio_swclk,const GpioPin, +Variable,+,gpio_swdio,const GpioPin, Variable,+,gpio_usart_rx,const GpioPin, Variable,+,gpio_usart_tx,const GpioPin, Variable,+,gpio_usb_dm,const GpioPin, Variable,+,gpio_usb_dp,const GpioPin, -Variable,+,ibutton_gpio,const GpioPin, +Variable,+,gpio_vibro,const GpioPin, Variable,+,input_pins,const InputPin[], Variable,+,input_pins_count,const size_t, Variable,+,lfrfid_protocols,const ProtocolBase*[], @@ -4913,7 +4918,6 @@ Variable,+,message_red_255,const NotificationMessage, Variable,+,message_sound_off,const NotificationMessage, Variable,+,message_vibro_off,const NotificationMessage, Variable,+,message_vibro_on,const NotificationMessage, -Variable,+,periph_power,const GpioPin, Variable,+,sequence_audiovisual_alert,const NotificationSequence, Variable,+,sequence_blink_blue_10,const NotificationSequence, Variable,+,sequence_blink_blue_100,const NotificationSequence, @@ -6920,4 +6924,3 @@ Variable,+,usb_cdc_single,FuriHalUsbInterface, Variable,+,usb_hid,FuriHalUsbInterface, Variable,+,usb_hid_u2f,FuriHalUsbInterface, Variable,+,usbd_devfs,const usbd_driver, -Variable,+,vibro_gpio,const GpioPin, diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index 83562c73e..a2f2f1a94 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -58,12 +58,6 @@ void ble_glue_init() { ble_glue = malloc(sizeof(BleGlue)); ble_glue->status = BleGlueStatusStartup; - // Configure the system Power Mode - // Select HSI as system clock source after Wake Up from Stop mode - LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); - /* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */ - LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); - #ifdef BLE_GLUE_DEBUG APPD_Init(); #endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.c b/firmware/targets/f7/furi_hal/furi_hal_clock.c index cf19451ec..d85524ce4 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_clock.c +++ b/firmware/targets/f7/furi_hal/furi_hal_clock.c @@ -63,6 +63,10 @@ void furi_hal_clock_init() { LL_RCC_HSI_Enable(); while(!HS_CLOCK_IS_READY()) ; + /* Select HSI as system clock source after Wake Up from Stop mode + * Must be set before enabling CSS */ + LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); + LL_RCC_HSE_EnableCSS(); /* LSE and LSI1 configuration and activation */ @@ -215,11 +219,14 @@ void furi_hal_clock_switch_to_hsi() { void furi_hal_clock_switch_to_pll() { LL_RCC_HSE_Enable(); LL_RCC_PLL_Enable(); + LL_RCC_PLLSAI1_Enable(); while(!LL_RCC_HSE_IsReady()) ; while(!LL_RCC_PLL_IsReady()) ; + while(!LL_RCC_PLLSAI1_IsReady()) + ; LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); @@ -296,4 +303,4 @@ void furi_hal_clock_mco_disable() { LL_RCC_MSI_Disable(); while(LL_RCC_MSI_IsReady() != 0) ; -} \ No newline at end of file +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_debug.c b/firmware/targets/f7/furi_hal/furi_hal_debug.c index 3b5dfe622..3dc03ea69 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_debug.c +++ b/firmware/targets/f7/furi_hal/furi_hal_debug.c @@ -3,12 +3,26 @@ #include #include +#include +#include + +volatile bool furi_hal_debug_gdb_session_active = false; + void furi_hal_debug_enable() { // Low power mode debug LL_DBGMCU_EnableDBGSleepMode(); LL_DBGMCU_EnableDBGStopMode(); LL_DBGMCU_EnableDBGStandbyMode(); LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48); + // SWD GPIO + furi_hal_gpio_init_ex( + &gpio_swdio, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedVeryHigh, + GpioAltFn0JTMS_SWDIO); + furi_hal_gpio_init_ex( + &gpio_swclk, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn0JTCK_SWCLK); } void furi_hal_debug_disable() { @@ -17,4 +31,11 @@ void furi_hal_debug_disable() { LL_DBGMCU_DisableDBGStopMode(); LL_DBGMCU_DisableDBGStandbyMode(); LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_48); + // SWD GPIO + furi_hal_gpio_init_simple(&gpio_swdio, GpioModeAnalog); + furi_hal_gpio_init_simple(&gpio_swclk, GpioModeAnalog); } + +bool furi_hal_debug_is_gdb_session_active() { + return furi_hal_debug_gdb_session_active; +} \ No newline at end of file diff --git a/firmware/targets/f7/furi_hal/furi_hal_ibutton.c b/firmware/targets/f7/furi_hal/furi_hal_ibutton.c index f19fd0a0e..c8041c9f2 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_ibutton.c +++ b/firmware/targets/f7/furi_hal/furi_hal_ibutton.c @@ -93,15 +93,15 @@ void furi_hal_ibutton_emulate_stop() { } void furi_hal_ibutton_pin_configure() { - furi_hal_gpio_write(&ibutton_gpio, true); - furi_hal_gpio_init(&ibutton_gpio, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_ibutton, true); + furi_hal_gpio_init(&gpio_ibutton, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); } void furi_hal_ibutton_pin_reset() { - furi_hal_gpio_write(&ibutton_gpio, true); - furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_ibutton, true); + furi_hal_gpio_init(&gpio_ibutton, GpioModeAnalog, GpioPullNo, GpioSpeedLow); } void furi_hal_ibutton_pin_write(const bool state) { - furi_hal_gpio_write(&ibutton_gpio, state); + furi_hal_gpio_write(&gpio_ibutton, state); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_infrared.c b/firmware/targets/f7/furi_hal/furi_hal_infrared.c index b65ea42e1..8098f8bd0 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_infrared.c +++ b/firmware/targets/f7/furi_hal/furi_hal_infrared.c @@ -570,9 +570,9 @@ static void furi_hal_infrared_async_tx_free_resources(void) { (furi_hal_infrared_state == InfraredStateAsyncTxStopped)); if(infrared_external_output) { - furi_hal_gpio_init(&gpio_ext_pa7, GpioModeOutputOpenDrain, GpioPullDown, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullDown, GpioSpeedLow); } else { - furi_hal_gpio_init(&gpio_infrared_tx, GpioModeOutputOpenDrain, GpioPullDown, GpioSpeedLow); + furi_hal_gpio_init(&gpio_infrared_tx, GpioModeAnalog, GpioPullDown, GpioSpeedLow); } furi_hal_interrupt_set_isr(IR_DMA_CH1_IRQ, NULL, NULL); furi_hal_interrupt_set_isr(IR_DMA_CH2_IRQ, NULL, NULL); diff --git a/firmware/targets/f7/furi_hal/furi_hal_os.c b/firmware/targets/f7/furi_hal/furi_hal_os.c index ee9743e62..3fc1fbea8 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_os.c +++ b/firmware/targets/f7/furi_hal/furi_hal_os.c @@ -28,11 +28,24 @@ // Arbitrary (but small) number for better tick consistency #define FURI_HAL_OS_EXTRA_CNT 3 +#ifndef FURI_HAL_OS_DEBUG_AWAKE_GPIO +#define FURI_HAL_OS_DEBUG_AWAKE_GPIO (&gpio_ext_pa7) +#endif + +#ifndef FURI_HAL_OS_DEBUG_TICK_GPIO +#define FURI_HAL_OS_DEBUG_TICK_GPIO (&gpio_ext_pa6) +#endif + +#ifndef FURI_HAL_OS_DEBUG_SECOND_GPIO +#define FURI_HAL_OS_DEBUG_SECOND_GPIO (&gpio_ext_pa4) +#endif + #ifdef FURI_HAL_OS_DEBUG #include void furi_hal_os_timer_callback() { - furi_hal_gpio_write(&gpio_ext_pa4, !furi_hal_gpio_read(&gpio_ext_pa4)); + furi_hal_gpio_write( + FURI_HAL_OS_DEBUG_SECOND_GPIO, !furi_hal_gpio_read(FURI_HAL_OS_DEBUG_SECOND_GPIO)); } #endif @@ -44,9 +57,11 @@ void furi_hal_os_init() { furi_hal_idle_timer_init(); #ifdef FURI_HAL_OS_DEBUG - furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); - furi_hal_gpio_init_simple(&gpio_ext_pa6, GpioModeOutputPushPull); - furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeOutputPushPull); + furi_hal_gpio_init_simple(FURI_HAL_OS_DEBUG_AWAKE_GPIO, GpioModeOutputPushPull); + furi_hal_gpio_init_simple(FURI_HAL_OS_DEBUG_TICK_GPIO, GpioModeOutputPushPull); + furi_hal_gpio_init_simple(FURI_HAL_OS_DEBUG_SECOND_GPIO, GpioModeOutputPushPull); + furi_hal_gpio_write(FURI_HAL_OS_DEBUG_AWAKE_GPIO, 1); + FuriTimer* second_timer = furi_timer_alloc(furi_hal_os_timer_callback, FuriTimerTypePeriodic, NULL); furi_timer_start(second_timer, FURI_HAL_OS_TICK_HZ); @@ -58,7 +73,8 @@ void furi_hal_os_init() { void furi_hal_os_tick() { if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { #ifdef FURI_HAL_OS_DEBUG - furi_hal_gpio_write(&gpio_ext_pa6, !furi_hal_gpio_read(&gpio_ext_pa6)); + furi_hal_gpio_write( + FURI_HAL_OS_DEBUG_TICK_GPIO, !furi_hal_gpio_read(FURI_HAL_OS_DEBUG_TICK_GPIO)); #endif xPortSysTickHandler(); } @@ -121,14 +137,14 @@ static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) { furi_hal_idle_timer_start(FURI_HAL_OS_TICKS_TO_IDLE_CNT(expected_idle_ticks)); #ifdef FURI_HAL_OS_DEBUG - furi_hal_gpio_write(&gpio_ext_pa7, 0); + furi_hal_gpio_write(FURI_HAL_OS_DEBUG_AWAKE_GPIO, 0); #endif // Go to sleep mode furi_hal_power_sleep(); #ifdef FURI_HAL_OS_DEBUG - furi_hal_gpio_write(&gpio_ext_pa7, 1); + furi_hal_gpio_write(FURI_HAL_OS_DEBUG_AWAKE_GPIO, 1); #endif // Calculate how much time we spent in the sleep diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index dd7c34ae7..9a87cef15 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include @@ -19,15 +21,16 @@ #define TAG "FuriHalPower" -#ifdef FURI_HAL_POWER_DEEP_SLEEP_ENABLED -#define FURI_HAL_POWER_DEEP_INSOMNIA 0 -#else -#define FURI_HAL_POWER_DEEP_INSOMNIA 1 +#ifndef FURI_HAL_POWER_DEBUG_WFI_GPIO +#define FURI_HAL_POWER_DEBUG_WFI_GPIO (&gpio_ext_pb2) +#endif + +#ifndef FURI_HAL_POWER_DEBUG_STOP_GPIO +#define FURI_HAL_POWER_DEBUG_STOP_GPIO (&gpio_ext_pc3) #endif typedef struct { volatile uint8_t insomnia; - volatile uint8_t deep_insomnia; volatile uint8_t suppress_charge; uint8_t gauge_initialized; @@ -36,7 +39,6 @@ typedef struct { static volatile FuriHalPower furi_hal_power = { .insomnia = 0, - .deep_insomnia = FURI_HAL_POWER_DEEP_INSOMNIA, .suppress_charge = 0, }; @@ -79,19 +81,23 @@ const ParamCEDV cedv = { }; void furi_hal_power_init() { +#ifdef FURI_HAL_POWER_DEBUG + furi_hal_gpio_init_simple(FURI_HAL_POWER_DEBUG_WFI_GPIO, GpioModeOutputPushPull); + furi_hal_gpio_init_simple(FURI_HAL_POWER_DEBUG_STOP_GPIO, GpioModeOutputPushPull); + furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_WFI_GPIO, 0); + furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_STOP_GPIO, 0); +#endif + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN); + LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2); + LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2); furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); bq27220_init(&furi_hal_i2c_handle_power, &cedv); bq25896_init(&furi_hal_i2c_handle_power); furi_hal_i2c_release(&furi_hal_i2c_handle_power); -#ifdef FURI_HAL_OS_DEBUG - furi_hal_gpio_init_simple(&gpio_ext_pb2, GpioModeOutputPushPull); - furi_hal_gpio_init_simple(&gpio_ext_pc3, GpioModeOutputPushPull); -#endif - FURI_LOG_I(TAG, "Init OK"); } @@ -140,11 +146,12 @@ bool furi_hal_power_sleep_available() { return furi_hal_power.insomnia == 0; } -bool furi_hal_power_deep_sleep_available() { - return furi_hal_bt_is_alive() && furi_hal_power.deep_insomnia == 0; +static inline bool furi_hal_power_deep_sleep_available() { + return furi_hal_bt_is_alive() && !furi_hal_rtc_is_flag_set(FuriHalRtcFlagLegacySleep) && + !furi_hal_debug_is_gdb_session_active(); } -void furi_hal_power_light_sleep() { +static inline void furi_hal_power_light_sleep() { __WFI(); } @@ -152,17 +159,15 @@ static inline void furi_hal_power_suspend_aux_periphs() { // Disable USART furi_hal_uart_suspend(FuriHalUartIdUSART1); furi_hal_uart_suspend(FuriHalUartIdLPUART1); - // TODO: Disable USB } static inline void furi_hal_power_resume_aux_periphs() { // Re-enable USART furi_hal_uart_resume(FuriHalUartIdUSART1); furi_hal_uart_resume(FuriHalUartIdLPUART1); - // TODO: Re-enable USB } -void furi_hal_power_deep_sleep() { +static inline void furi_hal_power_deep_sleep() { furi_hal_power_suspend_aux_periphs(); while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) @@ -187,8 +192,6 @@ void furi_hal_power_deep_sleep() { LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); // Prepare deep sleep - LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2); - LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2); LL_LPM_EnableDeepSleep(); #if defined(__CC_ARM) @@ -200,13 +203,6 @@ void furi_hal_power_deep_sleep() { LL_LPM_EnableSleep(); - // Make sure that values differ to prevent disaster on wfi - LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0); - LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); - - LL_PWR_ClearFlag_C1STOP_C1STB(); - LL_PWR_ClearFlag_C2STOP_C2STB(); - /* Release ENTRY_STOP_MODE semaphore */ LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); @@ -220,28 +216,25 @@ void furi_hal_power_deep_sleep() { LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); furi_hal_power_resume_aux_periphs(); + furi_hal_rtc_sync_shadow(); } void furi_hal_power_sleep() { if(furi_hal_power_deep_sleep_available()) { -#ifdef FURI_HAL_OS_DEBUG - furi_hal_gpio_write(&gpio_ext_pc3, 1); +#ifdef FURI_HAL_POWER_DEBUG + furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_STOP_GPIO, 1); #endif - furi_hal_power_deep_sleep(); - -#ifdef FURI_HAL_OS_DEBUG - furi_hal_gpio_write(&gpio_ext_pc3, 0); +#ifdef FURI_HAL_POWER_DEBUG + furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_STOP_GPIO, 0); #endif } else { -#ifdef FURI_HAL_OS_DEBUG - furi_hal_gpio_write(&gpio_ext_pb2, 1); +#ifdef FURI_HAL_POWER_DEBUG + furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_WFI_GPIO, 1); #endif - furi_hal_power_light_sleep(); - -#ifdef FURI_HAL_OS_DEBUG - furi_hal_gpio_write(&gpio_ext_pb2, 0); +#ifdef FURI_HAL_POWER_DEBUG + furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_WFI_GPIO, 0); #endif } } @@ -440,11 +433,11 @@ float furi_hal_power_get_usb_voltage() { } void furi_hal_power_enable_external_3_3v() { - furi_hal_gpio_write(&periph_power, 1); + furi_hal_gpio_write(&gpio_periph_power, 1); } void furi_hal_power_disable_external_3_3v() { - furi_hal_gpio_write(&periph_power, 0); + furi_hal_gpio_write(&gpio_periph_power, 0); } void furi_hal_power_suppress_charge_enter() { diff --git a/firmware/targets/f7/furi_hal/furi_hal_random.c b/firmware/targets/f7/furi_hal/furi_hal_random.c index f36407cc1..d3461c4d1 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_random.c +++ b/firmware/targets/f7/furi_hal/furi_hal_random.c @@ -9,19 +9,35 @@ #define TAG "FuriHalRandom" +static uint32_t furi_hal_random_read_rng() { + while(LL_RNG_IsActiveFlag_CECS(RNG) && LL_RNG_IsActiveFlag_SECS(RNG) && + !LL_RNG_IsActiveFlag_DRDY(RNG)) { + /* Error handling as described in RM0434, pg. 582-583 */ + if(LL_RNG_IsActiveFlag_CECS(RNG)) { + /* Clock error occurred */ + LL_RNG_ClearFlag_CEIS(RNG); + } + + if(LL_RNG_IsActiveFlag_SECS(RNG)) { + /* Noise source error occurred */ + LL_RNG_ClearFlag_SEIS(RNG); + + for(uint32_t i = 0; i < 12; ++i) { + const volatile uint32_t discard = LL_RNG_ReadRandData32(RNG); + UNUSED(discard); + } + } + } + + return LL_RNG_ReadRandData32(RNG); +} + uint32_t furi_hal_random_get() { while(LL_HSEM_1StepLock(HSEM, CFG_HW_RNG_SEMID)) ; LL_RNG_Enable(RNG); - while(!LL_RNG_IsActiveFlag_DRDY(RNG)) - ; - - if((LL_RNG_IsActiveFlag_CECS(RNG)) || (LL_RNG_IsActiveFlag_SECS(RNG))) { - furi_crash("TRNG error"); - } - - uint32_t random_val = LL_RNG_ReadRandData32(RNG); + const uint32_t random_val = furi_hal_random_read_rng(); LL_RNG_Disable(RNG); LL_HSEM_ReleaseLock(HSEM, CFG_HW_RNG_SEMID, 0); @@ -35,15 +51,7 @@ void furi_hal_random_fill_buf(uint8_t* buf, uint32_t len) { LL_RNG_Enable(RNG); for(uint32_t i = 0; i < len; i += 4) { - while(!LL_RNG_IsActiveFlag_DRDY(RNG)) - ; - - if((LL_RNG_IsActiveFlag_CECS(RNG)) || (LL_RNG_IsActiveFlag_SECS(RNG))) { - furi_crash("TRNG error"); - } - - uint32_t random_val = LL_RNG_ReadRandData32(RNG); - + const uint32_t random_val = furi_hal_random_read_rng(); uint8_t len_cur = ((i + 4) < len) ? (4) : (len - i); memcpy(&buf[i], &random_val, len_cur); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.c b/firmware/targets/f7/furi_hal/furi_hal_resources.c index 5cf44a6a8..f87f2a31a 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.c @@ -6,8 +6,11 @@ #define TAG "FuriHalResources" -const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin}; -const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin}; +const GpioPin gpio_swdio = {.port = GPIOA, .pin = LL_GPIO_PIN_13}; +const GpioPin gpio_swclk = {.port = GPIOA, .pin = LL_GPIO_PIN_14}; + +const GpioPin gpio_vibro = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin}; +const GpioPin gpio_ibutton = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin}; const GpioPin gpio_cc1101_g0 = {.port = CC1101_G0_GPIO_Port, .pin = CC1101_G0_Pin}; const GpioPin gpio_cc1101_g0_ext = {.port = GPIOB, .pin = LL_GPIO_PIN_2}; @@ -64,7 +67,7 @@ const GpioPin gpio_i2c_power_scl = {.port = GPIOA, .pin = LL_GPIO_PIN_9}; const GpioPin gpio_speaker = {.port = GPIOB, .pin = LL_GPIO_PIN_8}; -const GpioPin periph_power = {.port = GPIOA, .pin = LL_GPIO_PIN_3}; +const GpioPin gpio_periph_power = {.port = GPIOA, .pin = LL_GPIO_PIN_3}; const GpioPin gpio_usb_dm = {.port = GPIOA, .pin = LL_GPIO_PIN_11}; const GpioPin gpio_usb_dp = {.port = GPIOA, .pin = LL_GPIO_PIN_12}; @@ -111,8 +114,8 @@ void furi_hal_resources_init_early() { furi_hal_resources_init_input_pins(GpioModeInput); // SD Card stepdown control - furi_hal_gpio_write(&periph_power, 1); - furi_hal_gpio_init(&periph_power, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_periph_power, 1); + furi_hal_gpio_init(&gpio_periph_power, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); // Display pins furi_hal_gpio_write(&gpio_display_rst_n, 1); @@ -158,6 +161,12 @@ void furi_hal_resources_init() { // Button pins furi_hal_resources_init_input_pins(GpioModeInterruptRiseFall); + // Explicit, surviving reset, pulls + LL_PWR_EnablePUPDCfg(); + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_9); // gpio_infrared_tx + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_8); // gpio_speaker + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_A, LL_PWR_GPIO_BIT_8); // gpio_vibro + // Display pins furi_hal_gpio_init(&gpio_display_rst_n, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); furi_hal_gpio_write(&gpio_display_rst_n, 0); @@ -169,9 +178,7 @@ void furi_hal_resources_init() { furi_hal_gpio_init(&gpio_sdcard_cd, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_gpio_write(&gpio_sdcard_cd, 0); - furi_hal_gpio_init(&vibro_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - - furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ibutton, GpioModeAnalog, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInterruptRise, GpioPullNo, GpioSpeedLow); @@ -218,7 +225,7 @@ int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) { return 15; else if(gpio == &gpio_ext_pc0) return 16; - else if(gpio == &ibutton_gpio) + else if(gpio == &gpio_ibutton) return 17; else return -1; diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.h b/firmware/targets/f7/furi_hal/furi_hal_resources.h index 33e2a3289..391f8f4ff 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.h @@ -50,8 +50,11 @@ extern const size_t input_pins_count; extern const GpioPinRecord gpio_pins[]; extern const size_t gpio_pins_count; -extern const GpioPin vibro_gpio; -extern const GpioPin ibutton_gpio; +extern const GpioPin gpio_swdio; +extern const GpioPin gpio_swclk; + +extern const GpioPin gpio_vibro; +extern const GpioPin gpio_ibutton; extern const GpioPin gpio_cc1101_g0; extern const GpioPin gpio_cc1101_g0_ext; @@ -107,7 +110,7 @@ extern const GpioPin gpio_i2c_power_scl; extern const GpioPin gpio_speaker; -extern const GpioPin periph_power; +extern const GpioPin gpio_periph_power; extern const GpioPin gpio_usb_dm; extern const GpioPin gpio_usb_dp; diff --git a/firmware/targets/f7/furi_hal/furi_hal_rtc.c b/firmware/targets/f7/furi_hal/furi_hal_rtc.c index 84e7fe395..7bd45c35d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rtc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rtc.c @@ -165,6 +165,14 @@ void furi_hal_rtc_init() { FURI_LOG_I(TAG, "Init OK"); } +void furi_hal_rtc_sync_shadow() { + if(!LL_RTC_IsShadowRegBypassEnabled(RTC)) { + LL_RTC_ClearFlag_RS(RTC); + while(!LL_RTC_IsActiveFlag_RS(RTC)) { + }; + } +} + uint32_t furi_hal_rtc_get_register(FuriHalRtcRegister reg) { return LL_RTC_BAK_GetRegister(RTC, reg); } @@ -312,12 +320,7 @@ void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime) { /* Exit Initialization mode */ LL_RTC_DisableInitMode(RTC); - /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ - if(!LL_RTC_IsShadowRegBypassEnabled(RTC)) { - LL_RTC_ClearFlag_RS(RTC); - while(!LL_RTC_IsActiveFlag_RS(RTC)) { - }; - } + furi_hal_rtc_sync_shadow(); /* Enable write protection */ LL_RTC_EnableWriteProtection(RTC); diff --git a/firmware/targets/f7/furi_hal/furi_hal_speaker.c b/firmware/targets/f7/furi_hal/furi_hal_speaker.c index c4a0bdd1e..5421509cc 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_speaker.c +++ b/firmware/targets/f7/furi_hal/furi_hal_speaker.c @@ -52,7 +52,7 @@ void furi_hal_speaker_release() { furi_check(furi_hal_speaker_is_mine()); furi_hal_speaker_stop(); - furi_hal_gpio_init(&gpio_speaker, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_speaker, GpioModeAnalog, GpioPullDown, GpioSpeedLow); furi_hal_power_insomnia_exit(); furi_check(furi_mutex_release(furi_hal_speaker_mutex) == FuriStatusOk); diff --git a/firmware/targets/f7/furi_hal/furi_hal_vibro.c b/firmware/targets/f7/furi_hal/furi_hal_vibro.c index 4315ea637..f46784677 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_vibro.c +++ b/firmware/targets/f7/furi_hal/furi_hal_vibro.c @@ -4,11 +4,11 @@ #define TAG "FuriHalVibro" void furi_hal_vibro_init() { - furi_hal_gpio_init(&vibro_gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&vibro_gpio, false); + furi_hal_gpio_init(&gpio_vibro, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_vibro, false); FURI_LOG_I(TAG, "Init OK"); } void furi_hal_vibro_on(bool value) { - furi_hal_gpio_write(&vibro_gpio, value); + furi_hal_gpio_write(&gpio_vibro, value); } diff --git a/firmware/targets/furi_hal_include/furi_hal_debug.h b/firmware/targets/furi_hal_include/furi_hal_debug.h index 88397bbba..befbb4f40 100644 --- a/firmware/targets/furi_hal_include/furi_hal_debug.h +++ b/firmware/targets/furi_hal_include/furi_hal_debug.h @@ -18,6 +18,9 @@ void furi_hal_debug_enable(); /** Disable MCU debug */ void furi_hal_debug_disable(); +/** Check if GDB debug session is active */ +bool furi_hal_debug_is_gdb_session_active(); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h index 462e20e41..00182fa28 100644 --- a/firmware/targets/furi_hal_include/furi_hal_power.h +++ b/firmware/targets/furi_hal_include/furi_hal_power.h @@ -58,12 +58,6 @@ void furi_hal_power_insomnia_exit(); */ bool furi_hal_power_sleep_available(); -/** Check if deep sleep availble - * - * @return true if available - */ -bool furi_hal_power_deep_sleep_available(); - /** Go to sleep */ void furi_hal_power_sleep(); diff --git a/firmware/targets/furi_hal_include/furi_hal_rtc.h b/firmware/targets/furi_hal_include/furi_hal_rtc.h index b16b04a68..0d9f46f01 100644 --- a/firmware/targets/furi_hal_include/furi_hal_rtc.h +++ b/firmware/targets/furi_hal_include/furi_hal_rtc.h @@ -30,6 +30,7 @@ typedef enum { FuriHalRtcFlagLock = (1 << 2), FuriHalRtcFlagC2Update = (1 << 3), FuriHalRtcFlagHandOrient = (1 << 4), + FuriHalRtcFlagLegacySleep = (1 << 5), } FuriHalRtcFlag; typedef enum { @@ -85,6 +86,9 @@ void furi_hal_rtc_deinit_early(); /** Initialize RTC subsystem */ void furi_hal_rtc_init(); +/** Force sync shadow registers */ +void furi_hal_rtc_sync_shadow(); + /** Get RTC register content * * @param[in] reg The register identifier diff --git a/furi/core/check.c b/furi/core/check.c index 910527cee..64f9f72f1 100644 --- a/furi/core/check.c +++ b/furi/core/check.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -117,6 +118,8 @@ FURI_NORETURN void __furi_crash() { if(debug) { furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n"); furi_hal_console_puts("\033[0m\r\n"); + furi_hal_debug_enable(); + RESTORE_REGISTERS_AND_HALT_MCU(true); } else { furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message); diff --git a/furi/core/core_defines.h b/furi/core/core_defines.h index 03a364abd..830bb191c 100644 --- a/furi/core/core_defines.h +++ b/furi/core/core_defines.h @@ -24,6 +24,10 @@ extern "C" { }) #endif +#ifndef ABS +#define ABS(a) ({ (a) < 0 ? -(a) : (a); }) +#endif + #ifndef ROUND_UP_TO #define ROUND_UP_TO(a, b) \ ({ \ diff --git a/lib/ibutton/protocols/dallas/protocol_group_dallas.c b/lib/ibutton/protocols/dallas/protocol_group_dallas.c index d0ffa511b..63ec97855 100644 --- a/lib/ibutton/protocols/dallas/protocol_group_dallas.c +++ b/lib/ibutton/protocols/dallas/protocol_group_dallas.c @@ -14,8 +14,8 @@ typedef struct { static iButtonProtocolGroupDallas* ibutton_protocol_group_dallas_alloc() { iButtonProtocolGroupDallas* group = malloc(sizeof(iButtonProtocolGroupDallas)); - group->host = onewire_host_alloc(&ibutton_gpio); - group->bus = onewire_slave_alloc(&ibutton_gpio); + group->host = onewire_host_alloc(&gpio_ibutton); + group->bus = onewire_slave_alloc(&gpio_ibutton); return group; } diff --git a/lib/subghz/blocks/custom_btn.c b/lib/subghz/blocks/custom_btn.c index dd1436798..3023e09ea 100644 --- a/lib/subghz/blocks/custom_btn.c +++ b/lib/subghz/blocks/custom_btn.c @@ -1,7 +1,7 @@ #include "custom_btn.h" -static uint8_t custom_btn_id; -static uint8_t custom_btn_original; +static uint8_t custom_btn_id = 0; +static uint8_t custom_btn_original = 0; static uint8_t custom_btn_max_btns = 0; void subghz_custom_btn_set(uint8_t b) { diff --git a/lib/subghz/environment.c b/lib/subghz/environment.c index b39b259d4..5ded243c4 100644 --- a/lib/subghz/environment.c +++ b/lib/subghz/environment.c @@ -16,6 +16,7 @@ SubGhzEnvironment* subghz_environment_alloc() { instance->protocol_registry = NULL; instance->came_atomo_rainbow_table_file_name = NULL; instance->nice_flor_s_rainbow_table_file_name = NULL; + instance->alutech_at_4n_rainbow_table_file_name = NULL; return instance; } @@ -26,6 +27,7 @@ void subghz_environment_free(SubGhzEnvironment* instance) { instance->protocol_registry = NULL; instance->came_atomo_rainbow_table_file_name = NULL; instance->nice_flor_s_rainbow_table_file_name = NULL; + instance->alutech_at_4n_rainbow_table_file_name = NULL; subghz_keystore_free(instance->keystore); free(instance); diff --git a/scripts/get_env.py b/scripts/get_env.py index f661f38d6..92f9243c2 100644 --- a/scripts/get_env.py +++ b/scripts/get_env.py @@ -32,7 +32,7 @@ def parse_args(): def get_commit_json(event): context = ssl._create_unverified_context() commit_url = event["pull_request"]["base"]["repo"]["commits_url"].replace( - "{/sha}", f"/{event['after']}" + "{/sha}", f"/{event['pull_request']['head']['sha']}" ) with urllib.request.urlopen(commit_url, context=context) as commit_file: commit_json = json.loads(commit_file.read().decode("utf-8")) diff --git a/scripts/sconsdist.py b/scripts/sconsdist.py index 2d5b1ae79..23e194a94 100644 --- a/scripts/sconsdist.py +++ b/scripts/sconsdist.py @@ -181,9 +181,9 @@ class Main(App): ) as zf: for component_key in sdk_components_keys: component_path = self._dist_components.get(component_key) - components_paths[component_key] = basename(component_path) if component_key.endswith(".dir"): + components_paths[component_key] = basename(component_path) for root, dirnames, files in walk(component_path): if "__pycache__" in dirnames: dirnames.remove("__pycache__") @@ -199,7 +199,9 @@ class Main(App): ), ) else: - zf.write(component_path, basename(component_path)) + # We use fixed names for files to avoid having to regenerate VSCode project + components_paths[component_key] = component_key + zf.write(component_path, component_key) zf.writestr( "components.json", diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index a82189c14..7228e2f51 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -163,6 +163,18 @@ dist_env.Alias("flash", openocd_target) if env["FORCE"]: env.AlwaysBuild(openocd_target) + +firmware_jflash = dist_env.JFlash( + dist_env["UFBT_STATE_DIR"].File("jflash"), + dist_env["FW_BIN"], + JFLASHADDR="0x20000000", +) +dist_env.Alias("firmware_jflash", firmware_jflash) +dist_env.Alias("jflash", firmware_jflash) +if env["FORCE"]: + env.AlwaysBuild(firmware_jflash) + + firmware_debug = dist_env.PhonyTarget( "debug", "${GDBPYCOM}", @@ -391,3 +403,13 @@ AddPostAction( dist_env.Precious(app_template_dist) dist_env.NoClean(app_template_dist) dist_env.Alias("create", app_template_dist) + +dist_env.PhonyTarget( + "get_blackmagic", + "@echo $( ${BLACKMAGIC_ADDR} $)", +) + +dist_env.PhonyTarget( + "get_apiversion", + "@echo $( ${UFBT_API_VERSION} $)", +) diff --git a/scripts/ufbt/project_template/.vscode/launch.json b/scripts/ufbt/project_template/.vscode/launch.json index d9c98dcc1..697de9a49 100644 --- a/scripts/ufbt/project_template/.vscode/launch.json +++ b/scripts/ufbt/project_template/.vscode/launch.json @@ -2,19 +2,16 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "inputs": [ - // { - // "id": "BLACKMAGIC", - // "type": "command", - // "command": "shellCommand.execute", - // "args": { - // "useSingleResult": true, - // "env": { - // "PATH": "${workspaceFolder};${env:PATH}" - // }, - // "command": "./fbt get_blackmagic", - // "description": "Get Blackmagic device", - // } - // }, + { + "id": "BLACKMAGIC", + "type": "command", + "command": "shellCommand.execute", + "args": { + "description": "Get Blackmagic device", + "useSingleResult": true, + "command": "ufbt -s get_blackmagic", + } + }, ], "configurations": [ { @@ -57,26 +54,26 @@ ], // "showDevDebugOutput": "raw", }, - // { - // "name": "Attach FW (blackmagic)", - // "cwd": "${workspaceFolder}", - // "executable": "@UFBT_FIRMWARE_ELF@", - // "request": "attach", - // "type": "cortex-debug", - // "servertype": "external", - // "gdbTarget": "${input:BLACKMAGIC}", - // "svdFile": "@UFBT_DEBUG_DIR@/STM32WB55_CM4.svd", - // "rtos": "FreeRTOS", - // "postAttachCommands": [ - // "monitor swdp_scan", - // "attach 1", - // "set confirm off", - // "set mem inaccessible-by-default off", - // "source @UFBT_DEBUG_DIR@/flipperapps.py", - // "fap-set-debug-elf-root @UFBT_DEBUG_ELF_DIR@" - // ] - // // "showDevDebugOutput": "raw", - // }, + { + "name": "Attach FW (blackmagic)", + "cwd": "${workspaceFolder}", + "executable": "@UFBT_FIRMWARE_ELF@", + "request": "attach", + "type": "cortex-debug", + "servertype": "external", + "gdbTarget": "${input:BLACKMAGIC}", + "svdFile": "@UFBT_DEBUG_DIR@/STM32WB55_CM4.svd", + "rtos": "FreeRTOS", + "postAttachCommands": [ + "monitor swdp_scan", + "attach 1", + "set confirm off", + "set mem inaccessible-by-default off", + "source @UFBT_DEBUG_DIR@/flipperapps.py", + "fap-set-debug-elf-root @UFBT_DEBUG_ELF_DIR@" + ] + // "showDevDebugOutput": "raw", + }, { "name": "Attach FW (JLink)", "cwd": "${workspaceFolder}", diff --git a/scripts/ufbt/project_template/.vscode/tasks.json b/scripts/ufbt/project_template/.vscode/tasks.json index 6343bba7b..4b3f4bda5 100644 --- a/scripts/ufbt/project_template/.vscode/tasks.json +++ b/scripts/ufbt/project_template/.vscode/tasks.json @@ -20,24 +20,30 @@ "type": "shell", "command": "ufbt" }, + { + "label": "Clean", + "group": "build", + "type": "shell", + "command": "ufbt -c" + }, { "label": "Flash FW (ST-Link)", "group": "build", "type": "shell", "command": "ufbt FORCE=1 flash" }, - // { - // "label": "[NOTIMPL] Flash FW (blackmagic)", - // "group": "build", - // "type": "shell", - // "command": "ufbt flash_blackmagic" - // }, - // { - // "label": "[NOTIMPL] Flash FW (JLink)", - // "group": "build", - // "type": "shell", - // "command": "ufbt FORCE=1 jflash" - // }, + { + "label": "Flash FW (blackmagic)", + "group": "build", + "type": "shell", + "command": "ufbt flash_blackmagic" + }, + { + "label": "Flash FW (JLink)", + "group": "build", + "type": "shell", + "command": "ufbt FORCE=1 jflash" + }, { "label": "Flash FW (USB, with resources)", "group": "build", @@ -49,6 +55,12 @@ "group": "build", "type": "shell", "command": "ufbt update" + }, + { + "label": "Update VSCode config for current SDK", + "group": "build", + "type": "shell", + "command": "ufbt vscode_dist" } ] } \ No newline at end of file diff --git a/scripts/ufbt/project_template/app_template/application.fam b/scripts/ufbt/project_template/app_template/application.fam index 31fadb207..37a4ce665 100644 --- a/scripts/ufbt/project_template/app_template/application.fam +++ b/scripts/ufbt/project_template/app_template/application.fam @@ -6,7 +6,7 @@ App( apptype=FlipperAppType.EXTERNAL, entry_point="@FBT_APPID@_app", stack_size=2 * 1024, - fap_category="Misc", + fap_category="Examples", # Optional values # fap_version=(0, 1), # (major, minor) fap_icon="@FBT_APPID@.png", # 10x10 1-bit PNG diff --git a/scripts/ufbt/site_tools/ufbt_state.py b/scripts/ufbt/site_tools/ufbt_state.py index 6ba8c6962..76c6e9acf 100644 --- a/scripts/ufbt/site_tools/ufbt_state.py +++ b/scripts/ufbt/site_tools/ufbt_state.py @@ -75,12 +75,6 @@ def generate(env, **kw): if not sdk_state["meta"]["hw_target"].endswith(sdk_data["hardware"]): raise StopError("SDK state file doesn't match hardware target") - if sdk_state["meta"]["version"] != ufbt_state["version"]: - warn( - WarningOnByDefault, - f"Version mismatch: SDK state vs uFBT: {sdk_state['meta']['version']} vs {ufbt_state['version']}", - ) - scripts_dir = sdk_current_sdk_dir_node.Dir(sdk_components["scripts.dir"]) env.SetDefault( # Paths diff --git a/site_scons/cc.scons b/site_scons/cc.scons index 1eb6a3376..55ab72ba6 100644 --- a/site_scons/cc.scons +++ b/site_scons/cc.scons @@ -36,6 +36,7 @@ ENV.AppendUnique( ], CPPDEFINES=[ "_GNU_SOURCE", + *GetOption("extra_defines"), ], LINKFLAGS=[ "-mcpu=cortex-m4", diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index 5610478cb..84ef6ce19 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -26,6 +26,14 @@ AddOption( help="List of applications to add to firmware's built-ins. Also see FIRMWARE_APP_SET and FIRMWARE_APPS", ) +AddOption( + "--extra-define", + action="append", + dest="extra_defines", + default=[], + help="Extra global define that will be passed to C/C++ compiler, can be specified multiple times", +) + AddOption( "--extra-ext-apps", action="store", diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 798b85ea1..89ee49242 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -1,5 +1,4 @@ from dataclasses import dataclass, field -from os.path import dirname from SCons.Node import NodeList from SCons.Warnings import warn, WarningOnByDefault @@ -131,6 +130,7 @@ Depends(sdk_source, appenv.ProcessSdkDepends(f"{amalgamated_api}.d")) appenv["SDK_DIR"] = appenv.Dir("${BUILD_DIR}/sdk_headers") sdk_header_tree = appenv.SDKHeaderTreeExtractor(appenv["SDK_DIR"], amalgamated_api) +Depends(sdk_header_tree, appenv["SDK_DEFINITION"]) # AlwaysBuild(sdk_tree) Alias("sdk_tree", sdk_header_tree) extapps.sdk_tree = sdk_header_tree