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

Merge branch 'dev' into release

This commit is contained in:
MX
2023-04-21 15:59:36 +03:00
94 changed files with 2149 additions and 478 deletions

View File

@@ -1,11 +1,32 @@
### New changes
### New changes
* Note: Due to latest official changes this release was delayed - release was tested by group of users, and some of them reported getting one crash on "furi_check failed", but this can not be reproduced in any way we tried, so, please if you found any issues with BLE (+ Mobile app) that results in crash, create issue with all details how you got it and how many times, and detailed steps on repeating such issue, if you got one crash and can't get it again, collect information how it happened and create issue with as much details as possible -> Thanks!
* SubGHz: New option to use timestamps + protocol name when you saving file, instead of random name - Enable in `Radio Settings -> Time in names = ON`
* SubGHz: Read mode UI improvements (scrolling text, + shows time when signal was received) (by @wosk | PR #429)
* SubGHz: New options to ignore Magellan, Cars(ScherKhan, Kia)(no you can't send that signals)
* SubGHz: Fix keeloq custom buttons bugs
* SubGhz: Nero Radio 57bit **experimental** support + encoder improvements and decoder changes
* SubGhz: Fix RAW recording and reading, (bug where raw file plays endlessly) (Fixes issue #431)
* SubGHz Remote: Add Alutech AT4N Support, fix some issues
* Power GUI: Changing battery style doesnt require reboot (Added API to trigger UI change from different place) (Inspired by @ESurge work)
* Plugins: BLE Remote -> Keynote with vertical layout (by @Kami-no | PR #428)
* Plugins: Improve wifi marauder keyboard (added extra symbols!) (Port uart terminal keyboard into wifi marauder)
* Infrared: Update universal remote assets (by @amec0e | PR #421)
* Docs: Update build docs (by @PhoenixSheppy | PR #425)
* OFW: cubewb: updated to v1.16.0 -> **Part 2 of "Various stop mode fixes"**
* OFW: github: testing SDK with ufbt action
* OFW: Raw RFID documentation
* OFW: Introduce stealth mode and auto-selective lock
* OFW: Active RPC session icon -> **Breaking API change, api was changed from 22.x to 23.x**
* OFW: Various stop mode fixes -> **Should fix known issues with BLE (Random freezes, menu freeze, BT Remote plugin freeze) and other similar issues**
* OFW: Picopass: Correctly aborts when correct key is found -> Fixes Bug (Picopass app not reading elite keyed cards anymore. #413)
### Pre-release changes
* 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: Bluetooth Remote - improvements and fixes for TikTok remote (by @krolchonok | PR #420 and #432)
* 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)

View File

@@ -54,6 +54,8 @@ Our Discord Community:
- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107)
* Sub-GHz -> Short press OK in frequency analyzer to save detected frequency for usage in Read modes
* Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu and automatically use selected frequency
* SubGHz -> New option to use timestamps + protocol name when you saving file, instead of random name - Enable in `Radio Settings -> Time in names = ON`
* SubGHz -> Read mode UI improvements (scrolling text, + shows time when signal was received) (by @wosk)
* Sub-GHz -> External CC1101 module support (Hardware SPI used)
* SubGHz -> **Hold right in received signal list to delete selected signal**
* SubGHz -> **Custom buttons for Keeloq / Alutech AT4N / Nice Flor S / Somfy Telis / Security+ 2.0** - now you can use arrow buttons to send signal with different button code
@@ -72,6 +74,7 @@ Thanks to Official team (to their SubGHz Developer, Skorp) for implementing deco
Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b)
Encoders or sending made by @xMasterX:
- Nero Radio 57bit (experimental) (+ 56bit encoder improvements)
- Keeloq: HCS101
- Keeloq: AN-Motors
- Keeloq: JCM Tech

View File

@@ -84,7 +84,7 @@ static void test_rpc_setup(void) {
rpc = furi_record_open(RECORD_RPC);
for(int i = 0; !(rpc_session[0].session) && (i < 10000); ++i) {
rpc_session[0].session = rpc_session_open(rpc);
rpc_session[0].session = rpc_session_open(rpc, RpcOwnerUnknown);
furi_delay_tick(1);
}
furi_check(rpc_session[0].session);
@@ -104,7 +104,7 @@ static void test_rpc_setup_second_session(void) {
furi_check(!(rpc_session[1].session));
for(int i = 0; !(rpc_session[1].session) && (i < 10000); ++i) {
rpc_session[1].session = rpc_session_open(rpc);
rpc_session[1].session = rpc_session_open(rpc, RpcOwnerUnknown);
furi_delay_tick(1);
}
furi_check(rpc_session[1].session);

View File

@@ -7,6 +7,7 @@
enum HidDebugSubmenuIndex {
HidSubmenuIndexKeynote,
HidSubmenuIndexKeynoteVertical,
HidSubmenuIndexKeyboard,
HidSubmenuIndexMedia,
HidSubmenuIndexTikTok,
@@ -21,6 +22,9 @@ static void hid_submenu_callback(void* context, uint32_t index) {
if(index == HidSubmenuIndexKeynote) {
app->view_id = HidViewKeynote;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeynote);
} else if(index == HidSubmenuIndexKeynoteVertical) {
app->view_id = HidViewKeynoteVertical;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeynoteVertical);
} else if(index == HidSubmenuIndexKeyboard) {
app->view_id = HidViewKeyboard;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeyboard);
@@ -54,6 +58,7 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con
}
}
hid_keynote_set_connected_status(hid->hid_keynote, connected);
hid_keynote_vertical_set_connected_status(hid->hid_keynote_vertical, connected);
hid_keyboard_set_connected_status(hid->hid_keyboard, connected);
hid_media_set_connected_status(hid->hid_media, connected);
hid_mouse_set_connected_status(hid->hid_mouse, connected);
@@ -105,6 +110,12 @@ Hid* hid_alloc(HidTransport transport) {
app->device_type_submenu = submenu_alloc();
submenu_add_item(
app->device_type_submenu, "Keynote", HidSubmenuIndexKeynote, hid_submenu_callback, app);
submenu_add_item(
app->device_type_submenu,
"Keynote Vertical",
HidSubmenuIndexKeynoteVertical,
hid_submenu_callback,
app);
submenu_add_item(
app->device_type_submenu, "Keyboard", HidSubmenuIndexKeyboard, hid_submenu_callback, app);
submenu_add_item(
@@ -120,7 +131,7 @@ Hid* hid_alloc(HidTransport transport) {
app);
submenu_add_item(
app->device_type_submenu,
"YT Shorts Controller",
"[Beta]YT Shorts Controller",
HidSubmenuIndexYTShorts,
hid_submenu_callback,
app);
@@ -159,6 +170,15 @@ Hid* hid_app_alloc_view(void* context) {
view_dispatcher_add_view(
app->view_dispatcher, HidViewKeynote, hid_keynote_get_view(app->hid_keynote));
// Keynote Vertical view
app->hid_keynote_vertical = hid_keynote_vertical_alloc(app);
view_set_previous_callback(
hid_keynote_vertical_get_view(app->hid_keynote_vertical), hid_exit_confirm_view);
view_dispatcher_add_view(
app->view_dispatcher,
HidViewKeynoteVertical,
hid_keynote_vertical_get_view(app->hid_keynote_vertical));
// Keyboard view
app->hid_keyboard = hid_keyboard_alloc(app);
view_set_previous_callback(hid_keyboard_get_view(app->hid_keyboard), hid_exit_confirm_view);
@@ -216,6 +236,8 @@ void hid_free(Hid* app) {
dialog_ex_free(app->dialog);
view_dispatcher_remove_view(app->view_dispatcher, HidViewKeynote);
hid_keynote_free(app->hid_keynote);
view_dispatcher_remove_view(app->view_dispatcher, HidViewKeynoteVertical);
hid_keynote_vertical_free(app->hid_keynote_vertical);
view_dispatcher_remove_view(app->view_dispatcher, HidViewKeyboard);
hid_keyboard_free(app->hid_keyboard);
view_dispatcher_remove_view(app->view_dispatcher, HidViewMedia);

View File

@@ -17,6 +17,7 @@
#include <gui/modules/dialog_ex.h>
#include <gui/modules/popup.h>
#include "views/hid_keynote.h"
#include "views/hid_keynote_vertical.h"
#include "views/hid_keyboard.h"
#include "views/hid_media.h"
#include "views/hid_mouse.h"
@@ -41,6 +42,7 @@ struct Hid {
Submenu* device_type_submenu;
DialogEx* dialog;
HidKeynote* hid_keynote;
HidKeynoteVertical* hid_keynote_vertical;
HidKeyboard* hid_keyboard;
HidMedia* hid_media;
HidMouse* hid_mouse;
@@ -64,4 +66,4 @@ void hid_hal_mouse_move(Hid* instance, int8_t dx, int8_t dy);
void hid_hal_mouse_scroll(Hid* instance, int8_t delta);
void hid_hal_mouse_press(Hid* instance, uint16_t event);
void hid_hal_mouse_release(Hid* instance, uint16_t event);
void hid_hal_mouse_release_all(Hid* instance);
void hid_hal_mouse_release_all(Hid* instance);

View File

@@ -1,6 +1,7 @@
typedef enum {
HidViewSubmenu,
HidViewKeynote,
HidViewKeynoteVertical,
HidViewKeyboard,
HidViewMedia,
HidViewMouse,
@@ -8,4 +9,4 @@ typedef enum {
BtHidViewTikTok,
BtHidViewYTShorts,
HidViewExitConfirm,
} HidView;
} HidView;

View File

@@ -0,0 +1,228 @@
#include "hid_keynote_vertical.h"
#include <gui/elements.h>
#include "../hid.h"
#include "hid_icons.h"
#define TAG "HidKeynoteVertical"
struct HidKeynoteVertical {
View* view;
Hid* hid;
};
typedef struct {
bool left_pressed;
bool up_pressed;
bool right_pressed;
bool down_pressed;
bool ok_pressed;
bool back_pressed;
bool connected;
HidTransport transport;
} HidKeynoteVerticalModel;
static void
hid_keynote_vertical_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) {
canvas_draw_triangle(canvas, x, y, 5, 3, dir);
if(dir == CanvasDirectionBottomToTop) {
canvas_draw_line(canvas, x, y + 6, x, y - 1);
} else if(dir == CanvasDirectionTopToBottom) {
canvas_draw_line(canvas, x, y - 6, x, y + 1);
} else if(dir == CanvasDirectionRightToLeft) {
canvas_draw_line(canvas, x + 6, y, x - 1, y);
} else if(dir == CanvasDirectionLeftToRight) {
canvas_draw_line(canvas, x - 6, y, x + 1, y);
}
}
static void hid_keynote_vertical_draw_callback(Canvas* canvas, void* context) {
furi_assert(context);
HidKeynoteVerticalModel* 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, "Keynote");
canvas_set_font(canvas, FontSecondary);
elements_multiline_text_aligned(
canvas, 24, 14, AlignLeft, AlignTop, "Vertical Up --->");
canvas_draw_icon(canvas, 68, 2, &I_Pin_back_arrow_10x8);
canvas_set_font(canvas, FontSecondary);
elements_multiline_text_aligned(canvas, 127, 3, AlignRight, AlignTop, "Hold to exit");
// Up
canvas_draw_icon(canvas, 21, 24, &I_Button_18x18);
if(model->up_pressed) {
elements_slightly_rounded_box(canvas, 24, 26, 13, 13);
canvas_set_color(canvas, ColorWhite);
}
hid_keynote_vertical_draw_arrow(canvas, 30, 30, CanvasDirectionBottomToTop);
canvas_set_color(canvas, ColorBlack);
// Down
canvas_draw_icon(canvas, 21, 45, &I_Button_18x18);
if(model->down_pressed) {
elements_slightly_rounded_box(canvas, 24, 47, 13, 13);
canvas_set_color(canvas, ColorWhite);
}
hid_keynote_vertical_draw_arrow(canvas, 30, 55, CanvasDirectionTopToBottom);
canvas_set_color(canvas, ColorBlack);
// Left
canvas_draw_icon(canvas, 0, 35, &I_Button_18x18);
if(model->left_pressed) {
elements_slightly_rounded_box(canvas, 3, 37, 13, 13);
canvas_set_color(canvas, ColorWhite);
}
hid_keynote_vertical_draw_arrow(canvas, 7, 43, CanvasDirectionRightToLeft);
canvas_set_color(canvas, ColorBlack);
// Right
canvas_draw_icon(canvas, 42, 35, &I_Button_18x18);
if(model->right_pressed) {
elements_slightly_rounded_box(canvas, 45, 37, 13, 13);
canvas_set_color(canvas, ColorWhite);
}
hid_keynote_vertical_draw_arrow(canvas, 53, 43, CanvasDirectionLeftToRight);
canvas_set_color(canvas, ColorBlack);
// Ok
canvas_draw_icon(canvas, 63, 25, &I_Space_65x18);
if(model->ok_pressed) {
elements_slightly_rounded_box(canvas, 66, 27, 60, 13);
canvas_set_color(canvas, ColorWhite);
}
canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9);
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Space");
canvas_set_color(canvas, ColorBlack);
// Back
canvas_draw_icon(canvas, 63, 45, &I_Space_65x18);
if(model->back_pressed) {
elements_slightly_rounded_box(canvas, 66, 47, 60, 13);
canvas_set_color(canvas, ColorWhite);
}
canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8);
elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Back");
}
static void
hid_keynote_vertical_process(HidKeynoteVertical* hid_keynote_vertical, InputEvent* event) {
with_view_model(
hid_keynote_vertical->view,
HidKeynoteVerticalModel * model,
{
if(event->type == InputTypePress) {
if(event->key == InputKeyUp) {
model->up_pressed = true;
hid_hal_keyboard_press(hid_keynote_vertical->hid, HID_KEYBOARD_LEFT_ARROW);
} else if(event->key == InputKeyDown) {
model->down_pressed = true;
hid_hal_keyboard_press(hid_keynote_vertical->hid, HID_KEYBOARD_RIGHT_ARROW);
} else if(event->key == InputKeyLeft) {
model->left_pressed = true;
hid_hal_keyboard_press(hid_keynote_vertical->hid, HID_KEYBOARD_DOWN_ARROW);
} else if(event->key == InputKeyRight) {
model->right_pressed = true;
hid_hal_keyboard_press(hid_keynote_vertical->hid, HID_KEYBOARD_UP_ARROW);
} else if(event->key == InputKeyOk) {
model->ok_pressed = true;
hid_hal_keyboard_press(hid_keynote_vertical->hid, HID_KEYBOARD_SPACEBAR);
} else if(event->key == InputKeyBack) {
model->back_pressed = true;
}
} else if(event->type == InputTypeRelease) {
if(event->key == InputKeyUp) {
model->up_pressed = false;
hid_hal_keyboard_release(hid_keynote_vertical->hid, HID_KEYBOARD_LEFT_ARROW);
} else if(event->key == InputKeyDown) {
model->down_pressed = false;
hid_hal_keyboard_release(hid_keynote_vertical->hid, HID_KEYBOARD_RIGHT_ARROW);
} else if(event->key == InputKeyLeft) {
model->left_pressed = false;
hid_hal_keyboard_release(hid_keynote_vertical->hid, HID_KEYBOARD_DOWN_ARROW);
} else if(event->key == InputKeyRight) {
model->right_pressed = false;
hid_hal_keyboard_release(hid_keynote_vertical->hid, HID_KEYBOARD_UP_ARROW);
} else if(event->key == InputKeyOk) {
model->ok_pressed = false;
hid_hal_keyboard_release(hid_keynote_vertical->hid, HID_KEYBOARD_SPACEBAR);
} else if(event->key == InputKeyBack) {
model->back_pressed = false;
}
} else if(event->type == InputTypeShort) {
if(event->key == InputKeyBack) {
hid_hal_keyboard_press(hid_keynote_vertical->hid, HID_KEYBOARD_DELETE);
hid_hal_keyboard_release(hid_keynote_vertical->hid, HID_KEYBOARD_DELETE);
hid_hal_consumer_key_press(hid_keynote_vertical->hid, HID_CONSUMER_AC_BACK);
hid_hal_consumer_key_release(hid_keynote_vertical->hid, HID_CONSUMER_AC_BACK);
}
}
},
true);
}
static bool hid_keynote_vertical_input_callback(InputEvent* event, void* context) {
furi_assert(context);
HidKeynoteVertical* hid_keynote_vertical = context;
bool consumed = false;
if(event->type == InputTypeLong && event->key == InputKeyBack) {
hid_hal_keyboard_release_all(hid_keynote_vertical->hid);
} else {
hid_keynote_vertical_process(hid_keynote_vertical, event);
consumed = true;
}
return consumed;
}
HidKeynoteVertical* hid_keynote_vertical_alloc(Hid* hid) {
HidKeynoteVertical* hid_keynote_vertical = malloc(sizeof(HidKeynoteVertical));
hid_keynote_vertical->view = view_alloc();
hid_keynote_vertical->hid = hid;
view_set_context(hid_keynote_vertical->view, hid_keynote_vertical);
view_allocate_model(
hid_keynote_vertical->view, ViewModelTypeLocking, sizeof(HidKeynoteVerticalModel));
view_set_draw_callback(hid_keynote_vertical->view, hid_keynote_vertical_draw_callback);
view_set_input_callback(hid_keynote_vertical->view, hid_keynote_vertical_input_callback);
with_view_model(
hid_keynote_vertical->view,
HidKeynoteVerticalModel * model,
{ model->transport = hid->transport; },
true);
return hid_keynote_vertical;
}
void hid_keynote_vertical_free(HidKeynoteVertical* hid_keynote_vertical) {
furi_assert(hid_keynote_vertical);
view_free(hid_keynote_vertical->view);
free(hid_keynote_vertical);
}
View* hid_keynote_vertical_get_view(HidKeynoteVertical* hid_keynote_vertical) {
furi_assert(hid_keynote_vertical);
return hid_keynote_vertical->view;
}
void hid_keynote_vertical_set_connected_status(
HidKeynoteVertical* hid_keynote_vertical,
bool connected) {
furi_assert(hid_keynote_vertical);
with_view_model(
hid_keynote_vertical->view,
HidKeynoteVerticalModel * model,
{ model->connected = connected; },
true);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <gui/view.h>
typedef struct Hid Hid;
typedef struct HidKeynoteVertical HidKeynoteVertical;
HidKeynoteVertical* hid_keynote_vertical_alloc(Hid* bt_hid);
void hid_keynote_vertical_free(HidKeynoteVertical* hid_keynote_vertical);
View* hid_keynote_vertical_get_view(HidKeynoteVertical* hid_keynote_vertical);
void hid_keynote_vertical_set_connected_status(
HidKeynoteVertical* hid_keynote_vertical,
bool connected);

View File

@@ -178,32 +178,25 @@ static bool hid_tiktok_input_callback(InputEvent* event, void* context) {
} else if(event->type == InputTypeShort) {
if(event->key == InputKeyOk) {
hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
furi_delay_ms(50);
furi_delay_ms(25);
hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
furi_delay_ms(50);
furi_delay_ms(100);
hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
furi_delay_ms(50);
furi_delay_ms(25);
hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
consumed = true;
} else if(event->key == InputKeyDown) {
// 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) {
// Pause
hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_RIGHT);
furi_delay_ms(25);
hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_RIGHT);
consumed = true;
}

View File

@@ -570,7 +570,7 @@ void picopass_worker_elite_dict_attack(PicopassWorker* picopass_worker) {
picopass_worker->callback(PicopassWorkerEventFail, picopass_worker->context);
break;
}
picopass_worker->callback(PicopassWorkerEventSuccess, picopass_worker->context);
picopass_worker->callback(PicopassWorkerEventAborted, picopass_worker->context);
break;
}
@@ -596,6 +596,9 @@ int32_t picopass_worker_task(void* context) {
picopass_worker_write_key(picopass_worker);
} else if(picopass_worker->state == PicopassWorkerStateEliteDictAttack) {
picopass_worker_elite_dict_attack(picopass_worker);
} else if(picopass_worker->state == PicopassWorkerStateStop) {
FURI_LOG_D(TAG, "Worker state stop");
// no-op
} else {
FURI_LOG_W(TAG, "Unknown state %d", picopass_worker->state);
}

View File

@@ -116,8 +116,7 @@ bool picopass_scene_elite_dict_attack_on_event(void* context, SceneManagerEvent
uint32_t state =
scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneEliteDictAttack);
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == PicopassWorkerEventSuccess ||
event.event == PicopassWorkerEventAborted) {
if(event.event == PicopassWorkerEventSuccess) {
if(state == DictAttackStateUserDictInProgress ||
state == DictAttackStateStandardDictInProgress) {
picopass_worker_stop(picopass->worker);
@@ -127,6 +126,9 @@ bool picopass_scene_elite_dict_attack_on_event(void* context, SceneManagerEvent
scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess);
consumed = true;
}
} else if(event.event == PicopassWorkerEventAborted) {
scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess);
consumed = true;
} else if(event.event == PicopassWorkerEventCardDetected) {
dict_attack_set_card_detected(picopass->dict_attack);
consumed = true;

View File

@@ -8,4 +8,5 @@ App(
order=90,
fap_icon="wifi_10px.png",
fap_category="GPIO",
fap_icon_assets="assets",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -44,24 +44,24 @@ void wifi_marauder_scene_text_input_on_enter(void* context) {
}
// Setup view
TextInput* text_input = app->text_input;
WIFI_TextInput* text_input = app->text_input;
// Add help message to header
if(app->special_case_input_step == 1) {
text_input_set_header_text(text_input, "Enter source MAC");
wifi_text_input_set_header_text(text_input, "Enter source MAC");
} else if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) {
text_input_set_header_text(text_input, "Enter # SSIDs to generate");
wifi_text_input_set_header_text(text_input, "Enter # SSIDs to generate");
} else if(0 == strncmp("ssid -a -n", app->selected_tx_string, strlen("ssid -a -n"))) {
text_input_set_header_text(text_input, "Enter SSID name to add");
wifi_text_input_set_header_text(text_input, "Enter SSID name to add");
} else if(0 == strncmp("ssid -r", app->selected_tx_string, strlen("ssid -r"))) {
text_input_set_header_text(text_input, "Remove target from SSID list");
wifi_text_input_set_header_text(text_input, "Remove target from SSID list");
} else if(0 == strncmp("select -a", app->selected_tx_string, strlen("select -a"))) {
text_input_set_header_text(text_input, "Add target from AP list");
wifi_text_input_set_header_text(text_input, "Add target from AP list");
} else if(0 == strncmp("select -s", app->selected_tx_string, strlen("select -s"))) {
text_input_set_header_text(text_input, "Add target from SSID list");
wifi_text_input_set_header_text(text_input, "Add target from SSID list");
} else {
text_input_set_header_text(text_input, "Add command arguments");
wifi_text_input_set_header_text(text_input, "Add command arguments");
}
text_input_set_result_callback(
wifi_text_input_set_result_callback(
text_input,
wifi_marauder_scene_text_input_callback,
app,
@@ -84,7 +84,7 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev
consumed = true;
} else if(event.event == WifiMarauderEventSaveSourceMac) {
if(12 != strlen(app->text_input_store)) {
text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!");
wifi_text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!");
} else {
snprintf(
app->special_case_input_src_addr,
@@ -106,12 +106,12 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev
// Advance scene to input destination MAC, clear text input
app->special_case_input_step = 2;
bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE);
text_input_set_header_text(app->text_input, "Enter destination MAC");
wifi_text_input_set_header_text(app->text_input, "Enter destination MAC");
}
consumed = true;
} else if(event.event == WifiMarauderEventSaveDestinationMac) {
if(12 != strlen(app->text_input_store)) {
text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!");
wifi_text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!");
} else {
snprintf(
app->special_case_input_dst_addr,
@@ -150,5 +150,5 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev
void wifi_marauder_scene_text_input_on_exit(void* context) {
WifiMarauderApp* app = context;
text_input_reset(app->text_input);
wifi_text_input_reset(app->text_input);
}

View File

@@ -64,9 +64,11 @@ WifiMarauderApp* wifi_marauder_app_alloc() {
app->text_box_store = furi_string_alloc();
furi_string_reserve(app->text_box_store, WIFI_MARAUDER_TEXT_BOX_STORE_SIZE);
app->text_input = text_input_alloc();
app->text_input = wifi_text_input_alloc();
view_dispatcher_add_view(
app->view_dispatcher, WifiMarauderAppViewTextInput, text_input_get_view(app->text_input));
app->view_dispatcher,
WifiMarauderAppViewTextInput,
wifi_text_input_get_view(app->text_input));
app->widget = widget_alloc();
view_dispatcher_add_view(
@@ -135,7 +137,7 @@ void wifi_marauder_app_free(WifiMarauderApp* app) {
widget_free(app->widget);
text_box_free(app->text_box);
furi_string_free(app->text_box_store);
text_input_free(app->text_input);
wifi_text_input_free(app->text_input);
storage_file_free(app->capture_file);
storage_file_free(app->log_file);
storage_file_free(app->save_pcap_setting_file);

View File

@@ -12,9 +12,9 @@
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <gui/modules/text_box.h>
#include <gui/modules/text_input.h>
#include <gui/modules/variable_item_list.h>
#include <gui/modules/widget.h>
#include "wifi_marauder_text_input.h"
#include <storage/storage.h>
#include <dialogs/dialogs.h>
@@ -42,7 +42,7 @@ struct WifiMarauderApp {
FuriString* text_box_store;
size_t text_box_store_strlen;
TextBox* text_box;
TextInput* text_input;
WIFI_TextInput* text_input;
Storage* storage;
File* capture_file;
File* log_file;

View File

@@ -0,0 +1,625 @@
#include "wifi_marauder_text_input.h"
#include <gui/elements.h>
#include "ESP32_WiFi_Marauder_icons.h"
#include "wifi_marauder_app_i.h"
#include <furi.h>
struct WIFI_TextInput {
View* view;
FuriTimer* timer;
};
typedef struct {
const char text;
const uint8_t x;
const uint8_t y;
} WIFI_TextInputKey;
typedef struct {
const char* header;
char* text_buffer;
size_t text_buffer_size;
bool clear_default_text;
WIFI_TextInputCallback callback;
void* callback_context;
uint8_t selected_row;
uint8_t selected_column;
WIFI_TextInputValidatorCallback validator_callback;
void* validator_callback_context;
FuriString* validator_text;
bool valadator_message_visible;
} WIFI_TextInputModel;
static const uint8_t keyboard_origin_x = 1;
static const uint8_t keyboard_origin_y = 29;
static const uint8_t keyboard_row_count = 4;
#define ENTER_KEY '\r'
#define BACKSPACE_KEY '\b'
static const WIFI_TextInputKey keyboard_keys_row_1[] = {
{'{', 1, 0},
{'(', 9, 0},
{'[', 17, 0},
{'|', 25, 0},
{'@', 33, 0},
{'&', 41, 0},
{'#', 49, 0},
{';', 57, 0},
{'^', 65, 0},
{'*', 73, 0},
{'`', 81, 0},
{'"', 89, 0},
{'~', 97, 0},
{'\'', 105, 0},
{'.', 113, 0},
{'/', 120, 0},
};
static const WIFI_TextInputKey keyboard_keys_row_2[] = {
{'q', 1, 10},
{'w', 9, 10},
{'e', 17, 10},
{'r', 25, 10},
{'t', 33, 10},
{'y', 41, 10},
{'u', 49, 10},
{'i', 57, 10},
{'o', 65, 10},
{'p', 73, 10},
{'0', 81, 10},
{'1', 89, 10},
{'2', 97, 10},
{'3', 105, 10},
{'=', 113, 10},
{'-', 120, 10},
};
static const WIFI_TextInputKey keyboard_keys_row_3[] = {
{'a', 1, 21},
{'s', 9, 21},
{'d', 18, 21},
{'f', 25, 21},
{'g', 33, 21},
{'h', 41, 21},
{'j', 49, 21},
{'k', 57, 21},
{'l', 65, 21},
{BACKSPACE_KEY, 72, 13},
{'4', 89, 21},
{'5', 97, 21},
{'6', 105, 21},
{'$', 113, 21},
{'%', 120, 21},
};
static const WIFI_TextInputKey keyboard_keys_row_4[] = {
{'z', 1, 33},
{'x', 9, 33},
{'c', 18, 33},
{'v', 25, 33},
{'b', 33, 33},
{'n', 41, 33},
{'m', 49, 33},
{'_', 57, 33},
{ENTER_KEY, 64, 24},
{'7', 89, 33},
{'8', 97, 33},
{'9', 105, 33},
{'!', 113, 33},
{'+', 120, 33},
};
static uint8_t get_row_size(uint8_t row_index) {
uint8_t row_size = 0;
switch(row_index + 1) {
case 1:
row_size = sizeof(keyboard_keys_row_1) / sizeof(WIFI_TextInputKey);
break;
case 2:
row_size = sizeof(keyboard_keys_row_2) / sizeof(WIFI_TextInputKey);
break;
case 3:
row_size = sizeof(keyboard_keys_row_3) / sizeof(WIFI_TextInputKey);
break;
case 4:
row_size = sizeof(keyboard_keys_row_4) / sizeof(WIFI_TextInputKey);
break;
}
return row_size;
}
static const WIFI_TextInputKey* get_row(uint8_t row_index) {
const WIFI_TextInputKey* row = NULL;
switch(row_index + 1) {
case 1:
row = keyboard_keys_row_1;
break;
case 2:
row = keyboard_keys_row_2;
break;
case 3:
row = keyboard_keys_row_3;
break;
case 4:
row = keyboard_keys_row_4;
break;
}
return row;
}
static char get_selected_char(WIFI_TextInputModel* model) {
return get_row(model->selected_row)[model->selected_column].text;
}
static bool char_is_lowercase(char letter) {
return (letter >= 0x61 && letter <= 0x7A);
}
static char char_to_uppercase(const char letter) {
switch(letter) {
case '_':
return 0x20;
break;
case '(':
return 0x29;
break;
case '{':
return 0x7d;
break;
case '[':
return 0x5d;
break;
case '/':
return 0x5c;
break;
case ';':
return 0x3a;
break;
case '.':
return 0x2c;
break;
case '!':
return 0x3f;
break;
case '<':
return 0x3e;
break;
}
if(char_is_lowercase(letter)) {
return (letter - 0x20);
} else {
return letter;
}
}
static void wifi_text_input_backspace_cb(WIFI_TextInputModel* model) {
uint8_t text_length = model->clear_default_text ? 1 : strlen(model->text_buffer);
if(text_length > 0) {
model->text_buffer[text_length - 1] = 0;
}
}
static void wifi_text_input_view_draw_callback(Canvas* canvas, void* _model) {
WIFI_TextInputModel* model = _model;
//uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
uint8_t needed_string_width = canvas_width(canvas) - 8;
uint8_t start_pos = 4;
const char* text = model->text_buffer;
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_draw_str(canvas, 2, 7, model->header);
elements_slightly_rounded_frame(canvas, 1, 8, 126, 12);
if(canvas_string_width(canvas, text) > needed_string_width) {
canvas_draw_str(canvas, start_pos, 17, "...");
start_pos += 6;
needed_string_width -= 8;
}
while(text != 0 && canvas_string_width(canvas, text) > needed_string_width) {
text++;
}
if(model->clear_default_text) {
elements_slightly_rounded_box(
canvas, start_pos - 1, 14, canvas_string_width(canvas, text) + 2, 10);
canvas_set_color(canvas, ColorWhite);
} else {
canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 1, 18, "|");
canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 2, 18, "|");
}
canvas_draw_str(canvas, start_pos, 17, text);
canvas_set_font(canvas, FontKeyboard);
for(uint8_t row = 0; row <= keyboard_row_count; row++) {
const uint8_t column_count = get_row_size(row);
const WIFI_TextInputKey* keys = get_row(row);
for(size_t column = 0; column < column_count; column++) {
if(keys[column].text == ENTER_KEY) {
canvas_set_color(canvas, ColorBlack);
if(model->selected_row == row && model->selected_column == column) {
canvas_draw_icon(
canvas,
keyboard_origin_x + keys[column].x,
keyboard_origin_y + keys[column].y,
&I_KeySaveSelected_24x11);
} else {
canvas_draw_icon(
canvas,
keyboard_origin_x + keys[column].x,
keyboard_origin_y + keys[column].y,
&I_KeySave_24x11);
}
} else if(keys[column].text == BACKSPACE_KEY) {
canvas_set_color(canvas, ColorBlack);
if(model->selected_row == row && model->selected_column == column) {
canvas_draw_icon(
canvas,
keyboard_origin_x + keys[column].x,
keyboard_origin_y + keys[column].y,
&I_KeyBackspaceSelected_16x9);
} else {
canvas_draw_icon(
canvas,
keyboard_origin_x + keys[column].x,
keyboard_origin_y + keys[column].y,
&I_KeyBackspace_16x9);
}
} else {
if(model->selected_row == row && model->selected_column == column) {
canvas_set_color(canvas, ColorBlack);
canvas_draw_box(
canvas,
keyboard_origin_x + keys[column].x - 1,
keyboard_origin_y + keys[column].y - 8,
7,
10);
canvas_set_color(canvas, ColorWhite);
} else {
canvas_set_color(canvas, ColorBlack);
}
canvas_draw_glyph(
canvas,
keyboard_origin_x + keys[column].x,
keyboard_origin_y + keys[column].y,
keys[column].text);
}
}
}
if(model->valadator_message_visible) {
canvas_set_font(canvas, FontSecondary);
canvas_set_color(canvas, ColorWhite);
canvas_draw_box(canvas, 8, 10, 110, 48);
canvas_set_color(canvas, ColorBlack);
canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42);
canvas_draw_rframe(canvas, 8, 8, 112, 50, 3);
canvas_draw_rframe(canvas, 9, 9, 110, 48, 2);
elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text));
canvas_set_font(canvas, FontKeyboard);
}
}
static void
wifi_text_input_handle_up(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) {
UNUSED(wifi_text_input);
if(model->selected_row > 0) {
model->selected_row--;
if(model->selected_column > get_row_size(model->selected_row) - 6) {
model->selected_column = model->selected_column + 1;
}
}
}
static void
wifi_text_input_handle_down(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) {
UNUSED(wifi_text_input);
if(model->selected_row < keyboard_row_count - 1) {
model->selected_row++;
if(model->selected_column > get_row_size(model->selected_row) - 4) {
model->selected_column = model->selected_column - 1;
}
}
}
static void
wifi_text_input_handle_left(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) {
UNUSED(wifi_text_input);
if(model->selected_column > 0) {
model->selected_column--;
} else {
model->selected_column = get_row_size(model->selected_row) - 1;
}
}
static void
wifi_text_input_handle_right(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) {
UNUSED(wifi_text_input);
if(model->selected_column < get_row_size(model->selected_row) - 1) {
model->selected_column++;
} else {
model->selected_column = 0;
}
}
static void wifi_text_input_handle_ok(
WIFI_TextInput* wifi_text_input,
WIFI_TextInputModel* model,
bool shift) {
char selected = get_selected_char(model);
uint8_t text_length = strlen(model->text_buffer);
if(shift) {
selected = char_to_uppercase(selected);
}
if(selected == ENTER_KEY) {
if(model->validator_callback &&
(!model->validator_callback(
model->text_buffer, model->validator_text, model->validator_callback_context))) {
model->valadator_message_visible = true;
furi_timer_start(wifi_text_input->timer, furi_kernel_get_tick_frequency() * 4);
} else if(model->callback != 0 && text_length > 0) {
model->callback(model->callback_context);
}
} else if(selected == BACKSPACE_KEY) {
wifi_text_input_backspace_cb(model);
} else {
if(model->clear_default_text) {
text_length = 0;
}
if(text_length < (model->text_buffer_size - 1)) {
model->text_buffer[text_length] = selected;
model->text_buffer[text_length + 1] = 0;
}
}
model->clear_default_text = false;
}
static bool wifi_text_input_view_input_callback(InputEvent* event, void* context) {
WIFI_TextInput* wifi_text_input = context;
furi_assert(wifi_text_input);
bool consumed = false;
// Acquire model
WIFI_TextInputModel* model = view_get_model(wifi_text_input->view);
if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) &&
model->valadator_message_visible) {
model->valadator_message_visible = false;
consumed = true;
} else if(event->type == InputTypeShort) {
consumed = true;
switch(event->key) {
case InputKeyUp:
wifi_text_input_handle_up(wifi_text_input, model);
break;
case InputKeyDown:
wifi_text_input_handle_down(wifi_text_input, model);
break;
case InputKeyLeft:
wifi_text_input_handle_left(wifi_text_input, model);
break;
case InputKeyRight:
wifi_text_input_handle_right(wifi_text_input, model);
break;
case InputKeyOk:
wifi_text_input_handle_ok(wifi_text_input, model, false);
break;
default:
consumed = false;
break;
}
} else if(event->type == InputTypeLong) {
consumed = true;
switch(event->key) {
case InputKeyUp:
wifi_text_input_handle_up(wifi_text_input, model);
break;
case InputKeyDown:
wifi_text_input_handle_down(wifi_text_input, model);
break;
case InputKeyLeft:
wifi_text_input_handle_left(wifi_text_input, model);
break;
case InputKeyRight:
wifi_text_input_handle_right(wifi_text_input, model);
break;
case InputKeyOk:
wifi_text_input_handle_ok(wifi_text_input, model, true);
break;
case InputKeyBack:
wifi_text_input_backspace_cb(model);
break;
default:
consumed = false;
break;
}
} else if(event->type == InputTypeRepeat) {
consumed = true;
switch(event->key) {
case InputKeyUp:
wifi_text_input_handle_up(wifi_text_input, model);
break;
case InputKeyDown:
wifi_text_input_handle_down(wifi_text_input, model);
break;
case InputKeyLeft:
wifi_text_input_handle_left(wifi_text_input, model);
break;
case InputKeyRight:
wifi_text_input_handle_right(wifi_text_input, model);
break;
case InputKeyBack:
wifi_text_input_backspace_cb(model);
break;
default:
consumed = false;
break;
}
}
// Commit model
view_commit_model(wifi_text_input->view, consumed);
return consumed;
}
void wifi_text_input_timer_callback(void* context) {
furi_assert(context);
WIFI_TextInput* wifi_text_input = context;
with_view_model(
wifi_text_input->view,
WIFI_TextInputModel * model,
{ model->valadator_message_visible = false; },
true);
}
WIFI_TextInput* wifi_text_input_alloc() {
WIFI_TextInput* wifi_text_input = malloc(sizeof(WIFI_TextInput));
wifi_text_input->view = view_alloc();
view_set_context(wifi_text_input->view, wifi_text_input);
view_allocate_model(wifi_text_input->view, ViewModelTypeLocking, sizeof(WIFI_TextInputModel));
view_set_draw_callback(wifi_text_input->view, wifi_text_input_view_draw_callback);
view_set_input_callback(wifi_text_input->view, wifi_text_input_view_input_callback);
wifi_text_input->timer =
furi_timer_alloc(wifi_text_input_timer_callback, FuriTimerTypeOnce, wifi_text_input);
with_view_model(
wifi_text_input->view,
WIFI_TextInputModel * model,
{ model->validator_text = furi_string_alloc(); },
false);
wifi_text_input_reset(wifi_text_input);
return wifi_text_input;
}
void wifi_text_input_free(WIFI_TextInput* wifi_text_input) {
furi_assert(wifi_text_input);
with_view_model(
wifi_text_input->view,
WIFI_TextInputModel * model,
{ furi_string_free(model->validator_text); },
false);
// Send stop command
furi_timer_stop(wifi_text_input->timer);
// Release allocated memory
furi_timer_free(wifi_text_input->timer);
view_free(wifi_text_input->view);
free(wifi_text_input);
}
void wifi_text_input_reset(WIFI_TextInput* wifi_text_input) {
furi_assert(wifi_text_input);
with_view_model(
wifi_text_input->view,
WIFI_TextInputModel * model,
{
model->text_buffer_size = 0;
model->header = "";
model->selected_row = 0;
model->selected_column = 0;
model->clear_default_text = false;
model->text_buffer = NULL;
model->text_buffer_size = 0;
model->callback = NULL;
model->callback_context = NULL;
model->validator_callback = NULL;
model->validator_callback_context = NULL;
furi_string_reset(model->validator_text);
model->valadator_message_visible = false;
},
true);
}
View* wifi_text_input_get_view(WIFI_TextInput* wifi_text_input) {
furi_assert(wifi_text_input);
return wifi_text_input->view;
}
void wifi_text_input_set_result_callback(
WIFI_TextInput* wifi_text_input,
WIFI_TextInputCallback callback,
void* callback_context,
char* text_buffer,
size_t text_buffer_size,
bool clear_default_text) {
with_view_model(
wifi_text_input->view,
WIFI_TextInputModel * model,
{
model->callback = callback;
model->callback_context = callback_context;
model->text_buffer = text_buffer;
model->text_buffer_size = text_buffer_size;
model->clear_default_text = clear_default_text;
if(text_buffer && text_buffer[0] != '\0') {
// Set focus on Save
model->selected_row = 2;
model->selected_column = 8;
}
},
true);
}
void wifi_text_input_set_validator(
WIFI_TextInput* wifi_text_input,
WIFI_TextInputValidatorCallback callback,
void* callback_context) {
with_view_model(
wifi_text_input->view,
WIFI_TextInputModel * model,
{
model->validator_callback = callback;
model->validator_callback_context = callback_context;
},
true);
}
WIFI_TextInputValidatorCallback
wifi_text_input_get_validator_callback(WIFI_TextInput* wifi_text_input) {
WIFI_TextInputValidatorCallback validator_callback = NULL;
with_view_model(
wifi_text_input->view,
WIFI_TextInputModel * model,
{ validator_callback = model->validator_callback; },
false);
return validator_callback;
}
void* wifi_text_input_get_validator_callback_context(WIFI_TextInput* wifi_text_input) {
void* validator_callback_context = NULL;
with_view_model(
wifi_text_input->view,
WIFI_TextInputModel * model,
{ validator_callback_context = model->validator_callback_context; },
false);
return validator_callback_context;
}
void wifi_text_input_set_header_text(WIFI_TextInput* wifi_text_input, const char* text) {
with_view_model(
wifi_text_input->view, WIFI_TextInputModel * model, { model->header = text; }, true);
}

View File

@@ -0,0 +1,82 @@
#pragma once
#include <gui/view.h>
#include "wifi_marauder_validators.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Text input anonymous structure */
typedef struct WIFI_TextInput WIFI_TextInput;
typedef void (*WIFI_TextInputCallback)(void* context);
typedef bool (*WIFI_TextInputValidatorCallback)(const char* text, FuriString* error, void* context);
/** Allocate and initialize text input
*
* This text input is used to enter string
*
* @return WIFI_TextInput instance
*/
WIFI_TextInput* wifi_text_input_alloc();
/** Deinitialize and free text input
*
* @param wifi_text_input WIFI_TextInput instance
*/
void wifi_text_input_free(WIFI_TextInput* wifi_text_input);
/** Clean text input view Note: this function does not free memory
*
* @param wifi_text_input Text input instance
*/
void wifi_text_input_reset(WIFI_TextInput* wifi_text_input);
/** Get text input view
*
* @param wifi_text_input WIFI_TextInput instance
*
* @return View instance that can be used for embedding
*/
View* wifi_text_input_get_view(WIFI_TextInput* wifi_text_input);
/** Set text input result callback
*
* @param wifi_text_input WIFI_TextInput instance
* @param callback callback fn
* @param callback_context callback context
* @param text_buffer pointer to YOUR text buffer, that we going
* to modify
* @param text_buffer_size YOUR text buffer size in bytes. Max string
* length will be text_buffer_size-1.
* @param clear_default_text clear text from text_buffer on first OK
* event
*/
void wifi_text_input_set_result_callback(
WIFI_TextInput* wifi_text_input,
WIFI_TextInputCallback callback,
void* callback_context,
char* text_buffer,
size_t text_buffer_size,
bool clear_default_text);
void wifi_text_input_set_validator(
WIFI_TextInput* wifi_text_input,
WIFI_TextInputValidatorCallback callback,
void* callback_context);
WIFI_TextInputValidatorCallback
wifi_text_input_get_validator_callback(WIFI_TextInput* wifi_text_input);
void* wifi_text_input_get_validator_callback_context(WIFI_TextInput* wifi_text_input);
/** Set text input header text
*
* @param wifi_text_input WIFI_TextInput instance
* @param text text to be shown
*/
void wifi_text_input_set_header_text(WIFI_TextInput* wifi_text_input, const char* text);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,57 @@
#include <furi.h>
#include "wifi_marauder_validators.h"
#include <storage/storage.h>
struct ValidatorIsFile {
char* app_path_folder;
const char* app_extension;
char* current_name;
};
bool validator_is_file_callback(const char* text, FuriString* error, void* context) {
furi_assert(context);
ValidatorIsFile* instance = context;
if(instance->current_name != NULL) {
if(strcmp(instance->current_name, text) == 0) {
return true;
}
}
bool ret = true;
FuriString* path = furi_string_alloc_printf(
"%s/%s%s", instance->app_path_folder, text, instance->app_extension);
Storage* storage = furi_record_open(RECORD_STORAGE);
if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) {
ret = false;
furi_string_printf(error, "This name\nexists!\nChoose\nanother one.");
} else {
ret = true;
}
furi_string_free(path);
furi_record_close(RECORD_STORAGE);
return ret;
}
ValidatorIsFile* validator_is_file_alloc_init(
const char* app_path_folder,
const char* app_extension,
const char* current_name) {
ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile));
instance->app_path_folder = strdup(app_path_folder);
instance->app_extension = app_extension;
if(current_name != NULL) {
instance->current_name = strdup(current_name);
}
return instance;
}
void validator_is_file_free(ValidatorIsFile* instance) {
furi_assert(instance);
free(instance->app_path_folder);
free(instance->current_name);
free(instance);
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <core/common_defines.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ValidatorIsFile ValidatorIsFile;
ValidatorIsFile* validator_is_file_alloc_init(
const char* app_path_folder,
const char* app_extension,
const char* current_name);
void validator_is_file_free(ValidatorIsFile* instance);
bool validator_is_file_callback(const char* text, FuriString* error, void* context);
#ifdef __cplusplus
}
#endif

View File

@@ -35,12 +35,6 @@ typedef enum {
SubGhzSpeakerStateEnable,
} SubGhzSpeakerState;
/** SubGhzStarLineIgnore state */
typedef enum {
SubGhzStarLineIgnoreDisable,
SubGhzStarLineIgnoreEnable,
} SubGhzStarLineIgnoreState;
/** SubGhzRxKeyState state */
typedef enum {
SubGhzRxKeyStateIDLE,

View File

@@ -62,26 +62,31 @@ static void subghz_scene_add_to_history_callback(
void* context) {
furi_assert(context);
SubGhz* subghz = context;
FuriString* str_buff;
str_buff = furi_string_alloc();
FuriString* item_name;
FuriString* item_time;
uint16_t idx = subghz_history_get_item(subghz->txrx->history);
item_name = furi_string_alloc();
item_time = furi_string_alloc();
if(subghz_history_add_to_history(subghz->txrx->history, decoder_base, subghz->txrx->preset)) {
furi_string_reset(str_buff);
furi_string_reset(item_name);
furi_string_reset(item_time);
subghz->state_notifications = SubGhzNotificationStateRxDone;
subghz_history_get_text_item_menu(
subghz->txrx->history, str_buff, subghz_history_get_item(subghz->txrx->history) - 1);
subghz_history_get_text_item_menu(subghz->txrx->history, item_name, idx);
subghz_history_get_time_item_menu(subghz->txrx->history, item_time, idx);
subghz_view_receiver_add_item_to_menu(
subghz->subghz_receiver,
furi_string_get_cstr(str_buff),
subghz_history_get_type_protocol(
subghz->txrx->history, subghz_history_get_item(subghz->txrx->history) - 1));
furi_string_get_cstr(item_name),
furi_string_get_cstr(item_time),
subghz_history_get_type_protocol(subghz->txrx->history, idx));
subghz_scene_receiver_update_statusbar(subghz);
}
subghz_receiver_reset(receiver);
furi_string_free(str_buff);
furi_string_free(item_name);
furi_string_free(item_time);
}
bool subghz_scene_decode_raw_start(SubGhz* subghz) {
@@ -159,8 +164,10 @@ bool subghz_scene_decode_raw_next(SubGhz* subghz) {
void subghz_scene_decode_raw_on_enter(void* context) {
SubGhz* subghz = context;
FuriString* str_buff;
str_buff = furi_string_alloc();
FuriString* item_name;
FuriString* item_time;
item_name = furi_string_alloc();
item_time = furi_string_alloc();
subghz_view_receiver_set_lock(subghz->subghz_receiver, subghz->lock);
subghz_view_receiver_set_mode(subghz->subghz_receiver, SubGhzViewReceiverModeFile);
@@ -183,14 +190,18 @@ void subghz_scene_decode_raw_on_enter(void* context) {
//Load history to receiver
subghz_view_receiver_exit(subghz->subghz_receiver);
for(uint8_t i = 0; i < subghz_history_get_item(subghz->txrx->history); i++) {
furi_string_reset(str_buff);
subghz_history_get_text_item_menu(subghz->txrx->history, str_buff, i);
furi_string_reset(item_name);
furi_string_reset(item_time);
subghz_history_get_text_item_menu(subghz->txrx->history, item_name, i);
subghz_history_get_time_item_menu(subghz->txrx->history, item_time, i);
subghz_view_receiver_add_item_to_menu(
subghz->subghz_receiver,
furi_string_get_cstr(str_buff),
furi_string_get_cstr(item_name),
furi_string_get_cstr(item_time),
subghz_history_get_type_protocol(subghz->txrx->history, i));
}
furi_string_free(str_buff);
furi_string_free(item_name);
furi_string_free(item_time);
subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen);
}

View File

@@ -1,10 +1,11 @@
#include "../subghz_i.h"
#include "../helpers/subghz_custom_event.h"
uint8_t value_index_exm;
uint8_t value_index_dpin;
uint8_t value_index_cnt;
uint8_t value_index_pwr;
static uint8_t value_index_exm;
static uint8_t value_index_dpin;
static uint8_t value_index_cnt;
static uint8_t value_index_pwr;
static uint8_t value_index_time;
#define EXT_MODULES_COUNT (sizeof(radio_modules_variables_text) / sizeof(char* const))
const char* const radio_modules_variables_text[] = {
@@ -18,6 +19,12 @@ const char* const ext_mod_power_text[EXT_MOD_POWER_COUNT] = {
"OFF",
};
#define TIMESTAMP_NAMES_COUNT 2
const char* const timestamp_names_text[TIMESTAMP_NAMES_COUNT] = {
"OFF",
"ON",
};
#define DEBUG_P_COUNT 2
const char* const debug_pin_text[DEBUG_P_COUNT] = {
"OFF",
@@ -104,6 +111,17 @@ static void subghz_scene_receiver_config_set_ext_mod_power(VariableItem* item) {
subghz_last_settings_save(subghz->last_settings);
}
static void subghz_scene_receiver_config_set_timestamp_file_names(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, timestamp_names_text[index]);
furi_hal_subghz_set_timestamp_file_names((index == 1));
subghz->last_settings->timestamp_file_names = (index == 1);
subghz_last_settings_save(subghz->last_settings);
}
void subghz_scene_ext_module_settings_on_enter(void* context) {
SubGhz* subghz = context;
@@ -129,6 +147,16 @@ void subghz_scene_ext_module_settings_on_enter(void* context) {
variable_item_set_current_value_index(item, value_index_pwr);
variable_item_set_current_value_text(item, ext_mod_power_text[value_index_pwr]);
item = variable_item_list_add(
subghz->variable_item_list,
"Time in names",
TIMESTAMP_NAMES_COUNT,
subghz_scene_receiver_config_set_timestamp_file_names,
subghz);
value_index_time = furi_hal_subghz_get_timestamp_file_names();
variable_item_set_current_value_index(item, value_index_time);
variable_item_set_current_value_text(item, timestamp_names_text[value_index_time]);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
item = variable_item_list_add(
subghz->variable_item_list,

View File

@@ -91,34 +91,41 @@ static void subghz_scene_add_to_history_callback(
void* context) {
furi_assert(context);
SubGhz* subghz = context;
FuriString* str_buff;
str_buff = furi_string_alloc();
FuriString* item_name;
FuriString* item_time;
uint16_t idx = subghz_history_get_item(subghz->txrx->history);
item_name = furi_string_alloc();
item_time = furi_string_alloc();
if(subghz_history_add_to_history(subghz->txrx->history, decoder_base, subghz->txrx->preset)) {
furi_string_reset(str_buff);
furi_string_reset(item_name);
furi_string_reset(item_time);
subghz->state_notifications = SubGhzNotificationStateRxDone;
subghz_history_get_text_item_menu(
subghz->txrx->history, str_buff, subghz_history_get_item(subghz->txrx->history) - 1);
subghz_history_get_text_item_menu(subghz->txrx->history, item_name, idx);
subghz_history_get_time_item_menu(subghz->txrx->history, item_time, idx);
subghz_view_receiver_add_item_to_menu(
subghz->subghz_receiver,
furi_string_get_cstr(str_buff),
subghz_history_get_type_protocol(
subghz->txrx->history, subghz_history_get_item(subghz->txrx->history) - 1));
furi_string_get_cstr(item_name),
furi_string_get_cstr(item_time),
subghz_history_get_type_protocol(subghz->txrx->history, idx));
subghz_scene_receiver_update_statusbar(subghz);
}
subghz_receiver_reset(receiver);
furi_string_free(str_buff);
furi_string_free(item_name);
furi_string_free(item_time);
subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey;
}
void subghz_scene_receiver_on_enter(void* context) {
SubGhz* subghz = context;
FuriString* str_buff;
str_buff = furi_string_alloc();
FuriString* item_name;
FuriString* item_time;
item_name = furi_string_alloc();
item_time = furi_string_alloc();
if(subghz->txrx->rx_key_state == SubGhzRxKeyStateIDLE) {
subghz_preset_init(subghz, "AM650", subghz->last_settings->frequency, NULL, 0);
@@ -132,22 +139,28 @@ void subghz_scene_receiver_on_enter(void* context) {
//Load history to receiver
subghz_view_receiver_exit(subghz->subghz_receiver);
for(uint8_t i = 0; i < subghz_history_get_item(subghz->txrx->history); i++) {
furi_string_reset(str_buff);
subghz_history_get_text_item_menu(subghz->txrx->history, str_buff, i);
furi_string_reset(item_name);
furi_string_reset(item_time);
subghz_history_get_text_item_menu(subghz->txrx->history, item_name, i);
subghz_history_get_time_item_menu(subghz->txrx->history, item_time, i);
subghz_view_receiver_add_item_to_menu(
subghz->subghz_receiver,
furi_string_get_cstr(str_buff),
furi_string_get_cstr(item_name),
furi_string_get_cstr(item_time),
subghz_history_get_type_protocol(subghz->txrx->history, i));
subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey;
}
furi_string_free(str_buff);
furi_string_free(item_name);
furi_string_free(item_time);
subghz_scene_receiver_update_statusbar(subghz);
subghz_view_receiver_set_callback(
subghz->subghz_receiver, subghz_scene_receiver_callback, subghz);
subghz_receiver_set_rx_callback(
subghz->txrx->receiver, subghz_scene_add_to_history_callback, subghz);
if(subghz->txrx->starline_state == SubGhzStarLineIgnoreEnable) {
// TODO: Replace with proper solution based on protocol flags, remove kostily and velosipedy from here
// Needs to be done after subghz refactoring merge!!!
if(subghz->txrx->ignore_starline == true) {
SubGhzProtocolDecoderBase* protocoldecoderbase = NULL;
protocoldecoderbase =
subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, "Star Line");
@@ -156,6 +169,31 @@ void subghz_scene_receiver_on_enter(void* context) {
protocoldecoderbase, NULL, subghz->txrx->receiver);
}
}
if(subghz->txrx->ignore_auto_alarms == true) {
SubGhzProtocolDecoderBase* protocoldecoderbase = NULL;
protocoldecoderbase =
subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, "KIA Seed");
if(protocoldecoderbase) {
subghz_protocol_decoder_base_set_decoder_callback(
protocoldecoderbase, NULL, subghz->txrx->receiver);
}
protocoldecoderbase = NULL;
protocoldecoderbase =
subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, "Scher-Khan");
if(protocoldecoderbase) {
subghz_protocol_decoder_base_set_decoder_callback(
protocoldecoderbase, NULL, subghz->txrx->receiver);
}
}
if(subghz->txrx->ignore_magellan == true) {
SubGhzProtocolDecoderBase* protocoldecoderbase = NULL;
protocoldecoderbase =
subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, "Magellan");
if(protocoldecoderbase) {
subghz_protocol_decoder_base_set_decoder_callback(
protocoldecoderbase, NULL, subghz->txrx->receiver);
}
}
subghz->state_notifications = SubGhzNotificationStateRx;
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {

View File

@@ -7,6 +7,8 @@ enum SubGhzSettingIndex {
SubGhzSettingIndexModulation,
SubGhzSettingIndexBinRAW,
SubGhzSettingIndexIgnoreStarline,
SubGhzSettingIndexIgnoreCars,
SubGhzSettingIndexIgnoreMagellan,
SubGhzSettingIndexSound,
SubGhzSettingIndexLock,
SubGhzSettingIndexRAWThresholdRSSI,
@@ -69,14 +71,22 @@ const uint32_t bin_raw_value[BIN_RAW_COUNT] = {
SubGhzProtocolFlag_Decodable,
SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW,
};
#define STAR_LINE_COUNT 2
const char* const star_line_text[STAR_LINE_COUNT] = {
#define STARLINE_COUNT 2
const char* const starline_text[STARLINE_COUNT] = {
"OFF",
"ON",
};
const uint32_t star_line_value[STAR_LINE_COUNT] = {
SubGhzStarLineIgnoreDisable,
SubGhzStarLineIgnoreEnable,
#define AUTO_ALARMS_COUNT 2
const char* const auto_alarms_text[AUTO_ALARMS_COUNT] = {
"OFF",
"ON",
};
#define MAGELLAN_COUNT 2
const char* const magellan_text[MAGELLAN_COUNT] = {
"OFF",
"ON",
};
uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
@@ -231,8 +241,24 @@ static void subghz_scene_receiver_config_set_starline(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, star_line_text[index]);
subghz->txrx->starline_state = star_line_value[index];
variable_item_set_current_value_text(item, starline_text[index]);
subghz->txrx->ignore_starline = (index == 1);
}
static void subghz_scene_receiver_config_set_auto_alarms(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, auto_alarms_text[index]);
subghz->txrx->ignore_auto_alarms = (index == 1);
}
static void subghz_scene_receiver_config_set_magellan(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, magellan_text[index]);
subghz->txrx->ignore_magellan = (index == 1);
}
static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {
@@ -313,15 +339,36 @@ void subghz_scene_receiver_config_on_enter(void* context) {
SubGhzCustomEventManagerSet) {
item = variable_item_list_add(
subghz->variable_item_list,
"Ignore StarLine:",
STAR_LINE_COUNT,
"Ignore Starline:",
STARLINE_COUNT,
subghz_scene_receiver_config_set_starline,
subghz);
value_index =
value_index_uint32(subghz->txrx->starline_state, star_line_value, STAR_LINE_COUNT);
value_index = subghz->txrx->ignore_starline;
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, star_line_text[value_index]);
variable_item_set_current_value_text(item, starline_text[value_index]);
item = variable_item_list_add(
subghz->variable_item_list,
"Ignore Cars:",
AUTO_ALARMS_COUNT,
subghz_scene_receiver_config_set_auto_alarms,
subghz);
value_index = subghz->txrx->ignore_auto_alarms;
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, auto_alarms_text[value_index]);
item = variable_item_list_add(
subghz->variable_item_list,
"Ignore Magellan:",
MAGELLAN_COUNT,
subghz_scene_receiver_config_set_magellan,
subghz);
value_index = subghz->txrx->ignore_magellan;
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, magellan_text[value_index]);
}
// Enable speaker, will send all incoming noises and signals to speaker so you can listen how your remote sounds like :)

View File

@@ -115,6 +115,9 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) {
void subghz_scene_receiver_info_on_enter(void* context) {
SubGhz* subghz = context;
keeloq_reset_original_btn();
subghz_custom_btns_reset();
subghz_scene_receiver_info_draw_widget(subghz);
}

View File

@@ -14,18 +14,34 @@ void subghz_scene_save_name_text_input_callback(void* context) {
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneSaveName);
}
void subghz_scene_save_name_get_timefilename(FuriString* name) {
void subghz_scene_save_name_get_timefilename(
FuriString* name,
const char* proto_name,
bool fulldate) {
FuriHalRtcDateTime datetime = {0};
furi_hal_rtc_get_datetime(&datetime);
furi_string_printf(
name,
"RAW_%.4d%.2d%.2d-%.2d%.2d%.2d",
datetime.year,
datetime.month,
datetime.day,
datetime.hour,
datetime.minute,
datetime.second);
if(fulldate) {
furi_string_printf(
name,
"%s_%.4d%.2d%.2d-%.2d%.2d%.2d",
proto_name,
datetime.year,
datetime.month,
datetime.day,
datetime.hour,
datetime.minute,
datetime.second);
} else {
furi_string_printf(
name,
"%s_%.2d%.2d-%.2d%.2d%.2d",
proto_name,
datetime.month,
datetime.day,
datetime.hour,
datetime.minute,
datetime.second);
}
}
void subghz_scene_save_name_on_enter(void* context) {
@@ -42,8 +58,30 @@ void subghz_scene_save_name_on_enter(void* context) {
if(!subghz_path_is_file(subghz->file_path)) {
char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0};
set_random_name(file_name_buf, SUBGHZ_MAX_LEN_NAME);
furi_string_set(file_name, file_name_buf);
if(furi_hal_subghz_get_timestamp_file_names()) {
if(subghz->txrx->decoder_result != 0x0) {
if(subghz->txrx->decoder_result != NULL) {
if(strlen(subghz->txrx->decoder_result->protocol->name) != 0) {
if(strcmp(subghz->txrx->decoder_result->protocol->name, "BinRAW") == 0) {
subghz_scene_save_name_get_timefilename(file_name, "S", true);
} else {
subghz_scene_save_name_get_timefilename(
file_name, subghz->txrx->decoder_result->protocol->name, false);
}
} else {
subghz_scene_save_name_get_timefilename(file_name, "S", true);
}
} else {
subghz_scene_save_name_get_timefilename(file_name, "S", true);
}
} else {
subghz_scene_save_name_get_timefilename(file_name, "S", true);
}
} else {
set_random_name(file_name_buf, SUBGHZ_MAX_LEN_NAME);
furi_string_set(file_name, file_name_buf);
}
furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER);
//highlighting the entire filename by default
dev_name_empty = true;
@@ -57,7 +95,7 @@ void subghz_scene_save_name_on_enter(void* context) {
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
SubGhzCustomEventManagerSetRAW) {
dev_name_empty = true;
subghz_scene_save_name_get_timefilename(file_name);
subghz_scene_save_name_get_timefilename(file_name, "RAW", true);
}
}
furi_string_set(subghz->file_path, dir_name);

View File

@@ -52,6 +52,10 @@ bool subghz_scene_transmitter_update_data_show(void* context) {
void subghz_scene_transmitter_on_enter(void* context) {
SubGhz* subghz = context;
keeloq_reset_original_btn();
subghz_custom_btns_reset();
if(!subghz_scene_transmitter_update_data_show(subghz)) {
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubGhzCustomEventViewTransmitterError);

View File

@@ -12,6 +12,7 @@ typedef struct {
FlipperFormat* flipper_string;
uint8_t type;
SubGhzRadioPreset* preset;
FuriHalRtcDateTime datetime;
} SubGhzHistoryItem;
ARRAY_DEF(SubGhzHistoryItemArray, SubGhzHistoryItem, M_POD_OPLIST)
@@ -164,6 +165,12 @@ void subghz_history_get_text_item_menu(SubGhzHistory* instance, FuriString* outp
furi_string_set(output, item->item_str);
}
void subghz_history_get_time_item_menu(SubGhzHistory* instance, FuriString* output, uint16_t idx) {
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
FuriHalRtcDateTime* t = &item->datetime;
furi_string_printf(output, "%.2d:%.2d:%.2d ", t->hour, t->minute, t->second);
}
bool subghz_history_add_to_history(
SubGhzHistory* instance,
void* context,
@@ -195,6 +202,7 @@ bool subghz_history_add_to_history(
furi_string_set(item->preset->name, preset->name);
item->preset->data = preset->data;
item->preset->data_size = preset->data_size;
furi_hal_rtc_get_datetime(&item->datetime);
item->item_str = furi_string_alloc();
item->flipper_string = flipper_format_string_alloc();

View File

@@ -78,6 +78,14 @@ const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t i
*/
void subghz_history_get_text_item_menu(SubGhzHistory* instance, FuriString* output, uint16_t idx);
/** Get time item menu to history[idx]
*
* @param instance - SubGhzHistory instance
* @param output - FuriString* output
* @param idx - record index
*/
void subghz_history_get_time_item_menu(SubGhzHistory* instance, FuriString* output, uint16_t idx);
/** Get string the remaining number of records to history
*
* @param instance - SubGhzHistory instance

View File

@@ -1,163 +0,0 @@
#pragma once
#include "subghz_history.h"
#include <toolbox/stream/stream.h>
/**
* @brief Generate filename like 000.tmp
*
* @param index - index of file, timestamp doesn't accepted!
*/
FuriString* subghz_history_generate_temp_filename(uint32_t index);
/**
* @brief Check if directory for temporary files is exists
*
* @param instance SubGhzHistory*
* @return true
* @return false
*/
bool subghz_history_is_tmp_dir_exists(SubGhzHistory* instance);
/**
* @brief Check SD card and create temporary dir if not exists,
* Result write_tmp_files without this unstable work is GUARANTEED
*
* @param instance - SubGhzHistory*
* @return - true all ok
* @return - false we have a problems
*/
bool subghz_history_check_sdcard(SubGhzHistory* instance);
/**
* @brief Recursive delete dir and files and create new temp dir
*
* @param instance - SubGhzHistory*
* @return true - if all ok
* @return false - if something failed
*/
void subghz_history_clear_tmp_dir(SubGhzHistory* instance);
/**
* @brief Free item and free all resources
*
* @param current_item - SubGhzHistoryItem*
*/
void subghz_history_item_free(void* current_item);
/**
* @brief free all items in array
*
* @param instance
*/
void subghz_history_clean_item_array(SubGhzHistory* instance);
/**
* @brief Write temp file fully, without splitting
*
* @param instance - SubGhzHistory*
* @param current_item - SubGhzHistoryItem*
* @param dir_path - full path to file
*/
void subghz_history_tmp_write_file_full(
SubGhzHistory* instance,
void* current_item,
FuriString* dir_path);
/**
* @brief Write temp spited to lines
*
* @param instance - SubGhzHistory*
* @param current_item - SubGhzHistoryItem*
* @param dir_path - full path to file
* @return true - file saved
* @return false - error occurred
*/
bool subghz_history_tmp_write_file_split(
SubGhzHistory* instance,
void* current_item,
const char* dir_path);
/**
* @brief generate random value
*
* @param min - min value
* @param max - max value
* @return uint32_t
*/
uint32_t subghz_history_rand_range(uint32_t min, uint32_t max);
/**
* @brief write random noise signals to file applying to max line value
*
* @param file - Stream*
* @param is_negative_start - first value is negative or positive?
* @param current_position - 0 if started from beginning
* @param empty_line - add RAW_Data to this line
* @return true
* @return false
*/
bool subghz_history_write_file_noise(
Stream* file,
bool is_negative_start,
size_t current_position,
bool empty_line);
/**
* @brief taken from flipper_format_stream_read_value_line but takes only one int32 value
*
* @param stream - Stream*
* @param _data - int32_t* output data
* @param data_size - size of data
* @return true
* @return false
*/
bool subghz_history_read_int32(Stream* stream, int32_t* _data, const uint16_t data_size);
/**
* @brief write payload to file spliting by lines
*
* @param src - Stream* of source
* @param file - Stream* of file
* @param is_negative_start - first value is negative or positive?
* @param current_position - by default is 0 but in this value returned last position of payload
* @return true
* @return false
*/
bool subghz_history_write_file_data(
Stream* src,
Stream* file,
bool* is_negative_start,
size_t* current_position);
/**
* @brief taken from flipper_format_stream_read_valid_key
*
* @param stream - Stream*
* @param key - FuriString* output value
* @return true
* @return false
*/
bool subghz_history_stream_read_valid_key(Stream* stream, FuriString* key);
/**
* @brief taken from flipper_format_stream_seek_to_key
*
* @param stream - Stream*
* @param key - key
* @param strict_mode - false
* @return true
* @return false
*/
bool subghz_history_stream_seek_to_key(Stream* stream, const char* key, bool strict_mode);
/**
* @brief taken from flipper_format_stream_read_value
*
* @param stream - Stream*
* @param value - FuriString* output value
* @param last - return position is last flag
* @return true
* @return false
*/
bool subghz_history_stream_read_value(Stream* stream, FuriString* value, bool* last);

View File

@@ -73,7 +73,9 @@ struct SubGhzTxRx {
SubGhzTxRxState txrx_state;
SubGhzHopperState hopper_state;
SubGhzSpeakerState speaker_state;
SubGhzStarLineIgnoreState starline_state;
bool ignore_starline;
bool ignore_auto_alarms;
bool ignore_magellan;
uint8_t hopper_timeout;
uint8_t hopper_idx_frequency;
SubGhzRxKeyState rx_key_state;

View File

@@ -19,6 +19,7 @@
#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_TRIGGER "FATrigger"
#define SUBGHZ_LAST_SETTING_FIELD_EXTERNAL_MODULE_ENABLED "External"
#define SUBGHZ_LAST_SETTING_FIELD_EXTERNAL_MODULE_POWER "ExtPower"
#define SUBGHZ_LAST_SETTING_FIELD_TIMESTAMP_FILE_NAMES "TimestampNames"
SubGhzLastSettings* subghz_last_settings_alloc(void) {
SubGhzLastSettings* instance = malloc(sizeof(SubGhzLastSettings));
@@ -45,6 +46,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
float temp_frequency_analyzer_trigger = 0;
bool temp_external_module_enabled = false;
bool temp_external_module_power_5v_disable = false;
bool temp_timestamp_file_names = false;
//int32_t temp_preset = 0;
bool frequency_analyzer_feedback_level_was_read = false;
bool frequency_analyzer_trigger_was_read = false;
@@ -76,6 +78,11 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
SUBGHZ_LAST_SETTING_FIELD_EXTERNAL_MODULE_POWER,
(bool*)&temp_external_module_power_5v_disable,
1);
flipper_format_read_bool(
fff_data_file,
SUBGHZ_LAST_SETTING_FIELD_TIMESTAMP_FILE_NAMES,
(bool*)&temp_timestamp_file_names,
1);
} else {
FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH);
@@ -89,6 +96,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_FEEDBACK_LEVEL;
instance->frequency_analyzer_trigger = SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER;
instance->external_module_enabled = false;
instance->timestamp_file_names = false;
} else {
instance->frequency = temp_frequency;
@@ -109,6 +117,11 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
instance->external_module_power_5v_disable = temp_external_module_power_5v_disable;
instance->timestamp_file_names = temp_timestamp_file_names;
// Set globally
furi_hal_subghz_set_timestamp_file_names(instance->timestamp_file_names);
if(instance->external_module_power_5v_disable) {
furi_hal_subghz_set_external_power_disable(true);
furi_hal_subghz_disable_ext_power();
@@ -189,6 +202,13 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) {
1)) {
break;
}
if(!flipper_format_insert_or_update_bool(
file,
SUBGHZ_LAST_SETTING_FIELD_TIMESTAMP_FILE_NAMES,
&instance->timestamp_file_names,
1)) {
break;
}
saved = true;
} while(0);

View File

@@ -12,6 +12,7 @@ typedef struct {
float frequency_analyzer_trigger;
bool external_module_enabled;
bool external_module_power_5v_disable;
bool timestamp_file_names;
} SubGhzLastSettings;
SubGhzLastSettings* subghz_last_settings_alloc(void);

View File

@@ -14,8 +14,12 @@
#define SUBGHZ_RAW_THRESHOLD_MIN -90.0f
#define SCROLL_INTERVAL (606)
#define SCROLL_DELAY (2)
typedef struct {
FuriString* item_str;
FuriString* time;
uint8_t type;
} SubGhzReceiverMenuItem;
@@ -51,6 +55,7 @@ struct SubGhzViewReceiver {
View* view;
SubGhzViewReceiverCallback callback;
void* context;
FuriTimer* scroll_timer;
};
typedef struct {
@@ -65,6 +70,7 @@ typedef struct {
SubGhzViewReceiverBarShow bar_show;
SubGhzViewReceiverMode mode;
uint8_t u_rssi;
size_t scroll_counter;
} SubGhzViewReceiverModel;
void subghz_view_receiver_set_mode(
@@ -144,6 +150,7 @@ static void subghz_view_receiver_update_offset(SubGhzViewReceiver* subghz_receiv
void subghz_view_receiver_add_item_to_menu(
SubGhzViewReceiver* subghz_receiver,
const char* name,
const char* time,
uint8_t type) {
furi_assert(subghz_receiver);
with_view_model(
@@ -152,6 +159,7 @@ void subghz_view_receiver_add_item_to_menu(
{
SubGhzReceiverMenuItem* item_menu =
SubGhzReceiverMenuItemArray_push_raw(model->history->data);
item_menu->time = furi_string_alloc_set(time);
item_menu->item_str = furi_string_alloc_set(name);
item_menu->type = type;
if((model->idx == model->history_item - 1)) {
@@ -240,14 +248,29 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
size_t idx = CLAMP((uint16_t)(i + model->list_offset), model->history_item, 0);
item_menu = SubGhzReceiverMenuItemArray_get(model->history->data, idx);
furi_string_set(str_buff, item_menu->item_str);
elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 7 : MAX_LEN_PX);
size_t scroll_counter = model->scroll_counter;
if(model->idx == idx) {
subghz_view_receiver_draw_frame(canvas, i, scrollbar);
if(scroll_counter < SCROLL_DELAY) {
// Show time of signal one moment
furi_string_set(str_buff, item_menu->time);
scroll_counter = 0;
} else {
scroll_counter -= SCROLL_DELAY;
}
} else {
canvas_set_color(canvas, ColorBlack);
scroll_counter = 0;
}
canvas_draw_icon(canvas, 4, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]);
canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buff));
elements_scrollable_text_line(
canvas,
15,
9 + i * FRAME_HEIGHT,
(scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX),
str_buff,
scroll_counter,
(model->idx != idx));
furi_string_reset(str_buff);
}
if(scrollbar) {
@@ -353,6 +376,13 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
}
}
static void subghz_view_receiver_scroll_timer_callback(void* context) {
furi_assert(context);
SubGhzViewReceiver* subghz_receiver = context;
with_view_model(
subghz_receiver->view, SubGhzViewReceiverModel * model, { model->scroll_counter++; }, true);
}
static void subghz_view_receiver_timer_callback(void* context) {
furi_assert(context);
SubGhzViewReceiver* subghz_receiver = context;
@@ -412,6 +442,7 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) {
SubGhzViewReceiverModel * model,
{
if(model->idx != 0) model->idx--;
model->scroll_counter = 0;
},
true);
} else if(
@@ -423,6 +454,7 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) {
{
if((model->history_item != 0) && (model->idx != model->history_item - 1))
model->idx++;
model->scroll_counter = 0;
},
true);
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
@@ -442,6 +474,7 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) {
if(it->index == (size_t)(model->idx)) {
furi_string_free(item->item_str);
furi_string_free(item->time);
item->type = 0;
SubGhzReceiverMenuItemArray_remove(model->history->data, it);
}
@@ -475,6 +508,13 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) {
void subghz_view_receiver_enter(void* context) {
furi_assert(context);
SubGhzViewReceiver* subghz_receiver = context;
with_view_model(
subghz_receiver->view,
SubGhzViewReceiverModel * model,
{ model->scroll_counter = 0; },
true);
furi_timer_start(subghz_receiver->scroll_timer, SCROLL_INTERVAL);
}
void subghz_view_receiver_exit(void* context) {
@@ -491,6 +531,7 @@ void subghz_view_receiver_exit(void* context) {
for
M_EACH(item_menu, model->history->data, SubGhzReceiverMenuItemArray_t) {
furi_string_free(item_menu->item_str);
furi_string_free(item_menu->time);
item_menu->type = 0;
}
SubGhzReceiverMenuItemArray_reset(model->history->data);
@@ -500,6 +541,7 @@ void subghz_view_receiver_exit(void* context) {
},
false);
furi_timer_stop(subghz_receiver->timer);
furi_timer_stop(subghz_receiver->scroll_timer);
}
SubGhzViewReceiver* subghz_view_receiver_alloc() {
@@ -518,6 +560,9 @@ SubGhzViewReceiver* subghz_view_receiver_alloc() {
view_set_enter_callback(subghz_receiver->view, subghz_view_receiver_enter);
view_set_exit_callback(subghz_receiver->view, subghz_view_receiver_exit);
subghz_receiver->scroll_timer = furi_timer_alloc(
subghz_view_receiver_scroll_timer_callback, FuriTimerTypePeriodic, subghz_receiver);
with_view_model(
subghz_receiver->view,
SubGhzViewReceiverModel * model,
@@ -539,6 +584,8 @@ SubGhzViewReceiver* subghz_view_receiver_alloc() {
void subghz_view_receiver_free(SubGhzViewReceiver* subghz_receiver) {
furi_assert(subghz_receiver);
furi_timer_free(subghz_receiver->scroll_timer);
with_view_model(
subghz_receiver->view,
SubGhzViewReceiverModel * model,
@@ -550,6 +597,7 @@ void subghz_view_receiver_free(SubGhzViewReceiver* subghz_receiver) {
for
M_EACH(item_menu, model->history->data, SubGhzReceiverMenuItemArray_t) {
furi_string_free(item_menu->item_str);
furi_string_free(item_menu->time);
item_menu->type = 0;
}
SubGhzReceiverMenuItemArray_clear(model->history->data);

View File

@@ -40,6 +40,7 @@ void subghz_view_receiver_add_data_progress(
void subghz_view_receiver_add_item_to_menu(
SubGhzViewReceiver* subghz_receiver,
const char* name,
const char* time,
uint8_t type);
uint16_t subghz_view_receiver_get_idx_menu(SubGhzViewReceiver* subghz_receiver);

View File

@@ -135,7 +135,7 @@ static void cfg_read_file_path(
*is_enabled = 0;
} else {
*text_file_label = extract_filename(furi_string_get_cstr(text_file_path), 16);
FURI_LOG_D(TAG, "%s file: %s", read_key, furi_string_get_cstr(text_file_path));
//FURI_LOG_D(TAG, "%s file: %s", read_key, furi_string_get_cstr(text_file_path));
*is_enabled = 1;
}
flipper_format_rewind(fff_file);
@@ -154,7 +154,7 @@ static void cfg_read_file_label(
if(is_enabled == 1) {
*text_file_label = char_to_str((char*)furi_string_get_cstr(temp_label), 16);
}
FURI_LOG_D(TAG, "%s label: %s", read_key, *text_file_label);
//FURI_LOG_D(TAG, "%s label: %s", read_key, *text_file_label);
}
flipper_format_rewind(fff_file);
furi_string_free(temp_label);
@@ -355,6 +355,8 @@ bool subghz_remote_key_load(
bool res = false;
subghz_custom_btn_set(0);
keeloq_reset_original_btn();
subghz_custom_btns_reset();
do {
// load frequency from file
@@ -387,6 +389,10 @@ bool subghz_remote_key_load(
FURI_LOG_E(TAG, "Could not read Protocol.");
break;
}
if(!flipper_format_rewind(fff_data)) {
FURI_LOG_E(TAG, "Rewind error");
return false;
}
if(!furi_string_cmp_str(preset->protocol, "RAW")) {
subghz_protocol_raw_gen_fff_data(fff_data, path);
@@ -395,10 +401,7 @@ bool subghz_remote_key_load(
FURI_LOG_E(TAG, "Unable to insert or update Repeat");
break;
}
if(!flipper_format_rewind(fff_data)) {
FURI_LOG_E(TAG, "Rewind error");
return false;
}
} else {
stream_copy_full(
flipper_format_get_raw_stream(fff_file), flipper_format_get_raw_stream(fff_data));
@@ -407,10 +410,6 @@ bool subghz_remote_key_load(
FURI_LOG_E(TAG, "Unable to insert or update Repeat");
break;
}
if(!flipper_format_rewind(fff_data)) {
FURI_LOG_E(TAG, "Rewind error");
return false;
}
}
if(!flipper_format_rewind(fff_file)) {
@@ -468,7 +467,7 @@ bool subghz_remote_save_protocol_to_file(FlipperFormat* fff_file, const char* de
stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS);
saved = true;
FURI_LOG_D(TAG, "(save) OK Save");
//FURI_LOG_D(TAG, "(save) OK Save");
} while(0);
furi_string_free(file_dir);
furi_record_close(RECORD_STORAGE);
@@ -528,7 +527,8 @@ static bool subghz_remote_send_sub(SubGHzRemote* app, FlipperFormat* fff_data) {
bool res = false;
do {
if(!furi_hal_subghz_is_tx_allowed(app->txpreset->frequency)) {
printf(
FURI_LOG_E(
TAG,
"In your settings, only reception on this frequency (%lu) is allowed,\r\n"
"the actual operation of the subghz remote app is not possible\r\n ",
app->txpreset->frequency);
@@ -545,7 +545,11 @@ static bool subghz_remote_send_sub(SubGHzRemote* app, FlipperFormat* fff_data) {
break;
}
subghz_transmitter_deserialize(app->tx_transmitter, fff_data);
if(subghz_transmitter_deserialize(app->tx_transmitter, fff_data) !=
SubGhzProtocolStatusOk) {
FURI_LOG_E(TAG, "Deserialize error!");
break;
}
furi_hal_subghz_reset();
furi_hal_subghz_idle();
@@ -576,7 +580,7 @@ static bool subghz_remote_send_sub(SubGHzRemote* app, FlipperFormat* fff_data) {
}
static void subghz_remote_send_signal(SubGHzRemote* app, Storage* storage, const char* path) {
FURI_LOG_D(TAG, "Sending: %s", path);
//FURI_LOG_D(TAG, "Sending: %s", path);
app->tx_file_path = path;
@@ -616,7 +620,7 @@ static void subghz_remote_send_signal(SubGHzRemote* app, Storage* storage, const
static void subghz_remote_process_signal(SubGHzRemote* app, FuriString* signal) {
view_port_update(app->view_port);
FURI_LOG_D(TAG, "signal = %s", furi_string_get_cstr(signal));
//FURI_LOG_D(TAG, "signal = %s", furi_string_get_cstr(signal));
if(strlen(furi_string_get_cstr(signal)) > 12) {
Storage* storage = furi_record_open(RECORD_STORAGE);
@@ -746,6 +750,8 @@ void subghz_remote_subghz_alloc(SubGHzRemote* app) {
app->environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
app->environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
app->environment, EXT_PATH("subghz/assets/alutech_at_4n"));
subghz_environment_set_protocol_registry(app->environment, (void*)&subghz_protocol_registry);
app->subghz_receiver = subghz_receiver_alloc_init(app->environment);
@@ -868,14 +874,14 @@ int32_t subghz_remote_app(void* p) {
bool exit_loop = false;
if(app->file_result == 2) {
FURI_LOG_D(
TAG,
"U: %s - D: %s - L: %s - R: %s - O: %s ",
furi_string_get_cstr(app->up_file),
furi_string_get_cstr(app->down_file),
furi_string_get_cstr(app->left_file),
furi_string_get_cstr(app->right_file),
furi_string_get_cstr(app->ok_file));
//FURI_LOG_D(
//TAG,
//"U: %s - D: %s - L: %s - R: %s - O: %s ",
//furi_string_get_cstr(app->up_file),
//furi_string_get_cstr(app->down_file),
//furi_string_get_cstr(app->left_file),
//furi_string_get_cstr(app->right_file),
//furi_string_get_cstr(app->ok_file));
//variables to control multiple button presses and status updates
app->send_status = "Idle";
@@ -893,11 +899,11 @@ int32_t subghz_remote_app(void* p) {
while(1) {
furi_check(
furi_message_queue_get(app->input_queue, &input, FuriWaitForever) == FuriStatusOk);
FURI_LOG_D(
TAG,
"key: %s type: %s",
input_get_key_name(input.key),
input_get_type_name(input.type));
//FURI_LOG_D(
//TAG,
//"key: %s type: %s",
//input_get_key_name(input.key),
//input_get_type_name(input.type));
switch(input.key) {
case InputKeyUp:
@@ -999,12 +1005,12 @@ int32_t subghz_remote_app(void* p) {
}
if(app->processing == 0) {
FURI_LOG_D(TAG, "processing 0");
//FURI_LOG_D(TAG, "processing 0");
app->send_status = "Idle";
app->send_status_c = 0;
app->button = 0;
} else if(app->processing == 1) {
FURI_LOG_D(TAG, "processing 1");
//FURI_LOG_D(TAG, "processing 1");
app->send_status = "Send";
@@ -1047,11 +1053,11 @@ int32_t subghz_remote_app(void* p) {
while(1) {
furi_check(
furi_message_queue_get(app->input_queue, &input, FuriWaitForever) == FuriStatusOk);
FURI_LOG_D(
TAG,
"key: %s type: %s",
input_get_key_name(input.key),
input_get_type_name(input.type));
//FURI_LOG_D(
//TAG,
//"key: %s type: %s",
//input_get_key_name(input.key),
//input_get_type_name(input.type));
switch(input.key) {
case InputKeyRight:

View File

@@ -225,7 +225,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) {
furi_event_flag_clear(bt->rpc_event, BT_RPC_EVENT_DISCONNECTED);
if(bt->profile == BtProfileSerial) {
// Open RPC session
bt->rpc_session = rpc_session_open(bt->rpc);
bt->rpc_session = rpc_session_open(bt->rpc, RpcOwnerBle);
if(bt->rpc_session) {
FURI_LOG_I(TAG, "Open RPC connection");
rpc_session_set_send_bytes_callback(bt->rpc_session, bt_rpc_send_bytes_callback);

View File

@@ -46,6 +46,12 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context)
canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8);
}
static void desktop_stealth_mode_icon_draw_callback(Canvas* canvas, void* context) {
UNUSED(context);
furi_assert(canvas);
canvas_draw_icon(canvas, 0, 0, &I_Muted_8x8);
}
static bool desktop_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);
Desktop* desktop = (Desktop*)context;
@@ -156,6 +162,17 @@ void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) {
desktop->in_transition = false;
}
void desktop_set_stealth_mode_state(Desktop* desktop, bool enabled) {
desktop->in_transition = true;
if(enabled) {
furi_hal_rtc_set_flag(FuriHalRtcFlagStealthMode);
} else {
furi_hal_rtc_reset_flag(FuriHalRtcFlagStealthMode);
}
view_port_enabled_set(desktop->stealth_mode_icon_viewport, enabled);
desktop->in_transition = false;
}
Desktop* desktop_alloc() {
Desktop* desktop = malloc(sizeof(Desktop));
@@ -247,6 +264,18 @@ Desktop* desktop_alloc() {
view_port_enabled_set(desktop->dummy_mode_icon_viewport, false);
gui_add_view_port(desktop->gui, desktop->dummy_mode_icon_viewport, GuiLayerStatusBarLeft);
// Stealth mode icon
desktop->stealth_mode_icon_viewport = view_port_alloc();
view_port_set_width(desktop->stealth_mode_icon_viewport, icon_get_width(&I_Muted_8x8));
view_port_draw_callback_set(
desktop->stealth_mode_icon_viewport, desktop_stealth_mode_icon_draw_callback, desktop);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode)) {
view_port_enabled_set(desktop->stealth_mode_icon_viewport, true);
} else {
view_port_enabled_set(desktop->stealth_mode_icon_viewport, false);
}
gui_add_view_port(desktop->gui, desktop->stealth_mode_icon_viewport, GuiLayerStatusBarLeft);
// Special case: autostart application is already running
desktop->loader = furi_record_open(RECORD_LOADER);
if(loader_is_locked(desktop->loader) &&

View File

@@ -59,6 +59,7 @@ struct Desktop {
ViewPort* lock_icon_viewport;
ViewPort* dummy_mode_icon_viewport;
ViewPort* stealth_mode_icon_viewport;
AnimationManager* animation_manager;
@@ -79,3 +80,4 @@ void desktop_free(Desktop* desktop);
void desktop_lock(Desktop* desktop);
void desktop_unlock(Desktop* desktop);
void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled);
void desktop_set_stealth_mode_state(Desktop* desktop, bool enabled);

View File

@@ -27,6 +27,8 @@ void desktop_scene_lock_menu_on_enter(void* context) {
desktop_lock_menu_set_callback(desktop->lock_menu, desktop_scene_lock_menu_callback, desktop);
desktop_lock_menu_set_pin_state(desktop->lock_menu, desktop->settings.pin_code.length > 0);
desktop_lock_menu_set_dummy_mode_state(desktop->lock_menu, desktop->settings.dummy_mode);
desktop_lock_menu_set_stealth_mode_state(
desktop->lock_menu, furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode));
desktop_lock_menu_set_idx(desktop->lock_menu, 0);
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdLockMenu);
@@ -78,6 +80,16 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
scene_manager_search_and_switch_to_previous_scene(
desktop->scene_manager, DesktopSceneMain);
break;
case DesktopLockMenuEventStealthModeOn:
desktop_set_stealth_mode_state(desktop, true);
scene_manager_search_and_switch_to_previous_scene(
desktop->scene_manager, DesktopSceneMain);
break;
case DesktopLockMenuEventStealthModeOff:
desktop_set_stealth_mode_state(desktop, false);
scene_manager_search_and_switch_to_previous_scene(
desktop->scene_manager, DesktopSceneMain);
break;
default:
break;
}

View File

@@ -39,6 +39,8 @@ typedef enum {
DesktopLockMenuEventPinLock,
DesktopLockMenuEventDummyModeOn,
DesktopLockMenuEventDummyModeOff,
DesktopLockMenuEventStealthModeOn,
DesktopLockMenuEventStealthModeOff,
DesktopAnimationEventCheckAnimation,
DesktopAnimationEventNewIdleAnimation,

View File

@@ -7,7 +7,7 @@
typedef enum {
DesktopLockMenuIndexLock,
DesktopLockMenuIndexPinLock,
DesktopLockMenuIndexStealth,
DesktopLockMenuIndexDummy,
DesktopLockMenuIndexTotalCount
@@ -39,6 +39,14 @@ void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool
true);
}
void desktop_lock_menu_set_stealth_mode_state(DesktopLockMenuView* lock_menu, bool stealth_mode) {
with_view_model(
lock_menu->view,
DesktopLockMenuViewModel * model,
{ model->stealth_mode = stealth_mode; },
true);
}
void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) {
furi_assert(idx < DesktopLockMenuIndexTotalCount);
with_view_model(
@@ -58,11 +66,11 @@ void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) {
if(i == DesktopLockMenuIndexLock) {
str = "Lock";
} else if(i == DesktopLockMenuIndexPinLock) {
if(m->pin_is_set) {
str = "Lock with PIN";
} else if(i == DesktopLockMenuIndexStealth) {
if(m->stealth_mode) {
str = "Sound Mode";
} else {
str = "Set PIN";
str = "Stealth Mode";
}
} else if(i == DesktopLockMenuIndexDummy) { //-V547
if(m->dummy_mode) {
@@ -93,6 +101,8 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) {
uint8_t idx = 0;
bool consumed = false;
bool dummy_mode = false;
bool stealth_mode = false;
bool pin_is_set = false;
bool update = false;
with_view_model(
@@ -120,14 +130,24 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) {
}
idx = model->idx;
dummy_mode = model->dummy_mode;
stealth_mode = model->stealth_mode;
pin_is_set = model->pin_is_set;
},
update);
if(event->key == InputKeyOk) {
if((idx == DesktopLockMenuIndexLock) && (event->type == InputTypeShort)) {
lock_menu->callback(DesktopLockMenuEventLock, lock_menu->context);
} else if((idx == DesktopLockMenuIndexPinLock) && (event->type == InputTypeShort)) {
lock_menu->callback(DesktopLockMenuEventPinLock, lock_menu->context);
if((idx == DesktopLockMenuIndexLock)) {
if((pin_is_set) && (event->type == InputTypeShort)) {
lock_menu->callback(DesktopLockMenuEventPinLock, lock_menu->context);
} else if((pin_is_set == false) && (event->type == InputTypeShort)) {
lock_menu->callback(DesktopLockMenuEventLock, lock_menu->context);
}
} else if(idx == DesktopLockMenuIndexStealth) {
if((stealth_mode == false) && (event->type == InputTypeShort)) {
lock_menu->callback(DesktopLockMenuEventStealthModeOn, lock_menu->context);
} else if((stealth_mode == true) && (event->type == InputTypeShort)) {
lock_menu->callback(DesktopLockMenuEventStealthModeOff, lock_menu->context);
}
} else if(idx == DesktopLockMenuIndexDummy) {
if((dummy_mode == false) && (event->type == InputTypeShort)) {
lock_menu->callback(DesktopLockMenuEventDummyModeOn, lock_menu->context);

View File

@@ -19,6 +19,7 @@ typedef struct {
uint8_t idx;
bool pin_is_set;
bool dummy_mode;
bool stealth_mode;
} DesktopLockMenuViewModel;
void desktop_lock_menu_set_callback(
@@ -29,6 +30,7 @@ void desktop_lock_menu_set_callback(
View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu);
void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is_set);
void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool dummy_mode);
void desktop_lock_menu_set_stealth_mode_state(DesktopLockMenuView* lock_menu, bool stealth_mode);
void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx);
DesktopLockMenuView* desktop_lock_menu_alloc();
void desktop_lock_menu_free(DesktopLockMenuView* lock_menu);

View File

@@ -154,6 +154,8 @@ Menu* menu_alloc() {
void menu_free(Menu* menu) {
furi_assert(menu);
menu_reset(menu);
with_view_model(
menu->view, MenuModel * model, { MenuItemArray_clear(model->items); }, false);
view_free(menu->view);
free(menu);
}

View File

@@ -20,9 +20,9 @@ static const uint8_t reset_sound_mask = 1 << 4;
static const uint8_t reset_display_mask = 1 << 5;
static const uint8_t reset_blink_mask = 1 << 6;
void notification_vibro_on();
void notification_vibro_on(bool force);
void notification_vibro_off();
void notification_sound_on(float freq, float volume);
void notification_sound_on(float freq, float volume, bool force);
void notification_sound_off();
uint8_t notification_settings_get_display_brightness(NotificationApp* app, uint8_t value);
@@ -141,17 +141,21 @@ uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app) {
}
// generics
void notification_vibro_on() {
furi_hal_vibro_on(true);
void notification_vibro_on(bool force) {
if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode) || force) {
furi_hal_vibro_on(true);
}
}
void notification_vibro_off() {
furi_hal_vibro_on(false);
}
void notification_sound_on(float freq, float volume) {
if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) {
furi_hal_speaker_start(freq, volume);
void notification_sound_on(float freq, float volume, bool force) {
if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode) || force) {
if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) {
furi_hal_speaker_start(freq, volume);
}
}
}
@@ -174,6 +178,8 @@ void notification_process_notification_message(
NotificationApp* app,
NotificationAppMessage* message) {
uint32_t notification_message_index = 0;
bool force_volume = false;
bool force_vibro = false;
const NotificationMessage* notification_message;
notification_message = (*message->sequence)[notification_message_index];
@@ -269,7 +275,7 @@ void notification_process_notification_message(
break;
case NotificationMessageTypeVibro:
if(notification_message->data.vibro.on) {
if(vibro_setting) notification_vibro_on();
if(vibro_setting) notification_vibro_on(force_vibro);
} else {
notification_vibro_off();
}
@@ -278,7 +284,8 @@ void notification_process_notification_message(
case NotificationMessageTypeSoundOn:
notification_sound_on(
notification_message->data.sound.frequency,
notification_message->data.sound.volume * speaker_volume_setting);
notification_message->data.sound.volume * speaker_volume_setting,
force_volume);
reset_mask |= reset_sound_mask;
break;
case NotificationMessageTypeSoundOff:
@@ -307,9 +314,11 @@ void notification_process_notification_message(
break;
case NotificationMessageTypeForceSpeakerVolumeSetting:
speaker_volume_setting = notification_message->data.forced_settings.speaker_volume;
force_volume = true;
break;
case NotificationMessageTypeForceVibroSetting:
vibro_setting = notification_message->data.forced_settings.vibro;
force_vibro = true;
break;
case NotificationMessageTypeForceDisplayBrightnessSetting:
display_brightness_setting =

View File

@@ -399,6 +399,18 @@ static void power_check_battery_level_change(Power* power) {
}
}
void power_trigger_ui_update(Power* power) {
DesktopSettings* settings = malloc(sizeof(DesktopSettings));
bool is_loaded = DESKTOP_SETTINGS_LOAD(settings);
if(is_loaded) {
power->displayBatteryPercentage = settings->displayBatteryPercentage;
} else {
power->displayBatteryPercentage = DISPLAY_BATTERY_BAR;
}
free(settings);
view_port_update(power->battery_view_port);
}
int32_t power_srv(void* p) {
UNUSED(p);
@@ -431,10 +443,6 @@ int32_t power_srv(void* p) {
// Update battery view port
if(need_refresh) {
DesktopSettings* settings = malloc(sizeof(DesktopSettings));
DESKTOP_SETTINGS_LOAD(settings);
power->displayBatteryPercentage = settings->displayBatteryPercentage;
free(settings);
view_port_update(power->battery_view_port);
}

View File

@@ -94,6 +94,12 @@ bool power_is_battery_healthy(Power* power);
*/
void power_enable_low_battery_level_notification(Power* power, bool enable);
/** Trigger UI update for changing battery layout
*
* @param power Power instance
*/
void power_trigger_ui_update(Power* power);
#ifdef __cplusplus
}
#endif

View File

@@ -76,6 +76,7 @@ struct RpcSession {
RpcBufferIsEmptyCallback buffer_is_empty_callback;
RpcSessionClosedCallback closed_callback;
RpcSessionTerminatedCallback terminated_callback;
RpcOwner owner;
void* context;
};
@@ -83,6 +84,11 @@ struct Rpc {
FuriMutex* busy_mutex;
};
RpcOwner rpc_session_get_owner(RpcSession* session) {
furi_assert(session);
return session->owner;
}
static void rpc_close_session_process(const PB_Main* request, void* context) {
furi_assert(request);
furi_assert(context);
@@ -348,7 +354,7 @@ static void rpc_session_free_callback(FuriThreadState thread_state, void* contex
}
}
RpcSession* rpc_session_open(Rpc* rpc) {
RpcSession* rpc_session_open(Rpc* rpc, RpcOwner owner) {
furi_assert(rpc);
RpcSession* session = malloc(sizeof(RpcSession));
@@ -357,6 +363,7 @@ RpcSession* rpc_session_open(Rpc* rpc) {
session->rpc = rpc;
session->terminate = false;
session->decode_error = false;
session->owner = owner;
RpcHandlerDict_init(session->handlers);
session->decoded_message = malloc(sizeof(PB_Main));

View File

@@ -30,6 +30,21 @@ typedef void (*RpcSessionClosedCallback)(void* context);
* and all operations were finished */
typedef void (*RpcSessionTerminatedCallback)(void* context);
/** RPC owner */
typedef enum {
RpcOwnerUnknown = 0,
RpcOwnerBle,
RpcOwnerUsb,
RpcOwnerCount,
} RpcOwner;
/** Get RPC session owner
*
* @param session pointer to RpcSession descriptor
* @return session owner
*/
RpcOwner rpc_session_get_owner(RpcSession* session);
/** Open RPC session
*
* USAGE:
@@ -44,10 +59,11 @@ typedef void (*RpcSessionTerminatedCallback)(void* context);
*
*
* @param rpc instance
* @param owner owner of session
* @return pointer to RpcSession descriptor, or
* NULL if RPC is busy and can't open session now
*/
RpcSession* rpc_session_open(Rpc* rpc);
RpcSession* rpc_session_open(Rpc* rpc, RpcOwner owner);
/** Close RPC session
* It is guaranteed that no callbacks will be called

View File

@@ -47,7 +47,7 @@ void rpc_cli_command_start_session(Cli* cli, FuriString* args, void* context) {
FURI_LOG_D(TAG, "Free memory %lu", mem_before);
furi_hal_usb_lock();
RpcSession* rpc_session = rpc_session_open(rpc);
RpcSession* rpc_session = rpc_session_open(rpc, RpcOwnerUsb);
if(rpc_session == NULL) {
printf("Session start error\r\n");
furi_hal_usb_unlock();

View File

@@ -2,6 +2,7 @@
#include "rpc_i.h"
#include "gui.pb.h"
#include <gui/gui_i.h>
#include <assets_icons.h>
#define TAG "RpcGui"
@@ -31,6 +32,8 @@ typedef struct {
uint32_t input_key_counter[InputKeyMAX];
uint32_t input_counter;
ViewPort* rpc_session_active_viewport;
} RpcGuiSystem;
static const PB_Gui_ScreenOrientation rpc_system_gui_screen_orientation_map[] = {
@@ -352,6 +355,12 @@ static void rpc_system_gui_virtual_display_frame_process(const PB_Main* request,
(void)session;
}
static void rpc_active_session_icon_draw_callback(Canvas* canvas, void* context) {
UNUSED(context);
furi_assert(canvas);
canvas_draw_icon(canvas, 0, 0, &I_Rpc_active_7x8);
}
void* rpc_system_gui_alloc(RpcSession* session) {
furi_assert(session);
@@ -359,6 +368,18 @@ void* rpc_system_gui_alloc(RpcSession* session) {
rpc_gui->gui = furi_record_open(RECORD_GUI);
rpc_gui->session = session;
// Active session icon
rpc_gui->rpc_session_active_viewport = view_port_alloc();
view_port_set_width(rpc_gui->rpc_session_active_viewport, icon_get_width(&I_Rpc_active_7x8));
view_port_draw_callback_set(
rpc_gui->rpc_session_active_viewport, rpc_active_session_icon_draw_callback, session);
if(rpc_session_get_owner(rpc_gui->session) != RpcOwnerBle) {
view_port_enabled_set(rpc_gui->rpc_session_active_viewport, true);
} else {
view_port_enabled_set(rpc_gui->rpc_session_active_viewport, false);
}
gui_add_view_port(rpc_gui->gui, rpc_gui->rpc_session_active_viewport, GuiLayerStatusBarLeft);
RpcHandler rpc_handler = {
.message_handler = NULL,
.decode_submessage = NULL,
@@ -399,6 +420,9 @@ void rpc_system_gui_free(void* context) {
rpc_gui->virtual_display_not_empty = false;
}
gui_remove_view_port(rpc_gui->gui, rpc_gui->rpc_session_active_viewport);
view_port_free(rpc_gui->rpc_session_active_viewport);
if(rpc_gui->is_streaming) {
rpc_gui->is_streaming = false;
// Remove GUI framebuffer callback
@@ -415,4 +439,4 @@ void rpc_system_gui_free(void* context) {
}
furi_record_close(RECORD_GUI);
free(rpc_gui);
}
}

View File

@@ -3,6 +3,7 @@
#include "../desktop_settings_app.h"
#include "desktop_settings_scene.h"
#include <power/power_service/power.h>
#define SCENE_EVENT_SELECT_FAVORITE_PRIMARY 0
#define SCENE_EVENT_SELECT_FAVORITE_SECONDARY 1
@@ -169,4 +170,9 @@ void desktop_settings_scene_start_on_exit(void* context) {
DesktopSettingsApp* app = context;
variable_item_list_reset(app->variable_item_list);
DESKTOP_SETTINGS_SAVE(&app->settings);
// Trigger UI update in case we changed battery layout
Power* power = furi_record_open(RECORD_POWER);
power_trigger_ui_update(power);
furi_record_close(RECORD_POWER);
}

View File

@@ -163,18 +163,33 @@ static NotificationAppSettings* alloc_settings() {
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, backlight_text[value_index]);
item = variable_item_list_add(
app->variable_item_list, "Volume", VOLUME_COUNT, volume_changed, app);
value_index =
value_index_float(app->notification->settings.speaker_volume, volume_value, VOLUME_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, volume_text[value_index]);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode)) {
item = variable_item_list_add(app->variable_item_list, "Volume", 1, NULL, app);
value_index = 0;
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, "Stealth");
} else {
item = variable_item_list_add(
app->variable_item_list, "Volume", VOLUME_COUNT, volume_changed, app);
value_index = value_index_float(
app->notification->settings.speaker_volume, volume_value, VOLUME_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, volume_text[value_index]);
}
item =
variable_item_list_add(app->variable_item_list, "Vibro", VIBRO_COUNT, vibro_changed, app);
value_index = value_index_bool(app->notification->settings.vibro_on, vibro_value, VIBRO_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, vibro_text[value_index]);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode)) {
item = variable_item_list_add(app->variable_item_list, "Vibro", 1, NULL, app);
value_index = 0;
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, "Stealth");
} else {
item = variable_item_list_add(
app->variable_item_list, "Vibro", VIBRO_COUNT, vibro_changed, app);
value_index =
value_index_bool(app->notification->settings.vibro_on, vibro_value, VIBRO_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, vibro_text[value_index]);
}
app->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(app->view_dispatcher);

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -1,7 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 21st Mar, 2023
# Last Checked 29th Mar, 2023
# Last Updated 14th Apr, 2023
# Last Checked 14th Apr, 2023
#
name: POWER
type: raw
@@ -1686,3 +1686,57 @@ type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1373 348 1310 376 463 1190 1318 400 1286 401 439 1244 442 1244 1288 400 465 1218 468 1218 468 1219 467 7970 1307 404 1281 405 435 1252 1281 406 1280 406 434 1252 434 1252 1281 406 434 1253 434 1252 434 1252 434 8000 1280 406 1281 406 434 1252 1281 406 1280 406 434 1252 434 1252 1281 406 434 1253 433 1253 433 1253 434 8000 1280 406 1280 406 434 1253 1280 406 1280 406 434 1253 433 1253 1280 406 434 1253 433 1253 433 1253 433 8001 1279 406 1280 406 434 1253 1280 407 1279 407 433 1253 434 1253 1280 407 433 1253 433 1253 433 1253 433 8001 1279 407 1279 407 433 1253 1280 407 1280 407 433 1253 433 1253 1280 407 433 1253 433 1253 434 1253 433
# OFF
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3827 1854 505 433 507 1382 506 434 506 1383 505 434 506 1410 478 433 507 1381 507 433 507 1383 505 435 505 1382 505 1383 505 435 505 1382 506 435 505 1383 505 1382 506 1384 504 1381 507 434 506 434 506 1382 506 1382 506 432 508 434 506 436 504 433 507 1382 506 435 505 434 506 436 504 1381 507 1383 505 434 506 1382 506 1381 507 434 506 1381 507 1381 507 1383 505 435 505 434 506 435 505 433 507 1383 505 435 505 435 505 434 506 1381 507 433 507 435 505 434 506 1382 506 433 507 434 506 433 507 438 502 434 506 433 507 434 506 434 506 432 508 435 505 434 506 433 507 433 507 1387 501 435 505 436 504 433 507 433 507 435 505 433 507 434 506 434 506 435 505 435 505 432 508 1410 478 461 479 432 508 435 505 434 506 433 507 436 504 434 506 434 506 433 507 435 505 1383 505 435 505 1381 507 1381 507 1382 506 1382 506 1381 507 435 505 433 507 433 507 461 478 1383 505 433 507 434 506
#
name: TEMP-
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3778 1905 506 434 506 1381 507 436 504 1381 507 435 505 1382 506 432 508 1380 508 433 507 1381 507 432 508 1380 508 1381 507 432 508 1380 508 432 508 1380 508 1380 508 1380 508 1380 508 433 507 432 508 1380 508 1380 508 432 508 431 509 432 508 433 507 1380 508 432 508 432 508 431 509 433 507 1380 508 434 506 1380 508 1380 508 434 506 1381 507 1380 508 1380 508 433 507 431 509 433 507 1381 507 1381 507 432 508 431 509 431 509 1381 507 431 509 432 508 432 508 1381 507 431 509 432 508 432 508 432 508 432 508 432 508 435 505 432 508 432 508 431 509 432 508 432 508 434 506 1379 509 432 508 432 508 433 507 431 509 433 507 432 508 433 507 432 508 432 508 432 508 431 509 1380 508 432 508 432 508 1380 508 431 509 433 507 432 508 432 508 432 508 431 509 432 508 1381 507 431 509 1382 506 1380 508 1380 508 1380 508 1380 507 434 506 433 507 433 507 431 509 1380 508 1380 508 432 508
#
name: TEMP+
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3828 1855 504 431 508 1382 506 434 506 1382 506 434 506 1381 507 432 508 1381 507 434 506 1381 560 381 506 1381 507 1410 478 433 507 1382 506 436 504 1381 507 1382 506 1409 479 1382 506 433 507 433 507 1381 507 1383 505 435 505 434 506 432 508 433 507 1381 507 433 507 435 505 432 508 1381 507 1382 506 433 507 1382 506 1380 508 433 507 1382 506 1379 509 1381 507 432 508 433 507 433 507 1381 507 1380 508 433 507 433 507 432 508 1380 508 432 508 432 508 434 506 1380 508 432 508 432 508 432 508 432 508 434 506 434 506 433 507 433 507 434 506 432 508 433 507 432 508 435 505 1383 505 433 507 433 507 434 506 433 507 433 507 432 508 433 507 434 506 433 507 433 507 432 508 1382 506 432 508 431 509 1381 507 433 507 434 506 434 506 432 508 433 507 434 506 433 507 1380 508 431 509 1381 507 1409 479 1382 506 1383 505 1381 507 435 505 433 507 433 507 1382 506 1380 508 1382 506 433 507
#
name: MODE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3778 1903 508 432 508 1380 508 431 509 1379 509 430 510 1379 509 431 509 1382 506 432 508 1378 510 431 509 1379 509 1381 507 431 509 1379 509 432 508 1379 509 1379 509 1380 508 1381 507 431 509 431 509 1380 508 1379 509 430 510 431 509 431 509 432 508 1379 509 430 510 432 508 431 508 1379 509 430 510 1379 509 1381 507 430 509 432 508 431 509 431 509 1378 510 431 509 431 509 431 509 1380 508 1378 510 432 508 430 510 1379 509 1380 508 431 509 432 508 432 508 1379 509 432 508 431 509 431 509 432 508 431 509 431 509 431 508 431 509 432 508 431 509 431 509 431 509 431 509 1381 507 430 510 431 509 431 509 431 509 431 509 431 509 431 509 430 510 431 509 431 509 432 508 1378 510 431 509 431 509 430 510 431 509 432 508 431 509 431 509 430 510 431 509 431 509 1379 509 431 509 1379 509 1380 508 1379 509 1379 509 1379 509 432 508 431 509 431 509 1379 509 431 509 431 509 1379 509
#
name: POWER
type: parsed
protocol: NEC
address: 04 00 00 00
command: 04 00 00 00
#
name: TEMP+
type: parsed
protocol: NEC
address: 04 00 00 00
command: 05 00 00 00
#
name: TEMP-
type: parsed
protocol: NEC
address: 04 00 00 00
command: 01 00 00 00
#
name: MODE
type: parsed
protocol: NEC
address: 04 00 00 00
command: 0D 00 00 00
#
name: TIMER
type: parsed
protocol: NEC
address: 04 00 00 00
command: 00 00 00 00

View File

@@ -1,7 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 29th Mar, 2023
# Last Checked 29th Mar, 2023
# Last Updated 14th Apr, 2023
# Last Checked 14th Apr, 2023
#
name: POWER
type: parsed
@@ -2134,3 +2134,45 @@ type: raw
frequency: 38000
duty_cycle: 0.330000
data: 2701 861 496 420 445 444 444 885 446 871 892 441 444 441 444 441 471 415 471 415 470 417 467 444 440 446 883 891 436 449 437 449 437 450 436 450 436 449 883 448 437 451 436 894 436 450 436 450 436 450 436 450 436 450 882 449 436 894 883 116552 2698 862 469 448 438 449 438 894 437 880 884 448 437 449 437 448 438 449 437 449 437 449 437 449 437 449 884 890 437 449 437 449 437 449 437 449 437 449 884 448 437 450 437 893 437 449 437 449 437 449 437 449 437 449 884 448 436 894 883
#
name: VOL+
type: parsed
protocol: NECext
address: 10 E7 00 00
command: 3C C3 00 00
#
name: VOL-
type: parsed
protocol: NECext
address: 10 E7 00 00
command: 4D B2 00 00
#
name: POWER
type: parsed
protocol: Kaseikyo
address: 52 54 32 00
command: 83 00 00 00
#
name: MUTE
type: parsed
protocol: Kaseikyo
address: 52 54 32 00
command: 86 00 00 00
#
name: VOL+
type: parsed
protocol: Kaseikyo
address: 52 54 32 00
command: 84 00 00 00
#
name: VOL-
type: parsed
protocol: Kaseikyo
address: 52 54 32 00
command: 85 00 00 00
#
name: POWER
type: parsed
protocol: NEC
address: 00 00 00 00
command: 46 00 00 00

View File

@@ -1,7 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 15th Feb, 2023
# Last Checked 29th Mar, 2023
# Last Updated 14th Apr, 2023
# Last Checked 14th Apr, 2023
#
name: POWER
type: raw
@@ -1419,3 +1419,81 @@ type: parsed
protocol: NECext
address: 80 DE 00 00
command: 10 EF 00 00
#
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 4640 4393 562 1442 562 1443 562 1443 537 1470 535 1468 562 1444 562 2398 562 1444 562 1446 560 2424 535 1470 535 2425 534 1472 533 1473 533 2427 533 1474 531 1473 4577 4456 531 1473 531 1474 532 1474 531 1474 532 1474 531 1474 531 2429 531 1474 531 1474 531 2429 531 1474 531 2429 531 1474 531 1474 531 2429 531 1474 531 14007 9125 2259 530
#
name: SPEED+
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 4609 4425 563 1441 563 1442 563 1442 538 1469 537 1469 561 1444 562 2400 560 1470 535 1470 536 1470 536 2424 536 1470 535 1471 534 1472 533 2427 533 2427 533 1472 4580 4454 531 1472 533 1474 532 1474 531 1474 532 1474 532 1474 532 2428 532 1474 532 1474 532 1474 532 2428 532 1474 532 1474 532 1474 532 2428 532 2429 532 14008 9127 2258 528 50213 9131 2253 532
#
name: MODE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 4607 4424 563 1441 563 1443 563 1444 536 1469 537 1469 537 1496 534 2399 561 1470 535 2424 536 1470 536 1470 535 2424 535 1471 534 1472 534 1472 533 2427 533 1472 4579 4455 531 1472 532 1474 532 1474 532 1474 532 1474 532 1474 532 2429 531 1474 532 2428 532 1474 532 1474 532 2429 532 1474 532 1474 532 1474 532 2428 532 14007 9125 2258 530
#
name: TIMER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 4604 4427 561 1442 562 1443 561 1444 537 1469 536 1469 562 1445 561 2399 560 1446 559 2424 534 1472 533 2426 533 1473 532 2428 531 1475 531 1474 531 1474 531 1473 4575 4457 530 1473 531 1475 531 1475 530 1475 531 1475 531 1475 530 2429 531 1475 530 2429 530 1475 530 2430 530 1475 530 2429 531 1475 531 1475 531 1475 530 14008 9122 2260 530
#
name: ROTATE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 4582 4424 562 1442 562 1471 534 1471 509 1496 510 1496 534 1472 534 2424 536 1470 536 1470 536 1470 536 1470 535 2424 535 2425 534 2426 534 1472 533 1473 533 1472 4581 4453 532 1472 532 1473 533 1473 533 1473 533 1473 533 1473 533 2428 532 1473 532 1473 532 1474 532 1474 532 2428 533 2428 532 2428 532 1474 532 1474 532
#
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1369 311 1327 312 498 1162 1286 355 1285 362 457 1221 458 1221 458 1221 458 1222 457 1221 458 1219 1312 6796 1310 330 1282 356 454 1219 1281 360 1280 367 452 1227 452 1227 452 1227 452 1227 452 1227 452 1225 1280 6815 1280 359 1279 359 451 1220 1280 361 1279 368 451 1228 451 1228 451 1228 451 1228 451 1228 451 1226 1279 6827 1279 382 1256 382 428 1245 1255 384 1256 391 427 1251 428 1252 426 1252 427 1252 427 1252 427 1250 1255 6838 1255 383 1255 383 426 1245 1255 385 1255 392 426 1252 427 1252 426 1252 426 1252 427 1252 426 1250 1255 6849 1255 383 1255 383 426 1245 1255 385 1254 392 426 1252 426 1252 426 1252 426 1252 426 1252 426 1250 1254 6835 1254 383 1254 383 426 1245 1254 385 1254 392 426 1252 426 1252 426 1252 426 1252 426 1252 426 1250 1254 6852 1254 383 1254 384 425 1245 1254 386 1253 392 426 1253 425 1252 426 1252 426 1253 425 1253 425 1251 1253 6835 1253 384 1253 384 425 1245 1253 386 1253 393 425 1252 425 1253 425 1253 425 1253 425 1253 425 1251 1253 6852 1252 384 1253 384 425 1246 1252 386 1253 393 425 1253 424 1253 425 1253 425 1254 424 1253 425 1252 1252 6835 1253 385 1252 385 424 1247 1252 387 1252 394 424 1254 424 1254 424 1254 424 1254 424 1254 424 1252 1251 6850 1251 386 1251 386 423 1248 1251 388 1250 395 423 1255 422 1256 422 1279 399 1280 398 1279 399 1277 1227 6862 1226 411 1226 411 398 1273 1226 413 1226 420 397 1280 398 1279 398 1280 397 1280 398 1280 398 1278 1226 6892 1226 411 1225 411 397 1273 1225 413 1225 420 397 1280 397 1280 398 1280 397 1280 397 1280 397 1279 1224
#
name: SPEED+
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1308 332 1305 332 479 1190 1309 333 1307 364 455 1199 479 1198 481 1198 480 1198 480 1197 1331 339 480 7657 1306 332 1305 332 479 1194 1304 335 1305 342 478 1201 477 1201 478 1201 477 1201 478 1199 1305 342 478 7647 1305 333 1304 333 478 1194 1304 335 1304 342 477 1201 477 1201 478 1201 477 1201 477 1199 1305 342 478 7660 1303 334 1304 333 478 1194 1304 336 1303 343 477 1202 477 1202 476 1202 477 1202 476 1200 1304 343 477 7647 1303 334 1304 334 476 1195 1303 336 1303 343 476 1202 476 1202 476 1202 476 1202 476 1200 1303 343 476 7659 1302 335 1302 335 476 1196 1302 337 1302 344 475 1203 475 1203 475 1203 475 1203 475 1201 1302 344 476 7646 1302 335 1300 338 474 1197 1300 338 1301 345 474 1204 474 1204 474 1204 449 1229 449 1227 1275 370 449 7690 1275 362 1275 361 449 1222 1275 364 1275 371 448 1230 448 1230 448 1231 447 1232 446 1229 1274 372 447
#
name: ROTATE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1338 312 1380 310 446 1133 1313 356 1284 362 457 1221 457 1219 1285 363 456 1221 457 1222 482 1196 482 7655 1282 356 1281 357 453 1219 1279 360 1279 367 452 1226 452 1224 1280 367 452 1226 452 1226 452 1226 452 7671 1279 358 1279 358 452 1219 1279 360 1279 367 452 1227 451 1225 1279 367 451 1227 451 1227 451 1227 451 7682 1279 359 1278 359 451 1220 1278 361 1278 368 451 1227 450 1225 1278 368 451 1227 451 1228 450 1228 450 7691 1277 360 1277 360 450 1221 1277 362 1277 368 450 1228 449 1226 1277 369 449 1229 449 1252 426 1252 426
#
name: TIMER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1338 311 1326 312 497 1134 1364 311 1276 361 457 1221 457 1220 457 1218 1283 361 456 1221 456 1221 457 7676 1285 351 1285 351 457 1213 1286 353 1285 360 457 1220 457 1220 457 1219 1285 361 456 1221 456 1222 481 7639 1283 353 1284 353 455 1216 1283 356 1282 363 454 1223 455 1223 454 1221 1283 363 454 1223 454 1223 454 7676 1282 354 1282 354 454 1217 1282 356 1282 364 453 1223 454 1223 454 1221 1282 363 454 1224 453 1224 454 7681 1281 355 1281 355 453 1217 1281 357 1281 364 453 1225 452 1225 452 1222 1281 365 452 1225 452 1225 452
#
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3565 3379 984 2506 984 2505 985 797 900 2590 900 2590 926 2572 926 826 925 829 922 858 894 859 894 858 895 2604 894 859 894 859 894 2596 894 859 894 859 894 867 894 2596 894 2596 894 2596 894 2596 894 2596 894 867 894 40343 3530 3468 895 2596 894 2596 894 859 894 2596 894 2596 894 2604 894 859 894 859 894 859 894 859 894 859 894 2604 894 859 894 859 894 2596 894 859 894 859 894 867 894 2596 894 2596 894 2596 894 2596 895 2596 894 866 895
#
name: SPEED+
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3595 3377 930 2561 929 2561 929 853 900 2591 899 2590 900 2597 901 2590 925 2565 924 2567 922 2570 920 2596 894 866 895 858 895 858 895 2596 894 858 895 859 894 866 895 858 895 858 895 858 895 859 894 858 895 2604 894 40343 3533 3467 895 2595 895 2596 894 858 895 2596 894 2596 894 2604 895 2596 894 2596 894 2596 894 2596 894 2596 894 867 894 859 894 859 894 2596 894 859 894 859 894 867 894 859 894 859 894 859 894 859 894 859 894 2605 893 40319 3533 3442 920 2595 895 2596 894 858 895 2596 894 2596 894 2604 894 2596 894 2596 894 2596 894 2596 894 2596 894 867 894 859 894 859 894 2596 894 859 894 859 894 867 894 859 894 859 894 859 894 859 894 859 894 2604 894
#
name: ROTATE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3594 3380 981 2505 930 2560 930 853 900 2590 900 2590 900 2598 900 2589 900 853 924 2568 921 2571 919 2596 894 867 894 859 894 859 894 2596 894 859 894 859 894 867 894 859 894 2596 894 859 894 859 894 859 894 2604 894 40335 3532 3467 895 2596 894 2596 895 859 894 2596 894 2596 894 2605 894 2596 894 859 894 2596 894 2597 894 2596 894 867 894 859 894 859 894 2596 894 859 894 859 894 867 894 859 894 2597 894 859 894 859 894 859 894 2605 893
#
name: TIMER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 3534 3439 954 2505 985 2535 955 798 954 2535 899 2591 899 2599 899 853 925 2566 924 2567 922 2596 894 2596 894 867 894 859 894 860 893 2597 894 859 894 859 894 867 894 2597 893 859 894 859 894 860 893 859 894 2605 894 40336 3531 3469 894 2597 893 2597 893 859 894 2597 893 2597 893 2605 893 860 893 2597 893 2597 893 2597 894 2597 893 868 893 860 893 860 893 2597 893 860 893 860 893 868 893 2597 893 860 893 860 893 860 893 860 893 2605 893

View File

@@ -1,7 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 07th Mar, 2023
# Last Checked 29th Mar, 2023
# Last Updated 14th Apr, 2023
# Last Checked 14th Apr, 2023
#
# ON
name: POWER
@@ -874,3 +874,15 @@ type: raw
frequency: 38000
duty_cycle: 0.330000
data: 9035 4437 563 548 563 548 563 522 594 1645 591 1639 592 518 593 548 563 552 563 1640 592 548 563 553 562 1668 564 524 592 1642 594 1674 562 1673 563 1639 593 548 563 552 564 1669 562 548 563 520 615 529 586 1645 587 529 587 1650 586 1646 586 529 586 1650 586 1649 587 1646 586 524 587 524 587 524 587 524 587 525 643 467 644 440 671 467 644 472 643 1592 644 1593 643 1593 642 1594 641 1594 587 1649 585 1651 563 1682 562 14430 9008 2205 562
#
name: VOL+
type: parsed
protocol: NECext
address: 84 F4 00 00
command: 2C D3 00 00
#
name: VOL-
type: parsed
protocol: NECext
address: 84 F4 00 00
command: 2F D0 00 00

View File

@@ -1,7 +1,7 @@
Filetype: IR library file
Version: 1
# Last Updated 07th Mar, 2023
# Last Checked 29th Mar, 2023
# Last Checked 14th Apr, 2023
#
name: POWER
type: parsed

View File

@@ -53,15 +53,17 @@ Check out `documentation/fbt.md` for details on building and flashing firmware.
### Compile everything for development
```sh
.\fbt.cmd FIRMWARE_APP_SET=debug_pack updater_package
./fbt.cmd FIRMWARE_APP_SET=debug_pack updater_package
```
### Compile everything for release + get updater package to update from microSD card
```sh
.\fbt.cmd COMPACT=1 DEBUG=0 updater_package
./fbt.cmd COMPACT=1 DEBUG=0 updater_package
```
**You may need to change** `/` **to** `\` **in front of fbt command (Only for Windows)!**
Check `dist/` for build outputs.
Use **`flipper-z-{target}-update-{suffix}.tgz`** to flash your device.

View File

@@ -0,0 +1,23 @@
# Reading RAW RFID data
Flipper Zero has the option to read RAW data from 125 kHz cards that allows you to record the card's data and save it, similar to how a dictaphone records sound.
To use this function, you need to activate the Debug mode on your Flipper Zero by doing the following:
1. Go to **Main Menu****Settings****System**.
2. Set **Debug** to **ON**.
Once the Debug mode is activated on your Flipper Zero, you can read RAW data from 125 kHz RFID cards:
1. Go to **Main Menu****125 kHz RFID****Extra Actions**.
2. Select **RAW RFID** data and name the raw file.
3. Read instructions and press **OK**.
4. Apply the card to Flipper Zero's back.
5. Once the reading is finished, press **OK**.
Two files with data (with ASK and PSK modulations) will be saved in the `lfrfid` folder on the microSD card. Now, you can share it and the card's photo with developers by creating an issue on GitHub.

View File

@@ -20,7 +20,7 @@ DIST_SUFFIX = "local"
COPRO_OB_DATA = "scripts/ob.data"
# Must match lib/STM32CubeWB version
COPRO_CUBE_VERSION = "1.13.3"
COPRO_CUBE_VERSION = "1.16.0"
COPRO_CUBE_DIR = "lib/STM32CubeWB"

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,22.0,,
Version,+,23.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -176,17 +176,17 @@ Header,+,lib/toolbox/tar/tar_archive.h,,
Header,+,lib/toolbox/value_index.h,,
Header,+,lib/toolbox/version.h,,
Function,-,LL_ADC_CommonDeInit,ErrorStatus,ADC_Common_TypeDef*
Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, LL_ADC_CommonInitTypeDef*"
Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, const LL_ADC_CommonInitTypeDef*"
Function,-,LL_ADC_CommonStructInit,void,LL_ADC_CommonInitTypeDef*
Function,-,LL_ADC_DeInit,ErrorStatus,ADC_TypeDef*
Function,-,LL_ADC_INJ_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_INJ_InitTypeDef*"
Function,-,LL_ADC_INJ_Init,ErrorStatus,"ADC_TypeDef*, const LL_ADC_INJ_InitTypeDef*"
Function,-,LL_ADC_INJ_StructInit,void,LL_ADC_INJ_InitTypeDef*
Function,-,LL_ADC_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_InitTypeDef*"
Function,-,LL_ADC_REG_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_REG_InitTypeDef*"
Function,-,LL_ADC_Init,ErrorStatus,"ADC_TypeDef*, const LL_ADC_InitTypeDef*"
Function,-,LL_ADC_REG_Init,ErrorStatus,"ADC_TypeDef*, const LL_ADC_REG_InitTypeDef*"
Function,-,LL_ADC_REG_StructInit,void,LL_ADC_REG_InitTypeDef*
Function,-,LL_ADC_StructInit,void,LL_ADC_InitTypeDef*
Function,-,LL_COMP_DeInit,ErrorStatus,COMP_TypeDef*
Function,+,LL_COMP_Init,ErrorStatus,"COMP_TypeDef*, LL_COMP_InitTypeDef*"
Function,+,LL_COMP_Init,ErrorStatus,"COMP_TypeDef*, const LL_COMP_InitTypeDef*"
Function,-,LL_COMP_StructInit,void,LL_COMP_InitTypeDef*
Function,-,LL_CRC_DeInit,ErrorStatus,CRC_TypeDef*
Function,-,LL_CRS_DeInit,ErrorStatus,
@@ -199,16 +199,16 @@ Function,-,LL_EXTI_StructInit,void,LL_EXTI_InitTypeDef*
Function,-,LL_GPIO_DeInit,ErrorStatus,GPIO_TypeDef*
Function,+,LL_GPIO_Init,ErrorStatus,"GPIO_TypeDef*, LL_GPIO_InitTypeDef*"
Function,-,LL_GPIO_StructInit,void,LL_GPIO_InitTypeDef*
Function,-,LL_I2C_DeInit,ErrorStatus,I2C_TypeDef*
Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, LL_I2C_InitTypeDef*"
Function,-,LL_I2C_DeInit,ErrorStatus,const I2C_TypeDef*
Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, const LL_I2C_InitTypeDef*"
Function,-,LL_I2C_StructInit,void,LL_I2C_InitTypeDef*
Function,-,LL_Init1msTick,void,uint32_t
Function,+,LL_LPTIM_DeInit,ErrorStatus,LPTIM_TypeDef*
Function,-,LL_LPTIM_Disable,void,LPTIM_TypeDef*
Function,+,LL_LPTIM_Init,ErrorStatus,"LPTIM_TypeDef*, LL_LPTIM_InitTypeDef*"
Function,+,LL_LPTIM_Init,ErrorStatus,"LPTIM_TypeDef*, const LL_LPTIM_InitTypeDef*"
Function,-,LL_LPTIM_StructInit,void,LL_LPTIM_InitTypeDef*
Function,-,LL_LPUART_DeInit,ErrorStatus,USART_TypeDef*
Function,+,LL_LPUART_Init,ErrorStatus,"USART_TypeDef*, LL_LPUART_InitTypeDef*"
Function,-,LL_LPUART_DeInit,ErrorStatus,const USART_TypeDef*
Function,+,LL_LPUART_Init,ErrorStatus,"USART_TypeDef*, const LL_LPUART_InitTypeDef*"
Function,-,LL_LPUART_StructInit,void,LL_LPUART_InitTypeDef*
Function,-,LL_PKA_DeInit,ErrorStatus,PKA_TypeDef*
Function,-,LL_PKA_Init,ErrorStatus,"PKA_TypeDef*, LL_PKA_InitTypeDef*"
@@ -253,23 +253,23 @@ Function,+,LL_SPI_Init,ErrorStatus,"SPI_TypeDef*, LL_SPI_InitTypeDef*"
Function,-,LL_SPI_StructInit,void,LL_SPI_InitTypeDef*
Function,-,LL_SetFlashLatency,ErrorStatus,uint32_t
Function,+,LL_SetSystemCoreClock,void,uint32_t
Function,-,LL_TIM_BDTR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_BDTR_InitTypeDef*"
Function,-,LL_TIM_BDTR_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_BDTR_InitTypeDef*"
Function,-,LL_TIM_BDTR_StructInit,void,LL_TIM_BDTR_InitTypeDef*
Function,+,LL_TIM_DeInit,ErrorStatus,TIM_TypeDef*
Function,-,LL_TIM_ENCODER_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_ENCODER_InitTypeDef*"
Function,-,LL_TIM_DeInit,ErrorStatus,TIM_TypeDef*
Function,-,LL_TIM_ENCODER_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_ENCODER_InitTypeDef*"
Function,-,LL_TIM_ENCODER_StructInit,void,LL_TIM_ENCODER_InitTypeDef*
Function,-,LL_TIM_HALLSENSOR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_HALLSENSOR_InitTypeDef*"
Function,-,LL_TIM_HALLSENSOR_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_HALLSENSOR_InitTypeDef*"
Function,-,LL_TIM_HALLSENSOR_StructInit,void,LL_TIM_HALLSENSOR_InitTypeDef*
Function,-,LL_TIM_IC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, LL_TIM_IC_InitTypeDef*"
Function,-,LL_TIM_IC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, const LL_TIM_IC_InitTypeDef*"
Function,-,LL_TIM_IC_StructInit,void,LL_TIM_IC_InitTypeDef*
Function,+,LL_TIM_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_InitTypeDef*"
Function,+,LL_TIM_OC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, LL_TIM_OC_InitTypeDef*"
Function,+,LL_TIM_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_InitTypeDef*"
Function,+,LL_TIM_OC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, const LL_TIM_OC_InitTypeDef*"
Function,-,LL_TIM_OC_StructInit,void,LL_TIM_OC_InitTypeDef*
Function,-,LL_TIM_StructInit,void,LL_TIM_InitTypeDef*
Function,-,LL_USART_ClockInit,ErrorStatus,"USART_TypeDef*, LL_USART_ClockInitTypeDef*"
Function,-,LL_USART_ClockInit,ErrorStatus,"USART_TypeDef*, const LL_USART_ClockInitTypeDef*"
Function,-,LL_USART_ClockStructInit,void,LL_USART_ClockInitTypeDef*
Function,-,LL_USART_DeInit,ErrorStatus,USART_TypeDef*
Function,+,LL_USART_Init,ErrorStatus,"USART_TypeDef*, LL_USART_InitTypeDef*"
Function,-,LL_USART_DeInit,ErrorStatus,const USART_TypeDef*
Function,+,LL_USART_Init,ErrorStatus,"USART_TypeDef*, const LL_USART_InitTypeDef*"
Function,-,LL_USART_StructInit,void,LL_USART_InitTypeDef*
Function,-,LL_mDelay,void,uint32_t
Function,-,SystemCoreClockUpdate,void,
@@ -1596,7 +1596,8 @@ Function,-,rindex,char*,"const char*, int"
Function,+,rpc_session_close,void,RpcSession*
Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, TickType_t"
Function,+,rpc_session_get_available_size,size_t,RpcSession*
Function,+,rpc_session_open,RpcSession*,Rpc*
Function,+,rpc_session_get_owner,RpcOwner,RpcSession*
Function,+,rpc_session_open,RpcSession*,"Rpc*, RpcOwner"
Function,+,rpc_session_set_buffer_is_empty_callback,void,"RpcSession*, RpcBufferIsEmptyCallback"
Function,+,rpc_session_set_close_callback,void,"RpcSession*, RpcSessionClosedCallback"
Function,+,rpc_session_set_context,void,"RpcSession*, void*"
1 entry status name type params
2 Version + 22.0 23.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
176 Header + lib/toolbox/value_index.h
177 Header + lib/toolbox/version.h
178 Function - LL_ADC_CommonDeInit ErrorStatus ADC_Common_TypeDef*
179 Function - LL_ADC_CommonInit ErrorStatus ADC_Common_TypeDef*, LL_ADC_CommonInitTypeDef* ADC_Common_TypeDef*, const LL_ADC_CommonInitTypeDef*
180 Function - LL_ADC_CommonStructInit void LL_ADC_CommonInitTypeDef*
181 Function - LL_ADC_DeInit ErrorStatus ADC_TypeDef*
182 Function - LL_ADC_INJ_Init ErrorStatus ADC_TypeDef*, LL_ADC_INJ_InitTypeDef* ADC_TypeDef*, const LL_ADC_INJ_InitTypeDef*
183 Function - LL_ADC_INJ_StructInit void LL_ADC_INJ_InitTypeDef*
184 Function - LL_ADC_Init ErrorStatus ADC_TypeDef*, LL_ADC_InitTypeDef* ADC_TypeDef*, const LL_ADC_InitTypeDef*
185 Function - LL_ADC_REG_Init ErrorStatus ADC_TypeDef*, LL_ADC_REG_InitTypeDef* ADC_TypeDef*, const LL_ADC_REG_InitTypeDef*
186 Function - LL_ADC_REG_StructInit void LL_ADC_REG_InitTypeDef*
187 Function - LL_ADC_StructInit void LL_ADC_InitTypeDef*
188 Function - LL_COMP_DeInit ErrorStatus COMP_TypeDef*
189 Function + LL_COMP_Init ErrorStatus COMP_TypeDef*, LL_COMP_InitTypeDef* COMP_TypeDef*, const LL_COMP_InitTypeDef*
190 Function - LL_COMP_StructInit void LL_COMP_InitTypeDef*
191 Function - LL_CRC_DeInit ErrorStatus CRC_TypeDef*
192 Function - LL_CRS_DeInit ErrorStatus
199 Function - LL_GPIO_DeInit ErrorStatus GPIO_TypeDef*
200 Function + LL_GPIO_Init ErrorStatus GPIO_TypeDef*, LL_GPIO_InitTypeDef*
201 Function - LL_GPIO_StructInit void LL_GPIO_InitTypeDef*
202 Function - LL_I2C_DeInit ErrorStatus I2C_TypeDef* const I2C_TypeDef*
203 Function + LL_I2C_Init ErrorStatus I2C_TypeDef*, LL_I2C_InitTypeDef* I2C_TypeDef*, const LL_I2C_InitTypeDef*
204 Function - LL_I2C_StructInit void LL_I2C_InitTypeDef*
205 Function - LL_Init1msTick void uint32_t
206 Function + LL_LPTIM_DeInit ErrorStatus LPTIM_TypeDef*
207 Function - LL_LPTIM_Disable void LPTIM_TypeDef*
208 Function + LL_LPTIM_Init ErrorStatus LPTIM_TypeDef*, LL_LPTIM_InitTypeDef* LPTIM_TypeDef*, const LL_LPTIM_InitTypeDef*
209 Function - LL_LPTIM_StructInit void LL_LPTIM_InitTypeDef*
210 Function - LL_LPUART_DeInit ErrorStatus USART_TypeDef* const USART_TypeDef*
211 Function + LL_LPUART_Init ErrorStatus USART_TypeDef*, LL_LPUART_InitTypeDef* USART_TypeDef*, const LL_LPUART_InitTypeDef*
212 Function - LL_LPUART_StructInit void LL_LPUART_InitTypeDef*
213 Function - LL_PKA_DeInit ErrorStatus PKA_TypeDef*
214 Function - LL_PKA_Init ErrorStatus PKA_TypeDef*, LL_PKA_InitTypeDef*
253 Function - LL_SPI_StructInit void LL_SPI_InitTypeDef*
254 Function - LL_SetFlashLatency ErrorStatus uint32_t
255 Function + LL_SetSystemCoreClock void uint32_t
256 Function - LL_TIM_BDTR_Init ErrorStatus TIM_TypeDef*, LL_TIM_BDTR_InitTypeDef* TIM_TypeDef*, const LL_TIM_BDTR_InitTypeDef*
257 Function - LL_TIM_BDTR_StructInit void LL_TIM_BDTR_InitTypeDef*
258 Function + - LL_TIM_DeInit ErrorStatus TIM_TypeDef*
259 Function - LL_TIM_ENCODER_Init ErrorStatus TIM_TypeDef*, LL_TIM_ENCODER_InitTypeDef* TIM_TypeDef*, const LL_TIM_ENCODER_InitTypeDef*
260 Function - LL_TIM_ENCODER_StructInit void LL_TIM_ENCODER_InitTypeDef*
261 Function - LL_TIM_HALLSENSOR_Init ErrorStatus TIM_TypeDef*, LL_TIM_HALLSENSOR_InitTypeDef* TIM_TypeDef*, const LL_TIM_HALLSENSOR_InitTypeDef*
262 Function - LL_TIM_HALLSENSOR_StructInit void LL_TIM_HALLSENSOR_InitTypeDef*
263 Function - LL_TIM_IC_Init ErrorStatus TIM_TypeDef*, uint32_t, LL_TIM_IC_InitTypeDef* TIM_TypeDef*, uint32_t, const LL_TIM_IC_InitTypeDef*
264 Function - LL_TIM_IC_StructInit void LL_TIM_IC_InitTypeDef*
265 Function + LL_TIM_Init ErrorStatus TIM_TypeDef*, LL_TIM_InitTypeDef* TIM_TypeDef*, const LL_TIM_InitTypeDef*
266 Function + LL_TIM_OC_Init ErrorStatus TIM_TypeDef*, uint32_t, LL_TIM_OC_InitTypeDef* TIM_TypeDef*, uint32_t, const LL_TIM_OC_InitTypeDef*
267 Function - LL_TIM_OC_StructInit void LL_TIM_OC_InitTypeDef*
268 Function - LL_TIM_StructInit void LL_TIM_InitTypeDef*
269 Function - LL_USART_ClockInit ErrorStatus USART_TypeDef*, LL_USART_ClockInitTypeDef* USART_TypeDef*, const LL_USART_ClockInitTypeDef*
270 Function - LL_USART_ClockStructInit void LL_USART_ClockInitTypeDef*
271 Function - LL_USART_DeInit ErrorStatus USART_TypeDef* const USART_TypeDef*
272 Function + LL_USART_Init ErrorStatus USART_TypeDef*, LL_USART_InitTypeDef* USART_TypeDef*, const LL_USART_InitTypeDef*
273 Function - LL_USART_StructInit void LL_USART_InitTypeDef*
274 Function - LL_mDelay void uint32_t
275 Function - SystemCoreClockUpdate void
1596 Function + rpc_session_close void RpcSession*
1597 Function + rpc_session_feed size_t RpcSession*, uint8_t*, size_t, TickType_t
1598 Function + rpc_session_get_available_size size_t RpcSession*
1599 Function + rpc_session_open rpc_session_get_owner RpcSession* RpcOwner Rpc* RpcSession*
1600 Function + rpc_session_open RpcSession* Rpc*, RpcOwner
1601 Function + rpc_session_set_buffer_is_empty_callback void RpcSession*, RpcBufferIsEmptyCallback
1602 Function + rpc_session_set_close_callback void RpcSession*, RpcSessionClosedCallback
1603 Function + rpc_session_set_context void RpcSession*, void*

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,22.0,,
Version,+,23.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -213,17 +213,17 @@ Header,+,lib/toolbox/value_index.h,,
Header,+,lib/toolbox/version.h,,
Header,+,lib/u8g2/u8g2.h,,
Function,-,LL_ADC_CommonDeInit,ErrorStatus,ADC_Common_TypeDef*
Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, LL_ADC_CommonInitTypeDef*"
Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, const LL_ADC_CommonInitTypeDef*"
Function,-,LL_ADC_CommonStructInit,void,LL_ADC_CommonInitTypeDef*
Function,-,LL_ADC_DeInit,ErrorStatus,ADC_TypeDef*
Function,-,LL_ADC_INJ_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_INJ_InitTypeDef*"
Function,-,LL_ADC_INJ_Init,ErrorStatus,"ADC_TypeDef*, const LL_ADC_INJ_InitTypeDef*"
Function,-,LL_ADC_INJ_StructInit,void,LL_ADC_INJ_InitTypeDef*
Function,-,LL_ADC_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_InitTypeDef*"
Function,-,LL_ADC_REG_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_REG_InitTypeDef*"
Function,-,LL_ADC_Init,ErrorStatus,"ADC_TypeDef*, const LL_ADC_InitTypeDef*"
Function,-,LL_ADC_REG_Init,ErrorStatus,"ADC_TypeDef*, const LL_ADC_REG_InitTypeDef*"
Function,-,LL_ADC_REG_StructInit,void,LL_ADC_REG_InitTypeDef*
Function,-,LL_ADC_StructInit,void,LL_ADC_InitTypeDef*
Function,-,LL_COMP_DeInit,ErrorStatus,COMP_TypeDef*
Function,+,LL_COMP_Init,ErrorStatus,"COMP_TypeDef*, LL_COMP_InitTypeDef*"
Function,+,LL_COMP_Init,ErrorStatus,"COMP_TypeDef*, const LL_COMP_InitTypeDef*"
Function,-,LL_COMP_StructInit,void,LL_COMP_InitTypeDef*
Function,-,LL_CRC_DeInit,ErrorStatus,CRC_TypeDef*
Function,-,LL_CRS_DeInit,ErrorStatus,
@@ -236,16 +236,16 @@ Function,-,LL_EXTI_StructInit,void,LL_EXTI_InitTypeDef*
Function,-,LL_GPIO_DeInit,ErrorStatus,GPIO_TypeDef*
Function,+,LL_GPIO_Init,ErrorStatus,"GPIO_TypeDef*, LL_GPIO_InitTypeDef*"
Function,-,LL_GPIO_StructInit,void,LL_GPIO_InitTypeDef*
Function,-,LL_I2C_DeInit,ErrorStatus,I2C_TypeDef*
Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, LL_I2C_InitTypeDef*"
Function,-,LL_I2C_DeInit,ErrorStatus,const I2C_TypeDef*
Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, const LL_I2C_InitTypeDef*"
Function,-,LL_I2C_StructInit,void,LL_I2C_InitTypeDef*
Function,-,LL_Init1msTick,void,uint32_t
Function,+,LL_LPTIM_DeInit,ErrorStatus,LPTIM_TypeDef*
Function,-,LL_LPTIM_Disable,void,LPTIM_TypeDef*
Function,+,LL_LPTIM_Init,ErrorStatus,"LPTIM_TypeDef*, LL_LPTIM_InitTypeDef*"
Function,+,LL_LPTIM_Init,ErrorStatus,"LPTIM_TypeDef*, const LL_LPTIM_InitTypeDef*"
Function,-,LL_LPTIM_StructInit,void,LL_LPTIM_InitTypeDef*
Function,-,LL_LPUART_DeInit,ErrorStatus,USART_TypeDef*
Function,+,LL_LPUART_Init,ErrorStatus,"USART_TypeDef*, LL_LPUART_InitTypeDef*"
Function,-,LL_LPUART_DeInit,ErrorStatus,const USART_TypeDef*
Function,+,LL_LPUART_Init,ErrorStatus,"USART_TypeDef*, const LL_LPUART_InitTypeDef*"
Function,-,LL_LPUART_StructInit,void,LL_LPUART_InitTypeDef*
Function,-,LL_PKA_DeInit,ErrorStatus,PKA_TypeDef*
Function,-,LL_PKA_Init,ErrorStatus,"PKA_TypeDef*, LL_PKA_InitTypeDef*"
@@ -290,23 +290,23 @@ Function,+,LL_SPI_Init,ErrorStatus,"SPI_TypeDef*, LL_SPI_InitTypeDef*"
Function,-,LL_SPI_StructInit,void,LL_SPI_InitTypeDef*
Function,-,LL_SetFlashLatency,ErrorStatus,uint32_t
Function,+,LL_SetSystemCoreClock,void,uint32_t
Function,-,LL_TIM_BDTR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_BDTR_InitTypeDef*"
Function,-,LL_TIM_BDTR_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_BDTR_InitTypeDef*"
Function,-,LL_TIM_BDTR_StructInit,void,LL_TIM_BDTR_InitTypeDef*
Function,+,LL_TIM_DeInit,ErrorStatus,TIM_TypeDef*
Function,-,LL_TIM_ENCODER_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_ENCODER_InitTypeDef*"
Function,-,LL_TIM_ENCODER_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_ENCODER_InitTypeDef*"
Function,-,LL_TIM_ENCODER_StructInit,void,LL_TIM_ENCODER_InitTypeDef*
Function,-,LL_TIM_HALLSENSOR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_HALLSENSOR_InitTypeDef*"
Function,-,LL_TIM_HALLSENSOR_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_HALLSENSOR_InitTypeDef*"
Function,-,LL_TIM_HALLSENSOR_StructInit,void,LL_TIM_HALLSENSOR_InitTypeDef*
Function,-,LL_TIM_IC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, LL_TIM_IC_InitTypeDef*"
Function,-,LL_TIM_IC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, const LL_TIM_IC_InitTypeDef*"
Function,-,LL_TIM_IC_StructInit,void,LL_TIM_IC_InitTypeDef*
Function,+,LL_TIM_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_InitTypeDef*"
Function,+,LL_TIM_OC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, LL_TIM_OC_InitTypeDef*"
Function,+,LL_TIM_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_InitTypeDef*"
Function,+,LL_TIM_OC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, const LL_TIM_OC_InitTypeDef*"
Function,-,LL_TIM_OC_StructInit,void,LL_TIM_OC_InitTypeDef*
Function,-,LL_TIM_StructInit,void,LL_TIM_InitTypeDef*
Function,-,LL_USART_ClockInit,ErrorStatus,"USART_TypeDef*, LL_USART_ClockInitTypeDef*"
Function,-,LL_USART_ClockInit,ErrorStatus,"USART_TypeDef*, const LL_USART_ClockInitTypeDef*"
Function,-,LL_USART_ClockStructInit,void,LL_USART_ClockInitTypeDef*
Function,-,LL_USART_DeInit,ErrorStatus,USART_TypeDef*
Function,+,LL_USART_Init,ErrorStatus,"USART_TypeDef*, LL_USART_InitTypeDef*"
Function,-,LL_USART_DeInit,ErrorStatus,const USART_TypeDef*
Function,+,LL_USART_Init,ErrorStatus,"USART_TypeDef*, const LL_USART_InitTypeDef*"
Function,-,LL_USART_StructInit,void,LL_USART_InitTypeDef*
Function,-,LL_mDelay,void,uint32_t
Function,-,SystemCoreClockUpdate,void,
@@ -1373,6 +1373,7 @@ Function,+,furi_hal_subghz_get_lqi,uint8_t,
Function,+,furi_hal_subghz_get_radio_type,SubGhzRadioType,
Function,+,furi_hal_subghz_get_rolling_counter_mult,uint8_t,
Function,+,furi_hal_subghz_get_rssi,float,
Function,+,furi_hal_subghz_get_timestamp_file_names,_Bool,
Function,+,furi_hal_subghz_idle,void,
Function,-,furi_hal_subghz_init,void,
Function,+,furi_hal_subghz_init_check,_Bool,
@@ -1395,6 +1396,7 @@ Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t
Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath
Function,+,furi_hal_subghz_set_radio_type,_Bool,SubGhzRadioType
Function,+,furi_hal_subghz_set_rolling_counter_mult,void,uint8_t
Function,+,furi_hal_subghz_set_timestamp_file_names,void,_Bool
Function,-,furi_hal_subghz_shutdown,void,
Function,+,furi_hal_subghz_sleep,void,
Function,+,furi_hal_subghz_start_async_rx,void,"FuriHalSubGhzCaptureCallback, void*"
@@ -2171,6 +2173,7 @@ Function,+,power_get_pubsub,FuriPubSub*,Power*
Function,+,power_is_battery_healthy,_Bool,Power*
Function,+,power_off,void,Power*
Function,+,power_reboot,void,PowerBootMode
Function,+,power_trigger_ui_update,void,Power*
Function,+,powf,float,"float, float"
Function,-,powl,long double,"long double, long double"
Function,+,pretty_format_bytes_hex_canonical,void,"FuriString*, size_t, const char*, const uint8_t*, size_t"
@@ -2414,7 +2417,8 @@ Function,-,roundl,long double,long double
Function,+,rpc_session_close,void,RpcSession*
Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, TickType_t"
Function,+,rpc_session_get_available_size,size_t,RpcSession*
Function,+,rpc_session_open,RpcSession*,Rpc*
Function,+,rpc_session_get_owner,RpcOwner,RpcSession*
Function,+,rpc_session_open,RpcSession*,"Rpc*, RpcOwner"
Function,+,rpc_session_set_buffer_is_empty_callback,void,"RpcSession*, RpcBufferIsEmptyCallback"
Function,+,rpc_session_set_close_callback,void,"RpcSession*, RpcSessionClosedCallback"
Function,+,rpc_session_set_context,void,"RpcSession*, void*"
1 entry status name type params
2 Version + 22.0 23.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
213 Header + lib/toolbox/version.h
214 Header + lib/u8g2/u8g2.h
215 Function - LL_ADC_CommonDeInit ErrorStatus ADC_Common_TypeDef*
216 Function - LL_ADC_CommonInit ErrorStatus ADC_Common_TypeDef*, LL_ADC_CommonInitTypeDef* ADC_Common_TypeDef*, const LL_ADC_CommonInitTypeDef*
217 Function - LL_ADC_CommonStructInit void LL_ADC_CommonInitTypeDef*
218 Function - LL_ADC_DeInit ErrorStatus ADC_TypeDef*
219 Function - LL_ADC_INJ_Init ErrorStatus ADC_TypeDef*, LL_ADC_INJ_InitTypeDef* ADC_TypeDef*, const LL_ADC_INJ_InitTypeDef*
220 Function - LL_ADC_INJ_StructInit void LL_ADC_INJ_InitTypeDef*
221 Function - LL_ADC_Init ErrorStatus ADC_TypeDef*, LL_ADC_InitTypeDef* ADC_TypeDef*, const LL_ADC_InitTypeDef*
222 Function - LL_ADC_REG_Init ErrorStatus ADC_TypeDef*, LL_ADC_REG_InitTypeDef* ADC_TypeDef*, const LL_ADC_REG_InitTypeDef*
223 Function - LL_ADC_REG_StructInit void LL_ADC_REG_InitTypeDef*
224 Function - LL_ADC_StructInit void LL_ADC_InitTypeDef*
225 Function - LL_COMP_DeInit ErrorStatus COMP_TypeDef*
226 Function + LL_COMP_Init ErrorStatus COMP_TypeDef*, LL_COMP_InitTypeDef* COMP_TypeDef*, const LL_COMP_InitTypeDef*
227 Function - LL_COMP_StructInit void LL_COMP_InitTypeDef*
228 Function - LL_CRC_DeInit ErrorStatus CRC_TypeDef*
229 Function - LL_CRS_DeInit ErrorStatus
236 Function - LL_GPIO_DeInit ErrorStatus GPIO_TypeDef*
237 Function + LL_GPIO_Init ErrorStatus GPIO_TypeDef*, LL_GPIO_InitTypeDef*
238 Function - LL_GPIO_StructInit void LL_GPIO_InitTypeDef*
239 Function - LL_I2C_DeInit ErrorStatus I2C_TypeDef* const I2C_TypeDef*
240 Function + LL_I2C_Init ErrorStatus I2C_TypeDef*, LL_I2C_InitTypeDef* I2C_TypeDef*, const LL_I2C_InitTypeDef*
241 Function - LL_I2C_StructInit void LL_I2C_InitTypeDef*
242 Function - LL_Init1msTick void uint32_t
243 Function + LL_LPTIM_DeInit ErrorStatus LPTIM_TypeDef*
244 Function - LL_LPTIM_Disable void LPTIM_TypeDef*
245 Function + LL_LPTIM_Init ErrorStatus LPTIM_TypeDef*, LL_LPTIM_InitTypeDef* LPTIM_TypeDef*, const LL_LPTIM_InitTypeDef*
246 Function - LL_LPTIM_StructInit void LL_LPTIM_InitTypeDef*
247 Function - LL_LPUART_DeInit ErrorStatus USART_TypeDef* const USART_TypeDef*
248 Function + LL_LPUART_Init ErrorStatus USART_TypeDef*, LL_LPUART_InitTypeDef* USART_TypeDef*, const LL_LPUART_InitTypeDef*
249 Function - LL_LPUART_StructInit void LL_LPUART_InitTypeDef*
250 Function - LL_PKA_DeInit ErrorStatus PKA_TypeDef*
251 Function - LL_PKA_Init ErrorStatus PKA_TypeDef*, LL_PKA_InitTypeDef*
290 Function - LL_SPI_StructInit void LL_SPI_InitTypeDef*
291 Function - LL_SetFlashLatency ErrorStatus uint32_t
292 Function + LL_SetSystemCoreClock void uint32_t
293 Function - LL_TIM_BDTR_Init ErrorStatus TIM_TypeDef*, LL_TIM_BDTR_InitTypeDef* TIM_TypeDef*, const LL_TIM_BDTR_InitTypeDef*
294 Function - LL_TIM_BDTR_StructInit void LL_TIM_BDTR_InitTypeDef*
295 Function + LL_TIM_DeInit ErrorStatus TIM_TypeDef*
296 Function - LL_TIM_ENCODER_Init ErrorStatus TIM_TypeDef*, LL_TIM_ENCODER_InitTypeDef* TIM_TypeDef*, const LL_TIM_ENCODER_InitTypeDef*
297 Function - LL_TIM_ENCODER_StructInit void LL_TIM_ENCODER_InitTypeDef*
298 Function - LL_TIM_HALLSENSOR_Init ErrorStatus TIM_TypeDef*, LL_TIM_HALLSENSOR_InitTypeDef* TIM_TypeDef*, const LL_TIM_HALLSENSOR_InitTypeDef*
299 Function - LL_TIM_HALLSENSOR_StructInit void LL_TIM_HALLSENSOR_InitTypeDef*
300 Function - LL_TIM_IC_Init ErrorStatus TIM_TypeDef*, uint32_t, LL_TIM_IC_InitTypeDef* TIM_TypeDef*, uint32_t, const LL_TIM_IC_InitTypeDef*
301 Function - LL_TIM_IC_StructInit void LL_TIM_IC_InitTypeDef*
302 Function + LL_TIM_Init ErrorStatus TIM_TypeDef*, LL_TIM_InitTypeDef* TIM_TypeDef*, const LL_TIM_InitTypeDef*
303 Function + LL_TIM_OC_Init ErrorStatus TIM_TypeDef*, uint32_t, LL_TIM_OC_InitTypeDef* TIM_TypeDef*, uint32_t, const LL_TIM_OC_InitTypeDef*
304 Function - LL_TIM_OC_StructInit void LL_TIM_OC_InitTypeDef*
305 Function - LL_TIM_StructInit void LL_TIM_InitTypeDef*
306 Function - LL_USART_ClockInit ErrorStatus USART_TypeDef*, LL_USART_ClockInitTypeDef* USART_TypeDef*, const LL_USART_ClockInitTypeDef*
307 Function - LL_USART_ClockStructInit void LL_USART_ClockInitTypeDef*
308 Function - LL_USART_DeInit ErrorStatus USART_TypeDef* const USART_TypeDef*
309 Function + LL_USART_Init ErrorStatus USART_TypeDef*, LL_USART_InitTypeDef* USART_TypeDef*, const LL_USART_InitTypeDef*
310 Function - LL_USART_StructInit void LL_USART_InitTypeDef*
311 Function - LL_mDelay void uint32_t
312 Function - SystemCoreClockUpdate void
1373 Function + furi_hal_subghz_get_radio_type SubGhzRadioType
1374 Function + furi_hal_subghz_get_rolling_counter_mult uint8_t
1375 Function + furi_hal_subghz_get_rssi float
1376 Function + furi_hal_subghz_get_timestamp_file_names _Bool
1377 Function + furi_hal_subghz_idle void
1378 Function - furi_hal_subghz_init void
1379 Function + furi_hal_subghz_init_check _Bool
1396 Function + furi_hal_subghz_set_path void FuriHalSubGhzPath
1397 Function + furi_hal_subghz_set_radio_type _Bool SubGhzRadioType
1398 Function + furi_hal_subghz_set_rolling_counter_mult void uint8_t
1399 Function + furi_hal_subghz_set_timestamp_file_names void _Bool
1400 Function - furi_hal_subghz_shutdown void
1401 Function + furi_hal_subghz_sleep void
1402 Function + furi_hal_subghz_start_async_rx void FuriHalSubGhzCaptureCallback, void*
2173 Function + power_is_battery_healthy _Bool Power*
2174 Function + power_off void Power*
2175 Function + power_reboot void PowerBootMode
2176 Function + power_trigger_ui_update void Power*
2177 Function + powf float float, float
2178 Function - powl long double long double, long double
2179 Function + pretty_format_bytes_hex_canonical void FuriString*, size_t, const char*, const uint8_t*, size_t
2417 Function + rpc_session_close void RpcSession*
2418 Function + rpc_session_feed size_t RpcSession*, uint8_t*, size_t, TickType_t
2419 Function + rpc_session_get_available_size size_t RpcSession*
2420 Function + rpc_session_open rpc_session_get_owner RpcSession* RpcOwner Rpc* RpcSession*
2421 Function + rpc_session_open RpcSession* Rpc*, RpcOwner
2422 Function + rpc_session_set_buffer_is_empty_callback void RpcSession*, RpcBufferIsEmptyCallback
2423 Function + rpc_session_set_close_callback void RpcSession*, RpcSessionClosedCallback
2424 Function + rpc_session_set_context void RpcSession*, void*

View File

@@ -33,6 +33,7 @@ extern "C" {
#include <stdarg.h>
#include <core/common_defines.h>
#include <tl.h>
#include "app_conf.h"

View File

@@ -8,6 +8,8 @@
#define CFG_TX_POWER (0x19) /* +0dBm */
#define CFG_IDENTITY_ADDRESS GAP_PUBLIC_ADDR
/**
* Define Advertising parameters
*/

View File

@@ -33,7 +33,8 @@ PLACE_IN_SECTION("MB_MEM2")
ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig = {0, 0, 0, 0};
PLACE_IN_SECTION("MB_MEM2")
ALIGN(4)
static SHCI_C2_DEBUG_GeneralConfig_t APPD_GeneralConfig = {BLE_DTB_CFG, SYS_DBG_CFG1, {0, 0}};
static SHCI_C2_DEBUG_GeneralConfig_t APPD_GeneralConfig =
{BLE_DTB_CFG, SYS_DBG_CFG1, {0, 0}, 0, 0, 0, 0, 0};
/**
* THE DEBUG ON GPIO FOR CPU2 IS INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT
@@ -68,7 +69,7 @@ static const APPD_GpioConfig_t aGpioConfigList[GPIO_CFG_NBR_OF_FEATURES] = {
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */
{GPIOA, LL_GPIO_PIN_4, 1, 0}, /* PES_ACTIVITY - Set on Entry / Reset on Exit */
{GPIOB, LL_GPIO_PIN_2, 1, 0}, /* MB_BLE_SEND_EVT - Set on Entry / Reset on Exit */
{GPIOC, LL_GPIO_PIN_0, 1, 0}, /* MB_BLE_SEND_EVT - Set on Entry / Reset on Exit */
/* From v1.3.0 */
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_NO_DELAY - Set on Entry / Reset on Exit */
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_STACK_STORE_NVM_CB - Set on Entry / Reset on Exit */

View File

@@ -18,8 +18,8 @@ PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t ble_app_cmd_buffer;
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint32_t ble_app_nvm[BLE_NVM_SRAM_SIZE];
_Static_assert(
sizeof(SHCI_C2_Ble_Init_Cmd_Packet_t) == 49,
"Ble stack config structure size mismatch");
sizeof(SHCI_C2_Ble_Init_Cmd_Packet_t) == 58,
"Ble stack config structure size mismatch (check new config options - last updated for v.1.16.0)");
typedef struct {
FuriMutex* hci_mtx;
@@ -88,6 +88,12 @@ bool ble_app_init() {
.min_tx_power = 0,
.max_tx_power = 0,
.rx_model_config = 1,
/* New stack (13.3->16.0)*/
.max_adv_set_nbr = 1, // Only used if SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV is set
.max_adv_data_len = 31, // Only used if SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV is set
.tx_path_compens = 0, // RF TX Path Compensation, * 0.1 dB
.rx_path_compens = 0, // RF RX Path Compensation, * 0.1 dB
.ble_core_version = 11, // BLE Core Version: 11(5.2), 12(5.3)
}};
status = SHCI_C2_BLE_Init(&ble_init_cmd_packet);
if(status) {
@@ -137,38 +143,33 @@ static int32_t ble_app_hci_thread(void* arg) {
// Called by WPAN lib
void hci_notify_asynch_evt(void* pdata) {
UNUSED(pdata);
if(ble_app) {
FuriThreadId thread_id = furi_thread_get_id(ble_app->thread);
furi_assert(thread_id);
furi_thread_flags_set(thread_id, BLE_APP_FLAG_HCI_EVENT);
}
furi_check(ble_app);
FuriThreadId thread_id = furi_thread_get_id(ble_app->thread);
furi_assert(thread_id);
furi_thread_flags_set(thread_id, BLE_APP_FLAG_HCI_EVENT);
}
void hci_cmd_resp_release(uint32_t flag) {
UNUSED(flag);
if(ble_app) {
furi_semaphore_release(ble_app->hci_sem);
}
furi_check(ble_app);
furi_check(furi_semaphore_release(ble_app->hci_sem) == FuriStatusOk);
}
void hci_cmd_resp_wait(uint32_t timeout) {
UNUSED(timeout);
if(ble_app) {
furi_semaphore_acquire(ble_app->hci_sem, FuriWaitForever);
}
furi_check(ble_app);
furi_check(furi_semaphore_acquire(ble_app->hci_sem, timeout) == FuriStatusOk);
}
static void ble_app_hci_event_handler(void* pPayload) {
SVCCTL_UserEvtFlowStatus_t svctl_return_status;
tHCI_UserEvtRxParam* pParam = (tHCI_UserEvtRxParam*)pPayload;
if(ble_app) {
svctl_return_status = SVCCTL_UserEvtRx((void*)&(pParam->pckt->evtserial));
if(svctl_return_status != SVCCTL_UserEvtFlowDisable) {
pParam->status = HCI_TL_UserEventFlow_Enable;
} else {
pParam->status = HCI_TL_UserEventFlow_Disable;
}
furi_check(ble_app);
svctl_return_status = SVCCTL_UserEvtRx((void*)&(pParam->pckt->evtserial));
if(svctl_return_status != SVCCTL_UserEvtFlowDisable) {
pParam->status = HCI_TL_UserEventFlow_Enable;
} else {
pParam->status = HCI_TL_UserEventFlow_Disable;
}
}

View File

@@ -23,6 +23,7 @@
#include <ble/core/ble_std.h>
#include <ble/core/ble_defs.h>
#include "osal.h"
#include "compiler.h"
/* Default BLE variant */
#ifndef BASIC_FEATURES
@@ -34,6 +35,9 @@
#ifndef LL_ONLY
#define LL_ONLY 0
#endif
#ifndef LL_ONLY_BASIC
#define LL_ONLY_BASIC 0
#endif
#ifndef BEACON_ONLY
#define BEACON_ONLY 0
#endif

View File

@@ -403,7 +403,9 @@ void shci_cmd_resp_release(uint32_t flag) {
void shci_cmd_resp_wait(uint32_t timeout) {
UNUSED(timeout);
if(ble_glue) {
furi_hal_power_insomnia_enter();
furi_semaphore_acquire(ble_glue->shci_sem, FuriWaitForever);
furi_hal_power_insomnia_exit();
}
}

View File

@@ -5,7 +5,7 @@
*****************************************************************************
* @attention
*
* Copyright (c) 2018-2022 STMicroelectronics.
* Copyright (c) 2018-2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
@@ -18,6 +18,14 @@
#ifndef COMPILER_H__
#define COMPILER_H__
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT PACKED(struct)
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION PACKED(union)
#endif
/**
* @brief This is the section dedicated to IAR toolchain
*/

View File

@@ -1,5 +1,6 @@
#include "gap.h"
#include "app_common.h"
#include <ble/ble.h>
#include <furi_hal.h>
@@ -85,7 +86,7 @@ static void gap_verify_connection_parameters(Gap* gap) {
SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
hci_event_pckt* event_pckt;
evt_le_meta_event* meta_evt;
evt_blue_aci* blue_evt;
evt_blecore_aci* blue_evt;
hci_le_phy_update_complete_event_rp0* evt_le_phy_update_complete;
uint8_t tx_phy;
uint8_t rx_phy;
@@ -97,7 +98,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
furi_mutex_acquire(gap->state_mutex, FuriWaitForever);
}
switch(event_pckt->evt) {
case EVT_DISCONN_COMPLETE: {
case HCI_DISCONNECTION_COMPLETE_EVT_CODE: {
hci_disconnection_complete_event_rp0* disconnection_complete_event =
(hci_disconnection_complete_event_rp0*)event_pckt->data;
if(disconnection_complete_event->Connection_Handle == gap->service.connection_handle) {
@@ -106,6 +107,8 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
FURI_LOG_I(
TAG, "Disconnect from client. Reason: %02X", disconnection_complete_event->Reason);
}
// Enterprise sleep
furi_delay_us(666 + 666);
if(gap->enable_adv) {
// Restart advertising
gap_advertise_start(GapStateAdvFast);
@@ -114,10 +117,10 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
gap->on_event_cb(event, gap->context);
} break;
case EVT_LE_META_EVENT:
case HCI_LE_META_EVT_CODE:
meta_evt = (evt_le_meta_event*)event_pckt->data;
switch(meta_evt->subevent) {
case EVT_LE_CONN_UPDATE_COMPLETE: {
case HCI_LE_CONNECTION_UPDATE_COMPLETE_SUBEVT_CODE: {
hci_le_connection_update_complete_event_rp0* event =
(hci_le_connection_update_complete_event_rp0*)meta_evt->data;
gap->connection_params.conn_interval = event->Conn_Interval;
@@ -128,7 +131,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
break;
}
case EVT_LE_PHY_UPDATE_COMPLETE:
case HCI_LE_PHY_UPDATE_COMPLETE_SUBEVT_CODE:
evt_le_phy_update_complete = (hci_le_phy_update_complete_event_rp0*)meta_evt->data;
if(evt_le_phy_update_complete->Status) {
FURI_LOG_E(
@@ -144,7 +147,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
}
break;
case EVT_LE_CONN_COMPLETE: {
case HCI_LE_CONNECTION_COMPLETE_SUBEVT_CODE: {
hci_le_connection_complete_event_rp0* event =
(hci_le_connection_complete_event_rp0*)meta_evt->data;
gap->connection_params.conn_interval = event->Conn_Interval;
@@ -168,16 +171,16 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
}
break;
case EVT_VENDOR:
blue_evt = (evt_blue_aci*)event_pckt->data;
case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE:
blue_evt = (evt_blecore_aci*)event_pckt->data;
switch(blue_evt->ecode) {
aci_gap_pairing_complete_event_rp0* pairing_complete;
case EVT_BLUE_GAP_LIMITED_DISCOVERABLE:
case ACI_GAP_LIMITED_DISCOVERABLE_VSEVT_CODE:
FURI_LOG_I(TAG, "Limited discoverable event");
break;
case EVT_BLUE_GAP_PASS_KEY_REQUEST: {
case ACI_GAP_PASS_KEY_REQ_VSEVT_CODE: {
// Generate random PIN code
uint32_t pin = rand() % 999999; //-V1064
aci_gap_pass_key_resp(gap->service.connection_handle, pin);
@@ -190,7 +193,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
gap->on_event_cb(event, gap->context);
} break;
case EVT_BLUE_ATT_EXCHANGE_MTU_RESP: {
case ACI_ATT_EXCHANGE_MTU_RESP_VSEVT_CODE: {
aci_att_exchange_mtu_resp_event_rp0* pr = (void*)blue_evt->data;
FURI_LOG_I(TAG, "Rx MTU size: %d", pr->Server_RX_MTU);
// Set maximum packet size given header size is 3 bytes
@@ -199,32 +202,28 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
gap->on_event_cb(event, gap->context);
} break;
case EVT_BLUE_GAP_AUTHORIZATION_REQUEST:
case ACI_GAP_AUTHORIZATION_REQ_VSEVT_CODE:
FURI_LOG_D(TAG, "Authorization request event");
break;
case EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED:
case ACI_GAP_SLAVE_SECURITY_INITIATED_VSEVT_CODE:
FURI_LOG_D(TAG, "Slave security initiated");
break;
case EVT_BLUE_GAP_BOND_LOST:
case ACI_GAP_BOND_LOST_VSEVT_CODE:
FURI_LOG_D(TAG, "Bond lost event. Start rebonding");
aci_gap_allow_rebond(gap->service.connection_handle);
break;
case EVT_BLUE_GAP_DEVICE_FOUND:
FURI_LOG_D(TAG, "Device found event");
break;
case EVT_BLUE_GAP_ADDR_NOT_RESOLVED:
case ACI_GAP_ADDR_NOT_RESOLVED_VSEVT_CODE:
FURI_LOG_D(TAG, "Address not resolved event");
break;
case EVT_BLUE_GAP_KEYPRESS_NOTIFICATION:
case ACI_GAP_KEYPRESS_NOTIFICATION_VSEVT_CODE:
FURI_LOG_D(TAG, "Key press notification event");
break;
case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: {
case ACI_GAP_NUMERIC_COMPARISON_VALUE_VSEVT_CODE: {
uint32_t pin =
((aci_gap_numeric_comparison_value_event_rp0*)(blue_evt->data))->Numeric_Value;
FURI_LOG_I(TAG, "Verify numeric comparison: %06lu", pin);
@@ -234,7 +233,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
break;
}
case EVT_BLUE_GAP_PAIRING_CMPLT:
case ACI_GAP_PAIRING_COMPLETE_VSEVT_CODE:
pairing_complete = (aci_gap_pairing_complete_event_rp0*)blue_evt->data;
if(pairing_complete->Status) {
FURI_LOG_E(
@@ -249,11 +248,11 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
}
break;
case EVT_BLUE_GAP_PROCEDURE_COMPLETE:
case ACI_L2CAP_CONNECTION_UPDATE_RESP_VSEVT_CODE:
FURI_LOG_D(TAG, "Procedure complete event");
break;
case EVT_BLUE_L2CAP_CONNECTION_UPDATE_RESP: {
case ACI_L2CAP_CONNECTION_UPDATE_REQ_VSEVT_CODE: {
uint16_t result =
((aci_l2cap_connection_update_resp_event_rp0*)(blue_evt->data))->Result;
if(result == 0) {
@@ -289,8 +288,6 @@ static void gap_init_svc(Gap* gap) {
tBleStatus status;
uint32_t srd_bd_addr[2];
// HCI Reset to synchronise BLE Stack
hci_reset();
// Configure mac address
aci_hal_write_config_data(
CONFIG_DATA_PUBADDR_OFFSET, CONFIG_DATA_PUBADDR_LEN, gap->config->mac_address);
@@ -364,7 +361,7 @@ static void gap_init_svc(Gap* gap) {
CFG_ENCRYPTION_KEY_SIZE_MAX,
CFG_USED_FIXED_PIN,
0,
PUBLIC_ADDR);
CFG_IDENTITY_ADDRESS);
// Configure whitelist
aci_gap_configure_whitelist();
}
@@ -399,7 +396,7 @@ static void gap_advertise_start(GapState new_state) {
ADV_IND,
min_interval,
max_interval,
PUBLIC_ADDR,
CFG_IDENTITY_ADDRESS,
0,
strlen(gap->service.adv_name),
(uint8_t*)gap->service.adv_name,

View File

@@ -1,5 +1,6 @@
#include <furi_hal_flash.h>
#include <furi_hal_bt.h>
#include <furi_hal_power.h>
#include <furi.h>
#include <ble/ble.h>
#include <interface/patterns/ble_thread/shci/shci.h>
@@ -114,6 +115,7 @@ static void furi_hal_flash_lock(void) {
}
static void furi_hal_flash_begin_with_core2(bool erase_flag) {
furi_hal_power_insomnia_enter();
/* Take flash controller ownership */
while(LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID) != 0) {
furi_thread_yield();
@@ -188,6 +190,7 @@ static void furi_hal_flash_end_with_core2(bool erase_flag) {
/* Release flash controller ownership */
LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0);
furi_hal_power_insomnia_exit();
}
static void furi_hal_flash_end(bool erase_flag) {

View File

@@ -29,6 +29,14 @@
#define FURI_HAL_POWER_DEBUG_STOP_GPIO (&gpio_ext_pc3)
#endif
#ifndef FURI_HAL_POWER_DEBUG_ABNORMAL_GPIO
#define FURI_HAL_POWER_DEBUG_ABNORMAL_GPIO (&gpio_ext_pb3)
#endif
#ifndef FURI_HAL_POWER_STOP_MODE
#define FURI_HAL_POWER_STOP_MODE (LL_PWR_MODE_STOP2)
#endif
typedef struct {
volatile uint8_t insomnia;
volatile uint8_t suppress_charge;
@@ -84,14 +92,16 @@ 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_init_simple(FURI_HAL_POWER_DEBUG_ABNORMAL_GPIO, GpioModeOutputPushPull);
furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_WFI_GPIO, 0);
furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_STOP_GPIO, 0);
furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_ABNORMAL_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);
LL_PWR_SetPowerMode(FURI_HAL_POWER_STOP_MODE);
LL_C2_PWR_SetPowerMode(FURI_HAL_POWER_STOP_MODE);
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
bq27220_init(&furi_hal_i2c_handle_power, &cedv);
@@ -148,7 +158,9 @@ bool furi_hal_power_sleep_available() {
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();
!furi_hal_debug_is_gdb_session_active() && !LL_PWR_IsActiveFlag_CRPE() &&
!LL_PWR_IsActiveFlag_CRP() && !LL_PWR_IsActiveFlag_BLEA() &&
!LL_PWR_IsActiveFlag_BLEWU();
}
static inline void furi_hal_power_light_sleep() {
@@ -199,7 +211,16 @@ static inline void furi_hal_power_deep_sleep() {
__force_stores();
#endif
__WFI();
bool should_abort_sleep = LL_PWR_IsActiveFlag_CRPE() || LL_PWR_IsActiveFlag_CRP() ||
LL_PWR_IsActiveFlag_BLEA() || LL_PWR_IsActiveFlag_BLEWU();
if(should_abort_sleep) {
#ifdef FURI_HAL_POWER_DEBUG
furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_ABNORMAL_GPIO, 1);
#endif
} else {
__WFI();
}
LL_LPM_EnableSleep();

View File

@@ -40,6 +40,7 @@ volatile FuriHalSubGhz furi_hal_subghz = {
.cc1101_g0_pin = &gpio_cc1101_g0,
.rolling_counter_mult = 1,
.ext_module_power_disabled = false,
.timestamp_file_names = false,
};
bool furi_hal_subghz_set_radio_type(SubGhzRadioType state) {
@@ -79,6 +80,14 @@ bool furi_hal_subghz_get_external_power_disable(void) {
return furi_hal_subghz.ext_module_power_disabled;
}
void furi_hal_subghz_set_timestamp_file_names(bool state) {
furi_hal_subghz.timestamp_file_names = state;
}
bool furi_hal_subghz_get_timestamp_file_names(void) {
return furi_hal_subghz.timestamp_file_names;
}
void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin) {
furi_hal_subghz.async_mirror_pin = pin;
}

View File

@@ -79,6 +79,7 @@ typedef struct {
const GpioPin* cc1101_g0_pin;
uint8_t rolling_counter_mult;
bool ext_module_power_disabled;
bool timestamp_file_names;
} FuriHalSubGhz;
extern volatile FuriHalSubGhz furi_hal_subghz;
@@ -330,6 +331,14 @@ void furi_hal_subghz_set_external_power_disable(bool state);
*/
bool furi_hal_subghz_get_external_power_disable(void);
/** If true - disable generation of random name and add timestamp to filenames instead
*/
void furi_hal_subghz_set_timestamp_file_names(bool state);
/** Get the current state of the timestamp instead of random name flag
*/
bool furi_hal_subghz_get_timestamp_file_names(void);
#ifdef __cplusplus
}
#endif

View File

@@ -29,6 +29,8 @@ int main() {
FuriThread* main_thread = furi_thread_alloc_ex("Init", 4096, init_task, NULL);
#ifdef FURI_RAM_EXEC
// Prevent entering sleep mode when executed from RAM
furi_hal_power_insomnia_enter();
furi_thread_start(main_thread);
#else
furi_hal_light_sequence("RGB");
@@ -44,6 +46,7 @@ int main() {
furi_hal_power_reset();
} else if(boot_mode == FuriHalRtcBootModeUpdate) {
furi_hal_light_sequence("rgb BR");
// Do update
flipper_boot_update_exec();
// if things go nice, we shouldn't reach this point.
// But if we do, abandon to avoid bootloops

View File

@@ -31,6 +31,7 @@ typedef enum {
FuriHalRtcFlagC2Update = (1 << 3),
FuriHalRtcFlagHandOrient = (1 << 4),
FuriHalRtcFlagLegacySleep = (1 << 5),
FuriHalRtcFlagStealthMode = (1 << 6),
} FuriHalRtcFlag;
typedef enum {

View File

@@ -152,7 +152,7 @@ SubGhzProtocolStatus subghz_block_generic_deserialize_check_count_bit(
break;
}
if(instance->data_count_bit != count_bit) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
FURI_LOG_D(TAG, "Wrong number of bits in key");
ret = SubGhzProtocolStatusErrorValueBitCount;
break;
}

View File

@@ -79,6 +79,11 @@ const SubGhzProtocol subghz_protocol_alutech_at_4n = {
.encoder = &subghz_protocol_alutech_at_4n_encoder,
};
static void subghz_protocol_alutech_at_4n_remote_controller(
SubGhzBlockGeneric* instance,
uint8_t crc,
const char* file_name);
void* subghz_protocol_encoder_alutech_at_4n_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
SubGhzProtocolEncoderAlutech_at_4n* instance =
@@ -503,10 +508,18 @@ SubGhzProtocolStatus subghz_protocol_encoder_alutech_at_4n_deserialize(
break;
}
if(!flipper_format_read_uint32(flipper_format, "CRC", (uint32_t*)&instance->crc, 1)) {
FURI_LOG_E(TAG, "Missing CRC");
break;
}
//optional parameter parameter
flipper_format_read_uint32(
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
subghz_protocol_alutech_at_4n_remote_controller(
&instance->generic, instance->crc, instance->alutech_at_4n_rainbow_table_file_name);
subghz_protocol_encoder_alutech_at_4n_get_upload(instance, instance->generic.btn);
if(!flipper_format_rewind(flipper_format)) {

View File

@@ -393,7 +393,6 @@ static bool
uint8_t custom_btn_id = subghz_custom_btn_get();
uint8_t original_btn_num = subghz_custom_btn_get_original();
// Set custom button
if(custom_btn_id == 1) {
switch(original_btn_num) {
@@ -499,11 +498,9 @@ static bool
break;
}
}
if((custom_btn_id == 0) && (original_btn_num != 0)) {
btn = original_btn_num;
}
// Generate new key
if(subghz_protocol_keeloq_gen_data(instance, btn, true)) {

View File

@@ -117,8 +117,7 @@ static bool
}
//Send start bit
instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_nero_radio_const.te_short * 4);
instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)830);
instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_nero_radio_const.te_short);
@@ -142,14 +141,22 @@ static bool
//send bit 1
instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_nero_radio_const.te_long);
instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_nero_radio_const.te_short * 37);
if(instance->generic.data_count_bit == 57) {
instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)1300);
} else {
instance->encoder.upload[index++] = level_duration_make(
false, (uint32_t)subghz_protocol_nero_radio_const.te_short * 23);
}
} else {
//send bit 0
instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_nero_radio_const.te_short);
instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_nero_radio_const.te_short * 37);
if(instance->generic.data_count_bit == 57) {
instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)1300);
} else {
instance->encoder.upload[index++] = level_duration_make(
false, (uint32_t)subghz_protocol_nero_radio_const.te_short * 23);
}
}
return true;
}
@@ -164,8 +171,14 @@ SubGhzProtocolStatus
&instance->generic,
flipper_format,
subghz_protocol_nero_radio_const.min_count_bit_for_found);
if(ret != SubGhzProtocolStatusOk) {
break;
if((ret == SubGhzProtocolStatusErrorValueBitCount) &&
(instance->generic.data_count_bit == 57)) {
ret = SubGhzProtocolStatusOk;
} else {
if(ret != SubGhzProtocolStatusOk) {
break;
}
}
//optional parameter parameter
flipper_format_read_uint32(
@@ -284,8 +297,7 @@ void subghz_protocol_decoder_nero_radio_feed(void* context, bool level, uint32_t
break;
case NeroRadioDecoderStepCheckDuration:
if(!level) {
if(duration >= ((uint32_t)subghz_protocol_nero_radio_const.te_short * 10 +
subghz_protocol_nero_radio_const.te_delta * 2)) {
if(duration >= ((uint32_t)1250)) {
//Found stop bit
if(DURATION_DIFF(
instance->decoder.te_last, subghz_protocol_nero_radio_const.te_short) <
@@ -298,8 +310,10 @@ void subghz_protocol_decoder_nero_radio_feed(void* context, bool level, uint32_t
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
}
instance->decoder.parser_step = NeroRadioDecoderStepReset;
if(instance->decoder.decode_count_bit ==
subghz_protocol_nero_radio_const.min_count_bit_for_found) {
if((instance->decoder.decode_count_bit ==
subghz_protocol_nero_radio_const.min_count_bit_for_found) ||
(instance->decoder.decode_count_bit ==
subghz_protocol_nero_radio_const.min_count_bit_for_found + 1)) {
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
@@ -356,10 +370,19 @@ SubGhzProtocolStatus
subghz_protocol_decoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
SubGhzProtocolDecoderNeroRadio* instance = context;
return subghz_block_generic_deserialize_check_count_bit(
SubGhzProtocolStatus stat;
stat = subghz_block_generic_deserialize_check_count_bit(
&instance->generic,
flipper_format,
subghz_protocol_nero_radio_const.min_count_bit_for_found);
if((stat == SubGhzProtocolStatusErrorValueBitCount) &&
(instance->generic.data_count_bit == 57)) {
return SubGhzProtocolStatusOk;
} else {
return stat;
}
}
void subghz_protocol_decoder_nero_radio_get_string(void* context, FuriString* output) {

View File

@@ -244,8 +244,8 @@ void subghz_protocol_decoder_raw_reset(void* context) {
void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
SubGhzProtocolDecoderRAW* instance = context;
if(!instance->pause && (instance->upload_raw != NULL)) {
// Add check if we got duration higher than 1 second, we skipping it, temp fix
if((!instance->pause && (instance->upload_raw != NULL)) && (duration < ((uint32_t)1000000))) {
if(duration > subghz_protocol_raw_const.te_short) {
if(instance->last_level != level) {
instance->last_level = (level ? true : false);

View File

@@ -56,6 +56,7 @@ void subghz_file_encoder_worker_add_level_duration(
bool subghz_file_encoder_worker_data_parse(SubGhzFileEncoderWorker* instance, const char* strStart) {
char* str1;
int32_t temp_ds = 0;
bool res = false;
// Line sample: "RAW_Data: -1, 2, -2..."
@@ -72,7 +73,18 @@ bool subghz_file_encoder_worker_data_parse(SubGhzFileEncoderWorker* instance, co
// Skip space
str1 += 1;
subghz_file_encoder_worker_add_level_duration(instance, atoi(str1));
//
temp_ds = atoi(str1);
if((temp_ds < -1000000) || (temp_ds > 1000000)) {
if(temp_ds > 0) {
subghz_file_encoder_worker_add_level_duration(instance, (int32_t)100);
} else {
subghz_file_encoder_worker_add_level_duration(instance, (int32_t)-100);
}
//FURI_LOG_I("PARSE", "Number overflow - %d", atoi(str1));
} else {
subghz_file_encoder_worker_add_level_duration(instance, temp_ds);
}
}
res = true;
}

View File

@@ -14,7 +14,7 @@ IWDGSTOP:0x1:rw
IWDGSW:0x1:rw
IPCCDBA:0x0:rw
ESE:0x1:r
SFSA:0xD7:r
SFSA:0xD5:r
FSD:0x0:r
DDS:0x1:r
C2OPT:0x1:r
@@ -22,7 +22,7 @@ NBRSD:0x0:r
SNBRSA:0xD:r
BRSD:0x0:r
SBRSA:0x12:r
SBRV:0x35C00:r
SBRV:0x35400:r
PCROP1A_STRT:0x1FF:r
PCROP1A_END:0x0:r
PCROP_RDP:0x1:rw

View File

@@ -1,6 +1,8 @@
from SCons.Platform import TempFileMunge
from SCons.Node import FS
from SCons.Errors import UserError
from SCons.Warnings import warn, WarningOnByDefault
import os
import multiprocessing
@@ -246,7 +248,12 @@ known_extapps = [
for apptype in apps_to_build_as_faps
for app in appenv["APPBUILD"].get_apps_of_type(apptype, True)
]
incompatible_apps = []
for app in known_extapps:
if not app.supports_hardware_target(appenv.subst("f${TARGET_HW}")):
incompatible_apps.append(app)
continue
app_artifacts = appenv.BuildAppElf(app)
app_src_dir = extract_abs_dir(app_artifacts.app._appdir)
app_artifacts.installer = [
@@ -254,6 +261,13 @@ for app in known_extapps:
appenv.Install(app_src_dir.Dir("dist").Dir("debug"), app_artifacts.debug),
]
if len(incompatible_apps):
print(
"WARNING: The following apps are not compatible with the current target hardware and will not be built: {}".format(
", ".join([app.name for app in incompatible_apps])
)
)
if appenv["FORCE"]:
appenv.AlwaysBuild([extapp.compact for extapp in apps_artifacts.values()])

View File

@@ -154,6 +154,7 @@ class Main(App):
"firmware_commit": current_info["GIT_COMMIT"],
"firmware_branch": current_info["GIT_BRANCH"],
"firmware_target": current_info["TARGET"],
"firmware_version": current_info["VERSION"],
}
with open(version_json_name, "w", newline="\n") as file:
json.dump(version_json, file, indent=4)