Compare commits

..

1 Commits

Author SHA1 Message Date
d4rks1d33 7ebd996eed Fxck! 2.0
Build Dev Firmware / build (push) Successful in 16m53s
2026-06-26 00:52:09 -03:00
54 changed files with 1331 additions and 389 deletions
@@ -402,7 +402,7 @@ static bool subghz_protocol_encoder_alutech_at_4n_get_upload(
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(btn);
// subghz_custom_btn_set_original(btn);
}
btn = subghz_protocol_alutech_at_4n_get_btn_code();
@@ -727,9 +727,9 @@ static void subghz_protocol_alutech_at_4n_remote_controller(
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
// subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(4);
// subghz_custom_btn_set_max(4);
}
uint8_t subghz_protocol_decoder_alutech_at_4n_get_hash_data(void* context) {
@@ -206,10 +206,10 @@ static uint64_t
generic->seed = ((uint16_t)encrypted_data[14] << 8) | encrypted_data[15];
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(generic->btn);
}
subghz_custom_btn_set_max(2);
// if(subghz_custom_btn_get_original() == 0) {
// subghz_custom_btn_set_original(generic->btn);
// }
// subghz_custom_btn_set_max(2);
return middle_bytes;
}
@@ -244,9 +244,9 @@ static void subghz_protocol_encoder_came_atomo_get_upload(
}
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(btn);
}
// if(subghz_custom_btn_get_original() == 0) {
// // // subghz_custom_btn_set_original(btn);
// }
btn = subghz_protocol_came_atomo_get_btn_code();
@@ -669,9 +669,9 @@ static void subghz_protocol_came_atomo_remote_controller(SubGhzBlockGeneric* ins
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
// subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(3);
// subghz_custom_btn_set_max(3);
}
void atomo_encrypt(uint8_t* buff) {
@@ -131,7 +131,7 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
} else {
// TODO: Stupid bypass for custom button, remake later
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(0xF);
// subghz_custom_btn_set_original(0xF);
}
uint8_t custom_btn_id = subghz_custom_btn_get();
@@ -565,10 +565,10 @@ static void subghz_protocol_faac_slh_check_remote_controller(
// TODO: Stupid bypass for custom button, remake later
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(0xF);
// subghz_custom_btn_set_original(0xF);
}
subghz_custom_btn_set_max(1);
// subghz_custom_btn_set_max(1);
uint8_t data_tmp = 0;
uint8_t data_prg[8];
@@ -230,10 +230,10 @@ static void subghz_protocol_gangqi_remote_controller(SubGhzBlockGeneric* instanc
instance->serial = (instance->data & 0xFFFFF0000) >> 16;
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(3);
// if(subghz_custom_btn_get_original() == 0) {
// subghz_custom_btn_set_original(instance->btn);
// }
// subghz_custom_btn_set_max(3);
// GangQi Decoder
// 09.2024 - @xMasterX (MMX) (last update - bytesum calculation at 02.2025)
@@ -223,9 +223,7 @@ static void subghz_protocol_hay21_remote_controller(SubGhzBlockGeneric* instance
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(2);
// Hay21 Decoder
// 09.2024 - @xMasterX (MMX)
@@ -225,9 +225,9 @@ static void subghz_protocol_hollarm_remote_controller(SubGhzBlockGeneric* instan
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
// subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(3);
// subghz_custom_btn_set_max(3);
// Hollarm Decoder
// 09.2024 - @xMasterX (MMX)
@@ -147,7 +147,7 @@ static bool
subghz_protocol_jarolift_gen_data(SubGhzProtocolEncoderJarolift* instance, uint8_t btn) {
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(btn);
// subghz_custom_btn_set_original(btn);
}
btn = subghz_protocol_jarolift_get_btn_code();
@@ -605,9 +605,9 @@ static void subghz_protocol_jarolift_remote_controller(
instance->cnt = decrypt & 0xFFFF;
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
// subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(3);
// subghz_custom_btn_set_max(3);
} else {
instance->btn = 0;
instance->serial = 0;
@@ -149,7 +149,7 @@ static bool subghz_protocol_kinggates_stylo_4k_gen_data(
uint8_t btn) {
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(btn);
// subghz_custom_btn_set_original(btn);
}
btn = subghz_protocol_kinggates_stylo_4k_get_btn_code();
@@ -576,9 +576,9 @@ static void subghz_protocol_kinggates_stylo_4k_remote_controller(
instance->cnt = decrypt & 0xFFFF;
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
// subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(3);
// subghz_custom_btn_set_max(3);
} else {
instance->btn = 0;
instance->serial = 0;
@@ -145,7 +145,7 @@ static void subghz_protocol_encoder_nice_flor_s_get_upload(
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(btn);
// subghz_custom_btn_set_original(btn);
}
btn = subghz_protocol_nice_flor_s_get_btn_code();
@@ -759,10 +759,10 @@ static void subghz_protocol_nice_flor_s_remote_controller(
}
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(4);
// if(subghz_custom_btn_get_original() == 0) {
// // subghz_custom_btn_set_original(instance->btn);
// }
// // subghz_custom_btn_set_max(4);
}
uint8_t subghz_protocol_decoder_nice_flor_s_get_hash_data(void* context) {
@@ -250,9 +250,9 @@ static bool
uint8_t btn = instance->generic.btn;
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(btn);
}
// if(subghz_custom_btn_get_original() == 0) {
// // // subghz_custom_btn_set_original(btn);
// }
// Get custom button code
// This will override the btn variable if a custom button is set
@@ -611,9 +611,9 @@ static void subghz_protocol_phoenix_v2_check_remote_controller(SubGhzBlockGeneri
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
// subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(4);
// subghz_custom_btn_set_max(4);
}
uint8_t subghz_protocol_decoder_phoenix_v2_get_hash_data(void* context) {
@@ -330,9 +330,9 @@ static void subghz_protocol_princeton_check_remote_controller(SubGhzBlockGeneric
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
// subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(4);
// subghz_custom_btn_set_max(4);
}
SubGhzProtocolStatus
@@ -170,9 +170,7 @@ static void subghz_protocol_encoder_roger_get_upload(SubGhzProtocolEncoderRoger*
uint8_t btn = instance->generic.btn;
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(btn);
}
// // // subghz_custom_btn_set_original(btn);
// Get custom button code
// This will override the btn variable if a custom button is set
@@ -251,9 +249,9 @@ static void subghz_protocol_roger_check_remote_controller(SubGhzBlockGeneric* in
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
// subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(3);
// subghz_custom_btn_set_max(3);
}
SubGhzProtocolStatus
@@ -342,10 +342,10 @@ static void
}
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(4);
// if(subghz_custom_btn_get_original() == 0) {
// subghz_custom_btn_set_original(instance->btn);
// }
// subghz_custom_btn_set_max(4);
}
/**
@@ -390,7 +390,7 @@ static uint8_t subghz_protocol_secplus_v2_get_btn_code(void);
static void subghz_protocol_secplus_v2_encode(SubGhzProtocolEncoderSecPlus_v2* instance) {
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->generic.btn);
// subghz_custom_btn_set_original(instance->generic.btn);
}
instance->generic.btn = subghz_protocol_secplus_v2_get_btn_code();
@@ -119,7 +119,7 @@ static bool subghz_protocol_somfy_telis_gen_data(
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(btn);
// subghz_custom_btn_set_original(btn);
}
btn = subghz_protocol_somfy_telis_get_btn_code();
@@ -627,9 +627,9 @@ static void subghz_protocol_somfy_telis_check_remote_controller(SubGhzBlockGener
// Save original button for later use
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(instance->btn);
// subghz_custom_btn_set_original(instance->btn);
}
subghz_custom_btn_set_max(3);
// subghz_custom_btn_set_max(3);
}
/**
@@ -5,7 +5,7 @@ App(
targets=["f7"],
entry_point="protopirate_app",
requires=["gui"],
stack_size=2 * 1024,
stack_size=8 * 1024,
fap_description="Decode car key fob signals from Sub-GHz",
fap_version="3.0",
fap_icon="images/protopirate_10px.png",
+37 -35
View File
@@ -6,11 +6,12 @@ App(
entry_point="rolljam_app",
requires=["gui"],
stack_size=10 * 1024,
order=10,
fap_description="RollJam Shield Receiver",
fap_version="2.0",
fap_category="Sub-GHz",
cdefines=["ENABLE_SHIELD_RX_SCENE=1", "ENABLE_EMULATE_FEATURE=1"],
fap_icon=None,
fap_icon="icon.png",
fap_file_assets="keystore",
sources=[
"rolljam_app.c",
@@ -26,14 +27,15 @@ App(
"scenes/rolljam_scene_need_saving.c",
"scenes/rolljam_scene_emulate.c",
"scenes/rolljam_scene_about.c",
// "scenes/plugins/rolljam_psa_bf_plugin.c",
# "scenes/plugins/rolljam_psa_bf_plugin.c",
"views/rolljam_receiver.c",
"helpers/rolljam_rx_chain.c",
"helpers/rolljam_tx_chain.c",
"helpers/rolljam_storage.c",
"helpers/rolljam_settings.c",
"helpers/rolljam_selected_capture.c",
"helpers/radio_device_loader.c",
"helpers/rolljam_psa_bf_host.c",
# "helpers/rolljam_psa_bf_host.c",
"protocols/protocol_items.c",
"protocols/protocols_common.c",
"protocols/keys.c",
@@ -71,22 +73,22 @@ App(
)
// App(
// appid="rolljam_psa_bf_plugin",
// apptype=FlipperAppType.PLUGIN,
// entry_point="rolljam_psa_bf_plugin_ep",
// requires=["rolljam_standalone"],
// cdefines=["ROLLJAM_PSA_BF_PLUGIN_BUILD=1"],
// sources=[
// "scenes/plugins/rolljam_psa_bf_plugin.c",
// "protocols/psa_crypto.c",
// "protocols/psa_crypto_bf.c",
// "protocols/psa_bf_core.c",
// "protocols/protocols_common.c",
// ],
// // fap_icon_assets="images",
// fal_embedded=True,
// )
# App(
# appid="rolljam_psa_bf_plugin",
# apptype=FlipperAppType.PLUGIN,
# entry_point="rolljam_psa_bf_plugin_ep",
# requires=["rolljam_standalone"],
# cdefines=["ROLLJAM_PSA_BF_PLUGIN_BUILD=1"],
# sources=[
# "scenes/plugins/rolljam_psa_bf_plugin.c",
# "protocols/psa_crypto.c",
# "protocols/psa_crypto_bf.c",
# "protocols/psa_bf_core.c",
# "protocols/protocols_common.c",
# ],
# # fap_icon_assets="images",
# fal_embedded=True,
# )
App(
appid="rolljam_emulate_plugin",
@@ -177,22 +179,22 @@ App(
fal_embedded=True,
)
// App(
// appid="rolljam_psa_bf_plugin",
// apptype=FlipperAppType.PLUGIN,
// entry_point="rolljam_psa_bf_plugin_ep",
// requires=["rolljam_standalone"],
// cdefines=["ROLLJAM_PSA_BF_PLUGIN_BUILD=1"],
// sources=[
// "scenes/plugins/rolljam_psa_bf_plugin.c",
// "protocols/psa_crypto.c",
// "protocols/psa_crypto_bf.c",
// "protocols/psa_bf_core.c",
// "protocols/protocols_common.c",
// ],
// // fap_icon_assets="images",
// fal_embedded=True,
// )
# App(
# appid="rolljam_psa_bf_plugin",
# apptype=FlipperAppType.PLUGIN,
# entry_point="rolljam_psa_bf_plugin_ep",
# requires=["rolljam_standalone"],
# cdefines=["ROLLJAM_PSA_BF_PLUGIN_BUILD=1"],
# sources=[
# "scenes/plugins/rolljam_psa_bf_plugin.c",
# "protocols/psa_crypto.c",
# "protocols/psa_crypto_bf.c",
# "protocols/psa_bf_core.c",
# "protocols/protocols_common.c",
# ],
# # fap_icon_assets="images",
# fal_embedded=True,
# )
App(
appid="rolljam_emulate_plugin",
@@ -0,0 +1,81 @@
#include "rolljam_selected_capture.h"
#include "../rolljam_app_i.h"
#include "rolljam_types.h"
#include "../rolljam_history.h"
void rolljam_selected_capture_set(RollJamApp* app, RollJamCaptureOwner owner, uint16_t index) {
furi_check(app);
app->selected_capture.owner = owner;
app->selected_capture.index = index;
if(owner == RollJamCaptureOwnerMainReceiver && app->txrx) {
app->selected_capture.history = app->txrx->history;
} else if(owner == RollJamCaptureOwnerDualReceiver) {
#ifdef ENABLE_DUAL_RX_SCENE
if(app->dual_history) {
app->selected_capture.history = app->dual_history;
}
#endif
} else if(owner == RollJamCaptureOwnerShieldReceiver) {
#ifdef ENABLE_SHIELD_RX_SCENE
if(app->shield_history) {
app->selected_capture.history = app->shield_history;
}
#endif
} else {
app->selected_capture.history = NULL;
}
}
void rolljam_selected_capture_clear(RollJamApp* app) {
furi_check(app);
app->selected_capture.owner = RollJamCaptureOwnerNone;
app->selected_capture.index = 0;
app->selected_capture.history = NULL;
}
bool rolljam_selected_capture_is_valid(RollJamApp* app) {
furi_check(app);
return (app->selected_capture.owner != RollJamCaptureOwnerNone && app->selected_capture.history != NULL);
}
uint16_t rolljam_selected_capture_get_index(RollJamApp* app) {
furi_check(app);
return app->selected_capture.index;
}
RollJamHistory* rolljam_selected_capture_get_history(RollJamApp* app) {
furi_check(app);
return app->selected_capture.history;
}
RollJamHistorySource rolljam_selected_capture_get_source(RollJamApp* app) {
furi_check(app);
if(!rolljam_selected_capture_is_valid(app)) {
return RollJamHistorySourceUnknown;
}
return rolljam_history_get_source(app->selected_capture.history, app->selected_capture.index);
}
bool rolljam_selected_capture_get_path(RollJamApp* app, FuriString* out_path) {
furi_check(app);
if(!rolljam_selected_capture_is_valid(app)) {
return false;
}
return rolljam_history_get_capture_path(app->selected_capture.history, app->selected_capture.index, out_path);
}
FlipperFormat* rolljam_selected_capture_get_raw_data(RollJamApp* app) {
furi_check(app);
if(!rolljam_selected_capture_is_valid(app)) {
return NULL;
}
return rolljam_history_get_raw_data(app->selected_capture.history, app->selected_capture.index);
}
void rolljam_selected_capture_release_scratch(RollJamApp* app) {
furi_check(app);
if(rolljam_selected_capture_is_valid(app)) {
rolljam_history_release_scratch(app->selected_capture.history);
}
}
@@ -0,0 +1,20 @@
#pragma once
#include <furi.h>
#include <lib/flipper_format/flipper_format.h>
#include "rolljam_types.h"
#include "../rolljam_history.h"
typedef struct RollJamApp RollJamApp;
typedef struct RollJamApp RollJamApp;
void rolljam_selected_capture_set(RollJamApp* app, RollJamCaptureOwner owner, uint16_t index);
void rolljam_selected_capture_clear(RollJamApp* app);
bool rolljam_selected_capture_is_valid(RollJamApp* app);
uint16_t rolljam_selected_capture_get_index(RollJamApp* app);
RollJamHistory* rolljam_selected_capture_get_history(RollJamApp* app);
RollJamHistorySource rolljam_selected_capture_get_source(RollJamApp* app);
bool rolljam_selected_capture_get_path(RollJamApp* app, FuriString* out_path);
FlipperFormat* rolljam_selected_capture_get_raw_data(RollJamApp* app);
void rolljam_selected_capture_release_scratch(RollJamApp* app);
@@ -5,6 +5,22 @@
#include <furi_hal.h>
#include "../defines.h"
typedef struct RollJamApp RollJamApp;
typedef struct RollJamHistory RollJamHistory;
typedef enum {
RollJamCaptureOwnerNone = 0,
RollJamCaptureOwnerDualReceiver,
RollJamCaptureOwnerShieldReceiver,
RollJamCaptureOwnerMainReceiver,
} RollJamCaptureOwner;
typedef struct {
uint16_t index;
RollJamHistory* history;
RollJamCaptureOwner owner;
} RollJamSelectedCapture;
typedef enum {
RollJamViewVariableItemList,
RollJamViewSubmenu,
@@ -1,6 +1,6 @@
#include "fiat_v0.h"
#include "protocols_common.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include <lib/toolbox/manchester_decoder.h>
#include <inttypes.h>
@@ -1,6 +1,6 @@
#include "ford_v0.h"
#include "protocols_common.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#define TAG "FordProtocolV0"
@@ -1,5 +1,5 @@
#include "ford_v1.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include "protocols_common.h"
#include <string.h>
@@ -1,5 +1,5 @@
#include "ford_v2.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include <furi.h>
#include <string.h>
@@ -1,5 +1,5 @@
#include "ford_v3.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include "protocols_common.h"
#include <string.h>
@@ -1,6 +1,6 @@
#include "honda_static.h"
#include "protocols_common.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#define HONDA_STATIC_BIT_COUNT 64
#define HONDA_STATIC_MIN_SYMBOLS 36
+1 -1
View File
@@ -10,7 +10,7 @@ uint64_t kia_v6_a_key = 0;
uint64_t kia_v6_b_key = 0;
uint64_t kia_v5_key = 0;
void protopirate_keys_load(SubGhzEnvironment* environment) {
void rolljam_keys_load(SubGhzEnvironment* environment) {
SubGhzKeystore* keystore = subghz_environment_get_keystore(environment);
// Load keys from secure keystore
for
+1 -1
View File
@@ -18,4 +18,4 @@ uint64_t get_kia_v6_keystore_b();
uint64_t get_kia_v5_key();
void protopirate_keys_load(SubGhzEnvironment* environment);
void rolljam_keys_load(SubGhzEnvironment* environment);
@@ -1,6 +1,6 @@
#include "kia_v0.h"
#include "protocols_common.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include <string.h>
@@ -1,6 +1,6 @@
#include "kia_v1.h"
#include "protocols_common.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include <lib/toolbox/manchester_decoder.h>
#define TAG "KiaV1"
@@ -1,5 +1,5 @@
#include "kia_v2.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include <lib/toolbox/manchester_encoder.h>
#include <furi.h>
@@ -1,5 +1,5 @@
#include "kia_v3_v4.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include "keeloq_common.h"
#include "keys.h"
#include "protocols_common.h"
@@ -211,7 +211,7 @@ void* kia_protocol_encoder_v3_v4_alloc(SubGhzEnvironment* environment) {
furi_check(instance);
if(environment) {
protopirate_keys_load(environment);
rolljam_keys_load(environment);
}
instance->base.protocol = &kia_protocol_v3_v4;
@@ -601,7 +601,7 @@ void* kia_protocol_decoder_v3_v4_alloc(SubGhzEnvironment* environment) {
furi_check(instance);
if(environment) {
protopirate_keys_load(environment);
rolljam_keys_load(environment);
}
instance->base.protocol = &kia_protocol_v3_v4;
@@ -1,5 +1,5 @@
#include "kia_v5.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include "protocols_common.h"
#include "keys.h"
@@ -247,7 +247,7 @@ void* kia_protocol_encoder_v5_alloc(SubGhzEnvironment* environment) {
furi_check(instance);
if(environment) {
protopirate_keys_load(environment);
rolljam_keys_load(environment);
}
instance->base.protocol = &kia_protocol_v5;
@@ -432,7 +432,7 @@ void* kia_protocol_decoder_v5_alloc(SubGhzEnvironment* environment) {
furi_check(instance);
if(environment) {
protopirate_keys_load(environment);
rolljam_keys_load(environment);
}
instance->base.protocol = &kia_protocol_v5;
@@ -1,5 +1,5 @@
#include "kia_v6.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include "protocols_common.h"
#include "keys.h"
#include <furi.h>
@@ -464,7 +464,7 @@ void* kia_protocol_decoder_v6_alloc(SubGhzEnvironment* environment) {
memset(instance, 0, sizeof(SubGhzProtocolDecoderKiaV6));
if(environment) {
protopirate_keys_load(environment);
rolljam_keys_load(environment);
}
instance->base.protocol = &kia_protocol_v6;
@@ -933,7 +933,7 @@ void* kia_protocol_encoder_v6_alloc(SubGhzEnvironment* environment) {
memset(instance, 0, sizeof(SubGhzProtocolEncoderKiaV6));
if(environment) {
protopirate_keys_load(environment);
rolljam_keys_load(environment);
}
instance->base.protocol = &kia_protocol_v6;
@@ -4,17 +4,17 @@
#include <string.h>
#endif
#define TAG "ProtoPirateRegistry"
#define TAG "RollJamRegistry"
#define PROTOPIRATE_CC1101_REG_MDMCFG2 0x12U
#define PROTOPIRATE_CC1101_MOD_FORMAT_MASK 0x70U
#define PROTOPIRATE_CC1101_MOD_FORMAT_2FSK 0x00U
#define PROTOPIRATE_CC1101_MOD_FORMAT_GFSK 0x10U
#define PROTOPIRATE_CC1101_MOD_FORMAT_ASK_OOK 0x30U
#define PROTOPIRATE_CC1101_MOD_FORMAT_4FSK 0x40U
#define PROTOPIRATE_CC1101_MOD_FORMAT_MSK 0x70U
#define rolljam_CC1101_REG_MDMCFG2 0x12U
#define rolljam_CC1101_MOD_FORMAT_MASK 0x70U
#define rolljam_CC1101_MOD_FORMAT_2FSK 0x00U
#define rolljam_CC1101_MOD_FORMAT_GFSK 0x10U
#define rolljam_CC1101_MOD_FORMAT_ASK_OOK 0x30U
#define rolljam_CC1101_MOD_FORMAT_4FSK 0x40U
#define rolljam_CC1101_MOD_FORMAT_MSK 0x70U
static bool protopirate_preset_try_get_register(
static bool rolljam_preset_try_get_register(
const uint8_t* preset_data,
size_t preset_data_size,
uint8_t reg,
@@ -40,41 +40,41 @@ static bool protopirate_preset_try_get_register(
return false;
}
ProtoPirateProtocolRegistryFilter protopirate_get_protocol_registry_filter_for_preset(
RollJamProtocolRegistryFilter rolljam_get_protocol_registry_filter_for_preset(
const uint8_t* preset_data,
size_t preset_data_size) {
uint8_t mdmcfg2 = 0U;
if(!protopirate_preset_try_get_register(
preset_data, preset_data_size, PROTOPIRATE_CC1101_REG_MDMCFG2, &mdmcfg2)) {
if(!rolljam_preset_try_get_register(
preset_data, preset_data_size, rolljam_CC1101_REG_MDMCFG2, &mdmcfg2)) {
FURI_LOG_W(TAG, "Preset missing MDMCFG2, defaulting to AM registry");
return ProtoPirateProtocolRegistryFilterAM;
return RollJamProtocolRegistryFilterAM;
}
// MDMCFG2[6:4] stores the CC1101 modulation format.
// ASK/OOK maps to our AM decoder set; the FSK-family formats map to FM.
switch(mdmcfg2 & PROTOPIRATE_CC1101_MOD_FORMAT_MASK) {
case PROTOPIRATE_CC1101_MOD_FORMAT_ASK_OOK:
return ProtoPirateProtocolRegistryFilterAM;
case PROTOPIRATE_CC1101_MOD_FORMAT_2FSK:
case PROTOPIRATE_CC1101_MOD_FORMAT_GFSK:
case PROTOPIRATE_CC1101_MOD_FORMAT_4FSK:
case PROTOPIRATE_CC1101_MOD_FORMAT_MSK:
return ProtoPirateProtocolRegistryFilterFM;
switch(mdmcfg2 & rolljam_CC1101_MOD_FORMAT_MASK) {
case rolljam_CC1101_MOD_FORMAT_ASK_OOK:
return RollJamProtocolRegistryFilterAM;
case rolljam_CC1101_MOD_FORMAT_2FSK:
case rolljam_CC1101_MOD_FORMAT_GFSK:
case rolljam_CC1101_MOD_FORMAT_4FSK:
case rolljam_CC1101_MOD_FORMAT_MSK:
return RollJamProtocolRegistryFilterFM;
default:
FURI_LOG_W(TAG, "Unknown MDMCFG2 0x%02X, defaulting to AM registry", mdmcfg2);
return ProtoPirateProtocolRegistryFilterAM;
return RollJamProtocolRegistryFilterAM;
}
}
const char*
protopirate_get_protocol_registry_filter_name(ProtoPirateProtocolRegistryFilter filter) {
return (filter == ProtoPirateProtocolRegistryFilterFM) ? "FM" : "AM";
rolljam_get_protocol_registry_filter_name(RollJamProtocolRegistryFilter filter) {
return (filter == RollJamProtocolRegistryFilterFM) ? "FM" : "AM";
}
#ifdef ENABLE_TIMING_TUNER_SCENE
// Protocol timing definitions - mirrors the SubGhzBlockConst in each protocol
static const ProtoPirateProtocolTiming protocol_timings[] = {
static const RollJamProtocolTiming protocol_timings[] = {
// Honda Static
{
.name = HONDA_STATIC_PROTOCOL_NAME,
@@ -271,7 +271,7 @@ static const ProtoPirateProtocolTiming protocol_timings[] = {
static const size_t protocol_timings_count = COUNT_OF(protocol_timings);
const ProtoPirateProtocolTiming* protopirate_get_protocol_timing(const char* protocol_name) {
const RollJamProtocolTiming* rolljam_get_protocol_timing(const char* protocol_name) {
if(!protocol_name) return NULL;
for(size_t i = 0; i < protocol_timings_count; i++) {
@@ -303,12 +303,12 @@ const ProtoPirateProtocolTiming* protopirate_get_protocol_timing(const char* pro
return NULL;
}
const ProtoPirateProtocolTiming* protopirate_get_protocol_timing_by_index(size_t index) {
const RollJamProtocolTiming* rolljam_get_protocol_timing_by_index(size_t index) {
if(index >= protocol_timings_count) return NULL;
return &protocol_timings[index];
}
size_t protopirate_get_protocol_timing_count(void) {
size_t rolljam_get_protocol_timing_count(void) {
return protocol_timings_count;
}
#endif
@@ -30,16 +30,16 @@
#include "honda_v1.h"
typedef enum {
ProtoPirateProtocolRegistryFilterAM = 0,
ProtoPirateProtocolRegistryFilterFM,
} ProtoPirateProtocolRegistryFilter;
RollJamProtocolRegistryFilterAM = 0,
RollJamProtocolRegistryFilterFM,
} RollJamProtocolRegistryFilter;
ProtoPirateProtocolRegistryFilter protopirate_get_protocol_registry_filter_for_preset(
RollJamProtocolRegistryFilter rolljam_get_protocol_registry_filter_for_preset(
const uint8_t* preset_data,
size_t preset_data_size);
const char*
protopirate_get_protocol_registry_filter_name(ProtoPirateProtocolRegistryFilter filter);
rolljam_get_protocol_registry_filter_name(RollJamProtocolRegistryFilter filter);
#ifdef ENABLE_TIMING_TUNER_SCENE
// Timing information for protocol analysis
@@ -49,14 +49,14 @@ typedef struct {
uint32_t te_long;
uint32_t te_delta;
uint32_t min_count_bit;
} ProtoPirateProtocolTiming;
} RollJamProtocolTiming;
// Get timing info for a protocol by name (returns NULL if not found)
const ProtoPirateProtocolTiming* protopirate_get_protocol_timing(const char* protocol_name);
const RollJamProtocolTiming* rolljam_get_protocol_timing(const char* protocol_name);
// Get timing info by index (for iteration)
const ProtoPirateProtocolTiming* protopirate_get_protocol_timing_by_index(size_t index);
const RollJamProtocolTiming* rolljam_get_protocol_timing_by_index(size_t index);
// Get number of protocols with timing info
size_t protopirate_get_protocol_timing_count(void);
size_t rolljam_get_protocol_timing_count(void);
#endif
@@ -249,7 +249,7 @@ size_t
void pp_encoder_free(void* context) {
furi_check(context);
ProtoPirateEncoderHeader* hdr = context;
RollJamEncoderHeader* hdr = context;
hdr->encoder.upload = NULL;
hdr->encoder.size_upload = 0;
free(hdr);
@@ -257,14 +257,14 @@ void pp_encoder_free(void* context) {
void pp_encoder_stop(void* context) {
furi_check(context);
ProtoPirateEncoderHeader* hdr = context;
RollJamEncoderHeader* hdr = context;
hdr->encoder.is_running = false;
hdr->encoder.front = 0;
}
LevelDuration pp_encoder_yield(void* context) {
furi_check(context);
ProtoPirateEncoderHeader* hdr = context;
RollJamEncoderHeader* hdr = context;
if(hdr->encoder.repeat == 0 || !hdr->encoder.is_running || hdr->encoder.size_upload == 0) {
hdr->encoder.is_running = false;
return level_duration_reset();
@@ -298,7 +298,7 @@ void pp_shared_upload_release(void) {
void pp_encoder_buffer_ensure(void* context, size_t capacity) {
furi_check(context);
ProtoPirateEncoderHeader* hdr = context;
RollJamEncoderHeader* hdr = context;
furi_check(capacity <= PP_SHARED_UPLOAD_CAPACITY);
hdr->encoder.upload = pp_shared_upload_buffer();
hdr->encoder.size_upload = capacity;
@@ -306,7 +306,7 @@ void pp_encoder_buffer_ensure(void* context, size_t capacity) {
uint8_t pp_decoder_hash_blocks(void* context) {
furi_check(context);
ProtoPirateDecoderHeader* hdr = context;
RollJamDecoderHeader* hdr = context;
return subghz_protocol_blocks_get_hash_data(
&hdr->decoder, (hdr->decoder.decode_count_bit / 8U) + 1U);
}
@@ -112,7 +112,7 @@ typedef struct {
SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder;
SubGhzBlockGeneric generic;
} ProtoPirateDecoderHeader;
} RollJamDecoderHeader;
uint8_t pp_decoder_hash_blocks(void* context);
@@ -121,7 +121,7 @@ void pp_decoder_free_default(void* context);
typedef struct {
SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder;
} ProtoPirateEncoderHeader;
} RollJamEncoderHeader;
void pp_encoder_free(void* context);
void pp_encoder_stop(void* context);
@@ -1,14 +0,0 @@
#pragma once
#include <lib/flipper_application/flipper_application.h>
#include <lib/subghz/types.h>
#include "protocol_items.h"
#define PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID "protopirate_protocol_plugins"
#define PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION 1U
typedef struct {
const char* plugin_name;
ProtoPirateProtocolRegistryFilter filter;
const SubGhzProtocolRegistry* registry;
} ProtoPirateProtocolPlugin;
@@ -1,5 +1,5 @@
#include "scher_khan.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include "protocols_common.h"
@@ -1,5 +1,5 @@
#include "star_line.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include "keeloq_common.h"
#include <lib/subghz/subghz_keystore.h>
@@ -1,5 +1,5 @@
#include "subaru.h"
#include "../protopirate_app_i.h"
#include "../rolljam_app_i.h"
#include "protocols_common.h"
#define TAG "SubaruProtocol"
+4 -4
View File
@@ -216,7 +216,7 @@ static void rolljam_radio_init_cleanup(RollJamApp* app, bool devices_initialized
}
if(app->txrx->protocol_plugin_manager) {
rolljam_unload_protocol_plugins(app->txrx);
rolljam_unload_protocol_plugin(app->txrx);
}
if(app->txrx->plugin_resolver) {
@@ -577,7 +577,7 @@ void rolljam_radio_deinit(RollJamApp* app) {
}
if(app->txrx->protocol_plugin_manager) {
rolljam_unload_protocol_plugins(app->txrx);
rolljam_unload_protocol_plugin(app->txrx);
}
@@ -799,10 +799,10 @@ void rolljam_app_free(RollJamApp* app) {
}
#endif
rolljam_psa_bf_context_release(app);
// rolljam_psa_bf_context_release(app);
#ifdef ENABLE_SHIELD_RX_SCENE
rolljam_scene_shield_receiver_cleanup_rolljam_tx();
// rolljam_scene_shield_receiver_cleanup_rolljam_tx();
#endif
// Setting
+1 -189
View File
@@ -12,7 +12,7 @@ static const char* rolljam_get_registry_plugin_path(RollJamProtocolRegistryFilte
APP_ASSETS_PATH("plugins/rolljam_am_plugin.fal");
}
static void rolljam_unload_protocol_plugin(RollJamTxRx* txrx) {
void rolljam_unload_protocol_plugin(RollJamTxRx* txrx) {
furi_check(txrx);
txrx->protocol_plugin = NULL;
@@ -57,29 +57,6 @@ static void rolljam_teardown_receiver_stack_for_registry_switch(RollJamApp* app)
}
}
static const char* rolljam_get_registry_plugin_path(RollJamProtocolRegistryFilter filter) {
return (filter == RollJamProtocolRegistryFilterFM) ?
APP_ASSETS_PATH("plugins/rolljam_fm_plugin.fal") :
APP_ASSETS_PATH("plugins/rolljam_am_plugin.fal");
}
static void rolljam_unload_protocol_plugin(RollJamTxRx* txrx) {
furi_check(txrx);
txrx->protocol_plugin = NULL;
txrx->protocol_registry = NULL;
if(txrx->protocol_plugin_manager) {
plugin_manager_free(txrx->protocol_plugin_manager);
txrx->protocol_plugin_manager = NULL;
}
if(txrx->plugin_resolver) {
composite_api_resolver_free(txrx->plugin_resolver);
txrx->plugin_resolver = NULL;
}
}
static bool rolljam_ensure_protocol_registry_plugin(
RollJamApp* app,
RollJamProtocolRegistryFilter filter,
@@ -216,171 +193,6 @@ bool rolljam_refresh_protocol_registry(RollJamApp* app, bool ensure_receiver_rea
return true;
}
bool rolljam_apply_protocol_registry_for_preset_data(
RollJamApp* app,
const uint8_t* preset_data,
size_t preset_data_size) {
furi_check(app);
furi_check(app->txrx);
if(!app->txrx->environment) {
return false;
}
RollJamProtocolRegistryFilter filter =
rolljam_get_protocol_registry_filter_for_preset(preset_data, preset_data_size);
bool filter_changed = !app->txrx->protocol_plugin ||
(app->txrx->protocol_registry_filter != filter);
if(filter_changed) {
rolljam_teardown_receiver_stack_for_registry_switch(app);
}
const SubGhzProtocolRegistry* registry = NULL;
if(!rolljam_ensure_protocol_registry_plugin(app, filter, &registry) || !registry) {
FURI_LOG_E(
TAG,
"Failed to resolve %s registry plugin for preset apply",
rolljam_get_protocol_registry_filter_name(filter));
return false;
}
if(app->txrx->protocol_registry == registry) {
return true;
}
FURI_LOG_I(
TAG,
"Switching active protocol registry to %s (%zu protocols)",
rolljam_get_protocol_registry_filter_name(filter),
registry->size);
subghz_environment_set_protocol_registry(app->txrx->environment, registry);
app->txrx->protocol_registry = registry;
return true;
}
if(app->txrx->protocol_plugin && app->txrx->protocol_plugin->registry &&
app->txrx->protocol_registry_filter == filter) {
*registry = app->txrx->protocol_plugin->registry;
return true;
}
if(app->txrx->protocol_plugin || app->txrx->protocol_plugin_manager ||
app->txrx->plugin_resolver) {
rolljam_unload_protocol_plugin(app->txrx);
}
CompositeApiResolver* resolver = composite_api_resolver_alloc();
if(!resolver) {
FURI_LOG_E(TAG, "Failed to allocate protocol plugin resolver");
return false;
}
composite_api_resolver_add(resolver, firmware_api_interface);
PluginManager* manager = plugin_manager_alloc(
PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID,
PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION,
composite_api_resolver_get(resolver));
if(!manager) {
FURI_LOG_E(TAG, "Failed to allocate protocol plugin manager");
composite_api_resolver_free(resolver);
return false;
}
const char* plugin_path = rolljam_get_registry_plugin_path(filter);
PluginManagerError error = plugin_manager_load_single(manager, plugin_path);
if(error != PluginManagerErrorNone) {
FURI_LOG_E(TAG, "Failed to load protocol plugin %s: %d", plugin_path, (int)error);
plugin_manager_free(manager);
composite_api_resolver_free(resolver);
return false;
}
const RollJamProtocolPlugin* plugin = plugin_manager_get_ep(manager, 0U);
if(!plugin || !plugin->registry) {
FURI_LOG_E(TAG, "Protocol plugin entry point is invalid");
plugin_manager_free(manager);
composite_api_resolver_free(resolver);
return false;
}
if(plugin->filter != filter) {
FURI_LOG_E(
TAG, "Protocol plugin filter mismatch (expected %d got %d)", filter, plugin->filter);
plugin_manager_free(manager);
composite_api_resolver_free(resolver);
return false;
}
app->txrx->plugin_resolver = resolver;
app->txrx->protocol_plugin_manager = manager;
app->txrx->protocol_plugin = plugin;
app->txrx->protocol_registry_filter = filter;
*registry = plugin->registry;
return true;
}
bool rolljam_refresh_protocol_registry(RollJamApp* app, bool ensure_receiver_ready) {
furi_check(app);
furi_check(app->txrx);
if(!app->txrx->environment || !app->txrx->preset) {
return true;
}
RollJamProtocolRegistryFilter filter = rolljam_get_protocol_registry_filter_for_preset(
app->txrx->preset->data, app->txrx->preset->data_size);
bool filter_changed = !app->txrx->protocol_plugin ||
(app->txrx->protocol_registry_filter != filter);
if(filter_changed) {
rolljam_teardown_receiver_stack_for_registry_switch(app);
} else if(ensure_receiver_ready && !app->txrx->receiver) {
rolljam_teardown_receiver_stack_for_registry_switch(app);
}
const SubGhzProtocolRegistry* registry = NULL;
if(!rolljam_ensure_protocol_registry_plugin(app, filter, &registry) || !registry) {
FURI_LOG_E(
TAG,
"Failed to resolve %s protocol registry plugin",
rolljam_get_protocol_registry_filter_name(filter));
return false;
}
const bool registry_already_bound = (app->txrx->protocol_registry == registry);
if(!registry_already_bound) {
FURI_LOG_I(
TAG,
"Using %s protocol registry (%zu protocols)",
rolljam_get_protocol_registry_filter_name(filter),
registry->size);
subghz_environment_set_protocol_registry(app->txrx->environment, registry);
app->txrx->protocol_registry = registry;
}
if(!ensure_receiver_ready) {
return true;
}
if(app->txrx->receiver) {
return true;
}
app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment);
if(!app->txrx->receiver) {
FURI_LOG_E(
TAG,
"Failed to allocate receiver for %s registry",
rolljam_get_protocol_registry_filter_name(filter));
return false;
}
subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable);
return true;
}
bool rolljam_apply_protocol_registry_for_preset_data(
RollJamApp* app,
const uint8_t* preset_data,
+8 -1
View File
@@ -7,6 +7,9 @@
#include "scenes/rolljam_scene.h"
#include "views/rolljam_receiver.h"
#include "rolljam_history.h"
#include "helpers/rolljam_selected_capture.h"
#include "helpers/rolljam_rx_chain.h"
#include "helpers/rolljam_tx_chain.h"
#include "helpers/radio_device_loader.h"
#include <gui/gui.h>
@@ -35,7 +38,7 @@
#endif
#include "scenes/plugins/rolljam_psa_bf_plugin.h"
#define PROTOPIRATE_KEYSTORE_DIR_NAME APP_ASSETS_PATH("encrypted")
#define ROLLJAM_KEYSTORE_DIR_NAME APP_ASSETS_PATH("encrypted")
typedef struct RollJamApp RollJamApp;
@@ -88,6 +91,8 @@ struct RollJamApp {
bool emulate_disabled_for_loaded;
bool emulate_feature_enabled;
RollJamSelectedCapture selected_capture;
RollJamCaptureOwner unsaved_history_owner;
bool shield_auto_save_failed;
#ifdef ENABLE_EMULATE_FEATURE
#define EMULATE_NAV_NONE 0U
#define EMULATE_NAV_POP 1U
@@ -181,6 +186,8 @@ void rolljam_rx_stack_resume_after_tx(RollJamApp* app);
void rolljam_app_free(RollJamApp* app);
void rolljam_unload_protocol_plugin(RollJamTxRx* txrx);
static const NotificationSequence sequence_tx = {
&message_note_c5,
&message_vibro_on,
@@ -1205,8 +1205,8 @@ static const RollJamEmulatePlugin rolljam_emulate_plugin = {
};
static const FlipperAppPluginDescriptor rolljam_emulate_plugin_descriptor = {
.appid = PROTOPIRATE_EMULATE_PLUGIN_APP_ID,
.ep_api_version = PROTOPIRATE_EMULATE_PLUGIN_API_VERSION,
.appid = ROLLJAM_EMULATE_PLUGIN_APP_ID,
.ep_api_version = ROLLJAM_EMULATE_PLUGIN_API_VERSION,
.entry_point = &rolljam_emulate_plugin,
};
@@ -6,8 +6,8 @@
#include <lib/flipper_application/flipper_application.h>
#include <gui/scene_manager.h>
#define PROTOPIRATE_EMULATE_PLUGIN_APP_ID "rolljam_emulate_plugin"
#define PROTOPIRATE_EMULATE_PLUGIN_API_VERSION 1U
#define ROLLJAM_EMULATE_PLUGIN_APP_ID "rolljam_emulate_plugin"
#define ROLLJAM_EMULATE_PLUGIN_API_VERSION 1U
typedef struct {
bool (*radio_init)(void* app);
@@ -114,8 +114,8 @@ static bool emulate_plugin_load(RollJamApp* app) {
composite_api_resolver_add(resolver, firmware_api_interface);
PluginManager* manager = plugin_manager_alloc(
PROTOPIRATE_EMULATE_PLUGIN_APP_ID,
PROTOPIRATE_EMULATE_PLUGIN_API_VERSION,
ROLLJAM_EMULATE_PLUGIN_APP_ID,
ROLLJAM_EMULATE_PLUGIN_API_VERSION,
composite_api_resolver_get(resolver));
if(!manager) {
FURI_LOG_E(TAG, "Failed to allocate emulate plugin manager");
@@ -167,18 +167,12 @@ static void rolljam_scene_receiver_info_widget_callback(
view_dispatcher_send_custom_event(
app->view_dispatcher, RollJamCustomEventReceiverInfoSave);
} else if(result == GuiButtonTypeLeft) {
// if(rolljam_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin &&
// app->psa_bf_plugin->widget_left_should_bruteforce(
// app, RollJamPsaBfContextReceiverInfo)) {
// view_dispatcher_send_custom_event(
// app->view_dispatcher, RollJamCustomEventReceiverInfoBruteforceStart);
// }
#ifdef ENABLE_EMULATE_FEATURE
else if(app->emulate_feature_enabled && !app->emulate_disabled_for_loaded) {
#ifdef ENABLE_EMULATE_FEATURE
if(app->emulate_feature_enabled && !app->emulate_disabled_for_loaded) {
view_dispatcher_send_custom_event(
app->view_dispatcher, RollJamCustomEventReceiverInfoEmulate);
}
#endif
#endif
} else if(result == GuiButtonTypeCenter) {
view_dispatcher_send_custom_event(
app->view_dispatcher, RollJamCustomEventReceiverInfoBruteforceCancel);
@@ -202,10 +196,8 @@ void rolljam_scene_receiver_info_on_enter(void* context) {
app->txrx->idx_menu_chosen < rolljam_history_get_item(app->txrx->history)) {
rolljam_selected_capture_set(
app,
app->txrx->history,
NULL,
app->txrx->idx_menu_chosen,
RollJamCaptureOwnerReceiver);
RollJamCaptureOwnerMainReceiver,
app->txrx->idx_menu_chosen);
}
// if(rolljam_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
@@ -620,10 +620,8 @@ bool rolljam_scene_shield_receiver_on_event(void* context, SceneManagerEvent eve
if(valid) {
rolljam_selected_capture_set(
app,
app->shield_history,
app->shield_history_mutex,
idx,
RollJamCaptureOwnerShieldReceiver);
RollJamCaptureOwnerShieldReceiver,
idx);
scene_manager_set_scene_state(
app->scene_manager,
RollJamSceneShieldReceiver,
@@ -0,0 +1,14 @@
App(
appid="ble_killer",
name="[BLE] BLE Killer",
apptype=FlipperAppType.EXTERNAL,
entry_point="main_entry",
stack_size=4 * 1024,
requires=[
"gui",
],
order=1,
fap_category="Bluetooth",
fap_icon="icon.png",
)
+984
View File
@@ -0,0 +1,984 @@
#include <furi.h>
#include <furi_hal.h>
#include <furi_hal_bt.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/submenu.h>
#include <gui/modules/text_input.h>
#include <gui/modules/widget.h>
#include <gui/elements.h>
#include <gui/gui.h>
#include <gui/view.h>
#include <gui/modules/variable_item_list.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <gui/scene_manager.h>
#include <gui/modules/text_box.h>
#include "uart.h"
typedef enum {
subMenuSetup,
subMenuScan,
subMenuWeapon,
subMenuConsole,
subMenuAbout
}subMenu;
typedef enum {
subMenuViewMain,
subMenuViewScan,
subMenuViewWeapon,
subMenuViewConsole,
subMenuViewAbout,
subMenuViewSetup
} ViewList;
typedef enum {
Weapon_OKLOK_UNLOCK,
Weapon_Aerlang,
Weapon_COUNT
} Weapon_List;
typedef struct {
ViewDispatcher* view_dispatcher;
Submenu* submenu;
void *view_list[6];
NotificationApp* notification;
VariableItemList* variable_item_list;
uart_app *uapp;
}bleScanCtx;
typedef struct {
signed int state_index;
bool is_start;
} SkeletonWeaponModel;
typedef struct {
bleScanCtx *widget;
FuriString *s;
} SkeletonScanModel;
NotificationMessage blink_message = {
.type = NotificationMessageTypeLedBlinkStart,
.data.led_blink.color = LightBlue | LightGreen,
.data.led_blink.on_time = 10,
.data.led_blink.period = 100,
};
const NotificationSequence blink_sequence = {
&blink_message,
&message_do_not_reset,
NULL,
};
typedef enum {
WorkerEvtStop = (1 << 0),
WorkerEvtRxDone = (1 << 1),
} WorkerEvtFlags;
#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
#define UART_CH 0
#define UART_TERMINAL_TEXT_BOX_STORE_SIZE 4096
#define TAG "ble_killer"
#define MAX_DEVICE_SCAN 5
bool scanEndFlag = false;
char *device[MAX_DEVICE_SCAN];
static void start_blink(bleScanCtx* ctx) {
// uint16_t period = delays[state->delay];
// if(period <= 100) period += 30;
blink_message.data.led_blink.period = 30;
notification_message(ctx->notification, &blink_sequence);
}
static void stop_blink(bleScanCtx* ctx) {
notification_message(ctx->notification, &sequence_blink_stop);
}
char* flipbip_strtok_r(char* s, const char* delim, char** last) {
char* spanp;
int c, sc;
char* tok;
if(s == NULL && (s = *last) == NULL) return (NULL);
/*
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
*/
cont:
c = *s++;
for(spanp = (char*)delim; (sc = *spanp++) != 0;) {
if(c == sc) goto cont;
}
if(c == 0) { /* no non-delimiter characters */
*last = NULL;
return (NULL);
}
tok = s - 1;
/*
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
* Note that delim must have one NUL; we stop if we see that, too.
*/
for(;;) {
c = *s++;
spanp = (char*)delim;
do {
if((sc = *spanp++) == c) {
if(c == 0)
s = NULL;
else
s[-1] = 0;
*last = s;
return (tok);
}
} while(sc != 0);
}
/* NOTREACHED */
}
char* flipbip_strtok(char* s, const char* delim) {
static char* last;
return flipbip_strtok_r(s, delim, &last);
}
static void scan_console_recv(void *ctx){
uart_app *uapp = ((bleScanCtx *)ctx)->uapp;
if(scanEndFlag == true){
// furi_timer_free(uapp->scan_timer);
return;
}
TextBox *text_box = uapp->text_box;
uart_terminal_uart_set_handle_rx_data_cb(
((uart_app *)uapp), uart_terminal_console_output_handle_rx_data_cb); // setup callback for rx thread
text_box_set_text(text_box, furi_string_get_cstr(((uart_app *)uapp)->text_box_store));
char recv_buf[512];
// // memset(recv_buf, '\0', sizeof(recv_buf));
memcpy(recv_buf, furi_string_get_cstr(((uart_app *)uapp)->text_box_store), sizeof(recv_buf));
if(strstr(furi_string_get_cstr(((uart_app *)uapp)->text_box_store), ";")){
scanEndFlag = true;
char *token = flipbip_strtok(recv_buf, ",");
// UNUSED(token);
int i = 0;
while (token != NULL && i < MAX_DEVICE_SCAN) {
device[i] = (char *)malloc(64);
if(device[i]!=NULL){
memcpy(device[i], token, strlen(token));
}
i++;
token = flipbip_strtok(NULL, ",");
}
// furi_string_printf(uapp->text_box_store, "recv buf:%s,;", uapp->rx_buf);
// TextBox* text_box = uapp->text_box;
// text_box_set_text(text_box, furi_string_get_cstr(uapp->text_box_store));
stop_blink((bleScanCtx *)ctx);
view_dispatcher_switch_to_view(((bleScanCtx *)ctx)->view_dispatcher, subMenuViewScan);
}
// furi_string_printf(uapp->text_box_store, "recv buf:%s,;", uapp->rx_buf);
// TextBox* text_box = uapp->text_box;
// text_box_set_text(text_box, furi_string_get_cstr(uapp->text_box_store));
}
void uart_send_cmd(uart_app *uart, uint8_t* data, size_t len) {
// furi_hal_uart_tx(uart_ch, data, len);
furi_hal_serial_tx(uart->serial_handle, data, len);
}
void skeleton_submenu_callback(void* context, uint32_t index){
bleScanCtx *ctx = (bleScanCtx *)context;
if(index == subMenuScan){
view_dispatcher_switch_to_view(ctx->view_dispatcher, subMenuViewScan);
}else if(index == subMenuWeapon){
view_dispatcher_switch_to_view(ctx->view_dispatcher, subMenuViewWeapon);
}else if(index == subMenuConsole){
view_dispatcher_switch_to_view(ctx->view_dispatcher, subMenuViewConsole);
}else if(index == subMenuAbout){
view_dispatcher_switch_to_view(ctx->view_dispatcher, subMenuViewAbout);
}else if(index == subMenuSetup){
view_dispatcher_switch_to_view(ctx->view_dispatcher, subMenuViewSetup);
}
}
static void view_scan_draw_callback(Canvas* canvas, void* context) {
// SkeletonScanModel *model = (SkeletonScanModel *)context;
UNUSED(context);
if(!scanEndFlag){
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 15, 30, "Press 'OK' to scan.");
// start_blink(_ctx);
// notification_message(_ctx->notification, &sequence_notification);
}else{
// char buf[20] = "Aerlang";
// FuriString* xstr = furi_string_alloc();
// furi_string_printf(xstr, "result: %s\n", buf);
canvas_set_font(canvas, FontPrimary);
// canvas_draw_str(canvas, 20, 15, "Result:");
canvas_draw_str_aligned(canvas, 10, 12, AlignLeft, AlignBottom, "Result:");
FuriString* xstr = furi_string_alloc();
int i;
for(i = 0;i < MAX_DEVICE_SCAN;i++){
if(device[i] != NULL){
furi_string_printf(xstr, "%s", device[i]);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 5, 10+i*10, furi_string_get_cstr(xstr));
}
}
// furi_string_printf(xstr, "%s", "notification_message(_ctx->notification, &sequence_blink_stop);\ncanvas_draw_str(canvas, 5, 10+i*10, furi_string_get_cstr(xstr));");
// elements_scrollable_text_line(
// canvas,
// 40,
// 50,
// 128,
// xstr,
// 0,
// true
// );
// canvas_draw_str(canvas, 50, 50, furi_string_get_cstr(model->s));
// widget_add_string_element(model->widget->view_list[subMenuViewAbout],10,20, AlignLeft, AlignTop, FontPrimary,furi_string_get_cstr(model->s));
// widget_add_string_multiline_element(model->widget->view_list[subMenuViewAbout],10,20, AlignLeft, AlignTop, FontPrimary,furi_string_get_cstr(model->s));
// Bus Fault
// widget_add_text_scroll_element(
// model->widget->view_list[subMenuViewScan],
// 0,
// 0,
// 128,
// 64,
// "This is a bluetooth ble scanner and controller tool.\n---\nScan any low energy ble device around."
// );
furi_string_free(xstr);
}
// elements_button_center(canvas, scanEndFlag ? "Stop":"Start");
}
static void view_weapon_draw_callback(Canvas* canvas, void* context) {
// UNUSED(context);
// FURI_LOG_I(TAG, "view_weapon_draw_callback context null.");
SkeletonWeaponModel* model = (SkeletonWeaponModel*)context;
if(model == NULL){
FURI_LOG_I(TAG, "view_weapon_draw_callback context null.");
return;
}
FURI_LOG_I(TAG, "View index: %d", model->state_index);
switch(model->state_index){
case Weapon_OKLOK_UNLOCK:
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 124, 12, AlignRight, AlignBottom, "OKLOK unlock");
elements_text_box(
canvas,
4,
30,
80,
48,
AlignLeft,
AlignTop,
"Press \e#OK\e# button\n"
"To \e#attack\e#",
false);
elements_button_center(canvas, model->is_start ? "Stop":"Start");
elements_button_right(canvas, "Next");
break;
case Weapon_Aerlang:
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 124, 12, AlignRight, AlignBottom, "Aerlang controller");
elements_text_box(
canvas,
4,
30,
80,
48,
AlignLeft,
AlignTop,
"Press \e#OK\e# button\n"
"To \e#attack\e#",
false);
elements_button_center(canvas, model->is_start ? "Stop":"Start");
elements_button_left(canvas, "Pre");
break;
default:
break;
}
}
static bool view_weapon_input_callback(InputEvent* input_event, void* context){
bleScanCtx *_ctx = (bleScanCtx *)context;
// FURI_LOG_I(TAG, "Weapon_count: %d\n", Weapon_COUNT);
if(input_event->type == InputTypeShort){
if(input_event->key == InputKeyRight){
with_view_model(
_ctx->view_list[subMenuViewWeapon],
SkeletonWeaponModel * model,
{
if(model->state_index < Weapon_COUNT-1) {
model->state_index++;
}
},
true);
return true;
}else if(input_event->key == InputKeyLeft){
with_view_model(
_ctx->view_list[subMenuViewWeapon],
SkeletonWeaponModel * model,
{
if(model->state_index > 0) {
model->state_index--;
}
},
true);
return true;
}else if(input_event->key == InputKeyOk){
SkeletonWeaponModel *model = view_get_model(_ctx->view_list[subMenuViewWeapon]);
if(!model->is_start){
view_dispatcher_send_custom_event(_ctx->view_dispatcher, model->state_index);
start_blink(_ctx);
}else{
stop_blink(_ctx);
}
model->is_start = !model->is_start;
// 更新下方按钮状态
view_dispatcher_switch_to_view(_ctx->view_dispatcher, subMenuViewWeapon);
}else if(input_event->key == InputKeyBack){
stop_blink(_ctx);
}
}
return false;
}
static bool weapon_custom_event_callback(uint32_t event, void* context) {
bleScanCtx *ctx = (bleScanCtx *)context;
char label[20] = "weapon";
FuriString* cmd_buf = furi_string_alloc();
if(ctx->uapp->uart_is_init == 0){
// view_dispatcher_send_custom_event(_ctx->view_dispatcher, 2);
uart_init(ctx->uapp, ctx->uapp->BAUDRATE, UART_CH);
ctx->uapp->uart_is_init = 1;
}
switch(event){
case Weapon_OKLOK_UNLOCK:
FURI_LOG_I(TAG, "Weapon custom event: Weapon_OKLOK_UNLOCK");
// sprintf(cmd_buf, "%s,%d", label, (int)event);
furi_string_cat_printf(cmd_buf, "%s,%d", label, (int)event);
uart_send_cmd(ctx->uapp, (uint8_t *)furi_string_get_cstr(cmd_buf), furi_string_size(cmd_buf));
// return true;
break;
case Weapon_Aerlang:
FURI_LOG_I(TAG, "Weapon custom event: Weapon_Aerlang");
// sprintf(cmd_buf, "%s,%d", label, (int)event);
furi_string_cat_printf(cmd_buf, "%s,%d", label, (int)event);
uart_send_cmd(ctx->uapp, (uint8_t *)furi_string_get_cstr(cmd_buf), furi_string_size(cmd_buf));
// return true;
break;
default:
return false;
}
furi_string_free(cmd_buf);
return false;
}
static bool setup_custom_event_callback(uint32_t event, void* context) {
bleScanCtx *ctx = (bleScanCtx *)context;
UNUSED(ctx);
switch(event){
case 0:
return true;
default:
return false;
}
return false;
}
// 自定义event的处理
static bool scan_custom_event_callback(uint32_t event, void* context) {
bleScanCtx *ctx = (bleScanCtx *)context;
uart_app *uapp = ctx->uapp;
FURI_LOG_I(TAG, "scan_custom_event_callback event: %ld", event);
float frequency;
switch(event){
case TEST_BTN:
if(furi_hal_speaker_acquire(500)) {
frequency = 200;
furi_hal_speaker_start(frequency, 1.0);
furi_delay_ms(100);
furi_hal_speaker_stop();
furi_hal_speaker_release();
}
// x = 1;
return true;
case START_SCAN:
// scanEndFlag = true;
// uint8_t cmd[20] = "scan";
if(!scanEndFlag){
TextBox* text_box = uapp->text_box;
text_box_reset(text_box);
furi_string_reset(uapp->text_box_store);
text_box_set_text(text_box, furi_string_get_cstr(uapp->text_box_store));
uart_send_cmd(uapp, (uint8_t*)"scan\n", 5);
if(uapp->scan_timer == NULL){
start_blink(ctx);
uapp->scan_timer = furi_timer_alloc(scan_console_recv, FuriTimerTypePeriodic, ctx);
furi_timer_start(uapp->scan_timer, 200);
}
}
// while(!(strlen((char *)uapp->rx_buf) > 0));
// furi_string_printf(uapp->text_box_store, "recv buf:%s,;", uapp->rx_buf);
// TextBox* text_box = uapp->text_box;
// text_box_set_text(text_box, furi_string_get_cstr(uapp->text_box_store));
// stop_blink(bleCtx);
return true;
case UART_INIT:
FURI_LOG_I(TAG, "UART init by scan module, baudrate: %d", uapp->BAUDRATE);
uart_init(uapp, uapp->BAUDRATE, UART_CH);
return true;
default:
return false;
}
return true;
}
static bool console_custom_event_callback(uint32_t event, void* context) {
bleScanCtx *ctx = (bleScanCtx *)context;
char buf[20] = "";
switch(event){
// clean logs
case 1:
// text_box_reset(_ctx->uapp->text_box);
// view_dispatcher_switch_to_view(_ctx->view_dispatcher, subMenuViewConsole);
furi_string_printf(ctx->uapp->text_box_store, "%s", buf);
text_box_set_text(ctx->uapp->text_box, furi_string_get_cstr(ctx->uapp->text_box_store));
return true;
case 2:
FURI_LOG_I(TAG, "UART init by console module, baudrate: %d", ctx->uapp->BAUDRATE);
uart_init(ctx->uapp, ctx->uapp->BAUDRATE, UART_CH);
return true;
default:
return false;
}
return true;
}
static bool view_scan_input_callback(InputEvent* input_event, void* context) {
bleScanCtx *_ctx = (bleScanCtx *)context;
// uart_app *uapp = _ctx->uapp;
if(input_event->type == InputTypeShort){
if(input_event->key == InputKeyLeft){
view_dispatcher_send_custom_event(_ctx->view_dispatcher, TEST_BTN);
return true;
}else if(input_event->key == InputKeyOk){
view_dispatcher_send_custom_event(_ctx->view_dispatcher, START_SCAN);
return true;
}
}
return false;
}
static bool view_console_input_callback(InputEvent* input_event, void* context) {
bleScanCtx *_ctx = (bleScanCtx *)context;
if(input_event->type == InputTypeShort){
if(input_event->key == InputKeyLeft){
view_dispatcher_send_custom_event(_ctx->view_dispatcher, 42);
return true;
// clean uart log
}else if(input_event->key == InputKeyOk){
// view_dispatcher_switch_to_view(_ctx->view_dispatcher, subMenuViewConsole);
view_dispatcher_send_custom_event(_ctx->view_dispatcher, 1);
return true;
}
}
return false;
}
void uart_terminal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
furi_assert(context);
uart_app* app = context;
FuriString* new_str = furi_string_alloc();
furi_string_cat_printf(new_str, "%s", buf);
app->text_box_store_strlen += furi_string_size(new_str);
;
while(app->text_box_store_strlen >= UART_TERMINAL_TEXT_BOX_STORE_SIZE - 1) {
furi_string_right(app->text_box_store, app->text_box_store_strlen / 2);
app->text_box_store_strlen = furi_string_size(app->text_box_store) + len;
}
furi_string_cat(app->text_box_store, new_str);
// furi_string_cat(app->text_box_store, "\n");
furi_string_free(new_str);
}
void uart_terminal_uart_set_handle_rx_data_cb(uart_app* uart, void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)) {
furi_assert(uart);
uart->handle_rx_data_cb = handle_rx_data_cb;
}
static void loop_console(void *app){
TextBox* text_box = ((uart_app *)app)->text_box;
text_box_set_font(text_box, TextBoxFontText);
text_box_set_focus(text_box, TextBoxFocusEnd);
uart_terminal_uart_set_handle_rx_data_cb(
((uart_app *)app), uart_terminal_console_output_handle_rx_data_cb); // setup callback for rx thread
text_box_set_text(text_box, furi_string_get_cstr(((uart_app *)app)->text_box_store));
}
static void view_console_enter_callback(void* context) {
furi_assert(context);
bleScanCtx *_ctx = (bleScanCtx *)context;
uart_app *uapp = _ctx->uapp;
if(uapp->uart_is_init == 0){
view_dispatcher_send_custom_event(_ctx->view_dispatcher, 2);
uapp->uart_is_init = 1;
}
TextBox* text_box = uapp->text_box;
// text_box_reset(text_box);
text_box_set_font(text_box, TextBoxFontText);
text_box_set_focus(text_box, TextBoxFocusEnd);
furi_string_reset(uapp->text_box_store);
// uart_terminal_uart_set_handle_rx_data_cb(
// ((uart_app *)uapp), uart_terminal_console_output_handle_rx_data_cb); // setup callback for rx thread
text_box_set_text(text_box, furi_string_get_cstr(uapp->text_box_store));
// 设置定时器,更新接收到的数据
uapp->console_timer = furi_timer_alloc(loop_console, FuriTimerTypePeriodic, uapp);
furi_timer_start(uapp->console_timer, 200);
}
void view_console_exit_callback(void* context) {
bleScanCtx *_ctx = (bleScanCtx *)context;
// UNUSED(_ctx);
// Unregister rx callback
uart_terminal_uart_set_handle_rx_data_cb(_ctx->uapp, NULL);
}
static void view_scan_enter_callback(void* context) {
bleScanCtx *_ctx = (bleScanCtx *)context;
uart_app *uapp = _ctx->uapp;
if(uapp->uart_is_init == 0){
view_dispatcher_send_custom_event(_ctx->view_dispatcher, UART_INIT);
uapp->uart_is_init = 1;
}
}
static void view_scan_exit_callback(void* context) {
bleScanCtx *_ctx = (bleScanCtx *)context;
stop_blink(_ctx);
}
static uint32_t navigation_submenu_callback(void* _context) {
UNUSED(_context);
return subMenuViewMain;
}
static uint32_t navigation_exit_callback(void* _context) {
UNUSED(_context);
return VIEW_NONE;
}
static int32_t uart_worker(void* context) {
uart_app* uart = (void*)context;
while(1) {
uint32_t events =
furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
furi_check((events & FuriFlagError) == 0);
if(events & WorkerEvtStop) break;
if(events & WorkerEvtRxDone) {
size_t len = furi_stream_buffer_receive(uart->rx_stream, uart->rx_buf, RX_BUF_SIZE, 0);
if(len > 0) {
if(uart->handle_rx_data_cb) uart->handle_rx_data_cb(uart->rx_buf, len, uart);
}
}
}
furi_stream_buffer_free(uart->rx_stream);
return 0;
}
void uart_terminal_uart_on_irq_cb(
FuriHalSerialHandle* handle,
FuriHalSerialRxEvent event,
void* context) {
uart_app* uart = (void*)context;
if(event == FuriHalSerialRxEventData) {
uint8_t data = furi_hal_serial_async_rx(handle);
furi_stream_buffer_send(uart->rx_stream, &data, 1, 0);
furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone);
}
}
void uart_init(uart_app* uapp, int baudrate, FuriHalSerialId ch){
FURI_LOG_I(TAG, "UART initialing...\n");
uapp->rx_stream = furi_stream_buffer_alloc(320*3, 1);
uapp->rx_thread = furi_thread_alloc();
furi_thread_set_name(uapp->rx_thread, "UART_TerminalUartRxThread");
furi_thread_set_stack_size(uapp->rx_thread, 1024);
furi_thread_set_context(uapp->rx_thread, uapp);
furi_thread_set_callback(uapp->rx_thread, uart_worker);
furi_thread_start(uapp->rx_thread);
uapp->BAUDRATE = baudrate;
uapp->serial_handle = furi_hal_serial_control_acquire(ch);
// furi_check(uapp->serial_handle);
furi_hal_serial_init(uapp->serial_handle, uapp->BAUDRATE);
furi_hal_serial_async_rx_start(uapp->serial_handle, uart_terminal_uart_on_irq_cb, uapp, false);
}
void uart_terminal_uart_free(uart_app* uart) {
furi_assert(uart);
furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtStop);
furi_thread_join(uart->rx_thread);
furi_thread_free(uart->rx_thread);
furi_hal_serial_deinit(uart->serial_handle);
furi_hal_serial_control_release(uart->serial_handle);
free(uart);
}
char *BaudRate_strings[] = {"115200", "38400", "9600"};
static void baudRate_change_callback(VariableItem* item){
furi_assert(item);
bleScanCtx *bleCtx = variable_item_get_context(item);
uart_app *uapp = bleCtx->uapp;
int index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, BaudRate_strings[index]);
uapp->baudrate_index = index;
FURI_LOG_I(TAG, "BaudRate changed: %s", BaudRate_strings[uapp->baudrate_index]);
uapp->BAUDRATE = atoi(BaudRate_strings[uapp->baudrate_index]);
// view_dispatcher_send_custom_event(bleCtx->view_dispatcher, 0);
}
bleScanCtx *ble_init(){
bleScanCtx *bleCtx = malloc(sizeof(bleScanCtx));
Gui* gui = furi_record_open(RECORD_GUI);
bleCtx->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(bleCtx->view_dispatcher);
view_dispatcher_attach_to_gui(bleCtx->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
view_dispatcher_set_event_callback_context(bleCtx->view_dispatcher, bleCtx);
bleCtx->notification = furi_record_open(RECORD_NOTIFICATION);
bleCtx->submenu = submenu_alloc();
uart_app* uapp = malloc(sizeof(uart_app));
// 默认波特率
uapp->BAUDRATE = 9600;
// uapp->scanEndFlag = false;
bleCtx->uapp = uapp;
// 添加主菜单setup list列表
submenu_add_item(
bleCtx->submenu, "Setup", subMenuSetup, skeleton_submenu_callback, bleCtx);
submenu_add_item(
bleCtx->submenu, "Scan", subMenuScan, skeleton_submenu_callback, bleCtx);
submenu_add_item(
bleCtx->submenu, "Weapon", subMenuWeapon, skeleton_submenu_callback, bleCtx);
submenu_add_item(
bleCtx->submenu, "Console", subMenuConsole, skeleton_submenu_callback, bleCtx);
submenu_add_item(
bleCtx->submenu, "About", subMenuAbout, skeleton_submenu_callback, bleCtx);
view_set_previous_callback(submenu_get_view(bleCtx->submenu), navigation_exit_callback);
view_dispatcher_add_view(
bleCtx->view_dispatcher, subMenuViewMain, submenu_get_view(bleCtx->submenu)
);
view_dispatcher_switch_to_view(bleCtx->view_dispatcher, subMenuViewMain);
bleCtx->variable_item_list = variable_item_list_alloc();
variable_item_list_reset(bleCtx->variable_item_list);
VariableItem* item = variable_item_list_add(bleCtx->variable_item_list,
"BAUDRATE", // label to display
COUNT_OF(BaudRate_strings), // number of choices
baudRate_change_callback, // callback
bleCtx); // context [use variable_item_get_context(item) to access]
variable_item_set_current_value_index(item, 0);
variable_item_set_current_value_text(item, BaudRate_strings[0]);
view_set_previous_callback(variable_item_list_get_view(bleCtx->variable_item_list), navigation_submenu_callback);
view_set_custom_callback(variable_item_list_get_view(bleCtx->variable_item_list) ,setup_custom_event_callback);
view_dispatcher_add_view(
bleCtx->view_dispatcher, subMenuViewSetup, variable_item_list_get_view(bleCtx->variable_item_list)
);
// bleCtx->view_list[subMenuViewSetup] = view_alloc();
bleCtx->view_list[subMenuViewScan] = view_alloc();
bleCtx->view_list[subMenuViewWeapon] = view_alloc();
uapp->text_box = text_box_alloc();
bleCtx->view_list[subMenuViewConsole] = uapp->text_box;
// bleCtx->view_list[subMenuViewConsole] = view_alloc();
bleCtx->view_list[subMenuViewAbout] = widget_alloc();
View *text_box_view = text_box_get_view(uapp->text_box);
view_dispatcher_add_view(
bleCtx->view_dispatcher,
subMenuViewConsole,
text_box_view
);
uapp->text_box_store = furi_string_alloc();
furi_string_reserve(uapp->text_box_store, UART_TERMINAL_TEXT_BOX_STORE_SIZE);
View *scan_view = (View*)bleCtx->view_list[subMenuViewScan];
view_dispatcher_add_view(
bleCtx->view_dispatcher,
subMenuViewScan,
scan_view
);
view_set_context(scan_view, bleCtx);
view_set_draw_callback(scan_view, view_scan_draw_callback);
view_set_input_callback(scan_view, view_scan_input_callback);
view_set_previous_callback(scan_view, navigation_submenu_callback);
view_set_enter_callback(scan_view, view_scan_enter_callback);
view_set_exit_callback(scan_view, view_scan_exit_callback);
view_set_custom_callback(scan_view ,scan_custom_event_callback);
view_allocate_model(scan_view, ViewModelTypeLockFree, sizeof(SkeletonScanModel));
SkeletonScanModel *scan_model = view_get_model(scan_view);
scan_model->widget = bleCtx;
scan_model->s = furi_string_alloc();
furi_string_printf(scan_model->s, "%s", "This is a bluetooth ble scanner and controller tool.\n---\nScan any low energy ble device around.\nScan any low energy ble device around.\nScan any low energy ble device around.");
widget_add_text_scroll_element(
bleCtx->view_list[subMenuViewAbout],
0,
0,
128,
64,
"This is a bluetooth ble scanner and something ble devices controller tool.\n---\nScan any low energy ble device around."
);
view_set_context(text_box_view, bleCtx);
view_set_previous_callback(text_box_view, navigation_submenu_callback);
view_set_enter_callback(text_box_view, view_console_enter_callback);
view_set_exit_callback(text_box_view, view_console_exit_callback);
view_set_input_callback(text_box_view, view_console_input_callback);
view_set_custom_callback(text_box_view ,console_custom_event_callback);
View *weapon_view = (View* )bleCtx->view_list[subMenuViewWeapon];
view_dispatcher_add_view(
bleCtx->view_dispatcher,
subMenuViewWeapon,
weapon_view
);
view_set_context(weapon_view, bleCtx);
view_set_draw_callback(weapon_view, view_weapon_draw_callback);
view_set_input_callback(weapon_view, view_weapon_input_callback);
view_set_custom_callback(weapon_view ,weapon_custom_event_callback);
// view_set_exit_callback(weapon_view, view_console_exit_callback);
view_set_previous_callback(weapon_view, navigation_submenu_callback);
// draw callback 必须使用view_allocate_model
view_allocate_model(weapon_view, ViewModelTypeLockFree, sizeof(SkeletonWeaponModel));
SkeletonWeaponModel* model = view_get_model(weapon_view);
model->state_index = 0;
model->is_start = false;
view_set_previous_callback(widget_get_view(bleCtx->view_list[subMenuViewAbout]), navigation_submenu_callback);
view_dispatcher_add_view(
bleCtx->view_dispatcher,
subMenuViewAbout,
widget_get_view(bleCtx->view_list[subMenuViewAbout])
);
return bleCtx;
}
void ble_free(bleScanCtx *bleCtx){
uart_app * uapp = bleCtx->uapp;
view_dispatcher_remove_view(bleCtx->view_dispatcher, subMenuViewMain);
view_dispatcher_remove_view(bleCtx->view_dispatcher, subMenuViewScan);
view_dispatcher_remove_view(bleCtx->view_dispatcher, subMenuViewWeapon);
view_dispatcher_remove_view(bleCtx->view_dispatcher, subMenuViewConsole);
view_dispatcher_remove_view(bleCtx->view_dispatcher, subMenuViewAbout);
view_dispatcher_remove_view(bleCtx->view_dispatcher, subMenuViewSetup);
int i;
for(i = 0;i < MAX_DEVICE_SCAN;i++){
if(device[i] != NULL){
free(device[i]);
}
}
if(uapp->console_timer){
furi_timer_free(uapp->console_timer);
}
if(uapp->scan_timer){
furi_timer_free(uapp->scan_timer);
}
text_box_free(uapp->text_box);
furi_string_free(uapp->text_box_store);
if(uapp->uart_is_init != 0){
uart_terminal_uart_free(uapp);
}
widget_free(bleCtx->view_list[subMenuViewAbout]);
view_free(bleCtx->view_list[subMenuViewScan]);
submenu_free(bleCtx->submenu);
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_NOTIFICATION);
view_dispatcher_free(bleCtx->view_dispatcher);
free(bleCtx);
scanEndFlag = false;
}
int32_t main_entry() {
bleScanCtx *bleCtx = ble_init();
FURI_LOG_I(TAG, "FINISH ble_init.");
view_dispatcher_run(bleCtx->view_dispatcher);
ble_free(bleCtx);
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

+34
View File
@@ -0,0 +1,34 @@
#include "furi_hal.h"
#include <gui/modules/text_box.h>
#define RX_BUF_SIZE 1024
#define START_SCAN 0
#define TEST_BTN 1
#define UART_INIT 2
typedef struct UART_TerminalApp {
uint8_t uart_ch;
uint8_t baudrate_index;
FuriStreamBuffer* rx_stream;
FuriThread* rx_thread;
uint8_t rx_buf[RX_BUF_SIZE + 1];
TextBox *text_box;
FuriString *text_box_store;
size_t text_box_store_strlen;
FuriTimer* console_timer;
FuriTimer* scan_timer;
int BAUDRATE;
int uart_is_init;
FuriHalSerialHandle* serial_handle;
void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
} uart_app;
void uart_init(uart_app* uapp, int baudrate, FuriHalSerialId ch);
static void scan_console_recv(void *ctx);
void uart_terminal_uart_set_handle_rx_data_cb(uart_app* uart, void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
void uart_terminal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context);
void uart_terminal_uart_free(uart_app* uart);
static void baudRate_change_callback(VariableItem* item);