mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-24 03:29:57 -07:00
Merge remote-tracking branch 'ul/dev' into mntm-dev
This commit is contained in:
@@ -26,6 +26,8 @@
|
|||||||
- USB: Portal Of Flipper (by @Bettse & @sanjay900)
|
- USB: Portal Of Flipper (by @Bettse & @sanjay900)
|
||||||
- Sub-GHz:
|
- Sub-GHz:
|
||||||
- UL: Add ReversRB2/RB2M Protocol full support with add manually (by @xMasterX)
|
- UL: Add ReversRB2/RB2M Protocol full support with add manually (by @xMasterX)
|
||||||
|
- UL: Add Feron static 32-bit protocol full support (by @xMasterX)
|
||||||
|
- UL: Various bugfixes and experimental options, rolling counter overflow (by @xMasterX)
|
||||||
- OFW: Added support for 42-bit Prastel variation (by @pmazzini)
|
- OFW: Added support for 42-bit Prastel variation (by @pmazzini)
|
||||||
- RFID:
|
- RFID:
|
||||||
- OFW: EM4305 support (by @Astrrra)
|
- OFW: EM4305 support (by @Astrrra)
|
||||||
@@ -102,6 +104,7 @@
|
|||||||
- Split NfcProtocolSupport handlers into plugins for ~23kb less RAM usage (#396 by @Willy-JL)
|
- Split NfcProtocolSupport handlers into plugins for ~23kb less RAM usage (#396 by @Willy-JL)
|
||||||
- Enable Asset Packs in NFC app again due to reduced RAM usage (#396 by @Willy-JL)
|
- Enable Asset Packs in NFC app again due to reduced RAM usage (#396 by @Willy-JL)
|
||||||
- Improve loading of parser plugins (by @Willy-JL)
|
- Improve loading of parser plugins (by @Willy-JL)
|
||||||
|
- UL: Use default UL/UL-C pwd/key as default value for key input (by @mishamyte)
|
||||||
- OFW: Added naming for DESFire cards + fix MF3ICD40 cards unable to be read (by @Demae)
|
- OFW: Added naming for DESFire cards + fix MF3ICD40 cards unable to be read (by @Demae)
|
||||||
- OFW: FeliCa Protocol Expose Read Block API and Allow Specifying Service (by @zinongli)
|
- OFW: FeliCa Protocol Expose Read Block API and Allow Specifying Service (by @zinongli)
|
||||||
- OFW: Enable MFUL sync poller to be provided with passwords (by @GMMan)
|
- OFW: Enable MFUL sync poller to be provided with passwords (by @GMMan)
|
||||||
|
|||||||
@@ -453,7 +453,7 @@ static int32_t bad_usb_worker(void* context) {
|
|||||||
if(bad_usb->hid->is_connected(bad_usb->hid_inst)) {
|
if(bad_usb->hid->is_connected(bad_usb->hid_inst)) {
|
||||||
worker_state = BadUsbStateIdle; // Ready to run
|
worker_state = BadUsbStateIdle; // Ready to run
|
||||||
} else {
|
} else {
|
||||||
worker_state = BadUsbStateNotConnected; // USB not connected
|
worker_state = BadUsbStateNotConnected; // Not connected
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
worker_state = BadUsbStateScriptError; // Script preload error
|
worker_state = BadUsbStateScriptError; // Script preload error
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ void mf_ultralight_auth_free(MfUltralightAuth* instance) {
|
|||||||
void mf_ultralight_auth_reset(MfUltralightAuth* instance) {
|
void mf_ultralight_auth_reset(MfUltralightAuth* instance) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
|
uint32_t default_password = MF_ULTRALIGHT_DEFAULT_PASSWORD;
|
||||||
|
|
||||||
instance->type = MfUltralightAuthTypeNone;
|
instance->type = MfUltralightAuthTypeNone;
|
||||||
memset(&instance->password, 0, sizeof(MfUltralightAuthPassword));
|
memcpy(&instance->password, &default_password, sizeof(MfUltralightAuthPassword));
|
||||||
memset(&instance->tdes_key, 0, sizeof(MfUltralightC3DesAuthKey));
|
memcpy(&instance->tdes_key, MF_ULTRALIGHT_C_DEFAULT_KEY, sizeof(MfUltralightC3DesAuthKey));
|
||||||
memset(&instance->pack, 0, sizeof(MfUltralightAuthPack));
|
memset(&instance->pack, 0, sizeof(MfUltralightAuthPack));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,37 @@
|
|||||||
#include <cli/cli_main_commands.h>
|
#include <cli/cli_main_commands.h>
|
||||||
#include <lib/toolbox/args.h>
|
#include <lib/toolbox/args.h>
|
||||||
#include <lib/toolbox/hex.h>
|
#include <lib/toolbox/hex.h>
|
||||||
|
#include <lib/toolbox/bit_buffer.h>
|
||||||
|
#include <lib/nfc/nfc_poller.h>
|
||||||
|
#include <lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h>
|
||||||
|
#include <lib/nfc/protocols/iso14443_4b/iso14443_4b_poller.h>
|
||||||
|
#include <lib/nfc/protocols/iso15693_3/iso15693_3_poller.h>
|
||||||
#include <toolbox/pipe.h>
|
#include <toolbox/pipe.h>
|
||||||
|
|
||||||
#include <furi_hal_nfc.h>
|
#include <furi_hal_nfc.h>
|
||||||
|
|
||||||
#define FLAG_EVENT (1 << 10)
|
#define FLAG_EVENT (1 << 10)
|
||||||
|
|
||||||
|
#define NFC_MAX_BUFFER_SIZE (256)
|
||||||
|
#define NFC_BASE_PROTOCOL_MAX (3)
|
||||||
|
#define POLLER_DONE (1 << 0)
|
||||||
|
#define POLLER_ERR (1 << 1)
|
||||||
|
static NfcProtocol BASE_PROTOCOL[NFC_BASE_PROTOCOL_MAX] = {
|
||||||
|
NfcProtocolIso14443_4a,
|
||||||
|
NfcProtocolIso14443_4b,
|
||||||
|
NfcProtocolIso15693_3};
|
||||||
|
typedef struct ApduContext {
|
||||||
|
BitBuffer* tx_buffer;
|
||||||
|
BitBuffer* rx_buffer;
|
||||||
|
bool ready;
|
||||||
|
FuriThreadId thread_id;
|
||||||
|
} ApduContext;
|
||||||
|
|
||||||
static void nfc_cli_print_usage(void) {
|
static void nfc_cli_print_usage(void) {
|
||||||
printf("Usage:\r\n");
|
printf("Usage:\r\n");
|
||||||
printf("nfc <cmd>\r\n");
|
printf("nfc <cmd>\r\n");
|
||||||
printf("Cmd list:\r\n");
|
printf("Cmd list:\r\n");
|
||||||
|
printf("\tapdu\t - Send APDU and print response \r\n");
|
||||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||||
printf("\tfield\t - turn field on\r\n");
|
printf("\tfield\t - turn field on\r\n");
|
||||||
}
|
}
|
||||||
@@ -41,6 +62,144 @@ static void nfc_cli_field(PipeSide* pipe, FuriString* args) {
|
|||||||
furi_hal_nfc_release();
|
furi_hal_nfc_release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NfcCommand trx_callback(NfcGenericEvent event, void* context) {
|
||||||
|
furi_check(context);
|
||||||
|
ApduContext* apdu_context = (ApduContext*)context;
|
||||||
|
|
||||||
|
if(apdu_context->ready) {
|
||||||
|
apdu_context->ready = false;
|
||||||
|
if(NfcProtocolIso14443_4a == event.protocol) {
|
||||||
|
Iso14443_4aError err = iso14443_4a_poller_send_block(
|
||||||
|
event.instance, apdu_context->tx_buffer, apdu_context->rx_buffer);
|
||||||
|
if(Iso14443_4aErrorNone == err) {
|
||||||
|
furi_thread_flags_set(apdu_context->thread_id, POLLER_DONE);
|
||||||
|
return NfcCommandContinue;
|
||||||
|
} else {
|
||||||
|
furi_thread_flags_set(apdu_context->thread_id, POLLER_ERR);
|
||||||
|
return NfcCommandStop;
|
||||||
|
}
|
||||||
|
} else if(NfcProtocolIso14443_4b == event.protocol) {
|
||||||
|
Iso14443_4bError err = iso14443_4b_poller_send_block(
|
||||||
|
event.instance, apdu_context->tx_buffer, apdu_context->rx_buffer);
|
||||||
|
if(Iso14443_4bErrorNone == err) {
|
||||||
|
furi_thread_flags_set(apdu_context->thread_id, POLLER_DONE);
|
||||||
|
return NfcCommandContinue;
|
||||||
|
} else {
|
||||||
|
furi_thread_flags_set(apdu_context->thread_id, POLLER_ERR);
|
||||||
|
return NfcCommandStop;
|
||||||
|
}
|
||||||
|
} else if(NfcProtocolIso15693_3 == event.protocol) {
|
||||||
|
Iso15693_3Error err = iso15693_3_poller_send_frame(
|
||||||
|
event.instance,
|
||||||
|
apdu_context->tx_buffer,
|
||||||
|
apdu_context->rx_buffer,
|
||||||
|
ISO15693_3_FDT_POLL_FC);
|
||||||
|
if(Iso15693_3ErrorNone == err) {
|
||||||
|
furi_thread_flags_set(apdu_context->thread_id, POLLER_DONE);
|
||||||
|
return NfcCommandContinue;
|
||||||
|
} else {
|
||||||
|
furi_thread_flags_set(apdu_context->thread_id, POLLER_ERR);
|
||||||
|
return NfcCommandStop;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// should never reach here
|
||||||
|
furi_crash("Unknown protocol");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
furi_delay_ms(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NfcCommandContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nfc_cli_apdu(PipeSide* pipe, FuriString* args) {
|
||||||
|
UNUSED(pipe);
|
||||||
|
Nfc* nfc = NULL;
|
||||||
|
NfcPoller* poller = NULL;
|
||||||
|
FuriString* data = furi_string_alloc();
|
||||||
|
uint8_t* req_buffer = NULL;
|
||||||
|
uint8_t* resp_buffer = NULL;
|
||||||
|
size_t apdu_size = 0;
|
||||||
|
size_t resp_size = 0;
|
||||||
|
NfcProtocol current_protocol = NfcProtocolInvalid;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(0 == args_get_first_word_length(args)) {
|
||||||
|
printf(
|
||||||
|
"Use like `nfc apdu 00a404000e325041592e5359532e444446303100 00a4040008a0000003010102` \r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nfc = nfc_alloc();
|
||||||
|
|
||||||
|
printf("detecting tag\r\n");
|
||||||
|
for(int i = 0; i < NFC_BASE_PROTOCOL_MAX; i++) {
|
||||||
|
poller = nfc_poller_alloc(nfc, BASE_PROTOCOL[i]);
|
||||||
|
bool is_detected = nfc_poller_detect(poller);
|
||||||
|
nfc_poller_free(poller);
|
||||||
|
if(is_detected) {
|
||||||
|
current_protocol = BASE_PROTOCOL[i];
|
||||||
|
printf("detected tag:%d\r\n", BASE_PROTOCOL[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(NfcProtocolInvalid == current_protocol) {
|
||||||
|
nfc_free(nfc);
|
||||||
|
printf("Can not find any tag\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
poller = nfc_poller_alloc(nfc, current_protocol);
|
||||||
|
ApduContext* apdu_context = malloc(sizeof(ApduContext));
|
||||||
|
apdu_context->tx_buffer = bit_buffer_alloc(NFC_MAX_BUFFER_SIZE);
|
||||||
|
apdu_context->rx_buffer = bit_buffer_alloc(NFC_MAX_BUFFER_SIZE);
|
||||||
|
apdu_context->ready = false;
|
||||||
|
apdu_context->thread_id = furi_thread_get_current_id();
|
||||||
|
|
||||||
|
nfc_poller_start(poller, trx_callback, apdu_context);
|
||||||
|
while(args_read_string_and_trim(args, data)) {
|
||||||
|
bit_buffer_reset(apdu_context->tx_buffer);
|
||||||
|
bit_buffer_reset(apdu_context->rx_buffer);
|
||||||
|
apdu_size = furi_string_size(data) / 2;
|
||||||
|
req_buffer = malloc(apdu_size);
|
||||||
|
|
||||||
|
hex_chars_to_uint8(furi_string_get_cstr(data), req_buffer);
|
||||||
|
printf("Sending APDU:%s to Tag\r\n", furi_string_get_cstr(data));
|
||||||
|
bit_buffer_copy_bytes(apdu_context->tx_buffer, req_buffer, apdu_size);
|
||||||
|
apdu_context->ready = true;
|
||||||
|
uint32_t flags = furi_thread_flags_wait(POLLER_DONE, FuriFlagWaitAny, 3000);
|
||||||
|
if(0 == (flags & POLLER_DONE)) {
|
||||||
|
printf("Error or Timeout");
|
||||||
|
free(req_buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
furi_assert(apdu_context->ready == false);
|
||||||
|
resp_size = bit_buffer_get_size_bytes(apdu_context->rx_buffer) * 2;
|
||||||
|
if(!resp_size) {
|
||||||
|
printf("No response\r\n");
|
||||||
|
free(req_buffer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
resp_buffer = malloc(resp_size);
|
||||||
|
uint8_to_hex_chars(
|
||||||
|
bit_buffer_get_data(apdu_context->rx_buffer), resp_buffer, resp_size);
|
||||||
|
resp_buffer[resp_size] = 0;
|
||||||
|
printf("Response: %s\r\n", resp_buffer);
|
||||||
|
|
||||||
|
free(req_buffer);
|
||||||
|
free(resp_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_poller_stop(poller);
|
||||||
|
nfc_poller_free(poller);
|
||||||
|
nfc_free(nfc);
|
||||||
|
|
||||||
|
bit_buffer_free(apdu_context->tx_buffer);
|
||||||
|
bit_buffer_free(apdu_context->rx_buffer);
|
||||||
|
free(apdu_context);
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
furi_string_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
static void execute(PipeSide* pipe, FuriString* args, void* context) {
|
static void execute(PipeSide* pipe, FuriString* args, void* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
FuriString* cmd;
|
FuriString* cmd;
|
||||||
@@ -51,6 +210,10 @@ static void execute(PipeSide* pipe, FuriString* args, void* context) {
|
|||||||
nfc_cli_print_usage();
|
nfc_cli_print_usage();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(furi_string_cmp_str(cmd, "apdu") == 0) {
|
||||||
|
nfc_cli_apdu(pipe, args);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||||
if(furi_string_cmp_str(cmd, "field") == 0) {
|
if(furi_string_cmp_str(cmd, "field") == 0) {
|
||||||
nfc_cli_field(pipe, args);
|
nfc_cli_field(pipe, args);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const char* const gps_text[GPS_COUNT] = {
|
|||||||
"115200",
|
"115200",
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEBUG_COUNTER_COUNT 13
|
#define DEBUG_COUNTER_COUNT 16
|
||||||
const char* const debug_counter_text[DEBUG_COUNTER_COUNT] = {
|
const char* const debug_counter_text[DEBUG_COUNTER_COUNT] = {
|
||||||
"+1",
|
"+1",
|
||||||
"+2",
|
"+2",
|
||||||
@@ -44,21 +44,26 @@ const char* const debug_counter_text[DEBUG_COUNTER_COUNT] = {
|
|||||||
"+4",
|
"+4",
|
||||||
"+5",
|
"+5",
|
||||||
"+10",
|
"+10",
|
||||||
"0",
|
"+50",
|
||||||
|
"OVFL",
|
||||||
|
"No",
|
||||||
"-1",
|
"-1",
|
||||||
"-2",
|
"-2",
|
||||||
"-3",
|
"-3",
|
||||||
"-4",
|
"-4",
|
||||||
"-5",
|
"-5",
|
||||||
"-10",
|
"-10",
|
||||||
|
"-50",
|
||||||
};
|
};
|
||||||
const uint32_t debug_counter_val[DEBUG_COUNTER_COUNT] = {
|
const int32_t debug_counter_val[DEBUG_COUNTER_COUNT] = {
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
3,
|
3,
|
||||||
4,
|
4,
|
||||||
5,
|
5,
|
||||||
10,
|
10,
|
||||||
|
50,
|
||||||
|
65535,
|
||||||
0,
|
0,
|
||||||
-1,
|
-1,
|
||||||
-2,
|
-2,
|
||||||
@@ -66,6 +71,7 @@ const uint32_t debug_counter_val[DEBUG_COUNTER_COUNT] = {
|
|||||||
-4,
|
-4,
|
||||||
-5,
|
-5,
|
||||||
-10,
|
-10,
|
||||||
|
-50,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void subghz_scene_radio_settings_set_device(VariableItem* item) {
|
static void subghz_scene_radio_settings_set_device(VariableItem* item) {
|
||||||
@@ -149,7 +155,7 @@ void subghz_scene_radio_settings_on_enter(void* context) {
|
|||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
|
|
||||||
VariableItemList* variable_item_list = subghz->variable_item_list;
|
VariableItemList* variable_item_list = subghz->variable_item_list;
|
||||||
uint8_t value_index;
|
int32_t value_index;
|
||||||
VariableItem* item;
|
VariableItem* item;
|
||||||
|
|
||||||
uint8_t value_count_device = RADIO_DEVICE_COUNT;
|
uint8_t value_count_device = RADIO_DEVICE_COUNT;
|
||||||
@@ -196,7 +202,7 @@ void subghz_scene_radio_settings_on_enter(void* context) {
|
|||||||
furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) ? DEBUG_COUNTER_COUNT : 3,
|
furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) ? DEBUG_COUNTER_COUNT : 3,
|
||||||
subghz_scene_receiver_config_set_debug_counter,
|
subghz_scene_receiver_config_set_debug_counter,
|
||||||
subghz);
|
subghz);
|
||||||
value_index = value_index_uint32(
|
value_index = value_index_int32(
|
||||||
furi_hal_subghz_get_rolling_counter_mult(),
|
furi_hal_subghz_get_rolling_counter_mult(),
|
||||||
debug_counter_val,
|
debug_counter_val,
|
||||||
furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) ? DEBUG_COUNTER_COUNT : 3);
|
furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) ? DEBUG_COUNTER_COUNT : 3);
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
|
|||||||
subghz_txrx_stop(subghz->txrx);
|
subghz_txrx_stop(subghz->txrx);
|
||||||
if(subghz_custom_btn_get() != SUBGHZ_CUSTOM_BTN_OK) {
|
if(subghz_custom_btn_get() != SUBGHZ_CUSTOM_BTN_OK) {
|
||||||
subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK);
|
subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK);
|
||||||
int8_t tmp_counter = furi_hal_subghz_get_rolling_counter_mult();
|
int32_t tmp_counter = furi_hal_subghz_get_rolling_counter_mult();
|
||||||
furi_hal_subghz_set_rolling_counter_mult(0);
|
furi_hal_subghz_set_rolling_counter_mult(0);
|
||||||
// Calling restore!
|
// Calling restore!
|
||||||
subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx));
|
subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx));
|
||||||
|
|||||||
@@ -816,7 +816,6 @@ void subghz_cli_command_tx_from_file(PipeSide* pipe, FuriString* args, void* con
|
|||||||
subghz_devices_deinit();
|
subghz_devices_deinit();
|
||||||
// Reset custom settings
|
// Reset custom settings
|
||||||
subghz_environment_reset_keeloq(environment);
|
subghz_environment_reset_keeloq(environment);
|
||||||
faac_slh_reset_prog_mode();
|
|
||||||
subghz_custom_btns_reset();
|
subghz_custom_btns_reset();
|
||||||
// Free environment
|
// Free environment
|
||||||
subghz_environment_free(environment);
|
subghz_environment_free(environment);
|
||||||
@@ -1117,7 +1116,8 @@ static void subghz_cli_command_chat(PipeSide* pipe, FuriString* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void execute(PipeSide* pipe, FuriString* args, void* context) {
|
static void execute(PipeSide* pipe, FuriString* args, void* context) {
|
||||||
FuriString* cmd = furi_string_alloc();
|
FuriString* cmd;
|
||||||
|
cmd = furi_string_alloc();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!args_read_string_and_trim(args, cmd)) {
|
if(!args_read_string_and_trim(args, cmd)) {
|
||||||
|
|||||||
@@ -501,7 +501,10 @@ void submenu_process_ok(Submenu* submenu, InputType input_type) {
|
|||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
|
|
||||||
if(!item || item->locked) return;
|
if(!item) return;
|
||||||
|
if(item->locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!item->has_extended_events && input_type == InputTypeShort && item->callback) {
|
if(!item->has_extended_events && input_type == InputTypeShort && item->callback) {
|
||||||
item->callback(item->callback_context, item->index);
|
item->callback(item->callback_context, item->index);
|
||||||
|
|||||||
@@ -54,22 +54,6 @@ void submenu_add_item(
|
|||||||
SubmenuItemCallback callback,
|
SubmenuItemCallback callback,
|
||||||
void* callback_context);
|
void* callback_context);
|
||||||
|
|
||||||
/** Add item to submenu with extended press events
|
|
||||||
*
|
|
||||||
* @param submenu Submenu instance
|
|
||||||
* @param label menu item label
|
|
||||||
* @param index menu item index, used for callback, may be
|
|
||||||
* the same with other items
|
|
||||||
* @param callback menu item extended callback
|
|
||||||
* @param callback_context menu item callback context
|
|
||||||
*/
|
|
||||||
void submenu_add_item_ex(
|
|
||||||
Submenu* submenu,
|
|
||||||
const char* label,
|
|
||||||
uint32_t index,
|
|
||||||
SubmenuItemCallbackEx callback,
|
|
||||||
void* callback_context);
|
|
||||||
|
|
||||||
/** Add lockable item to submenu
|
/** Add lockable item to submenu
|
||||||
*
|
*
|
||||||
* @param submenu Submenu instance
|
* @param submenu Submenu instance
|
||||||
@@ -90,6 +74,22 @@ void submenu_add_lockable_item(
|
|||||||
bool locked,
|
bool locked,
|
||||||
const char* locked_message);
|
const char* locked_message);
|
||||||
|
|
||||||
|
/** Add item to submenu with extended press events
|
||||||
|
*
|
||||||
|
* @param submenu Submenu instance
|
||||||
|
* @param label menu item label
|
||||||
|
* @param index menu item index, used for callback, may be
|
||||||
|
* the same with other items
|
||||||
|
* @param callback menu item extended callback
|
||||||
|
* @param callback_context menu item callback context
|
||||||
|
*/
|
||||||
|
void submenu_add_item_ex(
|
||||||
|
Submenu* submenu,
|
||||||
|
const char* label,
|
||||||
|
uint32_t index,
|
||||||
|
SubmenuItemCallbackEx callback,
|
||||||
|
void* callback_context);
|
||||||
|
|
||||||
/** Change label of an existing item
|
/** Change label of an existing item
|
||||||
*
|
*
|
||||||
* @param submenu Submenu instance
|
* @param submenu Submenu instance
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal_gpio.h>
|
#include <furi_hal_gpio.h>
|
||||||
|
#include <furi_hal_vibro.h>
|
||||||
#include <toolbox/cli/cli_command.h>
|
#include <toolbox/cli/cli_command.h>
|
||||||
#include <cli/cli_main_commands.h>
|
#include <cli/cli_main_commands.h>
|
||||||
#include <toolbox/pipe.h>
|
#include <toolbox/pipe.h>
|
||||||
#include <furi_hal_vibro.h>
|
|
||||||
|
|
||||||
#define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2)
|
#define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2)
|
||||||
#define INPUT_PRESS_TICKS 150
|
#define INPUT_PRESS_TICKS 150
|
||||||
@@ -155,8 +155,10 @@ int32_t input_srv(void* p) {
|
|||||||
// Send Press/Release event
|
// Send Press/Release event
|
||||||
event.type = pin_states[i].state ? InputTypePress : InputTypeRelease;
|
event.type = pin_states[i].state ? InputTypePress : InputTypeRelease;
|
||||||
furi_pubsub_publish(event_pubsub, &event);
|
furi_pubsub_publish(event_pubsub, &event);
|
||||||
// do vibro if user setup vibro touch level in Settings-Input.
|
// vibro signal if user setup vibro touch level in Settings-Input.
|
||||||
if(settings->vibro_touch_level) {
|
if(settings->vibro_touch_level) {
|
||||||
|
//delay 1 ticks for compatibility with rgb_backlight_mod
|
||||||
|
furi_delay_tick(1);
|
||||||
furi_hal_vibro_on(true);
|
furi_hal_vibro_on(true);
|
||||||
furi_delay_tick(settings->vibro_touch_level);
|
furi_delay_tick(settings->vibro_touch_level);
|
||||||
furi_hal_vibro_on(false);
|
furi_hal_vibro_on(false);
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ void input_settings_load(InputSettings* settings) {
|
|||||||
sizeof(InputSettings),
|
sizeof(InputSettings),
|
||||||
INPUT_SETTINGS_MAGIC,
|
INPUT_SETTINGS_MAGIC,
|
||||||
INPUT_SETTINGS_VER);
|
INPUT_SETTINGS_VER);
|
||||||
// if config previous version - load it and inicialize new settings
|
|
||||||
}
|
}
|
||||||
// in case of another config version we exit from useless cycle to next step
|
// in case of another config version we exit from useless cycle to next step
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|||||||
@@ -388,13 +388,18 @@ static void power_handle_reboot(PowerBootMode mode) {
|
|||||||
|
|
||||||
//start furi timer for autopoweroff
|
//start furi timer for autopoweroff
|
||||||
static void power_start_auto_poweroff_timer(Power* power) {
|
static void power_start_auto_poweroff_timer(Power* power) {
|
||||||
|
if(furi_timer_is_running(power->auto_poweroff_timer)) {
|
||||||
|
furi_timer_stop(power->auto_poweroff_timer);
|
||||||
|
}
|
||||||
furi_timer_start(
|
furi_timer_start(
|
||||||
power->auto_poweroff_timer, furi_ms_to_ticks(power->settings.auto_poweroff_delay_ms));
|
power->auto_poweroff_timer, furi_ms_to_ticks(power->settings.auto_poweroff_delay_ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
//stop furi timer for autopoweroff
|
//stop furi timer for autopoweroff
|
||||||
static void power_stop_auto_poweroff_timer(Power* power) {
|
static void power_stop_auto_poweroff_timer(Power* power) {
|
||||||
furi_timer_stop(power->auto_poweroff_timer);
|
if(furi_timer_is_running(power->auto_poweroff_timer)) {
|
||||||
|
furi_timer_stop(power->auto_poweroff_timer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t power_is_running_auto_poweroff_timer(Power* power) {
|
static uint32_t power_is_running_auto_poweroff_timer(Power* power) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ App(
|
|||||||
"passport",
|
"passport",
|
||||||
"system_settings",
|
"system_settings",
|
||||||
"clock_settings",
|
"clock_settings",
|
||||||
|
"input_settings",
|
||||||
"about",
|
"about",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ extern "C" {
|
|||||||
#define MF_ULTRALIGHT_TEARING_FLAG_NUM (3)
|
#define MF_ULTRALIGHT_TEARING_FLAG_NUM (3)
|
||||||
#define MF_ULTRALIGHT_AUTH_PASSWORD_SIZE (4)
|
#define MF_ULTRALIGHT_AUTH_PASSWORD_SIZE (4)
|
||||||
#define MF_ULTRALIGHT_AUTH_PACK_SIZE (2)
|
#define MF_ULTRALIGHT_AUTH_PACK_SIZE (2)
|
||||||
|
#define MF_ULTRALIGHT_DEFAULT_PASSWORD (0xffffffffUL)
|
||||||
|
|
||||||
#define MF_ULTRALIGHT_C_AUTH_RESPONSE_SIZE (9)
|
#define MF_ULTRALIGHT_C_AUTH_RESPONSE_SIZE (9)
|
||||||
#define MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE (16)
|
#define MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE (16)
|
||||||
@@ -47,6 +48,11 @@ extern "C" {
|
|||||||
#define MF_ULTRALIGHT_C_AUTH_RND_A_BLOCK_OFFSET (0)
|
#define MF_ULTRALIGHT_C_AUTH_RND_A_BLOCK_OFFSET (0)
|
||||||
#define MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET (8)
|
#define MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET (8)
|
||||||
#define MF_ULTRALIGHT_C_ENCRYPTED_PACK_SIZE (MF_ULTRALIGHT_C_AUTH_DATA_SIZE + 1)
|
#define MF_ULTRALIGHT_C_ENCRYPTED_PACK_SIZE (MF_ULTRALIGHT_C_AUTH_DATA_SIZE + 1)
|
||||||
|
#define MF_ULTRALIGHT_C_DEFAULT_KEY \
|
||||||
|
(uint8_t[]) { \
|
||||||
|
0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, \
|
||||||
|
0x46 \
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MfUltralightErrorNone,
|
MfUltralightErrorNone,
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ extern "C" {
|
|||||||
#define MF_ULTRALIGHT_POLLER_STANDARD_FWT_FC (60000)
|
#define MF_ULTRALIGHT_POLLER_STANDARD_FWT_FC (60000)
|
||||||
#define MF_ULTRALIGHT_MAX_BUFF_SIZE (64)
|
#define MF_ULTRALIGHT_MAX_BUFF_SIZE (64)
|
||||||
|
|
||||||
#define MF_ULTRALIGHT_DEFAULT_PASSWORD (0xffffffffUL)
|
|
||||||
|
|
||||||
#define MF_ULTRALIGHT_IS_NTAG_I2C(type) \
|
#define MF_ULTRALIGHT_IS_NTAG_I2C(type) \
|
||||||
(((type) == MfUltralightTypeNTAGI2C1K) || ((type) == MfUltralightTypeNTAGI2C2K) || \
|
(((type) == MfUltralightTypeNTAGI2C1K) || ((type) == MfUltralightTypeNTAGI2C2K) || \
|
||||||
((type) == MfUltralightTypeNTAGI2CPlus1K) || ((type) == MfUltralightTypeNTAGI2CPlus2K))
|
((type) == MfUltralightTypeNTAGI2CPlus1K) || ((type) == MfUltralightTypeNTAGI2CPlus2K))
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ static bool subghz_protocol_alutech_at_4n_gen_data(
|
|||||||
} else {
|
} else {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
}
|
}
|
||||||
} else if(instance->generic.cnt >= 0xFFFF) {
|
} else if((instance->generic.cnt >= 0xFFFF) && (furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
instance->generic.cnt = 0;
|
instance->generic.cnt = 0;
|
||||||
}
|
}
|
||||||
crc = subghz_protocol_alutech_at_4n_decrypt_data_crc((uint8_t)(instance->generic.cnt & 0xFF));
|
crc = subghz_protocol_alutech_at_4n_decrypt_data_crc((uint8_t)(instance->generic.cnt & 0xFF));
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ static void subghz_protocol_encoder_came_atomo_get_upload(
|
|||||||
} else {
|
} else {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
}
|
}
|
||||||
} else if(instance->generic.cnt >= 0xFFFF) {
|
} else if((instance->generic.cnt >= 0xFFFF) && (furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
instance->generic.cnt = 0;
|
instance->generic.cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,9 +142,40 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
|
|||||||
data_prg[0] = 0x00;
|
data_prg[0] = 0x00;
|
||||||
|
|
||||||
if(allow_zero_seed || (instance->generic.seed != 0x0)) {
|
if(allow_zero_seed || (instance->generic.seed != 0x0)) {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
if(!(furi_hal_subghz_get_rolling_counter_mult() >= 0xFFFF)) {
|
||||||
|
if(instance->generic.cnt < 0xFFFFF) {
|
||||||
|
if((instance->generic.cnt + furi_hal_subghz_get_rolling_counter_mult()) >
|
||||||
|
0xFFFFF) {
|
||||||
|
instance->generic.cnt = 0;
|
||||||
|
} else {
|
||||||
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
|
}
|
||||||
|
} else if(
|
||||||
|
(instance->generic.cnt >= 0xFFFFF) &&
|
||||||
|
(furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
|
instance->generic.cnt = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
instance->generic.cnt += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if(temp_counter_backup != 0x0) {
|
if(temp_counter_backup != 0x0) {
|
||||||
temp_counter_backup += furi_hal_subghz_get_rolling_counter_mult();
|
if(!(furi_hal_subghz_get_rolling_counter_mult() >= 0xFFFF)) {
|
||||||
|
if(temp_counter_backup < 0xFFFFF) {
|
||||||
|
if((temp_counter_backup + furi_hal_subghz_get_rolling_counter_mult()) >
|
||||||
|
0xFFFFF) {
|
||||||
|
temp_counter_backup = 0;
|
||||||
|
} else {
|
||||||
|
temp_counter_backup += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
|
}
|
||||||
|
} else if(
|
||||||
|
(temp_counter_backup >= 0xFFFFF) &&
|
||||||
|
(furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
|
temp_counter_backup = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
temp_counter_backup += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +226,9 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
|
|||||||
(temp_fix_backup != 0x0) && !faac_prog_mode) {
|
(temp_fix_backup != 0x0) && !faac_prog_mode) {
|
||||||
instance->generic.serial = temp_fix_backup >> 4;
|
instance->generic.serial = temp_fix_backup >> 4;
|
||||||
instance->generic.btn = temp_fix_backup & 0xF;
|
instance->generic.btn = temp_fix_backup & 0xF;
|
||||||
instance->generic.cnt = temp_counter_backup;
|
if(temp_counter_backup != 0x0) {
|
||||||
|
instance->generic.cnt = temp_counter_backup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uint32_t fix = instance->generic.serial << 4 | instance->generic.btn;
|
uint32_t fix = instance->generic.serial << 4 | instance->generic.btn;
|
||||||
uint32_t hop = 0;
|
uint32_t hop = 0;
|
||||||
@@ -209,7 +242,32 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(allow_zero_seed || (instance->generic.seed != 0x0)) {
|
if(allow_zero_seed || (instance->generic.seed != 0x0)) {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
if(!(furi_hal_subghz_get_rolling_counter_mult() >= 0xFFFF)) {
|
||||||
|
if(instance->generic.cnt < 0xFFFFF) {
|
||||||
|
if((instance->generic.cnt + furi_hal_subghz_get_rolling_counter_mult()) >
|
||||||
|
0xFFFFF) {
|
||||||
|
instance->generic.cnt = 0;
|
||||||
|
} else {
|
||||||
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
|
}
|
||||||
|
} else if(
|
||||||
|
(instance->generic.cnt >= 0xFFFFF) &&
|
||||||
|
(furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
|
instance->generic.cnt = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(instance->generic.cnt < 0xFFFFF) {
|
||||||
|
if((instance->generic.cnt + 0xFFFFF) > 0xFFFFF) {
|
||||||
|
instance->generic.cnt = 0;
|
||||||
|
} else {
|
||||||
|
instance->generic.cnt += 0xFFFFF;
|
||||||
|
}
|
||||||
|
} else if(
|
||||||
|
(instance->generic.cnt >= 0xFFFFF) &&
|
||||||
|
(furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
|
instance->generic.cnt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((instance->generic.cnt % 2) == 0) {
|
if((instance->generic.cnt % 2) == 0) {
|
||||||
@@ -250,7 +308,7 @@ bool subghz_protocol_faac_slh_create_data(
|
|||||||
const char* manufacture_name,
|
const char* manufacture_name,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
// roguemaster don't steal!!!
|
// OwO
|
||||||
SubGhzProtocolEncoderFaacSLH* instance = context;
|
SubGhzProtocolEncoderFaacSLH* instance = context;
|
||||||
instance->generic.serial = serial;
|
instance->generic.serial = serial;
|
||||||
instance->generic.btn = btn;
|
instance->generic.btn = btn;
|
||||||
|
|||||||
352
lib/subghz/protocols/feron.c
Normal file
352
lib/subghz/protocols/feron.c
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
#include "feron.h"
|
||||||
|
#include "../blocks/const.h"
|
||||||
|
#include "../blocks/decoder.h"
|
||||||
|
#include "../blocks/encoder.h"
|
||||||
|
#include "../blocks/generic.h"
|
||||||
|
#include "../blocks/math.h"
|
||||||
|
|
||||||
|
#define TAG "SubGhzProtocolFeron"
|
||||||
|
|
||||||
|
static const SubGhzBlockConst subghz_protocol_feron_const = {
|
||||||
|
.te_short = 350,
|
||||||
|
.te_long = 750,
|
||||||
|
.te_delta = 150,
|
||||||
|
.min_count_bit_for_found = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubGhzProtocolDecoderFeron {
|
||||||
|
SubGhzProtocolDecoderBase base;
|
||||||
|
|
||||||
|
SubGhzBlockDecoder decoder;
|
||||||
|
SubGhzBlockGeneric generic;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubGhzProtocolEncoderFeron {
|
||||||
|
SubGhzProtocolEncoderBase base;
|
||||||
|
|
||||||
|
SubGhzProtocolBlockEncoder encoder;
|
||||||
|
SubGhzBlockGeneric generic;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FeronDecoderStepReset = 0,
|
||||||
|
FeronDecoderStepSaveDuration,
|
||||||
|
FeronDecoderStepCheckDuration,
|
||||||
|
} FeronDecoderStep;
|
||||||
|
|
||||||
|
const SubGhzProtocolDecoder subghz_protocol_feron_decoder = {
|
||||||
|
.alloc = subghz_protocol_decoder_feron_alloc,
|
||||||
|
.free = subghz_protocol_decoder_feron_free,
|
||||||
|
|
||||||
|
.feed = subghz_protocol_decoder_feron_feed,
|
||||||
|
.reset = subghz_protocol_decoder_feron_reset,
|
||||||
|
|
||||||
|
.get_hash_data = NULL,
|
||||||
|
.get_hash_data_long = subghz_protocol_decoder_feron_get_hash_data,
|
||||||
|
.serialize = subghz_protocol_decoder_feron_serialize,
|
||||||
|
.deserialize = subghz_protocol_decoder_feron_deserialize,
|
||||||
|
.get_string = subghz_protocol_decoder_feron_get_string,
|
||||||
|
.get_string_brief = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGhzProtocolEncoder subghz_protocol_feron_encoder = {
|
||||||
|
.alloc = subghz_protocol_encoder_feron_alloc,
|
||||||
|
.free = subghz_protocol_encoder_feron_free,
|
||||||
|
|
||||||
|
.deserialize = subghz_protocol_encoder_feron_deserialize,
|
||||||
|
.stop = subghz_protocol_encoder_feron_stop,
|
||||||
|
.yield = subghz_protocol_encoder_feron_yield,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGhzProtocol subghz_protocol_feron = {
|
||||||
|
.name = SUBGHZ_PROTOCOL_FERON_NAME,
|
||||||
|
.type = SubGhzProtocolTypeStatic,
|
||||||
|
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
|
||||||
|
SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
|
||||||
|
|
||||||
|
.decoder = &subghz_protocol_feron_decoder,
|
||||||
|
.encoder = &subghz_protocol_feron_encoder,
|
||||||
|
};
|
||||||
|
|
||||||
|
void* subghz_protocol_encoder_feron_alloc(SubGhzEnvironment* environment) {
|
||||||
|
UNUSED(environment);
|
||||||
|
SubGhzProtocolEncoderFeron* instance = malloc(sizeof(SubGhzProtocolEncoderFeron));
|
||||||
|
|
||||||
|
instance->base.protocol = &subghz_protocol_feron;
|
||||||
|
instance->generic.protocol_name = instance->base.protocol->name;
|
||||||
|
|
||||||
|
instance->encoder.repeat = 10;
|
||||||
|
instance->encoder.size_upload = 256;
|
||||||
|
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
|
||||||
|
instance->encoder.is_running = false;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_encoder_feron_free(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolEncoderFeron* instance = context;
|
||||||
|
free(instance->encoder.upload);
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generating an upload from data.
|
||||||
|
* @param instance Pointer to a SubGhzProtocolEncoderFeron instance
|
||||||
|
*/
|
||||||
|
static void subghz_protocol_encoder_feron_get_upload(SubGhzProtocolEncoderFeron* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
// Send key and GAP
|
||||||
|
for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
|
||||||
|
if(bit_read(instance->generic.data, i - 1)) {
|
||||||
|
// Send bit 1
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(true, (uint32_t)subghz_protocol_feron_const.te_long);
|
||||||
|
if(i == 1) {
|
||||||
|
//Send 500/500 and gap if bit was last
|
||||||
|
instance->encoder.upload[index++] = level_duration_make(
|
||||||
|
false, (uint32_t)subghz_protocol_feron_const.te_short + 150);
|
||||||
|
instance->encoder.upload[index++] = level_duration_make(
|
||||||
|
true, (uint32_t)subghz_protocol_feron_const.te_short + 150);
|
||||||
|
// Gap
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(false, (uint32_t)subghz_protocol_feron_const.te_long * 6);
|
||||||
|
} else {
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(false, (uint32_t)subghz_protocol_feron_const.te_short);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Send bit 0
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(true, (uint32_t)subghz_protocol_feron_const.te_short);
|
||||||
|
if(i == 1) {
|
||||||
|
//Send 500/500 and gap if bit was last
|
||||||
|
instance->encoder.upload[index++] = level_duration_make(
|
||||||
|
false, (uint32_t)subghz_protocol_feron_const.te_short + 150);
|
||||||
|
instance->encoder.upload[index++] = level_duration_make(
|
||||||
|
true, (uint32_t)subghz_protocol_feron_const.te_short + 150);
|
||||||
|
// Gap
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(false, (uint32_t)subghz_protocol_feron_const.te_long * 6);
|
||||||
|
} else {
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(false, (uint32_t)subghz_protocol_feron_const.te_long);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->encoder.size_upload = index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analysis of received data
|
||||||
|
* @param instance Pointer to a SubGhzBlockGeneric* instance
|
||||||
|
*/
|
||||||
|
static void subghz_protocol_feron_check_remote_controller(SubGhzBlockGeneric* instance) {
|
||||||
|
instance->serial = instance->data >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubGhzProtocolStatus
|
||||||
|
subghz_protocol_encoder_feron_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolEncoderFeron* instance = context;
|
||||||
|
SubGhzProtocolStatus ret = SubGhzProtocolStatusError;
|
||||||
|
do {
|
||||||
|
ret = subghz_block_generic_deserialize_check_count_bit(
|
||||||
|
&instance->generic,
|
||||||
|
flipper_format,
|
||||||
|
subghz_protocol_feron_const.min_count_bit_for_found);
|
||||||
|
if(ret != SubGhzProtocolStatusOk) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//optional parameter parameter
|
||||||
|
flipper_format_read_uint32(
|
||||||
|
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
|
||||||
|
|
||||||
|
subghz_protocol_feron_check_remote_controller(&instance->generic);
|
||||||
|
subghz_protocol_encoder_feron_get_upload(instance);
|
||||||
|
instance->encoder.is_running = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_encoder_feron_stop(void* context) {
|
||||||
|
SubGhzProtocolEncoderFeron* instance = context;
|
||||||
|
instance->encoder.is_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelDuration subghz_protocol_encoder_feron_yield(void* context) {
|
||||||
|
SubGhzProtocolEncoderFeron* instance = context;
|
||||||
|
|
||||||
|
if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
|
||||||
|
instance->encoder.is_running = false;
|
||||||
|
return level_duration_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||||
|
|
||||||
|
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||||
|
instance->encoder.repeat--;
|
||||||
|
instance->encoder.front = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* subghz_protocol_decoder_feron_alloc(SubGhzEnvironment* environment) {
|
||||||
|
UNUSED(environment);
|
||||||
|
SubGhzProtocolDecoderFeron* instance = malloc(sizeof(SubGhzProtocolDecoderFeron));
|
||||||
|
instance->base.protocol = &subghz_protocol_feron;
|
||||||
|
instance->generic.protocol_name = instance->base.protocol->name;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_decoder_feron_free(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFeron* instance = context;
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_decoder_feron_reset(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFeron* instance = context;
|
||||||
|
instance->decoder.parser_step = FeronDecoderStepReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_decoder_feron_feed(void* context, bool level, volatile uint32_t duration) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFeron* instance = context;
|
||||||
|
|
||||||
|
// Feron Decoder
|
||||||
|
// 2025.04 - @xMasterX (MMX)
|
||||||
|
|
||||||
|
// Key samples
|
||||||
|
/*
|
||||||
|
0110001100111000 1000010101111010 - ON
|
||||||
|
0110001100111000 1000010001111011 - OFF
|
||||||
|
|
||||||
|
0110001100111000 1000011001111001 - brightness up
|
||||||
|
0110001100111000 1000011101111000 - brightness down
|
||||||
|
|
||||||
|
0110001100111000 1000001001111101 - scroll mode command
|
||||||
|
|
||||||
|
------------------------------------------
|
||||||
|
0110001100111000 0111000010001111 - R
|
||||||
|
0110001100111000 0001101011100101 - B
|
||||||
|
0110001100111000 0100000010111111 - G
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch(instance->decoder.parser_step) {
|
||||||
|
case FeronDecoderStepReset:
|
||||||
|
if((!level) && (DURATION_DIFF(duration, subghz_protocol_feron_const.te_long * 6) <
|
||||||
|
subghz_protocol_feron_const.te_delta * 4)) {
|
||||||
|
//Found GAP
|
||||||
|
instance->decoder.decode_data = 0;
|
||||||
|
instance->decoder.decode_count_bit = 0;
|
||||||
|
instance->decoder.parser_step = FeronDecoderStepSaveDuration;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FeronDecoderStepSaveDuration:
|
||||||
|
if(level) {
|
||||||
|
instance->decoder.te_last = duration;
|
||||||
|
instance->decoder.parser_step = FeronDecoderStepCheckDuration;
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = FeronDecoderStepReset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FeronDecoderStepCheckDuration:
|
||||||
|
if(!level) {
|
||||||
|
// Bit 0 is short and long timing = 350us HIGH (te_last) and 750us LOW
|
||||||
|
if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_feron_const.te_short) <
|
||||||
|
subghz_protocol_feron_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, subghz_protocol_feron_const.te_long) <
|
||||||
|
subghz_protocol_feron_const.te_delta)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||||
|
instance->decoder.parser_step = FeronDecoderStepSaveDuration;
|
||||||
|
// Bit 1 is long and short timing = 750us HIGH (te_last) and 350us LOW
|
||||||
|
} else if(
|
||||||
|
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_feron_const.te_long) <
|
||||||
|
subghz_protocol_feron_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, subghz_protocol_feron_const.te_short) <
|
||||||
|
subghz_protocol_feron_const.te_delta)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||||
|
instance->decoder.parser_step = FeronDecoderStepSaveDuration;
|
||||||
|
} else if(
|
||||||
|
// End of the key 500Low(we are here)/500High us
|
||||||
|
DURATION_DIFF(
|
||||||
|
duration, (uint16_t)(subghz_protocol_feron_const.te_short + (uint16_t)150)) <
|
||||||
|
subghz_protocol_feron_const.te_delta) {
|
||||||
|
if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_feron_const.te_short) <
|
||||||
|
subghz_protocol_feron_const.te_delta)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||||
|
}
|
||||||
|
if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_feron_const.te_long) <
|
||||||
|
subghz_protocol_feron_const.te_delta)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||||
|
}
|
||||||
|
// If got 32 bits key reading is finished
|
||||||
|
if(instance->decoder.decode_count_bit ==
|
||||||
|
subghz_protocol_feron_const.min_count_bit_for_found) {
|
||||||
|
instance->generic.data = instance->decoder.decode_data;
|
||||||
|
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
|
||||||
|
if(instance->base.callback)
|
||||||
|
instance->base.callback(&instance->base, instance->base.context);
|
||||||
|
}
|
||||||
|
instance->decoder.decode_data = 0;
|
||||||
|
instance->decoder.decode_count_bit = 0;
|
||||||
|
instance->decoder.parser_step = FeronDecoderStepReset;
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = FeronDecoderStepReset;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = FeronDecoderStepReset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t subghz_protocol_decoder_feron_get_hash_data(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFeron* instance = context;
|
||||||
|
return subghz_protocol_blocks_get_hash_data_long(
|
||||||
|
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubGhzProtocolStatus subghz_protocol_decoder_feron_serialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format,
|
||||||
|
SubGhzRadioPreset* preset) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFeron* instance = context;
|
||||||
|
return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubGhzProtocolStatus
|
||||||
|
subghz_protocol_decoder_feron_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFeron* instance = context;
|
||||||
|
return subghz_block_generic_deserialize_check_count_bit(
|
||||||
|
&instance->generic, flipper_format, subghz_protocol_feron_const.min_count_bit_for_found);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_decoder_feron_get_string(void* context, FuriString* output) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFeron* instance = context;
|
||||||
|
|
||||||
|
subghz_protocol_feron_check_remote_controller(&instance->generic);
|
||||||
|
|
||||||
|
furi_string_cat_printf(
|
||||||
|
output,
|
||||||
|
"%s %db\r\n"
|
||||||
|
"Key: 0x%08lX\r\n"
|
||||||
|
"Serial: 0x%04lX\r\n"
|
||||||
|
"Command: 0x%04lX\r\n",
|
||||||
|
instance->generic.protocol_name,
|
||||||
|
instance->generic.data_count_bit,
|
||||||
|
(uint32_t)(instance->generic.data & 0xFFFFFFFF),
|
||||||
|
instance->generic.serial,
|
||||||
|
(uint32_t)(instance->generic.data & 0xFFFF));
|
||||||
|
}
|
||||||
109
lib/subghz/protocols/feron.h
Normal file
109
lib/subghz/protocols/feron.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
#define SUBGHZ_PROTOCOL_FERON_NAME "Feron"
|
||||||
|
|
||||||
|
typedef struct SubGhzProtocolDecoderFeron SubGhzProtocolDecoderFeron;
|
||||||
|
typedef struct SubGhzProtocolEncoderFeron SubGhzProtocolEncoderFeron;
|
||||||
|
|
||||||
|
extern const SubGhzProtocolDecoder subghz_protocol_feron_decoder;
|
||||||
|
extern const SubGhzProtocolEncoder subghz_protocol_feron_encoder;
|
||||||
|
extern const SubGhzProtocol subghz_protocol_feron;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate SubGhzProtocolEncoderFeron.
|
||||||
|
* @param environment Pointer to a SubGhzEnvironment instance
|
||||||
|
* @return SubGhzProtocolEncoderFeron* pointer to a SubGhzProtocolEncoderFeron instance
|
||||||
|
*/
|
||||||
|
void* subghz_protocol_encoder_feron_alloc(SubGhzEnvironment* environment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free SubGhzProtocolEncoderFeron.
|
||||||
|
* @param context Pointer to a SubGhzProtocolEncoderFeron instance
|
||||||
|
*/
|
||||||
|
void subghz_protocol_encoder_feron_free(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize and generating an upload to send.
|
||||||
|
* @param context Pointer to a SubGhzProtocolEncoderFeron instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @return status
|
||||||
|
*/
|
||||||
|
SubGhzProtocolStatus
|
||||||
|
subghz_protocol_encoder_feron_deserialize(void* context, FlipperFormat* flipper_format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forced transmission stop.
|
||||||
|
* @param context Pointer to a SubGhzProtocolEncoderFeron instance
|
||||||
|
*/
|
||||||
|
void subghz_protocol_encoder_feron_stop(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting the level and duration of the upload to be loaded into DMA.
|
||||||
|
* @param context Pointer to a SubGhzProtocolEncoderFeron instance
|
||||||
|
* @return LevelDuration
|
||||||
|
*/
|
||||||
|
LevelDuration subghz_protocol_encoder_feron_yield(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate SubGhzProtocolDecoderFeron.
|
||||||
|
* @param environment Pointer to a SubGhzEnvironment instance
|
||||||
|
* @return SubGhzProtocolDecoderFeron* pointer to a SubGhzProtocolDecoderFeron instance
|
||||||
|
*/
|
||||||
|
void* subghz_protocol_decoder_feron_alloc(SubGhzEnvironment* environment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free SubGhzProtocolDecoderFeron.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFeron instance
|
||||||
|
*/
|
||||||
|
void subghz_protocol_decoder_feron_free(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset decoder SubGhzProtocolDecoderFeron.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFeron instance
|
||||||
|
*/
|
||||||
|
void subghz_protocol_decoder_feron_reset(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a raw sequence of levels and durations received from the air.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFeron instance
|
||||||
|
* @param level Signal level true-high false-low
|
||||||
|
* @param duration Duration of this level in, us
|
||||||
|
*/
|
||||||
|
void subghz_protocol_decoder_feron_feed(void* context, bool level, uint32_t duration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting the hash sum of the last randomly received parcel.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFeron instance
|
||||||
|
* @return hash Hash sum
|
||||||
|
*/
|
||||||
|
uint32_t subghz_protocol_decoder_feron_get_hash_data(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize data SubGhzProtocolDecoderFeron.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFeron instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
||||||
|
* @return status
|
||||||
|
*/
|
||||||
|
SubGhzProtocolStatus subghz_protocol_decoder_feron_serialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format,
|
||||||
|
SubGhzRadioPreset* preset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize data SubGhzProtocolDecoderFeron.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFeron instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @return status
|
||||||
|
*/
|
||||||
|
SubGhzProtocolStatus
|
||||||
|
subghz_protocol_decoder_feron_deserialize(void* context, FlipperFormat* flipper_format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting a textual representation of the received data.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFeron instance
|
||||||
|
* @param output Resulting text
|
||||||
|
*/
|
||||||
|
void subghz_protocol_decoder_feron_get_string(void* context, FuriString* output);
|
||||||
@@ -153,6 +153,9 @@ static void subghz_protocol_encoder_hay21_get_upload(SubGhzProtocolEncoderHay21*
|
|||||||
} else {
|
} else {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
}
|
}
|
||||||
|
if(furi_hal_subghz_get_rolling_counter_mult() >= 0xF) {
|
||||||
|
instance->generic.cnt = 0xF;
|
||||||
|
}
|
||||||
} else if(instance->generic.cnt >= 0xF) {
|
} else if(instance->generic.cnt >= 0xF) {
|
||||||
instance->generic.cnt = 0;
|
instance->generic.cnt = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,7 +192,9 @@ static bool subghz_protocol_keeloq_gen_data(
|
|||||||
} else {
|
} else {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
}
|
}
|
||||||
} else if(instance->generic.cnt >= 0xFFFF) {
|
} else if(
|
||||||
|
(instance->generic.cnt >= 0xFFFF) &&
|
||||||
|
(furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
instance->generic.cnt = 0;
|
instance->generic.cnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ static bool subghz_protocol_kinggates_stylo_4k_gen_data(
|
|||||||
} else {
|
} else {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
}
|
}
|
||||||
} else if(instance->generic.cnt >= 0xFFFF) {
|
} else if((instance->generic.cnt >= 0xFFFF) && (furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
instance->generic.cnt = 0;
|
instance->generic.cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ static void subghz_protocol_encoder_nice_flor_s_get_upload(
|
|||||||
} else {
|
} else {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
}
|
}
|
||||||
} else if(instance->generic.cnt >= 0xFFFF) {
|
} else if((instance->generic.cnt >= 0xFFFF) && (furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
instance->generic.cnt = 0;
|
instance->generic.cnt = 0;
|
||||||
}
|
}
|
||||||
uint64_t decrypt = ((uint64_t)instance->generic.serial << 16) | instance->generic.cnt;
|
uint64_t decrypt = ((uint64_t)instance->generic.serial << 16) | instance->generic.cnt;
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ const SubGhzProtocol* const subghz_protocol_registry_items[] = {
|
|||||||
&subghz_protocol_hollarm,
|
&subghz_protocol_hollarm,
|
||||||
&subghz_protocol_hay21,
|
&subghz_protocol_hay21,
|
||||||
&subghz_protocol_revers_rb2,
|
&subghz_protocol_revers_rb2,
|
||||||
|
&subghz_protocol_feron,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SubGhzProtocolRegistry subghz_protocol_registry = {
|
const SubGhzProtocolRegistry subghz_protocol_registry = {
|
||||||
|
|||||||
@@ -82,3 +82,4 @@
|
|||||||
#include "hollarm.h"
|
#include "hollarm.h"
|
||||||
#include "hay21.h"
|
#include "hay21.h"
|
||||||
#include "revers_rb2.h"
|
#include "revers_rb2.h"
|
||||||
|
#include "feron.h"
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ static bool
|
|||||||
} else {
|
} else {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
}
|
}
|
||||||
} else if(instance->generic.cnt >= 0xFFFF) {
|
} else if((instance->generic.cnt >= 0xFFFF) && (furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
instance->generic.cnt = 0;
|
instance->generic.cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ static bool subghz_protocol_somfy_telis_gen_data(
|
|||||||
} else {
|
} else {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
}
|
}
|
||||||
} else if(instance->generic.cnt >= 0xFFFF) {
|
} else if((instance->generic.cnt >= 0xFFFF) && (furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
instance->generic.cnt = 0;
|
instance->generic.cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ static bool
|
|||||||
} else {
|
} else {
|
||||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||||
}
|
}
|
||||||
} else if(instance->generic.cnt >= 0xFFFF) {
|
} else if((instance->generic.cnt >= 0xFFFF) && (furi_hal_subghz_get_rolling_counter_mult() != 0)) {
|
||||||
instance->generic.cnt = 0;
|
instance->generic.cnt = 0;
|
||||||
}
|
}
|
||||||
uint32_t fix = btn << 24 | instance->generic.serial;
|
uint32_t fix = btn << 24 | instance->generic.serial;
|
||||||
|
|||||||
@@ -282,6 +282,7 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
|
|||||||
FURI_LOG_E(TAG, "Rewind error");
|
FURI_LOG_E(TAG, "Rewind error");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
furi_string_reset(temp_str);
|
||||||
while(flipper_format_read_string(fff_data_file, "Custom_preset_name", temp_str)) {
|
while(flipper_format_read_string(fff_data_file, "Custom_preset_name", temp_str)) {
|
||||||
FURI_LOG_I(TAG, "Custom preset loaded %s", furi_string_get_cstr(temp_str));
|
FURI_LOG_I(TAG, "Custom preset loaded %s", furi_string_get_cstr(temp_str));
|
||||||
subghz_setting_load_custom_preset(
|
subghz_setting_load_custom_preset(
|
||||||
|
|||||||
@@ -1749,7 +1749,7 @@ Function,+,furi_hal_subghz_flush_rx,void,
|
|||||||
Function,+,furi_hal_subghz_flush_tx,void,
|
Function,+,furi_hal_subghz_flush_tx,void,
|
||||||
Function,+,furi_hal_subghz_get_data_gpio,const GpioPin*,
|
Function,+,furi_hal_subghz_get_data_gpio,const GpioPin*,
|
||||||
Function,+,furi_hal_subghz_get_lqi,uint8_t,
|
Function,+,furi_hal_subghz_get_lqi,uint8_t,
|
||||||
Function,+,furi_hal_subghz_get_rolling_counter_mult,int8_t,
|
Function,+,furi_hal_subghz_get_rolling_counter_mult,int32_t,
|
||||||
Function,+,furi_hal_subghz_get_rssi,float,
|
Function,+,furi_hal_subghz_get_rssi,float,
|
||||||
Function,+,furi_hal_subghz_idle,void,
|
Function,+,furi_hal_subghz_idle,void,
|
||||||
Function,-,furi_hal_subghz_init,void,
|
Function,-,furi_hal_subghz_init,void,
|
||||||
@@ -1768,7 +1768,7 @@ Function,+,furi_hal_subghz_set_async_mirror_pin,void,const GpioPin*
|
|||||||
Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t
|
Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t
|
||||||
Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t
|
Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t
|
||||||
Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath
|
Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath
|
||||||
Function,+,furi_hal_subghz_set_rolling_counter_mult,void,int8_t
|
Function,+,furi_hal_subghz_set_rolling_counter_mult,void,int32_t
|
||||||
Function,+,furi_hal_subghz_shutdown,void,
|
Function,+,furi_hal_subghz_shutdown,void,
|
||||||
Function,+,furi_hal_subghz_sleep,void,
|
Function,+,furi_hal_subghz_sleep,void,
|
||||||
Function,+,furi_hal_subghz_start_async_rx,void,"FuriHalSubGhzCaptureCallback, void*"
|
Function,+,furi_hal_subghz_start_async_rx,void,"FuriHalSubGhzCaptureCallback, void*"
|
||||||
@@ -3586,7 +3586,7 @@ Function,+,subghz_keystore_get_data,SubGhzKeyArray_t*,SubGhzKeystore*
|
|||||||
Function,+,subghz_keystore_load,_Bool,"SubGhzKeystore*, const char*"
|
Function,+,subghz_keystore_load,_Bool,"SubGhzKeystore*, const char*"
|
||||||
Function,+,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, uint8_t*"
|
Function,+,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, uint8_t*"
|
||||||
Function,+,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t"
|
Function,+,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t"
|
||||||
Function,-,subghz_keystore_reset_kl,void,SubGhzKeystore*
|
Function,+,subghz_keystore_reset_kl,void,SubGhzKeystore*
|
||||||
Function,+,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*"
|
Function,+,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*"
|
||||||
Function,+,subghz_protocol_alutech_at_4n_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*"
|
Function,+,subghz_protocol_alutech_at_4n_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*"
|
||||||
Function,+,subghz_protocol_blocks_add_bit,void,"SubGhzBlockDecoder*, uint8_t"
|
Function,+,subghz_protocol_blocks_add_bit,void,"SubGhzBlockDecoder*, uint8_t"
|
||||||
|
|||||||
|
@@ -52,7 +52,7 @@ typedef struct {
|
|||||||
volatile SubGhzRegulation regulation;
|
volatile SubGhzRegulation regulation;
|
||||||
const GpioPin* async_mirror_pin;
|
const GpioPin* async_mirror_pin;
|
||||||
|
|
||||||
int8_t rolling_counter_mult;
|
int32_t rolling_counter_mult;
|
||||||
bool extended_range : 1;
|
bool extended_range : 1;
|
||||||
bool bypass_region : 1;
|
bool bypass_region : 1;
|
||||||
} FuriHalSubGhz;
|
} FuriHalSubGhz;
|
||||||
@@ -66,11 +66,11 @@ volatile FuriHalSubGhz furi_hal_subghz = {
|
|||||||
.bypass_region = false,
|
.bypass_region = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
int8_t furi_hal_subghz_get_rolling_counter_mult(void) {
|
int32_t furi_hal_subghz_get_rolling_counter_mult(void) {
|
||||||
return furi_hal_subghz.rolling_counter_mult;
|
return furi_hal_subghz.rolling_counter_mult;
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_subghz_set_rolling_counter_mult(int8_t mult) {
|
void furi_hal_subghz_set_rolling_counter_mult(int32_t mult) {
|
||||||
furi_hal_subghz.rolling_counter_mult = mult;
|
furi_hal_subghz.rolling_counter_mult = mult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -183,14 +183,14 @@ SubGhzTx furi_hal_subghz_check_tx(uint32_t value);
|
|||||||
bool furi_hal_subghz_is_tx_allowed(uint32_t value);
|
bool furi_hal_subghz_is_tx_allowed(uint32_t value);
|
||||||
|
|
||||||
/** Get the current rolling protocols counter ++/-- value
|
/** Get the current rolling protocols counter ++/-- value
|
||||||
* @return int8_t current value
|
* @return int32_t current value
|
||||||
*/
|
*/
|
||||||
int8_t furi_hal_subghz_get_rolling_counter_mult(void);
|
int32_t furi_hal_subghz_get_rolling_counter_mult(void);
|
||||||
|
|
||||||
/** Set the current rolling protocols counter ++/-- value
|
/** Set the current rolling protocols counter ++/-- value
|
||||||
* @param mult int8_t = -1, -10, -100, 0, 1, 10, 100
|
* @param mult int32_t = -1, -10, -50, 0, 1, 10, 50
|
||||||
*/
|
*/
|
||||||
void furi_hal_subghz_set_rolling_counter_mult(int8_t mult);
|
void furi_hal_subghz_set_rolling_counter_mult(int32_t mult);
|
||||||
|
|
||||||
/** Set frequency
|
/** Set frequency
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -14,11 +14,12 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FURI_HAL_VERSION_NAME_LENGTH 8
|
#define FURI_HAL_VERSION_NAME_LENGTH (8)
|
||||||
#define FURI_HAL_VERSION_ARRAY_NAME_LENGTH (FURI_HAL_VERSION_NAME_LENGTH + 1)
|
#define FURI_HAL_VERSION_ARRAY_NAME_LENGTH (FURI_HAL_VERSION_NAME_LENGTH + 1)
|
||||||
#define FURI_HAL_BT_ADV_NAME_LENGTH (18 + 1) // 18 characters + null terminator
|
/** 31b BLE Adv - 3b flags - 2b name prefix - 4b service uuid - 3b tx power = 19, + 1b null terminator (not present in packet) */
|
||||||
#define FURI_HAL_VERSION_DEVICE_NAME_LENGTH \
|
#define FURI_HAL_BT_ADV_NAME_LENGTH (20)
|
||||||
(1 + FURI_HAL_BT_ADV_NAME_LENGTH) // Used for custom BT name, BLE symbol + name
|
/** BLE symbol + name */
|
||||||
|
#define FURI_HAL_VERSION_DEVICE_NAME_LENGTH (1 + FURI_HAL_BT_ADV_NAME_LENGTH)
|
||||||
|
|
||||||
/** OTP Versions enum */
|
/** OTP Versions enum */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
Reference in New Issue
Block a user