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)
|
||||
- Sub-GHz:
|
||||
- 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)
|
||||
- RFID:
|
||||
- OFW: EM4305 support (by @Astrrra)
|
||||
@@ -102,6 +104,7 @@
|
||||
- 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)
|
||||
- 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: FeliCa Protocol Expose Read Block API and Allow Specifying Service (by @zinongli)
|
||||
- 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)) {
|
||||
worker_state = BadUsbStateIdle; // Ready to run
|
||||
} else {
|
||||
worker_state = BadUsbStateNotConnected; // USB not connected
|
||||
worker_state = BadUsbStateNotConnected; // Not connected
|
||||
}
|
||||
} else {
|
||||
worker_state = BadUsbStateScriptError; // Script preload error
|
||||
|
||||
@@ -18,9 +18,11 @@ void mf_ultralight_auth_free(MfUltralightAuth* instance) {
|
||||
void mf_ultralight_auth_reset(MfUltralightAuth* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
uint32_t default_password = MF_ULTRALIGHT_DEFAULT_PASSWORD;
|
||||
|
||||
instance->type = MfUltralightAuthTypeNone;
|
||||
memset(&instance->password, 0, sizeof(MfUltralightAuthPassword));
|
||||
memset(&instance->tdes_key, 0, sizeof(MfUltralightC3DesAuthKey));
|
||||
memcpy(&instance->password, &default_password, sizeof(MfUltralightAuthPassword));
|
||||
memcpy(&instance->tdes_key, MF_ULTRALIGHT_C_DEFAULT_KEY, sizeof(MfUltralightC3DesAuthKey));
|
||||
memset(&instance->pack, 0, sizeof(MfUltralightAuthPack));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,37 @@
|
||||
#include <cli/cli_main_commands.h>
|
||||
#include <lib/toolbox/args.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 <furi_hal_nfc.h>
|
||||
|
||||
#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) {
|
||||
printf("Usage:\r\n");
|
||||
printf("nfc <cmd>\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)) {
|
||||
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();
|
||||
}
|
||||
|
||||
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) {
|
||||
UNUSED(context);
|
||||
FuriString* cmd;
|
||||
@@ -51,6 +210,10 @@ static void execute(PipeSide* pipe, FuriString* args, void* context) {
|
||||
nfc_cli_print_usage();
|
||||
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_string_cmp_str(cmd, "field") == 0) {
|
||||
nfc_cli_field(pipe, args);
|
||||
|
||||
@@ -36,7 +36,7 @@ const char* const gps_text[GPS_COUNT] = {
|
||||
"115200",
|
||||
};
|
||||
|
||||
#define DEBUG_COUNTER_COUNT 13
|
||||
#define DEBUG_COUNTER_COUNT 16
|
||||
const char* const debug_counter_text[DEBUG_COUNTER_COUNT] = {
|
||||
"+1",
|
||||
"+2",
|
||||
@@ -44,21 +44,26 @@ const char* const debug_counter_text[DEBUG_COUNTER_COUNT] = {
|
||||
"+4",
|
||||
"+5",
|
||||
"+10",
|
||||
"0",
|
||||
"+50",
|
||||
"OVFL",
|
||||
"No",
|
||||
"-1",
|
||||
"-2",
|
||||
"-3",
|
||||
"-4",
|
||||
"-5",
|
||||
"-10",
|
||||
"-50",
|
||||
};
|
||||
const uint32_t debug_counter_val[DEBUG_COUNTER_COUNT] = {
|
||||
const int32_t debug_counter_val[DEBUG_COUNTER_COUNT] = {
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
10,
|
||||
50,
|
||||
65535,
|
||||
0,
|
||||
-1,
|
||||
-2,
|
||||
@@ -66,6 +71,7 @@ const uint32_t debug_counter_val[DEBUG_COUNTER_COUNT] = {
|
||||
-4,
|
||||
-5,
|
||||
-10,
|
||||
-50,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
VariableItemList* variable_item_list = subghz->variable_item_list;
|
||||
uint8_t value_index;
|
||||
int32_t value_index;
|
||||
VariableItem* item;
|
||||
|
||||
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,
|
||||
subghz_scene_receiver_config_set_debug_counter,
|
||||
subghz);
|
||||
value_index = value_index_uint32(
|
||||
value_index = value_index_int32(
|
||||
furi_hal_subghz_get_rolling_counter_mult(),
|
||||
debug_counter_val,
|
||||
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);
|
||||
if(subghz_custom_btn_get() != 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);
|
||||
// Calling restore!
|
||||
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();
|
||||
// Reset custom settings
|
||||
subghz_environment_reset_keeloq(environment);
|
||||
faac_slh_reset_prog_mode();
|
||||
subghz_custom_btns_reset();
|
||||
// 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) {
|
||||
FuriString* cmd = furi_string_alloc();
|
||||
FuriString* cmd;
|
||||
cmd = furi_string_alloc();
|
||||
|
||||
do {
|
||||
if(!args_read_string_and_trim(args, cmd)) {
|
||||
|
||||
@@ -501,7 +501,10 @@ void submenu_process_ok(Submenu* submenu, InputType input_type) {
|
||||
},
|
||||
true);
|
||||
|
||||
if(!item || item->locked) return;
|
||||
if(!item) return;
|
||||
if(item->locked) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!item->has_extended_events && input_type == InputTypeShort && item->callback) {
|
||||
item->callback(item->callback_context, item->index);
|
||||
|
||||
@@ -54,22 +54,6 @@ void submenu_add_item(
|
||||
SubmenuItemCallback callback,
|
||||
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
|
||||
*
|
||||
* @param submenu Submenu instance
|
||||
@@ -90,6 +74,22 @@ void submenu_add_lockable_item(
|
||||
bool locked,
|
||||
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
|
||||
*
|
||||
* @param submenu Submenu instance
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_vibro.h>
|
||||
#include <toolbox/cli/cli_command.h>
|
||||
#include <cli/cli_main_commands.h>
|
||||
#include <toolbox/pipe.h>
|
||||
#include <furi_hal_vibro.h>
|
||||
|
||||
#define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2)
|
||||
#define INPUT_PRESS_TICKS 150
|
||||
@@ -155,8 +155,10 @@ int32_t input_srv(void* p) {
|
||||
// Send Press/Release event
|
||||
event.type = pin_states[i].state ? InputTypePress : InputTypeRelease;
|
||||
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) {
|
||||
//delay 1 ticks for compatibility with rgb_backlight_mod
|
||||
furi_delay_tick(1);
|
||||
furi_hal_vibro_on(true);
|
||||
furi_delay_tick(settings->vibro_touch_level);
|
||||
furi_hal_vibro_on(false);
|
||||
|
||||
@@ -29,7 +29,6 @@ void input_settings_load(InputSettings* settings) {
|
||||
sizeof(InputSettings),
|
||||
INPUT_SETTINGS_MAGIC,
|
||||
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
|
||||
} while(false);
|
||||
|
||||
@@ -388,14 +388,19 @@ static void power_handle_reboot(PowerBootMode mode) {
|
||||
|
||||
//start furi timer for autopoweroff
|
||||
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(
|
||||
power->auto_poweroff_timer, furi_ms_to_ticks(power->settings.auto_poweroff_delay_ms));
|
||||
}
|
||||
|
||||
//stop furi timer for autopoweroff
|
||||
static void power_stop_auto_poweroff_timer(Power* power) {
|
||||
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) {
|
||||
return furi_timer_is_running(power->auto_poweroff_timer);
|
||||
|
||||
@@ -6,6 +6,7 @@ App(
|
||||
"passport",
|
||||
"system_settings",
|
||||
"clock_settings",
|
||||
"input_settings",
|
||||
"about",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -38,6 +38,7 @@ extern "C" {
|
||||
#define MF_ULTRALIGHT_TEARING_FLAG_NUM (3)
|
||||
#define MF_ULTRALIGHT_AUTH_PASSWORD_SIZE (4)
|
||||
#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_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_B_BLOCK_OFFSET (8)
|
||||
#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 {
|
||||
MfUltralightErrorNone,
|
||||
|
||||
@@ -11,8 +11,6 @@ extern "C" {
|
||||
#define MF_ULTRALIGHT_POLLER_STANDARD_FWT_FC (60000)
|
||||
#define MF_ULTRALIGHT_MAX_BUFF_SIZE (64)
|
||||
|
||||
#define MF_ULTRALIGHT_DEFAULT_PASSWORD (0xffffffffUL)
|
||||
|
||||
#define MF_ULTRALIGHT_IS_NTAG_I2C(type) \
|
||||
(((type) == MfUltralightTypeNTAGI2C1K) || ((type) == MfUltralightTypeNTAGI2C2K) || \
|
||||
((type) == MfUltralightTypeNTAGI2CPlus1K) || ((type) == MfUltralightTypeNTAGI2CPlus2K))
|
||||
|
||||
@@ -281,7 +281,7 @@ static bool subghz_protocol_alutech_at_4n_gen_data(
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,10 +142,41 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
|
||||
data_prg[0] = 0x00;
|
||||
|
||||
if(allow_zero_seed || (instance->generic.seed != 0x0)) {
|
||||
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(!(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_prg[1] = instance->generic.cnt & 0xFF;
|
||||
@@ -195,8 +226,10 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
|
||||
(temp_fix_backup != 0x0) && !faac_prog_mode) {
|
||||
instance->generic.serial = temp_fix_backup >> 4;
|
||||
instance->generic.btn = temp_fix_backup & 0xF;
|
||||
if(temp_counter_backup != 0x0) {
|
||||
instance->generic.cnt = temp_counter_backup;
|
||||
}
|
||||
}
|
||||
uint32_t fix = instance->generic.serial << 4 | instance->generic.btn;
|
||||
uint32_t hop = 0;
|
||||
uint32_t decrypt = 0;
|
||||
@@ -209,8 +242,33 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
|
||||
}
|
||||
|
||||
if(allow_zero_seed || (instance->generic.seed != 0x0)) {
|
||||
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) {
|
||||
decrypt = fixx[6] << 28 | fixx[7] << 24 | fixx[5] << 20 |
|
||||
@@ -250,7 +308,7 @@ bool subghz_protocol_faac_slh_create_data(
|
||||
const char* manufacture_name,
|
||||
SubGhzRadioPreset* preset) {
|
||||
furi_assert(context);
|
||||
// roguemaster don't steal!!!
|
||||
// OwO
|
||||
SubGhzProtocolEncoderFaacSLH* instance = context;
|
||||
instance->generic.serial = serial;
|
||||
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 {
|
||||
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) {
|
||||
instance->generic.cnt = 0;
|
||||
}
|
||||
|
||||
@@ -192,7 +192,9 @@ static bool subghz_protocol_keeloq_gen_data(
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ static bool subghz_protocol_kinggates_stylo_4k_gen_data(
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ static void subghz_protocol_encoder_nice_flor_s_get_upload(
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
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_hay21,
|
||||
&subghz_protocol_revers_rb2,
|
||||
&subghz_protocol_feron,
|
||||
};
|
||||
|
||||
const SubGhzProtocolRegistry subghz_protocol_registry = {
|
||||
|
||||
@@ -82,3 +82,4 @@
|
||||
#include "hollarm.h"
|
||||
#include "hay21.h"
|
||||
#include "revers_rb2.h"
|
||||
#include "feron.h"
|
||||
|
||||
@@ -138,7 +138,7 @@ static bool
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ static bool subghz_protocol_somfy_telis_gen_data(
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ static bool
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
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");
|
||||
break;
|
||||
}
|
||||
furi_string_reset(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));
|
||||
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_get_data_gpio,const GpioPin*,
|
||||
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_idle,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_and_path,uint32_t,uint32_t
|
||||
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_sleep,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_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_reset_kl,void,SubGhzKeystore*
|
||||
Function,+,subghz_keystore_reset_kl,void,SubGhzKeystore*
|
||||
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_blocks_add_bit,void,"SubGhzBlockDecoder*, uint8_t"
|
||||
|
||||
|
@@ -52,7 +52,7 @@ typedef struct {
|
||||
volatile SubGhzRegulation regulation;
|
||||
const GpioPin* async_mirror_pin;
|
||||
|
||||
int8_t rolling_counter_mult;
|
||||
int32_t rolling_counter_mult;
|
||||
bool extended_range : 1;
|
||||
bool bypass_region : 1;
|
||||
} FuriHalSubGhz;
|
||||
@@ -66,11 +66,11 @@ volatile FuriHalSubGhz furi_hal_subghz = {
|
||||
.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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,14 +183,14 @@ SubGhzTx furi_hal_subghz_check_tx(uint32_t value);
|
||||
bool furi_hal_subghz_is_tx_allowed(uint32_t 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
|
||||
* @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
|
||||
*
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
extern "C" {
|
||||
#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_BT_ADV_NAME_LENGTH (18 + 1) // 18 characters + null terminator
|
||||
#define FURI_HAL_VERSION_DEVICE_NAME_LENGTH \
|
||||
(1 + FURI_HAL_BT_ADV_NAME_LENGTH) // Used for custom BT name, BLE symbol + name
|
||||
/** 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_BT_ADV_NAME_LENGTH (20)
|
||||
/** BLE symbol + name */
|
||||
#define FURI_HAL_VERSION_DEVICE_NAME_LENGTH (1 + FURI_HAL_BT_ADV_NAME_LENGTH)
|
||||
|
||||
/** OTP Versions enum */
|
||||
typedef enum {
|
||||
|
||||
Reference in New Issue
Block a user