mirror of
https://github.com/D4C1-Labs/Flipper-ARF.git
synced 2026-07-14 11:38:57 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 63d951dc38 | |||
| f1422cb701 |
@@ -15,6 +15,7 @@ typedef enum {
|
||||
SubGhzCustomEventSceneReceiverInfoTxStart,
|
||||
SubGhzCustomEventSceneReceiverInfoTxStop,
|
||||
SubGhzCustomEventSceneReceiverInfoSave,
|
||||
SubGhzCustomEventSceneReceiverInfoTxFullDpad,
|
||||
SubGhzCustomEventSceneSaveName,
|
||||
SubGhzCustomEventSceneSignalSettings,
|
||||
SubGhzCustomEventSceneSaveSuccess,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../subghz_i.h"
|
||||
|
||||
#include <lib/subghz/blocks/custom_btn.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
|
||||
#include "applications/main/subghz/helpers/subghz_txrx_i.h"
|
||||
#include <lib/subghz/blocks/generic.h>
|
||||
@@ -20,6 +21,9 @@ void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, v
|
||||
} else if((result == GuiButtonTypeRight) && (type == InputTypeShort)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzCustomEventSceneReceiverInfoSave);
|
||||
} else if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzCustomEventSceneReceiverInfoTxFullDpad);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +33,6 @@ static bool subghz_scene_receiver_info_update_parser(void* context) {
|
||||
if(subghz_txrx_load_decoder_by_name_protocol(
|
||||
subghz->txrx,
|
||||
subghz_history_get_protocol_name(subghz->history, subghz->idx_menu_chosen))) {
|
||||
// we are trying to deserialize without checking for errors, since it is assumed that we just received this chignal
|
||||
subghz_protocol_decoder_base_deserialize(
|
||||
subghz_txrx_get_decoder(subghz->txrx),
|
||||
subghz_history_get_raw_data(subghz->history, subghz->idx_menu_chosen));
|
||||
@@ -37,7 +40,6 @@ static bool subghz_scene_receiver_info_update_parser(void* context) {
|
||||
SubGhzRadioPreset* preset =
|
||||
subghz_history_get_radio_preset(subghz->history, subghz->idx_menu_chosen);
|
||||
|
||||
//Edit TX power, if necessary.
|
||||
subghz_txrx_set_tx_power(preset->data, preset->data_size, subghz->tx_power);
|
||||
|
||||
subghz_txrx_set_preset(
|
||||
@@ -93,7 +95,7 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) {
|
||||
subghz_scene_receiver_info_callback,
|
||||
subghz);
|
||||
}
|
||||
// Removed static check
|
||||
|
||||
if(subghz_txrx_protocol_is_transmittable(subghz->txrx, false)) {
|
||||
widget_add_button_element(
|
||||
subghz->widget,
|
||||
@@ -101,9 +103,14 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) {
|
||||
"Send",
|
||||
subghz_scene_receiver_info_callback,
|
||||
subghz);
|
||||
widget_add_button_element(
|
||||
subghz->widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Full",
|
||||
subghz_scene_receiver_info_callback,
|
||||
subghz);
|
||||
}
|
||||
} else {
|
||||
// [NO_DOLPHIN] widget_add_icon_element(subghz->widget, 83, 22, &I_WarningDolphinFlip_45x42);
|
||||
widget_add_string_element(
|
||||
subghz->widget, 13, 8, AlignLeft, AlignBottom, FontSecondary, "Error history parse.");
|
||||
}
|
||||
@@ -131,12 +138,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
if(!subghz_scene_receiver_info_update_parser(subghz)) {
|
||||
return false;
|
||||
}
|
||||
//CC1101 Stop RX -> Start TX
|
||||
subghz_txrx_hopper_pause(subghz->txrx);
|
||||
// key concept: we start endless TX until user release OK button, and after this we send last
|
||||
// protocols repeats - this guarantee that one press OK will
|
||||
// be guarantee send the required minimum protocol data packets
|
||||
// for all of this we use subghz_block_generic_global.endless_tx in protocols _yield function.
|
||||
subghz->state_notifications = SubGhzNotificationStateTx;
|
||||
subghz_block_generic_global.endless_tx = true;
|
||||
if(!subghz_tx_start(
|
||||
@@ -146,37 +148,51 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
subghz_txrx_hopper_unpause(subghz->txrx);
|
||||
subghz->state_notifications = SubGhzNotificationStateRx;
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if(event.event == SubGhzCustomEventSceneReceiverInfoTxStop) {
|
||||
//CC1101 Stop Tx -> next tick event Start RX
|
||||
// user release OK
|
||||
// we switch off endless_tx - that mean protocols yield finish endless transmission,
|
||||
// send upload "repeat=xx" times, and after will be stoped by the tick event down in this code
|
||||
subghz->state_notifications = SubGhzNotificationStateTxWait;
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
|
||||
return true;
|
||||
|
||||
} else if(event.event == SubGhzCustomEventSceneReceiverInfoSave) {
|
||||
//CC1101 Stop RX -> Save
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
subghz_txrx_hopper_set_state(subghz->txrx, SubGhzHopperStateOFF);
|
||||
|
||||
subghz_txrx_stop(subghz->txrx);
|
||||
if(!subghz_scene_receiver_info_update_parser(subghz)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(subghz_txrx_protocol_is_serializable(subghz->txrx)) {
|
||||
subghz_file_name_clear(subghz);
|
||||
|
||||
subghz->save_datetime =
|
||||
subghz_history_get_datetime(subghz->history, subghz->idx_menu_chosen);
|
||||
subghz->save_datetime_set = true;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if(event.event == SubGhzCustomEventSceneReceiverInfoTxFullDpad) {
|
||||
if(!subghz_scene_receiver_info_update_parser(subghz)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FlipperFormat* fff_history =
|
||||
subghz_history_get_raw_data(subghz->history, subghz->idx_menu_chosen);
|
||||
FlipperFormat* fff_data = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
|
||||
Stream* src = flipper_format_get_raw_stream(fff_history);
|
||||
Stream* dst = flipper_format_get_raw_stream(fff_data);
|
||||
|
||||
stream_seek(src, 0, StreamOffsetFromStart);
|
||||
stream_clean(dst);
|
||||
stream_copy_full(src, dst);
|
||||
stream_seek(dst, 0, StreamOffsetFromStart);
|
||||
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTransmitter);
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF) {
|
||||
subghz_txrx_hopper_update(subghz->txrx, subghz->last_settings->hopping_threshold);
|
||||
@@ -193,18 +209,15 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
subghz->state_notifications = SubGhzNotificationStateRx;
|
||||
break;
|
||||
case SubGhzNotificationStateTxWait:
|
||||
// we wait until hardware TX finished and after stop TX and start RX, else just blink led
|
||||
if(!subghz_devices_is_async_complete_tx(subghz->txrx->radio_device)) {
|
||||
notification_message(subghz->notifications, &sequence_blink_magenta_10);
|
||||
} else {
|
||||
subghz_txrx_stop(subghz->txrx);
|
||||
// update screen
|
||||
widget_reset(subghz->widget);
|
||||
subghz_scene_receiver_info_draw_widget(subghz);
|
||||
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
|
||||
if(!scene_manager_has_previous_scene(subghz->scene_manager, SubGhzSceneDecodeRAW)) {
|
||||
if(!scene_manager_has_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneDecodeRAW)) {
|
||||
subghz_txrx_rx_start(subghz->txrx);
|
||||
subghz_txrx_hopper_unpause(subghz->txrx);
|
||||
if(!subghz_history_get_text_space_left(subghz->history, NULL)) {
|
||||
@@ -222,7 +235,6 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
|
||||
void subghz_scene_receiver_info_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
widget_reset(subghz->widget);
|
||||
subghz_txrx_reset_dynamic_and_custom_btns(subghz->txrx);
|
||||
}
|
||||
|
||||
@@ -13,12 +13,15 @@ def ProtoPirateDefineEnabled(name, app_manifest_path=app_manifest_path):
|
||||
|
||||
|
||||
_ENABLE_TIMING_TUNER = ProtoPirateDefineEnabled("ENABLE_TIMING_TUNER_SCENE")
|
||||
_ENABLE_EMULATE = ProtoPirateDefineEnabled("ENABLE_EMULATE_FEATURE")
|
||||
|
||||
_MAIN_APP_SOURCES = [
|
||||
"*.c*",
|
||||
"!protocols/plugins",
|
||||
"!scenes/plugins",
|
||||
"!protocols",
|
||||
"!protopirate_emulate_plugin.c",
|
||||
"!protopirate_psa_bf_plugin.c",
|
||||
"protocols/protocol_items.c",
|
||||
"protocols/protocols_common.c",
|
||||
"!raw_file_reader.c",
|
||||
@@ -30,6 +33,11 @@ if not _ENABLE_TIMING_TUNER:
|
||||
"!protocol_timings.c",
|
||||
]
|
||||
|
||||
if not _ENABLE_EMULATE:
|
||||
_MAIN_APP_SOURCES += [
|
||||
"!protopirate_scene_emulate.c",
|
||||
]
|
||||
|
||||
App(
|
||||
appid="proto_pirate",
|
||||
name="ProtoPirate",
|
||||
@@ -39,7 +47,7 @@ App(
|
||||
requires=["gui"],
|
||||
stack_size=8 * 1024,
|
||||
fap_description="Decode car key fob signals from Sub-GHz",
|
||||
fap_version="3.0",
|
||||
fap_version="3.2",
|
||||
fap_icon="images/protopirate_10px.png",
|
||||
fap_category="Sub-GHz",
|
||||
fap_icon_assets="images",
|
||||
@@ -165,7 +173,11 @@ def ProtoPirateTxProtocolPlugin(
|
||||
App=App,
|
||||
FlipperAppType=FlipperAppType,
|
||||
tx_plugin_sources=_TX_PLUGIN_SOURCES,
|
||||
enable_emulate=_ENABLE_EMULATE,
|
||||
):
|
||||
if not enable_emulate:
|
||||
return
|
||||
|
||||
App(
|
||||
appid=f"protopirate_tx_{key}_plugin",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
@@ -370,17 +382,18 @@ if _ENABLE_TIMING_TUNER:
|
||||
fal_embedded=True,
|
||||
)
|
||||
|
||||
App(
|
||||
appid="protopirate_emulate_plugin",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="protopirate_emulate_plugin_ep",
|
||||
requires=["proto_pirate"],
|
||||
sources=[
|
||||
"scenes/plugins/protopirate_emulate_plugin.c",
|
||||
"protocols/protocol_items.c",
|
||||
],
|
||||
fal_embedded=True,
|
||||
)
|
||||
if _ENABLE_EMULATE:
|
||||
App(
|
||||
appid="protopirate_emulate_plugin",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="protopirate_emulate_plugin_ep",
|
||||
requires=["proto_pirate"],
|
||||
sources=[
|
||||
"scenes/plugins/protopirate_emulate_plugin.c",
|
||||
"protocols/protocol_items.c",
|
||||
],
|
||||
fal_embedded=True,
|
||||
)
|
||||
|
||||
App(
|
||||
appid="protopirate_psa_bf_plugin",
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "ProtoPirateProtocolPlugin"
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
#define PROTOPIRATE_TX_PLUGIN_PATH_MAX 160U
|
||||
#endif
|
||||
|
||||
static const char* protopirate_get_registry_plugin_path(ProtoPirateProtocolRegistryRoute route) {
|
||||
switch(route) {
|
||||
@@ -25,6 +27,7 @@ static const char* protopirate_get_registry_plugin_path(ProtoPirateProtocolRegis
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
static bool protopirate_build_tx_protocol_plugin_path(
|
||||
const char* tx_key,
|
||||
char* plugin_path,
|
||||
@@ -40,6 +43,7 @@ static bool protopirate_build_tx_protocol_plugin_path(
|
||||
tx_key);
|
||||
return (written > 0) && ((size_t)written < plugin_path_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const SubGhzProtocolRegistry protopirate_empty_protocol_registry = {
|
||||
.items = NULL,
|
||||
@@ -165,6 +169,7 @@ static bool protopirate_ensure_protocol_registry_plugin(
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
static bool protopirate_ensure_tx_protocol_plugin(
|
||||
ProtoPirateApp* app,
|
||||
const char* protocol_name,
|
||||
@@ -264,6 +269,7 @@ static bool protopirate_ensure_tx_protocol_plugin(
|
||||
*registry = plugin->registry;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool protopirate_refresh_protocol_registry(ProtoPirateApp* app, bool ensure_receiver_ready) {
|
||||
furi_check(app);
|
||||
@@ -378,6 +384,7 @@ bool protopirate_apply_protocol_registry_for_context(
|
||||
}
|
||||
|
||||
if(protocol_name && protocol_name[0] != '\0') {
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
const char* registry_name = protopirate_protocol_catalog_canonical_name(protocol_name);
|
||||
if(!registry_name || !protopirate_protocol_catalog_can_tx(protocol_name)) {
|
||||
FURI_LOG_E(TAG, "No TX protocol plugin for %s", protocol_name);
|
||||
@@ -410,6 +417,9 @@ bool protopirate_apply_protocol_registry_for_context(
|
||||
subghz_environment_set_protocol_registry(app->txrx->environment, tx_registry);
|
||||
app->txrx->protocol_registry = tx_registry;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
ProtoPirateProtocolRegistryRoute route = protopirate_get_protocol_registry_route(
|
||||
|
||||
@@ -103,12 +103,14 @@ void protopirate_settings_load(ProtoPirateSettings* settings) {
|
||||
}
|
||||
settings->hopping_enabled = (hopping_temp == 1);
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
uint32_t emulate_temp = 0;
|
||||
if(!flipper_format_read_uint32(ff, "EmulateFeature", &emulate_temp, 1)) {
|
||||
FURI_LOG_I(TAG, "EmulateFeature key missing, defaulting to disabled");
|
||||
emulate_temp = 0;
|
||||
}
|
||||
settings->emulate_feature_enabled = (emulate_temp == 1);
|
||||
#endif
|
||||
|
||||
uint32_t check_saved_temp = 0;
|
||||
if(!flipper_format_read_uint32(ff, "CheckSaved", &check_saved_temp, 1)) {
|
||||
@@ -185,11 +187,13 @@ void protopirate_settings_save(ProtoPirateSettings* settings) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
uint32_t emulate_temp = settings->emulate_feature_enabled ? 1 : 0;
|
||||
if(!flipper_format_write_uint32(ff, "EmulateFeature", &emulate_temp, 1)) {
|
||||
FURI_LOG_E(TAG, "Failed to write emulate feature flag");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t check_saved_temp = settings->check_saved ? 1 : 0;
|
||||
if(!flipper_format_write_uint32(ff, "CheckSaved", &check_saved_temp, 1)) {
|
||||
|
||||
@@ -513,6 +513,20 @@ static bool protopirate_storage_copy_key_2(
|
||||
protopirate_storage_copy_u32_optional(save_file, flipper_format, "Key_2");
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_key2(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format) {
|
||||
bool copied = false;
|
||||
if(!protopirate_storage_copy_hex_fixed(save_file, flipper_format, "Key2", 8, &copied)) {
|
||||
return false;
|
||||
}
|
||||
if(copied) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return protopirate_storage_copy_hex_or_u32(save_file, flipper_format, "Key2", 4);
|
||||
}
|
||||
|
||||
static bool protopirate_storage_write_capture_data(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format) {
|
||||
@@ -548,7 +562,7 @@ static bool protopirate_storage_write_capture_data(
|
||||
protopirate_storage_base_u32_fields,
|
||||
COUNT_OF(protopirate_storage_base_u32_fields)))
|
||||
break;
|
||||
if(!protopirate_storage_copy_hex_or_u32(save_file, flipper_format, "Key2", 4)) break;
|
||||
if(!protopirate_storage_copy_key2(save_file, flipper_format)) break;
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, "KeyIdx")) break;
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, "Seed")) break;
|
||||
if(!protopirate_storage_copy_hex_or_u32(save_file, flipper_format, "ValidationField", 2))
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <furi.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../defines.h"
|
||||
|
||||
#define TAG "ProtoPirateCatalog"
|
||||
|
||||
#define PROTOPIRATE_CC1101_REG_MDMCFG2 0x12U
|
||||
@@ -17,6 +19,12 @@
|
||||
|
||||
#define PROTOPIRATE_COUNT_OF(array) (sizeof(array) / sizeof((array)[0]))
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
#define PROTOPIRATE_TX_KEY(key) key
|
||||
#else
|
||||
#define PROTOPIRATE_TX_KEY(key) NULL
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateProtocolCatalogModulationAM = 0,
|
||||
ProtoPirateProtocolCatalogModulationFM,
|
||||
@@ -28,33 +36,33 @@ typedef struct {
|
||||
} ProtoPirateProtocolCatalogAlias;
|
||||
|
||||
static const ProtoPirateProtocolCatalogEntry protopirate_protocol_catalog[] = {
|
||||
{"Chrysler V0", ProtoPirateProtocolCatalogRouteAMDefault, "chrysler_v0"},
|
||||
{"Fiat V0", ProtoPirateProtocolCatalogRouteAMDefault, "fiat_v0"},
|
||||
{"Fiat V1", ProtoPirateProtocolCatalogRouteAMDefault, "fiat_v1"},
|
||||
{"Chrysler V0", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("chrysler_v0")},
|
||||
{"Fiat V0", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("fiat_v0")},
|
||||
{"Fiat V1", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("fiat_v1")},
|
||||
{"Fiat V2", ProtoPirateProtocolCatalogRouteAMDefault, NULL},
|
||||
{"Ford V0", ProtoPirateProtocolCatalogRouteAMDefault, "ford_v0"},
|
||||
{"Ford V1", ProtoPirateProtocolCatalogRouteFMF4, "ford_v1"},
|
||||
{"Ford V2", ProtoPirateProtocolCatalogRouteFMF4, "ford_v2"},
|
||||
{"Ford V0", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("ford_v0")},
|
||||
{"Ford V1", ProtoPirateProtocolCatalogRouteFMF4, PROTOPIRATE_TX_KEY("ford_v1")},
|
||||
{"Ford V2", ProtoPirateProtocolCatalogRouteFMF4, PROTOPIRATE_TX_KEY("ford_v2")},
|
||||
{"Ford V3", ProtoPirateProtocolCatalogRouteFMF4, NULL},
|
||||
{"Honda Static", ProtoPirateProtocolCatalogRouteFMHonda1, "honda_static"},
|
||||
{"Honda V1", ProtoPirateProtocolCatalogRouteAMDefault, "honda_v1"},
|
||||
{"Kia V0", ProtoPirateProtocolCatalogRouteFMDefault, "kia_v0"},
|
||||
{"Kia V1", ProtoPirateProtocolCatalogRouteAMDefault, "kia_v1"},
|
||||
{"Kia V2", ProtoPirateProtocolCatalogRouteAMDefault, "kia_v2"},
|
||||
{"Kia V3/V4", ProtoPirateProtocolCatalogRouteFMDefault, "kia_v3_v4"},
|
||||
{"Kia V5", ProtoPirateProtocolCatalogRouteFMDefault, "kia_v5"},
|
||||
{"Kia V6", ProtoPirateProtocolCatalogRouteFMDefault, "kia_v6"},
|
||||
{"Kia V7", ProtoPirateProtocolCatalogRouteFMDefault, "kia_v7"},
|
||||
{"Honda V2", ProtoPirateProtocolCatalogRouteFMF4, "honda_v2"},
|
||||
{"Mazda V0", ProtoPirateProtocolCatalogRouteByModulation, "mazda_v0"},
|
||||
{"Honda Static", ProtoPirateProtocolCatalogRouteFMHonda1, PROTOPIRATE_TX_KEY("honda_static")},
|
||||
{"Honda V1", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("honda_v1")},
|
||||
{"Kia V0", ProtoPirateProtocolCatalogRouteFMDefault, PROTOPIRATE_TX_KEY("kia_v0")},
|
||||
{"Kia V1", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("kia_v1")},
|
||||
{"Kia V2", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("kia_v2")},
|
||||
{"Kia V3/V4", ProtoPirateProtocolCatalogRouteFMDefault, PROTOPIRATE_TX_KEY("kia_v3_v4")},
|
||||
{"Kia V5", ProtoPirateProtocolCatalogRouteFMDefault, PROTOPIRATE_TX_KEY("kia_v5")},
|
||||
{"Kia V6", ProtoPirateProtocolCatalogRouteFMDefault, PROTOPIRATE_TX_KEY("kia_v6")},
|
||||
{"Kia V7", ProtoPirateProtocolCatalogRouteFMDefault, PROTOPIRATE_TX_KEY("kia_v7")},
|
||||
{"Honda V2", ProtoPirateProtocolCatalogRouteFMF4, PROTOPIRATE_TX_KEY("honda_v2")},
|
||||
{"Mazda V0", ProtoPirateProtocolCatalogRouteByModulation, PROTOPIRATE_TX_KEY("mazda_v0")},
|
||||
{"Mitsubishi V0", ProtoPirateProtocolCatalogRouteFMDefault, NULL},
|
||||
{"Porsche Touareg", ProtoPirateProtocolCatalogRouteAMDefault, NULL},
|
||||
{"PSA", ProtoPirateProtocolCatalogRouteByModulation, "psa"},
|
||||
{"Renault V0", ProtoPirateProtocolCatalogRouteAMDefault, "renault_v0"},
|
||||
{"PSA", ProtoPirateProtocolCatalogRouteByModulation, PROTOPIRATE_TX_KEY("psa")},
|
||||
{"Renault V0", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("renault_v0")},
|
||||
{"Scher-Khan", ProtoPirateProtocolCatalogRouteFMDefault, NULL},
|
||||
{"Star Line", ProtoPirateProtocolCatalogRouteAMDefault, "star_line"},
|
||||
{"Subaru", ProtoPirateProtocolCatalogRouteAMDefault, "subaru"},
|
||||
{"VAG", ProtoPirateProtocolCatalogRouteAMVag, "vag"},
|
||||
{"Star Line", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("star_line")},
|
||||
{"Subaru", ProtoPirateProtocolCatalogRouteAMDefault, PROTOPIRATE_TX_KEY("subaru")},
|
||||
{"VAG", ProtoPirateProtocolCatalogRouteAMVag, PROTOPIRATE_TX_KEY("vag")},
|
||||
};
|
||||
|
||||
static const ProtoPirateProtocolCatalogAlias protopirate_protocol_catalog_aliases[] = {
|
||||
|
||||
@@ -90,7 +90,11 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
app->auto_save = settings.auto_save;
|
||||
app->check_saved = settings.check_saved;
|
||||
app->tx_power = settings.tx_power;
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
app->emulate_feature_enabled = settings.emulate_feature_enabled;
|
||||
#else
|
||||
app->emulate_feature_enabled = false;
|
||||
#endif
|
||||
|
||||
// Init setting - KEEP THIS, it's small
|
||||
app->setting = subghz_setting_alloc();
|
||||
@@ -175,7 +179,11 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
settings.check_saved = app->check_saved;
|
||||
settings.tx_power = app->tx_power;
|
||||
settings.hopping_enabled = (app->txrx->hopper_state != ProtoPirateHopperStateOFF);
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
settings.emulate_feature_enabled = app->emulate_feature_enabled;
|
||||
#else
|
||||
settings.emulate_feature_enabled = false;
|
||||
#endif
|
||||
|
||||
// Find current preset index
|
||||
settings.preset_index = 0;
|
||||
@@ -273,14 +281,18 @@ int32_t protopirate_app(char* p) {
|
||||
|
||||
//We now jump straight to emulate scene from Browser. If the user wanted the key to look at, just click back.
|
||||
if(load_saved) {
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
if(protopirate_app->emulate_feature_enabled) {
|
||||
view_dispatcher_send_custom_event(
|
||||
protopirate_app->view_dispatcher, ProtoPirateCustomEventSavedInfoEmulate);
|
||||
notification_message(protopirate_app->notifications, &sequence_success);
|
||||
} else {
|
||||
#endif
|
||||
view_dispatcher_send_custom_event(
|
||||
protopirate_app->view_dispatcher, ProtoPirateCustomEventReceiverInfoSave);
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
view_dispatcher_run(protopirate_app->view_dispatcher);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define CREDIT_LINE_HEIGHT 10
|
||||
#define SCROLL_SPEED 1
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
static const InputKey EMULATE_TOGGLE_COMBO[] = {
|
||||
InputKeyUp,
|
||||
InputKeyUp,
|
||||
@@ -23,6 +24,7 @@ static const InputKey EMULATE_TOGGLE_COMBO[] = {
|
||||
InputKeyRight,
|
||||
};
|
||||
#define EMULATE_TOGGLE_COMBO_LEN (sizeof(EMULATE_TOGGLE_COMBO) / sizeof(EMULATE_TOGGLE_COMBO[0]))
|
||||
#endif
|
||||
|
||||
static const char* credits[] = {
|
||||
"",
|
||||
@@ -62,7 +64,9 @@ typedef struct {
|
||||
uint8_t frame;
|
||||
uint8_t seed;
|
||||
int16_t scroll_offset;
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
uint8_t combo_progress;
|
||||
#endif
|
||||
} GlitchState;
|
||||
|
||||
static GlitchState g_state = {0};
|
||||
@@ -159,6 +163,7 @@ static void about_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
static bool about_input_callback(InputEvent* event, void* context) {
|
||||
furi_check(context);
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
ProtoPirateApp* app = context;
|
||||
|
||||
if(event->type != InputTypePress) {
|
||||
@@ -184,8 +189,13 @@ static bool about_input_callback(InputEvent* event, void* context) {
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
UNUSED(event);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
static void about_show_emulate_toggle_popup(ProtoPirateApp* app) {
|
||||
const bool now_enabled = app->emulate_feature_enabled;
|
||||
|
||||
@@ -204,6 +214,7 @@ static void about_show_emulate_toggle_popup(ProtoPirateApp* app) {
|
||||
dialog_message_show(app->dialogs, message);
|
||||
dialog_message_free(message);
|
||||
}
|
||||
#endif
|
||||
|
||||
void protopirate_scene_about_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
@@ -218,7 +229,9 @@ void protopirate_scene_about_on_enter(void* context) {
|
||||
g_state.frame = 0;
|
||||
g_state.seed = furi_get_tick() & 0xFF;
|
||||
g_state.scroll_offset = 0;
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
g_state.combo_progress = 0;
|
||||
#endif
|
||||
|
||||
view_set_draw_callback(app->view_about, about_draw_callback);
|
||||
view_set_input_callback(app->view_about, about_input_callback);
|
||||
@@ -245,7 +258,9 @@ bool protopirate_scene_about_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
view_commit_model(app->view_about, true);
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
}
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
else if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventAboutToggleEmulate) {
|
||||
app->emulate_feature_enabled = !app->emulate_feature_enabled;
|
||||
|
||||
@@ -262,6 +277,7 @@ bool protopirate_scene_about_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
@@ -1205,7 +1205,9 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
app);
|
||||
|
||||
ctx->signal_info_left_is_emulate = false;
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
bool left_button_used = false;
|
||||
#endif
|
||||
app->emulate_disabled_for_loaded = true;
|
||||
|
||||
// Store reference to history item's flipper format for saving
|
||||
@@ -1239,7 +1241,9 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
"Brute force",
|
||||
protopirate_scene_sub_decode_widget_callback,
|
||||
app);
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
left_button_used = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -3,6 +3,7 @@ import hashlib
|
||||
import os
|
||||
import struct
|
||||
import subprocess
|
||||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
from collections import defaultdict
|
||||
@@ -26,6 +27,10 @@ def replace_file_with_retry(source: str, target: str, attempts: int = 50) -> Non
|
||||
if attempt == attempts - 1:
|
||||
raise
|
||||
time.sleep(0.1)
|
||||
except OSError:
|
||||
shutil.copy2(source, target)
|
||||
os.remove(source)
|
||||
return
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -147,7 +152,7 @@ class Main(App):
|
||||
RelSection(section_name, section.name, unique_relocations)
|
||||
)
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
with tempfile.TemporaryDirectory(dir=os.path.dirname(os.path.abspath(fap_path))) as temp_dir:
|
||||
current_fap_path = fap_path
|
||||
|
||||
for section_index, section in enumerate(sections):
|
||||
|
||||
Reference in New Issue
Block a user