1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 04:34:43 +04:00

Merge branch 'dev' into release

This commit is contained in:
MX
2023-04-14 04:08:34 +03:00
113 changed files with 1328 additions and 657 deletions

2
.gitignore vendored
View File

@@ -30,7 +30,7 @@ bindings/
Brewfile.lock.json
# Visual Studio Code
.vscode/
/.vscode/
# Kate
.kateproject

View File

@@ -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)

View File

@@ -10,7 +10,7 @@
<br>
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
<br>
@@ -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

View File

@@ -34,7 +34,7 @@ void AccessorApp::run(void) {
AccessorApp::AccessorApp()
: text_store{0} {
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
onewire_host = onewire_host_alloc(&ibutton_gpio);
onewire_host = onewire_host_alloc(&gpio_ibutton);
furi_hal_power_enable_otg();
}

View File

@@ -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",
)

View File

@@ -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.

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -198,9 +198,10 @@ bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance) {
}
avr_isp_end_pmode(instance->avr_isp);
} while(0);
furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4);
} while(0);
if(instance->callback) {
if(instance->chip_arr_ind > avr_isp_chip_arr_size) {
instance->callback(instance->context, "No detect", instance->chip_detect, 0);

View File

@@ -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 <20>flashpoll<6C>
// ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as <20>flashpoll<6C>
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;
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -3,11 +3,11 @@
#include <furi_hal.h>
#include <notification/notification_messages.h>
#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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -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

View File

@@ -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;

View File

@@ -6,5 +6,6 @@ typedef enum {
HidViewMouse,
HidViewMouseJiggler,
BtHidViewTikTok,
BtHidViewYTShorts,
HidViewExitConfirm,
} HidView;

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -0,0 +1,268 @@
#include "hid_ytshorts.h"
#include "../hid.h"
#include <gui/elements.h>
#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);
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include <gui/view.h>
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);

View File

@@ -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;

View File

@@ -1,7 +1,7 @@
#include "reset.h"
#include <stdlib.h>
#include <furi/furi.h>
#include <furi/core/string.h>
#include "../../cli_helpers.h"
#include "../../../services/config/config.h"

View File

@@ -27,7 +27,7 @@
#pragma once
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
/**

View File

@@ -22,7 +22,7 @@ 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];
}

View File

@@ -1,3 +1,6 @@
#pragma once
#pragma weak strnlen
#include <stddef.h>
size_t strnlen(const char* s, size_t maxlen);

View File

@@ -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;
}

View File

@@ -1,7 +1,6 @@
#pragma once
#include <flipper_format/flipper_format.h>
#include <furi.h>
#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

View File

@@ -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"

View File

@@ -1,14 +1,15 @@
#include "crypto.h"
#include <furi.h>
#include <furi_hal.h>
#include <furi_hal_crypto.h>
#include <furi_hal_random.h>
#include <furi_hal_version.h>
#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,

View File

@@ -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)

View File

@@ -1,15 +1,13 @@
#include "totp.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <timezone_utils.h>
#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

View File

@@ -1,10 +1,7 @@
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <input/input.h>
#include <dialogs/dialogs.h>
#include <stdlib.h>
#include <flipper_format/flipper_format.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <dolphin/dolphin.h>
@@ -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);

View File

@@ -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

View File

@@ -1,9 +1,7 @@
#include "token_info.h"
#include <furi_hal.h>
#include <base32.h>
#include <base64.h>
#include <memset_s.h>
#include <strnlen.h>
#include "common.h"
#include "../services/crypto/crypto.h"

View File

@@ -2,15 +2,15 @@
#include <inttypes.h>
#include <stdbool.h>
#include <furi/furi.h>
#include <furi/core/string.h>
#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

View File

@@ -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)

View File

@@ -1,4 +1,5 @@
#include "mode_nine.h"
#include <stdint.h>
/* GENERATED BY https://github.com/pavius/the-dot-factory */

View File

@@ -3,7 +3,6 @@
/* GENERATED BY https://github.com/pavius/the-dot-factory */
#include "../font_info.h"
#include <stdint.h>
/* Font data for ModeNine 15pt */
extern const FONT_INFO modeNine_15ptFontInfo;

View File

@@ -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) {

View File

@@ -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

View File

@@ -1,6 +1,5 @@
#include "totp_input_text.h"
#include <gui/view_i.h>
#include "../../../lib/polyfills/strnlen.h"
void view_draw(View* view, Canvas* canvas) {
furi_assert(view);

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -1,8 +1,6 @@
#pragma once
#include <gui/gui.h>
#include <furi.h>
#include <furi_hal.h>
#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);

View File

@@ -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);
}

View File

@@ -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);
@@ -17,4 +16,3 @@ 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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -2,39 +2,44 @@
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <totp_icons.h>
#include <roll_value.h>
#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];
if(ch >= modeNine_15ptFontInfo.startChar && ch <= modeNine_15ptFontInfo.endChar) {
uint8_t char_index = ch - modeNine_15ptFontInfo.startChar;
canvas_draw_xbm(
canvas,
offset_x,
offset_y,
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);
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -2,8 +2,8 @@
#include <totp_icons.h>
#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,

View File

@@ -1,10 +1,11 @@
#include "bt_type_code.h"
#include <furi_hal_bt_hid.h>
#include <furi_hal_version.h>
#include <bt/bt_service/bt_i.h>
#include <storage/storage.h>
#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)) {

View File

@@ -1,47 +1,48 @@
#pragma once
#include <stdlib.h>
#include <furi/furi.h>
#include <furi_hal.h>
#include <furi/core/thread.h>
#include <furi/core/mutex.h>
#include <furi/core/string.h>
#include <furi/core/kernel.h>
#include <bt/bt_service/bt.h>
#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,

View File

@@ -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 <furi_hal_rtc.h>
#include <memset_s.h>
#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;
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include <stdlib.h>
#include <furi/core/thread.h>
#include <furi/core/mutex.h>
#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);

View File

@@ -1,6 +1,6 @@
#include "common.h"
#include <furi/furi.h>
#include <furi_hal.h>
#include "type_code_common.h"
#include <furi_hal_usb_hid.h>
#include <furi/core/kernel.h>
#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;

View File

@@ -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);

View File

@@ -1,7 +1,8 @@
#include "usb_type_code.h"
#include <furi_hal_usb_hid.h>
#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");

View File

@@ -1,17 +1,20 @@
#pragma once
#include <stdlib.h>
#include <furi/furi.h>
#include <furi_hal.h>
#include <furi/core/thread.h>
#include <furi/core/mutex.h>
#include <furi/core/kernel.h>
#include <furi/core/check.h>
#include <furi_hal_usb.h>
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,

View File

@@ -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"));
//}
}

View File

@@ -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 - порт свободен, указатель на интерфейс - порт занят этим интерфейсом

View File

@@ -1,6 +1,7 @@
#include "fap_loader_app.h"
#include <furi.h>
#include <furi_hal_debug.h>
#include <assets_icons.h>
#include <gui/gui.h>
@@ -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 */

View File

@@ -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;

View File

@@ -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) ||

View File

@@ -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);

View File

@@ -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();
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()) {

View File

@@ -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,

View File

@@ -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)) {

View File

@@ -4,8 +4,8 @@
#include <assets_icons.h>
#include <locale/locale.h>
#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,23 +52,22 @@ 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) {
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");
@@ -82,6 +80,9 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
} else {
snprintf(header, sizeof(header), "Charged!");
}
} else {
snprintf(header, sizeof(header), "Napping...");
}
canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote);
canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);

View File

@@ -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(

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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,
1 entry status name type params
2 Version + 20.1 22.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
901 Function + furi_hal_crypto_verify_key _Bool uint8_t
902 Function + furi_hal_debug_disable void
903 Function + furi_hal_debug_enable void
904 Function + furi_hal_debug_is_gdb_session_active _Bool
905 Function - furi_hal_deinit_early void
906 Function - furi_hal_flash_erase void uint8_t
907 Function - furi_hal_flash_get_base size_t
984 Function + furi_hal_os_tick void
985 Function + furi_hal_power_check_otg_status void
986 Function + furi_hal_power_debug_get void PropertyValueCallback, void*
Function + furi_hal_power_deep_sleep_available _Bool
987 Function + furi_hal_power_disable_external_3_3v void
988 Function + furi_hal_power_disable_otg void
989 Function + furi_hal_power_enable_external_3_3v void
1059 Function + furi_hal_rtc_set_log_level void uint8_t
1060 Function + furi_hal_rtc_set_pin_fails void uint32_t
1061 Function + furi_hal_rtc_set_register void FuriHalRtcRegister, uint32_t
1062 Function + furi_hal_rtc_sync_shadow void
1063 Function + furi_hal_rtc_validate_datetime _Bool FuriHalRtcDateTime*
1064 Function + furi_hal_speaker_acquire _Bool uint32_t
1065 Function - furi_hal_speaker_deinit void
2150 Variable + gpio_ext_pe4 const GpioPin
2151 Variable + gpio_i2c_power_scl const GpioPin
2152 Variable + gpio_i2c_power_sda const GpioPin
2153 Variable + gpio_ibutton const GpioPin
2154 Variable + gpio_periph_power const GpioPin
2155 Variable + gpio_pins const GpioPinRecord[]
2156 Variable + gpio_pins_count const size_t
2157 Variable + gpio_sdcard_cd const GpioPin
2160 Variable + gpio_spi_d_miso const GpioPin
2161 Variable + gpio_spi_d_mosi const GpioPin
2162 Variable + gpio_spi_d_sck const GpioPin
2163 Variable + gpio_swclk const GpioPin
2164 Variable + gpio_swdio const GpioPin
2165 Variable + gpio_usart_rx const GpioPin
2166 Variable + gpio_usart_tx const GpioPin
2167 Variable + gpio_usb_dm const GpioPin
2168 Variable + gpio_usb_dp const GpioPin
2169 Variable + ibutton_gpio gpio_vibro const GpioPin
2170 Variable + input_pins const InputPin[]
2171 Variable + input_pins_count const size_t
2172 Variable + message_blink_set_color_blue const NotificationMessage
2314 Variable + message_sound_off const NotificationMessage
2315 Variable + message_vibro_off const NotificationMessage
2316 Variable + message_vibro_on const NotificationMessage
Variable + periph_power const GpioPin
2317 Variable + sequence_audiovisual_alert const NotificationSequence
2318 Variable + sequence_blink_blue_10 const NotificationSequence
2319 Variable + sequence_blink_blue_100 const NotificationSequence
2368 Variable + usb_hid FuriHalUsbInterface
2369 Variable + usb_hid_u2f FuriHalUsbInterface
2370 Variable + usbd_devfs const usbd_driver
Variable + vibro_gpio const GpioPin

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,
1 entry status name type params
2 Version + 20.1 22.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
1106 Function + furi_hal_crypto_verify_key _Bool uint8_t
1107 Function + furi_hal_debug_disable void
1108 Function + furi_hal_debug_enable void
1109 Function + furi_hal_debug_is_gdb_session_active _Bool
1110 Function - furi_hal_deinit_early void
1111 Function - furi_hal_flash_erase void uint8_t
1112 Function - furi_hal_flash_get_base size_t
1239 Function + furi_hal_os_tick void
1240 Function + furi_hal_power_check_otg_status void
1241 Function + furi_hal_power_debug_get void PropertyValueCallback, void*
Function + furi_hal_power_deep_sleep_available _Bool
1242 Function + furi_hal_power_disable_external_3_3v void
1243 Function + furi_hal_power_disable_otg void
1244 Function + furi_hal_power_enable_external_3_3v void
1338 Function + furi_hal_rtc_set_log_level void uint8_t
1339 Function + furi_hal_rtc_set_pin_fails void uint32_t
1340 Function + furi_hal_rtc_set_register void FuriHalRtcRegister, uint32_t
1341 Function + furi_hal_rtc_sync_shadow void
1342 Function + furi_hal_rtc_validate_datetime _Bool FuriHalRtcDateTime*
1343 Function + furi_hal_speaker_acquire _Bool uint32_t
1344 Function - furi_hal_speaker_deinit void
4737 Variable + gpio_ext_pc3 const GpioPin
4738 Variable + gpio_i2c_power_scl const GpioPin
4739 Variable + gpio_i2c_power_sda const GpioPin
4740 Variable + gpio_ibutton const GpioPin
4741 Variable + gpio_infrared_rx const GpioPin
4742 Variable + gpio_infrared_tx const GpioPin
4743 Variable + gpio_nfc_cs const GpioPin
4744 Variable + gpio_nfc_irq_rfid_pull const GpioPin
4745 Variable + gpio_periph_power const GpioPin
4746 Variable + gpio_pins const GpioPinRecord[]
4747 Variable + gpio_pins_count const size_t
4748 Variable + gpio_rf_sw_0 const GpioPin
4763 Variable + gpio_spi_r_sck_ext const GpioPin
4764 Variable + gpio_subghz_cs const GpioPin
4765 Variable + gpio_subghz_cs_ext const GpioPin
4766 Variable + gpio_swclk const GpioPin
4767 Variable + gpio_swdio const GpioPin
4768 Variable + gpio_usart_rx const GpioPin
4769 Variable + gpio_usart_tx const GpioPin
4770 Variable + gpio_usb_dm const GpioPin
4771 Variable + gpio_usb_dp const GpioPin
4772 Variable + ibutton_gpio gpio_vibro const GpioPin
4773 Variable + input_pins const InputPin[]
4774 Variable + input_pins_count const size_t
4775 Variable + lfrfid_protocols const ProtocolBase*[]
4918 Variable + message_sound_off const NotificationMessage
4919 Variable + message_vibro_off const NotificationMessage
4920 Variable + message_vibro_on const NotificationMessage
Variable + periph_power const GpioPin
4921 Variable + sequence_audiovisual_alert const NotificationSequence
4922 Variable + sequence_blink_blue_10 const NotificationSequence
4923 Variable + sequence_blink_blue_100 const NotificationSequence
6924 Variable + usb_hid FuriHalUsbInterface
6925 Variable + usb_hid_u2f FuriHalUsbInterface
6926 Variable + usbd_devfs const usbd_driver
Variable + vibro_gpio const GpioPin

View File

@@ -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

View File

@@ -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);

View File

@@ -3,12 +3,26 @@
#include <stm32wbxx_ll_exti.h>
#include <stm32wbxx_ll_system.h>
#include <furi_hal_gpio.h>
#include <furi_hal_resources.h>
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;
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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 <stm32wbxx_ll_gpio.h>
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

View File

@@ -4,6 +4,8 @@
#include <furi_hal_vibro.h>
#include <furi_hal_resources.h>
#include <furi_hal_uart.h>
#include <furi_hal_rtc.h>
#include <furi_hal_debug.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_pwr.h>
@@ -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() {

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View File

@@ -5,6 +5,7 @@
#include <furi_hal_console.h>
#include <furi_hal_power.h>
#include <furi_hal_rtc.h>
#include <furi_hal_debug.h>
#include <stdio.h>
#include <FreeRTOS.h>
@@ -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);

View File

@@ -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) \
({ \

Some files were not shown because too many files have changed in this diff Show More