From d7ecc95de44d3b4d57a80cab045ba787807dc50b Mon Sep 17 00:00:00 2001 From: Victor Nikitchuk Date: Thu, 9 Feb 2023 06:40:04 +0300 Subject: [PATCH 1/4] Firmware fixes and improvements for flashing via blackmagic (#2321) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: quen0n Co-authored-by: あく Co-authored-by: hedger --- scripts/fbt_tools/fbt_debugopts.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/fbt_tools/fbt_debugopts.py b/scripts/fbt_tools/fbt_debugopts.py index f4b021c20..9abe59893 100644 --- a/scripts/fbt_tools/fbt_debugopts.py +++ b/scripts/fbt_tools/fbt_debugopts.py @@ -47,6 +47,7 @@ def generate(env, **kw): "source ${FBT_DEBUG_DIR}/gdbinit", ], GDBOPTS_BLACKMAGIC=[ + "-q", "-ex", "monitor swdp_scan", "-ex", From 71871949ec6999ab71fff5d25be8fb18a17a8186 Mon Sep 17 00:00:00 2001 From: Patrick Cunningham Date: Wed, 8 Feb 2023 19:47:16 -0800 Subject: [PATCH 2/4] Picopass: show elite key used from dictionary (#2119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * show elite key used from dictionary * remove space so it fits on screen Co-authored-by: あく --- .../scenes/picopass_scene_read_card_success.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c index 0d1cc78c3..d89a5d89b 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c +++ b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c @@ -69,6 +69,19 @@ void picopass_scene_read_card_success_on_enter(void* context) { furi_string_cat_printf(sio_str, "+SIO"); } + if(pacs->key) { + if(pacs->sio) { + furi_string_cat_printf(sio_str, " "); + } + furi_string_cat_printf(sio_str, "Key: "); + + uint8_t key[PICOPASS_BLOCK_LEN]; + memcpy(key, &pacs->key, PICOPASS_BLOCK_LEN); + for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) { + furi_string_cat_printf(sio_str, "%02X", key[i]); + } + } + widget_add_button_element( widget, GuiButtonTypeLeft, From 163be139ebb7a56d495d97ca87b662dfcd8a0bb8 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Thu, 9 Feb 2023 08:48:06 +0400 Subject: [PATCH 3/4] SubGhz: add protocol BinRAW (binarization of data quantized by the minimum correlated duration) (#2322) * SubGhz: add protocol DataRAW (binarization of data quantized by the minimum correlated duration) * SubGhz: fix name history * SubGhz: add encoder Data_RAW protocol * SubGhz: decreasing the size of the LevelDuration structure * SubGhz: history, added check that there is free RAM * SubGhz: checking for free memory, support to pass without gap * SubGhz: add running average to average the result, auto cut noise at the end of a burst * SubGhz: support for repeating sequences * SubGhz: fix secplus_v2 decoder * SubGhz: bin_RAW fix add history * SubGhz: add debug * SubGhz: debug refactoring * FURI_LOG: add FURI_LOG_RAW_x formatted string output like printf * SubGhz: fix new FURI_LOG metod * FURI_LOG: fix unit test * SubGhz: add enable/disable BinRAW protocol decoding * SubGhz: fix PVS * SubGhz: forcibly turn off the speaker when exiting SubGhz * SubGhz: adaptive adjustment to the noise level Co-authored-by: Aleksandr Kutuzov --- applications/debug/unit_tests/test_index.c | 2 +- applications/main/subghz/application.fam | 2 +- .../subghz/scenes/subghz_scene_read_raw.c | 2 +- .../subghz/scenes/subghz_scene_receiver.c | 13 + .../scenes/subghz_scene_receiver_config.c | 32 + applications/main/subghz/subghz.c | 5 +- applications/main/subghz/subghz_history.c | 40 +- applications/main/subghz/subghz_i.h | 1 + applications/main/subghz/views/receiver.c | 33 +- applications/main/subghz/views/receiver.h | 2 + .../subghz/views/subghz_frequency_analyzer.c | 1 - applications/main/subghz/views/transmitter.c | 7 +- firmware/targets/f7/api_symbols.csv | 3 +- furi/core/log.c | 31 +- furi/core/log.h | 51 +- lib/subghz/blocks/encoder.c | 23 +- lib/subghz/blocks/encoder.h | 11 +- lib/subghz/blocks/generic.c | 2 +- lib/subghz/blocks/generic.h | 2 +- lib/subghz/protocols/bin_raw.c | 1120 +++++++++++++++++ lib/subghz/protocols/bin_raw.h | 111 ++ lib/subghz/protocols/chamberlain_code.c | 5 +- lib/subghz/protocols/protocol_items.c | 1 + lib/subghz/protocols/protocol_items.h | 1 + lib/subghz/protocols/secplus_v2.c | 8 +- lib/subghz/receiver.c | 2 +- lib/subghz/types.h | 1 + lib/toolbox/level_duration.h | 4 +- 28 files changed, 1451 insertions(+), 65 deletions(-) create mode 100644 lib/subghz/protocols/bin_raw.c create mode 100644 lib/subghz/protocols/bin_raw.h diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index 2bb9c423f..ac71ca397 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -70,7 +70,7 @@ void minunit_print_progress() { } void minunit_print_fail(const char* str) { - printf(FURI_LOG_CLR_E "%s\r\n" FURI_LOG_CLR_RESET, str); + printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str); } void unit_tests_cli(Cli* cli, FuriString* args, void* context) { diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index 6df4b1a8a..f0dc66e89 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -12,7 +12,7 @@ App( ], provides=["subghz_start"], icon="A_Sub1ghz_14", - stack_size=2 * 1024, + stack_size=3 * 1024, order=10, ) diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 6f95c4169..96acc90ee 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -411,5 +411,5 @@ void subghz_scene_read_raw_on_exit(void* context) { notification_message(subghz->notifications, &sequence_reset_rgb); //filter restoration - subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); + subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter); } diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 2b01e2975..93c369092 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -1,6 +1,7 @@ #include "../subghz_i.h" #include "../views/receiver.h" #include +#include static const NotificationSequence subghs_sequence_rx = { &message_green_255, @@ -143,6 +144,11 @@ void subghz_scene_receiver_on_enter(void* context) { } subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen); + //to use a universal decoder, we are looking for a link to it + subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( + subghz->txrx->receiver, SUBGHZ_PROTOCOL_BIN_RAW_NAME); + furi_assert(subghz->txrx->decoder_result); + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReceiver); } @@ -208,6 +214,13 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { subghz_hopper_update(subghz); subghz_scene_receiver_update_statusbar(subghz); } + + //get RSSI + float rssi = furi_hal_subghz_get_rssi(); + subghz_receiver_rssi(subghz->subghz_receiver, rssi); + subghz_protocol_decoder_bin_raw_data_input_rssi( + (SubGhzProtocolDecoderBinRAW*)subghz->txrx->decoder_result, rssi); + switch(subghz->state_notifications) { case SubGhzNotificationStateRx: notification_message(subghz->notifications, &sequence_blink_cyan_10); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index b49aac922..895e43342 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -5,6 +5,7 @@ enum SubGhzSettingIndex { SubGhzSettingIndexFrequency, SubGhzSettingIndexHopping, SubGhzSettingIndexModulation, + SubGhzSettingIndexBinRAW, SubGhzSettingIndexSound, SubGhzSettingIndexLock, SubGhzSettingIndexRAWThesholdRSSI, @@ -58,6 +59,15 @@ const uint32_t speaker_value[SPEAKER_COUNT] = { SubGhzSpeakerStateShutdown, SubGhzSpeakerStateEnable, }; +#define BIN_RAW_COUNT 2 +const char* const bin_raw_text[BIN_RAW_COUNT] = { + "OFF", + "ON", +}; +const uint32_t bin_raw_value[BIN_RAW_COUNT] = { + SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW, +}; uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) { furi_assert(context); @@ -186,6 +196,15 @@ static void subghz_scene_receiver_config_set_speaker(VariableItem* item) { subghz->txrx->speaker_state = speaker_value[index]; } +static void subghz_scene_receiver_config_set_bin_raw(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, bin_raw_text[index]); + subghz->txrx->filter = bin_raw_value[index]; + subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter); +} + static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -254,6 +273,19 @@ void subghz_scene_receiver_config_on_enter(void* context) { variable_item_set_current_value_text( item, subghz_setting_get_preset_name(subghz->setting, value_index)); + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != + SubGhzCustomEventManagerSet) { + item = variable_item_list_add( + subghz->variable_item_list, + "Bin_RAW:", + BIN_RAW_COUNT, + subghz_scene_receiver_config_set_bin_raw, + subghz); + value_index = value_index_uint32(subghz->txrx->filter, bin_raw_value, BIN_RAW_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, bin_raw_text[value_index]); + } + item = variable_item_list_add( subghz->variable_item_list, "Sound:", diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 200be6262..25233fe21 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -194,7 +194,8 @@ SubGhz* subghz_alloc() { subghz_environment_set_protocol_registry( subghz->txrx->environment, (void*)&subghz_protocol_registry); subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment); - subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); + subghz->txrx->filter = SubGhzProtocolFlag_Decodable; + subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter); subghz_worker_set_overrun_callback( subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); @@ -218,6 +219,8 @@ void subghz_free(SubGhz* subghz) { subghz->rpc_ctx = NULL; } + subghz_speaker_off(subghz); + // Packet Test view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestPacket); subghz_test_packet_free(subghz->subghz_test_packet); diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index beecc6e8b..e6c93e05c 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -5,6 +5,7 @@ #include #define SUBGHZ_HISTORY_MAX 50 +#define SUBGHZ_HISTORY_FREE_HEAP 20480 #define TAG "SubGhzHistory" typedef struct { @@ -121,8 +122,12 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx } bool subghz_history_get_text_space_left(SubGhzHistory* instance, FuriString* output) { furi_assert(instance); + if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) { + if(output != NULL) furi_string_printf(output, " Free heap LOW"); + return true; + } if(instance->last_index_write == SUBGHZ_HISTORY_MAX) { - if(output != NULL) furi_string_printf(output, "Memory is FULL"); + if(output != NULL) furi_string_printf(output, " Memory is FULL"); return true; } if(output != NULL) @@ -142,6 +147,7 @@ bool subghz_history_add_to_history( furi_assert(instance); furi_assert(context); + if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) return false; if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false; SubGhzProtocolDecoderBase* decoder_base = context; @@ -200,27 +206,31 @@ bool subghz_history_add_to_history( } uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex(item->flipper_string, "Key", key_data, sizeof(uint64_t))) { - FURI_LOG_E(TAG, "Missing Key"); - break; + FURI_LOG_D(TAG, "No Key"); } uint64_t data = 0; for(uint8_t i = 0; i < sizeof(uint64_t); i++) { data = (data << 8) | key_data[i]; } - if(!(uint32_t)(data >> 32)) { - furi_string_printf( - item->item_str, - "%s %lX", - furi_string_get_cstr(instance->tmp_string), - (uint32_t)(data & 0xFFFFFFFF)); + if(data != 0) { + if(!(uint32_t)(data >> 32)) { + furi_string_printf( + item->item_str, + "%s %lX", + furi_string_get_cstr(instance->tmp_string), + (uint32_t)(data & 0xFFFFFFFF)); + } else { + furi_string_printf( + item->item_str, + "%s %lX%08lX", + furi_string_get_cstr(instance->tmp_string), + (uint32_t)(data >> 32), + (uint32_t)(data & 0xFFFFFFFF)); + } } else { - furi_string_printf( - item->item_str, - "%s %lX%08lX", - furi_string_get_cstr(instance->tmp_string), - (uint32_t)(data >> 32), - (uint32_t)(data & 0xFFFFFFFF)); + furi_string_printf(item->item_str, "%s", furi_string_get_cstr(instance->tmp_string)); } + } while(false); furi_string_free(text); diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index cd33da447..65480c6fd 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -45,6 +45,7 @@ struct SubGhzTxRx { SubGhzEnvironment* environment; SubGhzReceiver* receiver; SubGhzTransmitter* transmitter; + SubGhzProtocolFlag filter; SubGhzProtocolDecoderBase* decoder_result; FlipperFormat* fff_data; diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index aaec2adda..acc39e258 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -12,6 +12,8 @@ #define MENU_ITEMS 4u #define UNLOCK_CNT 3 +#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f + typedef struct { FuriString* item_str; uint8_t type; @@ -59,8 +61,24 @@ typedef struct { uint16_t list_offset; uint16_t history_item; SubGhzViewReceiverBarShow bar_show; + uint8_t u_rssi; } SubGhzViewReceiverModel; +void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi) { + furi_assert(instance); + with_view_model( + instance->view, + SubGhzViewReceiverModel * model, + { + if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) { + model->u_rssi = 0; + } else { + model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN); + } + }, + true); +} + void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock lock) { furi_assert(subghz_receiver); subghz_receiver->lock_count = 0; @@ -168,13 +186,22 @@ static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool s canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11); } +static void subghz_view_rssi_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { + for(uint8_t i = 1; i < model->u_rssi; i++) { + if(i % 5) { + canvas_draw_dot(canvas, 46 + i, 50); + canvas_draw_dot(canvas, 47 + i, 51); + canvas_draw_dot(canvas, 46 + i, 52); + } + } +} + void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); elements_button_left(canvas, "Config"); - canvas_draw_line(canvas, 46, 51, 125, 51); bool scrollbar = model->history_item > 4; FuriString* str_buff; @@ -206,11 +233,11 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { if(model->history_item == 0) { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 63, 46, "Scanning..."); - canvas_draw_line(canvas, 46, 51, 125, 51); + canvas_draw_str(canvas, 63, 44, "Scanning..."); canvas_set_font(canvas, FontSecondary); } + subghz_view_rssi_draw(canvas, model); switch(model->bar_show) { case SubGhzViewReceiverBarShowLock: canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8); diff --git a/applications/main/subghz/views/receiver.h b/applications/main/subghz/views/receiver.h index aab7a76c5..9b12ccfee 100644 --- a/applications/main/subghz/views/receiver.h +++ b/applications/main/subghz/views/receiver.h @@ -8,6 +8,8 @@ typedef struct SubGhzViewReceiver SubGhzViewReceiver; typedef void (*SubGhzViewReceiverCallback)(SubGhzCustomEvent event, void* context); +void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi); + void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock keyboard); void subghz_view_receiver_set_callback( diff --git a/applications/main/subghz/views/subghz_frequency_analyzer.c b/applications/main/subghz/views/subghz_frequency_analyzer.c index 94419084b..325664f4a 100644 --- a/applications/main/subghz/views/subghz_frequency_analyzer.c +++ b/applications/main/subghz/views/subghz_frequency_analyzer.c @@ -79,7 +79,6 @@ void subghz_frequency_analyzer_draw_rssi(Canvas* canvas, uint8_t rssi, uint8_t x void subghz_frequency_analyzer_draw_log_rssi(Canvas* canvas, uint8_t rssi, uint8_t x, uint8_t y) { uint8_t column_height = 6; if(rssi) { - //rssi = rssi if(rssi > 54) rssi = 54; for(uint8_t i = 1; i < rssi; i++) { if(i % 5) { diff --git a/applications/main/subghz/views/transmitter.c b/applications/main/subghz/views/transmitter.c index 833805ccb..4a13460a3 100644 --- a/applications/main/subghz/views/transmitter.c +++ b/applications/main/subghz/views/transmitter.c @@ -84,9 +84,10 @@ void subghz_view_transmitter_draw(Canvas* canvas, SubGhzViewTransmitterModel* mo canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 8, furi_string_get_cstr(model->key_str)); - canvas_draw_str(canvas, 78, 8, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 113, 8, furi_string_get_cstr(model->preset_str)); + elements_multiline_text_aligned( + canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->key_str)); + canvas_draw_str(canvas, 78, 7, furi_string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 113, 7, furi_string_get_cstr(model->preset_str)); if(model->show_button) subghz_view_transmitter_button_right(canvas, "Send"); } diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 846041c3e..906ab357a 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1409,6 +1409,7 @@ Function,+,furi_kernel_unlock,int32_t, Function,+,furi_log_get_level,FuriLogLevel, Function,-,furi_log_init,void, Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..." +Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..." Function,+,furi_log_set_level,void,FuriLogLevel Function,-,furi_log_set_puts,void,FuriLogPuts Function,-,furi_log_set_timestamp,void,FuriLogTimestamp @@ -2599,7 +2600,7 @@ Function,+,subghz_protocol_blocks_crc8le,uint8_t,"const uint8_t[], size_t, uint8 Function,+,subghz_protocol_blocks_get_bit_array,_Bool,"uint8_t[], size_t" Function,+,subghz_protocol_blocks_get_hash_data,uint8_t,"SubGhzBlockDecoder*, size_t" Function,+,subghz_protocol_blocks_get_parity,uint8_t,"uint64_t, uint8_t" -Function,+,subghz_protocol_blocks_get_upload,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t" +Function,+,subghz_protocol_blocks_get_upload_from_bit_array,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t, SubGhzProtocolBlockAlignBit" Function,+,subghz_protocol_blocks_lfsr_digest16,uint16_t,"const uint8_t[], size_t, uint16_t, uint16_t" Function,+,subghz_protocol_blocks_lfsr_digest8,uint8_t,"const uint8_t[], size_t, uint8_t, uint8_t" Function,+,subghz_protocol_blocks_lfsr_digest8_reflect,uint8_t,"const uint8_t[], size_t, uint8_t, uint8_t" diff --git a/furi/core/log.c b/furi/core/log.c index a3967ed92..d910ecf21 100644 --- a/furi/core/log.c +++ b/furi/core/log.c @@ -28,27 +28,27 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form FuriString* string; string = furi_string_alloc(); - const char* color = FURI_LOG_CLR_RESET; + const char* color = _FURI_LOG_CLR_RESET; const char* log_letter = " "; switch(level) { case FuriLogLevelError: - color = FURI_LOG_CLR_E; + color = _FURI_LOG_CLR_E; log_letter = "E"; break; case FuriLogLevelWarn: - color = FURI_LOG_CLR_W; + color = _FURI_LOG_CLR_W; log_letter = "W"; break; case FuriLogLevelInfo: - color = FURI_LOG_CLR_I; + color = _FURI_LOG_CLR_I; log_letter = "I"; break; case FuriLogLevelDebug: - color = FURI_LOG_CLR_D; + color = _FURI_LOG_CLR_D; log_letter = "D"; break; case FuriLogLevelTrace: - color = FURI_LOG_CLR_T; + color = _FURI_LOG_CLR_T; log_letter = "T"; break; default: @@ -58,7 +58,7 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form // Timestamp furi_string_printf( string, - "%lu %s[%s][%s] " FURI_LOG_CLR_RESET, + "%lu %s[%s][%s] " _FURI_LOG_CLR_RESET, furi_log.timestamp(), color, log_letter, @@ -80,6 +80,23 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form } } +void furi_log_print_raw_format(FuriLogLevel level, const char* format, ...) { + if(level <= furi_log.log_level && + furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk) { + FuriString* string; + string = furi_string_alloc(); + va_list args; + va_start(args, format); + furi_string_vprintf(string, format, args); + va_end(args); + + furi_log.puts(furi_string_get_cstr(string)); + furi_string_free(string); + + furi_mutex_release(furi_log.mutex); + } +} + void furi_log_set_level(FuriLogLevel level) { if(level == FuriLogLevelDefault) { level = FURI_LOG_LEVEL_DEFAULT; diff --git a/furi/core/log.h b/furi/core/log.h index cb8b3d9cc..46ae7f007 100644 --- a/furi/core/log.h +++ b/furi/core/log.h @@ -22,21 +22,21 @@ typedef enum { FuriLogLevelTrace = 6, } FuriLogLevel; -#define FURI_LOG_CLR(clr) "\033[0;" clr "m" -#define FURI_LOG_CLR_RESET "\033[0m" +#define _FURI_LOG_CLR(clr) "\033[0;" clr "m" +#define _FURI_LOG_CLR_RESET "\033[0m" -#define FURI_LOG_CLR_BLACK "30" -#define FURI_LOG_CLR_RED "31" -#define FURI_LOG_CLR_GREEN "32" -#define FURI_LOG_CLR_BROWN "33" -#define FURI_LOG_CLR_BLUE "34" -#define FURI_LOG_CLR_PURPLE "35" +#define _FURI_LOG_CLR_BLACK "30" +#define _FURI_LOG_CLR_RED "31" +#define _FURI_LOG_CLR_GREEN "32" +#define _FURI_LOG_CLR_BROWN "33" +#define _FURI_LOG_CLR_BLUE "34" +#define _FURI_LOG_CLR_PURPLE "35" -#define FURI_LOG_CLR_E FURI_LOG_CLR(FURI_LOG_CLR_RED) -#define FURI_LOG_CLR_W FURI_LOG_CLR(FURI_LOG_CLR_BROWN) -#define FURI_LOG_CLR_I FURI_LOG_CLR(FURI_LOG_CLR_GREEN) -#define FURI_LOG_CLR_D FURI_LOG_CLR(FURI_LOG_CLR_BLUE) -#define FURI_LOG_CLR_T FURI_LOG_CLR(FURI_LOG_CLR_PURPLE) +#define _FURI_LOG_CLR_E _FURI_LOG_CLR(_FURI_LOG_CLR_RED) +#define _FURI_LOG_CLR_W _FURI_LOG_CLR(_FURI_LOG_CLR_BROWN) +#define _FURI_LOG_CLR_I _FURI_LOG_CLR(_FURI_LOG_CLR_GREEN) +#define _FURI_LOG_CLR_D _FURI_LOG_CLR(_FURI_LOG_CLR_BLUE) +#define _FURI_LOG_CLR_T _FURI_LOG_CLR(_FURI_LOG_CLR_PURPLE) typedef void (*FuriLogPuts)(const char* data); typedef uint32_t (*FuriLogTimestamp)(void); @@ -54,6 +54,15 @@ void furi_log_init(); void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...) _ATTRIBUTE((__format__(__printf__, 3, 4))); +/** Print log record + * + * @param level + * @param format + * @param ... + */ +void furi_log_print_raw_format(FuriLogLevel level, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 2, 3))); + /** Set log level * * @param[in] level The level @@ -95,6 +104,22 @@ void furi_log_set_timestamp(FuriLogTimestamp timestamp); #define FURI_LOG_T(tag, format, ...) \ furi_log_print_format(FuriLogLevelTrace, tag, format, ##__VA_ARGS__) +/** Log methods + * + * @param format The raw format + * @param ... VA Args + */ +#define FURI_LOG_RAW_E(format, ...) \ + furi_log_print_raw_format(FuriLogLevelError, format, ##__VA_ARGS__) +#define FURI_LOG_RAW_W(format, ...) \ + furi_log_print_raw_format(FuriLogLevelWarn, format, ##__VA_ARGS__) +#define FURI_LOG_RAW_I(format, ...) \ + furi_log_print_raw_format(FuriLogLevelInfo, format, ##__VA_ARGS__) +#define FURI_LOG_RAW_D(format, ...) \ + furi_log_print_raw_format(FuriLogLevelDebug, format, ##__VA_ARGS__) +#define FURI_LOG_RAW_T(format, ...) \ + furi_log_print_raw_format(FuriLogLevelTrace, format, ##__VA_ARGS__) + #ifdef __cplusplus } #endif diff --git a/lib/subghz/blocks/encoder.c b/lib/subghz/blocks/encoder.c index f3349b5fc..49ec4f177 100644 --- a/lib/subghz/blocks/encoder.c +++ b/lib/subghz/blocks/encoder.c @@ -2,6 +2,8 @@ #include "math.h" #include +#include "furi.h" + #define TAG "SubGhzBlockEncoder" void subghz_protocol_blocks_set_bit_array( @@ -17,21 +19,32 @@ bool subghz_protocol_blocks_get_bit_array(uint8_t data_array[], size_t read_inde return bit_read(data_array[read_index_bit >> 3], 7 - (read_index_bit & 0x7)); } -size_t subghz_protocol_blocks_get_upload( +size_t subghz_protocol_blocks_get_upload_from_bit_array( uint8_t data_array[], size_t count_bit_data_array, LevelDuration* upload, size_t max_size_upload, - uint32_t duration_bit) { - size_t index_bit = 0; + uint32_t duration_bit, + SubGhzProtocolBlockAlignBit align_bit) { + size_t bias_bit = 0; size_t size_upload = 0; uint32_t duration = duration_bit; + + if(align_bit == SubGhzProtocolBlockAlignBitRight) { + if(count_bit_data_array & 0x7) { + bias_bit = 8 - (count_bit_data_array & 0x7); + } + } + size_t index_bit = bias_bit; + bool last_bit = subghz_protocol_blocks_get_bit_array(data_array, index_bit++); - for(size_t i = 1; i < count_bit_data_array; i++) { + for(size_t i = 1 + bias_bit; i < count_bit_data_array + bias_bit; i++) { if(last_bit == subghz_protocol_blocks_get_bit_array(data_array, index_bit)) { duration += duration_bit; } else { - furi_assert(max_size_upload > size_upload); + if(size_upload > max_size_upload) { + furi_crash("SubGhz: Encoder buffer overflow"); + } upload[size_upload++] = level_duration_make( subghz_protocol_blocks_get_bit_array(data_array, index_bit - 1), duration); last_bit = !last_bit; diff --git a/lib/subghz/blocks/encoder.h b/lib/subghz/blocks/encoder.h index 1ff077726..aeaa2add0 100644 --- a/lib/subghz/blocks/encoder.h +++ b/lib/subghz/blocks/encoder.h @@ -19,6 +19,11 @@ typedef struct { } SubGhzProtocolBlockEncoder; +typedef enum { + SubGhzProtocolBlockAlignBitLeft, + SubGhzProtocolBlockAlignBitRight, +} SubGhzProtocolBlockAlignBit; + /** * Set data bit when encoding HEX array. * @param bit_value The value of the bit to be set @@ -47,13 +52,15 @@ bool subghz_protocol_blocks_get_bit_array(uint8_t data_array[], size_t read_inde * @param upload Pointer to a LevelDuration * @param max_size_upload upload size, check not to overflow * @param duration_bit duration 1 bit + * @param align_bit alignment of useful bits in an array */ -size_t subghz_protocol_blocks_get_upload( +size_t subghz_protocol_blocks_get_upload_from_bit_array( uint8_t data_array[], size_t count_bit_data_array, LevelDuration* upload, size_t max_size_upload, - uint32_t duration_bit); + uint32_t duration_bit, + SubGhzProtocolBlockAlignBit align_bit); #ifdef __cplusplus } diff --git a/lib/subghz/blocks/generic.c b/lib/subghz/blocks/generic.c index 94114676d..3d59adc82 100644 --- a/lib/subghz/blocks/generic.c +++ b/lib/subghz/blocks/generic.c @@ -100,7 +100,7 @@ bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperForma FURI_LOG_E(TAG, "Missing Bit"); break; } - instance->data_count_bit = (uint8_t)temp_data; + instance->data_count_bit = (uint16_t)temp_data; uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { diff --git a/lib/subghz/blocks/generic.h b/lib/subghz/blocks/generic.h index d1c7dc356..284df51ae 100644 --- a/lib/subghz/blocks/generic.h +++ b/lib/subghz/blocks/generic.h @@ -19,7 +19,7 @@ struct SubGhzBlockGeneric { const char* protocol_name; uint64_t data; uint32_t serial; - uint8_t data_count_bit; + uint16_t data_count_bit; uint8_t btn; uint32_t cnt; }; diff --git a/lib/subghz/protocols/bin_raw.c b/lib/subghz/protocols/bin_raw.c new file mode 100644 index 000000000..c3f544110 --- /dev/null +++ b/lib/subghz/protocols/bin_raw.c @@ -0,0 +1,1120 @@ +#include "bin_raw.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" +#include +#include +#include + +#define TAG "SubGhzProtocolBinRAW" + +//change very carefully, RAM ends at the most inopportune moment +#define BIN_RAW_BUF_RAW_SIZE 2048 +#define BIN_RAW_BUF_DATA_SIZE 512 + +#define BIN_RAW_THRESHOLD_RSSI -85.0f +#define BIN_RAW_DELTA_RSSI 7.0f +#define BIN_RAW_SEARCH_CLASSES 20 +#define BIN_RAW_TE_MIN_COUNT 40 +#define BIN_RAW_BUF_MIN_DATA_COUNT 128 +#define BIN_RAW_MAX_MARKUP_COUNT 20 + +//#define BIN_RAW_DEBUG + +#ifdef BIN_RAW_DEBUG +#define bin_raw_debug(...) FURI_LOG_RAW_D(__VA_ARGS__) +#define bin_raw_debug_tag(tag, ...) \ + FURI_LOG_RAW_D("\033[0;32m[" tag "]\033[0m "); \ + FURI_LOG_RAW_D(__VA_ARGS__) +#else +#define bin_raw_debug(...) +#define bin_raw_debug_tag(...) +#endif + +static const SubGhzBlockConst subghz_protocol_bin_raw_const = { + .te_short = 30, + .te_long = 65000, + .te_delta = 0, + .min_count_bit_for_found = 0, +}; + +typedef enum { + BinRAWDecoderStepReset = 0, + BinRAWDecoderStepWrite, + BinRAWDecoderStepBufFull, + BinRAWDecoderStepNoParse, +} BinRAWDecoderStep; + +typedef enum { + BinRAWTypeUnknown = 0, + BinRAWTypeNoGap, + BinRAWTypeGap, + BinRAWTypeGapRecurring, + BinRAWTypeGapRolling, + BinRAWTypeGapUnknown, +} BinRAWType; + +struct BinRAW_Markup { + uint16_t byte_bias; + uint16_t bit_count; +}; +typedef struct BinRAW_Markup BinRAW_Markup; + +struct SubGhzProtocolDecoderBinRAW { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + int32_t* data_raw; + uint8_t* data; + BinRAW_Markup data_markup[BIN_RAW_MAX_MARKUP_COUNT]; + size_t data_raw_ind; + uint32_t te; + float adaptive_threshold_rssi; +}; + +struct SubGhzProtocolEncoderBinRAW { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; + + uint8_t* data; + BinRAW_Markup data_markup[BIN_RAW_MAX_MARKUP_COUNT]; + uint32_t te; +}; + +const SubGhzProtocolDecoder subghz_protocol_bin_raw_decoder = { + .alloc = subghz_protocol_decoder_bin_raw_alloc, + .free = subghz_protocol_decoder_bin_raw_free, + + .feed = subghz_protocol_decoder_bin_raw_feed, + .reset = subghz_protocol_decoder_bin_raw_reset, + + .get_hash_data = subghz_protocol_decoder_bin_raw_get_hash_data, + .serialize = subghz_protocol_decoder_bin_raw_serialize, + .deserialize = subghz_protocol_decoder_bin_raw_deserialize, + .get_string = subghz_protocol_decoder_bin_raw_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_bin_raw_encoder = { + .alloc = subghz_protocol_encoder_bin_raw_alloc, + .free = subghz_protocol_encoder_bin_raw_free, + + .deserialize = subghz_protocol_encoder_bin_raw_deserialize, + .stop = subghz_protocol_encoder_bin_raw_stop, + .yield = subghz_protocol_encoder_bin_raw_yield, +}; + +const SubGhzProtocol subghz_protocol_bin_raw = { + .name = SUBGHZ_PROTOCOL_BIN_RAW_NAME, + .type = SubGhzProtocolTypeStatic, +#ifdef BIN_RAW_DEBUG + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_FM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, +#else + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_FM | SubGhzProtocolFlag_BinRAW | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, +#endif + .decoder = &subghz_protocol_bin_raw_decoder, + .encoder = &subghz_protocol_bin_raw_encoder, +}; + +static uint16_t subghz_protocol_bin_raw_get_full_byte(uint16_t bit_count) { + if(bit_count & 0x7) { + return (bit_count >> 3) + 1; + } else { + return (bit_count >> 3); + } +} + +void* subghz_protocol_encoder_bin_raw_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderBinRAW* instance = malloc(sizeof(SubGhzProtocolEncoderBinRAW)); + + instance->base.protocol = &subghz_protocol_bin_raw; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = BIN_RAW_BUF_DATA_SIZE * 5; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->data = malloc(instance->encoder.size_upload * sizeof(uint8_t)); + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_bin_raw_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderBinRAW* instance = context; + free(instance->encoder.upload); + free(instance->data); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderBinRAW instance + * @return true On success + */ +static bool subghz_protocol_encoder_bin_raw_get_upload(SubGhzProtocolEncoderBinRAW* instance) { + furi_assert(instance); + + //we glue all the pieces of the package into 1 long sequence with left alignment, + //in the uploaded data we have right alignment. + + bin_raw_debug_tag(TAG, "Recovery of offset bits in sequences\r\n"); + uint16_t i = 0; + uint16_t ind = 0; + bin_raw_debug("\tind byte_bias\tbit_count\tbit_bias\r\n"); + while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) { + uint8_t bit_bias = + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count) * 8 - + instance->data_markup[i].bit_count; + bin_raw_debug( + "\t%d\t%d\t%d :\t\t%d\r\n", + i, + instance->data_markup[i].byte_bias, + instance->data_markup[i].bit_count, + bit_bias); + for(uint16_t y = instance->data_markup[i].byte_bias * 8; + y < instance->data_markup[i].byte_bias * 8 + + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count) * 8 - + bit_bias; + y++) { + subghz_protocol_blocks_set_bit_array( + subghz_protocol_blocks_get_bit_array(instance->data, y + bit_bias), + instance->data, + ind++, + BIN_RAW_BUF_DATA_SIZE); + } + i++; + } + bin_raw_debug("\r\n"); +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag(TAG, "Restored Sequence left aligned\r\n"); + for(uint16_t y = 0; y < subghz_protocol_bin_raw_get_full_byte(ind); y++) { + bin_raw_debug("%02X ", instance->data[y]); + } + bin_raw_debug("\r\n\tbin_count_result= %d\r\n\r\n", ind); + + bin_raw_debug_tag( + TAG, "Maximum levels encoded in upload %zu\r\n", instance->encoder.size_upload); +#endif + instance->encoder.size_upload = subghz_protocol_blocks_get_upload_from_bit_array( + instance->data, + ind, + instance->encoder.upload, + instance->encoder.size_upload, + instance->te, + SubGhzProtocolBlockAlignBitLeft); + + bin_raw_debug_tag(TAG, "The result %zu is levels\r\n", instance->encoder.size_upload); + bin_raw_debug_tag(TAG, "Remaining free memory %zu\r\n", memmgr_get_free_heap()); + return true; +} + +bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderBinRAW* instance = context; + + bool res = false; + uint32_t temp_data = 0; + + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { + FURI_LOG_E(TAG, "Missing Bit"); + break; + } + + instance->generic.data_count_bit = (uint16_t)temp_data; + + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + + temp_data = 0; + uint16_t ind = 0; + uint16_t byte_bias = 0; + uint16_t byte_count = 0; + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) { + if(ind >= BIN_RAW_MAX_MARKUP_COUNT) { + FURI_LOG_E(TAG, "Markup overflow"); + break; + } + byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data); + if(byte_count > BIN_RAW_BUF_DATA_SIZE) { + FURI_LOG_E(TAG, "Receive buffer overflow"); + break; + } + + instance->data_markup[ind].bit_count = temp_data; + instance->data_markup[ind].byte_bias = byte_bias; + byte_bias += subghz_protocol_bin_raw_get_full_byte(temp_data); + + if(!flipper_format_read_hex( + flipper_format, + "Data_RAW", + instance->data + instance->data_markup[ind].byte_bias, + subghz_protocol_bin_raw_get_full_byte(temp_data))) { + instance->data_markup[ind].bit_count = 0; + FURI_LOG_E(TAG, "Missing Data_RAW"); + break; + } + ind++; + } + +#ifdef BIN_RAW_DEBUG + uint16_t i = 0; + bin_raw_debug_tag(TAG, "Download data to encoder\r\n"); + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data"); + while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) { + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + i, + instance->data_markup[i].byte_bias, + instance->data_markup[i].bit_count); + for(uint16_t y = instance->data_markup[i].byte_bias; + y < instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count); + y++) { + bin_raw_debug("%02X ", instance->data[y]); + } + i++; + } + bin_raw_debug("\r\n\r\n"); +#endif + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_bin_raw_get_upload(instance)) break; + instance->encoder.is_running = true; + + res = true; + } while(0); + + return res; +} + +void subghz_protocol_encoder_bin_raw_stop(void* context) { + SubGhzProtocolEncoderBinRAW* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_bin_raw_yield(void* context) { + SubGhzProtocolEncoderBinRAW* 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_bin_raw_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderBinRAW* instance = malloc(sizeof(SubGhzProtocolDecoderBinRAW)); + instance->base.protocol = &subghz_protocol_bin_raw; + instance->generic.protocol_name = instance->base.protocol->name; + instance->data_raw_ind = 0; + instance->data_raw = malloc(BIN_RAW_BUF_RAW_SIZE * sizeof(int32_t)); + instance->data = malloc(BIN_RAW_BUF_RAW_SIZE * sizeof(uint8_t)); + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + instance->adaptive_threshold_rssi = BIN_RAW_THRESHOLD_RSSI; + return instance; +} + +void subghz_protocol_decoder_bin_raw_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + free(instance->data_raw); + free(instance->data); + free(instance); +} + +void subghz_protocol_decoder_bin_raw_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; +#ifdef BIN_RAW_DEBUG + UNUSED(instance); +#else + instance->decoder.parser_step = BinRAWDecoderStepNoParse; + instance->data_raw_ind = 0; +#endif +} + +void subghz_protocol_decoder_bin_raw_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + + if(instance->decoder.parser_step == BinRAWDecoderStepWrite) { + if(instance->data_raw_ind == BIN_RAW_BUF_RAW_SIZE) { + instance->decoder.parser_step = BinRAWDecoderStepBufFull; + } else { + instance->data_raw[instance->data_raw_ind++] = (level ? duration : -duration); + } + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzProtocolDecoderBinRAW* instance + */ +static bool + subghz_protocol_bin_raw_check_remote_controller(SubGhzProtocolDecoderBinRAW* instance) { + struct { + float data; + uint16_t count; + } classes[BIN_RAW_SEARCH_CLASSES]; + + size_t ind = 0; + + memset(classes, 0x00, sizeof(classes)); + + uint16_t data_markup_ind = 0; + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + + if(instance->data_raw_ind < 512) { + ind = + instance->data_raw_ind - + 100; //there is usually garbage at the end of the record, we exclude it from the classification + } else { + ind = 512; + } + + //sort the durations to find the shortest correlated interval + for(size_t i = 0; i < ind; i++) { + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + if(classes[k].count == 0) { + classes[k].data = (float)(abs(instance->data_raw[i])); + classes[k].count++; + break; + } else if( + DURATION_DIFF((float)(abs(instance->data_raw[i])), (classes[k].data)) < + (classes[k].data / 4)) { //if the test value does not differ by more than 25% + classes[k].data += ((float)(abs(instance->data_raw[i])) - classes[k].data) * + 0.05f; //running average k=0.05 + classes[k].count++; + break; + } + } + } + + // if(classes[BIN_RAW_SEARCH_CLASSES - 1].count != 0) { + // //filling the classifier, it means that they received an unclean signal + // return false; + // } + + //looking for the minimum te with an occurrence greater than BIN_RAW_TE_MIN_COUNT + instance->te = subghz_protocol_bin_raw_const.te_long * 2; + + bool te_ok = false; + uint16_t gap_ind = 0; + uint16_t gap_delta = 0; + uint32_t gap = 0; + int data_temp = 0; + BinRAWType bin_raw_type = BinRAWTypeUnknown; + + //sort by number of occurrences + bool swap = true; + while(swap) { + swap = false; + for(size_t i = 1; i < BIN_RAW_SEARCH_CLASSES; i++) { + if(classes[i].count > classes[i - 1].count) { + uint32_t data = classes[i - 1].data; + uint32_t count = classes[i - 1].count; + classes[i - 1].data = classes[i].data; + classes[i - 1].count = classes[i].count; + classes[i].data = data; + classes[i].count = count; + swap = true; + } + } + } +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag(TAG, "Sorted durations\r\n"); + bin_raw_debug("\t\tind\tcount\tus\r\n"); + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + bin_raw_debug("\t\t%zu\t%u\t%lu\r\n", k, classes[k].count, (uint32_t)classes[k].data); + } + bin_raw_debug("\r\n"); +#endif + if((classes[0].count > BIN_RAW_TE_MIN_COUNT) && (classes[1].count == 0)) { + //adopted only the preamble + instance->te = (uint32_t)classes[0].data; + te_ok = true; + gap = 0; //gap no + } else { + //take the 2 most common durations + //check that there are enough + if((classes[0].count < BIN_RAW_TE_MIN_COUNT) || + (classes[1].count < (BIN_RAW_TE_MIN_COUNT >> 1))) + return false; + //arrange the first 2 date values in ascending order + if(classes[0].data > classes[1].data) { + uint32_t data = classes[1].data; + classes[0].data = classes[1].data; + classes[1].data = data; + } + + //determine the value to be corrected + for(uint8_t k = 1; k < 5; k++) { + float delta = (classes[1].data / (classes[0].data / k)); + bin_raw_debug_tag(TAG, "K_div= %f\r\n", (double)(delta)); + delta -= (uint32_t)delta; + + if((delta < 0.20f) || (delta > 0.80f)) { + instance->te = (uint32_t)classes[0].data / k; + bin_raw_debug_tag(TAG, "K= %d\r\n", k); + te_ok = true; //found a correlated duration + break; + } + } + if(!te_ok) { + //did not find the minimum TE satisfying the condition + return false; + } + bin_raw_debug_tag(TAG, "TE= %lu\r\n\r\n", instance->te); + + //looking for a gap + for(size_t k = 2; k < BIN_RAW_SEARCH_CLASSES; k++) { + if((classes[k].count > 2) && (classes[k].data > gap)) { + gap = (uint32_t)classes[k].data; + gap_delta = gap / 5; //calculate 20% deviation from ideal value + } + } + + if((gap / instance->te) < + 10) { //make an assumption, the longest gap should be more than 10 TE + gap = 0; //check that our signal has a gap greater than 10*TE + bin_raw_type = BinRAWTypeNoGap; + } else { + bin_raw_type = BinRAWTypeGap; + //looking for the last occurrence of gap + ind = instance->data_raw_ind - 1; + while((ind > 0) && (DURATION_DIFF(abs(instance->data_raw[ind]), gap) > gap_delta)) { + ind--; + } + gap_ind = ind; + } + } + + //if we consider that there is a gap, then we divide the signal with respect to this gap + //processing input data from the end + if(bin_raw_type == BinRAWTypeGap) { + bin_raw_debug_tag(TAG, "Tinted sequence\r\n"); + ind = (BIN_RAW_BUF_DATA_SIZE * 8); + uint16_t bit_count = 0; + do { + gap_ind--; + data_temp = (int)(round((float)(instance->data_raw[gap_ind]) / instance->te)); + bin_raw_debug("%d ", data_temp); + if(data_temp == 0) bit_count++; //there is noise in the package + for(size_t i = 0; i < abs(data_temp); i++) { + bit_count++; + if(ind) { + ind--; + } else { + break; + } + if(data_temp > 0) { + subghz_protocol_blocks_set_bit_array( + true, instance->data, ind, BIN_RAW_BUF_DATA_SIZE); + } else { + subghz_protocol_blocks_set_bit_array( + false, instance->data, ind, BIN_RAW_BUF_DATA_SIZE); + } + } + //split into full bytes if gap is caught + if(DURATION_DIFF(abs(instance->data_raw[gap_ind]), gap) < gap_delta) { + instance->data_markup[data_markup_ind].byte_bias = ind >> 3; + instance->data_markup[data_markup_ind++].bit_count = bit_count; + bit_count = 0; + + if(data_markup_ind == BIN_RAW_MAX_MARKUP_COUNT) break; + ind &= 0xFFFFFFF8; //jump to the pre whole byte + } + } while(gap_ind != 0); + if((data_markup_ind != BIN_RAW_MAX_MARKUP_COUNT) && (ind != 0)) { + instance->data_markup[data_markup_ind].byte_bias = ind >> 3; + instance->data_markup[data_markup_ind++].bit_count = bit_count; + } + + bin_raw_debug("\r\n\t count bit= %zu\r\n\r\n", (BIN_RAW_BUF_DATA_SIZE * 8) - ind); + + //reset the classifier and classify the received data + memset(classes, 0x00, sizeof(classes)); + + bin_raw_debug_tag(TAG, "Sort the found pieces by the number of bits in them\r\n"); + for(size_t i = 0; i < data_markup_ind; i++) { + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + if(classes[k].count == 0) { + classes[k].data = instance->data_markup[i].bit_count; + classes[k].count++; + break; + } else if(instance->data_markup[i].bit_count == (uint16_t)classes[k].data) { + classes[k].count++; + break; + } + } + } + +#ifdef BIN_RAW_DEBUG + bin_raw_debug("\t\tind\tcount\tus\r\n"); + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + bin_raw_debug("\t\t%zu\t%u\t%lu\r\n", k, classes[k].count, (uint32_t)classes[k].data); + } + bin_raw_debug("\r\n"); +#endif + + //choose the value with the maximum repetition + data_temp = 0; + for(size_t i = 0; i < BIN_RAW_SEARCH_CLASSES; i++) { + if((classes[i].count > 1) && (data_temp < classes[i].count)) + data_temp = (int)classes[i].data; + } + + //if(data_markup_ind == 0) return false; + +#ifdef BIN_RAW_DEBUG + //output in reverse order + bin_raw_debug_tag(TAG, "Found sequences\r\n"); + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data\r\n"); + uint16_t data_markup_ind_temp = data_markup_ind; + if(data_markup_ind) { + data_markup_ind_temp--; + for(size_t i = (ind / 8); i < BIN_RAW_BUF_DATA_SIZE; i++) { + if(instance->data_markup[data_markup_ind_temp].byte_bias == i) { + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + data_markup_ind_temp, + instance->data_markup[data_markup_ind_temp].byte_bias, + instance->data_markup[data_markup_ind_temp].bit_count); + if(data_markup_ind_temp != 0) data_markup_ind_temp--; + } + bin_raw_debug("%02X ", instance->data[i]); + } + bin_raw_debug("\r\n\r\n"); + } + //compare data in chunks with the same number of bits + bin_raw_debug_tag(TAG, "Analyze sequences of long %d bit\r\n\r\n", data_temp); +#endif + + //if(data_temp == 0) data_temp = (int)classes[0].data; + + if(data_temp != 0) { + //check that data in transmission is repeated every packet + for(uint16_t i = 0; i < data_markup_ind - 1; i++) { + if((instance->data_markup[i].bit_count == data_temp) && + (instance->data_markup[i + 1].bit_count == data_temp)) { + //if the number of bits in adjacent parcels is the same, compare the data + bin_raw_debug_tag( + TAG, + "Comparison of neighboring sequences ind_1=%d ind_2=%d %02X=%02X .... %02X=%02X\r\n", + i, + i + 1, + instance->data[instance->data_markup[i].byte_bias], + instance->data[instance->data_markup[i + 1].byte_bias], + instance->data + [instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i].bit_count) - + 1], + instance->data + [instance->data_markup[i + 1].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i + 1].bit_count) - + 1]); + + uint16_t byte_count = + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count); + if(memcmp( + instance->data + instance->data_markup[i].byte_bias, + instance->data + instance->data_markup[i + 1].byte_bias, + byte_count - 1) == 0) { + bin_raw_debug_tag( + TAG, "Match found bin_raw_type=BinRAWTypeGapRecurring\r\n\r\n"); + + //place in 1 element the offset to valid data + instance->data_markup[0].bit_count = instance->data_markup[i].bit_count; + instance->data_markup[0].byte_bias = instance->data_markup[i].byte_bias; + //markup end sign + instance->data_markup[1].bit_count = 0; + instance->data_markup[1].byte_bias = 0; + + bin_raw_type = BinRAWTypeGapRecurring; + i = data_markup_ind; + break; + } + } + } + } + + if(bin_raw_type == BinRAWTypeGap) { + // check that retry occurs every n packets + for(uint16_t i = 0; i < data_markup_ind - 2; i++) { + uint16_t byte_count = + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count); + for(uint16_t y = i + 1; y < data_markup_ind - 1; y++) { + bin_raw_debug_tag( + TAG, + "Comparison every N sequences ind_1=%d ind_2=%d %02X=%02X .... %02X=%02X\r\n", + i, + y, + instance->data[instance->data_markup[i].byte_bias], + instance->data[instance->data_markup[y].byte_bias], + instance->data + [instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i].bit_count) - + 1], + instance->data + [instance->data_markup[y].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[y].bit_count) - + 1]); + + if(byte_count == + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[y].bit_count)) { //if the length in bytes matches + + if((memcmp( + instance->data + instance->data_markup[i].byte_bias, + instance->data + instance->data_markup[y].byte_bias, + byte_count - 1) == 0) && + (memcmp( + instance->data + instance->data_markup[i + 1].byte_bias, + instance->data + instance->data_markup[y + 1].byte_bias, + byte_count - 1) == 0)) { + uint8_t index = 0; +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag( + TAG, "Match found bin_raw_type=BinRAWTypeGapRolling\r\n\r\n"); + //output in reverse order + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data\r\n"); + index = y - 1; + for(size_t z = instance->data_markup[y].byte_bias + byte_count; + z < instance->data_markup[i].byte_bias + byte_count; + z++) { + if(instance->data_markup[index].byte_bias == z) { + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + index, + instance->data_markup[index].byte_bias, + instance->data_markup[index].bit_count); + if(index != 0) index--; + } + bin_raw_debug("%02X ", instance->data[z]); + } + + bin_raw_debug("\r\n\r\n"); +#endif + //todo can be optimized + BinRAW_Markup markup_temp[BIN_RAW_MAX_MARKUP_COUNT]; + memcpy( + markup_temp, + instance->data_markup, + BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + memset( + instance->data_markup, + 0x00, + BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + + for(index = i; index < y; index++) { + instance->data_markup[index - i].bit_count = + markup_temp[y - index - 1].bit_count; + instance->data_markup[index - i].byte_bias = + markup_temp[y - index - 1].byte_bias; + } + + bin_raw_type = BinRAWTypeGapRolling; + i = data_markup_ind; + break; + } + } + } + } + } + //todo can be optimized + if(bin_raw_type == BinRAWTypeGap) { + if(data_temp != 0) { //there are sequences with the same number of bits + + BinRAW_Markup markup_temp[BIN_RAW_MAX_MARKUP_COUNT]; + memcpy( + markup_temp, + instance->data_markup, + BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + memset( + instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + uint16_t byte_count = subghz_protocol_bin_raw_get_full_byte(data_temp); + uint16_t index = 0; + uint16_t it = BIN_RAW_MAX_MARKUP_COUNT; + do { + it--; + if(subghz_protocol_bin_raw_get_full_byte(markup_temp[it].bit_count) == + byte_count) { + instance->data_markup[index].bit_count = markup_temp[it].bit_count; + instance->data_markup[index].byte_bias = markup_temp[it].byte_bias; + index++; + bin_raw_type = BinRAWTypeGapUnknown; + } + } while(it != 0); + } + } + + if(bin_raw_type != BinRAWTypeGap) + return true; + else + return false; + + } else { + // if bin_raw_type == BinRAWTypeGap + bin_raw_debug_tag(TAG, "Sequence analysis without gap\r\n"); + ind = 0; + for(size_t i = 0; i < instance->data_raw_ind; i++) { + int data_temp = (int)(round((float)(instance->data_raw[i]) / instance->te)); + if(data_temp == 0) break; //found an interval 2 times shorter than TE, this is noise + bin_raw_debug("%d ", data_temp); + + for(size_t k = 0; k < abs(data_temp); k++) { + if(data_temp > 0) { + subghz_protocol_blocks_set_bit_array( + true, instance->data, ind++, BIN_RAW_BUF_DATA_SIZE); + } else { + subghz_protocol_blocks_set_bit_array( + false, instance->data, ind++, BIN_RAW_BUF_DATA_SIZE); + } + if(ind == BIN_RAW_BUF_DATA_SIZE * 8) { + i = instance->data_raw_ind; + break; + } + } + } + + if(ind != 0) { + bin_raw_type = BinRAWTypeNoGap; + //right alignment + uint8_t bit_bias = (subghz_protocol_bin_raw_get_full_byte(ind) << 3) - ind; +#ifdef BIN_RAW_DEBUG + bin_raw_debug( + "\r\n\t count bit= %zu\tcount full byte= %d\tbias bit= %d\r\n\r\n", + ind, + subghz_protocol_bin_raw_get_full_byte(ind), + bit_bias); + + for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) { + bin_raw_debug("%02X ", instance->data[i]); + } + bin_raw_debug("\r\n\r\n"); +#endif + //checking that the received sequence contains useful data + bool data_check = false; + for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) { + if(instance->data[i] != 0) { + data_check = true; + break; + } + } + + if(data_check) { + for(size_t i = subghz_protocol_bin_raw_get_full_byte(ind) - 1; i > 0; i--) { + instance->data[i] = (instance->data[i - 1] << (8 - bit_bias)) | + (instance->data[i] >> bit_bias); + } + instance->data[0] = (instance->data[0] >> bit_bias); + +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag(TAG, "Data right alignment\r\n"); + for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) { + bin_raw_debug("%02X ", instance->data[i]); + } + bin_raw_debug("\r\n\r\n"); +#endif + instance->data_markup[0].bit_count = ind; + instance->data_markup[0].byte_bias = 0; + + return true; + } else { + return false; + } + } else { + return false; + } + } + return false; +} + +void subghz_protocol_decoder_bin_raw_data_input_rssi( + SubGhzProtocolDecoderBinRAW* instance, + float rssi) { + furi_assert(instance); + switch(instance->decoder.parser_step) { + case BinRAWDecoderStepReset: + + bin_raw_debug("%ld %ld :", (int32_t)rssi, (int32_t)instance->adaptive_threshold_rssi); + if(rssi > (instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI)) { + instance->data_raw_ind = 0; + memset(instance->data_raw, 0x00, BIN_RAW_BUF_RAW_SIZE * sizeof(int32_t)); + memset(instance->data, 0x00, BIN_RAW_BUF_RAW_SIZE * sizeof(uint8_t)); + instance->decoder.parser_step = BinRAWDecoderStepWrite; + bin_raw_debug_tag(TAG, "RSSI\r\n"); + } else { + //adaptive noise level adjustment + instance->adaptive_threshold_rssi += (rssi - instance->adaptive_threshold_rssi) * 0.2f; + } + break; + + case BinRAWDecoderStepBufFull: + case BinRAWDecoderStepWrite: +#ifdef BIN_RAW_DEBUG + if(rssi > (instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI)) { + bin_raw_debug("\033[0;32m%ld \033[0m ", (int32_t)rssi); + } else { + bin_raw_debug("%ld ", (int32_t)rssi); + } +#endif + if(rssi < instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI) { +#ifdef BIN_RAW_DEBUG + bin_raw_debug("\r\n\r\n"); + bin_raw_debug_tag(TAG, "Data for analysis, positive high, negative low, us\r\n"); + for(size_t i = 0; i < instance->data_raw_ind; i++) { + bin_raw_debug("%ld ", instance->data_raw[i]); + } + bin_raw_debug("\r\n\t count data= %zu\r\n\r\n", instance->data_raw_ind); +#endif + instance->decoder.parser_step = BinRAWDecoderStepReset; + instance->generic.data_count_bit = 0; + if(instance->data_raw_ind >= BIN_RAW_BUF_MIN_DATA_COUNT) { + if(subghz_protocol_bin_raw_check_remote_controller(instance)) { + bin_raw_debug_tag(TAG, "Sequence found\r\n"); + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data"); + uint16_t i = 0; + while((i < BIN_RAW_MAX_MARKUP_COUNT) && + (instance->data_markup[i].bit_count != 0)) { + instance->generic.data_count_bit += instance->data_markup[i].bit_count; +#ifdef BIN_RAW_DEBUG + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + i, + instance->data_markup[i].byte_bias, + instance->data_markup[i].bit_count); + for(uint16_t y = instance->data_markup[i].byte_bias; + y < instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i].bit_count); + y++) { + bin_raw_debug("%02X ", instance->data[y]); + } +#endif + i++; + } + bin_raw_debug("\r\n"); + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + } + } + break; + + default: + //if instance->decoder.parser_step == BinRAWDecoderStepNoParse or others, restore the initial state + if(rssi < instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI) { + instance->decoder.parser_step = BinRAWDecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_bin_raw_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + return subghz_protocol_blocks_add_bytes( + instance->data + instance->data_markup[0].byte_bias, + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[0].bit_count)); +} + +bool subghz_protocol_decoder_bin_raw_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + + bool res = false; + FuriString* temp_str; + temp_str = furi_string_alloc(); + do { + stream_clean(flipper_format_get_raw_stream(flipper_format)); + if(!flipper_format_write_header_cstr( + flipper_format, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) { + FURI_LOG_E(TAG, "Unable to add header"); + break; + } + + if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) { + FURI_LOG_E(TAG, "Unable to add Frequency"); + break; + } + + subghz_block_generic_get_preset_name(furi_string_get_cstr(preset->name), temp_str); + if(!flipper_format_write_string_cstr( + flipper_format, "Preset", furi_string_get_cstr(temp_str))) { + FURI_LOG_E(TAG, "Unable to add Preset"); + break; + } + if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { + if(!flipper_format_write_string_cstr( + flipper_format, "Custom_preset_module", "CC1101")) { + FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); + break; + } + if(!flipper_format_write_hex( + flipper_format, "Custom_preset_data", preset->data, preset->data_size)) { + FURI_LOG_E(TAG, "Unable to add Custom_preset_data"); + break; + } + } + if(!flipper_format_write_string_cstr( + flipper_format, "Protocol", instance->generic.protocol_name)) { + FURI_LOG_E(TAG, "Unable to add Protocol"); + break; + } + + uint32_t temp = instance->generic.data_count_bit; + if(!flipper_format_write_uint32(flipper_format, "Bit", &temp, 1)) { + FURI_LOG_E(TAG, "Unable to add Bit"); + break; + } + + if(!flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { + FURI_LOG_E(TAG, "Unable to add TE"); + break; + } + + uint16_t i = 0; + while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) { + temp = instance->data_markup[i].bit_count; + if(!flipper_format_write_uint32(flipper_format, "Bit_RAW", &temp, 1)) { + FURI_LOG_E(TAG, "Bit_RAW"); + break; + } + if(!flipper_format_write_hex( + flipper_format, + "Data_RAW", + instance->data + instance->data_markup[i].byte_bias, + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count))) { + FURI_LOG_E(TAG, "Unable to add Data_RAW"); + break; + } + i++; + } + + res = true; + } while(false); + furi_string_free(temp_str); + return res; +} + +bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + + bool res = false; + uint32_t temp_data = 0; + + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { + FURI_LOG_E(TAG, "Missing Bit"); + break; + } + + instance->generic.data_count_bit = (uint16_t)temp_data; + + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + + temp_data = 0; + uint16_t ind = 0; + uint16_t byte_bias = 0; + uint16_t byte_count = 0; + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) { + if(ind >= BIN_RAW_MAX_MARKUP_COUNT) { + FURI_LOG_E(TAG, "Markup overflow"); + break; + } + byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data); + if(byte_count > BIN_RAW_BUF_DATA_SIZE) { + FURI_LOG_E(TAG, "Receive buffer overflow"); + break; + } + + instance->data_markup[ind].bit_count = temp_data; + instance->data_markup[ind].byte_bias = byte_bias; + byte_bias += subghz_protocol_bin_raw_get_full_byte(temp_data); + + if(!flipper_format_read_hex( + flipper_format, + "Data_RAW", + instance->data + instance->data_markup[ind].byte_bias, + subghz_protocol_bin_raw_get_full_byte(temp_data))) { + instance->data_markup[ind].bit_count = 0; + FURI_LOG_E(TAG, "Missing Data_RAW"); + break; + } + ind++; + } + + res = true; + } while(0); + + return res; +} + +void subghz_protocol_decoder_bin_raw_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:", + instance->generic.protocol_name, + instance->generic.data_count_bit); + + uint16_t byte_count = subghz_protocol_bin_raw_get_full_byte(instance->generic.data_count_bit); + for(size_t i = 0; (byte_count < 36 ? i < byte_count : i < 36); i++) { + furi_string_cat_printf(output, "%02X", instance->data[i]); + } + + furi_string_cat_printf(output, "\r\nTe:%luus\r\n", instance->te); +} diff --git a/lib/subghz/protocols/bin_raw.h b/lib/subghz/protocols/bin_raw.h new file mode 100644 index 000000000..c63f86ce6 --- /dev/null +++ b/lib/subghz/protocols/bin_raw.h @@ -0,0 +1,111 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_BIN_RAW_NAME "BinRAW" + +typedef struct SubGhzProtocolDecoderBinRAW SubGhzProtocolDecoderBinRAW; +typedef struct SubGhzProtocolEncoderBinRAW SubGhzProtocolEncoderBinRAW; + +extern const SubGhzProtocolDecoder subghz_protocol_bin_raw_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_bin_raw_encoder; +extern const SubGhzProtocol subghz_protocol_bin_raw; + +/** + * Allocate SubGhzProtocolEncoderBinRAW. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderBinRAW* pointer to a SubGhzProtocolEncoderBinRAW instance + */ +void* subghz_protocol_encoder_bin_raw_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderBinRAW. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + */ +void subghz_protocol_encoder_bin_raw_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + */ +void subghz_protocol_encoder_bin_raw_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_bin_raw_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderBinRAW. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderBinRAW* pointer to a SubGhzProtocolDecoderBinRAW instance + */ +void* subghz_protocol_decoder_bin_raw_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + */ +void subghz_protocol_decoder_bin_raw_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + */ +void subghz_protocol_decoder_bin_raw_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_bin_raw_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_bin_raw_get_hash_data(void* context); + +void subghz_protocol_decoder_bin_raw_data_input_rssi( + SubGhzProtocolDecoderBinRAW* instance, + float rssi); + +/** + * Serialize data SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_bin_raw_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param output Resulting text + */ +void subghz_protocol_decoder_bin_raw_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 32f4e9520..9c8e5ee4a 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -196,12 +196,13 @@ static bool break; } - instance->encoder.size_upload = subghz_protocol_blocks_get_upload( + instance->encoder.size_upload = subghz_protocol_blocks_get_upload_from_bit_array( upload_hex_data, upload_hex_count_bit, instance->encoder.upload, instance->encoder.size_upload, - subghz_protocol_chamb_code_const.te_short); + subghz_protocol_chamb_code_const.te_short, + SubGhzProtocolBlockAlignBitLeft); return true; } diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 050904eec..74244c5ff 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -42,6 +42,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_dooya, &subghz_protocol_alutech_at_4n, &subghz_protocol_kinggates_stylo_4k, + &subghz_protocol_bin_raw, }; const SubGhzProtocolRegistry subghz_protocol_registry = { diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index 522931d22..4ca1c4679 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -42,5 +42,6 @@ #include "dooya.h" #include "alutech_at_4n.h" #include "kinggates_stylo_4k.h" +#include "bin_raw.h" extern const SubGhzProtocolRegistry subghz_protocol_registry; diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index 7b79892b0..f7262bd17 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -261,16 +261,16 @@ static bool data = order << 4 | invert; int k = 0; for(int i = 6; i >= 0; i -= 2) { - roll_array[k++] = (data >> i) & 0x03; - if(roll_array[k] == 3) { + roll_array[k] = (data >> i) & 0x03; + if(roll_array[k++] == 3) { FURI_LOG_E(TAG, "Roll_Array FAIL"); return false; } } for(int i = 8; i >= 0; i -= 2) { - roll_array[k++] = (p[2] >> i) & 0x03; - if(roll_array[k] == 3) { + roll_array[k] = (p[2] >> i) & 0x03; + if(roll_array[k++] == 3) { FURI_LOG_E(TAG, "Roll_Array FAIL"); return false; } diff --git a/lib/subghz/receiver.c b/lib/subghz/receiver.c index fd6f1493e..698fe098e 100644 --- a/lib/subghz/receiver.c +++ b/lib/subghz/receiver.c @@ -64,7 +64,7 @@ void subghz_receiver_decode(SubGhzReceiver* instance, bool level, uint32_t durat for M_EACH(slot, instance->slots, SubGhzReceiverSlotArray_t) { - if((slot->base->protocol->flag & instance->filter) == instance->filter) { + if((slot->base->protocol->flag & instance->filter) != 0) { slot->base->protocol->decoder->feed(slot->base, level, duration); } } diff --git a/lib/subghz/types.h b/lib/subghz/types.h index 6c34dc728..1b8ef6a14 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -90,6 +90,7 @@ typedef enum { SubGhzProtocolFlag_Save = (1 << 7), SubGhzProtocolFlag_Load = (1 << 8), SubGhzProtocolFlag_Send = (1 << 9), + SubGhzProtocolFlag_BinRAW = (1 << 10), } SubGhzProtocolFlag; typedef struct { diff --git a/lib/toolbox/level_duration.h b/lib/toolbox/level_duration.h index 9406cef31..7618344ac 100644 --- a/lib/toolbox/level_duration.h +++ b/lib/toolbox/level_duration.h @@ -13,8 +13,8 @@ #define LEVEL_DURATION_RESERVED 0x800000U typedef struct { - uint32_t level; - uint32_t duration; + uint32_t duration : 30; + uint8_t level : 2; } LevelDuration; static inline LevelDuration level_duration_make(bool level, uint32_t duration) { From 4265057ee864a8d68a68e9a9ef4088b39d2b1e5c Mon Sep 17 00:00:00 2001 From: Petr Portnov | PROgrm_JARvis Date: Thu, 9 Feb 2023 07:58:01 +0300 Subject: [PATCH 4/4] feat: add missing `const` qualifiers (#2233) * feat: make `ViewPort` getters const * feat: make tx-buffers const * feat: make `canvas_get_buffer_size` const * feat: make `canvas` methods const * feat: make `icon_animation` methods const * feat: make `scene_manager` methods const * feat: make `loader` method const * feat: make `canvas_get_font_params` const Co-authored-by: Aleksandr Kutuzov --- applications/services/gui/canvas.c | 12 +++--- applications/services/gui/canvas.h | 8 ++-- applications/services/gui/canvas_i.h | 2 +- applications/services/gui/elements.c | 2 +- applications/services/gui/gui.c | 2 +- applications/services/gui/gui.h | 2 +- applications/services/gui/icon_animation.c | 8 ++-- applications/services/gui/icon_animation.h | 6 +-- applications/services/gui/icon_animation_i.h | 2 +- .../widget_element_text_scroll.c | 4 +- applications/services/gui/scene_manager.c | 4 +- applications/services/gui/scene_manager.h | 4 +- applications/services/gui/view_port.c | 6 +-- applications/services/gui/view_port.h | 6 +-- applications/services/loader/loader.c | 2 +- applications/services/loader/loader.h | 2 +- applications/services/locale/locale.h | 2 +- firmware/targets/f18/api_symbols.csv | 35 ++++++++--------- firmware/targets/f7/api_symbols.csv | 38 +++++++++---------- firmware/targets/f7/furi_hal/furi_hal_spi.c | 4 +- .../targets/furi_hal_include/furi_hal_spi.h | 4 +- 21 files changed, 78 insertions(+), 77 deletions(-) diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 18636eced..d47bba6b2 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -57,7 +57,7 @@ uint8_t* canvas_get_buffer(Canvas* canvas) { return u8g2_GetBufferPtr(&canvas->fb); } -size_t canvas_get_buffer_size(Canvas* canvas) { +size_t canvas_get_buffer_size(const Canvas* canvas) { furi_assert(canvas); return u8g2_GetBufferTileWidth(&canvas->fb) * u8g2_GetBufferTileHeight(&canvas->fb) * 8; } @@ -75,17 +75,17 @@ void canvas_frame_set( canvas->height = height; } -uint8_t canvas_width(Canvas* canvas) { +uint8_t canvas_width(const Canvas* canvas) { furi_assert(canvas); return canvas->width; } -uint8_t canvas_height(Canvas* canvas) { +uint8_t canvas_height(const Canvas* canvas) { furi_assert(canvas); return canvas->height; } -uint8_t canvas_current_font_height(Canvas* canvas) { +uint8_t canvas_current_font_height(const Canvas* canvas) { furi_assert(canvas); uint8_t font_height = u8g2_GetMaxCharHeight(&canvas->fb); @@ -96,10 +96,10 @@ uint8_t canvas_current_font_height(Canvas* canvas) { return font_height; } -CanvasFontParameters* canvas_get_font_params(Canvas* canvas, Font font) { +const CanvasFontParameters* canvas_get_font_params(const Canvas* canvas, Font font) { furi_assert(canvas); furi_assert(font < FontTotalNumber); - return (CanvasFontParameters*)&canvas_font_params[font]; + return &canvas_font_params[font]; } void canvas_clear(Canvas* canvas) { diff --git a/applications/services/gui/canvas.h b/applications/services/gui/canvas.h index b2a065ca7..f8fe2c1db 100644 --- a/applications/services/gui/canvas.h +++ b/applications/services/gui/canvas.h @@ -85,7 +85,7 @@ void canvas_commit(Canvas* canvas); * * @return width in pixels. */ -uint8_t canvas_width(Canvas* canvas); +uint8_t canvas_width(const Canvas* canvas); /** Get Canvas height * @@ -93,7 +93,7 @@ uint8_t canvas_width(Canvas* canvas); * * @return height in pixels. */ -uint8_t canvas_height(Canvas* canvas); +uint8_t canvas_height(const Canvas* canvas); /** Get current font height * @@ -101,7 +101,7 @@ uint8_t canvas_height(Canvas* canvas); * * @return height in pixels. */ -uint8_t canvas_current_font_height(Canvas* canvas); +uint8_t canvas_current_font_height(const Canvas* canvas); /** Get font parameters * @@ -110,7 +110,7 @@ uint8_t canvas_current_font_height(Canvas* canvas); * * @return pointer to CanvasFontParameters structure */ -CanvasFontParameters* canvas_get_font_params(Canvas* canvas, Font font); +const CanvasFontParameters* canvas_get_font_params(const Canvas* canvas, Font font); /** Clear canvas * diff --git a/applications/services/gui/canvas_i.h b/applications/services/gui/canvas_i.h index 2b6849235..12cabfa7d 100644 --- a/applications/services/gui/canvas_i.h +++ b/applications/services/gui/canvas_i.h @@ -45,7 +45,7 @@ uint8_t* canvas_get_buffer(Canvas* canvas); * * @return size of canvas in bytes */ -size_t canvas_get_buffer_size(Canvas* canvas); +size_t canvas_get_buffer_size(const Canvas* canvas); /** Set drawing region relative to real screen buffer * diff --git a/applications/services/gui/elements.c b/applications/services/gui/elements.c index 54c36af76..9b7c84ece 100644 --- a/applications/services/gui/elements.c +++ b/applications/services/gui/elements.c @@ -639,7 +639,7 @@ void elements_text_box( bool inversed_present = false; Font current_font = FontSecondary; Font prev_font = FontSecondary; - CanvasFontParameters* font_params = canvas_get_font_params(canvas, current_font); + const CanvasFontParameters* font_params = canvas_get_font_params(canvas, current_font); // Fill line parameters uint8_t line_leading_min = font_params->leading_min; diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index af5cf862d..94bab1402 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -467,7 +467,7 @@ void gui_remove_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, gui_unlock(gui); } -size_t gui_get_framebuffer_size(Gui* gui) { +size_t gui_get_framebuffer_size(const Gui* gui) { furi_assert(gui); return canvas_get_buffer_size(gui->canvas); } diff --git a/applications/services/gui/gui.h b/applications/services/gui/gui.h index 4e7fc2e4d..d7d73f27b 100644 --- a/applications/services/gui/gui.h +++ b/applications/services/gui/gui.h @@ -94,7 +94,7 @@ void gui_remove_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, * @param gui Gui instance * @return size_t size of frame buffer in bytes */ -size_t gui_get_framebuffer_size(Gui* gui); +size_t gui_get_framebuffer_size(const Gui* gui); /** Set lockdown mode * diff --git a/applications/services/gui/icon_animation.c b/applications/services/gui/icon_animation.c index 48c862208..b63d233f3 100644 --- a/applications/services/gui/icon_animation.c +++ b/applications/services/gui/icon_animation.c @@ -29,7 +29,7 @@ void icon_animation_set_update_callback( instance->callback_context = context; } -const uint8_t* icon_animation_get_data(IconAnimation* instance) { +const uint8_t* icon_animation_get_data(const IconAnimation* instance) { return instance->icon->frames[instance->frame]; } @@ -51,12 +51,12 @@ void icon_animation_timer_callback(void* context) { } } -uint8_t icon_animation_get_width(IconAnimation* instance) { +uint8_t icon_animation_get_width(const IconAnimation* instance) { furi_assert(instance); return instance->icon->width; } -uint8_t icon_animation_get_height(IconAnimation* instance) { +uint8_t icon_animation_get_height(const IconAnimation* instance) { furi_assert(instance); return instance->icon->height; } @@ -83,7 +83,7 @@ void icon_animation_stop(IconAnimation* instance) { } } -bool icon_animation_is_last_frame(IconAnimation* instance) { +bool icon_animation_is_last_frame(const IconAnimation* instance) { furi_assert(instance); return instance->icon->frame_count - instance->frame <= 1; } diff --git a/applications/services/gui/icon_animation.h b/applications/services/gui/icon_animation.h index 684790353..6e58df31d 100644 --- a/applications/services/gui/icon_animation.h +++ b/applications/services/gui/icon_animation.h @@ -55,7 +55,7 @@ void icon_animation_set_update_callback( * * @return width in pixels */ -uint8_t icon_animation_get_width(IconAnimation* instance); +uint8_t icon_animation_get_width(const IconAnimation* instance); /** Get icon animation height * @@ -63,7 +63,7 @@ uint8_t icon_animation_get_width(IconAnimation* instance); * * @return height in pixels */ -uint8_t icon_animation_get_height(IconAnimation* instance); +uint8_t icon_animation_get_height(const IconAnimation* instance); /** Start icon animation * @@ -83,7 +83,7 @@ void icon_animation_stop(IconAnimation* instance); * * @return true if last frame */ -bool icon_animation_is_last_frame(IconAnimation* instance); +bool icon_animation_is_last_frame(const IconAnimation* instance); #ifdef __cplusplus } diff --git a/applications/services/gui/icon_animation_i.h b/applications/services/gui/icon_animation_i.h index 4053a120d..62858d288 100644 --- a/applications/services/gui/icon_animation_i.h +++ b/applications/services/gui/icon_animation_i.h @@ -24,7 +24,7 @@ struct IconAnimation { * * @return pointer to current frame XBM bitmap data */ -const uint8_t* icon_animation_get_data(IconAnimation* instance); +const uint8_t* icon_animation_get_data(const IconAnimation* instance); /** Advance to next frame * diff --git a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c index d8fc11311..5d522c74b 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c +++ b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c @@ -74,7 +74,7 @@ static void widget_element_text_scroll_fill_lines(Canvas* canvas, WidgetElement* } // Set canvas font canvas_set_font(canvas, line_tmp.font); - CanvasFontParameters* params = canvas_get_font_params(canvas, line_tmp.font); + const CanvasFontParameters* params = canvas_get_font_params(canvas, line_tmp.font); total_height += params->height; if(total_height > model->height) { model->scroll_pos_total++; @@ -138,7 +138,7 @@ static void widget_element_text_scroll_draw(Canvas* canvas, WidgetElement* eleme TextScrollLineArray_next(it), curr_line++) { if(curr_line < model->scroll_pos_current) continue; TextScrollLineArray* line = TextScrollLineArray_ref(it); - CanvasFontParameters* params = canvas_get_font_params(canvas, line->font); + const CanvasFontParameters* params = canvas_get_font_params(canvas, line->font); if(y + params->descender > model->y + model->height) break; canvas_set_font(canvas, line->font); if(line->horizontal == AlignLeft) { diff --git a/applications/services/gui/scene_manager.c b/applications/services/gui/scene_manager.c index 590145e1e..4064dafb6 100644 --- a/applications/services/gui/scene_manager.c +++ b/applications/services/gui/scene_manager.c @@ -34,7 +34,7 @@ void scene_manager_set_scene_state(SceneManager* scene_manager, uint32_t scene_i scene_manager->scene[scene_id].state = state; } -uint32_t scene_manager_get_scene_state(SceneManager* scene_manager, uint32_t scene_id) { +uint32_t scene_manager_get_scene_state(const SceneManager* scene_manager, uint32_t scene_id) { furi_assert(scene_manager); furi_assert(scene_id < scene_manager->scene_handlers->scene_num); @@ -184,7 +184,7 @@ bool scene_manager_search_and_switch_to_previous_scene_one_of( return scene_found; } -bool scene_manager_has_previous_scene(SceneManager* scene_manager, uint32_t scene_id) { +bool scene_manager_has_previous_scene(const SceneManager* scene_manager, uint32_t scene_id) { furi_assert(scene_manager); bool scene_found = false; diff --git a/applications/services/gui/scene_manager.h b/applications/services/gui/scene_manager.h index 5b833e5de..c349a12ce 100644 --- a/applications/services/gui/scene_manager.h +++ b/applications/services/gui/scene_manager.h @@ -63,7 +63,7 @@ void scene_manager_set_scene_state(SceneManager* scene_manager, uint32_t scene_i * * @return Scene state */ -uint32_t scene_manager_get_scene_state(SceneManager* scene_manager, uint32_t scene_id); +uint32_t scene_manager_get_scene_state(const SceneManager* scene_manager, uint32_t scene_id); /** Scene Manager allocation and configuration * @@ -134,7 +134,7 @@ bool scene_manager_previous_scene(SceneManager* scene_manager); * * @return true if previous scene was found, false otherwise */ -bool scene_manager_has_previous_scene(SceneManager* scene_manager, uint32_t scene_id); +bool scene_manager_has_previous_scene(const SceneManager* scene_manager, uint32_t scene_id); /** Search and switch to previous Scene * diff --git a/applications/services/gui/view_port.c b/applications/services/gui/view_port.c index ffd01450b..5760ed577 100644 --- a/applications/services/gui/view_port.c +++ b/applications/services/gui/view_port.c @@ -89,7 +89,7 @@ void view_port_set_width(ViewPort* view_port, uint8_t width) { view_port->width = width; } -uint8_t view_port_get_width(ViewPort* view_port) { +uint8_t view_port_get_width(const ViewPort* view_port) { furi_assert(view_port); return view_port->width; } @@ -99,7 +99,7 @@ void view_port_set_height(ViewPort* view_port, uint8_t height) { view_port->height = height; } -uint8_t view_port_get_height(ViewPort* view_port) { +uint8_t view_port_get_height(const ViewPort* view_port) { furi_assert(view_port); return view_port->height; } @@ -112,7 +112,7 @@ void view_port_enabled_set(ViewPort* view_port, bool enabled) { } } -bool view_port_is_enabled(ViewPort* view_port) { +bool view_port_is_enabled(const ViewPort* view_port) { furi_assert(view_port); return view_port->is_enabled; } diff --git a/applications/services/gui/view_port.h b/applications/services/gui/view_port.h index 703e99248..752fc46ba 100644 --- a/applications/services/gui/view_port.h +++ b/applications/services/gui/view_port.h @@ -56,7 +56,7 @@ void view_port_free(ViewPort* view_port); * @param width wanted width, 0 - auto. */ void view_port_set_width(ViewPort* view_port, uint8_t width); -uint8_t view_port_get_width(ViewPort* view_port); +uint8_t view_port_get_width(const ViewPort* view_port); /** Set view_port height. * @@ -66,7 +66,7 @@ uint8_t view_port_get_width(ViewPort* view_port); * @param height wanted height, 0 - auto. */ void view_port_set_height(ViewPort* view_port, uint8_t height); -uint8_t view_port_get_height(ViewPort* view_port); +uint8_t view_port_get_height(const ViewPort* view_port); /** Enable or disable view_port rendering. * @@ -75,7 +75,7 @@ uint8_t view_port_get_height(ViewPort* view_port); * @warning automatically dispatches update event */ void view_port_enabled_set(ViewPort* view_port, bool enabled); -bool view_port_is_enabled(ViewPort* view_port); +bool view_port_is_enabled(const ViewPort* view_port); /** ViewPort event callbacks * diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index 97d1e6e4e..caaf9f11b 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -262,7 +262,7 @@ void loader_unlock(Loader* instance) { FURI_CRITICAL_EXIT(); } -bool loader_is_locked(Loader* instance) { +bool loader_is_locked(const Loader* instance) { return instance->lock_count > 0; } diff --git a/applications/services/loader/loader.h b/applications/services/loader/loader.h index 954e79c57..8dbc4fc35 100644 --- a/applications/services/loader/loader.h +++ b/applications/services/loader/loader.h @@ -43,7 +43,7 @@ bool loader_lock(Loader* instance); void loader_unlock(Loader* instance); /** Get loader lock status */ -bool loader_is_locked(Loader* instance); +bool loader_is_locked(const Loader* instance); /** Show primary loader */ void loader_show_menu(); diff --git a/applications/services/locale/locale.h b/applications/services/locale/locale.h index 5f2a4d87f..61fb4c605 100644 --- a/applications/services/locale/locale.h +++ b/applications/services/locale/locale.h @@ -81,7 +81,7 @@ void locale_format_time( * * @return The Locale DateFormat. */ -LocaleDateFormat locale_get_date_format(); +LocaleDateFormat locale_get_date_format(void); /** Set Locale DateFormat * diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index d29d696fc..462fbf739 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,13.1,, +Version,+,14.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -522,7 +522,7 @@ Function,-,bzero,void,"void*, size_t" Function,-,calloc,void*,"size_t, size_t" Function,+,canvas_clear,void,Canvas* Function,+,canvas_commit,void,Canvas* -Function,+,canvas_current_font_height,uint8_t,Canvas* +Function,+,canvas_current_font_height,uint8_t,const Canvas* Function,+,canvas_draw_bitmap,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" Function,+,canvas_draw_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,canvas_draw_circle,void,"Canvas*, uint8_t, uint8_t, uint8_t" @@ -539,9 +539,9 @@ Function,+,canvas_draw_str,void,"Canvas*, uint8_t, uint8_t, const char*" Function,+,canvas_draw_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" Function,+,canvas_draw_triangle,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, CanvasDirection" Function,+,canvas_draw_xbm,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" -Function,+,canvas_get_font_params,CanvasFontParameters*,"Canvas*, Font" +Function,+,canvas_get_font_params,const CanvasFontParameters*,"const Canvas*, Font" Function,+,canvas_glyph_width,uint8_t,"Canvas*, char" -Function,+,canvas_height,uint8_t,Canvas* +Function,+,canvas_height,uint8_t,const Canvas* Function,+,canvas_invert_color,void,Canvas* Function,+,canvas_reset,void,Canvas* Function,+,canvas_set_bitmap_mode,void,"Canvas*, _Bool" @@ -550,7 +550,7 @@ Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*" Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" -Function,+,canvas_width,uint8_t,Canvas* +Function,+,canvas_width,uint8_t,const Canvas* Function,-,cfree,void,void* Function,-,clearerr,void,FILE* Function,-,clearerr_unlocked,void,FILE* @@ -1063,9 +1063,9 @@ Function,+,furi_hal_spi_bus_handle_deinit,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus* Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, uint8_t*, size_t, uint32_t" Function,+,furi_hal_spi_bus_trx_dma,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, size_t, uint32_t" Function,-,furi_hal_spi_config_deinit_early,void, Function,-,furi_hal_spi_config_init,void, Function,-,furi_hal_spi_config_init_early,void, @@ -1123,6 +1123,7 @@ Function,+,furi_kernel_unlock,int32_t, Function,+,furi_log_get_level,FuriLogLevel, Function,-,furi_log_init,void, Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..." +Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..." Function,+,furi_log_set_level,void,FuriLogLevel Function,-,furi_log_set_puts,void,FuriLogPuts Function,-,furi_log_set_timestamp,void,FuriLogTimestamp @@ -1287,7 +1288,7 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_direct_draw_acquire,Canvas*,Gui* Function,+,gui_direct_draw_release,void,Gui* -Function,+,gui_get_framebuffer_size,size_t,Gui* +Function,+,gui_get_framebuffer_size,size_t,const Gui* Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" Function,+,gui_set_lockdown,void,"Gui*, _Bool" @@ -1301,9 +1302,9 @@ Function,+,hmac_sha256_init,void,"hmac_sha256_context*, const uint8_t*" Function,+,hmac_sha256_update,void,"const hmac_sha256_context*, const uint8_t*, unsigned" Function,+,icon_animation_alloc,IconAnimation*,const Icon* Function,+,icon_animation_free,void,IconAnimation* -Function,+,icon_animation_get_height,uint8_t,IconAnimation* -Function,+,icon_animation_get_width,uint8_t,IconAnimation* -Function,+,icon_animation_is_last_frame,_Bool,IconAnimation* +Function,+,icon_animation_get_height,uint8_t,const IconAnimation* +Function,+,icon_animation_get_width,uint8_t,const IconAnimation* +Function,+,icon_animation_is_last_frame,_Bool,const IconAnimation* Function,+,icon_animation_set_update_callback,void,"IconAnimation*, IconAnimationCallback, void*" Function,+,icon_animation_start,void,IconAnimation* Function,+,icon_animation_stop,void,IconAnimation* @@ -1352,7 +1353,7 @@ Function,-,ldiv,ldiv_t,"long, long" Function,-,llabs,long long,long long Function,-,lldiv,lldiv_t,"long long, long long" Function,+,loader_get_pubsub,FuriPubSub*,Loader* -Function,+,loader_is_locked,_Bool,Loader* +Function,+,loader_is_locked,_Bool,const Loader* Function,+,loader_lock,_Bool,Loader* Function,+,loader_show_menu,void, Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*" @@ -1570,11 +1571,11 @@ Function,+,saved_struct_save,_Bool,"const char*, void*, size_t, uint8_t, uint8_t Function,-,scanf,int,"const char*, ..." Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*" Function,+,scene_manager_free,void,SceneManager* -Function,+,scene_manager_get_scene_state,uint32_t,"SceneManager*, uint32_t" +Function,+,scene_manager_get_scene_state,uint32_t,"const SceneManager*, uint32_t" Function,+,scene_manager_handle_back_event,_Bool,SceneManager* Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t" Function,+,scene_manager_handle_tick_event,void,SceneManager* -Function,+,scene_manager_has_previous_scene,_Bool,"SceneManager*, uint32_t" +Function,+,scene_manager_has_previous_scene,_Bool,"const SceneManager*, uint32_t" Function,+,scene_manager_next_scene,void,"SceneManager*, uint32_t" Function,+,scene_manager_previous_scene,_Bool,SceneManager* Function,+,scene_manager_search_and_switch_to_another_scene,_Bool,"SceneManager*, uint32_t" @@ -1946,11 +1947,11 @@ Function,+,view_port_alloc,ViewPort*, Function,+,view_port_draw_callback_set,void,"ViewPort*, ViewPortDrawCallback, void*" Function,+,view_port_enabled_set,void,"ViewPort*, _Bool" Function,+,view_port_free,void,ViewPort* -Function,+,view_port_get_height,uint8_t,ViewPort* +Function,+,view_port_get_height,uint8_t,const ViewPort* Function,+,view_port_get_orientation,ViewPortOrientation,const ViewPort* -Function,+,view_port_get_width,uint8_t,ViewPort* +Function,+,view_port_get_width,uint8_t,const ViewPort* Function,+,view_port_input_callback_set,void,"ViewPort*, ViewPortInputCallback, void*" -Function,+,view_port_is_enabled,_Bool,ViewPort* +Function,+,view_port_is_enabled,_Bool,const ViewPort* Function,+,view_port_set_height,void,"ViewPort*, uint8_t" Function,+,view_port_set_orientation,void,"ViewPort*, ViewPortOrientation" Function,+,view_port_set_width,void,"ViewPort*, uint8_t" diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 906ab357a..33c443ae0 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,13.1,, +Version,+,14.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -607,7 +607,7 @@ Function,-,bzero,void,"void*, size_t" Function,-,calloc,void*,"size_t, size_t" Function,+,canvas_clear,void,Canvas* Function,+,canvas_commit,void,Canvas* -Function,+,canvas_current_font_height,uint8_t,Canvas* +Function,+,canvas_current_font_height,uint8_t,const Canvas* Function,+,canvas_draw_bitmap,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" Function,+,canvas_draw_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,canvas_draw_circle,void,"Canvas*, uint8_t, uint8_t, uint8_t" @@ -624,18 +624,18 @@ Function,+,canvas_draw_str,void,"Canvas*, uint8_t, uint8_t, const char*" Function,+,canvas_draw_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" Function,+,canvas_draw_triangle,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, CanvasDirection" Function,+,canvas_draw_xbm,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" -Function,+,canvas_get_font_params,CanvasFontParameters*,"Canvas*, Font" +Function,+,canvas_get_font_params,const CanvasFontParameters*,"const Canvas*, Font" Function,+,canvas_glyph_width,uint8_t,"Canvas*, char" -Function,+,canvas_height,uint8_t,Canvas* +Function,+,canvas_height,uint8_t,const Canvas* Function,+,canvas_invert_color,void,Canvas* Function,+,canvas_reset,void,Canvas* Function,+,canvas_set_bitmap_mode,void,"Canvas*, _Bool" Function,+,canvas_set_color,void,"Canvas*, Color" -Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*" +Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" -Function,+,canvas_width,uint8_t,Canvas* +Function,+,canvas_width,uint8_t,const Canvas* Function,-,cbrt,double,double Function,-,cbrtf,float,float Function,-,cbrtl,long double,long double @@ -1095,7 +1095,6 @@ Function,-,furi_hal_flash_write_dword,void,"size_t, uint64_t" Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*" Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin* Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin* -Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin* Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed" Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn" Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode" @@ -1249,6 +1248,7 @@ Function,+,furi_hal_region_is_frequency_allowed,_Bool,uint32_t Function,+,furi_hal_region_is_provisioned,_Bool, Function,+,furi_hal_region_set,void,FuriHalRegion* Function,-,furi_hal_resources_deinit_early,void, +Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin* Function,-,furi_hal_resources_init,void, Function,-,furi_hal_resources_init_early,void, Function,+,furi_hal_rfid_change_read_config,void,"float, float" @@ -1319,9 +1319,9 @@ Function,+,furi_hal_spi_bus_handle_deinit,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus* Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, uint8_t*, size_t, uint32_t" Function,+,furi_hal_spi_bus_trx_dma,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, size_t, uint32_t" Function,-,furi_hal_spi_config_deinit_early,void, Function,-,furi_hal_spi_config_init,void, Function,-,furi_hal_spi_config_init_early,void, @@ -1578,7 +1578,7 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_direct_draw_acquire,Canvas*,Gui* Function,+,gui_direct_draw_release,void,Gui* -Function,+,gui_get_framebuffer_size,size_t,Gui* +Function,+,gui_get_framebuffer_size,size_t,const Gui* Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" Function,+,gui_set_lockdown,void,"Gui*, _Bool" @@ -1621,9 +1621,9 @@ Function,+,ibutton_worker_write_set_callback,void,"iButtonWorker*, iButtonWorker Function,+,ibutton_worker_write_start,void,"iButtonWorker*, iButtonKey*" Function,+,icon_animation_alloc,IconAnimation*,const Icon* Function,+,icon_animation_free,void,IconAnimation* -Function,+,icon_animation_get_height,uint8_t,IconAnimation* -Function,+,icon_animation_get_width,uint8_t,IconAnimation* -Function,+,icon_animation_is_last_frame,_Bool,IconAnimation* +Function,+,icon_animation_get_height,uint8_t,const IconAnimation* +Function,+,icon_animation_get_width,uint8_t,const IconAnimation* +Function,+,icon_animation_is_last_frame,_Bool,const IconAnimation* Function,+,icon_animation_set_update_callback,void,"IconAnimation*, IconAnimationCallback, void*" Function,+,icon_animation_start,void,IconAnimation* Function,+,icon_animation_stop,void,IconAnimation* @@ -1763,7 +1763,7 @@ Function,-,llround,long long int,double Function,-,llroundf,long long int,float Function,-,llroundl,long long int,long double Function,+,loader_get_pubsub,FuriPubSub*,Loader* -Function,+,loader_is_locked,_Bool,Loader* +Function,+,loader_is_locked,_Bool,const Loader* Function,+,loader_lock,_Bool,Loader* Function,+,loader_show_menu,void, Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*" @@ -2372,11 +2372,11 @@ Function,-,scalbnl,long double,"long double, int" Function,-,scanf,int,"const char*, ..." Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*" Function,+,scene_manager_free,void,SceneManager* -Function,+,scene_manager_get_scene_state,uint32_t,"SceneManager*, uint32_t" +Function,+,scene_manager_get_scene_state,uint32_t,"const SceneManager*, uint32_t" Function,+,scene_manager_handle_back_event,_Bool,SceneManager* Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t" Function,+,scene_manager_handle_tick_event,void,SceneManager* -Function,+,scene_manager_has_previous_scene,_Bool,"SceneManager*, uint32_t" +Function,+,scene_manager_has_previous_scene,_Bool,"const SceneManager*, uint32_t" Function,+,scene_manager_next_scene,void,"SceneManager*, uint32_t" Function,+,scene_manager_previous_scene,_Bool,SceneManager* Function,+,scene_manager_search_and_switch_to_another_scene,_Bool,"SceneManager*, uint32_t" @@ -2895,11 +2895,11 @@ Function,+,view_port_alloc,ViewPort*, Function,+,view_port_draw_callback_set,void,"ViewPort*, ViewPortDrawCallback, void*" Function,+,view_port_enabled_set,void,"ViewPort*, _Bool" Function,+,view_port_free,void,ViewPort* -Function,+,view_port_get_height,uint8_t,ViewPort* +Function,+,view_port_get_height,uint8_t,const ViewPort* Function,+,view_port_get_orientation,ViewPortOrientation,const ViewPort* -Function,+,view_port_get_width,uint8_t,ViewPort* +Function,+,view_port_get_width,uint8_t,const ViewPort* Function,+,view_port_input_callback_set,void,"ViewPort*, ViewPortInputCallback, void*" -Function,+,view_port_is_enabled,_Bool,ViewPort* +Function,+,view_port_is_enabled,_Bool,const ViewPort* Function,+,view_port_set_height,void,"ViewPort*, uint8_t" Function,+,view_port_set_orientation,void,"ViewPort*, ViewPortOrientation" Function,+,view_port_set_width,void,"ViewPort*, uint8_t" diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi.c b/firmware/targets/f7/furi_hal/furi_hal_spi.c index 8dba8327f..42b854799 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi.c +++ b/firmware/targets/f7/furi_hal/furi_hal_spi.c @@ -103,7 +103,7 @@ bool furi_hal_spi_bus_rx( bool furi_hal_spi_bus_tx( FuriHalSpiBusHandle* handle, - uint8_t* buffer, + const uint8_t* buffer, size_t size, uint32_t timeout) { furi_assert(handle); @@ -128,7 +128,7 @@ bool furi_hal_spi_bus_tx( bool furi_hal_spi_bus_trx( FuriHalSpiBusHandle* handle, - uint8_t* tx_buffer, + const uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { diff --git a/firmware/targets/furi_hal_include/furi_hal_spi.h b/firmware/targets/furi_hal_include/furi_hal_spi.h index 79e809317..af15a8838 100644 --- a/firmware/targets/furi_hal_include/furi_hal_spi.h +++ b/firmware/targets/furi_hal_include/furi_hal_spi.h @@ -85,7 +85,7 @@ bool furi_hal_spi_bus_rx( */ bool furi_hal_spi_bus_tx( FuriHalSpiBusHandle* handle, - uint8_t* buffer, + const uint8_t* buffer, size_t size, uint32_t timeout); @@ -101,7 +101,7 @@ bool furi_hal_spi_bus_tx( */ bool furi_hal_spi_bus_trx( FuriHalSpiBusHandle* handle, - uint8_t* tx_buffer, + const uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout);