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

Compare commits

..

19 Commits

Author SHA1 Message Date
MX
5cf46d2aa9 Merge branch 'dev' into release 2023-02-11 04:56:15 +03:00
MX
beedf54e75 Merge branch 'dev' into release 2023-02-11 04:35:02 +03:00
MX
70ccb89c3d fix submodule update 2023-02-04 23:52:13 +03:00
MX
5ea43a2a4b Merge branch 'dev' into release 2023-02-04 23:50:09 +03:00
MX
41f60dbbf4 Merge branch 'dev' into release 2023-01-19 22:45:38 +03:00
MX
827341ec08 Merge branch 'dev' into release 2023-01-19 01:53:01 +03:00
MX
5c36043d03 Merge branch 'dev' into release 2022-12-31 03:21:55 +03:00
MX
cf5811f8d9 Merge branch 'dev' into release 2022-12-31 02:59:26 +03:00
MX
ec6a169bf8 Merge branch 'dev' into release 2022-12-19 21:57:35 +03:00
MX
f1dec87c1b Merge branch 'dev' into release 2022-12-19 20:52:17 +03:00
MX
ab29951a99 Merge branch 'dev' into release 2022-12-19 19:26:06 +03:00
MX
bbe9f88bbe Merge branch 'dev' into release 2022-12-11 01:34:50 +03:00
MX
9188bf0013 Merge branch 'dev' into release 2022-12-10 04:38:04 +03:00
MX
f33ed59567 Merge branch 'dev' into release 2022-12-03 01:04:48 +03:00
MX
3fd8c80861 Merge branch 'dev' into release 2022-12-03 00:59:18 +03:00
MX
7b8ac3a5a0 Merge branch 'dev' into release 2022-11-30 21:05:08 +03:00
MX
6fef957001 Merge branch 'dev' into release 2022-11-24 04:02:59 +03:00
MX
0de1c9df89 Merge branch 'dev' into release 2022-11-24 03:45:52 +03:00
MX
a0e8cfbe97 Merge branch 'dev' into release 2022-11-24 03:41:01 +03:00
45 changed files with 346 additions and 1105 deletions

View File

@@ -222,18 +222,6 @@ steps:
- chmod +x ./discord.sh
- ./discord.sh --text 'New Unleashed firmware released!\n\nVersion - '${DRONE_TAG}'\n\n[[Github - Changelog]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')\n\n[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)\n\n[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)\n\n[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/'${DRONE_TAG}'/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')\n\n[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)\n\n[-Version with extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)'
- name: "Send extra pack build to telegram"
image: appleboy/drone-telegram
settings:
token:
from_secret: tgtoken
to:
from_secret: tgid
format: markdown
message: "Build with extra apps pack:"
document:
- flipper-z-f7-update-${DRONE_TAG}e.tgz
trigger:
event:
- tag
@@ -392,18 +380,6 @@ steps:
document:
- dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz
- name: "Send extra pack build to telegram"
image: appleboy/drone-telegram
settings:
token:
from_secret: tgtoken
to:
from_secret: tgid_dev
format: markdown
message: "Build with extra apps pack:"
document:
- flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz
- name: "Send discord notification"
image: hfdj/fztools
pull: never

View File

@@ -1,12 +1,41 @@
### New changes
* SubGHz: **Nice ON2E (Nice One)** support (by @assasinfil | PR #335)
* SubGHz: Remove 467.75 From freq analyzer since it has too much noise (Frequency is still can be used, just excluded from FA to avoid false detections)
* Archive and FileBrowser: **Fixed more navigation issues** (by @Willy-JL | PR #334)
* Plugins -> SubGHz Bruteforcer: Fix Linear Delta 3 repeats (now its more stable and we will be sure signal is received correctly)
* Plugins: Updated TOTP (Authenticator) [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
* OFW: **Fix Cyfral & Metakom emulation (My temp fix removed and proper fix from OFW applied)**
* OFW: BadUSB: disable CDC mode, USB mode switch fix
* OFW: Updater visual fixes
* API: Due to OFW changes API was updated to 14.x, extra pack was updated you can install it separatly or use build with extra pack included
* SubGHz: **Fixed bug in SubGHz HAL, now CC1101 shutdowns properly, (also this fixed unstable TX)**
* SubGHz: **Alutech AT-4N** encoder (support for sending signals) (by @assasinfil | PR #322)
* SubGHz: **KingGates Stylo 4k** encoder (support for sending signals) (by @assasinfil | PR #321)
* SubGHz: Added Debug Pin setting for protocol development and fixed debug (and sound) with internal module
* SubGHz: GUI Fixes
* SubGHz: Removed bugged Detect RAW feature, now its replaced with BinRAW
* Plugins: SubGHz Bruteforcer - Added support for Linear Delta-3 310MHz
* Plugins: Fix CTRL-SHIFT in mousejacker (by @notmarek | PR #316)
* Infrared: Update universal remote assets (by @amec0e) (PR #318)
* NFC: Add Mifare Classic keys (by @Bon-Jorik (scaff.walker) | PR #324)
* Misc: Playing games now affect Flipper's level
* OFW: Fixed typo in nfc_magic_scene_wrong_card.c
* OFW: SubGhz: fix cc1101_read_fifo func
* OFW: feat: add missing `const` qualifiers
* OFW: **SubGhz: add protocol BinRAW (binarization of data quantized by the minimum correlated duration)**
* OFW: Picopass: show elite key used from dictionary
* OFW: Firmware fixes and improvements for flashing via blackmagic
* OFW: fbt: building fap_dist for compact gh build; accessor: fixed for latest ibutton changes
* OFW: Move CSN space to revent overflow
* OFW: **SubGhz: add protocol KingGates Stylo4k**
* OFW: **SubGhz: add protocol Nice One**
* OFW: **SubGhz: add protocol Alutech at-4n**
* OFW: **SubGhz: add DOOYA protocol**
* OFW: **SubGhz: add protocol "Linear Delta-3"**
* OFW: **SubGhz: Fix Raw write, add short duration filter setting**
* OFW: Update Missing SD Card icon from PR 2373
* OFW: SCons: do not include backup files in build
* OFW: Fix minor UI inconsistencies and bugs
* OFW: Allow use of any suitable pin for 1-Wire devices
* OFW: **SD over SPI improvements**
* OFW: Multitarget support for fbt (includes support for non released yet flipper hardware)
* OFW: Pin Reset
* OFW: nfc: Add mifare classic value block commands
* OFW: battery info temperature shown in C or F based on settings
* OFW: Script that can find programmer and flash firmware via it.
* OFW: **SPI Mem Manager C port** (You can use flipper as programmer to flash supported chips)
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)

View File

@@ -56,10 +56,6 @@ Our Discord Community:
Also check the changelog in releases for latest updates!
### Current modified and new Sub-GHz protocols list:
Thanks to Official team (to thier SubGHz Developer, Skorp) for implementing decoders for these protocols.
Encoders/sending made by Eng1n33r & @xMasterX:
- Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b)
- Keeloq: HCS101
- Keeloq: AN-Motors
@@ -76,19 +72,15 @@ Encoders/sending made by Eng1n33r & @xMasterX:
- BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)]
- Security+ v1 & v2
- Star Line
Encoders made by @assasinfil & @xMasterX:
- Somfy Telis
- Somfy Keytis
- KingGates Stylo 4k
- Alutech AT-4N
- Nice ON2E (Nice One)
- Somfy Telis (encoder by @assasinfil & @TQMatvey)
- Somfy Keytis (encoder by @assasinfil)
- KingGates Stylo 4k (encoder by @assasinfil)
- Alutech AT-4N (encoder by @assasinfil)
## Please support development of the project
The majority of this project is developed and maintained by me, @xMasterX.
I'm unemployed because of the war, and the only income I receive is from your donations.
Our team is small and the guys are working on this project as much as they can solely based on the enthusiasm they have for this project and the community.
- @assasinfil - SubGHz
- @Svaarich - UI design and animations
- @Amec0e - Infrared assets
- Community moderators in Telegram, Discord, and Reddit

View File

@@ -8,7 +8,6 @@
#include <gui/modules/file_browser_worker.h>
#include <fap_loader/fap_loader_app.h>
#include <math.h>
#include <furi_hal.h>
static void
archive_folder_open_cb(void* context, uint32_t item_cnt, int32_t file_idx, bool is_root) {
@@ -57,29 +56,16 @@ static void archive_list_load_cb(void* context, uint32_t list_load_offset) {
false);
}
static void archive_list_item_cb(
void* context,
FuriString* item_path,
uint32_t idx,
bool is_folder,
bool is_last) {
static void
archive_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last) {
furi_assert(context);
UNUSED(idx);
ArchiveBrowserView* browser = (ArchiveBrowserView*)context;
if(!is_last) {
archive_add_file_item(browser, is_folder, furi_string_get_cstr(item_path));
} else {
with_view_model(
browser->view,
ArchiveBrowserViewModel * model,
{
if(model->item_cnt <= BROWSER_SORT_THRESHOLD) {
files_array_sort(model->files);
}
model->list_loading = false;
},
true);
browser->view, ArchiveBrowserViewModel * model, { model->list_loading = false; }, true);
}
}
@@ -154,7 +140,7 @@ void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
archive_get_items(browser, furi_string_get_cstr(browser->path));
if(!archive_file_get_array_size(browser) && archive_is_home(browser)) {
archive_switch_tab(browser, TAB_LEFT);
archive_switch_tab(browser, TAB_RIGHT);
} else {
with_view_model(
browser->view,
@@ -221,7 +207,7 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) {
false);
if((items_cnt == 0) && (archive_is_home(browser))) {
archive_switch_tab(browser, TAB_LEFT);
archive_switch_tab(browser, TAB_RIGHT);
}
archive_update_offset(browser);
@@ -470,13 +456,6 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
} else {
tab = (tab + 1) % ArchiveTabTotal;
}
if(tab == ArchiveTabInternal && !furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
if(key == InputKeyLeft) {
tab = ((tab - 1) + ArchiveTabTotal) % ArchiveTabTotal;
} else {
tab = (tab + 1) % ArchiveTabTotal;
}
}
browser->is_root = true;
archive_set_tab(browser, tab);

View File

@@ -3,7 +3,7 @@
#include "../archive_i.h"
#include <storage/storage.h>
#define TAB_LEFT InputKeyLeft // Default tab switch direction
#define TAB_RIGHT InputKeyRight // Default tab switch direction
#define TAB_DEFAULT ArchiveTabFavorites // Start tab
#define FILE_LIST_BUF_LEN 50
@@ -17,7 +17,6 @@ static const char* tab_default_paths[] = {
[ArchiveTabBadUsb] = ANY_PATH("badusb"),
[ArchiveTabU2f] = "/app:u2f",
[ArchiveTabApplications] = ANY_PATH("apps"),
[ArchiveTabInternal] = STORAGE_INT_PATH_PREFIX,
[ArchiveTabBrowser] = STORAGE_ANY_PATH_PREFIX,
};
@@ -45,7 +44,6 @@ static const ArchiveFileTypeEnum known_type[] = {
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
[ArchiveTabU2f] = ArchiveFileTypeU2f,
[ArchiveTabApplications] = ArchiveFileTypeApplication,
[ArchiveTabInternal] = ArchiveFileTypeUnknown,
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
};

View File

@@ -2,7 +2,6 @@
#include <m-array.h>
#include <furi.h>
#include <m-algo.h>
#include <storage/storage.h>
#include "toolbox/path.h"
@@ -82,29 +81,13 @@ static void ArchiveFile_t_clear(ArchiveFile_t* obj) {
furi_string_free(obj->custom_name);
}
static int ArchiveFile_t_cmp(const ArchiveFile_t* a, const ArchiveFile_t* b) {
if(a->type == ArchiveFileTypeFolder && b->type != ArchiveFileTypeFolder) {
return -1;
}
if(a->type != ArchiveFileTypeFolder && b->type == ArchiveFileTypeFolder) {
return 1;
}
return furi_string_cmpi(a->path, b->path);
}
#define M_OPL_ArchiveFile_t() \
(INIT(API_2(ArchiveFile_t_init)), \
SET(API_6(ArchiveFile_t_set)), \
INIT_SET(API_6(ArchiveFile_t_init_set)), \
CLEAR(API_2(ArchiveFile_t_clear)), \
CMP(API_6(ArchiveFile_t_cmp)), \
SWAP(M_SWAP_DEFAULT), \
EQUAL(API_6(M_EQUAL_DEFAULT)))
ARRAY_DEF(files_array, ArchiveFile_t)
ALGO_DEF(files_array, ARRAY_OPLIST(files_array, M_OPL_ArchiveFile_t()))
ARRAY_DEF(
files_array,
ArchiveFile_t,
(INIT(API_2(ArchiveFile_t_init)),
SET(API_6(ArchiveFile_t_set)),
INIT_SET(API_6(ArchiveFile_t_init_set)),
CLEAR(API_2(ArchiveFile_t_clear))))
void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder, bool is_app);
bool archive_get_items(void* context, const char* path);

View File

@@ -19,7 +19,6 @@ static const char* ArchiveTabNames[] = {
[ArchiveTabBadUsb] = "Bad USB",
[ArchiveTabU2f] = "U2F",
[ArchiveTabApplications] = "Apps",
[ArchiveTabInternal] = "Internal",
[ArchiveTabBrowser] = "Browser",
};
@@ -398,20 +397,15 @@ static bool archive_view_input(InputEvent* event, void* context) {
bool in_menu;
bool move_fav_mode;
bool is_loading;
with_view_model(
browser->view,
ArchiveBrowserViewModel * model,
{
in_menu = model->menu;
move_fav_mode = model->move_fav;
is_loading = model->folder_loading || model->list_loading;
},
false);
if(is_loading) {
return false;
}
if(in_menu) {
if(event->type != InputTypeShort) {
return true; // RETURN
@@ -487,7 +481,7 @@ static bool archive_view_input(InputEvent* event, void* context) {
model->scroll_counter = 0;
}
},
false);
true);
archive_update_offset(browser);
}

View File

@@ -2,6 +2,7 @@
#include "../helpers/archive_files.h"
#include "../helpers/archive_favorites.h"
#include "../helpers/archive_menu.h"
#include <gui/gui_i.h>
#include <gui/view.h>
@@ -9,10 +10,7 @@
#include <gui/elements.h>
#include <gui/modules/file_browser_worker.h>
#include <storage/storage.h>
#include "../helpers/archive_files.h"
#include "../helpers/archive_menu.h"
#include "../helpers/archive_favorites.h"
#include "gui/modules/file_browser_worker.h"
#include <furi.h>
#define MAX_LEN_PX 110
#define MAX_NAME_LEN 255
@@ -31,7 +29,6 @@ typedef enum {
ArchiveTabBadUsb,
ArchiveTabU2f,
ArchiveTabApplications,
ArchiveTabInternal,
ArchiveTabBrowser,
ArchiveTabTotal,
} ArchiveTabEnum;

View File

@@ -115,12 +115,8 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
if(furi_hal_usb_is_locked()) {
app->error = BadUsbAppErrorCloseRpc;
app->usb_if_prev = NULL;
scene_manager_next_scene(app->scene_manager, BadUsbSceneError);
} else {
app->usb_if_prev = furi_hal_usb_get_config();
furi_check(furi_hal_usb_set_config(NULL, NULL));
if(!furi_string_empty(app->file_path)) {
app->bad_usb_script = bad_usb_script_open(app->file_path);
bad_usb_script_set_keyboard_layout(app->bad_usb_script, app->keyboard_layout);
@@ -142,10 +138,6 @@ void bad_usb_app_free(BadUsbApp* app) {
app->bad_usb_script = NULL;
}
if(app->usb_if_prev) {
furi_check(furi_hal_usb_set_config(app->usb_if_prev, NULL));
}
// Views
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork);
bad_usb_free(app->bad_usb_view);

View File

@@ -14,7 +14,6 @@
#include <gui/modules/variable_item_list.h>
#include <gui/modules/widget.h>
#include "views/bad_usb_view.h"
#include <furi_hal_usb.h>
#define BAD_USB_APP_BASE_FOLDER ANY_PATH("badusb")
#define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/assets/layouts"
@@ -40,8 +39,6 @@ struct BadUsbApp {
FuriString* keyboard_layout;
BadUsb* bad_usb_view;
BadUsbScript* bad_usb_script;
FuriHalUsbInterface* usb_if_prev;
};
typedef enum {

View File

@@ -490,6 +490,8 @@ static int32_t bad_usb_worker(void* context) {
BadUsbWorkerState worker_state = BadUsbStateInit;
int32_t delay_val = 0;
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
FURI_LOG_I(WORKER_TAG, "Init");
File* script_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
bad_usb->line = furi_string_alloc();
@@ -640,6 +642,8 @@ static int32_t bad_usb_worker(void* context) {
furi_hal_hid_set_state_callback(NULL, NULL);
furi_hal_usb_set_config(usb_mode_prev, NULL);
storage_file_close(script_file);
storage_file_free(script_file);
furi_string_free(bad_usb->line);

View File

@@ -117,15 +117,16 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
// First stage: coarse scan
for(size_t i = 0; i < subghz_setting_get_frequency_count(instance->setting); i++) {
uint32_t current_frequnecy = subghz_setting_get_frequency(instance->setting, i);
if(furi_hal_subghz_is_frequency_valid(current_frequnecy) &&
(current_frequnecy != 467750000) &&
if(furi_hal_subghz_is_frequency_valid(
subghz_setting_get_frequency(instance->setting, i)) &&
!((furi_hal_subghz.radio_type == SubGhzRadioExternal) &&
(current_frequnecy >= 311900000 && current_frequnecy <= 312200000))) {
(subghz_setting_get_frequency(instance->setting, i) >= 311900000 &&
subghz_setting_get_frequency(instance->setting, i) <= 312200000))) {
furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle);
cc1101_switch_to_idle(furi_hal_subghz.spi_bus_handle);
frequency =
cc1101_set_frequency(furi_hal_subghz.spi_bus_handle, current_frequnecy);
frequency = cc1101_set_frequency(
furi_hal_subghz.spi_bus_handle,
subghz_setting_get_frequency(instance->setting, i));
cc1101_calibrate(furi_hal_subghz.spi_bus_handle);
do {

View File

@@ -13,7 +13,7 @@ const char* const radio_modules_variables_text[] = {
#define DEBUG_P_COUNT 2
const char* const debug_pin_text[DEBUG_P_COUNT] = {
"OFF",
"17(1W)",
"A7",
};
static void subghz_scene_ext_module_changed(VariableItem* item) {

View File

@@ -208,38 +208,27 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
flipper_format_free(temp_fm_preset2);
// Pagers
// # HND - FM presets
FlipperFormat* temp_fm_preset3 = flipper_format_string_alloc();
flipper_format_write_string_cstr(
temp_fm_preset3,
(const char*)"Custom_preset_data",
(const char*)"02 0D 07 04 08 32 0B 06 10 64 11 93 12 0C 13 02 14 00 15 15 18 18 19 16 1B 07 1C 00 1D 91 20 FB 21 56 22 10 00 00 C0 00 00 00 00 00 00 00");
(const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00");
flipper_format_rewind(temp_fm_preset3);
subghz_setting_load_custom_preset(subghz->setting, (const char*)"Pagers", temp_fm_preset3);
subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_1", temp_fm_preset3);
flipper_format_free(temp_fm_preset3);
// # HND - FM presets
FlipperFormat* temp_fm_preset4 = flipper_format_string_alloc();
flipper_format_write_string_cstr(
temp_fm_preset4,
(const char*)"Custom_preset_data",
(const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00");
(const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 07 11 36 10 E9 15 32 18 18 19 16 1D 92 1C 40 1B 03 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00");
flipper_format_rewind(temp_fm_preset4);
subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_1", temp_fm_preset4);
subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_2", temp_fm_preset4);
flipper_format_free(temp_fm_preset4);
FlipperFormat* temp_fm_preset5 = flipper_format_string_alloc();
flipper_format_write_string_cstr(
temp_fm_preset5,
(const char*)"Custom_preset_data",
(const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 07 11 36 10 E9 15 32 18 18 19 16 1D 92 1C 40 1B 03 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00");
flipper_format_rewind(temp_fm_preset5);
subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_2", temp_fm_preset5);
flipper_format_free(temp_fm_preset5);
// custom presets loading - end
// Load last used values for Read, Read RAW, etc. or default

View File

@@ -598,7 +598,7 @@ void subghz_hopper_update(SubGhz* subghz) {
void subghz_speaker_on(SubGhz* subghz) {
if(subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(&ibutton_gpio);
furi_hal_subghz_set_async_mirror_pin(&gpio_ext_pa7);
}
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
@@ -643,7 +643,7 @@ void subghz_speaker_mute(SubGhz* subghz) {
void subghz_speaker_unmute(SubGhz* subghz) {
if(subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(&ibutton_gpio);
furi_hal_subghz_set_async_mirror_pin(&gpio_ext_pa7);
}
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_is_mine()) {

View File

@@ -645,4 +645,4 @@ SubGHzFrequencyAnalyzerFeedbackLevel subghz_frequency_analyzer_feedback_level(
float subghz_frequency_analyzer_get_trigger_level(SubGhzFrequencyAnalyzer* instance) {
furi_assert(instance);
return subghz_frequency_analyzer_worker_get_trigger_level(instance->worker);
}
}

View File

@@ -120,10 +120,7 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) {
furi_hal_subghz_rx();
} else {
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin,
GpioModeOutputPushPull,
GpioPullNo,
GpioSpeedLow);
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true);
if(!furi_hal_subghz_tx()) {
furi_hal_gpio_init(

View File

@@ -195,10 +195,6 @@ bool pocsag_pager_scene_receiver_on_event(void* context, SceneManagerEvent event
pcsg_hopper_update(app);
pocsag_pager_scene_receiver_update_statusbar(app);
}
// Get current RSSI
float rssi = furi_hal_subghz_get_rssi();
pcsg_receiver_rssi(app->pcsg_receiver, rssi);
if(app->txrx->txrx_state == PCSGTxRxStateRx) {
notification_message(app->notifications, &sequence_blink_cyan_10);
}

View File

@@ -12,8 +12,6 @@
#define MENU_ITEMS 4u
#define UNLOCK_CNT 3
#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f
typedef struct {
FuriString* item_str;
uint8_t type;
@@ -60,24 +58,8 @@ typedef struct {
uint16_t list_offset;
uint16_t history_item;
PCSGReceiverBarShow bar_show;
uint8_t u_rssi;
} PCSGReceiverModel;
void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi) {
furi_assert(instance);
with_view_model(
instance->view,
PCSGReceiverModel * model,
{
if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) {
model->u_rssi = 0;
} else {
model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN);
}
},
true);
}
void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock lock) {
furi_assert(pcsg_receiver);
pcsg_receiver->lock_count = 0;
@@ -185,23 +167,13 @@ static void pcsg_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scr
canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11);
}
static void pcsg_view_rssi_draw(Canvas* canvas, PCSGReceiverModel* model) {
for(uint8_t i = 1; i < model->u_rssi; i++) {
if(i % 5) {
canvas_draw_dot(canvas, 46 + i, 50);
canvas_draw_dot(canvas, 47 + i, 51);
canvas_draw_dot(canvas, 46 + i, 52);
}
}
}
void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) {
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
elements_button_left(canvas, "Config");
//canvas_draw_line(canvas, 46, 51, 125, 51);
canvas_draw_line(canvas, 46, 51, 125, 51);
bool scrollbar = model->history_item > 4;
FuriString* str_buff;
@@ -235,13 +207,10 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) {
canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 63, 46, "Scanning...");
//canvas_draw_line(canvas, 46, 51, 125, 51);
canvas_draw_line(canvas, 46, 51, 125, 51);
canvas_set_font(canvas, FontSecondary);
}
// Draw RSSI
pcsg_view_rssi_draw(canvas, model);
switch(model->bar_show) {
case PCSGReceiverBarShowLock:
canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8);

View File

@@ -8,8 +8,6 @@ typedef struct PCSGReceiver PCSGReceiver;
typedef void (*PCSGReceiverCallback)(PCSGCustomEvent event, void* context);
void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi);
void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock keyboard);
void pcsg_view_receiver_set_callback(

View File

@@ -34,10 +34,10 @@ void totp_cli_command_move_docopt_usage() {
void totp_cli_command_move_docopt_options() {
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME_PREFIX,
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME)) " New token name\r\n");
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME)) " New token name.\r\n");
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX_PREFIX,
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX)) " New token index\r\n");
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX)) " New token index.\r\n");
}
void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {

View File

@@ -20,7 +20,7 @@ void totp_cli_command_timezone_docopt_usage() {
void totp_cli_command_timezone_docopt_arguments() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE
" Timezone offset in hours to be set\r\n");
" Timezone offset in hours to be set.\r\n");
}
void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {

View File

@@ -196,7 +196,7 @@ static TotpConfigFileOpenResult totp_open_config_file(Storage* storage, FlipperF
return TotpConfigFileOpenSuccess;
}
static TotpConfigFileUpdateResult
TotpConfigFileUpdateResult
totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) {
TotpConfigFileUpdateResult update_result;
do {

View File

@@ -7,7 +7,6 @@
#include <flipper_format/flipper_format.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <dolphin/dolphin.h>
#include "services/config/config.h"
#include "types/plugin_state.h"
#include "types/token_info.h"
@@ -152,9 +151,6 @@ int32_t totp_app() {
return 253;
}
// Affecting dolphin level
DOLPHIN_DEED(DolphinDeedPluginStart);
// Set system callbacks
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex);

View File

@@ -195,10 +195,6 @@ bool weather_station_scene_receiver_on_event(void* context, SceneManagerEvent ev
ws_hopper_update(app);
weather_station_scene_receiver_update_statusbar(app);
}
// Get current RSSI
float rssi = furi_hal_subghz_get_rssi();
ws_receiver_rssi(app->ws_receiver, rssi);
if(app->txrx->txrx_state == WSTxRxStateRx) {
notification_message(app->notifications, &sequence_blink_cyan_10);
}

View File

@@ -12,7 +12,6 @@
#define MENU_ITEMS 4u
#define UNLOCK_CNT 3
#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f
typedef struct {
FuriString* item_str;
uint8_t type;
@@ -60,24 +59,8 @@ typedef struct {
uint16_t list_offset;
uint16_t history_item;
WSReceiverBarShow bar_show;
uint8_t u_rssi;
} WSReceiverModel;
void ws_receiver_rssi(WSReceiver* instance, float rssi) {
furi_assert(instance);
with_view_model(
instance->view,
WSReceiverModel * model,
{
if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) {
model->u_rssi = 0;
} else {
model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN);
}
},
true);
}
void ws_view_receiver_set_lock(WSReceiver* ws_receiver, WSLock lock) {
furi_assert(ws_receiver);
ws_receiver->lock_count = 0;
@@ -181,23 +164,13 @@ static void ws_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrol
canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11);
}
static void ws_view_rssi_draw(Canvas* canvas, WSReceiverModel* model) {
for(uint8_t i = 1; i < model->u_rssi; i++) {
if(i % 5) {
canvas_draw_dot(canvas, 46 + i, 50);
canvas_draw_dot(canvas, 47 + i, 51);
canvas_draw_dot(canvas, 46 + i, 52);
}
}
}
void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
elements_button_left(canvas, "Config");
//canvas_draw_line(canvas, 46, 51, 125, 51);
canvas_draw_line(canvas, 46, 51, 125, 51);
bool scrollbar = model->history_item > 4;
FuriString* str_buff;
@@ -230,13 +203,10 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 63, 46, "Scanning...");
//canvas_draw_line(canvas, 46, 51, 125, 51);
canvas_draw_line(canvas, 46, 51, 125, 51);
canvas_set_font(canvas, FontSecondary);
}
// Draw RSSI
ws_view_rssi_draw(canvas, model);
switch(model->bar_show) {
case WSReceiverBarShowLock:
canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8);

View File

@@ -8,8 +8,6 @@ typedef struct WSReceiver WSReceiver;
typedef void (*WSReceiverCallback)(WSCustomEvent event, void* context);
void ws_receiver_rssi(WSReceiver* instance, float rssi);
void ws_view_receiver_set_lock(WSReceiver* ws_receiver, WSLock keyboard);
void ws_view_receiver_set_callback(

View File

@@ -11,7 +11,6 @@
#include <core/check.h>
#include <core/common_defines.h>
#include <core/log.h>
#include "m-algo.h"
#include <m-array.h>
#define LIST_ITEMS 5u
@@ -34,7 +33,6 @@ typedef enum {
} BrowserItemType;
typedef struct {
uint32_t unsorted_idx;
FuriString* path;
BrowserItemType type;
uint8_t* custom_icon_data;
@@ -42,7 +40,6 @@ typedef struct {
} BrowserItem_t;
static void BrowserItem_t_init(BrowserItem_t* obj) {
obj->unsorted_idx = 0;
obj->type = BrowserItemTypeLoading;
obj->path = furi_string_alloc();
obj->display_name = furi_string_alloc();
@@ -50,7 +47,6 @@ static void BrowserItem_t_init(BrowserItem_t* obj) {
}
static void BrowserItem_t_init_set(BrowserItem_t* obj, const BrowserItem_t* src) {
obj->unsorted_idx = src->unsorted_idx;
obj->type = src->type;
obj->path = furi_string_alloc_set(src->path);
obj->display_name = furi_string_alloc_set(src->display_name);
@@ -63,7 +59,6 @@ static void BrowserItem_t_init_set(BrowserItem_t* obj, const BrowserItem_t* src)
}
static void BrowserItem_t_set(BrowserItem_t* obj, const BrowserItem_t* src) {
obj->unsorted_idx = src->unsorted_idx;
obj->type = src->type;
furi_string_set(obj->path, src->path);
furi_string_set(obj->display_name, src->display_name);
@@ -82,36 +77,13 @@ static void BrowserItem_t_clear(BrowserItem_t* obj) {
}
}
static int BrowserItem_t_cmp(const BrowserItem_t* a, const BrowserItem_t* b) {
// Back indicator comes before everything, then folders, then all other files.
if(a->type == BrowserItemTypeBack) {
return -1;
}
if(b->type == BrowserItemTypeBack) {
return 1;
}
if(a->type == BrowserItemTypeFolder && b->type != BrowserItemTypeFolder) {
return -1;
}
if(a->type != BrowserItemTypeFolder && b->type == BrowserItemTypeFolder) {
return 1;
}
return furi_string_cmpi(a->path, b->path);
}
#define M_OPL_BrowserItem_t() \
(INIT(API_2(BrowserItem_t_init)), \
SET(API_6(BrowserItem_t_set)), \
INIT_SET(API_6(BrowserItem_t_init_set)), \
CLEAR(API_2(BrowserItem_t_clear)), \
CMP(API_6(BrowserItem_t_cmp)), \
SWAP(M_SWAP_DEFAULT), \
EQUAL(API_6(M_EQUAL_DEFAULT)))
ARRAY_DEF(items_array, BrowserItem_t)
ALGO_DEF(items_array, ARRAY_OPLIST(items_array, M_OPL_BrowserItem_t()))
ARRAY_DEF(
items_array,
BrowserItem_t,
(INIT(API_2(BrowserItem_t_init)),
SET(API_6(BrowserItem_t_set)),
INIT_SET(API_6(BrowserItem_t_init_set)),
CLEAR(API_2(BrowserItem_t_clear))))
struct FileBrowser {
View* view;
@@ -161,12 +133,8 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context);
static void
browser_folder_open_cb(void* context, uint32_t item_cnt, int32_t file_idx, bool is_root);
static void browser_list_load_cb(void* context, uint32_t list_load_offset);
static void browser_list_item_cb(
void* context,
FuriString* item_path,
uint32_t idx,
bool is_folder,
bool is_last);
static void
browser_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last);
static void browser_long_load_cb(void* context);
static void file_browser_scroll_timer_callback(void* context) {
@@ -355,7 +323,7 @@ static void browser_update_offset(FileBrowser* browser) {
CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0);
}
},
true);
false);
}
static void
@@ -387,7 +355,7 @@ static void
model->list_loading = true;
model->folder_loading = false;
},
false);
true);
browser_update_offset(browser);
file_browser_worker_load(browser->worker, load_offset, ITEM_LIST_LEN_MAX);
@@ -420,18 +388,13 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset) {
BrowserItem_t_clear(&back_item);
}
static void browser_list_item_cb(
void* context,
FuriString* item_path,
uint32_t idx,
bool is_folder,
bool is_last) {
static void
browser_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last) {
furi_assert(context);
FileBrowser* browser = (FileBrowser*)context;
BrowserItem_t item;
item.custom_icon_data = NULL;
item.unsorted_idx = idx;
if(!is_last) {
item.path = furi_string_alloc_set(item_path);
@@ -467,7 +430,7 @@ static void browser_list_item_cb(
items_array_push_back(model->items, item);
// TODO: calculate if element is visible
},
false);
true);
furi_string_free(item.display_name);
furi_string_free(item.path);
if(item.custom_icon_data) {
@@ -475,31 +438,7 @@ static void browser_list_item_cb(
}
} else {
with_view_model(
browser->view,
FileBrowserModel * model,
{
if(model->item_cnt <= BROWSER_SORT_THRESHOLD) {
FuriString* selected = NULL;
if(model->item_idx > 0) {
selected = furi_string_alloc_set(
items_array_get(model->items, model->item_idx)->path);
}
items_array_sort(model->items);
if(selected != NULL) {
for(uint32_t i = 0; i < model->item_cnt; i++) {
if(!furi_string_cmp(items_array_get(model->items, i)->path, selected)) {
model->item_idx = i;
break;
}
}
}
}
model->list_loading = false;
},
false);
browser_update_offset(browser);
browser->view, FileBrowserModel * model, { model->list_loading = false; }, true);
}
}
@@ -546,25 +485,19 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) {
for(uint32_t i = 0; i < MIN(model->item_cnt, LIST_ITEMS); i++) {
int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->item_cnt, 0u);
BrowserItemType item_type;
BrowserItemType item_type = BrowserItemTypeLoading;
uint8_t* custom_icon_data = NULL;
if(browser_is_item_in_array(model, idx)) {
BrowserItem_t* item = items_array_get(
model->items, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0));
item_type = item->type;
if(model->list_loading && item_type != BrowserItemTypeBack) {
furi_string_set(filename, "---");
item_type = BrowserItemTypeLoading;
} else {
furi_string_set(filename, item->display_name);
if(item_type == BrowserItemTypeFile) {
custom_icon_data = item->custom_icon_data;
}
furi_string_set(filename, item->display_name);
if(item_type == BrowserItemTypeFile) {
custom_icon_data = item->custom_icon_data;
}
} else {
furi_string_set(filename, "---");
item_type = BrowserItemTypeLoading;
}
if(item_type == BrowserItemTypeBack) {
@@ -646,10 +579,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
bool is_loading = false;
with_view_model(
browser->view,
FileBrowserModel * model,
{ is_loading = model->folder_loading || model->list_loading; },
false);
browser->view, FileBrowserModel * model, { is_loading = model->folder_loading; }, false);
if(is_loading) {
return false;
@@ -686,7 +616,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
model->scroll_counter = 0;
}
},
false);
true);
browser_update_offset(browser);
consumed = true;
}
@@ -701,7 +631,10 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
if(browser_is_item_in_array(model, model->item_idx)) {
selected_item =
items_array_get(model->items, model->item_idx - model->array_offset);
select_index = selected_item->unsorted_idx;
select_index = model->item_idx;
if((!model->is_root) && (select_index > 0)) {
select_index -= 1;
}
}
},
false);

View File

@@ -189,12 +189,8 @@ static bool browser_folder_init(
return state;
}
// Load files list by chunks, like it was originally, not compatible with sorting, sorting needs to be disabled to use this
static bool browser_folder_load_chunked(
BrowserWorker* browser,
FuriString* path,
uint32_t offset,
uint32_t count) {
static bool
browser_folder_load(BrowserWorker* browser, FuriString* path, uint32_t offset, uint32_t count) {
FileInfo file_info;
Storage* storage = furi_record_open(RECORD_STORAGE);
@@ -244,11 +240,7 @@ static bool browser_folder_load_chunked(
furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp);
if(browser->list_item_cb) {
browser->list_item_cb(
browser->cb_ctx,
name_str,
items_cnt,
(file_info.flags & FSF_DIRECTORY),
false);
browser->cb_ctx, name_str, (file_info.flags & FSF_DIRECTORY), false);
}
items_cnt++;
}
@@ -257,7 +249,7 @@ static bool browser_folder_load_chunked(
}
}
if(browser->list_item_cb) {
browser->list_item_cb(browser->cb_ctx, NULL, 0, false, true);
browser->list_item_cb(browser->cb_ctx, NULL, false, true);
}
} while(0);
@@ -271,59 +263,6 @@ static bool browser_folder_load_chunked(
return (items_cnt == count);
}
// Load all files at once, may cause memory overflow so need to limit that to about 400 files
static bool browser_folder_load_full(BrowserWorker* browser, FuriString* path) {
FileInfo file_info;
Storage* storage = furi_record_open(RECORD_STORAGE);
File* directory = storage_file_alloc(storage);
char name_temp[FILE_NAME_LEN_MAX];
FuriString* name_str;
name_str = furi_string_alloc();
uint32_t items_cnt = 0;
bool ret = false;
do {
if(!storage_dir_open(directory, furi_string_get_cstr(path))) {
break;
}
if(browser->list_load_cb) {
browser->list_load_cb(browser->cb_ctx, 0);
}
while(storage_dir_read(directory, &file_info, name_temp, FILE_NAME_LEN_MAX) &&
storage_file_get_error(directory) == FSE_OK) {
furi_string_set(name_str, name_temp);
if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) {
furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp);
if(browser->list_item_cb) {
browser->list_item_cb(
browser->cb_ctx,
name_str,
items_cnt,
(file_info.flags & FSF_DIRECTORY),
false);
}
items_cnt++;
}
}
if(browser->list_item_cb) {
browser->list_item_cb(browser->cb_ctx, NULL, 0, false, true);
}
ret = true;
} while(0);
furi_string_free(name_str);
storage_dir_close(directory);
storage_file_free(directory);
furi_record_close(RECORD_STORAGE);
return ret;
}
static int32_t browser_worker(void* context) {
BrowserWorker* browser = (BrowserWorker*)context;
furi_assert(browser);
@@ -418,12 +357,7 @@ static int32_t browser_worker(void* context) {
if(flags & WorkerEvtLoad) {
FURI_LOG_D(
TAG, "Load offset: %lu cnt: %lu", browser->load_offset, browser->load_count);
if(items_cnt > BROWSER_SORT_THRESHOLD) {
browser_folder_load_chunked(
browser, path, browser->load_offset, browser->load_count);
} else {
browser_folder_load_full(browser, path);
}
browser_folder_load(browser, path, browser->load_offset, browser->load_count);
}
if(flags & WorkerEvtStop) {

View File

@@ -7,8 +7,6 @@
extern "C" {
#endif
#define BROWSER_SORT_THRESHOLD 400
typedef struct BrowserWorker BrowserWorker;
typedef void (*BrowserWorkerFolderOpenCallback)(
void* context,
@@ -19,7 +17,6 @@ typedef void (*BrowserWorkerListLoadCallback)(void* context, uint32_t list_load_
typedef void (*BrowserWorkerListItemCallback)(
void* context,
FuriString* item_path,
uint32_t idx,
bool is_folder,
bool is_last);
typedef void (*BrowserWorkerLongLoadCallback)(void* context);

View File

@@ -58,12 +58,8 @@ bool updater_scene_error_on_event(void* context, SceneManagerEvent event) {
}
void updater_scene_error_on_exit(void* context) {
furi_assert(context);
Updater* updater = (Updater*)context;
widget_reset(updater->widget);
if(updater->loaded_manifest) {
update_manifest_free(updater->loaded_manifest);
}
free(updater->pending_update);
}

View File

@@ -21,9 +21,11 @@ void updater_scene_loadcfg_apply_callback(GuiButtonType result, InputType type,
void updater_scene_loadcfg_on_enter(void* context) {
Updater* updater = (Updater*)context;
UpdateManifest* loaded_manifest = updater->loaded_manifest = update_manifest_alloc();
UpdaterManifestProcessingState* pending_upd = updater->pending_update =
malloc(sizeof(UpdaterManifestProcessingState));
pending_upd->manifest = update_manifest_alloc();
if(update_manifest_init(loaded_manifest, furi_string_get_cstr(updater->startup_arg))) {
if(update_manifest_init(pending_upd->manifest, furi_string_get_cstr(updater->startup_arg))) {
widget_add_string_element(
updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update");
@@ -35,7 +37,7 @@ void updater_scene_loadcfg_on_enter(void* context) {
32,
AlignCenter,
AlignCenter,
furi_string_get_cstr(loaded_manifest->version),
furi_string_get_cstr(pending_upd->manifest->version),
true);
widget_add_button_element(
@@ -93,12 +95,13 @@ bool updater_scene_loadcfg_on_event(void* context, SceneManagerEvent event) {
}
void updater_scene_loadcfg_on_exit(void* context) {
furi_assert(context);
Updater* updater = (Updater*)context;
widget_reset(updater->widget);
if(updater->loaded_manifest) {
update_manifest_free(updater->loaded_manifest);
if(updater->pending_update) {
update_manifest_free(updater->pending_update->manifest);
furi_string_free(updater->pending_update->message);
}
widget_reset(updater->widget);
free(updater->pending_update);
}

View File

@@ -33,6 +33,12 @@ typedef enum {
UpdaterCustomEventSdUnmounted,
} UpdaterCustomEvent;
typedef struct UpdaterManifestProcessingState {
UpdateManifest* manifest;
FuriString* message;
bool ready_to_be_applied;
} UpdaterManifestProcessingState;
typedef struct {
// GUI
Gui* gui;
@@ -43,7 +49,7 @@ typedef struct {
UpdaterMainView* main_view;
UpdateManifest* loaded_manifest;
UpdaterManifestProcessingState* pending_update;
UpdatePrepareResult preparation_result;
UpdateTask* update_task;

View File

@@ -41,22 +41,22 @@ typedef struct {
static const UpdateTaskStageGroupMap update_task_stage_progress[] = {
[UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0),
[UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 45),
[UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5),
[UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5),
[UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 15),
[UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 15),
[UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 35),
[UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
[UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 30),
[UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 5),
[UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
[UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 80),
[UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
[UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 80),
[UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 2),
[UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 10),
[UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30),
[UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 150),
[UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 15),
[UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 50),
[UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 200),
[UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30),
[UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 5),
[UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 30),
[UpdateTaskStageResourcesUpdate] = STAGE_DEF(UpdateTaskStageGroupResources, 255),
[UpdateTaskStageSplashscreenInstall] = STAGE_DEF(UpdateTaskStageGroupSplashscreen, 5),

View File

@@ -41,14 +41,6 @@ static bool update_task_pre_update(UpdateTask* update_task) {
return success;
}
typedef enum {
UpdateTaskResourcesWeightsFileCleanup = 20,
UpdateTaskResourcesWeightsDirCleanup = 20,
UpdateTaskResourcesWeightsFileUnpack = 60,
} UpdateTaskResourcesWeights;
#define UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT 90
typedef struct {
UpdateTask* update_task;
int32_t total_files, processed_files;
@@ -62,36 +54,33 @@ static bool update_task_resource_unpack_cb(const char* name, bool is_directory,
update_task_set_progress(
unpack_progress->update_task,
UpdateTaskStageProgress,
/* For this stage, last progress segment = extraction */
(UpdateTaskResourcesWeightsFileCleanup + UpdateTaskResourcesWeightsDirCleanup) +
(unpack_progress->processed_files * UpdateTaskResourcesWeightsFileUnpack) /
(unpack_progress->total_files + 1));
/* For this stage, last 70% of progress = extraction */
30 + (unpack_progress->processed_files * 70) / (unpack_progress->total_files + 1));
return true;
}
static void update_task_cleanup_resources(UpdateTask* update_task, const uint32_t n_tar_entries) {
static void
update_task_cleanup_resources(UpdateTask* update_task, uint32_t n_approx_file_entries) {
ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(update_task->storage);
do {
FURI_LOG_D(TAG, "Cleaning up old manifest");
FURI_LOG_I(TAG, "Cleaning up old manifest");
if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("Manifest"))) {
FURI_LOG_W(TAG, "No existing manifest");
break;
}
const uint32_t n_approx_file_entries =
n_tar_entries * UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT / 100 + 1;
uint32_t n_dir_entries = 1;
/* We got # of entries in TAR file. Approx 1/4th is dir entries, we skip them */
n_approx_file_entries = n_approx_file_entries * 3 / 4 + 1;
uint32_t n_processed_files = 0;
ResourceManifestEntry* entry_ptr = NULL;
uint32_t n_processed_entries = 0;
while((entry_ptr = resource_manifest_reader_next(manifest_reader))) {
if(entry_ptr->type == ResourceManifestEntryTypeFile) {
update_task_set_progress(
update_task,
UpdateTaskStageProgress,
/* For this stage, first pass = old manifest's file cleanup */
(n_processed_entries++ * UpdateTaskResourcesWeightsFileCleanup) /
n_approx_file_entries);
/* For this stage, first 20% of progress = cleanup files */
(n_processed_files++ * 20) / (n_approx_file_entries + 1));
FuriString* file_path = furi_string_alloc();
path_concat(
@@ -99,21 +88,16 @@ static void update_task_cleanup_resources(UpdateTask* update_task, const uint32_
FURI_LOG_D(TAG, "Removing %s", furi_string_get_cstr(file_path));
storage_simply_remove(update_task->storage, furi_string_get_cstr(file_path));
furi_string_free(file_path);
} else if(entry_ptr->type == ResourceManifestEntryTypeDirectory) {
n_dir_entries++;
}
}
n_processed_entries = 0;
while((entry_ptr = resource_manifest_reader_previous(manifest_reader))) {
if(entry_ptr->type == ResourceManifestEntryTypeDirectory) {
update_task_set_progress(
update_task,
UpdateTaskStageProgress,
/* For this stage, second 10% of progress = cleanup directories */
UpdateTaskResourcesWeightsFileCleanup +
(n_processed_entries++ * UpdateTaskResourcesWeightsDirCleanup) /
n_dir_entries);
(n_processed_files++ * 10) / (n_approx_file_entries + 1));
FuriString* folder_path = furi_string_alloc();
File* folder_file = storage_file_alloc(update_task->storage);

View File

@@ -44,15 +44,13 @@ volatile FuriHalSubGhz furi_hal_subghz = {
bool furi_hal_subghz_set_radio_type(SubGhzRadioType state) {
furi_hal_subghz.radio_type = state;
furi_hal_spi_bus_handle_deinit(furi_hal_subghz.spi_bus_handle);
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
furi_hal_subghz.spi_bus_handle = &furi_hal_spi_bus_handle_subghz;
furi_hal_subghz.cc1101_g0_pin = &gpio_cc1101_g0;
} else {
if(state) {
furi_hal_subghz.spi_bus_handle = &furi_hal_spi_bus_handle_subghz_ext;
furi_hal_subghz.cc1101_g0_pin = &gpio_cc1101_g0_ext;
} else {
furi_hal_subghz.spi_bus_handle = &furi_hal_spi_bus_handle_subghz;
furi_hal_subghz.cc1101_g0_pin = &gpio_cc1101_g0;
}
furi_hal_spi_bus_handle_init(furi_hal_subghz.spi_bus_handle);
furi_hal_subghz_init_check();
return true;
@@ -123,26 +121,37 @@ bool furi_hal_subghz_init_check(void) {
// Prepare GD0 for power on self test
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
// GD0 low
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW);
uint32_t test_start_time = furi_get_tick();
while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != false && result) {
if(furi_get_tick() - test_start_time > INIT_TIMEOUT) {
result = false;
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
// GD0 low
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW);
uint32_t test_start_time = furi_get_tick();
while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != false && result) {
if(furi_get_tick() - test_start_time > INIT_TIMEOUT) {
result = false;
}
}
}
// GD0 high
cc1101_write_reg(
furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
test_start_time = furi_get_tick();
while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != true && result) {
if(furi_get_tick() - test_start_time > INIT_TIMEOUT) {
result = false;
// GD0 high
cc1101_write_reg(
furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
test_start_time = furi_get_tick();
while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != true && result) {
if(furi_get_tick() - test_start_time > INIT_TIMEOUT) {
result = false;
}
}
}
} else {
// GD0 low
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW);
while(furi_hal_gpio_read(&gpio_cc1101_g0) != false)
;
// GD0 high
cc1101_write_reg(
furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
while(furi_hal_gpio_read(&gpio_cc1101_g0) != true)
;
}
// Reset GD0 to floating state
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance);
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
@@ -424,8 +433,8 @@ bool furi_hal_subghz_is_tx_allowed(uint32_t value) {
flipper_format_free(fff_data_file);
furi_record_close(RECORD_STORAGE);
if(!(value >= 299999755 && value <= 350000335) && // was increased from 348 to 350
!(value >= 386999938 && value <= 467750000) && // was increased from 464 to 467.75
if(!(value >= 299999755 && value <= 350000335) &&
!(value >= 386999938 && value <= 464000000) &&
!(value >= 778999847 && value <= 928000000) && !(is_extended)) {
FURI_LOG_I(TAG, "Frequency blocked - outside default range");
return false;
@@ -505,55 +514,56 @@ volatile uint32_t furi_hal_subghz_capture_delta_duration = 0;
volatile FuriHalSubGhzCaptureCallback furi_hal_subghz_capture_callback = NULL;
volatile void* furi_hal_subghz_capture_callback_context = NULL;
static void furi_hal_subghz_capture_int_ISR() {
// Channel 1
if(LL_TIM_IsActiveFlag_CC1(TIM2)) {
LL_TIM_ClearFlag_CC1(TIM2);
furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
if(furi_hal_subghz_capture_callback) {
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
static void furi_hal_subghz_capture_ISR() {
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
if(!furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin)) {
if(furi_hal_subghz_capture_callback) {
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
furi_hal_subghz_capture_callback(
true,
furi_hal_subghz_capture_delta_duration,
(void*)furi_hal_subghz_capture_callback_context);
}
}
// Channel 2
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
LL_TIM_ClearFlag_CC2(TIM2);
if(furi_hal_subghz_capture_callback) {
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
furi_hal_subghz_capture_callback(
false,
LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
(void*)furi_hal_subghz_capture_callback_context);
}
}
}
static void furi_hal_subghz_capture_ext_ISR() {
if(!furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin)) {
if(furi_hal_subghz_capture_callback) {
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
furi_hal_subghz_capture_callback(
true, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context);
furi_hal_subghz_capture_callback(
true, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context);
}
} else {
if(furi_hal_subghz_capture_callback) {
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
furi_hal_subghz_capture_callback(
false, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context);
}
}
//Forced correction for improved accuracy
TIM2->CNT = 7;
} else {
if(furi_hal_subghz_capture_callback) {
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
// Channel 1
if(LL_TIM_IsActiveFlag_CC1(TIM2)) {
LL_TIM_ClearFlag_CC1(TIM2);
furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
if(furi_hal_subghz_capture_callback) {
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
furi_hal_subghz_capture_callback(
false, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context);
furi_hal_subghz_capture_callback(
true,
furi_hal_subghz_capture_delta_duration,
(void*)furi_hal_subghz_capture_callback_context);
}
}
// Channel 2
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
LL_TIM_ClearFlag_CC2(TIM2);
if(furi_hal_subghz_capture_callback) {
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
furi_hal_subghz_capture_callback(
false,
LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
(void*)furi_hal_subghz_capture_callback_context);
}
}
}
TIM2->CNT = 6;
}
void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* context) {
@@ -563,27 +573,43 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
furi_hal_subghz_capture_callback = callback;
furi_hal_subghz_capture_callback_context = context;
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin,
GpioModeInterruptRiseFall,
GpioPullUp,
GpioSpeedVeryHigh);
furi_hal_gpio_add_int_callback(
furi_hal_subghz.cc1101_g0_pin,
furi_hal_subghz_capture_ISR,
furi_hal_subghz_capture_callback);
furi_hal_gpio_enable_int_callback(furi_hal_subghz.cc1101_g0_pin);
} else {
furi_hal_gpio_init_ex(
&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
}
// Timer: base
LL_TIM_InitTypeDef TIM_InitStruct = {0};
TIM_InitStruct.Prescaler = 64 - 1;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
// Clock division for capture filter (for internal radio)
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4; // Clock division for capture filter
LL_TIM_Init(TIM2, &TIM_InitStruct);
// Timer: advanced
LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_DisableARRPreload(TIM2);
LL_TIM_DisableDMAReq_TRIG(TIM2);
LL_TIM_DisableIT_TRIG(TIM2);
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_TI2FP2);
LL_TIM_SetSlaveMode(TIM2, LL_TIM_SLAVEMODE_RESET);
LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);
LL_TIM_EnableMasterSlaveMode(TIM2);
}
LL_TIM_DisableDMAReq_TRIG(TIM2);
LL_TIM_DisableIT_TRIG(TIM2);
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
// Timer: channel 1 indirect
LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_INDIRECTTI);
LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
@@ -597,31 +623,13 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV32_N8);
// ISR setup
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_subghz_capture_int_ISR, NULL);
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_subghz_capture_ISR, NULL);
// Interrupts and channels
LL_TIM_EnableIT_CC1(TIM2);
LL_TIM_EnableIT_CC2(TIM2);
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
furi_hal_gpio_init_ex(
furi_hal_subghz.cc1101_g0_pin,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedLow,
GpioAltFn1TIM2);
} else {
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin,
GpioModeInterruptRiseFall,
GpioPullUp,
GpioSpeedVeryHigh);
furi_hal_gpio_add_int_callback(
furi_hal_subghz.cc1101_g0_pin,
furi_hal_subghz_capture_ext_ISR,
furi_hal_subghz_capture_callback);
furi_hal_gpio_enable_int_callback(furi_hal_subghz.cc1101_g0_pin);
}
// Start timer
@@ -654,9 +662,6 @@ void furi_hal_subghz_stop_async_rx() {
FURI_CRITICAL_EXIT();
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
} else {
furi_hal_gpio_disable_int_callback(furi_hal_subghz.cc1101_g0_pin);
furi_hal_gpio_remove_int_callback(furi_hal_subghz.cc1101_g0_pin);
}
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
@@ -791,19 +796,18 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
furi_hal_subghz_async_tx.buffer =
malloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t));
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true);
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
} else {
// Connect CC1101_GD0 to TIM2 as output
furi_hal_gpio_init_ex(
furi_hal_subghz.cc1101_g0_pin,
&gpio_cc1101_g0,
GpioModeAltFunctionPushPull,
GpioPullDown,
GpioSpeedLow,
GpioAltFn1TIM2);
} else {
//Signal generation with mem-to-mem DMA
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true);
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
}
// Configure DMA
@@ -864,28 +868,22 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
LL_TIM_SetCounter(TIM2, 0);
LL_TIM_EnableCounter(TIM2);
// Start debug
if(furi_hal_subghz_start_debug() || furi_hal_subghz.radio_type == SubGhzRadioExternal) {
const GpioPin* gpio = furi_hal_subghz.cc1101_g0_pin;
//Preparing bit mask
//Debug pin is may be only PORTB! (PB0, PB1, .., PB15)
furi_hal_subghz_debug_gpio_buff[0] = 0;
furi_hal_subghz_debug_gpio_buff[1] = 0;
//Signal generation for external module
//Mirror pin (for example, speaker)
if(furi_hal_subghz.async_mirror_pin != NULL) {
furi_hal_subghz_debug_gpio_buff[0] |= (uint32_t)furi_hal_subghz.async_mirror_pin->pin
<< GPIO_NUMBER;
furi_hal_subghz_debug_gpio_buff[1] |= furi_hal_subghz.async_mirror_pin->pin;
gpio = furi_hal_subghz.async_mirror_pin;
}
// Start debug (and speaker)
furi_hal_subghz_start_debug();
//G0 singnal generation for external radio
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
furi_hal_subghz_debug_gpio_buff[0] |= (uint32_t)furi_hal_subghz.cc1101_g0_pin->pin
<< GPIO_NUMBER;
furi_hal_subghz_debug_gpio_buff[1] |= furi_hal_subghz.cc1101_g0_pin->pin;
}
const GpioPin* gpio = furi_hal_subghz.cc1101_g0_pin;
if((furi_hal_subghz.async_mirror_pin != NULL) &&
(furi_hal_subghz.radio_type == SubGhzRadioInternal)) {
gpio = furi_hal_subghz.async_mirror_pin;
}
if(((furi_hal_subghz.async_mirror_pin != NULL) &&
(furi_hal_subghz.radio_type == SubGhzRadioInternal)) ||
(furi_hal_subghz.radio_type == SubGhzRadioExternal)) {
furi_hal_subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER;
furi_hal_subghz_debug_gpio_buff[1] = gpio->pin;
dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_debug_gpio_buff;
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->BSRR);

View File

@@ -340,7 +340,7 @@ static void usb_process_mode_start(FuriHalUsbInterface* interface, void* context
}
static void usb_process_mode_change(FuriHalUsbInterface* interface, void* context) {
if((interface != usb.interface) || (context != usb.interface_context)) {
if(interface != usb.interface) {
if(usb.enabled) {
// Disable current interface
susp_evt(&udev, 0, 0);

View File

@@ -237,8 +237,10 @@ void ibutton_worker_emulate_timer_cb(void* context) {
const LevelDuration level_duration =
protocol_dict_encoder_yield(worker->protocols, worker->protocol_to_encode);
furi_hal_ibutton_emulate_set_next(level_duration_get_duration(level_duration));
furi_hal_ibutton_pin_write(level_duration_get_level(level_duration));
const bool level = level_duration_get_level(level_duration);
furi_hal_ibutton_emulate_set_next(level);
furi_hal_ibutton_pin_write(level);
}
void ibutton_worker_emulate_timer_start(iButtonWorker* worker) {

View File

@@ -100,7 +100,7 @@ void* subghz_protocol_encoder_nice_flor_s_alloc(SubGhzEnvironment* environment)
TAG, "Loading rainbow table from %s", instance->nice_flor_s_rainbow_table_file_name);
}
instance->encoder.repeat = 10;
instance->encoder.size_upload = 2400; //wrong!! upload 186*16 = 2976 - actual size about 1728
instance->encoder.size_upload = 1728; //wrong!! upload 186*16 = 2976 - actual size about 1728
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
instance->encoder.is_running = false;
return instance;
@@ -113,8 +113,6 @@ void subghz_protocol_encoder_nice_flor_s_free(void* context) {
free(instance);
}
static void subghz_protocol_nice_one_get_data(uint8_t* p, uint8_t num_parcel, uint8_t hold_bit);
/**
* Generating an upload from data.
* @param instance Pointer to a SubGhzProtocolEncoderNiceFlorS instance
@@ -162,8 +160,8 @@ static void subghz_protocol_encoder_nice_flor_s_get_upload(
level_duration_make(false, (uint32_t)subghz_protocol_nice_flor_s_const.te_short * 3);
//Send key data
for(uint8_t j = 52; j > 0; j--) {
if(bit_read(instance->generic.data, j - 1)) {
for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
if(bit_read(instance->generic.data, i - 1)) {
//send bit 1
instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_nice_flor_s_const.te_long);
@@ -177,35 +175,6 @@ static void subghz_protocol_encoder_nice_flor_s_get_upload(
false, (uint32_t)subghz_protocol_nice_flor_s_const.te_long);
}
}
if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) {
uint8_t add_data[10] = {0};
for(size_t i = 0; i < 7; i++) {
add_data[i] = (instance->generic.data >> (48 - i * 8)) & 0xFF;
}
subghz_protocol_nice_one_get_data(add_data, loops[i], loops[i]);
instance->generic.data_2 = 0;
for(size_t j = 7; j < 10; j++) {
instance->generic.data_2 <<= 8;
instance->generic.data_2 += add_data[j];
}
//Send key data
for(uint8_t j = 24; j > 4; j--) {
if(bit_read(instance->generic.data_2, j - 1)) {
//send bit 1
instance->encoder.upload[index++] = level_duration_make(
true, (uint32_t)subghz_protocol_nice_flor_s_const.te_long);
instance->encoder.upload[index++] = level_duration_make(
false, (uint32_t)subghz_protocol_nice_flor_s_const.te_short);
} else {
//send bit 0
instance->encoder.upload[index++] = level_duration_make(
true, (uint32_t)subghz_protocol_nice_flor_s_const.te_short);
instance->encoder.upload[index++] = level_duration_make(
false, (uint32_t)subghz_protocol_nice_flor_s_const.te_long);
}
}
}
//Send stop bit
instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_nice_flor_s_const.te_short * 3);
@@ -228,8 +197,6 @@ bool subghz_protocol_encoder_nice_flor_s_deserialize(void* context, FlipperForma
//optional parameter parameter
flipper_format_read_uint32(
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
// flipper_format_read_uint32(
// flipper_format, "Data", (uint32_t*)&instance->generic.data_2, 1);
subghz_protocol_nice_flor_s_remote_controller(
&instance->generic, instance->nice_flor_s_rainbow_table_file_name);
@@ -249,17 +216,6 @@ bool subghz_protocol_encoder_nice_flor_s_deserialize(void* context, FlipperForma
break;
}
if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) {
if(!flipper_format_rewind(flipper_format)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
uint32_t temp = (instance->generic.data_2 >> 4) & 0xFFFFF;
if(!flipper_format_update_uint32(flipper_format, "Data", &temp, 1)) {
FURI_LOG_E(TAG, "Unable to add Data");
}
}
instance->encoder.is_running = true;
res = true;
@@ -291,63 +247,63 @@ LevelDuration subghz_protocol_encoder_nice_flor_s_yield(void* context) {
return ret;
}
/**
* Read bytes from rainbow table
* @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-P8-P9-P10
* @return crc
*/
static uint32_t subghz_protocol_nice_one_crc(uint8_t* p) {
uint8_t crc = 0;
uint8_t crc_data = 0xff;
for(uint8_t i = 4; i < 68; i++) {
if(subghz_protocol_blocks_get_bit_array(p, i)) {
crc = crc_data ^ 1;
} else {
crc = crc_data;
}
crc_data >>= 1;
if((crc & 0x01)) {
crc_data ^= 0x97;
}
}
crc = 0;
for(uint8_t i = 0; i < 8; i++) {
crc <<= 1;
if((crc_data >> i) & 0x01) crc = crc | 1;
}
return crc;
}
// /**
// * Read bytes from rainbow table
// * @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-P8-P9-P10
// * @return crc
// */
// static uint32_t subghz_protocol_nice_one_crc(uint8_t* p) {
// uint8_t crc = 0;
// uint8_t crc_data = 0xff;
// for(uint8_t i = 4; i < 68; i++) {
// if(subghz_protocol_blocks_get_bit_array(p, i)) {
// crc = crc_data ^ 1;
// } else {
// crc = crc_data;
// }
// crc_data >>= 1;
// if((crc & 0x01)) {
// crc_data ^= 0x97;
// }
// }
// crc = 0;
// for(uint8_t i = 0; i < 8; i++) {
// crc <<= 1;
// if((crc_data >> i) & 0x01) crc = crc | 1;
// }
// return crc;
// }
/**
* Read bytes from rainbow table
* @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-XX-XX-XX
* @param num_parcel parcel number 0..15
* @param hold_bit 0 - the button was only pressed, 1 - the button was held down
*/
static void subghz_protocol_nice_one_get_data(uint8_t* p, uint8_t num_parcel, uint8_t hold_bit) {
uint8_t k = 0;
uint8_t crc = 0;
p[1] = (p[1] & 0x0f) | ((0x0f ^ (p[0] & 0x0F) ^ num_parcel) << 4);
if(num_parcel < 4) {
k = 0x8f;
} else {
k = 0x80;
}
// /**
// * Read bytes from rainbow table
// * @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-XX-XX-XX
// * @param num_parcel parcel number 0..15
// * @param hold_bit 0 - the button was only pressed, 1 - the button was held down
// */
// static void subghz_protocol_nice_one_get_data(uint8_t* p, uint8_t num_parcel, uint8_t hold_bit) {
// uint8_t k = 0;
// uint8_t crc = 0;
// p[1] = (p[1] & 0x0f) | ((0x0f ^ (p[0] & 0x0F) ^ num_parcel) << 4);
// if(num_parcel < 4) {
// k = 0x8f;
// } else {
// k = 0x80;
// }
if(!hold_bit) {
hold_bit = 0;
} else {
hold_bit = 0x10;
}
k = num_parcel ^ k;
p[7] = k;
p[8] = hold_bit ^ (k << 4);
// if(!hold_bit) {
// hold_bit = 0;
// } else {
// hold_bit = 0x10;
// }
// k = num_parcel ^ k;
// p[7] = k;
// p[8] = hold_bit ^ (k << 4);
crc = subghz_protocol_nice_one_crc(p);
// crc = subghz_protocol_nice_one_crc(p);
p[8] |= crc >> 4;
p[9] = crc << 4;
}
// p[8] |= crc >> 4;
// p[9] = crc << 4;
// }
/**
* Read bytes from rainbow table

View File

@@ -1,309 +0,0 @@
#include "revers.h"
#include "../blocks/const.h"
#include "../blocks/decoder.h"
#include "../blocks/encoder.h"
#include "../blocks/generic.h"
#include "../blocks/math.h"
#define TAG "SubGhzProtocolRevers"
static const SubGhzBlockConst subghz_protocol_revers_const = {
.te_short = 200,
.te_long = 430,
.te_delta = 80,
.min_count_bit_for_found = 8,
};
struct SubGhzProtocolDecoderRevers {
SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder;
SubGhzBlockGeneric generic;
uint32_t last_data;
uint16_t header_count;
};
struct SubGhzProtocolEncoderRevers {
SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder;
SubGhzBlockGeneric generic;
};
typedef enum {
ReversDecoderStepReset = 0,
ReversDecoderStepCheckPreambula,
ReversDecoderStepSaveDuration,
ReversDecoderStepCheckDuration,
} ReversDecoderStep;
const SubGhzProtocolDecoder subghz_protocol_revers_decoder = {
.alloc = subghz_protocol_decoder_revers_alloc,
.free = subghz_protocol_decoder_revers_free,
.feed = subghz_protocol_decoder_revers_feed,
.reset = subghz_protocol_decoder_revers_reset,
.get_hash_data = subghz_protocol_decoder_revers_get_hash_data,
.serialize = subghz_protocol_decoder_revers_serialize,
.deserialize = subghz_protocol_decoder_revers_deserialize,
.get_string = subghz_protocol_decoder_revers_get_string,
};
const SubGhzProtocolEncoder subghz_protocol_revers_encoder = {
.alloc = subghz_protocol_encoder_revers_alloc,
.free = subghz_protocol_encoder_revers_free,
.deserialize = subghz_protocol_encoder_revers_deserialize,
.stop = subghz_protocol_encoder_revers_stop,
.yield = subghz_protocol_encoder_revers_yield,
};
const SubGhzProtocol subghz_protocol_revers = {
.name = SUBGHZ_PROTOCOL_REVERS_NAME,
.type = SubGhzProtocolTypeStatic,
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
.decoder = &subghz_protocol_revers_decoder,
.encoder = &subghz_protocol_revers_encoder,
};
void* subghz_protocol_encoder_revers_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
SubGhzProtocolEncoderRevers* instance = malloc(sizeof(SubGhzProtocolEncoderRevers));
instance->base.protocol = &subghz_protocol_revers;
instance->generic.protocol_name = instance->base.protocol->name;
instance->encoder.repeat = 10;
instance->encoder.size_upload = 512;
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
instance->encoder.is_running = false;
return instance;
}
void subghz_protocol_encoder_revers_free(void* context) {
furi_assert(context);
SubGhzProtocolEncoderRevers* instance = context;
free(instance->encoder.upload);
free(instance);
}
/**
* Generating an upload from data.
* @param instance Pointer to a SubGhzProtocolEncoderRevers instance
* @return true On success
*/
static bool subghz_protocol_encoder_revers_get_upload(SubGhzProtocolEncoderRevers* instance) {
furi_assert(instance);
size_t index = 0;
/*size_t size_upload = instance->generic.data_count_bit;
if(size_upload > instance->encoder.size_upload) {
FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer.");
return false;
} else {
instance->encoder.size_upload = size_upload;
}*/
//Send key data
/*for(uint8_t i = instance->generic.data_count_bit; i > 1; i--) {
if(bit_read(instance->generic.data, i - 1)) {
//send bit 1
instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_revers_const.te_short);
instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_revers_const.te_short);
} else {
//send bit 0
instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_revers_const.te_long);
instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_revers_const.te_long);
}
}*/
return true;
}
bool subghz_protocol_encoder_revers_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
SubGhzProtocolEncoderRevers* instance = context;
bool res = false;
do {
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
FURI_LOG_E(TAG, "Deserialize error");
break;
}
if(instance->generic.data_count_bit !=
subghz_protocol_revers_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
//optional parameter parameter
flipper_format_read_uint32(
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
if(!subghz_protocol_encoder_revers_get_upload(instance)) break;
instance->encoder.is_running = true;
res = true;
} while(false);
return res;
}
void subghz_protocol_encoder_revers_stop(void* context) {
SubGhzProtocolEncoderRevers* instance = context;
instance->encoder.is_running = false;
}
LevelDuration subghz_protocol_encoder_revers_yield(void* context) {
SubGhzProtocolEncoderRevers* instance = context;
if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
instance->encoder.is_running = false;
return level_duration_reset();
}
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
if(++instance->encoder.front == instance->encoder.size_upload) {
instance->encoder.repeat--;
instance->encoder.front = 0;
}
return ret;
}
void* subghz_protocol_decoder_revers_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
SubGhzProtocolDecoderRevers* instance = malloc(sizeof(SubGhzProtocolDecoderRevers));
instance->base.protocol = &subghz_protocol_revers;
instance->generic.protocol_name = instance->base.protocol->name;
return instance;
}
void subghz_protocol_decoder_revers_free(void* context) {
furi_assert(context);
SubGhzProtocolDecoderRevers* instance = context;
free(instance);
}
void subghz_protocol_decoder_revers_reset(void* context) {
furi_assert(context);
SubGhzProtocolDecoderRevers* instance = context;
instance->decoder.parser_step = ReversDecoderStepReset;
instance->last_data = 0;
}
void subghz_protocol_decoder_revers_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
SubGhzProtocolDecoderRevers* instance = context;
switch(instance->decoder.parser_step) {
case ReversDecoderStepReset:
if((level) && DURATION_DIFF(duration, subghz_protocol_revers_const.te_short) <
subghz_protocol_revers_const.te_delta) {
instance->decoder.parser_step = ReversDecoderStepCheckPreambula;
instance->header_count++;
}
break;
case ReversDecoderStepCheckPreambula:
if((!level) && (DURATION_DIFF(duration, subghz_protocol_revers_const.te_short) <
subghz_protocol_revers_const.te_delta)) {
instance->decoder.parser_step = ReversDecoderStepReset;
break;
}
if((instance->header_count > 2) &&
(DURATION_DIFF(duration, subghz_protocol_revers_const.te_long) <
subghz_protocol_revers_const.te_delta)) {
// Preambula found
instance->decoder.parser_step = ReversDecoderStepSaveDuration;
} else {
instance->decoder.parser_step = ReversDecoderStepReset;
instance->header_count = 0;
}
case ReversDecoderStepSaveDuration:
if(level) {
instance->decoder.te_last = duration;
instance->decoder.parser_step = ReversDecoderStepCheckDuration;
} else {
instance->decoder.parser_step = ReversDecoderStepReset;
}
break;
case ReversDecoderStepCheckDuration:
if(!level) {
/*if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_revers_const.te_short) <
subghz_protocol_revers_const.te_delta) &&
(DURATION_DIFF(duration, subghz_protocol_revers_const.te_short * 7) <
subghz_protocol_revers_const.te_delta)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
instance->decoder.parser_step = ReversDecoderStepSaveDuration;
} else if(
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_revers_const.te_long) <
subghz_protocol_revers_const.te_delta) &&
(DURATION_DIFF(duration, subghz_protocol_revers_const.te_long) <
subghz_protocol_revers_const.te_delta)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
instance->decoder.parser_step = ReversDecoderStepSaveDuration;
} else {
instance->decoder.parser_step = ReversDecoderStepReset;
}*/
} else {
instance->decoder.parser_step = ReversDecoderStepReset;
}
break;
}
}
uint8_t subghz_protocol_decoder_revers_get_hash_data(void* context) {
furi_assert(context);
SubGhzProtocolDecoderRevers* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8));
}
bool subghz_protocol_decoder_revers_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset) {
furi_assert(context);
SubGhzProtocolDecoderRevers* instance = context;
return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
}
bool subghz_protocol_decoder_revers_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
SubGhzProtocolDecoderRevers* instance = context;
bool ret = false;
do {
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
break;
}
if(instance->generic.data_count_bit !=
subghz_protocol_revers_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
ret = true;
} while(false);
return ret;
}
void subghz_protocol_decoder_revers_get_string(void* context, FuriString* output) {
furi_assert(context);
SubGhzProtocolDecoderRevers* instance = context;
uint32_t data = instance->generic.data & 0xFF;
furi_string_cat_printf(
output,
"%s %dbit\r\n"
"Key:0x%lX\r\n",
instance->generic.protocol_name,
instance->generic.data_count_bit,
data);
}

View File

@@ -1,107 +0,0 @@
#pragma once
#include "base.h"
#define SUBGHZ_PROTOCOL_REVERS_NAME "Revers"
typedef struct SubGhzProtocolDecoderRevers SubGhzProtocolDecoderRevers;
typedef struct SubGhzProtocolEncoderRevers SubGhzProtocolEncoderRevers;
extern const SubGhzProtocolDecoder subghz_protocol_revers_decoder;
extern const SubGhzProtocolEncoder subghz_protocol_revers_encoder;
extern const SubGhzProtocol subghz_protocol_revers;
/**
* Allocate SubGhzProtocolEncoderRevers.
* @param environment Pointer to a SubGhzEnvironment instance
* @return SubGhzProtocolEncoderRevers* pointer to a SubGhzProtocolEncoderRevers instance
*/
void* subghz_protocol_encoder_revers_alloc(SubGhzEnvironment* environment);
/**
* Free SubGhzProtocolEncoderRevers.
* @param context Pointer to a SubGhzProtocolEncoderRevers instance
*/
void subghz_protocol_encoder_revers_free(void* context);
/**
* Deserialize and generating an upload to send.
* @param context Pointer to a SubGhzProtocolEncoderRevers instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool subghz_protocol_encoder_revers_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Forced transmission stop.
* @param context Pointer to a SubGhzProtocolEncoderRevers instance
*/
void subghz_protocol_encoder_revers_stop(void* context);
/**
* Getting the level and duration of the upload to be loaded into DMA.
* @param context Pointer to a SubGhzProtocolEncoderRevers instance
* @return LevelDuration
*/
LevelDuration subghz_protocol_encoder_revers_yield(void* context);
/**
* Allocate SubGhzProtocolDecoderRevers.
* @param environment Pointer to a SubGhzEnvironment instance
* @return SubGhzProtocolDecoderRevers* pointer to a SubGhzProtocolDecoderRevers instance
*/
void* subghz_protocol_decoder_revers_alloc(SubGhzEnvironment* environment);
/**
* Free SubGhzProtocolDecoderRevers.
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
*/
void subghz_protocol_decoder_revers_free(void* context);
/**
* Reset decoder SubGhzProtocolDecoderRevers.
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
*/
void subghz_protocol_decoder_revers_reset(void* context);
/**
* Parse a raw sequence of levels and durations received from the air.
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
* @param level Signal level true-high false-low
* @param duration Duration of this level in, us
*/
void subghz_protocol_decoder_revers_feed(void* context, bool level, uint32_t duration);
/**
* Getting the hash sum of the last randomly received parcel.
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
* @return hash Hash sum
*/
uint8_t subghz_protocol_decoder_revers_get_hash_data(void* context);
/**
* Serialize data SubGhzProtocolDecoderRevers.
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
* @return true On success
*/
bool subghz_protocol_decoder_revers_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset);
/**
* Deserialize data SubGhzProtocolDecoderRevers.
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool subghz_protocol_decoder_revers_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Getting a textual representation of the received data.
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
* @param output Resulting text
*/
void subghz_protocol_decoder_revers_get_string(void* context, FuriString* output);

View File

@@ -61,7 +61,6 @@ static const uint32_t subghz_frequency_list[] = {
438900000,
440175000,
464000000,
467750000,
/* 779 - 928 */
779000000,

View File

@@ -106,7 +106,6 @@ void tar_archive_set_file_callback(TarArchive* archive, tar_unpack_file_cb callb
static int tar_archive_entry_counter(mtar_t* tar, const mtar_header_t* header, void* param) {
UNUSED(tar);
UNUSED(header);
furi_assert(param);
int32_t* counter = param;
(*counter)++;
return 0;

View File

@@ -1,6 +1,6 @@
from SCons.Builder import Builder
from SCons.Action import Action
from SCons.Script import Delete, Mkdir, GetBuildFailures, Flatten
from SCons.Script import Delete, Mkdir, GetBuildFailures
import multiprocessing
import webbrowser
import atexit
@@ -30,14 +30,13 @@ def atexist_handler():
return
for bf in GetBuildFailures():
for node in Flatten(bf.node):
if node.exists and node.name.endswith(".html"):
# macOS
if sys.platform == "darwin":
subprocess.run(["open", node.abspath])
else:
webbrowser.open(node.abspath)
break
if bf.node.exists and bf.node.name.endswith(".html"):
# macOS
if sys.platform == "darwin":
subprocess.run(["open", bf.node.abspath])
else:
webbrowser.open(bf.node.abspath)
break
def generate(env):