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

Compare commits

..

17 Commits

Author SHA1 Message Date
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
443 changed files with 4212 additions and 18851 deletions

View File

@@ -192,7 +192,7 @@ steps:
Version: {{build.tag}}
[-Github - Changelog-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
[-Github-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
@@ -201,38 +201,45 @@ steps:
[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
[-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})
[-Version without custom animations - Install 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)
[-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)
[-Version with extra apps - Install 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)
[-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)"
[-Install 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})"
document:
- ${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz
- name: "Send discord notification"
image: hfdj/fztools
pull: never
environment:
DISCORD_WEBHOOK:
from_secret: dis_release_webhook
commands:
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
- 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
image: appleboy/drone-discord
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
webhook_id:
from_secret: ds_wh_id
webhook_token:
from_secret: ds_wh_token
message: "New Unleashed firmware released!
Version: {{build.tag}}
[[Github]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
[-Version without custom animations - Install 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)
[-Version with extra apps - Install 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)
[-Install 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})"
trigger:
event:
@@ -392,29 +399,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
environment:
DISCORD_WEBHOOK:
from_secret: dis_dev_webhook
commands:
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
- chmod +x ./discord.sh
- ./discord.sh --text 'Unleashed firmware dev build successful!\n\nBuild - '${DRONE_BUILD_NUMBER}'\n\nSHA - '${DRONE_COMMIT_SHA}'\n\n[-Version with extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'e.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'e)\n\n[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}')'
trigger:
branch:
- dev

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
*.swp
*.swo
*.gdb_history

View File

@@ -11,8 +11,5 @@
"augustocdias.tasks-shell-input"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [
"twxs.cmake",
"ms-vscode.cmake-tools"
]
}
"unwantedRecommendations": []
}

View File

@@ -1,12 +1,29 @@
### 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
* SubGHz: External CC1101 support (by @quen0n | PR #307) - [How to connect](https://github.com/quen0n/flipperzero-ext-cc1101)
* SubGHz: Fix GUI receiver bug - When keyboard is locked and popup appears it now shows bottom text correctly
* Plugins: Added movement interval in mouse_jiggler USB & BLE (by @DocKuro | PR #303)
* Plugins: Solitaire and Blackjack now affect Flipper's level (by @teeebor | PR #305)
* Plugins -> Updated **ProtoView** [(by antirez)](https://github.com/antirez/protoview)
* Plugins -> Updated **UniTemp** [(by quen0n)](https://github.com/quen0n/unitemp-flipperzero)
* Infrared: Update universal remote assets (by @amec0e) (PR #306)
* NFC: Remove invalid keys from mf classic dict (Fixes #304)
* GUI: Custom font set function (by @LTVA1) - [Link](https://github.com/LTVA1/flipperzero-firmware-wPlugins/tree/patch-custom-font)
* OFW: FreeRTOS: update to 10.5.1
* OFW: NFC: fix creating MF Classic tags from "Add Manually" menu (BCC calulation and ATQA/SAK writing)
* OFW: Print card CID in storage info
* OFW: Add support for `GUI-CTRL` in bad_usb
* OFW: Furi: getter for current thread stdout write callback
* OFW: LF-RFID: add CRC calculation to paradox protocol
* OFW: WS: add protocol LaCrosse-TX (TFA Dostmann)
* OFW: Assets: correct MicroSD card pinout in service animations
* OFW: Furi: make `furi_is_irq_context` public
* OFW: debug apps: made runnable as .faps; sdk: resolved additional APIs in use by faps
* OFW: NFC: change from int8_t to uint8_t
* OFW: NFC: add MIFARE MINI support
* OFW: emv: parse track1&2 equivalent data
* OFW: nfc: Fix sector reads when one block is unreadable for MIFARE Classic
* OFW: nfc: Fix crash when using debug PCAP trace
* OFW: ELF-loader: wait for notification to complete on app exit
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)

View File

@@ -40,7 +40,7 @@ Our Discord Community:
* FAAC SLH (Spa) & BFT Mitto (secure with seed) manual creation
* Sub-GHz static code brute-force plugin
* LFRFID Fuzzer plugin
* Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release
* Custom community plugins and games added
* Extra Sub-GHz frequencies + extra Mifare Classic keys
* Picopass/iClass plugin included in releases
* Recompiled IR TV Universal Remote for ALL buttons
@@ -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,13 @@ 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 (by @assasinfil & @TQMatvey)
- Somfy Keytis (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
@@ -162,6 +152,7 @@ Games:
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
- Sub-GHz -> External CC1101 module support - [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
- Sub-GHz -> New frequency analyzer - [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
- Sub-GHz -> Detect RAW feature - [(by perspecdev)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/152)
- Sub-GHz -> Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
- Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
- Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)

View File

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

View File

@@ -2,7 +2,6 @@ App(
appid="accessor",
name="Accessor",
apptype=FlipperAppType.DEBUG,
targets=["f7"],
entry_point="accessor_app",
cdefines=["APP_ACCESSOR"],
requires=["gui"],

View File

@@ -1,7 +1,7 @@
#include "bt_carrier_test.h"
#include "bt_test.h"
#include "bt_test_types.h"
#include <furi_hal_bt.h>
#include "furi_hal_bt.h"
struct BtCarrierTest {
BtTest* bt_test;

View File

@@ -1,7 +1,7 @@
#include "bt_packet_test.h"
#include "bt_test.h"
#include "bt_test_types.h"
#include <furi_hal_bt.h>
#include "furi_hal_bt.h"
struct BtPacketTest {
BtTest* bt_test;

View File

@@ -1,11 +1,10 @@
#include "file_browser_app_i.h"
#include <file_browser_test_icons.h>
#include <gui/modules/file_browser.h>
#include <storage/storage.h>
#include <lib/toolbox/path.h>
#include "file_browser_app_i.h"
#include "gui/modules/file_browser.h"
#include <furi.h>
#include <furi_hal.h>
#include <storage/storage.h>
#include <lib/toolbox/path.h>
static bool file_browser_app_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);

View File

@@ -2,7 +2,6 @@ App(
appid="lfrfid_debug",
name="LF-RFID Debug",
apptype=FlipperAppType.DEBUG,
targets=["f7"],
entry_point="lfrfid_debug_app",
requires=[
"gui",

View File

@@ -89,7 +89,7 @@ static void test_rpc_setup(void) {
}
furi_check(rpc_session[0].session);
rpc_session[0].output_stream = furi_stream_buffer_alloc(4096, 1);
rpc_session[0].output_stream = furi_stream_buffer_alloc(1000, 1);
rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback);
rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary();
rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary();

View File

@@ -12,9 +12,8 @@
#define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
#define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n")
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
#define TEST_RANDOM_COUNT_PARSE 329
#define TEST_RANDOM_COUNT_PARSE 273
#define TEST_TIMEOUT 10000
static SubGhzEnvironment* environment_handler;
@@ -44,8 +43,6 @@ static void subghz_test_init(void) {
environment_handler, CAME_ATOMO_DIR_NAME);
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
environment_handler, NICE_FLOR_S_DIR_NAME);
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
environment_handler, ALUTECH_AT_4N_DIR_NAME);
subghz_environment_set_protocol_registry(
environment_handler, (void*)&subghz_protocol_registry);
@@ -492,14 +489,6 @@ MU_TEST(subghz_decoder_linear_test) {
"Test decoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n");
}
MU_TEST(subghz_decoder_linear_delta3_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/linear_delta3_raw.sub"),
SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME),
"Test decoder " SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME " error\r\n");
}
MU_TEST(subghz_decoder_megacode_test) {
mu_assert(
subghz_decoder_test(
@@ -615,36 +604,6 @@ MU_TEST(subghz_decoder_holtek_ht12x_test) {
"Test decoder " SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME " error\r\n");
}
MU_TEST(subghz_decoder_dooya_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/dooya_raw.sub"), SUBGHZ_PROTOCOL_DOOYA_NAME),
"Test decoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n");
}
MU_TEST(subghz_decoder_alutech_at_4n_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/alutech_at_4n_raw.sub"),
SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME),
"Test decoder " SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME " error\r\n");
}
MU_TEST(subghz_decoder_nice_one_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/nice_one_raw.sub"), SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME),
"Test decoder " SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME " error\r\n");
}
MU_TEST(subghz_decoder_kinggates_stylo4k_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/kinggates_stylo4k_raw.sub"),
SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME),
"Test decoder " SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME " error\r\n");
}
//test encoders
MU_TEST(subghz_encoder_princeton_test) {
mu_assert(
@@ -688,12 +647,6 @@ MU_TEST(subghz_encoder_linear_test) {
"Test encoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n");
}
MU_TEST(subghz_encoder_linear_delta3_test) {
mu_assert(
subghz_encoder_test(EXT_PATH("unit_tests/subghz/linear_delta3.sub")),
"Test encoder " SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME " error\r\n");
}
MU_TEST(subghz_encoder_megacode_test) {
mu_assert(
subghz_encoder_test(EXT_PATH("unit_tests/subghz/megacode.sub")),
@@ -790,12 +743,6 @@ MU_TEST(subghz_encoder_holtek_ht12x_test) {
"Test encoder " SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME " error\r\n");
}
MU_TEST(subghz_encoder_dooya_test) {
mu_assert(
subghz_encoder_test(EXT_PATH("unit_tests/subghz/dooya.sub")),
"Test encoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n");
}
MU_TEST(subghz_random_test) {
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
}
@@ -825,7 +772,6 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_decoder_somfy_telis_test);
MU_RUN_TEST(subghz_decoder_star_line_test);
MU_RUN_TEST(subghz_decoder_linear_test);
MU_RUN_TEST(subghz_decoder_linear_delta3_test);
MU_RUN_TEST(subghz_decoder_megacode_test);
MU_RUN_TEST(subghz_decoder_secplus_v1_test);
MU_RUN_TEST(subghz_decoder_secplus_v2_test);
@@ -842,10 +788,6 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_decoder_ansonic_test);
MU_RUN_TEST(subghz_decoder_smc5326_test);
MU_RUN_TEST(subghz_decoder_holtek_ht12x_test);
MU_RUN_TEST(subghz_decoder_dooya_test);
MU_RUN_TEST(subghz_decoder_alutech_at_4n_test);
MU_RUN_TEST(subghz_decoder_nice_one_test);
MU_RUN_TEST(subghz_decoder_kinggates_stylo4k_test);
MU_RUN_TEST(subghz_encoder_princeton_test);
MU_RUN_TEST(subghz_encoder_came_test);
@@ -854,7 +796,6 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_encoder_nice_flo_test);
MU_RUN_TEST(subghz_encoder_keelog_test);
MU_RUN_TEST(subghz_encoder_linear_test);
MU_RUN_TEST(subghz_encoder_linear_delta3_test);
MU_RUN_TEST(subghz_encoder_megacode_test);
MU_RUN_TEST(subghz_encoder_holtek_test);
MU_RUN_TEST(subghz_encoder_secplus_v1_test);
@@ -871,7 +812,6 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_encoder_ansonic_test);
MU_RUN_TEST(subghz_encoder_smc5326_test);
MU_RUN_TEST(subghz_encoder_holtek_ht12x_test);
MU_RUN_TEST(subghz_encoder_dooya_test);
MU_RUN_TEST(subghz_random_test);
subghz_test_deinit();

View File

@@ -70,7 +70,7 @@ void minunit_print_progress() {
}
void minunit_print_fail(const char* str) {
printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str);
printf(FURI_LOG_CLR_E "%s\r\n" FURI_LOG_CLR_RESET, str);
}
void unit_tests_cli(Cli* cli, FuriString* args, void* context) {

View File

@@ -1,44 +0,0 @@
# 1-Wire Thermometer
This example application demonstrates the use of the 1-Wire library with a DS18B20 thermometer.
It also covers basic GUI, input handling, threads and localisation.
## Electrical connections
Before launching the application, connect the sensor to Flipper's external GPIO according to the table below:
| DS18B20 | Flipper |
| :-----: | :-----: |
| VDD | 9 |
| GND | 18 |
| DQ | 17 |
*NOTE 1*: GND is also available on pins 8 and 11.
*NOTE 2*: For any other pin than 17, connect an external 4.7k pull-up resistor to pin 9.
## Launching the application
In order to launch this demo, follow the steps below:
1. Make sure your Flipper has an SD card installed.
2. Connect your Flipper to the computer via a USB cable.
3. Run `./fbt launch_app APPSRC=example_thermo` in your terminal emulator of choice.
## Changing the data pin
It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below:
```c
/* Possible GPIO pin choices:
- gpio_ext_pc0
- gpio_ext_pc1
- gpio_ext_pc3
- gpio_ext_pb2
- gpio_ext_pb3
- gpio_ext_pa4
- gpio_ext_pa6
- gpio_ext_pa7
- ibutton_gpio
*/
#define THERMO_GPIO_PIN (ibutton_gpio)
```
Do not forget about the external pull-up resistor as these pins do not have one built-in.
With the changes been made, recompile and launch the application again.
The on-screen text should reflect it by asking to connect the thermometer to another pin.

View File

@@ -1,10 +0,0 @@
App(
appid="example_thermo",
name="Example: Thermometer",
apptype=FlipperAppType.EXTERNAL,
entry_point="example_thermo_main",
requires=["gui"],
stack_size=1 * 1024,
fap_icon="example_thermo_10px.png",
fap_category="Examples",
)

View File

@@ -1,356 +0,0 @@
/*
* This file contains an example application that reads and displays
* the temperature from a DS18B20 1-wire thermometer.
*
* It also covers basic GUI, input handling, threads and localisation.
*
* References:
* [1] DS18B20 Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf
*/
#include <gui/gui.h>
#include <gui/view_port.h>
#include <core/thread.h>
#include <core/kernel.h>
#include <locale/locale.h>
#include <one_wire/maxim_crc.h>
#include <one_wire/one_wire_host.h>
#define UPDATE_PERIOD_MS 1000UL
#define TEXT_STORE_SIZE 64U
#define DS18B20_CMD_CONVERT 0x44U
#define DS18B20_CMD_READ_SCRATCHPAD 0xbeU
#define DS18B20_CFG_RESOLUTION_POS 5U
#define DS18B20_CFG_RESOLUTION_MASK 0x03U
#define DS18B20_DECIMAL_PART_MASK 0x0fU
#define DS18B20_SIGN_MASK 0xf0U
/* Possible GPIO pin choices:
- gpio_ext_pc0
- gpio_ext_pc1
- gpio_ext_pc3
- gpio_ext_pb2
- gpio_ext_pb3
- gpio_ext_pa4
- gpio_ext_pa6
- gpio_ext_pa7
- ibutton_gpio
*/
#define THERMO_GPIO_PIN (ibutton_gpio)
/* Flags which the reader thread responds to */
typedef enum {
ReaderThreadFlagExit = 1,
} ReaderThreadFlag;
typedef union {
struct {
uint8_t temp_lsb; /* Least significant byte of the temperature */
uint8_t temp_msb; /* Most significant byte of the temperature */
uint8_t user_alarm_high; /* User register 1 (Temp high alarm) */
uint8_t user_alarm_low; /* User register 2 (Temp low alarm) */
uint8_t config; /* Configuration register */
uint8_t reserved[3]; /* Not used */
uint8_t crc; /* CRC checksum for error detection */
} fields;
uint8_t bytes[9];
} DS18B20Scratchpad;
/* Application context structure */
typedef struct {
Gui* gui;
ViewPort* view_port;
FuriThread* reader_thread;
FuriMessageQueue* event_queue;
OneWireHost* onewire;
float temp_celsius;
bool has_device;
} ExampleThermoContext;
/*************** 1-Wire Communication and Processing *****************/
/* Commands the thermometer to begin measuring the temperature. */
static void example_thermo_request_temperature(ExampleThermoContext* context) {
OneWireHost* onewire = context->onewire;
/* All 1-wire transactions must happen in a critical section, i.e
not interrupted by other threads. */
FURI_CRITICAL_ENTER();
bool success = false;
do {
/* Each communication with a 1-wire device starts by a reset.
The functon will return true if a device responded with a presence pulse. */
if(!onewire_host_reset(onewire)) break;
/* After the reset, a ROM operation must follow.
If there is only one device connected, the "Skip ROM" command is most appropriate
(it can also be used to address all of the connected devices in some cases).*/
onewire_host_skip(onewire);
/* After the ROM operation, a device-specific command is issued.
In this case, it's a request to start measuring the temperature. */
onewire_host_write(onewire, DS18B20_CMD_CONVERT);
success = true;
} while(false);
context->has_device = success;
FURI_CRITICAL_EXIT();
}
/* Reads the measured temperature from the thermometer. */
static void example_thermo_read_temperature(ExampleThermoContext* context) {
/* If there was no device detected, don't try to read the temperature */
if(!context->has_device) {
return;
}
OneWireHost* onewire = context->onewire;
/* All 1-wire transactions must happen in a critical section, i.e
not interrupted by other threads. */
FURI_CRITICAL_ENTER();
bool success = false;
do {
DS18B20Scratchpad buf;
/* Attempt reading the temperature 10 times before giving up */
size_t attempts_left = 10;
do {
/* Each communication with a 1-wire device starts by a reset.
The functon will return true if a device responded with a presence pulse. */
if(!onewire_host_reset(onewire)) continue;
/* After the reset, a ROM operation must follow.
If there is only one device connected, the "Skip ROM" command is most appropriate
(it can also be used to address all of the connected devices in some cases).*/
onewire_host_skip(onewire);
/* After the ROM operation, a device-specific command is issued.
This time, it will be the "Read Scratchpad" command which will
prepare the device's internal buffer memory for reading. */
onewire_host_write(onewire, DS18B20_CMD_READ_SCRATCHPAD);
/* The actual reading happens here. A total of 9 bytes is read. */
onewire_host_read_bytes(onewire, buf.bytes, sizeof(buf.bytes));
/* Calculate the checksum and compare it with one provided by the device. */
const uint8_t crc = maxim_crc8(buf.bytes, sizeof(buf.bytes) - 1, MAXIM_CRC8_INIT);
/* Checksums match, exit the loop */
if(crc == buf.fields.crc) break;
} while(--attempts_left);
if(attempts_left == 0) break;
/* Get the measurement resolution from the configuration register. (See [1] page 9) */
const uint8_t resolution_mode = (buf.fields.config >> DS18B20_CFG_RESOLUTION_POS) &
DS18B20_CFG_RESOLUTION_MASK;
/* Generate a mask for undefined bits in the decimal part. (See [1] page 6) */
const uint8_t decimal_mask =
(DS18B20_DECIMAL_PART_MASK << (DS18B20_CFG_RESOLUTION_MASK - resolution_mode)) &
DS18B20_DECIMAL_PART_MASK;
/* Get the integer and decimal part of the temperature (See [1] page 6) */
const uint8_t integer_part = (buf.fields.temp_msb << 4U) | (buf.fields.temp_lsb >> 4U);
const uint8_t decimal_part = buf.fields.temp_lsb & decimal_mask;
/* Calculate the sign of the temperature (See [1] page 6) */
const bool is_negative = (buf.fields.temp_msb & DS18B20_SIGN_MASK) != 0;
/* Combine the integer and decimal part together */
const float temp_celsius_abs = integer_part + decimal_part / 16.f;
/* Set the appropriate sign */
context->temp_celsius = is_negative ? -temp_celsius_abs : temp_celsius_abs;
success = true;
} while(false);
context->has_device = success;
FURI_CRITICAL_EXIT();
}
/* Periodically requests measurements and reads temperature. This function runs in a separare thread. */
static int32_t example_thermo_reader_thread_callback(void* ctx) {
ExampleThermoContext* context = ctx;
for(;;) {
/* Tell the termometer to start measuring the temperature. The process may take up to 750ms. */
example_thermo_request_temperature(context);
/* Wait for the measurement to finish. At the same time wait for an exit signal. */
const uint32_t flags =
furi_thread_flags_wait(ReaderThreadFlagExit, FuriFlagWaitAny, UPDATE_PERIOD_MS);
/* If an exit signal was received, return from this thread. */
if(flags != (unsigned)FuriFlagErrorTimeout) break;
/* The measurement is now ready, read it from the termometer. */
example_thermo_read_temperature(context);
}
return 0;
}
/*************** GUI, Input and Main Loop *****************/
/* Draw the GUI of the application. The screen is completely redrawn during each call. */
static void example_thermo_draw_callback(Canvas* canvas, void* ctx) {
ExampleThermoContext* context = ctx;
char text_store[TEXT_STORE_SIZE];
const size_t middle_x = canvas_width(canvas) / 2U;
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, middle_x, 12, AlignCenter, AlignBottom, "Thermometer Demo");
canvas_draw_line(canvas, 0, 16, 128, 16);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(
canvas, middle_x, 30, AlignCenter, AlignBottom, "Connnect thermometer");
snprintf(
text_store,
TEXT_STORE_SIZE,
"to GPIO pin %ld",
furi_hal_resources_get_ext_pin_number(&THERMO_GPIO_PIN));
canvas_draw_str_aligned(canvas, middle_x, 42, AlignCenter, AlignBottom, text_store);
canvas_set_font(canvas, FontKeyboard);
if(context->has_device) {
float temp;
char temp_units;
/* The applicaton is locale-aware.
Change Settings->System->Units to check it out. */
switch(locale_get_measurement_unit()) {
case LocaleMeasurementUnitsMetric:
temp = context->temp_celsius;
temp_units = 'C';
break;
case LocaleMeasurementUnitsImperial:
temp = locale_celsius_to_fahrenheit(context->temp_celsius);
temp_units = 'F';
break;
default:
furi_crash("Illegal measurement units");
}
/* If a reading is available, display it */
snprintf(text_store, TEXT_STORE_SIZE, "Temperature: %+.1f%c", (double)temp, temp_units);
} else {
/* Or show a message that no data is available */
strncpy(text_store, "-- No data --", TEXT_STORE_SIZE);
}
canvas_draw_str_aligned(canvas, middle_x, 58, AlignCenter, AlignBottom, text_store);
}
/* This function is called from the GUI thread. All it does is put the event
into the application's queue so it can be processed later. */
static void example_thermo_input_callback(InputEvent* event, void* ctx) {
ExampleThermoContext* context = ctx;
furi_message_queue_put(context->event_queue, event, FuriWaitForever);
}
/* Starts the reader thread and handles the input */
static void example_thermo_run(ExampleThermoContext* context) {
/* Configure the hardware in host mode */
onewire_host_start(context->onewire);
/* Start the reader thread. It will talk to the thermometer in the background. */
furi_thread_start(context->reader_thread);
/* An endless loop which handles the input*/
for(bool is_running = true; is_running;) {
InputEvent event;
/* Wait for an input event. Input events come from the GUI thread via a callback. */
const FuriStatus status =
furi_message_queue_get(context->event_queue, &event, FuriWaitForever);
/* This application is only interested in short button presses. */
if((status != FuriStatusOk) || (event.type != InputTypeShort)) {
continue;
}
/* When the user presses the "Back" button, break the loop and exit the application. */
if(event.key == InputKeyBack) {
is_running = false;
}
}
/* Signal the reader thread to cease operation and exit */
furi_thread_flags_set(furi_thread_get_id(context->reader_thread), ReaderThreadFlagExit);
/* Wait for the reader thread to finish */
furi_thread_join(context->reader_thread);
/* Reset the hardware */
onewire_host_stop(context->onewire);
}
/******************** Initialisation & startup *****************************/
/* Allocate the memory and initialise the variables */
static ExampleThermoContext* example_thermo_context_alloc() {
ExampleThermoContext* context = malloc(sizeof(ExampleThermoContext));
context->view_port = view_port_alloc();
view_port_draw_callback_set(context->view_port, example_thermo_draw_callback, context);
view_port_input_callback_set(context->view_port, example_thermo_input_callback, context);
context->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
context->reader_thread = furi_thread_alloc();
furi_thread_set_stack_size(context->reader_thread, 1024U);
furi_thread_set_context(context->reader_thread, context);
furi_thread_set_callback(context->reader_thread, example_thermo_reader_thread_callback);
context->gui = furi_record_open(RECORD_GUI);
gui_add_view_port(context->gui, context->view_port, GuiLayerFullscreen);
context->onewire = onewire_host_alloc(&THERMO_GPIO_PIN);
return context;
}
/* Release the unused resources and deallocate memory */
static void example_thermo_context_free(ExampleThermoContext* context) {
view_port_enabled_set(context->view_port, false);
gui_remove_view_port(context->gui, context->view_port);
onewire_host_free(context->onewire);
furi_thread_free(context->reader_thread);
furi_message_queue_free(context->event_queue);
view_port_free(context->view_port);
furi_record_close(RECORD_GUI);
}
/* The application's entry point. Execution starts from here. */
int32_t example_thermo_main(void* p) {
UNUSED(p);
/* Allocate all of the necessary structures */
ExampleThermoContext* context = example_thermo_context_alloc();
/* Start the applicaton's main loop. It won't return until the application was requested to exit. */
example_thermo_run(context);
/* Release all unneeded resources */
example_thermo_context_free(context);
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -1,14 +1,12 @@
#include <archive/views/archive_browser_view.h>
#include "archive_files.h"
#include "archive_apps.h"
#include "archive_browser.h"
#include "../views/archive_browser_view.h"
#include <core/common_defines.h>
#include <core/log.h>
#include <gui/modules/file_browser_worker.h>
#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 +55,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 +139,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 +206,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 +455,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

@@ -1,13 +1,10 @@
#pragma once
#include "../helpers/archive_files.h"
#include "../helpers/archive_favorites.h"
#include <gui/gui_i.h>
#include <gui/view.h>
#include <gui/canvas.h>
#include <gui/elements.h>
#include <gui/modules/file_browser_worker.h>
#include <furi.h>
#include <storage/storage.h>
#include "../helpers/archive_files.h"
#include "../helpers/archive_menu.h"
@@ -31,7 +28,6 @@ typedef enum {
ArchiveTabBadUsb,
ArchiveTabU2f,
ArchiveTabApplications,
ArchiveTabInternal,
ArchiveTabBrowser,
ArchiveTabTotal,
} ArchiveTabEnum;

View File

@@ -33,26 +33,9 @@ static void bad_usb_load_settings(BadUsbApp* app) {
!storage_file_eof(settings_file) && !isspace(chr)) {
furi_string_push_back(app->keyboard_layout, chr);
}
} else {
furi_string_reset(app->keyboard_layout);
}
storage_file_close(settings_file);
storage_file_free(settings_file);
if(!furi_string_empty(app->keyboard_layout)) {
Storage* fs_api = furi_record_open(RECORD_STORAGE);
FileInfo layout_file_info;
FS_Error file_check_err = storage_common_stat(
fs_api, furi_string_get_cstr(app->keyboard_layout), &layout_file_info);
furi_record_close(RECORD_STORAGE);
if(file_check_err != FSE_OK) {
furi_string_reset(app->keyboard_layout);
return;
}
if(layout_file_info.size != 256) {
furi_string_reset(app->keyboard_layout);
}
}
}
static void bad_usb_save_settings(BadUsbApp* app) {
@@ -115,12 +98,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 +121,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,10 +14,9 @@
#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"
#define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/layouts"
#define BAD_USB_APP_SCRIPT_EXTENSION ".txt"
#define BAD_USB_APP_LAYOUT_EXTENSION ".kl"
@@ -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

@@ -120,6 +120,8 @@ static const char ducky_cmd_altchar[] = {"ALTCHAR "};
static const char ducky_cmd_altstr_1[] = {"ALTSTRING "};
static const char ducky_cmd_altstr_2[] = {"ALTCODE "};
static const char ducky_cmd_lang[] = {"DUCKY_LANG"};
static const uint8_t numpad_keys[10] = {
HID_KEYPAD_0,
HID_KEYPAD_1,
@@ -255,6 +257,9 @@ static int32_t
} else if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) {
// ID - executed in ducky_script_preload
return (0);
} else if(strncmp(line_tmp, ducky_cmd_lang, strlen(ducky_cmd_lang)) == 0) {
// DUCKY_LANG - ignore command to retain compatibility with existing scripts
return (0);
} else if(strncmp(line_tmp, ducky_cmd_delay, strlen(ducky_cmd_delay)) == 0) {
// DELAY
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
@@ -490,6 +495,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 +647,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);
@@ -690,7 +699,7 @@ void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layou
}
File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
if(!furi_string_empty(layout_path)) { //-V1051
if(!furi_string_empty(layout_path)) {
if(storage_file_open(
layout_file, furi_string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
uint16_t layout[128];

View File

@@ -17,8 +17,6 @@ static bool bad_usb_layout_select(BadUsbApp* bad_usb) {
DialogsFileBrowserOptions browser_options;
dialog_file_browser_set_basic_options(
&browser_options, BAD_USB_APP_LAYOUT_EXTENSION, &I_keyboard_10px);
browser_options.base_path = BAD_USB_APP_PATH_LAYOUT_FOLDER;
browser_options.skip_assets = false;
// Input events and views are managed by file_browser
bool res = dialog_file_browser_show(

View File

@@ -1,6 +1,6 @@
#include "../bad_usb_app_i.h"
#include <furi_hal_power.h>
#include <furi_hal_usb.h>
#include "furi_hal_power.h"
#include "furi_hal_usb.h"
#include <storage/storage.h>
static bool bad_usb_file_select(BadUsbApp* bad_usb) {

View File

@@ -1,7 +1,7 @@
#include "../bad_usb_script.h"
#include "../bad_usb_app_i.h"
#include "../views/bad_usb_view.h"
#include <furi_hal.h>
#include "furi_hal.h"
#include "toolbox/path.h"
void bad_usb_scene_work_button_callback(InputKey key, void* context) {

View File

@@ -25,7 +25,6 @@ GpioApp* gpio_app_alloc() {
GpioApp* app = malloc(sizeof(GpioApp));
app->gui = furi_record_open(RECORD_GUI);
app->gpio_items = gpio_items_alloc();
app->view_dispatcher = view_dispatcher_alloc();
app->scene_manager = scene_manager_alloc(&gpio_scene_handlers, app);
@@ -48,7 +47,7 @@ GpioApp* gpio_app_alloc() {
app->view_dispatcher,
GpioAppViewVarItemList,
variable_item_list_get_view(app->var_item_list));
app->gpio_test = gpio_test_alloc(app->gpio_items);
app->gpio_test = gpio_test_alloc();
view_dispatcher_add_view(
app->view_dispatcher, GpioAppViewGpioTest, gpio_test_get_view(app->gpio_test));
@@ -92,7 +91,6 @@ void gpio_app_free(GpioApp* app) {
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_NOTIFICATION);
gpio_items_free(app->gpio_items);
free(app);
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include "gpio_app.h"
#include "gpio_items.h"
#include "gpio_item.h"
#include "scenes/gpio_scene.h"
#include "gpio_custom_event.h"
#include "usb_uart_bridge.h"
@@ -28,7 +28,6 @@ struct GpioApp {
VariableItem* var_item_flow;
GpioTest* gpio_test;
GpioUsbUart* gpio_usb_uart;
GPIOItems* gpio_items;
UsbUartBridge* usb_uart_bridge;
UsbUartConfig* usb_uart_cfg;
};

View File

@@ -0,0 +1,51 @@
#include "gpio_item.h"
#include <furi_hal_resources.h>
typedef struct {
const char* name;
const GpioPin* pin;
} GpioItem;
static const GpioItem gpio_item[GPIO_ITEM_COUNT] = {
{"1.2: PA7", &gpio_ext_pa7},
{"1.3: PA6", &gpio_ext_pa6},
{"1.4: PA4", &gpio_ext_pa4},
{"1.5: PB3", &gpio_ext_pb3},
{"1.6: PB2", &gpio_ext_pb2},
{"1.7: PC3", &gpio_ext_pc3},
{"2.7: PC1", &gpio_ext_pc1},
{"2.8: PC0", &gpio_ext_pc0},
};
void gpio_item_configure_pin(uint8_t index, GpioMode mode) {
furi_assert(index < GPIO_ITEM_COUNT);
furi_hal_gpio_write(gpio_item[index].pin, false);
furi_hal_gpio_init(gpio_item[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh);
}
void gpio_item_configure_all_pins(GpioMode mode) {
for(uint8_t i = 0; i < GPIO_ITEM_COUNT; i++) {
gpio_item_configure_pin(i, mode);
}
}
void gpio_item_set_pin(uint8_t index, bool level) {
furi_assert(index < GPIO_ITEM_COUNT);
furi_hal_gpio_write(gpio_item[index].pin, level);
}
void gpio_item_set_all_pins(bool level) {
for(uint8_t i = 0; i < GPIO_ITEM_COUNT; i++) {
gpio_item_set_pin(i, level);
}
}
const char* gpio_item_get_pin_name(uint8_t index) {
furi_assert(index < GPIO_ITEM_COUNT + 1);
if(index == GPIO_ITEM_COUNT) {
return "ALL";
} else {
return gpio_item[index].name;
}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <furi_hal_gpio.h>
#define GPIO_ITEM_COUNT 8
void gpio_item_configure_pin(uint8_t index, GpioMode mode);
void gpio_item_configure_all_pins(GpioMode mode);
void gpio_item_set_pin(uint8_t index, bool level);
void gpio_item_set_all_pins(bool level);
const char* gpio_item_get_pin_name(uint8_t index);

View File

@@ -1,69 +0,0 @@
#include "gpio_items.h"
#include <furi_hal_resources.h>
struct GPIOItems {
GpioPinRecord* pins;
size_t count;
};
GPIOItems* gpio_items_alloc() {
GPIOItems* items = malloc(sizeof(GPIOItems));
items->count = 0;
for(size_t i = 0; i < gpio_pins_count; i++) {
if(!gpio_pins[i].debug) {
items->count++;
}
}
items->pins = malloc(sizeof(GpioPinRecord) * items->count);
for(size_t i = 0; i < items->count; i++) {
if(!gpio_pins[i].debug) {
items->pins[i].pin = gpio_pins[i].pin;
items->pins[i].name = gpio_pins[i].name;
}
}
return items;
}
void gpio_items_free(GPIOItems* items) {
free(items->pins);
free(items);
}
uint8_t gpio_items_get_count(GPIOItems* items) {
return items->count;
}
void gpio_items_configure_pin(GPIOItems* items, uint8_t index, GpioMode mode) {
furi_assert(index < items->count);
furi_hal_gpio_write(items->pins[index].pin, false);
furi_hal_gpio_init(items->pins[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh);
}
void gpio_items_configure_all_pins(GPIOItems* items, GpioMode mode) {
for(uint8_t i = 0; i < items->count; i++) {
gpio_items_configure_pin(items, i, mode);
}
}
void gpio_items_set_pin(GPIOItems* items, uint8_t index, bool level) {
furi_assert(index < items->count);
furi_hal_gpio_write(items->pins[index].pin, level);
}
void gpio_items_set_all_pins(GPIOItems* items, bool level) {
for(uint8_t i = 0; i < items->count; i++) {
gpio_items_set_pin(items, i, level);
}
}
const char* gpio_items_get_pin_name(GPIOItems* items, uint8_t index) {
furi_assert(index < items->count + 1);
if(index == items->count) {
return "ALL";
} else {
return items->pins[index].name;
}
}

View File

@@ -1,29 +0,0 @@
#pragma once
#include <furi_hal_gpio.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct GPIOItems GPIOItems;
GPIOItems* gpio_items_alloc();
void gpio_items_free(GPIOItems* items);
uint8_t gpio_items_get_count(GPIOItems* items);
void gpio_items_configure_pin(GPIOItems* items, uint8_t index, GpioMode mode);
void gpio_items_configure_all_pins(GPIOItems* items, GpioMode mode);
void gpio_items_set_pin(GPIOItems* items, uint8_t index, bool level);
void gpio_items_set_all_pins(GPIOItems* items, bool level);
const char* gpio_items_get_pin_name(GPIOItems* items, uint8_t index);
#ifdef __cplusplus
}
#endif

View File

@@ -1,6 +1,6 @@
#include "../gpio_app_i.h"
#include <furi_hal_power.h>
#include <furi_hal_usb.h>
#include "furi_hal_power.h"
#include "furi_hal_usb.h"
#include <dolphin/dolphin.h>
enum GpioItem {

View File

@@ -12,9 +12,8 @@ void gpio_scene_test_ok_callback(InputType type, void* context) {
}
void gpio_scene_test_on_enter(void* context) {
furi_assert(context);
GpioApp* app = context;
gpio_items_configure_all_pins(app->gpio_items, GpioModeOutputPushPull);
gpio_item_configure_all_pins(GpioModeOutputPushPull);
gpio_test_set_ok_callback(app->gpio_test, gpio_scene_test_ok_callback, app);
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewGpioTest);
}
@@ -26,7 +25,6 @@ bool gpio_scene_test_on_event(void* context, SceneManagerEvent event) {
}
void gpio_scene_test_on_exit(void* context) {
furi_assert(context);
GpioApp* app = context;
gpio_items_configure_all_pins(app->gpio_items, GpioModeAnalog);
UNUSED(context);
gpio_item_configure_all_pins(GpioModeAnalog);
}

View File

@@ -1,6 +1,6 @@
#include "../usb_uart_bridge.h"
#include "../gpio_app_i.h"
#include <furi_hal.h>
#include "furi_hal.h"
typedef enum {
UsbUartLineIndexVcp,

View File

@@ -1,10 +1,10 @@
#include "usb_uart_bridge.h"
#include "usb_cdc.h"
#include <cli/cli_vcp.h>
#include <cli/cli.h>
#include <toolbox/api_lock.h>
#include <furi_hal.h>
#include "furi_hal.h"
#include <furi_hal_usb_cdc.h>
#include "usb_cdc.h"
#include "cli/cli_vcp.h"
#include <toolbox/api_lock.h>
#include "cli/cli.h"
#define USB_CDC_PKT_LEN CDC_DATA_SZ
#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)

View File

@@ -1,5 +1,5 @@
#include "gpio_test.h"
#include "../gpio_items.h"
#include "../gpio_item.h"
#include <gui/elements.h>
@@ -11,7 +11,6 @@ struct GpioTest {
typedef struct {
uint8_t pin_idx;
GPIOItems* gpio_items;
} GpioTestModel;
static bool gpio_test_process_left(GpioTest* gpio_test);
@@ -26,12 +25,7 @@ static void gpio_test_draw_callback(Canvas* canvas, void* _model) {
elements_multiline_text_aligned(
canvas, 64, 16, AlignCenter, AlignTop, "Press < or > to change pin");
elements_multiline_text_aligned(
canvas,
64,
32,
AlignCenter,
AlignTop,
gpio_items_get_pin_name(model->gpio_items, model->pin_idx));
canvas, 64, 32, AlignCenter, AlignTop, gpio_item_get_pin_name(model->pin_idx));
}
static bool gpio_test_input_callback(InputEvent* event, void* context) {
@@ -70,7 +64,7 @@ static bool gpio_test_process_right(GpioTest* gpio_test) {
gpio_test->view,
GpioTestModel * model,
{
if(model->pin_idx < gpio_items_get_count(model->gpio_items)) {
if(model->pin_idx < GPIO_ITEM_COUNT) {
model->pin_idx++;
}
},
@@ -86,17 +80,17 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
GpioTestModel * model,
{
if(event->type == InputTypePress) {
if(model->pin_idx < gpio_items_get_count(model->gpio_items)) {
gpio_items_set_pin(model->gpio_items, model->pin_idx, true);
if(model->pin_idx < GPIO_ITEM_COUNT) {
gpio_item_set_pin(model->pin_idx, true);
} else {
gpio_items_set_all_pins(model->gpio_items, true);
gpio_item_set_all_pins(true);
}
consumed = true;
} else if(event->type == InputTypeRelease) {
if(model->pin_idx < gpio_items_get_count(model->gpio_items)) {
gpio_items_set_pin(model->gpio_items, model->pin_idx, false);
if(model->pin_idx < GPIO_ITEM_COUNT) {
gpio_item_set_pin(model->pin_idx, false);
} else {
gpio_items_set_all_pins(model->gpio_items, false);
gpio_item_set_all_pins(false);
}
consumed = true;
}
@@ -107,15 +101,11 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
return consumed;
}
GpioTest* gpio_test_alloc(GPIOItems* gpio_items) {
GpioTest* gpio_test_alloc() {
GpioTest* gpio_test = malloc(sizeof(GpioTest));
gpio_test->view = view_alloc();
view_allocate_model(gpio_test->view, ViewModelTypeLocking, sizeof(GpioTestModel));
with_view_model(
gpio_test->view, GpioTestModel * model, { model->gpio_items = gpio_items; }, false);
view_set_context(gpio_test->view, gpio_test);
view_set_draw_callback(gpio_test->view, gpio_test_draw_callback);
view_set_input_callback(gpio_test->view, gpio_test_input_callback);

View File

@@ -1,13 +1,11 @@
#pragma once
#include "../gpio_items.h"
#include <gui/view.h>
typedef struct GpioTest GpioTest;
typedef void (*GpioTestOkCallback)(InputType type, void* context);
GpioTest* gpio_test_alloc(GPIOItems* gpio_items);
GpioTest* gpio_test_alloc();
void gpio_test_free(GpioTest* gpio_test);

View File

@@ -1,6 +1,6 @@
#include "../usb_uart_bridge.h"
#include "../gpio_app_i.h"
#include <furi_hal.h>
#include "furi_hal.h"
#include <gui/elements.h>
struct GpioUsbUart {

View File

@@ -2,7 +2,6 @@ App(
appid="ibutton",
name="iButton",
apptype=FlipperAppType.APP,
targets=["f7"],
entry_point="ibutton_app",
cdefines=["APP_IBUTTON"],
requires=[

View File

@@ -271,7 +271,7 @@ void onewire_cli_print_usage() {
static void onewire_cli_search(Cli* cli) {
UNUSED(cli);
OneWireHost* onewire = onewire_host_alloc(&ibutton_gpio);
OneWireHost* onewire = onewire_host_alloc();
uint8_t address[8];
bool done = false;

View File

@@ -3,7 +3,6 @@ App(
name="Infrared",
apptype=FlipperAppType.APP,
entry_point="infrared_app",
targets=["f7"],
cdefines=["APP_INFRARED"],
requires=[
"gui",

View File

@@ -86,7 +86,7 @@ static void infrared_cli_print_usage(void) {
printf("\tir universal <remote_name> <signal_name>\r\n");
printf("\tir universal list <remote_name>\r\n");
// TODO: Do not hardcode universal remote names
printf("\tAvailable universal remotes: tv audio ac projector\r\n");
printf("\tAvailable universal remotes: tv audio ac\r\n");
}
static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args) {

View File

@@ -1,5 +1,5 @@
#include "../infrared_i.h"
#include <gui/canvas.h>
#include "gui/canvas.h"
typedef enum {
InfraredRpcStateIdle,

View File

@@ -52,8 +52,7 @@ void infrared_scene_universal_on_enter(void* context) {
infrared_scene_universal_submenu_callback,
context);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneUniversal));
submenu_set_selected_item(submenu, 0);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu);
}
@@ -80,7 +79,6 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC);
consumed = true;
}
scene_manager_set_scene_state(scene_manager, InfraredSceneUniversal, event.event);
}
return consumed;

View File

@@ -1,11 +1,11 @@
#include "infrared_debug_view.h"
#include <gui/canvas.h>
#include <gui/elements.h>
#include <stdlib.h>
#include <string.h>
#include <gui/canvas.h>
#include <gui/elements.h>
#define INFRARED_DEBUG_TEXT_LENGTH 64
struct InfraredDebugView {

View File

@@ -1,15 +1,13 @@
#include "infrared_progress_view.h"
#include <assets_icons.h>
#include <gui/canvas.h>
#include <gui/view.h>
#include <gui/elements.h>
#include <gui/modules/button_panel.h>
#include <input/input.h>
#include <furi.h>
#include <furi_hal_resources.h>
#include <core/check.h>
#include "furi_hal_resources.h"
#include "assets_icons.h"
#include "gui/canvas.h"
#include "gui/view.h"
#include "input/input.h"
#include <gui/elements.h>
#include <furi.h>
#include "infrared_progress_view.h"
#include "gui/modules/button_panel.h"
#include <stdint.h>
struct InfraredProgressView {

View File

@@ -2,7 +2,6 @@ App(
appid="lfrfid",
name="125 kHz RFID",
apptype=FlipperAppType.APP,
targets=["f7"],
entry_point="lfrfid_app",
cdefines=["APP_LF_RFID"],
requires=[

View File

@@ -47,28 +47,21 @@ bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexRead) {
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, SubmenuIndexRead);
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
DOLPHIN_DEED(DolphinDeedRfidRead);
consumed = true;
} else if(event.event == SubmenuIndexSaved) {
// Like in the other apps, explicitly save the scene state
// in each branch in case the user cancels loading a file.
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, SubmenuIndexSaved);
furi_string_set(app->file_path, LFRFID_APP_FOLDER);
scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectKey);
consumed = true;
} else if(event.event == SubmenuIndexAddManually) {
scene_manager_set_scene_state(
app->scene_manager, LfRfidSceneStart, SubmenuIndexAddManually);
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveType);
consumed = true;
} else if(event.event == SubmenuIndexExtraActions) {
scene_manager_set_scene_state(
app->scene_manager, LfRfidSceneStart, SubmenuIndexExtraActions);
scene_manager_next_scene(app->scene_manager, LfRfidSceneExtraActions);
consumed = true;
}
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, event.event);
}
return consumed;

View File

@@ -2,7 +2,6 @@ App(
appid="nfc",
name="NFC",
apptype=FlipperAppType.APP,
targets=["f7"],
entry_point="nfc_app",
cdefines=["APP_NFC"],
requires=[

View File

@@ -1,5 +1,5 @@
#include "nfc_i.h"
#include <furi_hal_nfc.h>
#include "furi_hal_nfc.h"
#include <dolphin/dolphin.h>
bool nfc_custom_event_callback(void* context, uint32_t event) {

View File

@@ -4,7 +4,7 @@ ADD_SCENE(nfc, saved_menu, SavedMenu)
ADD_SCENE(nfc, extra_actions, ExtraActions)
ADD_SCENE(nfc, set_type, SetType)
ADD_SCENE(nfc, set_sak, SetSak)
ADD_SCENE(nfc, set_atqa, SetAtqa)
ADD_SCENE(nfc, set_atqa, SetAtqua)
ADD_SCENE(nfc, set_uid, SetUid)
ADD_SCENE(nfc, generate_info, GenerateInfo)
ADD_SCENE(nfc, read_card_success, ReadCardSuccess)

View File

@@ -30,7 +30,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
nfc->scene_manager, NfcSceneMfClassicKeys);
} else {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneFileSelect);
nfc->scene_manager, NfcSceneStart);
}
}
}

View File

@@ -34,8 +34,6 @@ void nfc_scene_extra_actions_on_enter(void* context) {
SubmenuIndexMfUltralightUnlock,
nfc_scene_extra_actions_submenu_callback,
nfc);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneExtraActions));
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}

View File

@@ -11,7 +11,7 @@ void nfc_scene_set_atqa_on_enter(void* context) {
// Setup view
ByteInput* byte_input = nfc->byte_input;
byte_input_set_header_text(byte_input, "Enter ATQA in hex");
byte_input_set_header_text(byte_input, "Enter atqa in hex");
byte_input_set_result_callback(
byte_input,
nfc_scene_set_atqa_byte_input_callback,

View File

@@ -28,7 +28,7 @@ bool nfc_scene_set_sak_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventByteInputDone) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqa);
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqua);
consumed = true;
}
}

View File

@@ -11,7 +11,7 @@ void nfc_scene_set_uid_on_enter(void* context) {
// Setup view
ByteInput* byte_input = nfc->byte_input;
byte_input_set_header_text(byte_input, "Enter UID in hex");
byte_input_set_header_text(byte_input, "Enter uid in hex");
nfc->dev_edit_data = nfc->dev->dev_data.nfc_data;
byte_input_set_result_callback(
byte_input,

View File

@@ -48,14 +48,11 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexRead) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexRead);
nfc->dev->dev_data.read_mode = NfcReadModeAuto;
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
DOLPHIN_DEED(DolphinDeedNfcRead);
consumed = true;
} else if(event.event == SubmenuIndexDetectReader) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneStart, SubmenuIndexDetectReader);
bool sd_exist = storage_sd_status(nfc->dev->storage) == FSE_OK;
if(sd_exist) {
nfc_device_data_clear(&nfc->dev->dev_data);
@@ -66,27 +63,19 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
}
consumed = true;
} else if(event.event == SubmenuIndexSaved) {
// Save the scene state explicitly in each branch, so that
// if the user cancels loading a file, the Saved menu item
// is properly reselected.
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexSaved);
scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect);
consumed = true;
} else if(event.event == SubmenuIndexExtraAction) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneStart, SubmenuIndexExtraAction);
scene_manager_next_scene(nfc->scene_manager, NfcSceneExtraActions);
consumed = true;
} else if(event.event == SubmenuIndexAddManually) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManually);
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType);
consumed = true;
} else if(event.event == SubmenuIndexDebug) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebug);
consumed = true;
}
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, event.event);
}
return consumed;
}

View File

@@ -2,7 +2,6 @@ App(
appid="subghz",
name="Sub-GHz",
apptype=FlipperAppType.APP,
targets=["f7"],
entry_point="subghz_app",
cdefines=["APP_SUBGHZ"],
requires=[
@@ -12,7 +11,7 @@ App(
],
provides=["subghz_start"],
icon="A_Sub1ghz_14",
stack_size=3 * 1024,
stack_size=2 * 1024,
order=10,
)

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

@@ -170,6 +170,11 @@ void subghz_scene_decode_raw_on_enter(void* context) {
subghz_receiver_set_rx_callback(
subghz->txrx->receiver, subghz_scene_add_to_history_callback, subghz);
// make sure we're not in auto-detect mode, which is only meant for the Read app
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
false);
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
if(subghz->decode_raw_state == SubGhzDecodeRawStateStart) {

View File

@@ -31,6 +31,7 @@ bool subghz_scene_delete_success_on_event(void* context, SceneManagerEvent event
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW);
} else if(scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneSaved)) {
//scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
} else {
scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart);

View File

@@ -2,7 +2,6 @@
#include "../helpers/subghz_custom_event.h"
uint8_t value_index;
uint8_t value_index2;
#define EXT_MODULES_COUNT (sizeof(radio_modules_variables_text) / sizeof(char* const))
const char* const radio_modules_variables_text[] = {
@@ -10,12 +9,6 @@ const char* const radio_modules_variables_text[] = {
"External",
};
#define DEBUG_P_COUNT 2
const char* const debug_pin_text[DEBUG_P_COUNT] = {
"OFF",
"17(1W)",
};
static void subghz_scene_ext_module_changed(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
value_index = variable_item_get_current_value_index(item);
@@ -28,15 +21,6 @@ static void subghz_ext_module_start_var_list_enter_callback(void* context, uint3
view_dispatcher_send_custom_event(subghz->view_dispatcher, index);
}
static void subghz_scene_receiver_config_set_debug_pin(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, debug_pin_text[index]);
subghz->txrx->debug_pin_state = index == 1;
}
void subghz_scene_ext_module_settings_on_enter(void* context) {
SubGhz* subghz = context;
@@ -52,18 +36,6 @@ void subghz_scene_ext_module_settings_on_enter(void* context) {
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, radio_modules_variables_text[value_index]);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
item = variable_item_list_add(
subghz->variable_item_list,
"Debug Pin:",
DEBUG_P_COUNT,
subghz_scene_receiver_config_set_debug_pin,
subghz);
value_index2 = subghz->txrx->debug_pin_state;
variable_item_set_current_value_index(item, value_index2);
variable_item_set_current_value_text(item, debug_pin_text[value_index2]);
}
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
}
@@ -72,10 +44,8 @@ bool subghz_scene_ext_module_settings_on_event(void* context, SceneManagerEvent
UNUSED(subghz);
UNUSED(event);
// Set selected radio module
furi_hal_subghz_set_radio_type(value_index);
// Check if module is present, if no -> show error
if(!furi_hal_subghz_check_radio()) {
value_index = 0;
furi_hal_subghz_set_radio_type(value_index);
@@ -89,4 +59,5 @@ bool subghz_scene_ext_module_settings_on_event(void* context, SceneManagerEvent
void subghz_scene_ext_module_settings_on_exit(void* context) {
SubGhz* subghz = context;
variable_item_list_reset(subghz->variable_item_list);
//furi_hal_subghz_set_radio_type(value_index);
}

View File

@@ -119,6 +119,9 @@ void subghz_scene_read_raw_on_enter(void* context) {
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME);
furi_assert(subghz->txrx->decoder_result);
// make sure we're not in auto-detect mode, which is only meant for the Read app
subghz_protocol_decoder_raw_set_auto_mode(subghz->txrx->decoder_result, false);
//set filter RAW feed
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_RAW);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReadRAW);
@@ -419,6 +422,10 @@ void subghz_scene_read_raw_on_exit(void* context) {
subghz->state_notifications = SubGhzNotificationStateIDLE;
notification_message(subghz->notifications, &sequence_reset_rgb);
//filter restoration
subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter);
//filter restoration
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
#endif
}

View File

@@ -1,7 +1,6 @@
#include "../subghz_i.h"
#include "../views/receiver.h"
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/bin_raw.h>
#define TAG "SubGhzSceneReceiver"
@@ -161,11 +160,6 @@ void subghz_scene_receiver_on_enter(void* context) {
}
subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen);
//to use a universal decoder, we are looking for a link to it
subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_BIN_RAW_NAME);
furi_assert(subghz->txrx->decoder_result);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReceiver);
}
@@ -229,13 +223,6 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
subghz_hopper_update(subghz);
subghz_scene_receiver_update_statusbar(subghz);
}
//get RSSI
float rssi = furi_hal_subghz_get_rssi();
subghz_receiver_rssi(subghz->subghz_receiver, rssi);
subghz_protocol_decoder_bin_raw_data_input_rssi(
(SubGhzProtocolDecoderBinRAW*)subghz->txrx->decoder_result, rssi);
switch(subghz->state_notifications) {
case SubGhzNotificationStateRx:
notification_message(subghz->notifications, &sequence_blink_cyan_10);

View File

@@ -1,11 +1,16 @@
#include "../subghz_i.h"
#include <lib/toolbox/value_index.h>
#include <lib/subghz/protocols/raw.h>
#define TAG "SubGhzSceneReceiverConfig"
enum SubGhzSettingIndex {
SubGhzSettingIndexFrequency,
SubGhzSettingIndexHopping,
SubGhzSettingIndexModulation,
SubGhzSettingIndexBinRAW,
SubGhzSettingIndexDetectRaw,
SubGhzSettingIndexRSSIThreshold,
SubGhzSettingIndexSound,
SubGhzSettingIndexLock,
SubGhzSettingIndexRAWThesholdRSSI,
@@ -50,6 +55,40 @@ const uint32_t hopping_value[HOPPING_COUNT] = {
SubGhzHopperStateRunnig,
};
#define DETECT_RAW_COUNT 2
const char* const detect_raw_text[DETECT_RAW_COUNT] = {
"OFF",
"ON",
};
#ifndef SUBGHZ_SAVE_DETECT_RAW_SETTING
const SubGhzProtocolFlag detect_raw_value[DETECT_RAW_COUNT] = {
SubGhzProtocolFlag_Decodable,
SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW,
};
#endif
#define RSSI_THRESHOLD_COUNT 7
const char* const rssi_threshold_text[RSSI_THRESHOLD_COUNT] = {
"-72db",
"-67db",
"-62db",
"-57db",
"-52db",
"-47db",
"-42db",
};
const int rssi_threshold_value[RSSI_THRESHOLD_COUNT] = {
-72,
-67,
-62,
-57,
-52,
-47,
-42,
};
#define SPEAKER_COUNT 2
const char* const speaker_text[SPEAKER_COUNT] = {
"OFF",
@@ -59,15 +98,6 @@ const uint32_t speaker_value[SPEAKER_COUNT] = {
SubGhzSpeakerStateShutdown,
SubGhzSpeakerStateEnable,
};
#define BIN_RAW_COUNT 2
const char* const bin_raw_text[BIN_RAW_COUNT] = {
"OFF",
"ON",
};
const uint32_t bin_raw_value[BIN_RAW_COUNT] = {
SubGhzProtocolFlag_Decodable,
SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW,
};
uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
furi_assert(context);
@@ -119,6 +149,36 @@ uint8_t subghz_scene_receiver_config_hopper_value_index(
}
}
#ifndef SUBGHZ_SAVE_DETECT_RAW_SETTING
uint8_t subghz_scene_receiver_config_detect_raw_value_index(
const SubGhzProtocolFlag value,
const SubGhzProtocolFlag values[],
uint8_t values_count) {
uint8_t index = 0;
for(uint8_t i = 0; i < values_count; i++) {
if(value == values[i]) {
index = i;
break;
}
}
return index;
}
#endif
uint8_t subghz_scene_receiver_config_rssi_threshold_value_index(
const int value,
const int values[],
uint8_t values_count) {
uint8_t index = 0;
for(uint8_t i = 0; i < values_count; i++) {
if(value == values[i]) {
index = i;
break;
}
}
return index;
}
static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
@@ -156,40 +216,79 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
subghz_setting_get_preset_data_size(subghz->setting, index));
}
static void subghz_scene_receiver_config_set_rssi_threshold(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, rssi_threshold_text[index]);
subghz_protocol_decoder_raw_set_rssi_threshold(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
rssi_threshold_value[index]);
}
static void subghz_scene_receiver_config_set_detect_raw(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
if(subghz->txrx->hopper_state == 0) {
variable_item_set_current_value_text(item, detect_raw_text[index]);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz->last_settings->detect_raw = index;
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]);
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
(index == 1));
#endif
} else {
variable_item_set_current_value_index(item, 0);
}
}
static void subghz_scene_receiver_config_set_hopping_running(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, hopping_text[index]);
if(hopping_value[index] == SubGhzHopperStateOFF) {
char text_buf[10] = {0};
snprintf(
text_buf,
sizeof(text_buf),
"%lu.%02lu",
subghz_setting_get_default_frequency(subghz->setting) / 1000000,
(subghz_setting_get_default_frequency(subghz->setting) % 1000000) / 10000);
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
text_buf);
subghz->txrx->preset->frequency = subghz_setting_get_default_frequency(subghz->setting);
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_setting_get_frequency_default_index(subghz->setting));
} else {
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
" -----");
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_setting_get_frequency_default_index(subghz->setting));
}
if(subghz_receiver_get_filter(subghz->txrx->receiver) == SubGhzProtocolFlag_Decodable) {
variable_item_set_current_value_text(item, hopping_text[index]);
if(hopping_value[index] == SubGhzHopperStateOFF) {
char text_buf[10] = {0};
snprintf(
text_buf,
sizeof(text_buf),
"%lu.%02lu",
subghz_setting_get_default_frequency(subghz->setting) / 1000000,
(subghz_setting_get_default_frequency(subghz->setting) % 1000000) / 10000);
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
text_buf);
subghz->txrx->preset->frequency =
subghz_setting_get_default_frequency(subghz->setting);
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_setting_get_frequency_default_index(subghz->setting));
} else {
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
" -----");
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_setting_get_frequency_default_index(subghz->setting));
}
subghz->txrx->hopper_state = hopping_value[index];
subghz->txrx->hopper_state = hopping_value[index];
} else {
variable_item_set_current_value_index(item, 0);
}
}
static void subghz_scene_receiver_config_set_speaker(VariableItem* item) {
@@ -200,15 +299,6 @@ static void subghz_scene_receiver_config_set_speaker(VariableItem* item) {
subghz->txrx->speaker_state = speaker_value[index];
}
static void subghz_scene_receiver_config_set_bin_raw(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, bin_raw_text[index]);
subghz->txrx->filter = bin_raw_value[index];
subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter);
}
static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
@@ -231,6 +321,13 @@ void subghz_scene_receiver_config_on_enter(void* context) {
VariableItem* item;
uint8_t value_index;
#ifdef FURI_DEBUG
FURI_LOG_D(
TAG,
"Last frequency: %ld, Preset: %ld",
subghz->last_settings->frequency,
subghz->last_settings->preset);
#endif
item = variable_item_list_add(
subghz->variable_item_list,
"Frequency:",
@@ -276,35 +373,52 @@ void subghz_scene_receiver_config_on_enter(void* context) {
subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, hopping_text[value_index]);
}
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
// Detect Raw
item = variable_item_list_add(
subghz->variable_item_list,
"Bin RAW:",
BIN_RAW_COUNT,
subghz_scene_receiver_config_set_bin_raw,
"Detect Raw:",
DETECT_RAW_COUNT,
subghz_scene_receiver_config_set_detect_raw,
subghz);
value_index = value_index_uint32(subghz->txrx->filter, bin_raw_value, BIN_RAW_COUNT);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
value_index = subghz->last_settings->detect_raw;
#else
value_index = subghz_scene_receiver_config_detect_raw_value_index(
subghz_receiver_get_filter(subghz->txrx->receiver),
detect_raw_value,
DETECT_RAW_COUNT);
#endif
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, bin_raw_text[value_index]);
}
variable_item_set_current_value_text(item, detect_raw_text[value_index]);
// Enable speaker, will send all incoming noises and signals to speaker so you can listen how your remote sounds like :)
item = variable_item_list_add(
subghz->variable_item_list,
"Sound:",
SPEAKER_COUNT,
subghz_scene_receiver_config_set_speaker,
subghz);
value_index = value_index_uint32(subghz->txrx->speaker_state, speaker_value, SPEAKER_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, speaker_text[value_index]);
// RSSI
item = variable_item_list_add(
subghz->variable_item_list,
"RSSI for Raw:",
RSSI_THRESHOLD_COUNT,
subghz_scene_receiver_config_set_rssi_threshold,
subghz);
value_index = subghz_scene_receiver_config_rssi_threshold_value_index(
subghz_protocol_encoder_get_rssi_threshold(subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME)),
rssi_threshold_value,
RSSI_THRESHOLD_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, rssi_threshold_text[value_index]);
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
// Lock keyboard
item = variable_item_list_add(
subghz->variable_item_list,
"Sound:",
SPEAKER_COUNT,
subghz_scene_receiver_config_set_speaker,
subghz);
value_index =
value_index_uint32(subghz->txrx->speaker_state, speaker_value, SPEAKER_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, speaker_text[value_index]);
variable_item_list_add(subghz->variable_item_list, "Lock Keyboard", 1, NULL, NULL);
variable_item_list_set_enter_callback(
subghz->variable_item_list,

View File

@@ -92,6 +92,8 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) {
// Removed static check
if(((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) ==
SubGhzProtocolFlag_Send) &&
// disable "Send" for auto-captured RAW signals for now. They can still be saved and sent by loading them.
subghz->txrx->decoder_result->protocol->type != SubGhzProtocolTypeRAW &&
subghz->txrx->decoder_result->protocol->encoder->deserialize) {
widget_add_button_element(
subghz->widget,
@@ -136,21 +138,6 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
subghz_history_get_raw_data(
subghz->txrx->history, subghz->txrx->idx_menu_chosen))) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx);
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
subghz_tx_stop(subghz);
}
if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) {
subghz_begin(
subghz,
subghz_setting_get_preset_data_by_name(
subghz->setting,
furi_string_get_cstr(subghz->txrx->preset->name)));
subghz_rx(subghz, subghz->txrx->preset->frequency);
}
if(subghz->txrx->hopper_state == SubGhzHopperStatePause) {
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
}
subghz->state_notifications = SubGhzNotificationStateRx;
} else {
subghz->state_notifications = SubGhzNotificationStateTx;
}

View File

@@ -23,6 +23,15 @@ void subghz_scene_start_on_enter(void* context) {
if(subghz->state_notifications == SubGhzNotificationStateStarting) {
subghz->state_notifications = SubGhzNotificationStateIDLE;
}
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
false);
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
#endif
submenu_add_item(
subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz);

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
@@ -247,11 +236,20 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
subghz->last_settings = subghz_last_settings_alloc();
subghz_last_settings_load(subghz->last_settings, 0);
#if FURI_DEBUG
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
FURI_LOG_D(
TAG,
"last frequency: %ld, preset: %ld, detect_raw: %d",
subghz->last_settings->frequency,
subghz->last_settings->preset,
subghz->last_settings->detect_raw);
#else
FURI_LOG_D(
TAG,
"last frequency: %ld, preset: %ld",
subghz->last_settings->frequency,
subghz->last_settings->preset);
#endif
#endif
subghz_setting_set_default_frequency(subghz->setting, subghz->last_settings->frequency);
}
@@ -270,7 +268,6 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
subghz->txrx->speaker_state = SubGhzSpeakerStateDisable;
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
subghz->txrx->debug_pin_state = false;
if(!alloc_for_tx_only) {
subghz->txrx->history = subghz_history_alloc();
}
@@ -284,15 +281,16 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
subghz->txrx->environment = subghz_environment_alloc();
subghz_environment_set_came_atomo_rainbow_table_file_name(
subghz->txrx->environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
subghz->txrx->environment, EXT_PATH("subghz/assets/alutech_at_4n"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(
subghz->txrx->environment, (void*)&subghz_protocol_registry);
subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment);
subghz->txrx->filter = SubGhzProtocolFlag_Decodable;
subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
#endif
subghz_worker_set_overrun_callback(
subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset);
@@ -316,8 +314,6 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) {
subghz->rpc_ctx = NULL;
}
subghz_speaker_off(subghz);
#if FURI_DEBUG
// Packet Test
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestPacket);

View File

@@ -253,8 +253,6 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
subghz_environment_load_keystore(environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user"));
subghz_environment_set_came_atomo_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/alutech_at_4n"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
@@ -307,81 +305,6 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
free(instance);
}
void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) {
UNUSED(context);
uint32_t frequency = 433920000;
if(furi_string_size(args)) {
int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency);
if(ret != 1) {
printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency);
cli_print_usage("subghz rx", "<Frequency: in Hz>", furi_string_get_cstr(args));
return;
}
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
printf(
"Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n",
frequency);
return;
}
}
// Allocate context and buffers
SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
instance->stream =
furi_stream_buffer_alloc(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
furi_check(instance->stream);
// Configure radio
furi_hal_subghz_reset();
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok270Async);
frequency = furi_hal_subghz_set_frequency_and_path(frequency);
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_power_suppress_charge_enter();
// Prepare and start RX
furi_hal_subghz_start_async_rx(subghz_cli_command_rx_capture_callback, instance);
// Wait for packets to arrive
printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
LevelDuration level_duration;
size_t counter = 0;
while(!cli_cmd_interrupt_received(cli)) {
int ret = furi_stream_buffer_receive(
instance->stream, &level_duration, sizeof(LevelDuration), 10);
if(ret == 0) {
continue;
}
if(ret != sizeof(LevelDuration)) {
puts("stream corrupt");
break;
}
if(level_duration_is_reset(level_duration)) {
puts(". ");
} else {
bool level = level_duration_get_level(level_duration);
uint32_t duration = level_duration_get_duration(level_duration);
printf("%c%lu ", level ? '+' : '-', duration);
}
furi_thread_stdout_flush();
counter++;
if(counter > 255) {
puts("\r\n");
counter = 0;
}
}
// Shutdown radio
furi_hal_subghz_stop_async_rx();
furi_hal_subghz_sleep();
furi_hal_power_suppress_charge_exit();
// Cleanup
furi_stream_buffer_free(instance->stream);
free(instance);
}
void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) {
UNUSED(context);
FuriString* file_name;
@@ -450,8 +373,6 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) {
}
subghz_environment_set_came_atomo_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/alutech_at_4n"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
@@ -506,8 +427,7 @@ static void subghz_cli_command_print_usage() {
printf("\tchat <frequency:in Hz>\t - Chat with other Flippers\r\n");
printf(
"\ttx <3 byte Key: in hex> <frequency: in Hz> <te: us> <repeat: count>\t - Transmitting key\r\n");
printf("\trx <frequency:in Hz>\t - Receive\r\n");
printf("\trx_raw <frequency:in Hz>\t - Receive RAW\r\n");
printf("\trx <frequency:in Hz>\t - Reception key\r\n");
printf("\tdecode_raw <file_name: path_RAW_file>\t - Testing\r\n");
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
@@ -809,11 +729,6 @@ static void subghz_cli_command(Cli* cli, FuriString* args, void* context) {
break;
}
if(furi_string_cmp_str(cmd, "rx_raw") == 0) {
subghz_cli_command_rx_raw(cli, args, context);
break;
}
if(furi_string_cmp_str(cmd, "decode_raw") == 0) {
subghz_cli_command_decode_raw(cli, args, context);
break;

View File

@@ -1,15 +1,33 @@
#include "subghz_history.h"
#include "subghz_history_private.h"
#include <lib/subghz/receiver.h>
#include <toolbox/path.h>
#include <flipper_format/flipper_format_i.h>
#include "flipper_format_stream_i.h"
#include <inttypes.h>
#include <furi.h>
#define SUBGHZ_HISTORY_MAX 60
/**
* @brief Settings for temporary files
*
*/
#define SUBGHZ_HISTORY_TMP_DIR EXT_PATH("subghz/tmp_history")
#define SUBGHZ_HISTORY_TMP_EXTENSION ".tmp"
#define SUBGHZ_HISTORY_TMP_SIGNAL_MAX 700
#define SUBGHZ_HISTORY_TMP_SIGNAL_MIN 100
#define SUBGHZ_HISTORY_TMP_REMOVE_FILES true
#define SUBGHZ_HISTORY_TMP_RAW_KEY "RAW_Data"
#define MAX_LINE 500
const size_t buffer_size = 32;
#define SUBGHZ_HISTORY_MAX 55
#define SUBGHZ_HISTORY_FREE_HEAP 20480
#define TAG "SubGhzHistory"
typedef struct {
FuriString* item_str;
FlipperFormat* flipper_string;
FuriString* protocol_name;
bool is_file;
uint8_t type;
SubGhzRadioPreset* preset;
} SubGhzHistoryItem;
@@ -27,30 +45,143 @@ struct SubGhzHistory {
uint16_t last_index_write;
uint8_t code_last_hash_data;
FuriString* tmp_string;
bool write_tmp_files;
Storage* storage;
SubGhzHistoryStruct* history;
};
#ifdef FURI_DEBUG
#define LOG_DELAY 0
#endif
FuriString* subghz_history_generate_temp_filename(uint32_t index) {
FuriHalRtcDateTime datetime = {0};
furi_hal_rtc_get_datetime(&datetime);
return furi_string_alloc_printf("%03ld%s", index, SUBGHZ_HISTORY_TMP_EXTENSION);
}
bool subghz_history_is_tmp_dir_exists(SubGhzHistory* instance) {
FileInfo file_info;
FS_Error error = storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &file_info);
if(error == FSE_OK) {
if(file_info.flags & FSF_DIRECTORY) {
return true;
}
}
return false;
}
bool subghz_history_check_sdcard(SubGhzHistory* instance) {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "check_sdcard");
uint32_t start_time = furi_get_tick();
#endif
bool result = false;
// Stage 0 - check SD Card
FS_Error status = storage_sd_status(instance->storage);
if(status == FSE_OK) {
result = subghz_history_is_tmp_dir_exists(instance);
if(!subghz_history_is_tmp_dir_exists(instance)) {
result = storage_simply_mkdir(instance->storage, SUBGHZ_HISTORY_TMP_DIR);
}
} else {
FURI_LOG_W(TAG, "SD storage not installed! Status: %d", status);
}
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Running time (check_sdcard): %ld ms", furi_get_tick() - start_time);
#endif
return result;
}
void subghz_history_clear_tmp_dir(SubGhzHistory* instance) {
furi_assert(instance);
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "clear_tmp_dir");
#endif
if(!instance->write_tmp_files) {
// Nothing to do here!
return;
}
//uint32_t start_time = furi_get_tick();
#ifdef SUBGHZ_HISTORY_TMP_REMOVE_FILES
// Stage 0 - Dir exists?
bool res = subghz_history_is_tmp_dir_exists(instance);
if(res) {
// Stage 1 - delete all content if exists
FileInfo fileinfo;
storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &fileinfo);
res = fileinfo.flags & FSF_DIRECTORY ?
storage_simply_remove_recursive(instance->storage, SUBGHZ_HISTORY_TMP_DIR) :
(storage_common_remove(instance->storage, SUBGHZ_HISTORY_TMP_DIR) == FSE_OK);
}
// Stage 2 - create dir if necessary
res = storage_simply_mkdir(instance->storage, SUBGHZ_HISTORY_TMP_DIR);
if(!res) {
FURI_LOG_E(TAG, "Cannot process temp dir!");
}
#endif
/* uint32_t stop_time = furi_get_tick() - start_time;
FURI_LOG_I(TAG, "Running time (clear_tmp_dir): %d ms", stop_time);*/
}
SubGhzHistory* subghz_history_alloc(void) {
SubGhzHistory* instance = malloc(sizeof(SubGhzHistory));
instance->tmp_string = furi_string_alloc();
instance->history = malloc(sizeof(SubGhzHistoryStruct));
SubGhzHistoryItemArray_init(instance->history->data);
instance->storage = furi_record_open(RECORD_STORAGE);
instance->write_tmp_files = subghz_history_check_sdcard(instance);
if(!instance->write_tmp_files) {
FURI_LOG_E(TAG, "Unstable work! Cannot use SD Card!");
}
return instance;
}
void subghz_history_item_free(void* current_item) {
furi_assert(current_item);
SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item;
furi_string_free(item->item_str);
furi_string_free(item->preset->name);
furi_string_free(item->protocol_name);
free(item->preset);
item->type = 0;
item->is_file = false;
if(item->flipper_string != NULL) {
flipper_format_free(item->flipper_string);
}
}
void subghz_history_clean_item_array(SubGhzHistory* instance) {
for
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
subghz_history_item_free(item);
}
}
void subghz_history_free(SubGhzHistory* instance) {
furi_assert(instance);
furi_string_free(instance->tmp_string);
for
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
furi_string_free(item->item_str);
furi_string_free(item->preset->name);
free(item->preset);
flipper_format_free(item->flipper_string);
item->type = 0;
}
subghz_history_clean_item_array(instance);
SubGhzHistoryItemArray_clear(instance->history->data);
free(instance->history);
// Delete all temporary file, on exit it's ok
subghz_history_clear_tmp_dir(instance);
furi_record_close(RECORD_STORAGE);
free(instance);
}
@@ -75,14 +206,9 @@ const char* subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) {
void subghz_history_reset(SubGhzHistory* instance) {
furi_assert(instance);
furi_string_reset(instance->tmp_string);
for
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
furi_string_free(item->item_str);
furi_string_free(item->preset->name);
free(item->preset);
flipper_format_free(item->flipper_string);
item->type = 0;
}
subghz_history_clean_item_array(instance);
SubGhzHistoryItemArray_reset(instance->history->data);
instance->last_index_write = 0;
instance->code_last_hash_data = 0;
@@ -102,12 +228,8 @@ uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx)
const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t idx) {
furi_assert(instance);
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
flipper_format_rewind(item->flipper_string);
if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) {
FURI_LOG_E(TAG, "Missing Protocol");
furi_string_reset(instance->tmp_string);
}
return furi_string_get_cstr(instance->tmp_string);
return furi_string_get_cstr(item->protocol_name);
}
FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx) {
@@ -116,27 +238,72 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx
if(item->flipper_string) {
return item->flipper_string;
} else {
return NULL;
bool result_ok = false;
if(instance->write_tmp_files && item->is_file) {
// We have files!
FuriString* filename = subghz_history_generate_temp_filename(idx);
FuriString* dir_path;
dir_path = furi_string_alloc_printf(
"%s/%s", SUBGHZ_HISTORY_TMP_DIR, furi_string_get_cstr(filename));
if(storage_file_exists(instance->storage, furi_string_get_cstr(dir_path))) {
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "Exist: %s", furi_string_get_cstr(dir_path));
furi_delay_ms(LOG_DELAY);
#endif
// Set to current anyway it has NULL value
item->flipper_string = flipper_format_string_alloc();
Stream* dst_stream = flipper_format_get_raw_stream(item->flipper_string);
stream_clean(dst_stream);
size_t size = stream_load_from_file(
dst_stream, instance->storage, furi_string_get_cstr(dir_path));
if(size > 0) {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save ok!");
furi_delay_ms(LOG_DELAY);
#endif
// We changed contents of file, so we no needed to load
// content from disk for the next time
item->is_file = false;
result_ok = true;
} else {
FURI_LOG_E(TAG, "Stream copy failed!");
flipper_format_free(item->flipper_string);
}
} else {
FURI_LOG_E(TAG, "Can't convert filename to file");
}
furi_string_free(filename);
furi_string_free(dir_path);
} else {
#ifdef FURI_DEBUG
FURI_LOG_W(TAG, "Write TMP files failed!");
furi_delay_ms(LOG_DELAY);
#endif
}
return result_ok ? item->flipper_string : NULL;
}
}
bool subghz_history_get_text_space_left(SubGhzHistory* instance, FuriString* output) {
furi_assert(instance);
if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) {
if(output != NULL) furi_string_printf(output, " Free heap LOW");
return true;
}
if(instance->last_index_write == SUBGHZ_HISTORY_MAX) {
if(output != NULL) furi_string_printf(output, " Memory is FULL");
if(output != NULL) furi_string_printf(output, "Memory is FULL");
return true;
}
if(output != NULL)
if(output != NULL) {
furi_string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX);
}
return false;
}
uint16_t subghz_history_get_last_index(SubGhzHistory* instance) {
return instance->last_index_write;
}
void subghz_history_get_text_item_menu(SubGhzHistory* instance, FuriString* output, uint16_t idx) {
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
furi_string_set(output, item->item_str);
@@ -149,8 +316,9 @@ bool subghz_history_add_to_history(
furi_assert(instance);
furi_assert(context);
if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) return false;
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false;
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) {
return false;
}
SubGhzProtocolDecoderBase* decoder_base = context;
if((instance->code_last_hash_data ==
@@ -162,7 +330,6 @@ bool subghz_history_add_to_history(
instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base);
instance->last_update_timestamp = furi_get_tick();
FuriString* text;
text = furi_string_alloc();
SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data);
@@ -175,6 +342,11 @@ bool subghz_history_add_to_history(
item->preset->data_size = preset->data_size;
item->item_str = furi_string_alloc();
item->protocol_name = furi_string_alloc();
bool tmp_file_for_raw = false;
// At this point file mapped to memory otherwise file cannot decode
item->flipper_string = flipper_format_string_alloc();
subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset);
@@ -186,8 +358,26 @@ bool subghz_history_add_to_history(
if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) {
FURI_LOG_E(TAG, "Missing Protocol");
break;
} else {
furi_string_printf(
item->protocol_name, "%s", furi_string_get_cstr(instance->tmp_string));
}
if(!strcmp(furi_string_get_cstr(instance->tmp_string), "KeeLoq")) {
if(!strcmp(furi_string_get_cstr(instance->tmp_string), "RAW")) {
// Enable writing temp files to micro sd
tmp_file_for_raw = true;
// Write display name
furi_string_printf(
item->item_str,
"RAW %03ld.%02ld",
preset->frequency / 1000000 % 1000,
preset->frequency / 10000 % 100);
// Rewind
if(!flipper_format_rewind(item->flipper_string)) {
FURI_LOG_E(TAG, "Rewind error");
}
break;
} else if(!strcmp(furi_string_get_cstr(instance->tmp_string), "KeeLoq")) {
furi_string_set(instance->tmp_string, "KL ");
if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) {
FURI_LOG_E(TAG, "Missing Protocol");
@@ -208,34 +398,485 @@ bool subghz_history_add_to_history(
}
uint8_t key_data[sizeof(uint64_t)] = {0};
if(!flipper_format_read_hex(item->flipper_string, "Key", key_data, sizeof(uint64_t))) {
FURI_LOG_D(TAG, "No Key");
FURI_LOG_E(TAG, "Missing Key");
break;
}
uint64_t data = 0;
for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
data = (data << 8) | key_data[i];
}
if(data != 0) {
if(!(uint32_t)(data >> 32)) {
furi_string_printf(
item->item_str,
"%s %lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data & 0xFFFFFFFF));
} else {
furi_string_printf(
item->item_str,
"%s %lX%08lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data >> 32),
(uint32_t)(data & 0xFFFFFFFF));
}
} else {
furi_string_printf(item->item_str, "%s", furi_string_get_cstr(instance->tmp_string));
}
if(!(uint32_t)(data >> 32)) {
furi_string_printf(
item->item_str,
"%s %lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data & 0xFFFFFFFF));
} else {
furi_string_printf(
item->item_str,
"%s %lX%08lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data >> 32),
(uint32_t)(data & 0xFFFFFFFF));
}
} while(false);
// If we can write to files
if(instance->write_tmp_files && tmp_file_for_raw) {
FuriString* filename = subghz_history_generate_temp_filename(instance->last_index_write);
FuriString* dir_path;
dir_path = furi_string_alloc();
furi_string_cat_printf(
dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, furi_string_get_cstr(filename));
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save temp file: %s", furi_string_get_cstr(dir_path));
#endif
if(!subghz_history_tmp_write_file_split(instance, item, furi_string_get_cstr(dir_path))) {
// Plan B!
subghz_history_tmp_write_file_full(instance, item, dir_path);
}
if(item->is_file) {
flipper_format_free(item->flipper_string);
item->flipper_string = NULL;
}
furi_string_free(filename);
furi_string_free(dir_path);
} else {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Old fashion way");
#endif
}
furi_string_free(text);
instance->last_index_write++;
return true;
}
static inline bool is_space_playground(char c) {
return c == ' ' || c == '\t' || c == flipper_format_eolr;
}
bool subghz_history_stream_read_valid_key(Stream* stream, FuriString* key) {
furi_string_reset(key);
uint8_t buffer[buffer_size];
bool found = false;
bool error = false;
bool accumulate = true;
bool new_line = true;
while(true) {
size_t was_read = stream_read(stream, buffer, buffer_size);
if(was_read == 0) break;
for(size_t i = 0; i < was_read; i++) {
uint8_t data = buffer[i];
if(data == flipper_format_eoln) {
// EOL found, clean data, start accumulating data and set the new_line flag
furi_string_reset(key);
accumulate = true;
new_line = true;
} else if(data == flipper_format_eolr) {
// ignore
} else if(data == flipper_format_comment && new_line) {
// if there is a comment character and we are at the beginning of a new line
// do not accumulate comment data and reset the new_line flag
accumulate = false;
new_line = false;
} else if(data == flipper_format_delimiter) {
if(new_line) {
// we are on a "new line" and found the delimiter
// this can only be if we have previously found some kind of key, so
// clear the data, set the flag that we no longer want to accumulate data
// and reset the new_line flag
furi_string_reset(key);
accumulate = false;
new_line = false;
} else {
// parse the delimiter only if we are accumulating data
if(accumulate) {
// we found the delimiter, move the rw pointer to the delimiter location
// and signal that we have found something
if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
error = true;
break;
}
found = true;
break;
}
}
} else {
// just new symbol, reset the new_line flag
new_line = false;
if(accumulate) {
// and accumulate data if we want
furi_string_push_back(key, data);
}
}
}
if(found || error) break;
}
return found;
}
bool subghz_history_stream_seek_to_key(Stream* stream, const char* key, bool strict_mode) {
bool found = false;
FuriString* read_key;
read_key = furi_string_alloc();
while(!stream_eof(stream)) {
if(subghz_history_stream_read_valid_key(stream, read_key)) {
if(furi_string_cmp_str(read_key, key) == 0) {
if(!stream_seek(stream, 2, StreamOffsetFromCurrent)) {
break;
}
found = true;
break;
} else if(strict_mode) {
found = false;
break;
}
}
}
furi_string_free(read_key);
return found;
}
bool subghz_history_stream_read_value(Stream* stream, FuriString* value, bool* last) {
enum { LeadingSpace, ReadValue, TrailingSpace } state = LeadingSpace;
const size_t buffer_size = 32;
uint8_t buffer[buffer_size];
bool result = false;
bool error = false;
furi_string_reset(value);
while(true) {
size_t was_read = stream_read(stream, buffer, buffer_size);
if(was_read == 0) {
if(state != LeadingSpace && stream_eof(stream)) {
result = true;
*last = true;
} else {
error = true;
}
}
for(uint16_t i = 0; i < was_read; i++) {
const uint8_t data = buffer[i];
if(state == LeadingSpace) {
if(is_space_playground(data)) {
continue;
} else if(data == flipper_format_eoln) {
stream_seek(stream, i - was_read, StreamOffsetFromCurrent);
error = true;
break;
} else {
state = ReadValue;
furi_string_push_back(value, data);
}
} else if(state == ReadValue) {
if(is_space_playground(data)) {
state = TrailingSpace;
} else if(data == flipper_format_eoln) {
if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
error = true;
} else {
result = true;
*last = true;
}
break;
} else {
furi_string_push_back(value, data);
}
} else if(state == TrailingSpace) {
if(is_space_playground(data)) {
continue;
} else if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
error = true;
} else {
*last = (data == flipper_format_eoln);
result = true;
}
break;
}
}
if(error || result) break;
}
return result;
}
bool subghz_history_read_int32(Stream* stream, int32_t* _data, const uint16_t data_size) {
bool result = false;
result = true;
FuriString* value;
value = furi_string_alloc();
for(size_t i = 0; i < data_size; i++) {
bool last = false;
result = subghz_history_stream_read_value(stream, value, &last);
if(result) {
int scan_values = 0;
int32_t* data = _data;
scan_values = sscanf(furi_string_get_cstr(value), "%" PRIi32, &data[i]);
if(scan_values != 1) {
result = false;
break;
}
} else {
break;
}
if(last && ((i + 1) != data_size)) {
result = false;
break;
}
}
furi_string_free(value);
return result;
}
uint32_t subghz_history_rand_range(uint32_t min, uint32_t max) {
// size of range, inclusive
const uint32_t length_of_range = max - min + 1;
// add n so that we don't return a number below our range
return (uint32_t)(rand() % length_of_range + min);
}
bool subghz_history_write_file_noise(
Stream* file,
bool is_negative_start,
size_t current_position,
bool empty_line) {
size_t was_write = 0;
if(empty_line) {
was_write = stream_write_format(file, "%s: ", SUBGHZ_HISTORY_TMP_RAW_KEY);
if(was_write <= 0) {
FURI_LOG_E(TAG, "Can't write key!");
return false;
}
}
int8_t first;
int8_t second;
if(is_negative_start) {
first = -1;
second = 1;
} else {
first = 1;
second = -1;
}
while(current_position < MAX_LINE) {
was_write = stream_write_format(
file,
"%ld %ld ",
subghz_history_rand_range(
SUBGHZ_HISTORY_TMP_SIGNAL_MIN, SUBGHZ_HISTORY_TMP_SIGNAL_MAX) *
first,
subghz_history_rand_range(
SUBGHZ_HISTORY_TMP_SIGNAL_MIN, SUBGHZ_HISTORY_TMP_SIGNAL_MAX) *
second);
if(was_write <= 0) {
FURI_LOG_E(TAG, "Can't write random values!");
return false;
}
current_position += was_write;
}
// Step back to write \n instead of space
size_t offset = stream_tell(file);
if(stream_seek(file, offset - 1, StreamOffsetFromCurrent)) {
FURI_LOG_E(TAG, "Step back failed!");
return false;
}
return stream_write_char(file, flipper_format_eoln) > 0;
}
bool subghz_history_write_file_data(
Stream* src,
Stream* file,
bool* is_negative_start,
size_t* current_position) {
size_t offset_file = 0;
bool result = false;
int32_t value = 0;
do {
if(!subghz_history_read_int32(src, &value, 1)) {
result = true;
break;
}
offset_file = stream_tell(file);
stream_write_format(file, "%ld ", value);
*current_position += stream_tell(file) - offset_file;
if(*current_position > MAX_LINE) {
if((is_negative_start && value > 0) || (!is_negative_start && value < 0)) {
// Align values
continue;
}
if(stream_write_format(file, "\n%s: ", SUBGHZ_HISTORY_TMP_RAW_KEY) == 0) {
FURI_LOG_E(TAG, "Can't write new line!");
result = false;
break;
}
*current_position = 0;
}
} while(true);
*is_negative_start = value < 0;
return result;
}
bool subghz_history_tmp_write_file_split(
SubGhzHistory* instance,
void* current_item,
const char* dir_path) {
furi_assert(instance);
furi_assert(current_item);
furi_assert(dir_path);
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save temp file splitted: %s", dir_path);
#endif
SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item;
uint8_t buffer[buffer_size];
Stream* src = flipper_format_get_raw_stream(item->flipper_string);
stream_rewind(src);
FlipperFormat* flipper_format_file = flipper_format_file_alloc(instance->storage);
bool result = false;
FuriString* temp_str = furi_string_alloc();
do {
if(storage_file_exists(instance->storage, dir_path) &&
storage_common_remove(instance->storage, dir_path) != FSE_OK) {
FURI_LOG_E(TAG, "Can't delete old file!");
break;
}
path_extract_dirname(dir_path, temp_str);
FS_Error fs_result =
storage_common_mkdir(instance->storage, furi_string_get_cstr(temp_str));
if(fs_result != FSE_OK && fs_result != FSE_EXIST) {
FURI_LOG_E(TAG, "Can't create dir!");
break;
}
result = flipper_format_file_open_always(flipper_format_file, dir_path);
if(!result) {
FURI_LOG_E(TAG, "Can't open file for write!");
break;
}
Stream* file = flipper_format_get_raw_stream(flipper_format_file);
if(!subghz_history_stream_seek_to_key(src, SUBGHZ_HISTORY_TMP_RAW_KEY, false)) {
FURI_LOG_E(TAG, "Can't find key!");
break;
}
bool is_negative_start = false;
bool found = false;
size_t offset_start;
offset_start = stream_tell(src);
// Check for negative value at the start and end to align file by correct values
size_t was_read = stream_read(src, buffer, 1);
if(was_read <= 0) {
FURI_LOG_E(TAG, "Can't obtain first mark!");
break;
}
is_negative_start = buffer[0] == '-';
// Ready to write stream to file
size_t current_position;
stream_rewind(src);
current_position = stream_copy(src, file, offset_start);
if(current_position != offset_start) {
FURI_LOG_E(TAG, "Invalid copy header data from one stream to another!");
break;
}
found = true;
current_position = 0;
if(!subghz_history_write_file_noise(file, is_negative_start, current_position, false)) {
FURI_LOG_E(TAG, "Add start noise failed!");
break;
}
if(stream_write_format(file, "%s: ", SUBGHZ_HISTORY_TMP_RAW_KEY) == 0) {
FURI_LOG_E(TAG, "Can't write new line!");
result = false;
break;
}
if(!subghz_history_write_file_data(src, file, &is_negative_start, &current_position)) {
FURI_LOG_E(TAG, "Split by lines failed!");
break;
}
if(!subghz_history_write_file_noise(file, is_negative_start, current_position, false)) {
FURI_LOG_E(TAG, "Add end noise failed!");
break;
}
if(!subghz_history_write_file_noise(file, is_negative_start, 0, true)) {
FURI_LOG_E(TAG, "Add end noise failed!");
break;
}
result = found;
} while(false);
flipper_format_file_close(flipper_format_file);
flipper_format_free(flipper_format_file);
furi_string_free(temp_str);
item->is_file = result;
return result;
}
void subghz_history_tmp_write_file_full(
SubGhzHistory* instance,
void* current_item,
FuriString* dir_path) {
SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item;
#ifdef FURI_DEBUG
FURI_LOG_W(TAG, "Save temp file full: %s", furi_string_get_cstr(dir_path));
#endif
Stream* dst = flipper_format_get_raw_stream(item->flipper_string);
stream_rewind(dst);
if(stream_save_to_file(
dst, instance->storage, furi_string_get_cstr(dir_path), FSOM_CREATE_ALWAYS) > 0) {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save done!");
#endif
// This item contains fake data to load from SD
item->is_file = true;
} else {
FURI_LOG_E(TAG, "Stream copy failed!");
}
}

View File

@@ -597,15 +597,9 @@ 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);
}
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_acquire(30)) {
if(!subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
}
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
} else {
subghz->txrx->speaker_state = SubGhzSpeakerStateDisable;
}
@@ -613,14 +607,9 @@ void subghz_speaker_on(SubGhz* subghz) {
}
void subghz_speaker_off(SubGhz* subghz) {
if(subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(NULL);
}
if(subghz->txrx->speaker_state != SubGhzSpeakerStateDisable) {
if(furi_hal_speaker_is_mine()) {
if(!subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(NULL);
}
furi_hal_subghz_set_async_mirror_pin(NULL);
furi_hal_speaker_release();
if(subghz->txrx->speaker_state == SubGhzSpeakerStateShutdown)
subghz->txrx->speaker_state = SubGhzSpeakerStateDisable;
@@ -629,27 +618,17 @@ void subghz_speaker_off(SubGhz* subghz) {
}
void subghz_speaker_mute(SubGhz* subghz) {
if(subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(NULL);
}
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_is_mine()) {
if(!subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(NULL);
}
furi_hal_subghz_set_async_mirror_pin(NULL);
}
}
}
void subghz_speaker_unmute(SubGhz* subghz) {
if(subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(&ibutton_gpio);
}
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_is_mine()) {
if(!subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
}
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
}
}
}

View File

@@ -62,7 +62,6 @@ struct SubGhzTxRx {
SubGhzEnvironment* environment;
SubGhzReceiver* receiver;
SubGhzTransmitter* transmitter;
SubGhzProtocolFlag filter;
SubGhzProtocolDecoderBase* decoder_result;
FlipperFormat* fff_data;
SecureData* secure_data;
@@ -77,8 +76,6 @@ struct SubGhzTxRx {
uint8_t hopper_idx_frequency;
SubGhzRxKeyState rx_key_state;
bool debug_pin_state;
float raw_threshold_rssi;
uint8_t raw_threshold_rssi_low_count;
};

View File

@@ -1,5 +1,8 @@
#include "subghz_last_settings.h"
#include "subghz_i.h"
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
#include <lib/subghz/protocols/raw.h>
#endif
#define TAG "SubGhzLastSettings"
@@ -13,6 +16,11 @@
#define SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_FEEDBACK_LEVEL 2
#define SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER -93.0f
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
#define SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW 0
#define SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW "DetectRaw"
#endif
#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY "Frequency"
//#define SUBGHZ_LAST_SETTING_FIELD_PRESET "Preset"
#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_FEEDBACK_LEVEL "FeedbackLevel"
@@ -44,6 +52,9 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
//int32_t temp_preset = 0;
bool frequency_analyzer_feedback_level_was_read = false;
bool frequency_analyzer_trigger_was_read = false;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
uint32_t temp_read_raw = 0;
#endif
if(FSE_OK == storage_sd_status(storage) && SUBGHZ_LAST_SETTINGS_PATH &&
flipper_format_file_open_existing(fff_data_file, SUBGHZ_LAST_SETTINGS_PATH)) {
@@ -62,7 +73,10 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_TRIGGER,
(float*)&temp_frequency_analyzer_trigger,
1);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
flipper_format_read_uint32(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, (uint32_t*)&temp_read_raw, 1);
#endif
} else {
FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH);
}
@@ -74,7 +88,9 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
instance->frequency_analyzer_feedback_level =
SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_FEEDBACK_LEVEL;
instance->frequency_analyzer_trigger = SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
instance->detect_raw = SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW;
#endif
} else {
instance->frequency = temp_frequency;
instance->frequency_analyzer_feedback_level =
@@ -85,6 +101,9 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
instance->frequency_analyzer_trigger = frequency_analyzer_trigger_was_read ?
temp_frequency_analyzer_trigger :
SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
instance->detect_raw = temp_read_raw;
#endif
/*if(temp_preset > (int32_t)preset_count - 1 || temp_preset < 0) {
FURI_LOG_W(TAG, "Last used preset no found");*/
@@ -145,6 +164,12 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) {
1)) {
break;
}
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
if(!flipper_format_insert_or_update_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, &instance->detect_raw, 1)) {
break;
}
#endif
saved = true;
} while(0);
@@ -158,3 +183,17 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) {
return saved;
}
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
void subghz_last_settings_set_detect_raw_values(void* context) {
furi_assert(context);
SubGhz* instance = (SubGhz*)context;
bool is_detect_raw = instance->last_settings->detect_raw > 0;
subghz_receiver_set_filter(
instance->txrx->receiver, is_detect_raw ? DETECT_RAW_TRUE : DETECT_RAW_FALSE);
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
instance->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
is_detect_raw);
}
#endif

View File

@@ -1,12 +1,23 @@
#pragma once
// Enable saving detect raw setting state
// #define SUBGHZ_SAVE_DETECT_RAW_SETTING 1
#include <furi_hal.h>
#include <stdint.h>
#include <stdbool.h>
#include <storage/storage.h>
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
#include <lib/subghz/protocols/base.h>
#define DETECT_RAW_FALSE SubGhzProtocolFlag_Decodable
#define DETECT_RAW_TRUE SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW
#endif
typedef struct {
uint32_t frequency;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
uint32_t detect_raw;
#endif
int32_t preset;
uint32_t frequency_analyzer_feedback_level;
float frequency_analyzer_trigger;
@@ -19,3 +30,6 @@ void subghz_last_settings_free(SubGhzLastSettings* instance);
void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count);
bool subghz_last_settings_save(SubGhzLastSettings* instance);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
void subghz_last_settings_set_detect_raw_values(void* context);
#endif

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;
@@ -34,7 +32,7 @@ static const Icon* ReceiverItemIcons[] = {
[SubGhzProtocolTypeUnknown] = &I_Quest_7x8,
[SubGhzProtocolTypeStatic] = &I_Static_9x7,
[SubGhzProtocolTypeDynamic] = &I_Dynamic_9x7,
[SubGhzProtocolTypeBinRAW] = &I_Raw_9x7,
[SubGhzProtocolTypeRAW] = &I_Raw_9x7,
};
typedef enum {
@@ -64,7 +62,6 @@ typedef struct {
uint16_t history_item;
SubGhzViewReceiverBarShow bar_show;
SubGhzViewReceiverMode mode;
uint8_t u_rssi;
} SubGhzViewReceiverModel;
void subghz_view_receiver_set_mode(
@@ -74,21 +71,6 @@ void subghz_view_receiver_set_mode(
subghz_receiver->view, SubGhzViewReceiverModel * model, { model->mode = mode; }, true);
}
void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi) {
furi_assert(instance);
with_view_model(
instance->view,
SubGhzViewReceiverModel * model,
{
if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) {
model->u_rssi = 0;
} else {
model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN);
}
},
true);
}
void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock lock) {
furi_assert(subghz_receiver);
subghz_receiver->lock_count = 0;
@@ -207,16 +189,6 @@ static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool s
canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11);
}
static void subghz_view_rssi_draw(Canvas* canvas, SubGhzViewReceiverModel* 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 subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
@@ -224,9 +196,8 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
if(model->mode == SubGhzViewReceiverModeLive) {
elements_button_left(canvas, "Config");
//canvas_draw_line(canvas, 46, 51, 125, 51);
canvas_draw_line(canvas, 46, 51, 125, 51);
} else {
canvas_draw_line(canvas, 2, 52, 125, 52);
canvas_draw_str(canvas, 3, 62, furi_string_get_cstr(model->progress_str));
}
@@ -266,7 +237,7 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
furi_hal_subghz_get_radio_type() ? &I_Fishing_123x52 : &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);
} else {
canvas_draw_icon(
@@ -280,9 +251,6 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
}
}
if(model->mode == SubGhzViewReceiverModeLive) {
subghz_view_rssi_draw(canvas, model);
}
switch(model->bar_show) {
case SubGhzViewReceiverBarShowLock:
canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8);

View File

@@ -12,8 +12,6 @@ void subghz_view_receiver_set_mode(
SubGhzViewReceiver* subghz_receiver,
SubGhzViewReceiverMode mode);
void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi);
void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock keyboard);
void subghz_view_receiver_set_callback(

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

@@ -30,7 +30,6 @@ typedef struct {
SubGhzReadRAWStatus status;
bool raw_send_only;
float raw_threshold_rssi;
bool not_showing_samples;
} SubGhzReadRAWModel;
void subghz_read_raw_set_callback(
@@ -93,10 +92,7 @@ void subghz_read_raw_update_sample_write(SubGhzReadRAW* instance, size_t sample)
with_view_model(
instance->view,
SubGhzReadRAWModel * model,
{
model->not_showing_samples = false;
furi_string_printf(model->sample_write, "%zu spl.", sample);
},
{ furi_string_printf(model->sample_write, "%zu spl.", sample); },
false);
}
@@ -287,10 +283,21 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) {
canvas_draw_str(canvas, 0, 7, furi_string_get_cstr(model->frequency_str));
canvas_draw_str(canvas, 35, 7, furi_string_get_cstr(model->preset_str));
if(model->not_showing_samples) {
canvas_draw_str(canvas, 77, 7, furi_hal_subghz_get_radio_type() ? "R: Ext" : "R: Int");
} else {
switch(model->status) {
case SubGhzReadRAWStatusIDLE:
canvas_draw_str(canvas, 70, 7, furi_hal_subghz_get_radio_type() ? "E" : "I");
break;
case SubGhzReadRAWStatusLoadKeyIDLE:
case SubGhzReadRAWStatusTX:
case SubGhzReadRAWStatusTXRepeat:
case SubGhzReadRAWStatusLoadKeyTX:
case SubGhzReadRAWStatusLoadKeyTXRepeat:
case SubGhzReadRAWStatusStart:
canvas_draw_str(canvas, 77, 7, furi_hal_subghz_get_radio_type() ? "R: Ext" : "R: Int");
break;
default:
canvas_draw_str(canvas, 70, 7, furi_hal_subghz_get_radio_type() ? "E" : "I");
break;
}
canvas_draw_str_aligned(
@@ -459,7 +466,6 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
model->status = SubGhzReadRAWStatusStart;
model->rssi_history_end = false;
model->ind_write = 0;
model->not_showing_samples = true;
furi_string_set(model->sample_write, "0 spl.");
furi_string_reset(model->file_name);
instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context);
@@ -521,7 +527,6 @@ void subghz_read_raw_set_status(
model->status = SubGhzReadRAWStatusStart;
model->rssi_history_end = false;
model->ind_write = 0;
model->not_showing_samples = true;
furi_string_reset(model->file_name);
furi_string_set(model->sample_write, "0 spl.");
model->raw_threshold_rssi = raw_threshold_rssi;
@@ -543,7 +548,6 @@ void subghz_read_raw_set_status(
model->status = SubGhzReadRAWStatusLoadKeyIDLE;
model->rssi_history_end = false;
model->ind_write = 0;
model->not_showing_samples = true;
furi_string_set(model->file_name, file_name);
furi_string_set(model->sample_write, "RAW");
},
@@ -556,7 +560,6 @@ void subghz_read_raw_set_status(
{
model->status = SubGhzReadRAWStatusLoadKeyIDLE;
if(!model->ind_write) {
model->not_showing_samples = true;
furi_string_set(model->file_name, file_name);
furi_string_set(model->sample_write, "RAW");
} else {

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

@@ -84,8 +84,7 @@ void subghz_view_transmitter_draw(Canvas* canvas, SubGhzViewTransmitterModel* mo
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
elements_multiline_text_aligned(
canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->key_str));
elements_multiline_text(canvas, 0, 7, furi_string_get_cstr(model->key_str));
canvas_draw_str(canvas, 78, 7, furi_string_get_cstr(model->frequency_str));
canvas_draw_str(canvas, 113, 7, furi_string_get_cstr(model->preset_str));

View File

@@ -1,7 +1,7 @@
#include "../u2f_app_i.h"
#include "../views/u2f_view.h"
#include <dolphin/dolphin.h>
#include <furi_hal.h>
#include "furi_hal.h"
#include "../u2f.h"
#define U2F_REQUEST_TIMEOUT 500

View File

@@ -5,7 +5,6 @@
#include <gui/view.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <dolphin/dolphin.h>
#define TAG "Arkanoid"
@@ -398,9 +397,6 @@ int32_t arkanoid_game_app(void* p) {
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
// Call dolphin deed on game start
DOLPHIN_DEED(DolphinDeedPluginGameStart);
GameEvent event;
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);

View File

@@ -571,8 +571,6 @@ int32_t blackjack_app(void* p) {
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
AppEvent event;
// Call dolphin deed on game start
DOLPHIN_DEED(DolphinDeedPluginGameStart);
for(bool processing = true; processing;) {

View File

@@ -13,7 +13,6 @@
#include "level.h"
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <dolphin/dolphin.h>
#define SOUND
@@ -990,9 +989,6 @@ int32_t doom_app() {
music_player_worker_load_rtttl_from_string(plugin_state->music_instance->worker, dsintro);
music_player_worker_start(plugin_state->music_instance->worker);
#endif
// Call dolphin deed on game start
DOLPHIN_DEED(DolphinDeedPluginGameStart);
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex);

View File

@@ -5,7 +5,6 @@
#include <gui/gui.h>
#include <gui/icon_animation_i.h>
#include <input/input.h>
#include <dolphin/dolphin.h>
#define TAG "Flappy"
#define DEBUG false
@@ -308,9 +307,6 @@ int32_t flappy_game_app(void* p) {
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
// Call dolphin deed on game start
DOLPHIN_DEED(DolphinDeedPluginGameStart);
GameEvent event;
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);

View File

@@ -3,7 +3,6 @@
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <storage/storage.h>
#include <dolphin/dolphin.h>
#include "sandbox.h"
@@ -462,10 +461,6 @@ int32_t game15_app() {
sandbox_init(
FPS, (SandboxRenderCallback)render_callback, (SandboxEventHandler)game_event_handler);
// Call dolphin deed on game start
DOLPHIN_DEED(DolphinDeedPluginGameStart);
sandbox_loop();
sandbox_free();
game_free();

View File

@@ -13,7 +13,6 @@
#include <gui/gui.h>
#include <input/input.h>
#include <storage/storage.h>
#include <dolphin/dolphin.h>
#include "digits.h"
#include "array_utils.h"
@@ -383,7 +382,7 @@ int32_t game_2048_app() {
ValueMutex state_mutex;
if(!init_mutex(&state_mutex, game_state, sizeof(GameState))) {
FURI_LOG_E("2048Game", "cannot create mutex\r\n");
FURI_LOG_E("SnakeGame", "cannot create mutex\r\n");
free(game_state);
return 255;
}
@@ -398,9 +397,6 @@ int32_t game_2048_app() {
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
// Call dolphin deed on game start
DOLPHIN_DEED(DolphinDeedPluginGameStart);
bool is_finished = false;
while(!is_finished) {
FuriStatus event_status = furi_message_queue_get(event_queue, &input, FuriWaitForever);

View File

@@ -15,7 +15,6 @@
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <gui/canvas_i.h>
#include <dolphin/dolphin.h>
#define Y_FIELD_SIZE 6
#define Y_LAST (Y_FIELD_SIZE - 1)
@@ -531,9 +530,6 @@ int32_t heap_defence_app(void* p) {
game->game_status = 0;
game->animation = AnimationPause;
// Call dolphin deed on game start
DOLPHIN_DEED(DolphinDeedPluginGameStart);
GameEvent event = {0};
while(event.input.key != InputKeyBack) {
if(furi_message_queue_get(event_queue, &event, 100) != FuriStatusOk) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 B

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