From 4c39dcbe0c40c89f92df93d8b572799e39e603e1 Mon Sep 17 00:00:00 2001 From: Anna Prosvetova Date: Sun, 31 Jul 2022 01:14:16 +0200 Subject: [PATCH 01/22] =?UTF-8?q?=E2=98=A6=EF=B8=8F=20Rpc:=20fix=20backup?= =?UTF-8?q?=20commands=20responses=20(#1502)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/rpc/rpc_storage.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/applications/rpc/rpc_storage.c b/applications/rpc/rpc_storage.c index 89c94b03f..d2b43ff66 100644 --- a/applications/rpc/rpc_storage.c +++ b/applications/rpc/rpc_storage.c @@ -594,23 +594,19 @@ static void rpc_system_storage_backup_create_process(const PB_Main* request, voi FURI_LOG_D(TAG, "BackupCreate"); - RpcSession* session = (RpcSession*)context; + RpcStorageSystem* rpc_storage = context; + RpcSession* session = rpc_storage->session; furi_assert(session); - PB_Main* response = malloc(sizeof(PB_Main)); - response->command_id = request->command_id; - response->has_next = false; - Storage* fs_api = furi_record_open(RECORD_STORAGE); bool backup_ok = lfs_backup_create(fs_api, request->content.storage_backup_create_request.archive_path); - response->command_status = backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR; furi_record_close(RECORD_STORAGE); - rpc_send_and_release(session, response); - free(response); + rpc_send_and_release_empty( + session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR); } static void rpc_system_storage_backup_restore_process(const PB_Main* request, void* context) { @@ -619,24 +615,19 @@ static void rpc_system_storage_backup_restore_process(const PB_Main* request, vo FURI_LOG_D(TAG, "BackupRestore"); - RpcSession* session = (RpcSession*)context; + RpcStorageSystem* rpc_storage = context; + RpcSession* session = rpc_storage->session; furi_assert(session); - PB_Main* response = malloc(sizeof(PB_Main)); - response->command_id = request->command_id; - response->has_next = false; - response->command_status = PB_CommandStatus_OK; - Storage* fs_api = furi_record_open(RECORD_STORAGE); bool backup_ok = lfs_backup_unpack(fs_api, request->content.storage_backup_restore_request.archive_path); - response->command_status = backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR; furi_record_close(RECORD_STORAGE); - rpc_send_and_release(session, response); - free(response); + rpc_send_and_release_empty( + session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR); } void* rpc_system_storage_alloc(RpcSession* session) { From 712a48b5db166a401cae9f6ca986d5aaeca7a1a5 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sun, 31 Jul 2022 02:34:38 +0300 Subject: [PATCH 02/22] Fix typo in subghz (#1467) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix typo across subghz Co-authored-by: あく Co-authored-by: Aleksandr Kutuzov --- applications/subghz/helpers/subghz_types.h | 4 ++-- applications/subghz/scenes/subghz_scene_receiver_info.c | 4 ++-- applications/subghz/subghz.c | 2 +- applications/subghz/subghz_history.c | 8 ++++---- applications/subghz/subghz_history.h | 6 +++--- applications/subghz/subghz_i.h | 2 +- lib/subghz/blocks/generic.c | 2 +- lib/subghz/blocks/generic.h | 4 ++-- lib/subghz/protocols/base.c | 2 +- lib/subghz/protocols/base.h | 4 ++-- lib/subghz/protocols/came.c | 2 +- lib/subghz/protocols/came.h | 4 ++-- lib/subghz/protocols/came_atomo.c | 2 +- lib/subghz/protocols/came_atomo.h | 4 ++-- lib/subghz/protocols/came_twee.c | 2 +- lib/subghz/protocols/came_twee.h | 4 ++-- lib/subghz/protocols/chamberlain_code.c | 2 +- lib/subghz/protocols/chamberlain_code.h | 4 ++-- lib/subghz/protocols/faac_slh.c | 2 +- lib/subghz/protocols/faac_slh.h | 4 ++-- lib/subghz/protocols/gate_tx.c | 2 +- lib/subghz/protocols/gate_tx.h | 4 ++-- lib/subghz/protocols/holtek.c | 2 +- lib/subghz/protocols/holtek.h | 4 ++-- lib/subghz/protocols/hormann.c | 2 +- lib/subghz/protocols/hormann.h | 4 ++-- lib/subghz/protocols/ido.c | 2 +- lib/subghz/protocols/ido.h | 4 ++-- lib/subghz/protocols/keeloq.c | 4 ++-- lib/subghz/protocols/keeloq.h | 8 ++++---- lib/subghz/protocols/kia.c | 2 +- lib/subghz/protocols/kia.h | 4 ++-- lib/subghz/protocols/linear.c | 2 +- lib/subghz/protocols/linear.h | 4 ++-- lib/subghz/protocols/megacode.c | 2 +- lib/subghz/protocols/megacode.h | 4 ++-- lib/subghz/protocols/nero_radio.c | 2 +- lib/subghz/protocols/nero_radio.h | 4 ++-- lib/subghz/protocols/nero_sketch.c | 2 +- lib/subghz/protocols/nero_sketch.h | 4 ++-- lib/subghz/protocols/nice_flo.c | 2 +- lib/subghz/protocols/nice_flo.h | 4 ++-- lib/subghz/protocols/nice_flor_s.c | 2 +- lib/subghz/protocols/nice_flor_s.h | 4 ++-- lib/subghz/protocols/power_smart.c | 2 +- lib/subghz/protocols/power_smart.h | 4 ++-- lib/subghz/protocols/princeton.c | 2 +- lib/subghz/protocols/princeton.h | 4 ++-- lib/subghz/protocols/raw.c | 2 +- lib/subghz/protocols/raw.h | 4 ++-- lib/subghz/protocols/scher_khan.c | 2 +- lib/subghz/protocols/scher_khan.h | 4 ++-- lib/subghz/protocols/secplus_v1.c | 2 +- lib/subghz/protocols/secplus_v1.h | 4 ++-- lib/subghz/protocols/secplus_v2.c | 4 ++-- lib/subghz/protocols/secplus_v2.h | 8 ++++---- lib/subghz/protocols/somfy_keytis.c | 2 +- lib/subghz/protocols/somfy_keytis.h | 4 ++-- lib/subghz/protocols/somfy_telis.c | 2 +- lib/subghz/protocols/somfy_telis.h | 4 ++-- lib/subghz/protocols/star_line.c | 2 +- lib/subghz/protocols/star_line.h | 4 ++-- lib/subghz/types.h | 6 ++++-- 63 files changed, 107 insertions(+), 105 deletions(-) diff --git a/applications/subghz/helpers/subghz_types.h b/applications/subghz/helpers/subghz_types.h index 1b9fe816d..8da4c8f53 100644 --- a/applications/subghz/helpers/subghz_types.h +++ b/applications/subghz/helpers/subghz_types.h @@ -72,11 +72,11 @@ typedef enum { SubGhzViewIdTestPacket, } SubGhzViewId; -struct SubGhzPesetDefinition { +struct SubGhzPresetDefinition { string_t name; uint32_t frequency; uint8_t* data; size_t data_size; }; -typedef struct SubGhzPesetDefinition SubGhzPesetDefinition; +typedef struct SubGhzPresetDefinition SubGhzPresetDefinition; diff --git a/applications/subghz/scenes/subghz_scene_receiver_info.c b/applications/subghz/scenes/subghz_scene_receiver_info.c index 40051eee2..cbda1bc7b 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/subghz/scenes/subghz_scene_receiver_info.c @@ -28,8 +28,8 @@ static bool subghz_scene_receiver_info_update_parser(void* context) { subghz->txrx->decoder_result, subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); - SubGhzPesetDefinition* preset = - subghz_history_get_presset(subghz->txrx->history, subghz->txrx->idx_menu_chosen); + SubGhzPresetDefinition* preset = + subghz_history_get_preset_def(subghz->txrx->history, subghz->txrx->idx_menu_chosen); subghz_preset_init( subghz, string_get_cstr(preset->name), diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 271fe041f..a970e10c4 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -199,7 +199,7 @@ SubGhz* subghz_alloc() { //init Worker & Protocol & History & KeyBoard subghz->lock = SubGhzLockOff; subghz->txrx = malloc(sizeof(SubGhzTxRx)); - subghz->txrx->preset = malloc(sizeof(SubGhzPesetDefinition)); + subghz->txrx->preset = malloc(sizeof(SubGhzPresetDefinition)); string_init(subghz->txrx->preset->name); subghz_preset_init( subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0); diff --git a/applications/subghz/subghz_history.c b/applications/subghz/subghz_history.c index f234f4c72..820a13d14 100644 --- a/applications/subghz/subghz_history.c +++ b/applications/subghz/subghz_history.c @@ -12,7 +12,7 @@ typedef struct { string_t item_str; FlipperFormat* flipper_string; uint8_t type; - SubGhzPesetDefinition* preset; + SubGhzPresetDefinition* preset; } SubGhzHistoryItem; ARRAY_DEF(SubGhzHistoryItemArray, SubGhzHistoryItem, M_POD_OPLIST) @@ -61,7 +61,7 @@ uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx) { return item->preset->frequency; } -SubGhzPesetDefinition* subghz_history_get_presset(SubGhzHistory* instance, uint16_t idx) { +SubGhzPresetDefinition* subghz_history_get_preset_def(SubGhzHistory* instance, uint16_t idx) { furi_assert(instance); SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx); return item->preset; @@ -139,7 +139,7 @@ void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, bool subghz_history_add_to_history( SubGhzHistory* instance, void* context, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(instance); furi_assert(context); @@ -159,7 +159,7 @@ bool subghz_history_add_to_history( string_t text; string_init(text); SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data); - item->preset = malloc(sizeof(SubGhzPesetDefinition)); + item->preset = malloc(sizeof(SubGhzPresetDefinition)); item->type = decoder_base->protocol->type; item->preset->frequency = preset->frequency; string_init(item->preset->name); diff --git a/applications/subghz/subghz_history.h b/applications/subghz/subghz_history.h index 0af56a40e..adbcfc18a 100644 --- a/applications/subghz/subghz_history.h +++ b/applications/subghz/subghz_history.h @@ -35,7 +35,7 @@ void subghz_history_reset(SubGhzHistory* instance); */ uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx); -SubGhzPesetDefinition* subghz_history_get_presset(SubGhzHistory* instance, uint16_t idx); +SubGhzPresetDefinition* subghz_history_get_preset_def(SubGhzHistory* instance, uint16_t idx); /** Get preset to history[idx] * @@ -88,13 +88,13 @@ bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output * * @param instance - SubGhzHistory instance * @param context - SubGhzProtocolCommon context - * @param preset - SubGhzPesetDefinition preset + * @param preset - SubGhzPresetDefinition preset * @return bool; */ bool subghz_history_add_to_history( SubGhzHistory* instance, void* context, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data * diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index 52c3ba599..01fbe57be 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -49,7 +49,7 @@ struct SubGhzTxRx { SubGhzProtocolDecoderBase* decoder_result; FlipperFormat* fff_data; - SubGhzPesetDefinition* preset; + SubGhzPresetDefinition* preset; SubGhzHistory* history; uint16_t idx_menu_chosen; SubGhzTxRxState txrx_state; diff --git a/lib/subghz/blocks/generic.c b/lib/subghz/blocks/generic.c index 187c30e6a..353ff18bf 100644 --- a/lib/subghz/blocks/generic.c +++ b/lib/subghz/blocks/generic.c @@ -23,7 +23,7 @@ void subghz_block_generic_get_preset_name(const char* preset_name, string_t pres bool subghz_block_generic_serialize( SubGhzBlockGeneric* instance, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(instance); bool res = false; string_t temp_str; diff --git a/lib/subghz/blocks/generic.h b/lib/subghz/blocks/generic.h index e1256ea4b..56a7fc2d3 100644 --- a/lib/subghz/blocks/generic.h +++ b/lib/subghz/blocks/generic.h @@ -31,13 +31,13 @@ void subghz_block_generic_get_preset_name(const char* preset_name, string_t pres * Serialize data SubGhzBlockGeneric. * @param instance Pointer to a SubGhzBlockGeneric instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_block_generic_serialize( SubGhzBlockGeneric* instance, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzBlockGeneric. diff --git a/lib/subghz/protocols/base.c b/lib/subghz/protocols/base.c index 32c64cce2..06542f5eb 100644 --- a/lib/subghz/protocols/base.c +++ b/lib/subghz/protocols/base.c @@ -26,7 +26,7 @@ bool subghz_protocol_decoder_base_get_string( bool subghz_protocol_decoder_base_serialize( SubGhzProtocolDecoderBase* decoder_base, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { bool status = false; if(decoder_base->protocol && decoder_base->protocol->decoder && diff --git a/lib/subghz/protocols/base.h b/lib/subghz/protocols/base.h index ad237bbe5..a1a7478d9 100644 --- a/lib/subghz/protocols/base.h +++ b/lib/subghz/protocols/base.h @@ -43,13 +43,13 @@ bool subghz_protocol_decoder_base_get_string( * Serialize data SubGhzProtocolDecoderBase. * @param decoder_base Pointer to a SubGhzProtocolDecoderBase instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_base_serialize( SubGhzProtocolDecoderBase* decoder_base, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderBase. diff --git a/lib/subghz/protocols/came.c b/lib/subghz/protocols/came.c index 1d2045ca0..145320aea 100644 --- a/lib/subghz/protocols/came.c +++ b/lib/subghz/protocols/came.c @@ -284,7 +284,7 @@ uint8_t subghz_protocol_decoder_came_get_hash_data(void* context) { bool subghz_protocol_decoder_came_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderCame* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/came.h b/lib/subghz/protocols/came.h index abd3044b8..c2648c057 100644 --- a/lib/subghz/protocols/came.h +++ b/lib/subghz/protocols/came.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_came_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderCame. * @param context Pointer to a SubGhzProtocolDecoderCame instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_came_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderCame. diff --git a/lib/subghz/protocols/came_atomo.c b/lib/subghz/protocols/came_atomo.c index 2178b4d1d..5781837d8 100644 --- a/lib/subghz/protocols/came_atomo.c +++ b/lib/subghz/protocols/came_atomo.c @@ -301,7 +301,7 @@ uint8_t subghz_protocol_decoder_came_atomo_get_hash_data(void* context) { bool subghz_protocol_decoder_came_atomo_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderCameAtomo* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/came_atomo.h b/lib/subghz/protocols/came_atomo.h index eaba74c89..70a79eca1 100644 --- a/lib/subghz/protocols/came_atomo.h +++ b/lib/subghz/protocols/came_atomo.h @@ -48,13 +48,13 @@ uint8_t subghz_protocol_decoder_came_atomo_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderCameAtomo. * @param context Pointer to a SubGhzProtocolDecoderCameAtomo instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_came_atomo_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderCameAtomo. diff --git a/lib/subghz/protocols/came_twee.c b/lib/subghz/protocols/came_twee.c index 7310d6f9e..89367a1e4 100644 --- a/lib/subghz/protocols/came_twee.c +++ b/lib/subghz/protocols/came_twee.c @@ -418,7 +418,7 @@ uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context) { bool subghz_protocol_decoder_came_twee_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderCameTwee* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/came_twee.h b/lib/subghz/protocols/came_twee.h index 66a894238..42e6ddaf3 100644 --- a/lib/subghz/protocols/came_twee.h +++ b/lib/subghz/protocols/came_twee.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderCameTwee. * @param context Pointer to a SubGhzProtocolDecoderCameTwee instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_came_twee_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderCameTwee. diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 409584217..08b3e12c2 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -423,7 +423,7 @@ uint8_t subghz_protocol_decoder_chamb_code_get_hash_data(void* context) { bool subghz_protocol_decoder_chamb_code_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderChamb_Code* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/chamberlain_code.h b/lib/subghz/protocols/chamberlain_code.h index e25e54c23..1ac2f9f96 100644 --- a/lib/subghz/protocols/chamberlain_code.h +++ b/lib/subghz/protocols/chamberlain_code.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_chamb_code_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderChamb_Code. * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_chamb_code_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderChamb_Code. diff --git a/lib/subghz/protocols/faac_slh.c b/lib/subghz/protocols/faac_slh.c index caa8e5ebc..78c456f83 100644 --- a/lib/subghz/protocols/faac_slh.c +++ b/lib/subghz/protocols/faac_slh.c @@ -183,7 +183,7 @@ uint8_t subghz_protocol_decoder_faac_slh_get_hash_data(void* context) { bool subghz_protocol_decoder_faac_slh_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderFaacSLH* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/faac_slh.h b/lib/subghz/protocols/faac_slh.h index f1ad14525..fe7a79265 100644 --- a/lib/subghz/protocols/faac_slh.h +++ b/lib/subghz/protocols/faac_slh.h @@ -49,13 +49,13 @@ uint8_t subghz_protocol_decoder_faac_slh_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderFaacSLH. * @param context Pointer to a SubGhzProtocolDecoderFaacSLH instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_faac_slh_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderFaacSLH. diff --git a/lib/subghz/protocols/gate_tx.c b/lib/subghz/protocols/gate_tx.c index a172eb3ca..7a295c091 100644 --- a/lib/subghz/protocols/gate_tx.c +++ b/lib/subghz/protocols/gate_tx.c @@ -289,7 +289,7 @@ uint8_t subghz_protocol_decoder_gate_tx_get_hash_data(void* context) { bool subghz_protocol_decoder_gate_tx_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderGateTx* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/gate_tx.h b/lib/subghz/protocols/gate_tx.h index f296a27e7..171576816 100644 --- a/lib/subghz/protocols/gate_tx.h +++ b/lib/subghz/protocols/gate_tx.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_gate_tx_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderGateTx. * @param context Pointer to a SubGhzProtocolDecoderGateTx instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_gate_tx_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderGateTx. diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c index c24bdf6ff..55b991f62 100644 --- a/lib/subghz/protocols/holtek.c +++ b/lib/subghz/protocols/holtek.c @@ -322,7 +322,7 @@ uint8_t subghz_protocol_decoder_holtek_get_hash_data(void* context) { bool subghz_protocol_decoder_holtek_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderHoltek* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/holtek.h b/lib/subghz/protocols/holtek.h index cc962dcc9..df7dd6448 100644 --- a/lib/subghz/protocols/holtek.h +++ b/lib/subghz/protocols/holtek.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_holtek_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderHoltek. * @param context Pointer to a SubGhzProtocolDecoderHoltek instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_holtek_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderHoltek. diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index 696aaf619..f6f684cc1 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -310,7 +310,7 @@ uint8_t subghz_protocol_decoder_hormann_get_hash_data(void* context) { bool subghz_protocol_decoder_hormann_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderHormann* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/hormann.h b/lib/subghz/protocols/hormann.h index 04634ff0c..45d6eb223 100644 --- a/lib/subghz/protocols/hormann.h +++ b/lib/subghz/protocols/hormann.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_hormann_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderHormann. * @param context Pointer to a SubGhzProtocolDecoderHormann instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_hormann_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderHormann. diff --git a/lib/subghz/protocols/ido.c b/lib/subghz/protocols/ido.c index 2f5a9195e..e6de577d1 100644 --- a/lib/subghz/protocols/ido.c +++ b/lib/subghz/protocols/ido.c @@ -182,7 +182,7 @@ uint8_t subghz_protocol_decoder_ido_get_hash_data(void* context) { bool subghz_protocol_decoder_ido_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderIDo* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/ido.h b/lib/subghz/protocols/ido.h index d2328218f..4fe4e740a 100644 --- a/lib/subghz/protocols/ido.h +++ b/lib/subghz/protocols/ido.h @@ -49,13 +49,13 @@ uint8_t subghz_protocol_decoder_ido_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderIDo. * @param context Pointer to a SubGhzProtocolDecoderIDo instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_ido_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderIDo. diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index de18e2948..a25454bee 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -174,7 +174,7 @@ bool subghz_protocol_keeloq_create_data( uint8_t btn, uint16_t cnt, const char* manufacture_name, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolEncoderKeeloq* instance = context; instance->generic.serial = serial; @@ -631,7 +631,7 @@ uint8_t subghz_protocol_decoder_keeloq_get_hash_data(void* context) { bool subghz_protocol_decoder_keeloq_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderKeeloq* instance = context; subghz_protocol_keeloq_check_remote_controller( diff --git a/lib/subghz/protocols/keeloq.h b/lib/subghz/protocols/keeloq.h index 2a590b0d2..e1485e5ef 100644 --- a/lib/subghz/protocols/keeloq.h +++ b/lib/subghz/protocols/keeloq.h @@ -32,7 +32,7 @@ void subghz_protocol_encoder_keeloq_free(void* context); * @param btn Button number, 4 bit * @param cnt Container value, 16 bit * @param manufacture_name Name of manufacturer's key - * @param preset Modulation, SubGhzPesetDefinition + * @param preset Modulation, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_keeloq_create_data( @@ -42,7 +42,7 @@ bool subghz_protocol_keeloq_create_data( uint8_t btn, uint16_t cnt, const char* manufacture_name, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize and generating an upload to send. @@ -103,13 +103,13 @@ uint8_t subghz_protocol_decoder_keeloq_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderKeeloq. * @param context Pointer to a SubGhzProtocolDecoderKeeloq instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_keeloq_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderKeeloq. diff --git a/lib/subghz/protocols/kia.c b/lib/subghz/protocols/kia.c index 069eb8f1d..9a3b8f39b 100644 --- a/lib/subghz/protocols/kia.c +++ b/lib/subghz/protocols/kia.c @@ -233,7 +233,7 @@ uint8_t subghz_protocol_decoder_kia_get_hash_data(void* context) { bool subghz_protocol_decoder_kia_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderKIA* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/kia.h b/lib/subghz/protocols/kia.h index a32940463..743ab7cbd 100644 --- a/lib/subghz/protocols/kia.h +++ b/lib/subghz/protocols/kia.h @@ -49,13 +49,13 @@ uint8_t subghz_protocol_decoder_kia_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderKIA. * @param context Pointer to a SubGhzProtocolDecoderKIA instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_kia_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderKIA. diff --git a/lib/subghz/protocols/linear.c b/lib/subghz/protocols/linear.c index a8c9dad68..652bf0bf6 100644 --- a/lib/subghz/protocols/linear.c +++ b/lib/subghz/protocols/linear.c @@ -299,7 +299,7 @@ uint8_t subghz_protocol_decoder_linear_get_hash_data(void* context) { bool subghz_protocol_decoder_linear_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderLinear* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/linear.h b/lib/subghz/protocols/linear.h index 5060d4440..035b130c4 100644 --- a/lib/subghz/protocols/linear.h +++ b/lib/subghz/protocols/linear.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_linear_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderLinear. * @param context Pointer to a SubGhzProtocolDecoderLinear instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_linear_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderLinear. diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c index 8a1f67b5a..542fd8b37 100644 --- a/lib/subghz/protocols/megacode.c +++ b/lib/subghz/protocols/megacode.c @@ -380,7 +380,7 @@ uint8_t subghz_protocol_decoder_megacode_get_hash_data(void* context) { bool subghz_protocol_decoder_megacode_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderMegaCode* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/megacode.h b/lib/subghz/protocols/megacode.h index f25011d7b..c8010665b 100644 --- a/lib/subghz/protocols/megacode.h +++ b/lib/subghz/protocols/megacode.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_megacode_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderMegaCode. * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_megacode_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderMegaCode. diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index 7dcb59759..50c79f609 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -342,7 +342,7 @@ uint8_t subghz_protocol_decoder_nero_radio_get_hash_data(void* context) { bool subghz_protocol_decoder_nero_radio_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderNeroRadio* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/nero_radio.h b/lib/subghz/protocols/nero_radio.h index f1c540d5b..f04dc2b3c 100644 --- a/lib/subghz/protocols/nero_radio.h +++ b/lib/subghz/protocols/nero_radio.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_nero_radio_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderNeroRadio. * @param context Pointer to a SubGhzProtocolDecoderNeroRadio instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_nero_radio_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderNeroRadio. diff --git a/lib/subghz/protocols/nero_sketch.c b/lib/subghz/protocols/nero_sketch.c index a4e9f2cfb..461bbcea2 100644 --- a/lib/subghz/protocols/nero_sketch.c +++ b/lib/subghz/protocols/nero_sketch.c @@ -327,7 +327,7 @@ uint8_t subghz_protocol_decoder_nero_sketch_get_hash_data(void* context) { bool subghz_protocol_decoder_nero_sketch_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderNeroSketch* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/nero_sketch.h b/lib/subghz/protocols/nero_sketch.h index af93a9d9a..ab592b48e 100644 --- a/lib/subghz/protocols/nero_sketch.h +++ b/lib/subghz/protocols/nero_sketch.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_nero_sketch_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderNeroSketch. * @param context Pointer to a SubGhzProtocolDecoderNeroSketch instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_nero_sketch_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderNeroSketch. diff --git a/lib/subghz/protocols/nice_flo.c b/lib/subghz/protocols/nice_flo.c index 1b8e03088..4c4ede933 100644 --- a/lib/subghz/protocols/nice_flo.c +++ b/lib/subghz/protocols/nice_flo.c @@ -277,7 +277,7 @@ uint8_t subghz_protocol_decoder_nice_flo_get_hash_data(void* context) { bool subghz_protocol_decoder_nice_flo_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderNiceFlo* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/nice_flo.h b/lib/subghz/protocols/nice_flo.h index f7d48dfa7..0873e81b9 100644 --- a/lib/subghz/protocols/nice_flo.h +++ b/lib/subghz/protocols/nice_flo.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_nice_flo_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderNiceFlo. * @param context Pointer to a SubGhzProtocolDecoderNiceFlo instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_nice_flo_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderNiceFlo. diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index 381e7bd13..1a02149cb 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -330,7 +330,7 @@ uint8_t subghz_protocol_decoder_nice_flor_s_get_hash_data(void* context) { bool subghz_protocol_decoder_nice_flor_s_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderNiceFlorS* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/nice_flor_s.h b/lib/subghz/protocols/nice_flor_s.h index fc27da38b..7d98876f6 100644 --- a/lib/subghz/protocols/nice_flor_s.h +++ b/lib/subghz/protocols/nice_flor_s.h @@ -49,13 +49,13 @@ uint8_t subghz_protocol_decoder_nice_flor_s_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderNiceFlorS. * @param context Pointer to a SubGhzProtocolDecoderNiceFlorS instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_nice_flor_s_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderNiceFlorS. diff --git a/lib/subghz/protocols/power_smart.c b/lib/subghz/protocols/power_smart.c index 3c356ff88..df8eb4fd1 100644 --- a/lib/subghz/protocols/power_smart.c +++ b/lib/subghz/protocols/power_smart.c @@ -345,7 +345,7 @@ uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context) { bool subghz_protocol_decoder_power_smart_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderPowerSmart* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/power_smart.h b/lib/subghz/protocols/power_smart.h index e6445ca46..f6e9571b1 100644 --- a/lib/subghz/protocols/power_smart.h +++ b/lib/subghz/protocols/power_smart.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderPowerSmart. * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_power_smart_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderPowerSmart. diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index ce34d32cf..b283d273b 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -300,7 +300,7 @@ uint8_t subghz_protocol_decoder_princeton_get_hash_data(void* context) { bool subghz_protocol_decoder_princeton_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderPrinceton* instance = context; bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/princeton.h b/lib/subghz/protocols/princeton.h index fb126f2df..9c296c4a1 100644 --- a/lib/subghz/protocols/princeton.h +++ b/lib/subghz/protocols/princeton.h @@ -83,13 +83,13 @@ uint8_t subghz_protocol_decoder_princeton_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderPrinceton. * @param context Pointer to a SubGhzProtocolDecoderPrinceton instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_princeton_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderPrinceton. diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index 92f20438a..ec4ed41f4 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -83,7 +83,7 @@ const SubGhzProtocol subghz_protocol_raw = { bool subghz_protocol_raw_save_to_file_init( SubGhzProtocolDecoderRAW* instance, const char* dev_name, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(instance); instance->storage = furi_record_open(RECORD_STORAGE); diff --git a/lib/subghz/protocols/raw.h b/lib/subghz/protocols/raw.h index a6435d335..5d6bb084e 100644 --- a/lib/subghz/protocols/raw.h +++ b/lib/subghz/protocols/raw.h @@ -17,13 +17,13 @@ extern const SubGhzProtocol subghz_protocol_raw; * Open file for writing * @param instance Pointer to a SubGhzProtocolDecoderRAW instance * @param dev_name File name - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_raw_save_to_file_init( SubGhzProtocolDecoderRAW* instance, const char* dev_name, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Stop writing file to flash diff --git a/lib/subghz/protocols/scher_khan.c b/lib/subghz/protocols/scher_khan.c index 7c9aa6a7f..dd8d4c8fa 100644 --- a/lib/subghz/protocols/scher_khan.c +++ b/lib/subghz/protocols/scher_khan.c @@ -251,7 +251,7 @@ uint8_t subghz_protocol_decoder_scher_khan_get_hash_data(void* context) { bool subghz_protocol_decoder_scher_khan_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderScherKhan* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/scher_khan.h b/lib/subghz/protocols/scher_khan.h index b22e89343..391ccc414 100644 --- a/lib/subghz/protocols/scher_khan.h +++ b/lib/subghz/protocols/scher_khan.h @@ -49,13 +49,13 @@ uint8_t subghz_protocol_decoder_scher_khan_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderScherKhan. * @param context Pointer to a SubGhzProtocolDecoderScherKhan instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_scher_khan_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderScherKhan. diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index 119c03070..1e25a439d 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -515,7 +515,7 @@ uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context) { bool subghz_protocol_decoder_secplus_v1_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderSecPlus_v1* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/secplus_v1.h b/lib/subghz/protocols/secplus_v1.h index 5447e3f84..8ae1c0cb2 100644 --- a/lib/subghz/protocols/secplus_v1.h +++ b/lib/subghz/protocols/secplus_v1.h @@ -82,13 +82,13 @@ uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderSecPlus_v1. * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_secplus_v1_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderSecPlus_v1. diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index 837b26387..3f28ee7ea 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -588,7 +588,7 @@ bool subghz_protocol_secplus_v2_create_data( uint32_t serial, uint8_t btn, uint32_t cnt, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolEncoderSecPlus_v2* instance = context; instance->generic.serial = serial; @@ -755,7 +755,7 @@ uint8_t subghz_protocol_decoder_secplus_v2_get_hash_data(void* context) { bool subghz_protocol_decoder_secplus_v2_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderSecPlus_v2* instance = context; bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/secplus_v2.h b/lib/subghz/protocols/secplus_v2.h index 43bce6293..9e9ae2a7d 100644 --- a/lib/subghz/protocols/secplus_v2.h +++ b/lib/subghz/protocols/secplus_v2.h @@ -52,7 +52,7 @@ LevelDuration subghz_protocol_encoder_secplus_v2_yield(void* context); * @param btn Button number, 8 bit * @param cnt Container value, 28 bit * @param manufacture_name Name of manufacturer's key - * @param preset Modulation, SubGhzPesetDefinition + * @param preset Modulation, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_secplus_v2_create_data( @@ -61,7 +61,7 @@ bool subghz_protocol_secplus_v2_create_data( uint32_t serial, uint8_t btn, uint32_t cnt, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Allocate SubGhzProtocolDecoderSecPlus_v2. @@ -101,13 +101,13 @@ uint8_t subghz_protocol_decoder_secplus_v2_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderSecPlus_v2. * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_secplus_v2_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderSecPlus_v2. diff --git a/lib/subghz/protocols/somfy_keytis.c b/lib/subghz/protocols/somfy_keytis.c index d2df9effd..a66c704ff 100644 --- a/lib/subghz/protocols/somfy_keytis.c +++ b/lib/subghz/protocols/somfy_keytis.c @@ -382,7 +382,7 @@ uint8_t subghz_protocol_decoder_somfy_keytis_get_hash_data(void* context) { bool subghz_protocol_decoder_somfy_keytis_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderSomfyKeytis* instance = context; bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/somfy_keytis.h b/lib/subghz/protocols/somfy_keytis.h index 46193994d..29f96cd6a 100644 --- a/lib/subghz/protocols/somfy_keytis.h +++ b/lib/subghz/protocols/somfy_keytis.h @@ -49,13 +49,13 @@ uint8_t subghz_protocol_decoder_somfy_keytis_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderSomfyKeytis. * @param context Pointer to a SubGhzProtocolDecoderSomfyKeytis instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_somfy_keytis_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderSomfyKeytis. diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index 039cb8eeb..a6a348abb 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -339,7 +339,7 @@ uint8_t subghz_protocol_decoder_somfy_telis_get_hash_data(void* context) { bool subghz_protocol_decoder_somfy_telis_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderSomfyTelis* instance = context; return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/protocols/somfy_telis.h b/lib/subghz/protocols/somfy_telis.h index ce4747694..ff5b45e23 100644 --- a/lib/subghz/protocols/somfy_telis.h +++ b/lib/subghz/protocols/somfy_telis.h @@ -49,13 +49,13 @@ uint8_t subghz_protocol_decoder_somfy_telis_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderSomfyTelis. * @param context Pointer to a SubGhzProtocolDecoderSomfyTelis instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_somfy_telis_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderSomfyTelis. diff --git a/lib/subghz/protocols/star_line.c b/lib/subghz/protocols/star_line.c index 4492338a0..5a1c9b744 100644 --- a/lib/subghz/protocols/star_line.c +++ b/lib/subghz/protocols/star_line.c @@ -320,7 +320,7 @@ uint8_t subghz_protocol_decoder_star_line_get_hash_data(void* context) { bool subghz_protocol_decoder_star_line_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset) { + SubGhzPresetDefinition* preset) { furi_assert(context); SubGhzProtocolDecoderStarLine* instance = context; subghz_protocol_star_line_check_remote_controller( diff --git a/lib/subghz/protocols/star_line.h b/lib/subghz/protocols/star_line.h index b48f1c21b..e240954b1 100644 --- a/lib/subghz/protocols/star_line.h +++ b/lib/subghz/protocols/star_line.h @@ -49,13 +49,13 @@ uint8_t subghz_protocol_decoder_star_line_get_hash_data(void* context); * Serialize data SubGhzProtocolDecoderStarLine. * @param context Pointer to a SubGhzProtocolDecoderStarLine instance * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzPesetDefinition + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition * @return true On success */ bool subghz_protocol_decoder_star_line_serialize( void* context, FlipperFormat* flipper_format, - SubGhzPesetDefinition* preset); + SubGhzPresetDefinition* preset); /** * Deserialize data SubGhzProtocolDecoderStarLine. diff --git a/lib/subghz/types.h b/lib/subghz/types.h index 41a04cb15..32b70b651 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -31,8 +31,10 @@ typedef void* (*SubGhzAlloc)(SubGhzEnvironment* environment); typedef void (*SubGhzFree)(void* context); // Serialize and Deserialize -typedef bool ( - *SubGhzSerialize)(void* context, FlipperFormat* flipper_format, SubGhzPesetDefinition* preset); +typedef bool (*SubGhzSerialize)( + void* context, + FlipperFormat* flipper_format, + SubGhzPresetDefinition* preset); typedef bool (*SubGhzDeserialize)(void* context, FlipperFormat* flipper_format); // Decoder specific From 84550d58784637fb46d91c8087a635350e84db5b Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 31 Jul 2022 02:48:55 +0300 Subject: [PATCH 03/22] [FL-2654] Updater: retrying pre-boot SD card mount multiple times (#1402) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updater: retrying pre-boot SD card mount multiple times * Updater: added delay before retrying SD card mount on early boot Co-authored-by: あく --- applications/storage/storages/storage_ext.c | 3 +-- firmware/targets/f7/Src/update.c | 23 ++++++++++++++----- firmware/targets/f7/fatfs/stm32_adafruit_sd.c | 4 ++++ firmware/targets/f7/fatfs/stm32_adafruit_sd.h | 1 + site_scons/site_tools/fbt_apps.py | 6 ++--- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/applications/storage/storages/storage_ext.c b/applications/storage/storages/storage_ext.c index 4a9d42185..7341a6ec8 100644 --- a/applications/storage/storages/storage_ext.c +++ b/applications/storage/storages/storage_ext.c @@ -26,8 +26,7 @@ static FS_Error storage_ext_parse_error(SDError error); static bool sd_mount_card(StorageData* storage, bool notify) { bool result = false; - const uint8_t max_init_counts = 10; - uint8_t counter = max_init_counts; + uint8_t counter = BSP_SD_MaxMountRetryCount(); uint8_t bsp_result; SDData* sd_data = storage->data; diff --git a/firmware/targets/f7/Src/update.c b/firmware/targets/f7/Src/update.c index af2471951..36204829e 100644 --- a/firmware/targets/f7/Src/update.c +++ b/firmware/targets/f7/Src/update.c @@ -22,6 +22,21 @@ static FATFS* pfs = NULL; } \ } +static bool flipper_update_mount_sd() { + for(int i = 0; i < BSP_SD_MaxMountRetryCount(); ++i) { + if(BSP_SD_Init((i % 2) == 0) != MSD_OK) { + /* Next attempt will be without card reset, let it settle */ + furi_delay_ms(1000); + continue; + } + + if(f_mount(pfs, "/", 1) == FR_OK) { + return true; + } + } + return false; +} + static bool flipper_update_init() { furi_hal_clock_init(); furi_hal_rtc_init(); @@ -34,13 +49,9 @@ static bool flipper_update_init() { return false; } - if(BSP_SD_Init(true)) { - return false; - } - pfs = malloc(sizeof(FATFS)); - CHECK_FRESULT(f_mount(pfs, "/", 1)); - return true; + + return flipper_update_mount_sd(); } static bool flipper_update_load_stage(const string_t work_dir, UpdateManifest* manifest) { diff --git a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c index 1ca38abe4..6db430a53 100644 --- a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c +++ b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c @@ -331,6 +331,10 @@ void SD_SPI_Bus_To_Normal_State() { * @{ */ +uint8_t BSP_SD_MaxMountRetryCount() { + return 10; +} + /** * @brief Initializes the SD/SD communication. * @param None diff --git a/firmware/targets/f7/fatfs/stm32_adafruit_sd.h b/firmware/targets/f7/fatfs/stm32_adafruit_sd.h index 74a0e0c22..e0c5e3bef 100644 --- a/firmware/targets/f7/fatfs/stm32_adafruit_sd.h +++ b/firmware/targets/f7/fatfs/stm32_adafruit_sd.h @@ -198,6 +198,7 @@ typedef struct { /** @defgroup STM32_ADAFRUIT_SD_Exported_Functions * @{ */ +uint8_t BSP_SD_MaxMountRetryCount(); uint8_t BSP_SD_Init(bool reset_card); uint8_t BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); diff --git a/site_scons/site_tools/fbt_apps.py b/site_scons/site_tools/fbt_apps.py index 2ffdcae3a..a0c43fa79 100644 --- a/site_scons/site_tools/fbt_apps.py +++ b/site_scons/site_tools/fbt_apps.py @@ -1,8 +1,8 @@ from SCons.Builder import Builder from SCons.Action import Action -from SCons.Errors import UserError - +from SCons.Warnings import warn, WarningOnByDefault import SCons + from fbt.appmanifest import ( FlipperAppType, AppManager, @@ -22,7 +22,7 @@ def LoadApplicationManifests(env): try: appmgr.load_manifest(entry.File("application.fam").abspath, entry.name) except FlipperManifestException as e: - raise UserError(e) + warn(WarningOnByDefault, str(e)) def PrepareApplicationsBuild(env): From 4da6eba395652de8266ecd6a2bb63012517efd85 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Mon, 1 Aug 2022 16:24:21 +0400 Subject: [PATCH 04/22] [FL-2706, FL-2709] SubGhz: checking saved key files for length (#1485) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [FL-2706] SubGhz: checking saved key files for length * SubGhz: fix RAW file upload error * [FL-2709] GubGhz: RAW screen fix Co-authored-by: あく --- applications/subghz/subghz_i.c | 6 ++++-- applications/subghz/views/subghz_read_raw.c | 4 ++-- lib/subghz/protocols/came.c | 24 +++++++++++++++++++-- lib/subghz/protocols/came_atomo.c | 14 +++++++++++- lib/subghz/protocols/came_twee.c | 20 +++++++++++++++-- lib/subghz/protocols/chamberlain_code.c | 20 +++++++++++++++-- lib/subghz/protocols/faac_slh.c | 16 ++++++++++++-- lib/subghz/protocols/gate_tx.c | 20 +++++++++++++++-- lib/subghz/protocols/holtek.c | 20 +++++++++++++++-- lib/subghz/protocols/hormann.c | 20 +++++++++++++++-- lib/subghz/protocols/ido.c | 13 ++++++++++- lib/subghz/protocols/keeloq.c | 11 +++++++++- lib/subghz/protocols/kia.c | 17 ++++++++++++--- lib/subghz/protocols/linear.c | 20 +++++++++++++++-- lib/subghz/protocols/megacode.c | 22 ++++++++++++++++--- lib/subghz/protocols/nero_radio.c | 22 ++++++++++++++++--- lib/subghz/protocols/nero_sketch.c | 22 ++++++++++++++++--- lib/subghz/protocols/nice_flo.c | 24 +++++++++++++++++++-- lib/subghz/protocols/nice_flor_s.c | 16 ++++++++++++-- lib/subghz/protocols/power_smart.c | 20 +++++++++++++++-- lib/subghz/protocols/princeton.c | 10 +++++++++ lib/subghz/protocols/raw.c | 10 +++++++++ lib/subghz/protocols/raw.h | 8 +++++++ lib/subghz/protocols/secplus_v1.c | 20 +++++++++++++++-- lib/subghz/protocols/secplus_v2.c | 13 +++++++++-- lib/subghz/protocols/somfy_keytis.c | 5 +++++ lib/subghz/protocols/somfy_telis.c | 14 +++++++++++- lib/subghz/protocols/star_line.c | 5 +++++ 28 files changed, 390 insertions(+), 46 deletions(-) diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index b8232fdbe..00cc922c7 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -331,8 +331,10 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( subghz->txrx->receiver, string_get_cstr(temp_str)); if(subghz->txrx->decoder_result) { - subghz_protocol_decoder_base_deserialize( - subghz->txrx->decoder_result, subghz->txrx->fff_data); + if(!subghz_protocol_decoder_base_deserialize( + subghz->txrx->decoder_result, subghz->txrx->fff_data)) { + break; + } } else { FURI_LOG_E(TAG, "Protocol not found"); break; diff --git a/applications/subghz/views/subghz_read_raw.c b/applications/subghz/views/subghz_read_raw.c index de8f371b7..ccffaf42f 100644 --- a/applications/subghz/views/subghz_read_raw.c +++ b/applications/subghz/views/subghz_read_raw.c @@ -216,8 +216,8 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { uint8_t graphics_mode = 1; canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 5, 8, string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 40, 8, string_get_cstr(model->preset_str)); + canvas_draw_str(canvas, 5, 7, string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 40, 7, string_get_cstr(model->preset_str)); canvas_draw_str_aligned( canvas, 126, 0, AlignRight, AlignTop, string_get_cstr(model->sample_write)); diff --git a/lib/subghz/protocols/came.c b/lib/subghz/protocols/came.c index 145320aea..d28b735c5 100644 --- a/lib/subghz/protocols/came.c +++ b/lib/subghz/protocols/came.c @@ -145,7 +145,13 @@ bool subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flip FURI_LOG_E(TAG, "Deserialize error"); break; } - + if((instance->generic.data_count_bit != + subghz_protocol_came_const.min_count_bit_for_found) && + (instance->generic.data_count_bit != + 2 * subghz_protocol_came_const.min_count_bit_for_found)) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -293,7 +299,21 @@ bool subghz_protocol_decoder_came_serialize( bool subghz_protocol_decoder_came_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderCame* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if((instance->generic.data_count_bit != + subghz_protocol_came_const.min_count_bit_for_found) && + (instance->generic.data_count_bit != + 2 * subghz_protocol_came_const.min_count_bit_for_found)) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_came_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/came_atomo.c b/lib/subghz/protocols/came_atomo.c index 5781837d8..0c3cdd8ad 100644 --- a/lib/subghz/protocols/came_atomo.c +++ b/lib/subghz/protocols/came_atomo.c @@ -310,7 +310,19 @@ bool subghz_protocol_decoder_came_atomo_serialize( bool subghz_protocol_decoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderCameAtomo* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_came_atomo_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_came_atomo_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/came_twee.c b/lib/subghz/protocols/came_twee.c index 89367a1e4..ef352bf60 100644 --- a/lib/subghz/protocols/came_twee.c +++ b/lib/subghz/protocols/came_twee.c @@ -250,7 +250,11 @@ bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_came_twee_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -427,7 +431,19 @@ bool subghz_protocol_decoder_came_twee_serialize( bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderCameTwee* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_came_twee_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_came_twee_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 08b3e12c2..3128b71ec 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -215,7 +215,11 @@ bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit < + subghz_protocol_chamb_code_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -432,7 +436,19 @@ bool subghz_protocol_decoder_chamb_code_serialize( bool subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderChamb_Code* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit < + subghz_protocol_chamb_code_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_chamb_code_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/faac_slh.c b/lib/subghz/protocols/faac_slh.c index 78c456f83..8b90f471c 100644 --- a/lib/subghz/protocols/faac_slh.c +++ b/lib/subghz/protocols/faac_slh.c @@ -115,7 +115,7 @@ void subghz_protocol_decoder_faac_slh_feed(void* context, bool level, uint32_t d if(duration >= ((uint32_t)subghz_protocol_faac_slh_const.te_short * 3 + subghz_protocol_faac_slh_const.te_delta)) { instance->decoder.parser_step = FaacSLHDecoderStepFoundPreambula; - if(instance->decoder.decode_count_bit >= + if(instance->decoder.decode_count_bit == subghz_protocol_faac_slh_const.min_count_bit_for_found) { instance->generic.data = instance->decoder.decode_data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; @@ -192,7 +192,19 @@ bool subghz_protocol_decoder_faac_slh_serialize( bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderFaacSLH* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_faac_slh_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_faac_slh_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/gate_tx.c b/lib/subghz/protocols/gate_tx.c index 7a295c091..66174d011 100644 --- a/lib/subghz/protocols/gate_tx.c +++ b/lib/subghz/protocols/gate_tx.c @@ -138,7 +138,11 @@ bool subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* f FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_gate_tx_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -298,7 +302,19 @@ bool subghz_protocol_decoder_gate_tx_serialize( bool subghz_protocol_decoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderGateTx* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_gate_tx_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_gate_tx_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c index 55b991f62..eeb240267 100644 --- a/lib/subghz/protocols/holtek.c +++ b/lib/subghz/protocols/holtek.c @@ -151,7 +151,11 @@ bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* fl FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_holtek_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -331,7 +335,19 @@ bool subghz_protocol_decoder_holtek_serialize( bool subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderHoltek* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_holtek_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_holtek_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index f6f684cc1..ac6312511 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -154,7 +154,11 @@ bool subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* f FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_hormann_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -319,7 +323,19 @@ bool subghz_protocol_decoder_hormann_serialize( bool subghz_protocol_decoder_hormann_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderHormann* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_hormann_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_hormann_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/ido.c b/lib/subghz/protocols/ido.c index e6de577d1..914468445 100644 --- a/lib/subghz/protocols/ido.c +++ b/lib/subghz/protocols/ido.c @@ -191,7 +191,18 @@ bool subghz_protocol_decoder_ido_serialize( bool subghz_protocol_decoder_ido_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderIDo* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != subghz_protocol_ido_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_ido_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index a25454bee..526a6b34e 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -264,7 +264,11 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_keeloq_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } subghz_protocol_keeloq_check_remote_controller( &instance->generic, instance->keystore, &instance->manufacture_name); @@ -656,6 +660,11 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl FURI_LOG_E(TAG, "Deserialize error"); break; } + if(instance->generic.data_count_bit != + subghz_protocol_keeloq_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } res = true; } while(false); diff --git a/lib/subghz/protocols/kia.c b/lib/subghz/protocols/kia.c index 9a3b8f39b..6fc106170 100644 --- a/lib/subghz/protocols/kia.c +++ b/lib/subghz/protocols/kia.c @@ -12,7 +12,7 @@ static const SubGhzBlockConst subghz_protocol_kia_const = { .te_short = 250, .te_long = 500, .te_delta = 100, - .min_count_bit_for_found = 60, + .min_count_bit_for_found = 61, }; struct SubGhzProtocolDecoderKIA { @@ -145,7 +145,7 @@ void subghz_protocol_decoder_kia_feed(void* context, bool level, uint32_t durati (uint32_t)(subghz_protocol_kia_const.te_long + subghz_protocol_kia_const.te_delta * 2)) { //Found stop bit instance->decoder.parser_step = KIADecoderStepReset; - if(instance->decoder.decode_count_bit >= + if(instance->decoder.decode_count_bit == subghz_protocol_kia_const.min_count_bit_for_found) { instance->generic.data = instance->decoder.decode_data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; @@ -242,7 +242,18 @@ bool subghz_protocol_decoder_kia_serialize( bool subghz_protocol_decoder_kia_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderKIA* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != subghz_protocol_kia_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_kia_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/linear.c b/lib/subghz/protocols/linear.c index 652bf0bf6..c989a6183 100644 --- a/lib/subghz/protocols/linear.c +++ b/lib/subghz/protocols/linear.c @@ -156,7 +156,11 @@ bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* fl FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_linear_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -308,7 +312,19 @@ bool subghz_protocol_decoder_linear_serialize( bool subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderLinear* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_linear_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_linear_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c index 542fd8b37..bfe1a76b9 100644 --- a/lib/subghz/protocols/megacode.c +++ b/lib/subghz/protocols/megacode.c @@ -184,7 +184,11 @@ bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_megacode_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -270,7 +274,7 @@ void subghz_protocol_decoder_megacode_feed(void* context, bool level, uint32_t d if(!level) { //save interval if(duration >= (subghz_protocol_megacode_const.te_short * 10)) { instance->decoder.parser_step = MegaCodeDecoderStepReset; - if(instance->decoder.decode_count_bit >= + if(instance->decoder.decode_count_bit == subghz_protocol_megacode_const.min_count_bit_for_found) { instance->generic.data = instance->decoder.decode_data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; @@ -389,7 +393,19 @@ bool subghz_protocol_decoder_megacode_serialize( bool subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderMegaCode* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_megacode_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_megacode_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index 50c79f609..b6b1587ff 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -163,7 +163,11 @@ bool subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_nero_radio_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -294,7 +298,7 @@ void subghz_protocol_decoder_nero_radio_feed(void* context, bool level, uint32_t subghz_protocol_blocks_add_bit(&instance->decoder, 1); } instance->decoder.parser_step = NeroRadioDecoderStepReset; - if(instance->decoder.decode_count_bit >= + if(instance->decoder.decode_count_bit == subghz_protocol_nero_radio_const.min_count_bit_for_found) { instance->generic.data = instance->decoder.decode_data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; @@ -351,7 +355,19 @@ bool subghz_protocol_decoder_nero_radio_serialize( bool subghz_protocol_decoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderNeroRadio* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_nero_radio_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_nero_radio_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/nero_sketch.c b/lib/subghz/protocols/nero_sketch.c index 461bbcea2..0b87ec11b 100644 --- a/lib/subghz/protocols/nero_sketch.c +++ b/lib/subghz/protocols/nero_sketch.c @@ -157,7 +157,11 @@ bool subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperForma FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_nero_sketch_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -271,7 +275,7 @@ void subghz_protocol_decoder_nero_sketch_feed(void* context, bool level, uint32_ subghz_protocol_nero_sketch_const.te_delta * 2)) { //Found stop bit instance->decoder.parser_step = NeroSketchDecoderStepReset; - if(instance->decoder.decode_count_bit >= + if(instance->decoder.decode_count_bit == subghz_protocol_nero_sketch_const.min_count_bit_for_found) { instance->generic.data = instance->decoder.decode_data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; @@ -336,7 +340,19 @@ bool subghz_protocol_decoder_nero_sketch_serialize( bool subghz_protocol_decoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderNeroSketch* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_nero_sketch_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_nero_sketch_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/nice_flo.c b/lib/subghz/protocols/nice_flo.c index 4c4ede933..236b42223 100644 --- a/lib/subghz/protocols/nice_flo.c +++ b/lib/subghz/protocols/nice_flo.c @@ -138,7 +138,13 @@ bool subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* FURI_LOG_E(TAG, "Deserialize error"); break; } - + if((instance->generic.data_count_bit != + subghz_protocol_nice_flo_const.min_count_bit_for_found) && + (instance->generic.data_count_bit != + 2 * subghz_protocol_nice_flo_const.min_count_bit_for_found)) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -286,7 +292,21 @@ bool subghz_protocol_decoder_nice_flo_serialize( bool subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderNiceFlo* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if((instance->generic.data_count_bit != + subghz_protocol_nice_flo_const.min_count_bit_for_found) && + (instance->generic.data_count_bit != + 2 * subghz_protocol_nice_flo_const.min_count_bit_for_found)) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_nice_flo_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index 1a02149cb..1d370e85a 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -237,7 +237,7 @@ void subghz_protocol_decoder_nice_flor_s_feed(void* context, bool level, uint32_ subghz_protocol_nice_flor_s_const.te_delta) { //Found STOP bit instance->decoder.parser_step = NiceFlorSDecoderStepReset; - if(instance->decoder.decode_count_bit >= + if(instance->decoder.decode_count_bit == subghz_protocol_nice_flor_s_const.min_count_bit_for_found) { instance->generic.data = instance->decoder.decode_data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; @@ -339,7 +339,19 @@ bool subghz_protocol_decoder_nice_flor_s_serialize( bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderNiceFlorS* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_nice_flor_s_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_nice_flor_s_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/power_smart.c b/lib/subghz/protocols/power_smart.c index df8eb4fd1..53e9f3380 100644 --- a/lib/subghz/protocols/power_smart.c +++ b/lib/subghz/protocols/power_smart.c @@ -201,7 +201,11 @@ bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperForma FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_power_smart_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -354,7 +358,19 @@ bool subghz_protocol_decoder_power_smart_serialize( bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderPowerSmart* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_power_smart_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_power_smart_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index b283d273b..0f1001372 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -158,6 +158,11 @@ bool subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* FURI_LOG_E(TAG, "Missing TE"); break; } + if(instance->generic.data_count_bit != + subghz_protocol_princeton_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -320,6 +325,11 @@ bool subghz_protocol_decoder_princeton_deserialize(void* context, FlipperFormat* FURI_LOG_E(TAG, "Deserialize error"); break; } + if(instance->generic.data_count_bit != + subghz_protocol_princeton_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); break; diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index ec4ed41f4..9ab649a7b 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -57,6 +57,7 @@ const SubGhzProtocolDecoder subghz_protocol_raw_decoder = { .get_hash_data = NULL, .serialize = NULL, + .deserialize = subghz_protocol_decoder_raw_deserialize, .get_string = subghz_protocol_decoder_raw_get_string, }; @@ -246,9 +247,18 @@ void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t durati } } +bool subghz_protocol_decoder_raw_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + UNUSED(context); + UNUSED(flipper_format); + //ToDo stub, for backwards compatibility + return true; +} + void subghz_protocol_decoder_raw_get_string(void* context, string_t output) { furi_assert(context); //SubGhzProtocolDecoderRAW* instance = context; + UNUSED(context); //ToDo no use string_cat_printf(output, "RAW Date"); } diff --git a/lib/subghz/protocols/raw.h b/lib/subghz/protocols/raw.h index 5d6bb084e..00654ad28 100644 --- a/lib/subghz/protocols/raw.h +++ b/lib/subghz/protocols/raw.h @@ -65,6 +65,14 @@ void subghz_protocol_decoder_raw_reset(void* context); */ void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t duration); +/** + * Deserialize data SubGhzProtocolDecoderRAW. + * @param context Pointer to a SubGhzProtocolDecoderRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_raw_deserialize(void* context, FlipperFormat* flipper_format); + /** * Getting a textual representation of the received data. * @param context Pointer to a SubGhzProtocolDecoderRAW instance diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index 1e25a439d..25c35ce55 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -273,7 +273,11 @@ bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + 2 * subghz_protocol_secplus_v1_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -524,7 +528,19 @@ bool subghz_protocol_decoder_secplus_v1_serialize( bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderSecPlus_v1* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + 2 * subghz_protocol_secplus_v1_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed) { diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index 3f28ee7ea..37dc1c823 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -514,7 +514,11 @@ bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat FURI_LOG_E(TAG, "Deserialize error"); break; } - + if(instance->generic.data_count_bit != + subghz_protocol_secplus_v2_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex( flipper_format, "Secplus_packet_1", key_data, sizeof(uint64_t))) { @@ -689,7 +693,7 @@ void subghz_protocol_decoder_secplus_v2_feed(void* context, bool level, uint32_t } else if( duration >= (uint32_t)(subghz_protocol_secplus_v2_const.te_long * 2 + subghz_protocol_secplus_v2_const.te_delta)) { - if(instance->decoder.decode_count_bit >= + if(instance->decoder.decode_count_bit == subghz_protocol_secplus_v2_const.min_count_bit_for_found) { instance->generic.data = instance->decoder.decode_data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; @@ -782,6 +786,11 @@ bool subghz_protocol_decoder_secplus_v2_deserialize(void* context, FlipperFormat FURI_LOG_E(TAG, "Deserialize error"); break; } + if(instance->generic.data_count_bit != + subghz_protocol_secplus_v2_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); break; diff --git a/lib/subghz/protocols/somfy_keytis.c b/lib/subghz/protocols/somfy_keytis.c index a66c704ff..7a3b2186f 100644 --- a/lib/subghz/protocols/somfy_keytis.c +++ b/lib/subghz/protocols/somfy_keytis.c @@ -403,6 +403,11 @@ bool subghz_protocol_decoder_somfy_keytis_deserialize(void* context, FlipperForm FURI_LOG_E(TAG, "Deserialize error"); break; } + if(instance->generic.data_count_bit != + subghz_protocol_somfy_keytis_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); break; diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index a6a348abb..b9aac5777 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -348,7 +348,19 @@ bool subghz_protocol_decoder_somfy_telis_serialize( bool subghz_protocol_decoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderSomfyTelis* instance = context; - return subghz_block_generic_deserialize(&instance->generic, flipper_format); + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_somfy_telis_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; } void subghz_protocol_decoder_somfy_telis_get_string(void* context, string_t output) { diff --git a/lib/subghz/protocols/star_line.c b/lib/subghz/protocols/star_line.c index 5a1c9b744..757b56622 100644 --- a/lib/subghz/protocols/star_line.c +++ b/lib/subghz/protocols/star_line.c @@ -332,6 +332,11 @@ bool subghz_protocol_decoder_star_line_serialize( FURI_LOG_E(TAG, "Unable to add manufacture name"); res = false; } + if(res && instance->generic.data_count_bit != + subghz_protocol_star_line_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + res = false; + } return res; } From f9386b2649c022fde75572046ceb51198a4a5317 Mon Sep 17 00:00:00 2001 From: SG Date: Tue, 2 Aug 2022 21:24:42 +1000 Subject: [PATCH 05/22] Assets: unused assets removed (#1514) --- assets/icons/Archive/ble_10px.png | Bin 301 -> 0 bytes assets/icons/BLE/BLE_HID/Ble_connected_38x34.png | Bin 3694 -> 0 bytes .../icons/BLE/BLE_HID/Ble_disconnected_24x34.png | Bin 3656 -> 0 bytes .../icons/Dolphin/DolphinFirstStart0_70x53.png | Bin 624 -> 0 bytes .../icons/Dolphin/DolphinFirstStart1_59x53.png | Bin 558 -> 0 bytes .../icons/Dolphin/DolphinFirstStart2_59x51.png | Bin 574 -> 0 bytes .../icons/Dolphin/DolphinFirstStart3_57x48.png | Bin 527 -> 0 bytes .../icons/Dolphin/DolphinFirstStart4_67x53.png | Bin 556 -> 0 bytes .../icons/Dolphin/DolphinFirstStart5_54x49.png | Bin 1721 -> 0 bytes .../icons/Dolphin/DolphinFirstStart6_58x54.png | Bin 553 -> 0 bytes assets/icons/Dolphin/DolphinOkay_41x43.png | Bin 423 -> 0 bytes assets/icons/Infrared/InfraredLearn_128x64.png | Bin 4161 -> 0 bytes .../icons/Infrared/InfraredSendShort_128x34.png | Bin 4009 -> 0 bytes assets/icons/Infrared/InfraredSend_128x64.png | Bin 4219 -> 0 bytes assets/icons/Interface/DoorLocked_10x56.png | Bin 372 -> 0 bytes assets/icons/Interface/PassportBottom_128x17.png | Bin 364 -> 0 bytes assets/icons/Interface/PassportLeft_6x47.png | Bin 298 -> 0 bytes assets/icons/MainMenu/Bluetooth_14/frame_01.png | Bin 100 -> 0 bytes assets/icons/MainMenu/Bluetooth_14/frame_02.png | Bin 99 -> 0 bytes assets/icons/MainMenu/Bluetooth_14/frame_03.png | Bin 99 -> 0 bytes assets/icons/MainMenu/Bluetooth_14/frame_04.png | Bin 96 -> 0 bytes assets/icons/MainMenu/Bluetooth_14/frame_05.png | Bin 97 -> 0 bytes assets/icons/MainMenu/Bluetooth_14/frame_06.png | Bin 99 -> 0 bytes assets/icons/MainMenu/Bluetooth_14/frame_rate | 1 - assets/icons/MainMenu/Games_14/frame_01.png | Bin 96 -> 0 bytes assets/icons/MainMenu/Games_14/frame_02.png | Bin 99 -> 0 bytes assets/icons/MainMenu/Games_14/frame_03.png | Bin 105 -> 0 bytes assets/icons/MainMenu/Games_14/frame_04.png | Bin 104 -> 0 bytes assets/icons/MainMenu/Games_14/frame_05.png | Bin 105 -> 0 bytes assets/icons/MainMenu/Games_14/frame_06.png | Bin 102 -> 0 bytes assets/icons/MainMenu/Games_14/frame_07.png | Bin 101 -> 0 bytes assets/icons/MainMenu/Games_14/frame_08.png | Bin 102 -> 0 bytes assets/icons/MainMenu/Games_14/frame_09.png | Bin 100 -> 0 bytes assets/icons/MainMenu/Games_14/frame_rate | 1 - assets/icons/MainMenu/Passport_14/frame_01.png | Bin 98 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_02.png | Bin 81 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_03.png | Bin 86 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_04.png | Bin 89 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_05.png | Bin 89 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_06.png | Bin 94 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_07.png | Bin 97 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_08.png | Bin 97 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_09.png | Bin 99 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_10.png | Bin 98 -> 0 bytes assets/icons/MainMenu/Passport_14/frame_rate | 1 - assets/icons/MainMenu/Power_14/frame_01.png | Bin 326 -> 0 bytes assets/icons/MainMenu/Power_14/frame_rate | 1 - assets/icons/MainMenu/Tamagotchi_14/frame_01.png | Bin 106 -> 0 bytes assets/icons/MainMenu/Tamagotchi_14/frame_02.png | Bin 106 -> 0 bytes assets/icons/MainMenu/Tamagotchi_14/frame_03.png | Bin 106 -> 0 bytes assets/icons/MainMenu/Tamagotchi_14/frame_04.png | Bin 106 -> 0 bytes assets/icons/MainMenu/Tamagotchi_14/frame_05.png | Bin 106 -> 0 bytes assets/icons/MainMenu/Tamagotchi_14/frame_06.png | Bin 106 -> 0 bytes assets/icons/MainMenu/Tamagotchi_14/frame_rate | 1 - assets/icons/PIN/Pin_cell_13x13.png | Bin 3593 -> 0 bytes assets/icons/StatusBar/BadUsb_9x8.png | Bin 83 -> 0 bytes assets/icons/StatusBar/Battery_19x8.png | Bin 81 -> 0 bytes assets/icons/StatusBar/PlaceholderL_11x13.png | Bin 312 -> 0 bytes assets/icons/StatusBar/PlaceholderR_30x13.png | Bin 318 -> 0 bytes 59 files changed, 5 deletions(-) delete mode 100644 assets/icons/Archive/ble_10px.png delete mode 100644 assets/icons/BLE/BLE_HID/Ble_connected_38x34.png delete mode 100644 assets/icons/BLE/BLE_HID/Ble_disconnected_24x34.png delete mode 100644 assets/icons/Dolphin/DolphinFirstStart0_70x53.png delete mode 100644 assets/icons/Dolphin/DolphinFirstStart1_59x53.png delete mode 100644 assets/icons/Dolphin/DolphinFirstStart2_59x51.png delete mode 100644 assets/icons/Dolphin/DolphinFirstStart3_57x48.png delete mode 100644 assets/icons/Dolphin/DolphinFirstStart4_67x53.png delete mode 100644 assets/icons/Dolphin/DolphinFirstStart5_54x49.png delete mode 100644 assets/icons/Dolphin/DolphinFirstStart6_58x54.png delete mode 100644 assets/icons/Dolphin/DolphinOkay_41x43.png delete mode 100644 assets/icons/Infrared/InfraredLearn_128x64.png delete mode 100644 assets/icons/Infrared/InfraredSendShort_128x34.png delete mode 100644 assets/icons/Infrared/InfraredSend_128x64.png delete mode 100644 assets/icons/Interface/DoorLocked_10x56.png delete mode 100644 assets/icons/Interface/PassportBottom_128x17.png delete mode 100644 assets/icons/Interface/PassportLeft_6x47.png delete mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_01.png delete mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_02.png delete mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_03.png delete mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_04.png delete mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_05.png delete mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_06.png delete mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_rate delete mode 100644 assets/icons/MainMenu/Games_14/frame_01.png delete mode 100644 assets/icons/MainMenu/Games_14/frame_02.png delete mode 100644 assets/icons/MainMenu/Games_14/frame_03.png delete mode 100644 assets/icons/MainMenu/Games_14/frame_04.png delete mode 100644 assets/icons/MainMenu/Games_14/frame_05.png delete mode 100644 assets/icons/MainMenu/Games_14/frame_06.png delete mode 100644 assets/icons/MainMenu/Games_14/frame_07.png delete mode 100644 assets/icons/MainMenu/Games_14/frame_08.png delete mode 100644 assets/icons/MainMenu/Games_14/frame_09.png delete mode 100644 assets/icons/MainMenu/Games_14/frame_rate delete mode 100644 assets/icons/MainMenu/Passport_14/frame_01.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_02.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_03.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_04.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_05.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_06.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_07.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_08.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_09.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_10.png delete mode 100644 assets/icons/MainMenu/Passport_14/frame_rate delete mode 100644 assets/icons/MainMenu/Power_14/frame_01.png delete mode 100644 assets/icons/MainMenu/Power_14/frame_rate delete mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_01.png delete mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_02.png delete mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_03.png delete mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_04.png delete mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_05.png delete mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_06.png delete mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_rate delete mode 100644 assets/icons/PIN/Pin_cell_13x13.png delete mode 100644 assets/icons/StatusBar/BadUsb_9x8.png delete mode 100644 assets/icons/StatusBar/Battery_19x8.png delete mode 100644 assets/icons/StatusBar/PlaceholderL_11x13.png delete mode 100644 assets/icons/StatusBar/PlaceholderR_30x13.png diff --git a/assets/icons/Archive/ble_10px.png b/assets/icons/Archive/ble_10px.png deleted file mode 100644 index d7ebdcf8a84e6c7870c858689609c36028f725e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 301 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2xkYHHq`AGmsv7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpafHrx4R1i<>&pI=m5)c>{NDU7b)b-fr;B3<$MxhL^$id2Ft!!2 zx2@#md47Q71Vd3{(|3LbhMnO&{!uGi{{hvimbgZgq$HN4S|t~y0x1R~10zFS15;f? zlMq8AD`NvIV+(Bq11kfA^%ccmP&DM`r(~v8LNyoz^@JFhSeaT{nVLW}IBimk0BT_H MboFyt=akR{016vUy#N3J diff --git a/assets/icons/BLE/BLE_HID/Ble_connected_38x34.png b/assets/icons/BLE/BLE_HID/Ble_connected_38x34.png deleted file mode 100644 index ed5514df827fb0e917789ed422ff57839899d0ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3694 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 Ks4zQq{(k^B*?y@2 diff --git a/assets/icons/BLE/BLE_HID/Ble_disconnected_24x34.png b/assets/icons/BLE/BLE_HID/Ble_disconnected_24x34.png deleted file mode 100644 index 6f135c1162b8fdd943e46c617e16e6e855349b16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3656 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 diff --git a/assets/icons/Dolphin/DolphinFirstStart1_59x53.png b/assets/icons/Dolphin/DolphinFirstStart1_59x53.png deleted file mode 100644 index 85bdb5d147b4c6cca6bc93f0b71fdb7b88edbf87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 558 zcmeAS@N?(olHy`uVBq!ia0vp^)O>_%)r1c1j3A$?$-SQ3bL1Y`ns||Wt8PJ)-%sNJdJ^YQPI=IF+}3B>BYTX%#I?g z4;ZTMct9< zeb3+d8-FfLOL(_;al--z3q9!4Eqx$M60|IJ(VIbF+Ax6;dC^&BnM$Cp+* zeK0CM#Wl%$`68=}elrsq%FD9MeCDyNZxKD?+pLi*ygO@h60fAr{2Mdau5R<)GyPD< z1xED=fx_A+S~@G+-M7U(-g$V6@rsM?e+&O}oX_!|@O`s8F#J?YTq8l#m4U&}ayc;+4Y~O#nQ4_E4FnpU4KuEA1EY(9!PC{xWt~$(69CeFzBK>< diff --git a/assets/icons/Dolphin/DolphinFirstStart2_59x51.png b/assets/icons/Dolphin/DolphinFirstStart2_59x51.png deleted file mode 100644 index e1fd177e8647ada52b75709fb5916d99745353ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 574 zcmeAS@N?(olHy`uVBq!ia0vp^)dAqwXFy8GFUIOHC z7I;JgP2?5=Va7{$>;3=**-JcqUD=;9%JLcOndcs!2DI1E)5S4F;1$298DUXOPkgx3Cvz>k zxp-lcl&kKfD;ErGkLqrV;hvzM9AJ@n(sf5*oBGc(@>h}>8@?Fp;dM%BvJn_p%yJ>lJE?kuHn-Q6l( zgd--i+yicW|Zt*ZsfCUs!~(&zY9V-x$AwBAG{LZ<>WZ~&qMo}+kY^6G5UC#Kh_Hc zhNo(YYeY#(Vo9o1a#1RfVlXl=GSoFN)HSjUF*LCYfAvZrI oGp!P&!9ds02&BQl+{)O{%ESPo;gwHCEl>l4r>mdKI;Vst0CeWcXaE2J diff --git a/assets/icons/Dolphin/DolphinFirstStart3_57x48.png b/assets/icons/Dolphin/DolphinFirstStart3_57x48.png deleted file mode 100644 index 04466fd83537721b9aa583d61402ec2863bf519c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 527 zcmeAS@N?(olHy`uVBq!ia0vp^mOyO42qYMqbKXAyQY`6?zK#qG8~eHcB(ehe3dtTp zz6=aiY77hwEes65fIO>_%)r1c1j3A$?$-SQ3bL1Y`ns||Wt8PJ)-%sNJdJ^Yk;&7=F+}2W>IFmZBMt(r z53U}IPna83-=e9zwrT0!sdHN^gtu(ivdgM9R_C3%4hMT#`GUV%?Jl}8fhoe1Za=>r z+udMr^muhJ&tis(sS86~+C!b16%R59EwmIoG@;@Yr}qr&w!RC@7uj3pvh-fHI`qIO zVP^FF%A~pnQJfX~Uq(ATuW|X7zDseQulE!D?r&lA!sNh2`~JQ36=l&SHrfY zAiqG+cXGn)Q|f!X(rw>w6ypuldL5uzvR37X?w^AnxQ&{e|M5G$Ftjo>z40R0*b&V`T3{9*|4Xq3zU^sp2onyDDUaw7@~1L^x}TM!v+Fu z1;H%>!oot*b1ON&^9Hn^dpr3^PERe%4TsoY9DF`~>)zjtXERq^=-8?>{_@@h8Of&x3up{C``l@=#`q|s1+SXSALr=BDHKHUXu_VKa*w7@Am_8d@1zXd4(<85sO5mlH$Lkei>9nN|tXV4!Pg1kzw&Ze?s_ YWoiP^U^(ykXP^cKPgg&ebxsLQ00T(O82|tP diff --git a/assets/icons/Dolphin/DolphinFirstStart5_54x49.png b/assets/icons/Dolphin/DolphinFirstStart5_54x49.png deleted file mode 100644 index 28ee477f5202f69e9cbcf8a7a62ee412b8165bfd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1721 zcmbVNZEO=|9KU5RnS;$2f-c5n$FVSQ+-tjbJ6mVBj^CfwB?3}_ zAojnp;5I17az&&o+A%XTgJ1i;Ji7@W_ZgvQEP`0D$azYL_jc71L^-WS`|WqIF9tT zFaqz5$-uLc6gYurISj3T#g z6%vM1$7X=R@(kz1mIEqs5oZjUshkIj%)%7Zpl(|j%NMam64}T~qJN<-{(Of4oMTBU z+L+fDO)HwP?2cg^Mj-4DM$RR2TplVRMU9Wl3&n-@+yTYC zqW~M+6|Bf&9GM!x0jnBFK-SO`6j@B8*p5=j#D=kVuACQ=B!+d%2D%KxK|h6KW>i%X zmAKpOiMap`+(4!kuiHxlmnTkx=4MYk&U<9e>z=(IMDmbR+1dNb|GdB2RPl^~)IIa$ zCczmCU#>I6kZR$YjTF^|{_cev=co$GluG6rLU126uRzBu-SThhy`D<7(<4@6^CkF@c%n~(N{ zBb8-=*OvrtHb%|q+ zZu!a`)6D62+OJ>kA62(b&y1hH_4w}HH4kSG?;m}8{CLf}504)md+k(e+oksheyLrz z=!L^4ukZBN{q;FHoH#hq5LU_`q*&4&eH|GXHuiJ>Nn{1`6_P!I zd>I(3)EF2VS{N990fib~Fff!FFfhDI0P3H?z#v{QXIG#NP=YDR+uenM@oty!5+IMW zz$3Dlfq`2Hgc&d0t@{HMWH0gbb!C6bD9dN8XP$d_8Uq8PjHioZh{Wa43mg3o8;G!8 z&@N4QCTF1(b zVLCNJVPaP{Pv8#M&r1AhbM7R6_q!s)Q2o$%R~K(QwX^CCZ+Q;8Ppg@W3im!;C9}45 zTg3hcSbk&Ax%t!h$FX}GtvPF@>lxZ#MfgMttXu>PI@J=_h?11Vl2ohYqEsNoU}Ruq zsB2)TYh)Q>Xkuk*Xk}=jZD3$!VDPhCP7FmuZhlH;S|wbAfklXcrInGnm5~WVgKN0n Qa-aqVPgg&ebxsLQ0C@+)SO5S3 diff --git a/assets/icons/Dolphin/DolphinOkay_41x43.png b/assets/icons/Dolphin/DolphinOkay_41x43.png deleted file mode 100644 index 52cc98b1dca4bf82dc8ac46dc94ff2e98a0cabb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 423 zcmeAS@N?(olHy`uVBq!ia0vp^nn0}02qYNJUY-*Gq*&4&eH|GXHuiJ>Nn{1`6_P!I zd>I(3)EF2VS{N990fib~Fff!FFfhDIU|_JC!N4G1FlSew4N!t9$=lt9f$?sa@Dd=8 zy~NYkmHjER7_Yc77mLb8pwN0x7sn8Z%dQs``3@O~usskzBgB(cC3jemZTXCr2*)FVYAVZ_P96h zw>Y{>TaHE@a+~_7_^Bk*?ixXje5v#V1F8BKo2vZSCYtQjt=YY*|y3XlPR; zTe4=0BBAUgyGXKq)BC=?-}lFRedoH)InQ~X`*+{J`}f@Uxt=Sy6Q;sK@kP*em2xo3&1fnx&ZWM1a00j1BSqC^Iu1f0;u98LV40{(I zr+P;KU}d&IlbGWju^Ry4l9;%DePpzdout(6Of%cM3*ACyS*q+v& zQyj>Dc0Oo+c6R;4dc|bsH%PZhZPvge5AL*^^gW|1N3h7{o;+o+ZW4ms`daV0T=>{PwwQ3#{*63HcgU1 zlPvJa`YA~WNCE(FR)`@OC=>=}md$nffZl?{0U4n8&Yl7R;5rwOcEEH$xBg4O#Wn)3 z#$8hjby0@T;Yz-5vJVXm3)AItV6u0z6%hZW~kN*fV8;*qkR%>JRl3699UQN zP{CPxWSJQkP}7p!mU_HPL$WOSt$e`J!qAA)NUir{LxRjfF*m_6aAs((e`m{Ufd&3h@I$|?>jp_-orz0+ z?Nx9J=(7Vn2G^W5`UP{Ggx&_N#jvzD^!H`o#x?2e-6OPf=d6nB?Mm2ajPAC^Fl{I% z^gCyDt3PM~IG3)UR#cOFaq}F($G;dKJK4f(2=`f?RNiWg4BL!7*g2y4__UhT)kTLZ zWjL^9BkKh|!C0v|c|?3F46&$~vMHDtAPlghtZGg?=YQ7XT@yOT#T_H!(B%*4hkk=x zli!&Dh`DPbSgQb#SiKgff0zqsOU)YvfQm1&r|&1pSTqO#fN@U5p+^S%yIx7MYeX_% z?X9Sh;U?@b*59?iMn}wW$5{9tq1&=4268qvm|oszk9g#BcBc=EmAry$3r`M-pN^QO z%j|HG&90TLh!W&AXcCYhC}E;^yT}d7!Ci$&=vvCPp52fuU!D zvzhV|gdvH(ep>%$e18)NadqQrg(*BK;>k&#_uPK^FYYVKUv0?o?PO|-I)|s+@#>T> z*@q2(ekZ^4_!mDWaQ6fn3mLYA_k_XA{ew$8lr>uHFrJ#=z}wM=kFc0eTo|`5PUEFpu1qN?aKmGaXUT$ zABXEWc{aD|?B<1^MByh1qJ+i9NrN15u} zW%p5Jpp32?o3_W5t@)We;H5)wr6BtA>hkKxst&d#d8NCRcb2?kwzf8@4X}IJ%`>s+ z?o6+2LeE7XsXg}I zI0gHRT^X2+mgo12GK%W_GpK`-Ba(3kyAG~c`}DzQHfDro(r0$eqQ4Wqt9++^@7UYA zM|^M35$2H)2Gg(A-c}J$tv3oAEMZpy(s@{ijxJ{rLy$mg*S_&Cai}^9IWcs}3XQT1T_;GxBS{ z#ZN-d_@8k+vtGH+>S?BGb`Ol&)L(aMsIn#41*3~4|7@S)(QVM>z7=%qa@D;m@F2EI zIkYDBSR#E?lp;# zbAjj~Q}5_9MT%US%-VU$gNG1>>R(TmSToNtSJishV~*?Ym9dL)1=n62>Gyoj@ONi> zdgHx`GZ|&!WrbxCftP=nET)PxCH4!>UKy+Ft;1d!_2r)QPS?mBOSeg35{t(N?!1th zm}+my4$yH#I>v`+N8S`qeWEvh5oCyi%36)*`&jOkSh|!EX=PG%=lY$Kk4wvr>D-ve zvP=H1{prYgqn{p8R!99BGz6{ihgk`7H(n@zv$Qkr`ONP4cuq?8=~ z04qIEYUOtLaH8-SYl8YlA@TB?)iLEY-*5d=-jNoaxh42woQSjq^#0+%Q?jQ5%gidx zoZf2;x@~=3Q{H(&I;1lG5w7gf)84W`$HgIVwaH6qw>W zeZTm}qoZXLBlaiGc89F6sC|8(kCnceoi>}!oAzO^I#xeCR_STb{WfYrxJY5~`nbYb z>aowv+d-Zyv27)7Z`yc}1mx_g*5~a0rQ4|7??G8%&MkJEMGs1=KC1ThRDTKx{w8v9 zuhfyx^GP!m&khILdsUj8U-9XhyYMMa-c_NzdLr~wnQ4GkeRf>%-C+LjCiBytOq%z= z!|LiMf>b=}`aUxZeLN$a)|WAx9`KCrbV#JuVEok|gZDy$M{!?nx4#~E-8PsOR=OfE zZN@s>g{k&qLvpD(*xQx!U#{h5?LD*Cw5oJFbRIrR^lL=M*=Ofu9l$QGja^6_%_rq& zXPwZ)zE2xqty*lPc{!hSu5>r*$kvl#&RLY6U2XpMc{0v|A9-g92lUG}2?RAQo%a+qeI_KYo{q(Hq_WkhVgSzuAR^@!dj6$i8>Zd(rD&;Fb z{J+o21PIMp3^)hH1wP!U>f8Lv|5Nm9SjpC7at(Fphf9r1$7@H?c@e?O*;`55?=BB_ znYNmCD<4(99+#!4s30s~xkPGD9L|4|FVXQP)NY$K?fYPIaC2n+c!$GA@50Wtn2zdV zR>3#M{DXprm`3GB#fo+ocJbauQG5US`Lg-)!Ny9(v;!OZTexqXKZ%X`Z>?5!CquS2 zpsSa@t%svkc5_aZa!eBkrZvrt89-o=0Rs}vl?*bc65PpnGJ(W8*G$#{0GIGG&jbA zIVj$XW;z97RN;h}!Vqe*O)QHZn#TAJsw_ zqK+cra1%oVgt3v4iG~RZhSWAjX&U^-n)~=N2|h&f@7NSh?7y+_|BJ;KF~|fajbTHh zdH=2goCl3b^Yx(7K?shZpab?49}+FV_u#KR`YUB)GK1nzCLLwasGvVZ#!&u+fVMUf zu0_^BK(xp(O$d^tNrs?FFfs&*(u8Tj2qXm36%GCyPx>G6{wh+=3?~WtZ!Q=VlBh{Q z!dxM6vKtYC)Y2qE2ymn;gh(c%wFzz{1R90{Lpcge|rr#OEN|LF?O$3J~V z_Te-WgVQx<4RoQLj@yB=urb-*-sTK#Yu|+e0N0ASv4Krs-^|UJCl^7xjD5GZ^J)14 z`;}gGHTq>L`Ln?{$bybIQvY*meV{|7=JxW1sr6xO`6tH}yx~BDJ77pd1KKXf(b$fa zLcE_%ux>(VuGgN;IRIwM<0NETUzvmXe4Ow4d+e8oy{QzOr!8a01Q2w5JcyUR+{OI} z62@J_f4nZ77a&DO$n$W8qiQSDLt(~O^59}TKh`v>bvkBjUe3C8-AvV{x*l?0<<23C zCU+bwB;v}AAW(!3Pj%slo7P3>uiW| zNn*5ocutk^p6i)ea(rzc95!VWc4YC~4qZD^OD>NV1k6R$s_OkD z%gBz;&4`SWxnRT2GfsN%tz-ve0olA~FthP|!#|6jA-NF$n!9x0yfSjzybiiwdfXfZq0$hySqo}Gu zzkRz|3}!Cf5GKnb#y>2^!xC!%WH&B9&7rC9|KoFrang{rV-sM65?BIuho=<2rvUNd zF1|N1_>EMTfgpEmxQ>*D%ryzfTSdJ=$y`bOq&T_v@g3tg?d_wU%D!CP;i=p!fVvQ% i6;=Ha^tp43R~E2RBrB%!7mLJ25h!7fFbR1r`>12&Y1 zG!X<1MNkj{rAQG010o<&eDPkr@BO&z%~~^a=A8ZQ{q67UJ?orz*>5i?p(+6YfTRP) z2FriP@o%u05dWEPsJR6IB&>t2tz8_ftwD4KEg+ao0)VK#T(?ME%95hl;1WsN)2es& zUIzID0M=rQwa9oE$Xo&Nr)6X%`Sx2qFz%5B&`kRB92+&)aGN1(X7HlaM11<{ynLF&a30gb>{5(!z zbp`7ifPA(ESWmdVTp-T-k-oiPT#X12k$_8*w(tYuGOcu50g$mEV7*nYO$g*Dln?8w z8!A0akLO?nfO>9PTgJXF19?u`E7i!avqK}ABMszxR(PeIG6CYF;GB$XEji4DkYoEM z08m}-e7bIIo-{E&Iy@dQLFRpHDp(JlrGd>f=LXlSF9`|*GW$DteTT=!dW7iB0(Zmf zLQ4+-eV#zj;Igklzj(fn#H;A#i!9?+i>-OrU0O`kw@7TW0!wAP#BkFO={>>M$?cTiX1!W`~A z#|7-v%zBJXw$Xf%HX=KDTz^g@eN8+iQW9XFajxJ0Nc16>Tp#;IK=7gzt}6nth@FRA zQr(yg$OIbdvz7oLrEWRVVz&U$mQnN(0IEMJA1p~#a(pfZ05%LgrfB=xs|^e?PlsJ4fvp1AKS^hPk;;&F+F>V@a|VVz7vY2Uc?g3wOY zimj$`j|z%A_k9Xy0>>^S5aK%FQURCV;SXLqYwLF&r>fJeNEpK*JQEQFb(~Rzf?9nZ zo+q|V@M4_YwAi83G7aRDNlErNN1Szu_Ow=oY?YXo_^H$IhV9^#66Xr-XxZh)D1Y?5 zB%B>v=Zof6%{=Wx+oj|Vr(m{8y|^;EUqVwmN#9|kLnx*n11WMVGV78F&T-V4N}{~@ zFe-LGjt$C4u1u0na=x|O-Pd`$SpHGQkh{9CSVrFn0} zZkpqY+0MP6rQwz$LI>Z@f2UX{K|^T6#|+;vnT z`K4?cI?XdJHf`dTyGNLZc{l6UM)%tu(zg$J9=mDh@xbL{srVbk+ufz=9#2Y<*2!M!)qsh5G3!PiMPu?gDG?;R6bX^tf}~1pEQTF>S1^aP3eYSb@D%Oe|g$5 zLS#iP0vhA!W*v4bfE|z=kUM^)O+f1Ty`fpuyPUo4n(dP9F%Th$IpkhXNLfHxY?)DC zbYE?s{|sYBab~KI7f#Q$$kokVKvU35;o?=uD%Yy`s{Zhf&t|U)Q>;nxg_jFblkYq2 z7bxEf7nDBpdU%~0MleG$WReOQZcLbMO(J{>y&BBvoIO2UvY8uHmE0Iq*y&KXoul*R zY~V*kl#*Eho3_QDZTNvS5Nd+=57zH5YAk9Rt=-v{8k!YQ)mibH+1lEoJHYN`znD%y zb?1cU;cMSj_pe@#zhRrxwD%(NVsm<5`cbY(x>NcR`>LmzC(Coe^DWz<=irp?6s5AN*ha`O?m~Y1zr!!oku9$+?T|a&4|cQa-$SqD5hSE z=BACQeyQqu_1C_E@O@^=v-~!@gc~{1`Z2dSySQOK zX##pE;*j^Dm71;24{~(!dSH~6{>B4CHQX3Kw3#XCNBg9Z*>f|&Yth%v*50fI51Q6$ z#rDKz#)_`yt?c>1T}%94H_ZB~IJaNKPvEJ*m_W@5)e{edLWMMhGlg%6B1A5WJlO!< zWTs%XNnFxfgONh3SNf{9OfVP-)XnNtcqx{v;G^~f)~e&UwP$m}nGUf*nONG*Wyi_Z zM`GuO?8)ai8o?@=O3TOOcka@^rT5vj!i{-^xun~}9`#-ctVx(lEWPx2Pk+cGMnoVx zgp4HoF8rMZ8SaqF-&lRoMn(Rn&qC(B$SU06g*ZM zpKRymMVfdcypxU^$6uArxNkmo3S{L1RdyaLraGz1eLbBW?`&IJaJj(sUL|L*$(8Y3 z&$LD3_j`_6{|GwcY#09AK-?L-o0Y6`<+0Yhlc!D32X@E1Bkv%n)ST3uLabzPdd2Ry zu*w~k&H=l3r$~;n#wjn=QqI0y8r513o9|a3$2)cwR$$9rq!b;YCA*^zC?AO8U}`Wv zZwv+l);}+6Z9J)Xv?l4U3+L{GUQU$v+z`0V_KBj_MK`5LJ-9EniWn6<+jWc^#J!)s z<}!lAdVCFG4SY?&p6a@B!+Q5gFT=Fb)E8W8`8S`(1OzP=B8D__n`VWx_vsO%;0x;uMoLM*#qotc#^Q=7XyrgoUJ z_XG2KbjU(NTSeQ;HX#HaF>|2x5xf8Eb!6dUbnbCquIF0W?aJDBI(2t_lc_hYE^aPvF|zdkFy&Qz1+mdEic6 z-Fn0dT%L2L@c z+TDe&3ui+LDfy*`w*Xx))#uEhM}Sb2Eq#r%hfMBmwJ`Zw^Bf4_F+zB1EtQ~Ox@ z+A!wM0ooL4i96$EQqKJ5G_|Lb_xkvckoxYhx8L9D`Ceny@SabrRZ?}{Z{cWHEqsqy zoKcFD_~JO=8=V++XSKF(?X&0)>CeY2*6)$(DMR1=>is&Nc}w%8#Lwofr~Z6>cDT#F z)xKNHPU~`Fu7-x1q-xDqVtdMP@%>`Cj+e2XKUq^@wrm&_)PuCGFu zPS3Bzp|m&iPn9Z6TO8Ak7Ql?eGf03Xk>*bVIZ*I{BrFL}WF2`yG64Xg6T$8{CeFzb zO`uWq@V{*Iq9}Ae8URepqv&`-D2WO3Cj|ymO~Je;bzo31(G={3aDq9}tw}+_m}myc zEqcE@Av%PzvQ&UVmAKF|nlo z()d^FFn1Q61jUlVXyFV3e?J1W{($+~{r^C}4Eb!(&J6zPfr=;F&`4FBWj-|#S77|Z~Uva~|l zA>nXaD@z-=p{*6l7>P8nMHwLN{$L%bVN5)gK>8Cqm>>H$7WIFzXln)u&!jQjX*BYm zDsTy+F==5zG&)G1FDPh-S1^@GiwxWOYmfd;*@najjvx{37&Hp#FOku~|3bjnm;g5- z8R$cdNH9YPf@nyBpolOM1c5Y!8Nu*GeS|*>{2NdFAMyS!QvM7-3Hl!{Xe5GQh)2Nu zA#hRv0fI0xBtY-ZhF!Nt+t_UF%^{Gms~>sSB~@O7}UbdTyA&FGYB0By33S^rt=^oBAM zwA1B{sCW7&n`q8KA04nG^4TIzW3#c9=wunG9+|PFv(8f@%=0j<(KiDvfqK`VoQ;LkP~pt+$%)8>6kbX zX<-M~8@p~sJoOcwUY(QMZ0Sm!;`(j<^!=4nQ)BVTfXGM#%>=1{bxU|bj4qy|IJyGE zEz8t%sm$BMBgvOKQ?83`6TJcf2F(@RMDkzmlN>6E6nVO1w~KIz3_04sXM68L#6h2U o&9w)I*cG{extCw5sjxCoeOv^&cwnyc*Wb>;cE3%zmEXz#06+BqIsgCw diff --git a/assets/icons/Infrared/InfraredSend_128x64.png b/assets/icons/Infrared/InfraredSend_128x64.png deleted file mode 100644 index 33e2cecb5feec9c19ee486d9ba949eb4abd96cdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4219 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 mY4b5O|M z>l2X0SQ6wH%;50sMjD8d21sKV=r?HDYU?bwC{`6z%Ea7{YPA zw%3ra!GMQZcI8d$DgRp*Rtb* W8AOASiQHtM1_n=8KbLh*2~7Zp&vAYL diff --git a/assets/icons/Interface/PassportBottom_128x17.png b/assets/icons/Interface/PassportBottom_128x17.png deleted file mode 100644 index e4caa754f337785486825791569055924f1eaea8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^4L~f&2qYM6>t}*EEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCjK(#Fl48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!Ib3f?!v%$w@Y{lkjGx) z>Fdh=lv$8VP2}V09VS4b5>FS$5Q)pl7Jub=>B1oktyHq2GDHxyxW z`q$d_C*8neGZ$Ofzw1#y=O_NNY5Dh`_soAuz6DXg5stX6&uUg_7QIe8a zl4_M)lnSI6j0}tnbq$Pl4b4Lg4XljKtxPPm4GgRd3?^%4+o5R4%}>cptHiD0QOV^d Ppaup{S3j3^P6n!epx1JuCa>FVdQ&MBb@0B*5S AEdT%j diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_01.png b/assets/icons/MainMenu/Bluetooth_14/frame_01.png deleted file mode 100644 index 3b1073358ec1a8a9b2951127b6d2921365186b00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlwx^3@2*>s0AOG4PewJ^$WX^MY xpFzy-gCD-I9)8Xvz+}`Avp^w$YsG`#@(gc(iMI<^9AyS+_jL7hS?83{1OO$qA8`Nx diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_02.png b/assets/icons/MainMenu/Bluetooth_14/frame_02.png deleted file mode 100644 index 748a0d9dbeec511660ff3e6f089e8a8774e96a78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlmZytj2*>s0AOG4PewJ^$WX^MY wpFzy-gCD-I9!@u4GHQrfpb)^d;=ylu2BuDl_U@@aV?nw-UHx3vIVCg!0Qj^X%m4rY diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_03.png b/assets/icons/MainMenu/Bluetooth_14/frame_03.png deleted file mode 100644 index 7a90fea5ca6d61607462af399dff4e67b1fd7e43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlmZytj2*>s0AOG4PewJ^$WX^MY wpFzy;gCD-IA5J%5GHQrfpb)^d;=ylu2A-3W>>FljdxLa)y85}Sb4q9e0QSWmBLDyZ diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_04.png b/assets/icons/MainMenu/Bluetooth_14/frame_04.png deleted file mode 100644 index 8baed331116a74a24af45f29ba2443e91f7957d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlx~Gd{2*>s0AOG4PewJ^$WY2T^ tpFzy;!yiP>{N+iDVdkFJwDbOd1_q&CN&lojX)i!pJzf1=);T3K0RXzR9s0AOG4PewJ^$WY2T^ upFzy;!yiOWtYuudJmH<$29bb+-|ZRx{*&-uXS%-uq}S8c&t;ucLK6T0OCWjx diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_06.png b/assets/icons/MainMenu/Bluetooth_14/frame_06.png deleted file mode 100644 index 06013e7e95c3ea6a776c6b311caf2c85c17a6e0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlmZytj2*>s0AOG4PewJ^$WY2T^ wpFzy-!ymrz9)2z(z+}{LCpSTJLDTzshR^%N&ll80Sc7zXy85}Sb4q9e04s|iS^xk5 diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_rate b/assets/icons/MainMenu/Bluetooth_14/frame_rate deleted file mode 100644 index e440e5c84..000000000 --- a/assets/icons/MainMenu/Bluetooth_14/frame_rate +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/assets/icons/MainMenu/Games_14/frame_01.png b/assets/icons/MainMenu/Games_14/frame_01.png deleted file mode 100644 index f471e0593b5767184ed9adf4f255c4dd5d648bc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlx~Gd{2*>s0AOG7K`{tcbv^a2h t!+&n)f4pqpMHMzJYFb#s-eLHkli}J%kx;8SGb=$_Jzf1=);T3K0RVTV9MJ#( diff --git a/assets/icons/MainMenu/Games_14/frame_02.png b/assets/icons/MainMenu/Games_14/frame_02.png deleted file mode 100644 index 7f06f6c604f66be2283dd1abbf8675143711bae1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlmZytj2*>s0AOG7Ko93NQv^a2h w!+&n)f4pqpMHMzJYFe1X-eFkF>HL?UVV{R^hve21mq5BbUHx3vIVCg!0LO71wg3PC diff --git a/assets/icons/MainMenu/Games_14/frame_03.png b/assets/icons/MainMenu/Games_14/frame_03.png deleted file mode 100644 index 15c412be5e31d6fb3b313179c0bed66d4814abe6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlfv1aO2*>s0AOG7KJLa8Fv^a2h z!+&n)f4pqpMHMzJYFe1X?tG88?WMQGsd9rW{}~t-R|xHvIk_36m%-E3&t;ucLK6V8 C+#zcK diff --git a/assets/icons/MainMenu/Games_14/frame_04.png b/assets/icons/MainMenu/Games_14/frame_04.png deleted file mode 100644 index 6d539b5c97ba7b2390594afd042ffb715b397a54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlzNd?02*>s0AOG7Q{*-BBw&D4` z-{8spgo1cRC2cKs03cL1)4E%@x>GS+F zm$(z&aH5N=ZIdidrMbj1{X~uX2Lt{$Km0GRz{HSSA+&o_w!=!08J@0wF6*2UngBC0 B9?1Xz diff --git a/assets/icons/MainMenu/Games_14/frame_06.png b/assets/icons/MainMenu/Games_14/frame_06.png deleted file mode 100644 index 6753b7a24e9b61da795907dc823a44dfb9bac575..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nluBVG*2*>s09pBp?{*+;3=WF{L yFYzhgV8?ofiK3!Bsn!lXFTEvR)f@cz&+Nib>?(Bmr*hV2kO7{qelF{r5}E+(+8x{g diff --git a/assets/icons/MainMenu/Games_14/frame_07.png b/assets/icons/MainMenu/Games_14/frame_07.png deleted file mode 100644 index 597451e87d9dae74250a26a5215eaaff94a3882e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlj;D)b2*>s09pBp+J1(UgSQHq% y`G06aee=Ou){ZqR5;X2JCY`B2^x;3h03$=iDWTWCYr0rL`aNC!T-G@yGywo2iywUe diff --git a/assets/icons/MainMenu/Games_14/frame_08.png b/assets/icons/MainMenu/Games_14/frame_08.png deleted file mode 100644 index 2109b6b0fa8e6443e2146ee834fb1d5d6b2fbead..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nluBVG*2*>s09pBp+J08UuEIFT0 z@F3yF|5nBSY|X#91R?_u2JB-#GUI>C!~gOOm6<|jYM(6cfei3;^>bP0l+XkKWjG-6 diff --git a/assets/icons/MainMenu/Games_14/frame_09.png b/assets/icons/MainMenu/Games_14/frame_09.png deleted file mode 100644 index 65f1af5d480744099e9b3d58cd34be8cce56a85a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlwx^3@2*>s0AOG7KJKpVOT=+$j whfjv*_kM#X_Y(@@8I`oPBuzopr0K8xwY5)KL diff --git a/assets/icons/MainMenu/Games_14/frame_rate b/assets/icons/MainMenu/Games_14/frame_rate deleted file mode 100644 index e440e5c84..000000000 --- a/assets/icons/MainMenu/Games_14/frame_rate +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/assets/icons/MainMenu/Passport_14/frame_01.png b/assets/icons/MainMenu/Passport_14/frame_01.png deleted file mode 100644 index 97da34659190f683f367b0734f9b7fb01a720a0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlrl*Tz2*>s0AD`PFmh*C$ZZNp= uKf&W!f(P5=rw&2Qir?6qlUY3WG_o?pF68?r!4;$r((LK#=d#Wzp$PzYqZ>B> diff --git a/assets/icons/MainMenu/Passport_14/frame_02.png b/assets/icons/MainMenu/Passport_14/frame_02.png deleted file mode 100644 index ecb66c5c926811117412ea961b603504425c9b0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlgr|#R2*>s0AD`PFmh*C$ZZNp= d|3Ify1jC}s!gB9dKY9dG>*?y}vd$@?2>{O+7Uci{ diff --git a/assets/icons/MainMenu/Passport_14/frame_03.png b/assets/icons/MainMenu/Passport_14/frame_03.png deleted file mode 100644 index 7164af227fa57d5ff3ca01a5744826ea1c428e3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nltfz}(2*>s0AD`PFmh*C$ZZNp= ipJ8E*!76uGULA%7%0mC%ZAw)GY4CLQb6Mw<&;$S?uNLJ1 diff --git a/assets/icons/MainMenu/Passport_14/frame_04.png b/assets/icons/MainMenu/Passport_14/frame_04.png deleted file mode 100644 index f28f77e257261f427ffc55ce5258df66bc59a094..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlf~SjP2*>s0AD`PFmh*C$ZZNp= lKf&YQ!3q3sUstSXWM!D^E%eCr*nfVI9#2<4mvv4FO#rE28Y%z) diff --git a/assets/icons/MainMenu/Passport_14/frame_05.png b/assets/icons/MainMenu/Passport_14/frame_05.png deleted file mode 100644 index 7d01eb34597f089bd05a20d2a630ce2e3ad10efe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlf~SjP2*>s0AD`PFmh*C$ZZNp= lKf$AI;U{?oJsHyt3=FgO3mtmq$*=>Y$J5o%Wt~$(699X$7;yjq diff --git a/assets/icons/MainMenu/Passport_14/frame_06.png b/assets/icons/MainMenu/Passport_14/frame_06.png deleted file mode 100644 index c445fae0ab567958b02cc113694ed458134b735a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nls;7%%2*>s0AD`PFmh*C$ZZNp= qKf$AI;U{^XpY{@u4svMRJHW&+ys0AD`PFmh*C$ZZNp= tKf$AI;U{^XpY{@u>J2RZF?5=5U|^WmFBD=K&#)P!*VEO{Wt~$(698(<8-D-* diff --git a/assets/icons/MainMenu/Passport_14/frame_08.png b/assets/icons/MainMenu/Passport_14/frame_08.png deleted file mode 100644 index a16cee9640723949b0dde2a79cec4373e27e7fbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlhNp{T2*>s0AD`PFmh*C$ZZNp= tKfz;Lg2z8br>6-<-`JZU^G~Q?=4NOX6l`m}Bzy;?*VEO{Wt~$(698?f8|eT5 diff --git a/assets/icons/MainMenu/Passport_14/frame_09.png b/assets/icons/MainMenu/Passport_14/frame_09.png deleted file mode 100644 index c581a9e8ff7917d7cc110d0701c10d94a0ad0404..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlmZytj2*>s0AD`PFmh*C$ZZNp= vKf&W!f(P3qF`lRP4m~&IdHU=f9`Wih6etQz(>m%E2GZ^6>gTe~DWM4feHR-E diff --git a/assets/icons/MainMenu/Passport_14/frame_10.png b/assets/icons/MainMenu/Passport_14/frame_10.png deleted file mode 100644 index f217e9bbc991bf6190db1a489b7a06d52e14d652..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlrl*Tz2*>s0AD`PFmh*C$ZZNp= uKf&W!f(P5=rw*5z6u+@IKjxoM!OYE&bdi5q diff --git a/assets/icons/MainMenu/Passport_14/frame_rate b/assets/icons/MainMenu/Passport_14/frame_rate deleted file mode 100644 index e440e5c84..000000000 --- a/assets/icons/MainMenu/Passport_14/frame_rate +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/assets/icons/MainMenu/Power_14/frame_01.png b/assets/icons/MainMenu/Power_14/frame_01.png deleted file mode 100644 index 382d7132f4efabf1fad9a595915447dd1e6d0248..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uk3?!4(jyeG;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5l;8~T332`ZAIM?=k_T^V zeFCx=OM?7@862M7NCR<_yxm77bm)M>fkPasG7%Co7dRQ&Cg^k|q%vrwag-)7Ff$~+WHyLs<-P*cs9NG0 zQIe8al4_M)lnSI6j0}tnbq!2(jm$y}4XjMftW1ox4GgRd3>2r{e~zLdH$NpatrAm% Xu?0j!1eetgpaup{S3j3^P6s09|?y))bSnuYpk$E zu{H6lP+JLe+a6vXR#u*`@)FzB4BpfqD%jWlu$hOUmR)eldwX#YkRhI~elF{r5}E*K Ciyo2y diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_02.png b/assets/icons/MainMenu/Tamagotchi_14/frame_02.png deleted file mode 100644 index 4de357a597fa7b70d8d684bf3b863b472c0674c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlp{I*u2*>s09|?y))bSnuYpk$E zu{Cigm-98Ywi4#HCZ@Ju{5;XZ65s3-E$$!w;K;^M7$L~BwY8rYWQeD$pUXO@geCxE C`yNUF diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_03.png b/assets/icons/MainMenu/Tamagotchi_14/frame_03.png deleted file mode 100644 index c2c11f6105069c79b42a257876db16687e280fa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlp{I*u2*>s09|?y))bSnuYpk$E zu{H6oP+JLe+Z$dUR#u*`@)FzB4BpfqD%jWlu$hOUR#I?^-%6kNAVWM|{an^LB{Ts5 DbI2cI diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_04.png b/assets/icons/MainMenu/Tamagotchi_14/frame_04.png deleted file mode 100644 index 43645f94e331ac1c1b468b6cf2a4057bf4abddd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sSBpA$%1!{nlp{I*u2*>s09|?y))bSnuYpk$E zu{Cimm-98Ywky0mtgJj=bP0l+XkK Da+)8F diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_05.png b/assets/icons/MainMenu/Tamagotchi_14/frame_05.png deleted file mode 100644 index a0040ebd1272d4a2c609c28a86a2c7c292fabae0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106 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 diff --git a/assets/icons/StatusBar/Battery_19x8.png b/assets/icons/StatusBar/Battery_19x8.png deleted file mode 100644 index 1265d7c184a40bfdcd4500b388c3fcf0eaa905b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmeAS@N?(olHy`uVBq!ia0vp^!a&Ty2qYMct$tbpDG5&(#}JO|$r%YA2`m2ZXXuh% eAaRKO6eGi9DL&IxFNBLgYCT>3T-G@yGywpi5)>r> diff --git a/assets/icons/StatusBar/PlaceholderL_11x13.png b/assets/icons/StatusBar/PlaceholderL_11x13.png deleted file mode 100644 index a6a5612798eccf8cd845fa0e2c5e7ab0e7e0dcd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 312 zcmeAS@N?(olHy`uVBq!ia0vp^+#og+GmvDOU9$p6v7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpaf@tPl)UP|3DT4kUV%> z>l2X0SQ6wH%;50sMjD8d21sKV=r?WYe$ZW=;SK$$PpuhHzX@ zPT(y~5MXd(XA|3F(csvkXkyafXmW*-At##Uab@vA4WLrh64!{5l*E!$tK_0oAjM#0 zU}UIkV61Cs8Dd~zWnyM!Y_4r!U}a$7cX`EO6b-rgDVb@Nm>LYB8fsUIGXXU)c)I$z JtaD0e0s!sVP1pbc diff --git a/assets/icons/StatusBar/PlaceholderR_30x13.png b/assets/icons/StatusBar/PlaceholderR_30x13.png deleted file mode 100644 index bc1c9367cf87414f9af08a2d9cdab6c50bbe1580..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 318 zcmeAS@N?(olHy`uVBq!ia0vp^av(MnGmtziW5xocSkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YhSC&cyte;|tiNFKbc z^$EygED7=pW^j0RBMrn!@^*J&=wOxg0CLz%Jbhi+pE3(`vZ@^X(y0v;QuTCk4B@z* zoWRS<%*MvZW>CQ3WFW9$iXcNGi$RCenu3Ieo2(4C12|7vf1Yas(oo_WQIe8al4_M) zlnSI6j0}tnbq$Pl4J|_qEUgR-tqe@G4GgRd4C>Tb4x?zu%}>cpt3=meU}b6w(ZHvF RX(CVqgQu&X%Q~loCIEz}PecF! From f9745b4141570e6dbc919ac5a63ed98acb9483c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Tue, 2 Aug 2022 21:54:12 +0900 Subject: [PATCH 06/22] [FL-2705] App RPC Bug Fixes and redesign (#1491) * Rpc: remove callback timer * Rpc: simplify rpc event callback * Rpc: migrate to new confirmation schema * Rpc: migrate to new confirmation schema part2: finalize ibutton and rfid * Rpc: migrate to new confirmation schema part3: finallize nfc and fix id in load * Rpc: hardened sequencing check * Rpc: migrate to new confirmation schema part4: finalize subghz * iButton: properly handle exit * Nfc: correct sequence for rpc exit send * Rpc: fix review issues and nfc exit message * Rpc: more logging and condition race fix in confirmation * Rpc: migrate to new confirmation schema part5: finalize infrared * Rpc: more logging --- applications/ibutton/ibutton.c | 29 +--- applications/ibutton/ibutton_custom_event.h | 1 + applications/ibutton/ibutton_i.h | 1 + .../ibutton/scenes/ibutton_scene_rpc.c | 48 ++++-- applications/infrared/infrared.c | 47 ++---- applications/infrared/infrared_custom_event.h | 7 +- .../infrared/scenes/infrared_scene_rpc.c | 35 ++++- applications/lfrfid/lfrfid_app.cpp | 35 ++--- applications/lfrfid/lfrfid_app.h | 2 + .../lfrfid/scene/lfrfid_app_scene_rpc.cpp | 26 ++++ applications/nfc/helpers/nfc_custom_event.h | 1 + applications/nfc/nfc.c | 84 +++------- applications/nfc/nfc_i.h | 2 - applications/nfc/scenes/nfc_scene_rpc.c | 49 +++++- applications/rpc/rpc_app.c | 147 +++++++++++------- applications/rpc/rpc_app.h | 6 +- .../subghz/helpers/subghz_custom_event.h | 3 + applications/subghz/scenes/subghz_scene_rpc.c | 60 +++++-- applications/subghz/subghz.c | 61 +++----- applications/subghz/subghz_i.h | 4 + 20 files changed, 378 insertions(+), 270 deletions(-) diff --git a/applications/ibutton/ibutton.c b/applications/ibutton/ibutton.c index 30accd469..5ccb1f6c8 100644 --- a/applications/ibutton/ibutton.c +++ b/applications/ibutton/ibutton.c @@ -5,7 +5,7 @@ #include "m-string.h" #include #include -#include "rpc/rpc_app.h" +#include #define TAG "iButtonApp" @@ -58,7 +58,7 @@ static void ibutton_make_app_folder(iButton* ibutton) { } } -static bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog) { +bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog) { FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); bool result = false; string_t data; @@ -99,33 +99,20 @@ static bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show return result; } -static bool ibutton_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context) { furi_assert(context); iButton* ibutton = context; - bool result = false; - if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL); - ibutton->rpc_ctx = NULL; - view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit); - result = true; + view_dispatcher_send_custom_event( + ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose); } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit); - result = true; } else if(event == RpcAppEventLoadFile) { - if(arg) { - string_set_str(ibutton->file_path, arg); - if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) { - ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key); - view_dispatcher_send_custom_event( - ibutton->view_dispatcher, iButtonCustomEventRpcLoad); - result = true; - } - } + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoad); + } else { + rpc_system_app_confirm(ibutton->rpc_ctx, event, false); } - - return result; } bool ibutton_custom_event_callback(void* context, uint32_t event) { diff --git a/applications/ibutton/ibutton_custom_event.h b/applications/ibutton/ibutton_custom_event.h index 25dfc31d9..1e2f0300d 100644 --- a/applications/ibutton/ibutton_custom_event.h +++ b/applications/ibutton/ibutton_custom_event.h @@ -12,4 +12,5 @@ enum iButtonCustomEvent { iButtonCustomEventRpcLoad, iButtonCustomEventRpcExit, + iButtonCustomEventRpcSessionClose, }; diff --git a/applications/ibutton/ibutton_i.h b/applications/ibutton/ibutton_i.h index de3065c32..9d4354d02 100644 --- a/applications/ibutton/ibutton_i.h +++ b/applications/ibutton/ibutton_i.h @@ -78,6 +78,7 @@ typedef enum { } iButtonNotificationMessage; bool ibutton_file_select(iButton* ibutton); +bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog); bool ibutton_save_key(iButton* ibutton, const char* key_name); bool ibutton_delete_key(iButton* ibutton); void ibutton_text_store_set(iButton* ibutton, const char* text, ...); diff --git a/applications/ibutton/scenes/ibutton_scene_rpc.c b/applications/ibutton/scenes/ibutton_scene_rpc.c index 14f7df638..a3f5eeee4 100644 --- a/applications/ibutton/scenes/ibutton_scene_rpc.c +++ b/applications/ibutton/scenes/ibutton_scene_rpc.c @@ -1,5 +1,6 @@ #include "../ibutton_i.h" #include +#include void ibutton_scene_rpc_on_enter(void* context) { iButton* ibutton = context; @@ -26,23 +27,40 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == iButtonCustomEventRpcLoad) { - string_t key_name; - string_init(key_name); - if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { - path_extract_filename(ibutton->file_path, key_name, true); + const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx); + bool result = false; + if(arg) { + string_set_str(ibutton->file_path, arg); + if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) { + ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key); + string_t key_name; + string_init(key_name); + if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + path_extract_filename(ibutton->file_path, key_name, true); + } + + if(!string_empty_p(key_name)) { + ibutton_text_store_set( + ibutton, "emulating\n%s", string_get_cstr(key_name)); + } else { + ibutton_text_store_set(ibutton, "emulating"); + } + popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop); + + ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); + + string_clear(key_name); + result = true; + } } - - if(!string_empty_p(key_name)) { - ibutton_text_store_set(ibutton, "emulating\n%s", string_get_cstr(key_name)); - } else { - ibutton_text_store_set(ibutton, "emulating"); - } - popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop); - - ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); - - string_clear(key_name); + rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result); } else if(event.event == iButtonCustomEventRpcExit) { + rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventAppExit, true); + ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop); + view_dispatcher_stop(ibutton->view_dispatcher); + } else if(event.event == iButtonCustomEventRpcSessionClose) { + rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL); + ibutton->rpc_ctx = NULL; ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop); view_dispatcher_stop(ibutton->view_dispatcher); } diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c index 4b7a46714..cbbd375d5 100644 --- a/applications/infrared/infrared.c +++ b/applications/infrared/infrared.c @@ -36,52 +36,29 @@ static void infrared_tick_event_callback(void* context) { scene_manager_handle_tick_event(infrared->scene_manager); } -static bool - infrared_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context) { furi_assert(context); Infrared* infrared = context; - - if(!infrared->rpc_ctx) { - return false; - } - - bool result = false; + furi_assert(infrared->rpc_ctx); if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL); - infrared->rpc_ctx = NULL; view_dispatcher_send_custom_event( - infrared->view_dispatcher, InfraredCustomEventTypeBackPressed); - result = true; + infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose); } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event( - infrared->view_dispatcher, InfraredCustomEventTypeBackPressed); - result = true; + infrared->view_dispatcher, InfraredCustomEventTypeRpcExit); } else if(event == RpcAppEventLoadFile) { - if(arg) { - string_set_str(infrared->file_path, arg); - result = infrared_remote_load(infrared->remote, infrared->file_path); - infrared_worker_tx_set_get_signal_callback( - infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); - infrared_worker_tx_set_signal_sent_callback( - infrared->worker, infrared_signal_sent_callback, infrared); - view_dispatcher_send_custom_event( - infrared->view_dispatcher, InfraredCustomEventTypeRpcLoaded); - } + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeRpcLoad); } else if(event == RpcAppEventButtonPress) { - if(arg) { - size_t button_index = 0; - if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) { - infrared_tx_start_button_index(infrared, button_index); - result = true; - } - } + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPress); } else if(event == RpcAppEventButtonRelease) { - infrared_tx_stop(infrared); - result = true; + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonRelease); + } else { + rpc_system_app_confirm(infrared->rpc_ctx, event, false); } - - return result; } static void infrared_find_vacant_remote_name(string_t name, const char* path) { diff --git a/applications/infrared/infrared_custom_event.h b/applications/infrared/infrared_custom_event.h index 29bd61f11..09440ddec 100644 --- a/applications/infrared/infrared_custom_event.h +++ b/applications/infrared/infrared_custom_event.h @@ -14,7 +14,12 @@ enum InfraredCustomEventType { InfraredCustomEventTypePopupClosed, InfraredCustomEventTypeButtonSelected, InfraredCustomEventTypeBackPressed, - InfraredCustomEventTypeRpcLoaded, + + InfraredCustomEventTypeRpcLoad, + InfraredCustomEventTypeRpcExit, + InfraredCustomEventTypeRpcButtonPress, + InfraredCustomEventTypeRpcButtonRelease, + InfraredCustomEventTypeRpcSessionClose, }; #pragma pack(push, 1) diff --git a/applications/infrared/scenes/infrared_scene_rpc.c b/applications/infrared/scenes/infrared_scene_rpc.c index e31e7fb61..1d970f6a8 100644 --- a/applications/infrared/scenes/infrared_scene_rpc.c +++ b/applications/infrared/scenes/infrared_scene_rpc.c @@ -28,12 +28,45 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { view_dispatcher_stop(infrared->view_dispatcher); } else if(event.event == InfraredCustomEventTypePopupClosed) { view_dispatcher_stop(infrared->view_dispatcher); - } else if(event.event == InfraredCustomEventTypeRpcLoaded) { + } else if(event.event == InfraredCustomEventTypeRpcLoad) { + bool result = false; + const char* arg = rpc_system_app_get_data(infrared->rpc_ctx); + if(arg) { + string_set_str(infrared->file_path, arg); + result = infrared_remote_load(infrared->remote, infrared->file_path); + infrared_worker_tx_set_get_signal_callback( + infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); + infrared_worker_tx_set_signal_sent_callback( + infrared->worker, infrared_signal_sent_callback, infrared); + } const char* remote_name = infrared_remote_get_name(infrared->remote); infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name); popup_set_text( infrared->popup, infrared->text_store[0], 82, 32, AlignCenter, AlignTop); + + rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventLoadFile, result); + } else if(event.event == InfraredCustomEventTypeRpcButtonPress) { + bool result = false; + const char* arg = rpc_system_app_get_data(infrared->rpc_ctx); + if(arg) { + size_t button_index = 0; + if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) { + infrared_tx_start_button_index(infrared, button_index); + result = true; + } + } + rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result); + } else if(event.event == InfraredCustomEventTypeRpcButtonRelease) { + infrared_tx_stop(infrared); + rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, true); + } else if(event.event == InfraredCustomEventTypeRpcExit) { + view_dispatcher_stop(infrared->view_dispatcher); + rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventAppExit, true); + } else if(event.event == InfraredCustomEventTypeRpcSessionClose) { + rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL); + infrared->rpc_ctx = NULL; + view_dispatcher_stop(infrared->view_dispatcher); } } return consumed; diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp index 329f052ba..29e99b74f 100644 --- a/applications/lfrfid/lfrfid_app.cpp +++ b/applications/lfrfid/lfrfid_app.cpp @@ -25,7 +25,7 @@ #include #include -#include "rpc/rpc_app.h" +#include const char* LfRfidApp::app_folder = ANY_PATH("lfrfid"); const char* LfRfidApp::app_extension = ".rfid"; @@ -48,38 +48,25 @@ LfRfidApp::~LfRfidApp() { } } -static bool rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) { furi_assert(context); LfRfidApp* app = static_cast(context); - bool result = false; - - if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL); - app->rpc_ctx = NULL; + if(rpc_event == RpcAppEventSessionClose) { + LfRfidApp::Event event; + event.type = LfRfidApp::EventType::RpcSessionClose; + app->view_controller.send_event(&event); + } else if(rpc_event == RpcAppEventAppExit) { LfRfidApp::Event event; event.type = LfRfidApp::EventType::Exit; app->view_controller.send_event(&event); - result = true; - } else if(event == RpcAppEventAppExit) { + } else if(rpc_event == RpcAppEventLoadFile) { LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Exit; + event.type = LfRfidApp::EventType::RpcLoadFile; app->view_controller.send_event(&event); - result = true; - } else if(event == RpcAppEventLoadFile) { - if(arg) { - string_set_str(app->file_path, arg); - if(app->load_key_data(app->file_path, &(app->worker.key), false)) { - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::EmulateStart; - app->view_controller.send_event(&event); - app->worker.start_emulate(); - result = true; - } - } + } else { + rpc_system_app_confirm(app->rpc_ctx, rpc_event, false); } - - return result; } void LfRfidApp::run(void* _args) { diff --git a/applications/lfrfid/lfrfid_app.h b/applications/lfrfid/lfrfid_app.h index 3372552fc..b0d4c5898 100644 --- a/applications/lfrfid/lfrfid_app.h +++ b/applications/lfrfid/lfrfid_app.h @@ -33,6 +33,8 @@ public: Retry, Exit, EmulateStart, + RpcLoadFile, + RpcSessionClose, }; enum class SceneType : uint8_t { diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp index bc070ce61..a32982afb 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp @@ -1,6 +1,7 @@ #include "lfrfid_app_scene_rpc.h" #include #include +#include static const NotificationSequence sequence_blink_start_magenta = { &message_blink_start_10, @@ -36,6 +37,16 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) { LfRfidApp::Event view_event; view_event.type = LfRfidApp::EventType::Back; app->view_controller.send_event(&view_event); + rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true); + } else if(event->type == LfRfidApp::EventType::RpcSessionClose) { + // Detach RPC + rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL); + app->rpc_ctx = NULL; + + consumed = true; + LfRfidApp::Event view_event; + view_event.type = LfRfidApp::EventType::Back; + app->view_controller.send_event(&view_event); } else if(event->type == LfRfidApp::EventType::EmulateStart) { auto popup = app->view_controller.get(); consumed = true; @@ -45,7 +56,22 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) { popup->set_text(app->text_store.text, 89, 43, AlignCenter, AlignTop); notification_message(app->notification, &sequence_blink_start_magenta); + } else if(event->type == LfRfidApp::EventType::RpcLoadFile) { + const char* arg = rpc_system_app_get_data(app->rpc_ctx); + bool result = false; + if(arg) { + string_set_str(app->file_path, arg); + if(app->load_key_data(app->file_path, &(app->worker.key), false)) { + LfRfidApp::Event event; + event.type = LfRfidApp::EventType::EmulateStart; + app->view_controller.send_event(&event); + app->worker.start_emulate(); + result = true; + } + } + rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result); } + return consumed; } diff --git a/applications/nfc/helpers/nfc_custom_event.h b/applications/nfc/helpers/nfc_custom_event.h index fbd54b277..4227a5b14 100644 --- a/applications/nfc/helpers/nfc_custom_event.h +++ b/applications/nfc/helpers/nfc_custom_event.h @@ -11,4 +11,5 @@ enum NfcCustomEvent { NfcCustomEventDictAttackDone, NfcCustomEventDictAttackSkip, NfcCustomEventRpcLoad, + NfcCustomEventRpcSessionClose, }; diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index b19f92f27..32e74e8f2 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -13,78 +13,21 @@ bool nfc_back_event_callback(void* context) { return scene_manager_handle_back_event(nfc->scene_manager); } -void nfc_rpc_exit_callback(Nfc* nfc) { - if(nfc->rpc_state == NfcRpcStateEmulating) { - // Stop worker - nfc_worker_stop(nfc->worker); - } else if(nfc->rpc_state == NfcRpcStateEmulated) { - // Stop worker - nfc_worker_stop(nfc->worker); - // Save data in shadow file - nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name); - } - if(nfc->rpc_ctx) { - rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); - rpc_system_app_send_exited(nfc->rpc_ctx); - nfc->rpc_ctx = NULL; - } -} - -static bool nfc_rpc_emulate_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - Nfc* nfc = context; - - nfc->rpc_state = NfcRpcStateEmulated; - return true; -} - -static bool nfc_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void nfc_rpc_command_callback(RpcAppSystemEvent event, void* context) { furi_assert(context); Nfc* nfc = context; - if(!nfc->rpc_ctx) { - return false; - } - - bool result = false; + furi_assert(nfc->rpc_ctx); if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); - nfc->rpc_ctx = NULL; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); - result = true; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcSessionClose); } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); - result = true; } else if(event == RpcAppEventLoadFile) { - if((arg) && (nfc->rpc_state == NfcRpcStateIdle)) { - if(nfc_device_load(nfc->dev, arg, false)) { - if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - nfc_worker_start( - nfc->worker, - NfcWorkerStateMfUltralightEmulate, - &nfc->dev->dev_data, - nfc_rpc_emulate_callback, - nfc); - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { - nfc_worker_start( - nfc->worker, - NfcWorkerStateMfClassicEmulate, - &nfc->dev->dev_data, - nfc_rpc_emulate_callback, - nfc); - } else { - nfc_worker_start( - nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc); - } - nfc->rpc_state = NfcRpcStateEmulating; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad); - result = true; - } - } + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad); + } else { + rpc_system_app_confirm(nfc->rpc_ctx, event, false); } - - return result; } Nfc* nfc_alloc() { @@ -163,6 +106,21 @@ Nfc* nfc_alloc() { void nfc_free(Nfc* nfc) { furi_assert(nfc); + if(nfc->rpc_state == NfcRpcStateEmulating) { + // Stop worker + nfc_worker_stop(nfc->worker); + } else if(nfc->rpc_state == NfcRpcStateEmulated) { + // Stop worker + nfc_worker_stop(nfc->worker); + // Save data in shadow file + nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name); + } + if(nfc->rpc_ctx) { + rpc_system_app_send_exited(nfc->rpc_ctx); + rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); + nfc->rpc_ctx = NULL; + } + // Nfc device nfc_device_free(nfc->dev); diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 84c0e7f0c..5a916e803 100755 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -102,5 +102,3 @@ void nfc_blink_start(Nfc* nfc); void nfc_blink_stop(Nfc* nfc); void nfc_show_loading_popup(void* context, bool show); - -void nfc_rpc_exit_callback(Nfc* nfc); diff --git a/applications/nfc/scenes/nfc_scene_rpc.c b/applications/nfc/scenes/nfc_scene_rpc.c index 582dff8e6..94beccc6b 100644 --- a/applications/nfc/scenes/nfc_scene_rpc.c +++ b/applications/nfc/scenes/nfc_scene_rpc.c @@ -14,6 +14,14 @@ void nfc_scene_rpc_on_enter(void* context) { notification_message(nfc->notifications, &sequence_display_backlight_on); } +static bool nfc_scene_rpc_emulate_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); + Nfc* nfc = context; + + nfc->rpc_state = NfcRpcStateEmulated; + return true; +} + bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; Popup* popup = nfc->popup; @@ -22,13 +30,47 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == NfcCustomEventViewExit) { + rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventAppExit, true); + view_dispatcher_stop(nfc->view_dispatcher); + nfc_blink_stop(nfc); + } else if(event.event == NfcCustomEventRpcSessionClose) { + rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); + nfc->rpc_ctx = NULL; view_dispatcher_stop(nfc->view_dispatcher); nfc_blink_stop(nfc); } else if(event.event == NfcCustomEventRpcLoad) { - nfc_blink_start(nfc); + bool result = false; + const char* arg = rpc_system_app_get_data(nfc->rpc_ctx); + if((arg) && (nfc->rpc_state == NfcRpcStateIdle)) { + if(nfc_device_load(nfc->dev, arg, false)) { + if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { + nfc_worker_start( + nfc->worker, + NfcWorkerStateMfUltralightEmulate, + &nfc->dev->dev_data, + nfc_scene_rpc_emulate_callback, + nfc); + } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { + nfc_worker_start( + nfc->worker, + NfcWorkerStateMfClassicEmulate, + &nfc->dev->dev_data, + nfc_scene_rpc_emulate_callback, + nfc); + } else { + nfc_worker_start( + nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc); + } + nfc->rpc_state = NfcRpcStateEmulating; + result = true; - nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name); - popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop); + nfc_blink_start(nfc); + nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name); + popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop); + } + } + + rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventLoadFile, result); } } return consumed; @@ -38,7 +80,6 @@ void nfc_scene_rpc_on_exit(void* context) { Nfc* nfc = context; Popup* popup = nfc->popup; - nfc_rpc_exit_callback(nfc); nfc_blink_stop(nfc); popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); diff --git a/applications/rpc/rpc_app.c b/applications/rpc/rpc_app.c index e349e61cf..555cec8cf 100644 --- a/applications/rpc/rpc_app.c +++ b/applications/rpc/rpc_app.c @@ -6,24 +6,18 @@ #include "rpc_app.h" #define TAG "RpcSystemApp" -#define APP_BUTTON_TIMEOUT 1000 struct RpcAppSystem { RpcSession* session; RpcAppSystemCallback app_callback; void* app_context; PB_Main* state_msg; - FuriTimer* timer; + + uint32_t last_id; + char* last_data; }; -static void rpc_system_app_timer_callback(void* context) { - furi_assert(context); - RpcAppSystem* rpc_app = context; - - if(rpc_app->app_callback) { - rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context); - } -} +#define RPC_SYSTEM_APP_TEMP_ARGS_SIZE 16 static void rpc_system_app_start_process(const PB_Main* request, void* context) { furi_assert(request); @@ -33,9 +27,12 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) RpcAppSystem* rpc_app = context; RpcSession* session = rpc_app->session; furi_assert(session); - char args_temp[16]; + char args_temp[RPC_SYSTEM_APP_TEMP_ARGS_SIZE]; - FURI_LOG_D(TAG, "Start"); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + + FURI_LOG_D(TAG, "StartProcess: id %d", request->command_id); PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START; @@ -43,9 +40,9 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) const char* app_name = request->content.app_start_request.name; if(app_name) { const char* app_args = request->content.app_start_request.args; - if(strcmp(app_args, "RPC") == 0) { + if(app_args && strcmp(app_args, "RPC") == 0) { // If app is being started in RPC mode - pass RPC context via args string - snprintf(args_temp, 16, "RPC %08lX", (uint32_t)rpc_app); + snprintf(args_temp, RPC_SYSTEM_APP_TEMP_ARGS_SIZE, "RPC %08lX", (uint32_t)rpc_app); app_args = args_temp; } LoaderStatus status = loader_start(loader, app_name, app_args); @@ -58,7 +55,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) } else if(status == LoaderStatusOk) { result = PB_CommandStatus_OK; } else { - furi_assert(0); + furi_crash("Programming Error"); } } else { result = PB_CommandStatus_ERROR_INVALID_PARAMETERS; @@ -66,6 +63,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) furi_record_close(RECORD_LOADER); + FURI_LOG_D(TAG, "StartProcess: response id %d, result %d", request->command_id, result); rpc_send_and_release_empty(session, request->command_id, result); } @@ -93,6 +91,7 @@ static void rpc_system_app_lock_status_process(const PB_Main* request, void* con furi_record_close(RECORD_LOADER); + FURI_LOG_D(TAG, "LockStatus: response"); rpc_send_and_release(session, &response); pb_release(&PB_Main_msg, &response); } @@ -109,17 +108,17 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - if(rpc_app->app_callback(RpcAppEventAppExit, NULL, rpc_app->app_context)) { - status = PB_CommandStatus_OK; - furi_timer_stop(rpc_app->timer); - } else { - status = PB_CommandStatus_ERROR_APP_CMD_ERROR; - } + FURI_LOG_D(TAG, "ExitRequest: id %d", request->command_id); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + rpc_app->last_id = request->command_id; + rpc_app->app_callback(RpcAppEventAppExit, rpc_app->app_context); } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; + FURI_LOG_E( + TAG, "ExitRequest: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + rpc_send_and_release_empty(session, request->command_id, status); } - - rpc_send_and_release_empty(session, request->command_id, status); } static void rpc_system_app_load_file(const PB_Main* request, void* context) { @@ -133,17 +132,18 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - const char* file_path = request->content.app_load_file_request.path; - if(rpc_app->app_callback(RpcAppEventLoadFile, file_path, rpc_app->app_context)) { - status = PB_CommandStatus_OK; - } else { - status = PB_CommandStatus_ERROR_APP_CMD_ERROR; - } + FURI_LOG_D(TAG, "LoadFile: id %d", request->command_id); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + rpc_app->last_id = request->command_id; + rpc_app->last_data = strdup(request->content.app_load_file_request.path); + rpc_app->app_callback(RpcAppEventLoadFile, rpc_app->app_context); } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; + FURI_LOG_E( + TAG, "LoadFile: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + rpc_send_and_release_empty(session, request->command_id, status); } - - rpc_send_and_release_empty(session, request->command_id, status); } static void rpc_system_app_button_press(const PB_Main* request, void* context) { @@ -157,18 +157,18 @@ static void rpc_system_app_button_press(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - const char* args = request->content.app_button_press_request.args; - if(rpc_app->app_callback(RpcAppEventButtonPress, args, rpc_app->app_context)) { - status = PB_CommandStatus_OK; - furi_timer_start(rpc_app->timer, APP_BUTTON_TIMEOUT); - } else { - status = PB_CommandStatus_ERROR_APP_CMD_ERROR; - } + FURI_LOG_D(TAG, "ButtonPress"); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + rpc_app->last_id = request->command_id; + rpc_app->last_data = strdup(request->content.app_button_press_request.args); + rpc_app->app_callback(RpcAppEventButtonPress, rpc_app->app_context); } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; + FURI_LOG_E( + TAG, "ButtonPress: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + rpc_send_and_release_empty(session, request->command_id, status); } - - rpc_send_and_release_empty(session, request->command_id, status); } static void rpc_system_app_button_release(const PB_Main* request, void* context) { @@ -182,17 +182,17 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context) PB_CommandStatus status; if(rpc_app->app_callback) { - if(rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context)) { - status = PB_CommandStatus_OK; - furi_timer_stop(rpc_app->timer); - } else { - status = PB_CommandStatus_ERROR_APP_CMD_ERROR; - } + FURI_LOG_D(TAG, "ButtonRelease"); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + rpc_app->last_id = request->command_id; + rpc_app->app_callback(RpcAppEventButtonRelease, rpc_app->app_context); } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; + FURI_LOG_E( + TAG, "ButtonRelease: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + rpc_send_and_release_empty(session, request->command_id, status); } - - rpc_send_and_release_empty(session, request->command_id, status); } void rpc_system_app_send_started(RpcAppSystem* rpc_app) { @@ -201,6 +201,8 @@ void rpc_system_app_send_started(RpcAppSystem* rpc_app) { furi_assert(session); rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_STARTED; + + FURI_LOG_D(TAG, "SendStarted"); rpc_send(session, rpc_app->state_msg); } @@ -210,9 +212,46 @@ void rpc_system_app_send_exited(RpcAppSystem* rpc_app) { furi_assert(session); rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_CLOSED; + + FURI_LOG_D(TAG, "SendExit"); rpc_send(session, rpc_app->state_msg); } +const char* rpc_system_app_get_data(RpcAppSystem* rpc_app) { + furi_assert(rpc_app); + furi_assert(rpc_app->last_data); + return rpc_app->last_data; +} + +void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result) { + furi_assert(rpc_app); + RpcSession* session = rpc_app->session; + furi_assert(session); + furi_assert(rpc_app->last_id); + + PB_CommandStatus status = result ? PB_CommandStatus_OK : PB_CommandStatus_ERROR_APP_CMD_ERROR; + + uint32_t last_id = 0; + switch(event) { + case RpcAppEventAppExit: + case RpcAppEventLoadFile: + case RpcAppEventButtonPress: + case RpcAppEventButtonRelease: + last_id = rpc_app->last_id; + rpc_app->last_id = 0; + if(rpc_app->last_data) { + free(rpc_app->last_data); + rpc_app->last_data = NULL; + } + FURI_LOG_D(TAG, "AppConfirm: event %d last_id %d status %d", event, last_id, status); + rpc_send_and_release_empty(session, last_id, status); + break; + default: + furi_crash("RPC App state programming Error"); + break; + } +} + void rpc_system_app_set_callback(RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* ctx) { furi_assert(rpc_app); @@ -226,8 +265,6 @@ void* rpc_system_app_alloc(RpcSession* session) { RpcAppSystem* rpc_app = malloc(sizeof(RpcAppSystem)); rpc_app->session = session; - rpc_app->timer = furi_timer_alloc(rpc_system_app_timer_callback, FuriTimerTypeOnce, rpc_app); - // App exit message rpc_app->state_msg = malloc(sizeof(PB_Main)); rpc_app->state_msg->which_content = PB_Main_app_state_response_tag; @@ -265,12 +302,16 @@ void rpc_system_app_free(void* context) { RpcSession* session = rpc_app->session; furi_assert(session); - furi_timer_free(rpc_app->timer); - if(rpc_app->app_callback) { - rpc_app->app_callback(RpcAppEventSessionClose, NULL, rpc_app->app_context); + rpc_app->app_callback(RpcAppEventSessionClose, rpc_app->app_context); } + while(rpc_app->app_callback) { + furi_delay_tick(1); + } + + if(rpc_app->last_data) free(rpc_app->last_data); + free(rpc_app->state_msg); free(rpc_app); } diff --git a/applications/rpc/rpc_app.h b/applications/rpc/rpc_app.h index 4e00922ff..635c9f8c6 100644 --- a/applications/rpc/rpc_app.h +++ b/applications/rpc/rpc_app.h @@ -13,7 +13,7 @@ typedef enum { RpcAppEventButtonRelease, } RpcAppSystemEvent; -typedef bool (*RpcAppSystemCallback)(RpcAppSystemEvent event, const char* arg, void* context); +typedef void (*RpcAppSystemCallback)(RpcAppSystemEvent event, void* context); typedef struct RpcAppSystem RpcAppSystem; @@ -23,6 +23,10 @@ void rpc_system_app_send_started(RpcAppSystem* rpc_app); void rpc_system_app_send_exited(RpcAppSystem* rpc_app); +const char* rpc_system_app_get_data(RpcAppSystem* rpc_app); + +void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result); + #ifdef __cplusplus } #endif diff --git a/applications/subghz/helpers/subghz_custom_event.h b/applications/subghz/helpers/subghz_custom_event.h index 801a8ae9d..765c9e251 100644 --- a/applications/subghz/helpers/subghz_custom_event.h +++ b/applications/subghz/helpers/subghz_custom_event.h @@ -47,6 +47,9 @@ typedef enum { SubGhzCustomEventSceneStay, SubGhzCustomEventSceneRpcLoad, + SubGhzCustomEventSceneRpcButtonPress, + SubGhzCustomEventSceneRpcButtonRelease, + SubGhzCustomEventSceneRpcSessionClose, SubGhzCustomEventViewReceiverOK, SubGhzCustomEventViewReceiverConfig, diff --git a/applications/subghz/scenes/subghz_scene_rpc.c b/applications/subghz/scenes/subghz_scene_rpc.c index 844f5c167..c6f7df268 100644 --- a/applications/subghz/scenes/subghz_scene_rpc.c +++ b/applications/subghz/scenes/subghz_scene_rpc.c @@ -22,20 +22,60 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == SubGhzCustomEventSceneExit) { + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_tx_stop(subghz); + subghz_sleep(subghz); + } view_dispatcher_stop(subghz->view_dispatcher); + rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventAppExit, true); + } else if(event.event == SubGhzCustomEventSceneRpcSessionClose) { + rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL); + subghz->rpc_ctx = NULL; + subghz_blink_stop(subghz); + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_tx_stop(subghz); + subghz_sleep(subghz); + } + view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit); + } else if(event.event == SubGhzCustomEventSceneRpcButtonPress) { + bool result = false; + if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) { + subghz_blink_start(subghz); + result = subghz_tx_start(subghz, subghz->txrx->fff_data); + result = true; + } + rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result); + } else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) { + bool result = false; + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_blink_stop(subghz); + subghz_tx_stop(subghz); + subghz_sleep(subghz); + result = true; + } + rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonRelease, result); } else if(event.event == SubGhzCustomEventSceneRpcLoad) { - string_t file_name; - string_init(file_name); - path_extract_filename(subghz->file_path, file_name, true); + bool result = false; + const char* arg = rpc_system_app_get_data(subghz->rpc_ctx); + if(arg) { + if(subghz_key_load(subghz, arg, false)) { + string_set_str(subghz->file_path, arg); + result = true; + string_t file_name; + string_init(file_name); + path_extract_filename(subghz->file_path, file_name, true); - snprintf( - subghz->file_name_tmp, - SUBGHZ_MAX_LEN_NAME, - "loaded\n%s", - string_get_cstr(file_name)); - popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop); + snprintf( + subghz->file_name_tmp, + SUBGHZ_MAX_LEN_NAME, + "loaded\n%s", + string_get_cstr(file_name)); + popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop); - string_clear(file_name); + string_clear(file_name); + } + } + rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventLoadFile, result); } } return consumed; diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index a970e10c4..4631d7a30 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -35,57 +35,38 @@ void subghz_tick_event_callback(void* context) { scene_manager_handle_tick_event(subghz->scene_manager); } -static bool subghz_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void subghz_rpc_command_callback(RpcAppSystemEvent event, void* context) { furi_assert(context); SubGhz* subghz = context; - if(!subghz->rpc_ctx) { - return false; - } - - bool result = false; + furi_assert(subghz->rpc_ctx); if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL); - subghz->rpc_ctx = NULL; - notification_message(subghz->notifications, &sequence_blink_stop); - view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit); - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - subghz_sleep(subghz); - } - result = true; + view_dispatcher_send_custom_event( + subghz->view_dispatcher, SubGhzCustomEventSceneRpcSessionClose); } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit); - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - subghz_sleep(subghz); - } - result = true; } else if(event == RpcAppEventLoadFile) { - if(arg) { - if(subghz_key_load(subghz, arg, false)) { - string_set_str(subghz->file_path, arg); - view_dispatcher_send_custom_event( - subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad); - result = true; - } - } + view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad); } else if(event == RpcAppEventButtonPress) { - if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) { - notification_message(subghz->notifications, &sequence_blink_start_magenta); - result = subghz_tx_start(subghz, subghz->txrx->fff_data); - } + view_dispatcher_send_custom_event( + subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonPress); } else if(event == RpcAppEventButtonRelease) { - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - notification_message(subghz->notifications, &sequence_blink_stop); - subghz_tx_stop(subghz); - subghz_sleep(subghz); - result = true; - } + view_dispatcher_send_custom_event( + subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonRelease); + } else { + rpc_system_app_confirm(subghz->rpc_ctx, event, false); } +} - return result; +void subghz_blink_start(SubGhz* instance) { + furi_assert(instance); + notification_message(instance->notifications, &sequence_blink_start_magenta); +} + +void subghz_blink_stop(SubGhz* instance) { + furi_assert(instance); + notification_message(instance->notifications, &sequence_blink_stop); } SubGhz* subghz_alloc() { @@ -237,7 +218,7 @@ void subghz_free(SubGhz* subghz) { if(subghz->rpc_ctx) { rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL); rpc_system_app_send_exited(subghz->rpc_ctx); - notification_message(subghz->notifications, &sequence_blink_stop); + subghz_blink_stop(subghz); subghz->rpc_ctx = NULL; } diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index 01fbe57be..99a0f8a28 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -108,6 +108,10 @@ void subghz_begin(SubGhz* subghz, uint8_t* preset_data); uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency); void subghz_rx_end(SubGhz* subghz); void subghz_sleep(SubGhz* subghz); + +void subghz_blink_start(SubGhz* instance); +void subghz_blink_stop(SubGhz* instance); + bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format); void subghz_tx_stop(SubGhz* subghz); void subghz_dialog_message_show_only_rx(SubGhz* subghz); From 01afb289c0dd968193ec6f8abf6282a327fa4e7e Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Tue, 2 Aug 2022 16:17:37 +0300 Subject: [PATCH 07/22] [FL-2713] Buffered file streams fix (#1515) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix incorrect buffered stream behaviour * Add specific tests * Make the test fail on wrong behaviour * Better names Co-authored-by: あく --- applications/unit_tests/stream/stream_test.c | 29 ++++++++++++++++++++ lib/toolbox/stream/buffered_file_stream.c | 28 ++++++++++++++++--- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/applications/unit_tests/stream/stream_test.c b/applications/unit_tests/stream/stream_test.c index 36155e333..b5a2d3980 100644 --- a/applications/unit_tests/stream/stream_test.c +++ b/applications/unit_tests/stream/stream_test.c @@ -387,6 +387,34 @@ MU_TEST(stream_split_test) { furi_record_close(RECORD_STORAGE); } +MU_TEST(stream_buffered_write_after_read_test) { + const char* prefix = "I write "; + const char* substr = "Hello there"; + + const size_t substr_len = strlen(substr); + const size_t prefix_len = strlen(prefix); + const size_t buf_size = substr_len + 1; + + char buf[buf_size]; + memset(buf, 0, buf_size); + + Storage* storage = furi_record_open(RECORD_STORAGE); + Stream* stream = buffered_file_stream_alloc(storage); + mu_check(buffered_file_stream_open( + stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)); + mu_assert_int_eq(strlen(stream_test_data), stream_write_cstring(stream, stream_test_data)); + mu_check(stream_rewind(stream)); + mu_assert_int_eq(prefix_len, stream_read(stream, (uint8_t*)buf, prefix_len)); + mu_assert_string_eq(prefix, buf); + mu_assert_int_eq(substr_len, stream_write(stream, (uint8_t*)substr, substr_len)); + mu_check(stream_seek(stream, prefix_len, StreamOffsetFromStart)); + mu_assert_int_eq(substr_len, stream_read(stream, (uint8_t*)buf, substr_len)); + mu_assert_string_eq(substr, buf); + + stream_free(stream); + furi_record_close(RECORD_STORAGE); +} + MU_TEST(stream_buffered_large_file_test) { string_t input_data; string_t output_data; @@ -470,6 +498,7 @@ MU_TEST_SUITE(stream_suite) { MU_RUN_TEST(stream_write_read_save_load_test); MU_RUN_TEST(stream_composite_test); MU_RUN_TEST(stream_split_test); + MU_RUN_TEST(stream_buffered_write_after_read_test); MU_RUN_TEST(stream_buffered_large_file_test); } diff --git a/lib/toolbox/stream/buffered_file_stream.c b/lib/toolbox/stream/buffered_file_stream.c index 5db276d3f..2f2359a04 100644 --- a/lib/toolbox/stream/buffered_file_stream.c +++ b/lib/toolbox/stream/buffered_file_stream.c @@ -1,5 +1,6 @@ #include "buffered_file_stream.h" +#include "core/check.h" #include "stream_i.h" #include "file_stream.h" #include "stream_cache.h" @@ -38,6 +39,8 @@ const StreamVTable buffered_file_stream_vtable = { .delete_and_insert = (StreamDeleteAndInsertFn)buffered_file_stream_delete_and_insert, }; +static bool buffered_file_stream_unread(BufferedFileStream* stream); + Stream* buffered_file_stream_alloc(Storage* storage) { BufferedFileStream* stream = malloc(sizeof(BufferedFileStream)); @@ -125,8 +128,12 @@ static size_t buffered_file_stream_size(BufferedFileStream* stream) { static size_t buffered_file_stream_write(BufferedFileStream* stream, const uint8_t* data, size_t size) { - stream_cache_drop(stream->cache); - return stream_write(stream->file_stream, data, size); + size_t need_to_write = size; + do { + if(!buffered_file_stream_unread(stream)) break; + need_to_write -= stream_write(stream->file_stream, data, size); + } while(false); + return size - need_to_write; } static size_t buffered_file_stream_read(BufferedFileStream* stream, uint8_t* data, size_t size) { @@ -150,6 +157,19 @@ static bool buffered_file_stream_delete_and_insert( size_t delete_size, StreamWriteCB write_callback, const void* ctx) { - stream_cache_drop(stream->cache); - return stream_delete_and_insert(stream->file_stream, delete_size, write_callback, ctx); + return buffered_file_stream_unread(stream) && + stream_delete_and_insert(stream->file_stream, delete_size, write_callback, ctx); +} + +// Drop read cache and adjust the underlying stream seek position +static bool buffered_file_stream_unread(BufferedFileStream* stream) { + bool success = true; + const size_t cache_size = stream_cache_size(stream->cache); + const size_t cache_pos = stream_cache_pos(stream->cache); + if(cache_pos < cache_size) { + const int32_t offset = cache_size - cache_pos; + success = stream_seek(stream->file_stream, -offset, StreamOffsetFromCurrent); + } + stream_cache_drop(stream->cache); + return success; } From 1e732830ec23be2a9acff42c240609d53bed275a Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 2 Aug 2022 16:29:16 +0300 Subject: [PATCH 08/22] ci: check for uncommited changes after build (#1461) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: check for uncommited changes after build * assets: updated Manifest to match sources * ci: simplified uncommited files check * resources: Updated Manifest * fbt: always rebuild manifest Co-authored-by: あく --- .github/workflows/build.yml | 4 ++++ assets/SConscript | 3 +-- assets/resources/Manifest | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3ebb9ad6..d792c127c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -106,6 +106,10 @@ jobs: rm -rf artifacts/${BUNDLE_NAME} done + - name: "Check for uncommited changes" + run: | + git diff --exit-code + - name: 'Bundle resources' if: ${{ !github.event.pull_request.head.repo.fork }} run: | diff --git a/assets/SConscript b/assets/SConscript index 46cc2ca2a..ecb109567 100644 --- a/assets/SConscript +++ b/assets/SConscript @@ -103,8 +103,7 @@ if assetsenv["IS_BASE_FIRMWARE"]: ) assetsenv.Precious(resources) assetsenv.NoClean(resources) - if assetsenv["FORCE"]: - assetsenv.AlwaysBuild(resources) + assetsenv.AlwaysBuild(resources) # Exporting resources node to external environment env["FW_RESOURCES"] = resources diff --git a/assets/resources/Manifest b/assets/resources/Manifest index a0aeb67b9..b353e3426 100644 --- a/assets/resources/Manifest +++ b/assets/resources/Manifest @@ -1,5 +1,5 @@ V:0 -T:1655152832 +T:1658906571 D:badusb D:dolphin D:infrared @@ -232,10 +232,10 @@ F:41b4f08774249014cb8d3dffa5f5c07d:1757:nfc/assets/currency_code.nfc F:c60e862919731b0bd538a1001bbc1098:17453:nfc/assets/mf_classic_dict.nfc D:subghz/assets F:dda1ef895b8a25fde57c874feaaef997:650:subghz/assets/came_atomo -F:610a0ffa2479a874f2060eb2348104c5:2712:subghz/assets/keeloq_mfcodes +F:788eef2cc74e29f3388463d6607dab0d:3264:subghz/assets/keeloq_mfcodes F:9214f9c10463b746a27e82ce0b96e040:465:subghz/assets/keeloq_mfcodes_user F:653bd8d349055a41e1152e557d4a52d3:202:subghz/assets/nice_flor_s -F:c6ec4374275cd20f482ecd46de9f53e3:528:subghz/assets/setting_user +F:c1c63fbd5f5aa3ea504027014652191f:1150:subghz/assets/setting_user D:u2f/assets F:7e11e688e39034bbb9d88410044795e1:365:u2f/assets/cert.der F:f60b88c20ed479ed9684e249f7134618:264:u2f/assets/cert_key.u2f From a1637e9216e98396938debd7ccb4e15cbcb41eb1 Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 2 Aug 2022 16:46:43 +0300 Subject: [PATCH 09/22] fbt fixes & improvements (#1490) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fbt: minimal USB flash mode; scripts: faster storage.py with larger chunks * fbt: fixed creation of temporary file nodes confusing scons * docs: removed refs to --with-updater * fbt: removed splashscreen from minimal update package * fbt: renamed dist arguments for consistency * docs: fixed updater_debug target * fbt: separate target for generating compilation_database.json without building the code. * fbt: added `jflash` target for programming over JLink probe; refactored usb flashing targets * fbt: building updater_app in unit_tests configuration * fbt: fixed reset behavior after flashing with J-Link * fbt: generating .map file for firmware binary & external apps * fbt/core: moved library contents before apps code Co-authored-by: あく --- .github/workflows/build.yml | 4 +- ReadMe.md | 4 +- SConstruct | 66 +++++++++++------ applications/extapps.scons | 2 + debug/fw.jflash | 90 ++++++++++++++++++++++++ documentation/OTA.md | 9 ++- documentation/fbt.md | 14 ++-- fbt_options.py | 1 + firmware.scons | 15 ++-- firmware/targets/f7/stm32wb55xx_flash.ld | 1 + scripts/flipper/storage.py | 11 +-- scripts/selfupdate.py | 11 +-- scripts/storage.py | 11 +-- site_scons/site_tools/fbt_apps.py | 7 +- site_scons/site_tools/fbt_dist.py | 31 ++++++++ site_scons/site_tools/jflash.py | 27 +++++++ 16 files changed, 240 insertions(+), 64 deletions(-) create mode 100644 debug/fw.jflash create mode 100644 site_scons/site_tools/jflash.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d792c127c..ab3f59946 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,7 +78,7 @@ jobs: set -e for TARGET in ${TARGETS} do - ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} + ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} done - name: 'Move upload files' @@ -214,5 +214,5 @@ jobs: set -e for TARGET in ${TARGETS} do - ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package DEBUG=0 COMPACT=1 + ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package DEBUG=0 COMPACT=1 done diff --git a/ReadMe.md b/ReadMe.md index f3a350564..36a887dc4 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -29,11 +29,11 @@ They both must be flashed in the order described. With Flipper attached over USB: -`./fbt --with-updater flash_usb` +`./fbt flash_usb` Just building the package: -`./fbt --with-updater updater_package` +`./fbt updater_package` To update, copy the resulting directory to Flipper's SD card and navigate to `update.fuf` file in Archive app. diff --git a/SConstruct b/SConstruct index 7cdf88fca..178ae192c 100644 --- a/SConstruct +++ b/SConstruct @@ -33,8 +33,10 @@ coreenv["ROOT_DIR"] = Dir(".") # Create a separate "dist" environment and add construction envs to it distenv = coreenv.Clone( - tools=["fbt_dist", "openocd", "blackmagic"], - OPENOCD_GDB_PIPE=["|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"], + tools=["fbt_dist", "openocd", "blackmagic", "jflash"], + OPENOCD_GDB_PIPE=[ + "|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" + ], GDBOPTS_BASE=[ "-ex", "target extended-remote ${GDBREMOTE}", @@ -61,6 +63,7 @@ distenv = coreenv.Clone( "-ex", "compare-sections", ], + JFLASHPROJECT="${ROOT_DIR.abspath}/debug/fw.jflash", ENV=os.environ, ) @@ -71,7 +74,9 @@ firmware_env = distenv.AddFwProject( ) # If enabled, initialize updater-related targets -if GetOption("fullenv"): +if GetOption("fullenv") or any( + filter(lambda target: "updater" in target or "flash_usb" in target, BUILD_TARGETS) +): updater_env = distenv.AddFwProject( base_env=coreenv, fw_type="updater", @@ -79,11 +84,11 @@ if GetOption("fullenv"): ) # Target for self-update package - dist_arguments = [ - "-r", - '"${ROOT_DIR.abspath}/assets/resources"', + dist_basic_arguments = [ "--bundlever", '"${UPDATE_VERSION_STRING}"', + ] + dist_radio_arguments = [ "--radio", '"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"', "--radiotype", @@ -92,16 +97,34 @@ if GetOption("fullenv"): "--obdata", '"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"', ] - if distenv["UPDATE_SPLASH"]: - dist_arguments += [ + dist_resource_arguments = [ + "-r", + '"${ROOT_DIR.abspath}/assets/resources"', + ] + dist_splash_arguments = ( + [ "--splash", distenv.subst("assets/slideshow/$UPDATE_SPLASH"), ] + if distenv["UPDATE_SPLASH"] + else [] + ) selfupdate_dist = distenv.DistCommand( "updater_package", (distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]), - DIST_EXTRA=dist_arguments, + DIST_EXTRA=[ + *dist_basic_arguments, + *dist_radio_arguments, + *dist_resource_arguments, + *dist_splash_arguments, + ], + ) + + selfupdate_min_dist = distenv.DistCommand( + "updater_minpackage", + distenv["DIST_DEPENDS"], + DIST_EXTRA=dist_basic_arguments, ) # Updater debug @@ -121,18 +144,16 @@ if GetOption("fullenv"): ) # Installation over USB & CLI - usb_update_package = distenv.UsbInstall( - "#build/usbinstall.flag", - ( - distenv["DIST_DEPENDS"], - firmware_env["FW_RESOURCES"], - selfupdate_dist, - ), + usb_update_package = distenv.AddUsbFlashTarget( + "#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist) ) - if distenv["FORCE"]: - distenv.AlwaysBuild(usb_update_package) - distenv.Depends(usb_update_package, selfupdate_dist) - distenv.Alias("flash_usb", usb_update_package) + distenv.Alias("flash_usb_full", usb_update_package) + + usb_minupdate_package = distenv.AddUsbFlashTarget( + "#build/minusbinstall.flag", (selfupdate_min_dist,) + ) + distenv.Alias("flash_usb", usb_minupdate_package) + # Target for copying & renaming binaries to dist folder basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"]) @@ -147,8 +168,9 @@ distenv.Alias("copro_dist", copro_dist) firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env) distenv.Alias("flash", firmware_flash) -if distenv["FORCE"]: - distenv.AlwaysBuild(firmware_flash) + +firmware_jflash = distenv.AddJFlashTarget(firmware_env) +distenv.Alias("jflash", firmware_jflash) firmware_bm_flash = distenv.PhonyTarget( "flash_blackmagic", diff --git a/applications/extapps.scons b/applications/extapps.scons index a53620b93..11b597576 100644 --- a/applications/extapps.scons +++ b/applications/extapps.scons @@ -38,6 +38,8 @@ appenv.AppendUnique( "-Wl,--no-export-dynamic", "-fvisibility=hidden", "-Wl,-e${APP_ENTRY}", + "-Xlinker", + "-Map=${TARGET}.map", ], ) diff --git a/debug/fw.jflash b/debug/fw.jflash new file mode 100644 index 000000000..8621efb4d --- /dev/null +++ b/debug/fw.jflash @@ -0,0 +1,90 @@ + AppVersion = 76803 + FileVersion = 2 +[GENERAL] + aATEModuleSel[24] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ConnectMode = 0 + CurrentFile = "..\build\latest\firmware.bin" + DataFileSAddr = 0x08000000 + GUIMode = 0 + HostName = "" + TargetIF = 1 + USBPort = 0 + USBSerialNo = 0x00000000 + UseATEModuleSelection = 0 +[JTAG] + IRLen = 0 + MultipleTargets = 0 + NumDevices = 0 + Speed0 = 8000 + Speed1 = 8000 + TAP_Number = 0 + UseAdaptive0 = 0 + UseAdaptive1 = 0 + UseMaxSpeed0 = 0 + UseMaxSpeed1 = 0 +[CPU] + NumInitSteps = 2 + InitStep0_Action = "Reset" + InitStep0_Value0 = 0x00000000 + InitStep0_Value1 = 0x00000000 + InitStep0_Comment = "" + InitStep1_Action = "Halt" + InitStep1_Value0 = 0xFFFFFFFF + InitStep1_Value1 = 0xFFFFFFFF + InitStep1_Comment = "" + NumExitSteps = 1 + ExitStep0_Action = "Reset" + ExitStep0_Value0 = 0x00000005 + ExitStep0_Value1 = 0x00000032 + ExitStep0_Comment = "" + UseScriptFile = 0 + ScriptFile = "" + UseRAM = 1 + RAMAddr = 0x20000000 + RAMSize = 0x00030000 + CheckCoreID = 1 + CoreID = 0x6BA02477 + CoreIDMask = 0x0F000FFF + UseAutoSpeed = 0x00000001 + ClockSpeed = 0x00000000 + EndianMode = 0 + ChipName = "ST STM32WB55RG" +[FLASH] + aRangeSel[1] = 0-255 + BankName = "Internal flash" + BankSelMode = 1 + BaseAddr = 0x08000000 + NumBanks = 1 +[PRODUCTION] + AutoPerformsDisconnect = 0 + AutoPerformsErase = 1 + AutoPerformsProgram = 1 + AutoPerformsSecure = 0 + AutoPerformsStartApp = 1 + AutoPerformsUnsecure = 0 + AutoPerformsVerify = 0 + EnableFixedVTref = 0 + EnableTargetPower = 0 + EraseType = 1 + FixedVTref = 0x00000CE4 + MonitorVTref = 0 + MonitorVTrefMax = 0x0000157C + MonitorVTrefMin = 0x000003E8 + OverrideTimeouts = 0 + ProgramSN = 0 + SerialFile = "" + SNAddr = 0x00000000 + SNInc = 0x00000001 + SNLen = 0x00000004 + SNListFile = "" + SNValue = 0x00000001 + StartAppType = 1 + TargetPowerDelay = 0x00000014 + TimeoutErase = 0x00003A98 + TimeoutProgram = 0x00002710 + TimeoutVerify = 0x00002710 + VerifyType = 1 +[PERFORMANCE] + DisableSkipBlankDataOnProgram = 0x00000000 + PerfromBlankCheckPriorEraseChip = 0x00000001 + PerfromBlankCheckPriorEraseSelectedSectors = 0x00000001 diff --git a/documentation/OTA.md b/documentation/OTA.md index 3e82336c1..2a6b09846 100644 --- a/documentation/OTA.md +++ b/documentation/OTA.md @@ -110,7 +110,12 @@ Even if something goes wrong, Updater gives you an option to retry failed operat ## Full package -To build a basic update package, run `./fbt --with-updater COMPACT=1 DEBUG=0 updater_package` +To build full update package, including firmware, radio stack and resources for SD card, run `./fbt COMPACT=1 DEBUG=0 updater_package` + + +## Minimal package + +To build minimal update package, including only firmware, run `./fbt COMPACT=1 DEBUG=0 updater_minpackage` ## Customizing update bundles @@ -118,7 +123,7 @@ To build a basic update package, run `./fbt --with-updater COMPACT=1 DEBUG=0 upd Default update packages are built with Bluetooth Light stack. You can pick a different stack, if your firmware version supports it, and build a bundle with it passing stack type and binary name to `fbt`: -`./fbt --with-updater updater_package COMPACT=1 DEBUG=0 COPRO_OB_DATA=scripts/ob_custradio.data COPRO_STACK_BIN=stm32wb5x_BLE_Stack_full_fw.bin COPRO_STACK_TYPE=ble_full` +`./fbt updater_package COMPACT=1 DEBUG=0 COPRO_OB_DATA=scripts/ob_custradio.data COPRO_STACK_BIN=stm32wb5x_BLE_Stack_full_fw.bin COPRO_STACK_TYPE=ble_full` Note that `COPRO_OB_DATA` must point to a valid file in `scripts` folder containing reference Option Byte data matching to your radio stack type. diff --git a/documentation/fbt.md b/documentation/fbt.md index af10cd9cd..7e56672ec 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -20,7 +20,7 @@ Make sure that `gcc-arm-none-eabi` toolchain & OpenOCD executables are in system To build with FBT, call it specifying configuration options & targets to build. For example, -`./fbt --with-updater COMPACT=1 DEBUG=0 VERBOSE=1 updater_package copro_dist` +`./fbt COMPACT=1 DEBUG=0 VERBOSE=1 updater_package copro_dist` To run cleanup (think of `make clean`) for specified targets, add `-c` option. @@ -31,13 +31,13 @@ FBT keeps track of internal dependencies, so you only need to build the highest- ### High-level (what you most likely need) - `fw_dist` - build & publish firmware to `dist` folder. This is a default target, when no other are specified -- `updater_package` - build self-update package. _Requires `--with-updater` option_ +- `updater_package`, `updater_minpackage` - build self-update package. Minimal version only inclues firmware's DFU file; full version also includes radio stack & resources for SD card - `copro_dist` - bundle Core2 FUS+stack binaries for qFlipper - `flash` - flash attached device with OpenOCD over ST-Link -- `flash_usb` - build, upload and install update package to device over USB. _Requires `--with-updater` option_ +- `flash_usb`, `flash_usb_full` - build, upload and install update package to device over USB. See details on `updater_package`, `updater_minpackage` - `debug` - build and flash firmware, then attach with gdb with firmware's .elf loaded -- `debug_updater` - attach gdb with updater's .elf loaded. _Requires `--with-updater` option_ -- `debug_other` - attach gdb without loading any .elf. Allows to manually add external elf files with `add-symbol-file` in gdb. +- `debug_other` - attach gdb without loading any .elf. Allows to manually add external elf files with `add-symbol-file` in gdb +- `updater_debug` - attach gdb with updater's .elf loaded - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board) - `openocd` - just start OpenOCD - `get_blackmagic` - output blackmagic address in gdb remote format. Useful for IDE integration @@ -49,9 +49,11 @@ FBT keeps track of internal dependencies, so you only need to build the highest- - Check out `--extra-ext-apps` for force adding extra apps to external build - `firmware_snake_game_list`, etc - generate source + assembler listing for app's .elf - `flash`, `firmware_flash` - flash current version to attached device with OpenOCD over ST-Link +- `jflash` - flash current version to attached device with JFlash using J-Link probe. JFlash executable must be on your $PATH - `flash_blackmagic` - flash current version to attached device with Blackmagic probe - `firmware_all`, `updater_all` - build basic set of binaries - `firmware_list`, `updater_list` - generate source + assembler listing +- `firmware_cdb`, `updater_cdb` - generate `compilation_database.json` file for external tools and IDEs. It can be created without actually building the firmware. ### Assets @@ -66,7 +68,7 @@ FBT keeps track of internal dependencies, so you only need to build the highest- ## Command-line parameters - `--options optionfile.py` (default value `fbt_options.py`) - load file with multiple configuration values -- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this option introduces extra startup time costs, so use it when bundling update packages. Or if you have a fast computer and don't care about a few extra seconds of startup time +- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this option introduces extra startup time costs, so use it when bundling update packages. _Explicily enabling this should no longer be required, fbt now has specific handling for updater-related targets_ - `--extra-int-apps=app1,app2,appN` - forces listed apps to be built as internal with `firmware` target - `--extra-ext-apps=app1,app2,appN` - forces listed apps to be built as external with `firmware_extapps` target diff --git a/fbt_options.py b/fbt_options.py index fb2a0d366..7276f579e 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -80,6 +80,7 @@ FIRMWARE_APPS = { ], "unit_tests": [ "basic_services", + "updater_app", "unit_tests", ], } diff --git a/firmware.scons b/firmware.scons index 438ac8e72..76f0b52de 100644 --- a/firmware.scons +++ b/firmware.scons @@ -9,7 +9,11 @@ from fbt.util import ( # Building initial C environment for libs env = ENV.Clone( - tools=["compilation_db", "fwbin", "fbt_apps"], + tools=[ + ("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}), + "fwbin", + "fbt_apps", + ], COMPILATIONDB_USE_ABSPATH=False, BUILD_DIR=fw_build_meta["build_dir"], IS_BASE_FIRMWARE=fw_build_meta["type"] == "firmware", @@ -76,7 +80,6 @@ if not env["VERBOSE"]: HEXCOMSTR="\tHEX\t${TARGET}", BINCOMSTR="\tBIN\t${TARGET}", DFUCOMSTR="\tDFU\t${TARGET}", - OPENOCDCOMSTR="\tFLASH\t${SOURCE}", ) @@ -139,7 +142,7 @@ apps_c = fwenv.ApplicationsC( Value(fwenv["APPS"]), ) # Adding dependency on manifest files so apps.c is rebuilt when any manifest is changed -fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", "applications")) +fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", "#/applications")) sources = [apps_c] # Gather sources only from app folders in current configuration @@ -164,6 +167,8 @@ fwenv.AppendUnique( "-u", "_printf_float", "-n", + "-Xlinker", + "-Map=${TARGET}.map", ], ) @@ -202,7 +207,6 @@ fwelf = fwenv["FW_ELF"] = fwenv.Program( ], ) -# Make it depend on everything child builders returned # Firmware depends on everything child builders returned Depends(fwelf, lib_targets) # Output extra details after building firmware @@ -232,7 +236,8 @@ if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS): fwcdb = fwenv.CompilationDatabase() # without filtering, both updater & firmware commands would be generated fwenv.Replace(COMPILATIONDB_PATH_FILTER=fwenv.subst("*${FW_FLAVOR}*")) - Depends(fwcdb, fwelf) + AlwaysBuild(fwcdb) + Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb) fw_artifacts.append(fwcdb) # Adding as a phony target, so folder link is updated even if elf didn't change diff --git a/firmware/targets/f7/stm32wb55xx_flash.ld b/firmware/targets/f7/stm32wb55xx_flash.ld index 1d0e916b0..20314ba3c 100644 --- a/firmware/targets/f7/stm32wb55xx_flash.ld +++ b/firmware/targets/f7/stm32wb55xx_flash.ld @@ -75,6 +75,7 @@ SECTIONS .text : { . = ALIGN(4); + *lib*.a:*(.text .text.*) /* code from libraries before apps */ *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ diff --git a/scripts/flipper/storage.py b/scripts/flipper/storage.py index 3d1b46b94..5fa8a2c81 100644 --- a/scripts/flipper/storage.py +++ b/scripts/flipper/storage.py @@ -53,13 +53,14 @@ class FlipperStorage: CLI_PROMPT = ">: " CLI_EOL = "\r\n" - def __init__(self, portname: str, portbaud: int = 115200): + def __init__(self, portname: str, chunk_size: int = 8192): self.port = serial.Serial() self.port.port = portname self.port.timeout = 2 - self.port.baudrate = portbaud + self.port.baudrate = 115200 # Doesn't matter for VCP self.read = BufferedRead(self.port) self.last_error = "" + self.chunk_size = chunk_size def start(self): self.port.open() @@ -192,7 +193,7 @@ class FlipperStorage: with open(filename_from, "rb") as file: filesize = os.fstat(file.fileno()).st_size - buffer_size = 512 + buffer_size = self.chunk_size while True: filedata = file.read(buffer_size) size = len(filedata) @@ -221,7 +222,7 @@ class FlipperStorage: def read_file(self, filename): """Receive file from Flipper, and get filedata (bytes)""" - buffer_size = 512 + buffer_size = self.chunk_size self.send_and_wait_eol( 'storage read_chunks "' + filename + '" ' + str(buffer_size) + "\r" ) @@ -355,7 +356,7 @@ class FlipperStorage: """Hash of local file""" hash_md5 = hashlib.md5() with open(filename, "rb") as f: - for chunk in iter(lambda: f.read(4096), b""): + for chunk in iter(lambda: f.read(self.chunk_size), b""): hash_md5.update(chunk) return hash_md5.hexdigest() diff --git a/scripts/selfupdate.py b/scripts/selfupdate.py index 6d7057474..1c16c5ca6 100644 --- a/scripts/selfupdate.py +++ b/scripts/selfupdate.py @@ -14,14 +14,6 @@ import serial.tools.list_ports as list_ports class Main(App): def init(self): self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") - self.parser.add_argument( - "-b", - "--baud", - help="Port Baud rate", - required=False, - default=115200 * 4, - type=int, - ) self.parser.add_argument("manifest_path", help="Manifest path") self.parser.add_argument( @@ -64,7 +56,7 @@ class Main(App): if not (port := resolve_port(self.logger, self.args.port)): return 1 - storage = FlipperStorage(port, self.args.baud) + storage = FlipperStorage(port) storage.start() try: @@ -99,6 +91,7 @@ class Main(App): self.logger.error(f"Error: {storage.last_error}") return -3 + # return -11 storage.send_and_wait_eol( f"update install {flipper_update_path}/{manifest_name}\r" ) diff --git a/scripts/storage.py b/scripts/storage.py index 0ddc2fc0c..167ba88eb 100755 --- a/scripts/storage.py +++ b/scripts/storage.py @@ -14,14 +14,7 @@ import tempfile class Main(App): def init(self): self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") - self.parser.add_argument( - "-b", - "--baud", - help="Port Baud rate", - required=False, - default=115200 * 4, - type=int, - ) + self.subparsers = self.parser.add_subparsers(help="sub-command help") self.parser_mkdir = self.subparsers.add_parser("mkdir", help="Create directory") @@ -77,7 +70,7 @@ class Main(App): if not (port := resolve_port(self.logger, self.args.port)): return None - storage = FlipperStorage(port, self.args.baud) + storage = FlipperStorage(port) storage.start() return storage diff --git a/site_scons/site_tools/fbt_apps.py b/site_scons/site_tools/fbt_apps.py index a0c43fa79..aaf08bfad 100644 --- a/site_scons/site_tools/fbt_apps.py +++ b/site_scons/site_tools/fbt_apps.py @@ -2,6 +2,7 @@ from SCons.Builder import Builder from SCons.Action import Action from SCons.Warnings import warn, WarningOnByDefault import SCons +import os.path from fbt.appmanifest import ( FlipperAppType, @@ -17,10 +18,12 @@ from fbt.appmanifest import ( def LoadApplicationManifests(env): appmgr = env["APPMGR"] = AppManager() - for entry in env.Glob("#/applications/*", source=True): + for entry in env.Glob("#/applications/*", ondisk=True, source=True): if isinstance(entry, SCons.Node.FS.Dir) and not str(entry).startswith("."): try: - appmgr.load_manifest(entry.File("application.fam").abspath, entry.name) + appmgr.load_manifest( + os.path.join(entry.abspath, "application.fam"), entry.name + ) except FlipperManifestException as e: warn(WarningOnByDefault, str(e)) diff --git a/site_scons/site_tools/fbt_dist.py b/site_scons/site_tools/fbt_dist.py index 7c28c69c4..399b7ecdd 100644 --- a/site_scons/site_tools/fbt_dist.py +++ b/site_scons/site_tools/fbt_dist.py @@ -66,9 +66,38 @@ def AddOpenOCDFlashTarget(env, targetenv, **kw): **kw, ) env.Alias(targetenv.subst("${FIRMWARE_BUILD_CFG}_flash"), openocd_target) + if env["FORCE"]: + env.AlwaysBuild(openocd_target) return openocd_target +def AddJFlashTarget(env, targetenv, **kw): + jflash_target = env.JFlash( + "#build/jflash-${BUILD_CFG}-flash.flag", + targetenv["FW_BIN"], + JFLASHADDR=targetenv.subst("$IMAGE_BASE_ADDRESS"), + BUILD_CFG=targetenv.subst("${FIRMWARE_BUILD_CFG}"), + **kw, + ) + env.Alias(targetenv.subst("${FIRMWARE_BUILD_CFG}_jflash"), jflash_target) + if env["FORCE"]: + env.AlwaysBuild(jflash_target) + return jflash_target + + +def AddUsbFlashTarget(env, file_flag, extra_deps, **kw): + usb_update = env.UsbInstall( + file_flag, + ( + env["DIST_DEPENDS"], + *extra_deps, + ), + ) + if env["FORCE"]: + env.AlwaysBuild(usb_update) + return usb_update + + def DistCommand(env, name, source, **kw): target = f"dist_{name}" command = env.Command( @@ -86,6 +115,8 @@ def generate(env): env.AddMethod(AddFwProject) env.AddMethod(DistCommand) env.AddMethod(AddOpenOCDFlashTarget) + env.AddMethod(AddJFlashTarget) + env.AddMethod(AddUsbFlashTarget) env.SetDefault( COPRO_MCU_FAMILY="STM32WB5x", diff --git a/site_scons/site_tools/jflash.py b/site_scons/site_tools/jflash.py new file mode 100644 index 000000000..aea7279b6 --- /dev/null +++ b/site_scons/site_tools/jflash.py @@ -0,0 +1,27 @@ +from SCons.Builder import Builder +from SCons.Defaults import Touch + + +def generate(env): + env.SetDefault( + JFLASH="JFlash" if env.subst("$PLATFORM") == "win32" else "JFlashExe", + JFLASHFLAGS=[ + "-auto", + "-exit", + ], + JFLASHCOM="${JFLASH} -openprj${JFLASHPROJECT} -open${SOURCE},${JFLASHADDR} ${JFLASHFLAGS}", + ) + env.Append( + BUILDERS={ + "JFlash": Builder( + action=[ + "${JFLASHCOM}", + Touch("${TARGET}"), + ], + ), + } + ) + + +def exists(env): + return True From 93a4b9c4a9ee35372e95eae7f96fffd42a2a809e Mon Sep 17 00:00:00 2001 From: Max Andreev Date: Tue, 2 Aug 2022 17:05:31 +0300 Subject: [PATCH 10/22] [FL-2649] Drop Docker in CI/CD (#1412) * enable sparseCheckout, moving github actions from docker to raw shell * fix missing known_hosts while setting ssh priv key * fix build.yml * add ssh key to upload just in time * fixing rsync syntax * fix build.yml * try to fix build.yml again * testing rsync * test rsync again * add linters * add Black Python linter to submodules * add Black submodule * add working python linter target, dirty file list * up toolchain to version 4 * up toolchain to ver 5 * up toolchain version to 6 * fbt: using black 22.6.0 * remove Black submodule, up toolchain to ver 7 * fbt: added lint_py, format_py targets * add pvs_studio workflow * fix pvs_studio segfault * fix pvs_studio command * fix pvs_studio command 2 * show env before run pvs_studio * try to debug pvs_studio * try to strace pvs_studio.. * Add FBT_TOOLCHAIN_PATH, MacOS Rosseta check, and ignore non-x86_64 linux architectures * prevent redownloading toolchain on github-runners * fix toolchain download exitcode * add strace to debug pvs_studio segfault * disable strace to catch full code dump * Add './fbt cli' target to access Flipper CLI via PySerial * remove pvs_studio from this PR * removing clang-format from toolchain due errors * make source easy, and fix some mistakes found by @hedger * Add check_submodules workflow, some fixes * fixing mistakes Co-authored-by: hedger Co-authored-by: hedger --- .github/workflows/build.yml | 111 ++++------ .github/workflows/build_toolchain.yml | 46 ---- .github/workflows/check_submodules.yml | 52 ++++- .github/workflows/lint_c.yml | 24 +- .github/workflows/lint_python.yml | 14 +- .github/workflows/reindex.yml | 7 +- SConstruct | 41 ++++ documentation/fbt.md | 2 + fbt | 14 +- lib/loclass.scons | 2 - lib/mbedtls.scons | 2 - scripts/serial_cli.py | 14 ++ scripts/toolchain/fbtenv.cmd | 2 +- scripts/toolchain/fbtenv.sh | 219 ++++++++++++++++--- scripts/toolchain/unix-toolchain-download.sh | 135 ------------ site_scons/site_tools/fbt_apps.py | 7 +- site_scons/site_tools/sconsmodular.py | 5 +- 17 files changed, 357 insertions(+), 340 deletions(-) delete mode 100644 .github/workflows/build_toolchain.yml create mode 100644 scripts/serial_cli.py delete mode 100755 scripts/toolchain/unix-toolchain-download.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ab3f59946..b491c600c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,11 +15,8 @@ env: jobs: main: - runs-on: [self-hosted,FlipperZero] + runs-on: [self-hosted,FlipperZeroShell] steps: - - name: 'Cleanup workspace' - uses: AutoModality/action-clean@v1 - - name: 'Decontaminate previous build leftovers' run: | if [ -d .git ] @@ -32,12 +29,8 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 - submodules: true ref: ${{ github.event.pull_request.head.sha }} - - name: 'Build docker image' - uses: ./.github/actions/docker - - name: 'Make artifacts directory' run: | test -d artifacts && rm -rf artifacts || true @@ -71,40 +64,34 @@ jobs: run: | tar czpf artifacts/flipper-z-any-scripts-${{steps.names.outputs.suffix}}.tgz scripts - - name: 'Build the firmware in docker' - uses: ./.github/actions/docker - with: - run: | - set -e - for TARGET in ${TARGETS} - do - ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} - done + - name: 'Build the firmware' + run: | + set -e + for TARGET in ${TARGETS} + do + FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} + done - name: 'Move upload files' if: ${{ !github.event.pull_request.head.repo.fork }} - uses: ./.github/actions/docker - with: - run: | - set -e - for TARGET in ${TARGETS} - do - mv dist/${TARGET}-*/* artifacts/ - done + run: | + set -e + for TARGET in ${TARGETS} + do + mv dist/${TARGET}-*/* artifacts/ + done - name: 'Bundle self-update package' if: ${{ !github.event.pull_request.head.repo.fork }} - uses: ./.github/actions/docker - with: - run: | - set -e - for UPDATEBUNDLE in artifacts/*/ - do - BUNDLE_NAME=`echo $UPDATEBUNDLE | cut -d'/' -f2` - echo Packaging ${BUNDLE_NAME} - tar czpf artifacts/flipper-z-${BUNDLE_NAME}.tgz -C artifacts ${BUNDLE_NAME} - rm -rf artifacts/${BUNDLE_NAME} - done + run: | + set -e + for UPDATEBUNDLE in artifacts/*/ + do + BUNDLE_NAME=`echo $UPDATEBUNDLE | cut -d'/' -f2` + echo Packaging ${BUNDLE_NAME} + tar czpf artifacts/flipper-z-${BUNDLE_NAME}.tgz -C artifacts ${BUNDLE_NAME} + rm -rf artifacts/${BUNDLE_NAME} + done - name: "Check for uncommited changes" run: | @@ -117,29 +104,23 @@ jobs: - name: 'Bundle core2 firmware' if: ${{ !github.event.pull_request.head.repo.fork }} - uses: ./.github/actions/docker - with: - run: | - ./fbt copro_dist - tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz -C assets core2_firmware + run: | + FBT_TOOLCHAIN_PATH=/opt ./fbt copro_dist + tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz -C assets core2_firmware - name: 'Upload artifacts to update server' if: ${{ !github.event.pull_request.head.repo.fork }} - uses: burnett01/rsync-deployments@5.1 - with: - switches: -avzP --delete --mkpath - path: artifacts/ - remote_path: "${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/" - remote_host: ${{ secrets.RSYNC_DEPLOY_HOST }} - remote_port: ${{ secrets.RSYNC_DEPLOY_PORT }} - remote_user: ${{ secrets.RSYNC_DEPLOY_USER }} - remote_key: ${{ secrets.RSYNC_DEPLOY_KEY }} + run: | + echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; + chmod 600 ./deploy_key; + rsync -avzP --mkpath \ + -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \ + artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/"; + rm ./deploy_key; - name: 'Trigger update server reindex' if: ${{ !github.event.pull_request.head.repo.fork }} - uses: wei/curl@master - with: - args: -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }} + run: curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }} - name: 'Find Previous Comment' if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }} @@ -165,11 +146,8 @@ jobs: compact: if: ${{ !startsWith(github.ref, 'refs/tags') }} - runs-on: [self-hosted,FlipperZero] + runs-on: [self-hosted,FlipperZeroShell] steps: - - name: 'Cleanup workspace' - uses: AutoModality/action-clean@v1 - - name: 'Decontaminate previous build leftovers' run: | if [ -d .git ] @@ -185,9 +163,6 @@ jobs: submodules: true ref: ${{ github.event.pull_request.head.sha }} - - name: 'Build docker image' - uses: ./.github/actions/docker - - name: 'Generate suffix and folder name' id: names run: | @@ -207,12 +182,10 @@ jobs: echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV - - name: 'Build the firmware in docker' - uses: ./.github/actions/docker - with: - run: | - set -e - for TARGET in ${TARGETS} - do - ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package DEBUG=0 COMPACT=1 - done + - name: 'Build the firmware' + run: | + set -e + for TARGET in ${TARGETS} + do + FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package DEBUG=0 COMPACT=1 + done diff --git a/.github/workflows/build_toolchain.yml b/.github/workflows/build_toolchain.yml deleted file mode 100644 index 452dfbee6..000000000 --- a/.github/workflows/build_toolchain.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: 'Build toolchain Docker image' - -on: - push: - branches: - - dev - tags: - - '*' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Docker meta - id: meta - uses: docker/metadata-action@v3 - with: - images: flipperdevices/flipperzero-toolchain - flavor: latest=${{ startsWith(github.ref, 'refs/tags/') && !endsWith(github.ref, 'rc')}} - tags: | - type=ref,event=branch - type=ref,event=tag - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push - id: docker_build - uses: docker/build-push-action@v2 - with: - context: docker/ - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - platforms: linux/amd64,linux/arm64 - cache-from: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache - cache-to: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache,mode=max diff --git a/.github/workflows/check_submodules.yml b/.github/workflows/check_submodules.yml index b02f9a8d0..f9699be87 100644 --- a/.github/workflows/check_submodules.yml +++ b/.github/workflows/check_submodules.yml @@ -1,17 +1,47 @@ -name: 'Check submodules' +name: 'Check submodules branch' on: + push: + branches: + - dev + - "release*" + tags: + - '*' pull_request: jobs: - protobuf: - runs-on: ubuntu-latest + check_protobuf: + runs-on: [self-hosted, FlipperZeroShell] steps: - - name: 'Checkout code' - uses: actions/checkout@v2 - - name: 'Check submodule commit branch' - uses: jtmullen/submodule-branch-check-action@v1 - with: - path: assets/protobuf - branch: dev - fetch_depth: 50 + - name: 'Decontaminate previous build leftovers' + run: | + if [ -d .git ] + then + git submodule status \ + || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1` + fi + + - name: 'Checkout code' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: 'Check protobuf branch' + run: | + SUB_PATH="assets/protobuf"; + SUB_BRANCH="dev"; + SUB_COMMITS_MIN=40; + cd "$SUB_PATH"; + SUBMODULE_HASH="$(git rev-parse HEAD)"; + BRANCHES=$(git branch -r --contains "$SUBMODULE_HASH"); + COMMITS_IN_BRANCH="$(git rev-list --count dev)"; + if [ $COMMITS_IN_BRANCH -lt $SUB_COMMITS_MIN ]; then + echo "::set-output name=fails::error"; + echo "::error::Error: Too low commits in $SUB_BRANCH of submodule $SUB_PATH: $COMMITS_IN_BRANCH(expected $SUB_COMMITS_MIN+)"; + exit 1; + fi + if ! grep -q "/$SUB_BRANCH" <<< "$BRANCHES"; then + echo "::set-output name=fails::error"; + echo "::error::Error: Submodule $SUB_PATH is not on branch $SUB_BRANCH"; + exit 1; + fi diff --git a/.github/workflows/lint_c.yml b/.github/workflows/lint_c.yml index f834586d3..aaff396ec 100644 --- a/.github/workflows/lint_c.yml +++ b/.github/workflows/lint_c.yml @@ -1,6 +1,6 @@ name: 'Lint C/C++ with clang-format' -on: +on: push: branches: - dev @@ -14,11 +14,8 @@ env: jobs: lint_c_cpp: - runs-on: [self-hosted,FlipperZero] + runs-on: [self-hosted,FlipperZeroShell] steps: - - name: 'Cleanup workspace' - uses: AutoModality/action-clean@v1 - - name: 'Decontaminate previous build leftovers' run: | if [ -d .git ] @@ -31,23 +28,10 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 - submodules: true - - - name: 'Docker cache' - uses: satackey/action-docker-layer-caching@v0.0.11 - continue-on-error: true - with: - key: docker-cache-${{ hashFiles('docker/**') }}-{hash} - restore-keys: docker-cache-${{ hashFiles('docker/**') }}- - - - name: 'Build docker image' - uses: ./.github/actions/docker - name: 'Check code formatting' id: syntax_check - uses: ./.github/actions/docker - with: - run: SET_GH_OUTPUT=1 ./fbt lint + run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/opt ./fbt lint - name: Report code formatting errors if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request @@ -59,4 +43,4 @@ jobs: ``` ${{ steps.syntax_check.outputs.errors }} ``` - You might want to run `docker compose exec dev make format` for an auto-fix. + You might want to run `./fbt format` for an auto-fix. diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index e665378b1..c059f4348 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -1,6 +1,6 @@ name: 'Python Lint' -on: +on: push: branches: - dev @@ -11,11 +11,8 @@ on: jobs: lint_python: - runs-on: ubuntu-latest + runs-on: [self-hosted,FlipperZeroShell] steps: - - name: 'Cleanup workspace' - uses: AutoModality/action-clean@v1 - - name: 'Decontaminate previous build leftovers' run: | if [ -d .git ] @@ -29,8 +26,5 @@ jobs: with: fetch-depth: 0 - - name: 'Setup python' - uses: actions/setup-python@v2 - - - name: 'Check python code with black' - uses: psf/black@20.8b1 + - name: 'Check code formatting' + run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/opt ./fbt lint_py diff --git a/.github/workflows/reindex.yml b/.github/workflows/reindex.yml index 78f9cbead..ea850e705 100644 --- a/.github/workflows/reindex.yml +++ b/.github/workflows/reindex.yml @@ -7,9 +7,8 @@ on: jobs: reindex: name: 'Reindex updates' - runs-on: [self-hosted,FlipperZero] + runs-on: [self-hosted,FlipperZeroShell] steps: - name: Trigger reindex - uses: wei/curl@master - with: - args: -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }} + run: | + curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }} diff --git a/SConstruct b/SConstruct index 178ae192c..fe731e357 100644 --- a/SConstruct +++ b/SConstruct @@ -7,6 +7,7 @@ # construction of certain targets behind command-line options. import os +import subprocess EnsurePythonVersion(3, 8) @@ -231,6 +232,46 @@ distenv.PhonyTarget( LINT_SOURCES=firmware_env["LINT_SOURCES"], ) +# PY_LINT_SOURCES contains recursively-built modules' SConscript files + application manifests +# Here we add additional Python files residing in repo root +firmware_env.Append( + PY_LINT_SOURCES=[ + # Py code folders + "site_scons", + "scripts", + # Extra files + "applications/extapps.scons", + "SConstruct", + "firmware.scons", + "fbt_options.py", + ] +) + + +black_commandline = "@${PYTHON3} -m black ${PY_BLACK_ARGS} ${PY_LINT_SOURCES}" +black_base_args = ["--include", '"\\.scons|\\.py|SConscript|SConstruct"'] + +distenv.PhonyTarget( + "lint_py", + black_commandline, + PY_BLACK_ARGS=[ + "--check", + "--diff", + *black_base_args, + ], + PY_LINT_SOURCES=firmware_env["PY_LINT_SOURCES"], +) + +distenv.PhonyTarget( + "format_py", + black_commandline, + PY_BLACK_ARGS=black_base_args, + PY_LINT_SOURCES=firmware_env["PY_LINT_SOURCES"], +) + +# Start Flipper CLI via PySerial's miniterm +distenv.PhonyTarget("cli", "${PYTHON3} scripts/serial_cli.py") + # Find blackmagic probe diff --git a/documentation/fbt.md b/documentation/fbt.md index 7e56672ec..c658ce20e 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -41,6 +41,8 @@ FBT keeps track of internal dependencies, so you only need to build the highest- - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board) - `openocd` - just start OpenOCD - `get_blackmagic` - output blackmagic address in gdb remote format. Useful for IDE integration +- `lint`, `format` - run clang-tidy on C source code to check and reformat it according to `.clang-format` specs +- `lint_py`, `format_py` - run [black](https://black.readthedocs.io/en/stable/index.html) on Python source code, build system files & application manifests ### Firmware targets diff --git a/fbt b/fbt index 0ea572b12..981489dd1 100755 --- a/fbt +++ b/fbt @@ -4,14 +4,20 @@ # unofficial strict mode set -eu; -SCONS_DEFAULT_FLAGS="-Q --warn=target-not-built"; +# private variables SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd -P)"; +SCONS_DEFAULT_FLAGS="-Q --warn=target-not-built"; -if [ -z "${FBT_NOENV:-}" ]; then +# public variables +FBT_NOENV="${FBT_NOENV:-""}"; +FBT_NO_SYNC="${FBT_NO_SYNC:-""}"; +FBT_TOOLCHAIN_PATH="${FBT_TOOLCHAIN_PATH:-$SCRIPT_PATH}"; + +if [ -z "$FBT_NOENV" ]; then . "$SCRIPT_PATH/scripts/toolchain/fbtenv.sh"; fi -if [ -z "${FBT_NO_SYNC:-}" ]; then +if [ -z "$FBT_NO_SYNC" ]; then if [ ! -d "$SCRIPT_PATH/.git" ]; then echo "\".git\" directory not found, please clone repo via \"git clone --recursive\""; exit 1; @@ -19,4 +25,4 @@ if [ -z "${FBT_NO_SYNC:-}" ]; then git submodule update --init; fi -python3 "$SCRIPT_PATH/lib/scons/scripts/scons.py" $SCONS_DEFAULT_FLAGS "$@" \ No newline at end of file +python3 "$SCRIPT_PATH/lib/scons/scripts/scons.py" $SCONS_DEFAULT_FLAGS "$@" diff --git a/lib/loclass.scons b/lib/loclass.scons index ba43dd6e7..a657f0424 100644 --- a/lib/loclass.scons +++ b/lib/loclass.scons @@ -4,8 +4,6 @@ env.Append( CPPPATH=[ "#/lib/loclass", ], - CPPDEFINES=[ - ], ) diff --git a/lib/mbedtls.scons b/lib/mbedtls.scons index 35de7e6fc..1b0bec87d 100644 --- a/lib/mbedtls.scons +++ b/lib/mbedtls.scons @@ -5,8 +5,6 @@ env.Append( "#/lib/mbedtls", "#/lib/mbedtls/include", ], - CPPDEFINES=[ - ], ) diff --git a/scripts/serial_cli.py b/scripts/serial_cli.py new file mode 100644 index 000000000..e07e6bfb4 --- /dev/null +++ b/scripts/serial_cli.py @@ -0,0 +1,14 @@ +import logging +import subprocess +from flipper.utils.cdc import resolve_port + + +def main(): + logger = logging.getLogger() + if not (port := resolve_port(logger, "auto")): + return 1 + subprocess.call(["python3", "-m", "serial.tools.miniterm", "--raw", port, "230400"]) + + +if __name__ == "__main__": + main() diff --git a/scripts/toolchain/fbtenv.cmd b/scripts/toolchain/fbtenv.cmd index 1a9af5a48..471ce835c 100644 --- a/scripts/toolchain/fbtenv.cmd +++ b/scripts/toolchain/fbtenv.cmd @@ -13,7 +13,7 @@ if not [%FBT_NOENV%] == [] ( exit /b 0 ) -set "FLIPPER_TOOLCHAIN_VERSION=3" +set "FLIPPER_TOOLCHAIN_VERSION=8" set "FBT_TOOLCHAIN_ROOT=%FBT_ROOT%\toolchain\i686-windows" diff --git a/scripts/toolchain/fbtenv.sh b/scripts/toolchain/fbtenv.sh index 55bc89b07..654b1fe0d 100755 --- a/scripts/toolchain/fbtenv.sh +++ b/scripts/toolchain/fbtenv.sh @@ -1,54 +1,211 @@ #!/bin/sh -# unofficial strict mode -set -eu; +# shellcheck disable=SC2034,SC2016,SC2086 -FLIPPER_TOOLCHAIN_VERSION="3"; +# public variables +DEFAULT_SCRIPT_PATH="$(pwd -P)"; +SCRIPT_PATH="${SCRIPT_PATH:-$DEFAULT_SCRIPT_PATH}"; +FBT_TOOLCHAIN_VERSION="${FBT_TOOLCHAIN_VERSION:-"8"}"; +FBT_TOOLCHAIN_PATH="${FBT_TOOLCHAIN_PATH:-$SCRIPT_PATH}"; -get_kernel_type() +fbtenv_check_sourced() { - SYS_TYPE="$(uname -s)" + case "${ZSH_EVAL_CONTEXT:-""}" in *:file:*) + return 0;; + esac + case ${0##*/} in dash|-dash|bash|-bash|ksh|-ksh|sh|-sh) + return 0;; + esac + if [ "$(basename $0)" = "fbt" ]; then + return 0; + fi + echo "Running this script manually is wrong, please source it"; + echo "Example:"; + printf "\tsource scripts/toolchain/fbtenv.sh\n"; + return 1; +} + +fbtenv_check_script_path() +{ + if [ ! -x "$SCRIPT_PATH/fbt" ]; then + echo "Please source this script being into flipperzero-firmware root directory, or specify 'SCRIPT_PATH' manually"; + echo "Example:"; + printf "\tSCRIPT_PATH=lang/c/flipperzero-firmware source lang/c/flipperzero-firmware/scripts/fbtenv.sh\n"; + echo "If current directory is right, type 'unset SCRIPT_PATH' and try again" + return 1; + fi + return 0; +} + +fbtenv_get_kernel_type() +{ + SYS_TYPE="$(uname -s)"; + ARCH_TYPE="$(uname -m)"; + if [ "$ARCH_TYPE" != "x86_64" ] && [ "$SYS_TYPE" != "Darwin" ]; then + echo "Now we provide toolchain only for x86_64 arhitecture, sorry.."; + return 1; + fi if [ "$SYS_TYPE" = "Darwin" ]; then - TOOLCHAIN_PATH="toolchain/x86_64-darwin"; + fbtenv_check_rosetta || return 1; + TOOLCHAIN_ARCH_DIR="$FBT_TOOLCHAIN_PATH/toolchain/x86_64-darwin"; + TOOLCHAIN_URL="https://update.flipperzero.one/builds/toolchain/gcc-arm-none-eabi-10.3-x86_64-darwin-flipper-$FBT_TOOLCHAIN_VERSION.tar.gz"; elif [ "$SYS_TYPE" = "Linux" ]; then - TOOLCHAIN_PATH="toolchain/x86_64-linux"; + TOOLCHAIN_ARCH_DIR="$FBT_TOOLCHAIN_PATH/toolchain/x86_64-linux"; + TOOLCHAIN_URL="https://update.flipperzero.one/builds/toolchain/gcc-arm-none-eabi-10.3-x86_64-linux-flipper-$FBT_TOOLCHAIN_VERSION.tar.gz"; elif echo "$SYS_TYPE" | grep -q "MINGW"; then echo "In MinGW shell use \"fbt.cmd\" instead of \"fbt\""; - exit 1; + return 1; else - echo "Sorry, your system is not supported. Please report your configuration to us."; - exit 1; + echo "Your system is not recognized. Sorry.. Please report us your configuration."; + return 1; fi + return 0; } -check_download_toolchain() +fbtenv_check_rosetta() { - if [ ! -d "$SCRIPT_PATH/$TOOLCHAIN_PATH" ]; then - download_toolchain; - elif [ ! -f "$SCRIPT_PATH/$TOOLCHAIN_PATH/VERSION" ]; then - download_toolchain; - elif [ "$(cat "$SCRIPT_PATH/$TOOLCHAIN_PATH/VERSION")" -ne "$FLIPPER_TOOLCHAIN_VERSION" ]; then - download_toolchain; + if [ "$ARCH_TYPE" = "arm64" ]; then + if ! /usr/bin/pgrep -q oahd; then + echo "Flipper Zero Toolchain needs Rosetta2 to run under Apple Silicon"; + echo "Please instal it by typing 'softwareupdate --install-rosetta --agree-to-license'"; + return 1; + fi fi + return 0; } -download_toolchain() +fbtenv_check_tar() { - chmod 755 "$SCRIPT_PATH/scripts/toolchain/unix-toolchain-download.sh"; - "$SCRIPT_PATH/scripts/toolchain/unix-toolchain-download.sh" "$FLIPPER_TOOLCHAIN_VERSION" || exit 1; + printf "Checking tar.."; + if ! tar --version > /dev/null 2>&1; then + echo "no"; + return 1; + fi + echo "yes"; + return 0; } -main() +fbtenv_check_downloaded_toolchain() { - if [ -z "${SCRIPT_PATH:-}" ]; then - echo "Manual running of this script is not allowed."; - exit 1; + printf "Checking downloaded toolchain tgz.."; + if [ ! -f "$FBT_TOOLCHAIN_PATH/toolchain/$TOOLCHAIN_TAR" ]; then + echo "no"; + return 1; fi - get_kernel_type; # sets TOOLCHAIN_PATH - check_download_toolchain; - PATH="$SCRIPT_PATH/$TOOLCHAIN_PATH/python/bin:$PATH"; - PATH="$SCRIPT_PATH/$TOOLCHAIN_PATH/bin:$PATH"; - PATH="$SCRIPT_PATH/$TOOLCHAIN_PATH/protobuf/bin:$PATH"; - PATH="$SCRIPT_PATH/$TOOLCHAIN_PATH/openocd/bin:$PATH"; + echo "yes"; + return 0; } -main; + +fbtenv_download_toolchain_tar() +{ + echo "Downloading toolchain:"; + mkdir -p "$FBT_TOOLCHAIN_PATH/toolchain" || return 1; + "$DOWNLOADER" $DOWNLOADER_ARGS "$FBT_TOOLCHAIN_PATH/toolchain/$TOOLCHAIN_TAR" "$TOOLCHAIN_URL" || return 1; + echo "done"; + return 0; +} + +fbtenv_remove_old_tooclhain() +{ + printf "Removing old toolchain (if exist).."; + rm -rf "${TOOLCHAIN_ARCH_DIR}"; + echo "done"; +} + +fbtenv_show_unpack_percentage() +{ + LINE=0; + while read -r line; do + LINE=$(( LINE + 1 )); + if [ $(( LINE % 300 )) -eq 0 ]; then + printf "#"; + fi + done + echo " 100.0%"; +} + +fbtenv_unpack_toolchain() +{ + echo "Unpacking toolchain:"; + tar -xvf "$FBT_TOOLCHAIN_PATH/toolchain/$TOOLCHAIN_TAR" -C "$FBT_TOOLCHAIN_PATH/toolchain" 2>&1 | fbtenv_show_unpack_percentage; + mkdir -p "$FBT_TOOLCHAIN_PATH/toolchain" || return 1; + mv "$FBT_TOOLCHAIN_PATH/toolchain/$TOOLCHAIN_DIR" "$TOOLCHAIN_ARCH_DIR" || return 1; + echo "done"; + return 0; +} + +fbtenv_clearing() +{ + printf "Clearing.."; + rm -rf "${FBT_TOOLCHAIN_PATH:?}/toolchain/$TOOLCHAIN_TAR"; + echo "done"; + return 0; +} + +fbtenv_curl_wget_check() +{ + printf "Checking curl.."; + if ! curl --version > /dev/null 2>&1; then + echo "no"; + printf "Checking wget.."; + if ! wget --version > /dev/null 2>&1; then + echo "no"; + echo "No curl or wget found in your PATH"; + echo "Please provide it or download this file:"; + echo; + echo "$TOOLCHAIN_URL"; + echo; + echo "And place in $FBT_TOOLCHAIN_PATH/toolchain/ dir mannualy"; + return 1; + fi + echo "yes" + DOWNLOADER="wget"; + DOWNLOADER_ARGS="--show-progress --progress=bar:force -qO"; + return 0; + fi + echo "yes" + DOWNLOADER="curl"; + DOWNLOADER_ARGS="--progress-bar -SLo"; + return 0; +} + +fbtenv_check_download_toolchain() +{ + if [ ! -d "$TOOLCHAIN_ARCH_DIR" ]; then + fbtenv_download_toolchain || return 1; + elif [ ! -f "$TOOLCHAIN_ARCH_DIR/VERSION" ]; then + fbtenv_download_toolchain || return 1; + elif [ "$(cat "$TOOLCHAIN_ARCH_DIR/VERSION")" -ne "$FBT_TOOLCHAIN_VERSION" ]; then + fbtenv_download_toolchain || return 1; + fi + return 0; +} + +fbtenv_download_toolchain() +{ + fbtenv_check_tar || return 1; + TOOLCHAIN_TAR="$(basename "$TOOLCHAIN_URL")"; + TOOLCHAIN_DIR="$(echo "$TOOLCHAIN_TAR" | sed "s/-$FBT_TOOLCHAIN_VERSION.tar.gz//g")"; + if ! fbtenv_check_downloaded_toolchain; then + fbtenv_curl_wget_check || return 1; + fbtenv_download_toolchain_tar; + fi + fbtenv_remove_old_tooclhain; + fbtenv_unpack_toolchain || { fbtenv_clearing && return 1; }; + fbtenv_clearing; + return 0; +} + +fbtenv_main() +{ + fbtenv_check_sourced || return 1; + fbtenv_check_script_path || return 1; + fbtenv_get_kernel_type || return 1; + fbtenv_check_download_toolchain || return 1; + PATH="$TOOLCHAIN_ARCH_DIR/python/bin:$PATH"; + PATH="$TOOLCHAIN_ARCH_DIR/bin:$PATH"; + PATH="$TOOLCHAIN_ARCH_DIR/protobuf/bin:$PATH"; + PATH="$TOOLCHAIN_ARCH_DIR/openocd/bin:$PATH"; +} + +fbtenv_main; diff --git a/scripts/toolchain/unix-toolchain-download.sh b/scripts/toolchain/unix-toolchain-download.sh deleted file mode 100755 index 386be2a3c..000000000 --- a/scripts/toolchain/unix-toolchain-download.sh +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/sh -# shellcheck disable=SC2086,SC2034 - -# unofficial strict mode -set -eu; - -check_system() -{ - VER="$1"; # toolchain version - printf "Checking kernel type.."; - SYS_TYPE="$(uname -s)" - if [ "$SYS_TYPE" = "Darwin" ]; then - echo "darwin"; - TOOLCHAIN_URL="https://update.flipperzero.one/builds/toolchain/gcc-arm-none-eabi-10.3-x86_64-darwin-flipper-$VER.tar.gz"; - TOOLCHAIN_PATH="toolchain/x86_64-darwin"; - elif [ "$SYS_TYPE" = "Linux" ]; then - echo "linux"; - TOOLCHAIN_URL="https://update.flipperzero.one/builds/toolchain/gcc-arm-none-eabi-10.3-x86_64-linux-flipper-$VER.tar.gz"; - TOOLCHAIN_PATH="toolchain/x86_64-linux"; - else - echo "unsupported."; - echo "Your system is unsupported.. sorry.."; - exit 1; - fi -} - -check_tar() -{ - printf "Checking tar.."; - if ! tar --version > /dev/null 2>&1; then - echo "no"; - exit 1; - fi - echo "yes"; -} - - -curl_wget_check() -{ - printf "Checking curl.."; - if ! curl --version > /dev/null 2>&1; then - echo "no"; - printf "Checking wget.."; - if ! wget --version > /dev/null 2>&1; then - echo "no"; - echo "No curl or wget found in your PATH."; - echo "Please provide it or download this file:"; - echo; - echo "$TOOLCHAIN_URL"; - echo; - echo "And place in repo root dir mannualy."; - exit 1; - fi - echo "yes" - DOWNLOADER="wget"; - DOWNLOADER_ARGS="--show-progress --progress=bar:force -qO"; - return; - fi - echo "yes" - DOWNLOADER="curl"; - DOWNLOADER_ARGS="--progress-bar -SLo"; -} - -check_downloaded_toolchain() -{ - printf "Checking downloaded toolchain tgz.."; - if [ -f "$REPO_ROOT/$TOOLCHAIN_TAR" ]; then - echo "yes"; - return 0; - fi - echo "no"; - return 1; -} - -download_toolchain() -{ - echo "Downloading toolchain:"; - "$DOWNLOADER" $DOWNLOADER_ARGS "$REPO_ROOT/$TOOLCHAIN_TAR" "$TOOLCHAIN_URL"; - echo "done"; -} - -remove_old_tooclhain() -{ - printf "Removing old toolchain (if exist).."; - rm -rf "${REPO_ROOT:?}/$TOOLCHAIN_PATH"; - echo "done"; -} - -show_unpack_percentage() -{ - LINE=0; - while read -r line; do - LINE=$(( LINE + 1 )); - if [ $(( LINE % 300 )) -eq 0 ]; then - printf "#"; - fi - done - echo " 100.0%"; -} - -unpack_toolchain() -{ - echo "Unpacking toolchain:"; - tar -xvf "$REPO_ROOT/$TOOLCHAIN_TAR" -C "$REPO_ROOT/" 2>&1 | show_unpack_percentage; - mkdir -p "$REPO_ROOT/toolchain"; - mv "$REPO_ROOT/$TOOLCHAIN_DIR" "$REPO_ROOT/$TOOLCHAIN_PATH/"; - echo "done"; -} - -clearing() -{ - printf "Clearing.."; - rm -rf "${REPO_ROOT:?}/$TOOLCHAIN_TAR"; - echo "done"; -} - -main() -{ - SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd -P)" - REPO_ROOT="$(cd "$SCRIPT_PATH/../../" && pwd)"; - check_system "$1"; # recives TOOLCHAIN_VERSION, defines TOOLCHAIN_URL and TOOLCHAIN_PATH - check_tar; - TOOLCHAIN_TAR="$(basename "$TOOLCHAIN_URL")"; - TOOLCHAIN_DIR="$(echo "$TOOLCHAIN_TAR" | sed "s/-$VER.tar.gz//g")"; - if ! check_downloaded_toolchain; then - curl_wget_check; - download_toolchain; - fi - remove_old_tooclhain; - unpack_toolchain; -} - -trap clearing EXIT; -trap clearing 2; # SIGINT not coverable by EXIT -main "$1"; # toochain version diff --git a/site_scons/site_tools/fbt_apps.py b/site_scons/site_tools/fbt_apps.py index aaf08bfad..2cd63b70b 100644 --- a/site_scons/site_tools/fbt_apps.py +++ b/site_scons/site_tools/fbt_apps.py @@ -21,9 +21,9 @@ def LoadApplicationManifests(env): for entry in env.Glob("#/applications/*", ondisk=True, source=True): if isinstance(entry, SCons.Node.FS.Dir) and not str(entry).startswith("."): try: - appmgr.load_manifest( - os.path.join(entry.abspath, "application.fam"), entry.name - ) + app_manifest_file_path = os.path.join(entry.abspath, "application.fam") + appmgr.load_manifest(app_manifest_file_path, entry.name) + env.Append(PY_LINT_SOURCES=[app_manifest_file_path]) except FlipperManifestException as e: warn(WarningOnByDefault, str(e)) @@ -67,6 +67,7 @@ def generate(env): build_apps_c, "${APPSCOMSTR}", ), + suffix=".c", ), } ) diff --git a/site_scons/site_tools/sconsmodular.py b/site_scons/site_tools/sconsmodular.py index db0cb8f35..778c664e4 100644 --- a/site_scons/site_tools/sconsmodular.py +++ b/site_scons/site_tools/sconsmodular.py @@ -1,5 +1,6 @@ import posixpath import os +from SCons.Errors import UserError def BuildModule(env, module): @@ -8,9 +9,9 @@ def BuildModule(env, module): if not os.path.exists(module_sconscript): module_sconscript = posixpath.join(src_dir, f"{module}.scons") if not os.path.exists(module_sconscript): - print(f"Cannot build module {module}: scons file not found") - Exit(2) + raise UserError(f"Cannot build module {module}: scons file not found") + env.Append(PY_LINT_SOURCES=[module_sconscript]) return env.SConscript( module_sconscript, variant_dir=posixpath.join(env.subst("$BUILD_DIR"), module), From 4a6477aaa87ed35388d27ffbedb8f3d19a032461 Mon Sep 17 00:00:00 2001 From: SG Date: Wed, 3 Aug 2022 22:01:38 +1000 Subject: [PATCH 11/22] Core, logs: removed tag concatenation (#1524) * Core, logs: removed tag concatenation * Logs: remove unused fn * Logs: remove allocation --- furi/core/log.c | 44 ++++++++++++++++++++++++++++++++++++++++---- furi/core/log.h | 30 ++++++++++++++---------------- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/furi/core/log.c b/furi/core/log.c index 8cf904855..8a36a930b 100644 --- a/furi/core/log.c +++ b/furi/core/log.c @@ -22,24 +22,60 @@ void furi_log_init() { furi_log.mutex = furi_mutex_alloc(FuriMutexTypeNormal); } -void furi_log_print(FuriLogLevel level, const char* format, ...) { +void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...) { if(level <= furi_log.log_level && furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk) { string_t string; + string_init(string); + + const char* color = FURI_LOG_CLR_RESET; + const char* log_letter = " "; + switch(level) { + case FuriLogLevelError: + color = FURI_LOG_CLR_E; + log_letter = "E"; + break; + case FuriLogLevelWarn: + color = FURI_LOG_CLR_W; + log_letter = "W"; + break; + case FuriLogLevelInfo: + color = FURI_LOG_CLR_I; + log_letter = "I"; + break; + case FuriLogLevelDebug: + color = FURI_LOG_CLR_D; + log_letter = "D"; + break; + case FuriLogLevelTrace: + color = FURI_LOG_CLR_T; + log_letter = "T"; + break; + default: + break; + } // Timestamp - string_init_printf(string, "%lu ", furi_log.timetamp()); + string_printf( + string, + "%lu %s[%s][%s] " FURI_LOG_CLR_RESET, + furi_log.timetamp(), + color, + log_letter, + tag); furi_log.puts(string_get_cstr(string)); - string_clear(string); + string_reset(string); va_list args; va_start(args, format); - string_init_vprintf(string, format, args); + string_vprintf(string, format, args); va_end(args); furi_log.puts(string_get_cstr(string)); string_clear(string); + furi_log.puts("\r\n"); + furi_mutex_release(furi_log.mutex); } } diff --git a/furi/core/log.h b/furi/core/log.h index 6d23a9c29..30026fc44 100644 --- a/furi/core/log.h +++ b/furi/core/log.h @@ -44,13 +44,14 @@ typedef uint32_t (*FuriLogTimestamp)(void); /** Initialize logging */ void furi_log_init(); -/** Log record - * - * @param[in] level The level - * @param[in] format The format - * @param[in] VA args +/** Print log record + * + * @param level + * @param tag + * @param format + * @param ... */ -void furi_log_print(FuriLogLevel level, const char* format, ...); +void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...); /** Set log level * @@ -76,11 +77,6 @@ void furi_log_set_puts(FuriLogPuts puts); */ void furi_log_set_timestamp(FuriLogTimestamp timestamp); -#define FURI_LOG_FORMAT(log_letter, tag, format) \ - FURI_LOG_CLR_##log_letter "[" #log_letter "][" tag "]: " FURI_LOG_CLR_RESET format "\r\n" -#define FURI_LOG_SHOW(tag, format, log_level, log_letter, ...) \ - furi_log_print(log_level, FURI_LOG_FORMAT(log_letter, tag, format), ##__VA_ARGS__) - /** Log methods * * @param tag The application tag @@ -88,13 +84,15 @@ void furi_log_set_timestamp(FuriLogTimestamp timestamp); * @param ... VA Args */ #define FURI_LOG_E(tag, format, ...) \ - FURI_LOG_SHOW(tag, format, FuriLogLevelError, E, ##__VA_ARGS__) -#define FURI_LOG_W(tag, format, ...) FURI_LOG_SHOW(tag, format, FuriLogLevelWarn, W, ##__VA_ARGS__) -#define FURI_LOG_I(tag, format, ...) FURI_LOG_SHOW(tag, format, FuriLogLevelInfo, I, ##__VA_ARGS__) + furi_log_print_format(FuriLogLevelError, tag, format, ##__VA_ARGS__) +#define FURI_LOG_W(tag, format, ...) \ + furi_log_print_format(FuriLogLevelWarn, tag, format, ##__VA_ARGS__) +#define FURI_LOG_I(tag, format, ...) \ + furi_log_print_format(FuriLogLevelInfo, tag, format, ##__VA_ARGS__) #define FURI_LOG_D(tag, format, ...) \ - FURI_LOG_SHOW(tag, format, FuriLogLevelDebug, D, ##__VA_ARGS__) + furi_log_print_format(FuriLogLevelDebug, tag, format, ##__VA_ARGS__) #define FURI_LOG_T(tag, format, ...) \ - FURI_LOG_SHOW(tag, format, FuriLogLevelTrace, T, ##__VA_ARGS__) + furi_log_print_format(FuriLogLevelTrace, tag, format, ##__VA_ARGS__) #ifdef __cplusplus } From eed4296890f7bb24c0b7f7627e9fcbcc695dd10a Mon Sep 17 00:00:00 2001 From: SG Date: Thu, 4 Aug 2022 01:47:10 +1000 Subject: [PATCH 12/22] MPU Hal (#1492) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Furi HAL: memory protection unit * Core: prohibit NULL dereferencing, even for reads. * Applications: fix NULL dereference * Core: stack protection by MPU * MPU: stack region alignment * Apps: fix null pointer dereferences * Threads: fix non-null arg check * Desktop settings: fix null pointer dereference * Core: documented null-check hack * Fix null dereference issues * Apps: args check * Core: naming fixes * format code * Core: remove NONNULL specifier * FurHal: move MPU initialization to begining, fix enum naming Co-authored-by: あく --- .../archive/scenes/archive_scene_rename.c | 2 +- applications/bad_usb/bad_usb_app.c | 3 +- applications/bad_usb/bad_usb_app_i.h | 1 - applications/bt/bt_service/bt.c | 3 +- .../animations/views/bubble_animation_view.c | 25 +++--- .../desktop_settings/desktop_settings_app.c | 2 +- applications/gui/modules/button_menu.c | 20 +++-- applications/gui/modules/text_input.c | 2 +- applications/gui/modules/validators.h | 2 +- applications/ibutton/ibutton.c | 2 +- applications/infrared/infrared.c | 2 +- applications/input/input.c | 3 +- applications/lfrfid/lfrfid_app.cpp | 2 +- applications/music_player/music_player.c | 2 +- applications/nfc/nfc.c | 2 +- applications/power/power_service/power.c | 2 +- .../power_settings_app/power_settings_app.c | 2 +- applications/rpc/rpc_system.c | 4 + .../subghz/scenes/subghz_scene_save_name.c | 4 +- applications/subghz/subghz.c | 2 +- applications/unit_tests/rpc/rpc_test.c | 13 +-- applications/updater/updater.c | 2 +- firmware/targets/f7/Inc/FreeRTOSConfig.h | 6 +- firmware/targets/f7/furi_hal/furi_hal.c | 13 +-- .../targets/f7/furi_hal/furi_hal_interrupt.c | 19 ++++ firmware/targets/f7/furi_hal/furi_hal_mpu.c | 66 ++++++++++++++ .../targets/furi_hal_include/furi_hal_mpu.h | 86 +++++++++++++++++++ furi/core/memmgr.c | 6 +- furi/core/thread.c | 2 +- 29 files changed, 238 insertions(+), 62 deletions(-) create mode 100644 firmware/targets/f7/furi_hal/furi_hal_mpu.c create mode 100644 firmware/targets/furi_hal_include/furi_hal_mpu.h diff --git a/applications/archive/scenes/archive_scene_rename.c b/applications/archive/scenes/archive_scene_rename.c index 2a85f3ceb..293fa89af 100644 --- a/applications/archive/scenes/archive_scene_rename.c +++ b/applications/archive/scenes/archive_scene_rename.c @@ -37,7 +37,7 @@ void archive_scene_rename_on_enter(void* context) { false); ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - string_get_cstr(archive->browser->path), archive->file_extension, NULL); + string_get_cstr(archive->browser->path), archive->file_extension, ""); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); string_clear(filename); diff --git a/applications/bad_usb/bad_usb_app.c b/applications/bad_usb/bad_usb_app.c index 7eb861818..09d7d3468 100644 --- a/applications/bad_usb/bad_usb_app.c +++ b/applications/bad_usb/bad_usb_app.c @@ -28,7 +28,7 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { string_init(app->file_path); - if(arg != NULL) { + if(arg && strlen(arg)) { string_set_str(app->file_path, arg); } @@ -79,7 +79,6 @@ void bad_usb_app_free(BadUsbApp* app) { furi_assert(app); // Views - view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewFileSelect); view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); bad_usb_free(app->bad_usb_view); diff --git a/applications/bad_usb/bad_usb_app_i.h b/applications/bad_usb/bad_usb_app_i.h index 6b323d355..6378bddfb 100644 --- a/applications/bad_usb/bad_usb_app_i.h +++ b/applications/bad_usb/bad_usb_app_i.h @@ -38,6 +38,5 @@ struct BadUsbApp { typedef enum { BadUsbAppViewError, - BadUsbAppViewFileSelect, BadUsbAppViewWork, } BadUsbAppView; diff --git a/applications/bt/bt_service/bt.c b/applications/bt/bt_service/bt.c index 6f0810dd9..bc80acc15 100644 --- a/applications/bt/bt_service/bt.c +++ b/applications/bt/bt_service/bt.c @@ -347,7 +347,8 @@ static void bt_close_connection(Bt* bt) { furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT); } -int32_t bt_srv() { +int32_t bt_srv(void* p) { + UNUSED(p); Bt* bt = bt_alloc(); if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) { diff --git a/applications/desktop/animations/views/bubble_animation_view.c b/applications/desktop/animations/views/bubble_animation_view.c index 54a686fb1..607862d11 100644 --- a/applications/desktop/animations/views/bubble_animation_view.c +++ b/applications/desktop/animations/views/bubble_animation_view.c @@ -143,7 +143,7 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) { furi_assert(view); bool activate = true; BubbleAnimationViewModel* model = view_get_model(view->view); - if(!model->current) { + if(model->current == NULL) { activate = false; } else if(model->freeze_frame) { activate = false; @@ -151,14 +151,16 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) { activate = false; } - if(!force) { - if((model->active_ended_at + model->current->active_cooldown * 1000) > - xTaskGetTickCount()) { - activate = false; - } else if(model->active_shift) { - activate = false; - } else if(model->current_frame >= model->current->passive_frames) { - activate = false; + if(model->current != NULL) { + if(!force) { + if((model->active_ended_at + model->current->active_cooldown * 1000) > + xTaskGetTickCount()) { + activate = false; + } else if(model->active_shift) { + activate = false; + } else if(model->current_frame >= model->current->passive_frames) { + activate = false; + } } } view_commit_model(view->view, false); @@ -288,7 +290,10 @@ static void bubble_animation_enter(void* context) { bubble_animation_activate(view, false); BubbleAnimationViewModel* model = view_get_model(view->view); - uint8_t frame_rate = model->current->icon_animation.frame_rate; + uint8_t frame_rate = 0; + if(model->current != NULL) { + frame_rate = model->current->icon_animation.frame_rate; + } view_commit_model(view->view, false); if(frame_rate) { diff --git a/applications/desktop/desktop_settings/desktop_settings_app.c b/applications/desktop/desktop_settings/desktop_settings_app.c index bc41be6e7..89513a8b8 100644 --- a/applications/desktop/desktop_settings/desktop_settings_app.c +++ b/applications/desktop/desktop_settings/desktop_settings_app.c @@ -90,7 +90,7 @@ void desktop_settings_app_free(DesktopSettingsApp* app) { extern int32_t desktop_settings_app(void* p) { DesktopSettingsApp* app = desktop_settings_app_alloc(); LOAD_DESKTOP_SETTINGS(&app->settings); - if(!strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG)) { + if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) { scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); } else { scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart); diff --git a/applications/gui/modules/button_menu.c b/applications/gui/modules/button_menu.c index 36fd6f3ab..84fea7888 100644 --- a/applications/gui/modules/button_menu.c +++ b/applications/gui/modules/button_menu.c @@ -185,17 +185,19 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) { return false; }); - if(item->type == ButtonMenuItemTypeControl) { - if(type == InputTypeShort) { - if(item && item->callback) { - item->callback(item->callback_context, item->index, type); + if(item) { + if(item->type == ButtonMenuItemTypeControl) { + if(type == InputTypeShort) { + if(item && item->callback) { + item->callback(item->callback_context, item->index, type); + } } } - } - if(item->type == ButtonMenuItemTypeCommon) { - if((type == InputTypePress) || (type == InputTypeRelease)) { - if(item && item->callback) { - item->callback(item->callback_context, item->index, type); + if(item->type == ButtonMenuItemTypeCommon) { + if((type == InputTypePress) || (type == InputTypeRelease)) { + if(item && item->callback) { + item->callback(item->callback_context, item->index, type); + } } } } diff --git a/applications/gui/modules/text_input.c b/applications/gui/modules/text_input.c index 5aa101bb4..c043c3c3c 100644 --- a/applications/gui/modules/text_input.c +++ b/applications/gui/modules/text_input.c @@ -147,7 +147,7 @@ static void text_input_backspace_cb(TextInputModel* model) { static void text_input_view_draw_callback(Canvas* canvas, void* _model) { TextInputModel* model = _model; - uint8_t text_length = strlen(model->text_buffer); + uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0; uint8_t needed_string_width = canvas_width(canvas) - 8; uint8_t start_pos = 4; diff --git a/applications/gui/modules/validators.h b/applications/gui/modules/validators.h index 15dbe901f..c4c4ef54c 100644 --- a/applications/gui/modules/validators.h +++ b/applications/gui/modules/validators.h @@ -1,7 +1,7 @@ #pragma once -// #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/applications/ibutton/ibutton.c b/applications/ibutton/ibutton.c index 5ccb1f6c8..6f690fce7 100644 --- a/applications/ibutton/ibutton.c +++ b/applications/ibutton/ibutton.c @@ -353,7 +353,7 @@ int32_t ibutton_app(void* p) { bool key_loaded = false; bool rpc_mode = false; - if(p) { + if(p && strlen(p)) { uint32_t rpc_ctx = 0; if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { FURI_LOG_D(TAG, "Running in RPC mode"); diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c index cbbd375d5..ddeaeecf3 100644 --- a/applications/infrared/infrared.c +++ b/applications/infrared/infrared.c @@ -405,7 +405,7 @@ int32_t infrared_app(void* p) { bool is_remote_loaded = false; bool is_rpc_mode = false; - if(p) { + if(p && strlen(p)) { uint32_t rpc_ctx = 0; if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { infrared->rpc_ctx = (void*)rpc_ctx; diff --git a/applications/input/input.c b/applications/input/input.c index 27e7bf21c..7b8433aef 100644 --- a/applications/input/input.c +++ b/applications/input/input.c @@ -64,7 +64,8 @@ const char* input_get_type_name(InputType type) { return "Unknown"; } -int32_t input_srv() { +int32_t input_srv(void* p) { + UNUSED(p); input = malloc(sizeof(Input)); input->thread_id = furi_thread_get_current_id(); input->event_pubsub = furi_pubsub_alloc(); diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp index 29e99b74f..5b762ae1d 100644 --- a/applications/lfrfid/lfrfid_app.cpp +++ b/applications/lfrfid/lfrfid_app.cpp @@ -74,7 +74,7 @@ void LfRfidApp::run(void* _args) { make_app_folder(); - if(strlen(args)) { + if(args && strlen(args)) { uint32_t rpc_ctx_ptr = 0; if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) { rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr; diff --git a/applications/music_player/music_player.c b/applications/music_player/music_player.c index ffdd2bea4..121efa0f9 100644 --- a/applications/music_player/music_player.c +++ b/applications/music_player/music_player.c @@ -300,7 +300,7 @@ int32_t music_player_app(void* p) { string_init(file_path); do { - if(p) { + if(p && strlen(p)) { string_cat_str(file_path, p); } else { string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index 32e74e8f2..93645cc13 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -238,7 +238,7 @@ int32_t nfc_app(void* p) { char* args = p; // Check argument and run corresponding scene - if((*args != '\0')) { + if(args && strlen(args)) { nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc); uint32_t rpc_ctx = 0; if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { diff --git a/applications/power/power_service/power.c b/applications/power/power_service/power.c index ac68bfd7d..9036ae1ce 100644 --- a/applications/power/power_service/power.c +++ b/applications/power/power_service/power.c @@ -200,7 +200,7 @@ static void power_check_battery_level_change(Power* power) { } int32_t power_srv(void* p) { - (void)p; + UNUSED(p); Power* power = power_alloc(); power_update_info(power); furi_record_create(RECORD_POWER, power); diff --git a/applications/power/power_settings_app/power_settings_app.c b/applications/power/power_settings_app/power_settings_app.c index 92c63704c..b01f32f75 100644 --- a/applications/power/power_settings_app/power_settings_app.c +++ b/applications/power/power_settings_app/power_settings_app.c @@ -76,7 +76,7 @@ void power_settings_app_free(PowerSettingsApp* app) { int32_t power_settings_app(void* p) { uint32_t first_scene = PowerSettingsAppSceneStart; - if(p && !strcmp(p, "off")) { + if(p && strlen(p) && !strcmp(p, "off")) { first_scene = PowerSettingsAppScenePowerOff; } PowerSettingsApp* app = power_settings_app_alloc(first_scene); diff --git a/applications/rpc/rpc_system.c b/applications/rpc/rpc_system.c index 38a288285..0538aa64d 100644 --- a/applications/rpc/rpc_system.c +++ b/applications/rpc/rpc_system.c @@ -78,6 +78,8 @@ static void rpc_system_system_device_info_callback( furi_assert(value); RpcSystemContext* ctx = context; + furi_assert(key); + furi_assert(value); char* str_key = strdup(key); char* str_value = strdup(value); @@ -232,6 +234,8 @@ static void rpc_system_system_power_info_callback( furi_assert(value); RpcSystemContext* ctx = context; + furi_assert(key); + furi_assert(value); char* str_key = strdup(key); char* str_value = strdup(value); diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c index 272cb6811..12ec98681 100644 --- a/applications/subghz/scenes/subghz_scene_save_name.c +++ b/applications/subghz/scenes/subghz_scene_save_name.c @@ -59,8 +59,8 @@ void subghz_scene_save_name_on_enter(void* context) { MAX_TEXT_INPUT_LEN, // buffer size dev_name_empty); - ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, NULL); + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, ""); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); string_clear(file_name); diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 4631d7a30..6edcd96d2 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -320,7 +320,7 @@ int32_t subghz_app(void* p) { subghz_environment_load_keystore( subghz->txrx->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); // Check argument and run corresponding scene - if(p) { + if(p && strlen(p)) { uint32_t rpc_ctx = 0; if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { subghz->rpc_ctx = (void*)rpc_ctx; diff --git a/applications/unit_tests/rpc/rpc_test.c b/applications/unit_tests/rpc/rpc_test.c index 1b9c5b0b3..69a0c434a 100644 --- a/applications/unit_tests/rpc/rpc_test.c +++ b/applications/unit_tests/rpc/rpc_test.c @@ -420,10 +420,12 @@ static void mu_check(result_msg_file->size == expected_msg_file->size); mu_check(result_msg_file->type == expected_msg_file->type); - mu_check(!result_msg_file->data == !expected_msg_file->data); - mu_check(result_msg_file->data->size == expected_msg_file->data->size); - for(int i = 0; i < result_msg_file->data->size; ++i) { - mu_check(result_msg_file->data->bytes[i] == expected_msg_file->data->bytes[i]); + if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) { + mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF??? + mu_check(result_msg_file->data->size == expected_msg_file->data->size); + for(int i = 0; i < result_msg_file->data->size; ++i) { + mu_check(result_msg_file->data->bytes[i] == expected_msg_file->data->bytes[i]); + } } } @@ -1346,8 +1348,7 @@ static void test_rpc_storage_rename_run( } MU_TEST(test_storage_rename) { - test_rpc_storage_rename_run( - NULL, NULL, ++command_id, PB_CommandStatus_ERROR_STORAGE_INVALID_NAME); + test_rpc_storage_rename_run("", "", ++command_id, PB_CommandStatus_ERROR_STORAGE_INVALID_NAME); furi_check(!test_is_exists(TEST_DIR "empty.txt")); test_create_file(TEST_DIR "empty.txt", 0); diff --git a/applications/updater/updater.c b/applications/updater/updater.c index daba9eafd..e9bedc72e 100644 --- a/applications/updater/updater.c +++ b/applications/updater/updater.c @@ -34,7 +34,7 @@ static void Updater* updater_alloc(const char* arg) { Updater* updater = malloc(sizeof(Updater)); - if(arg) { + if(arg && strlen(arg)) { string_init_set_str(updater->startup_arg, arg); string_replace_str(updater->startup_arg, ANY_PATH(""), EXT_PATH("")); } else { diff --git a/firmware/targets/f7/Inc/FreeRTOSConfig.h b/firmware/targets/f7/Inc/FreeRTOSConfig.h index 4f9d1fcf9..f54d774ca 100644 --- a/firmware/targets/f7/Inc/FreeRTOSConfig.h +++ b/firmware/targets/f7/Inc/FreeRTOSConfig.h @@ -32,7 +32,7 @@ extern uint32_t SystemCoreClock; #define configUSE_16_BIT_TICKS 0 #define configUSE_MUTEXES 1 #define configQUEUE_REGISTRY_SIZE 0 -#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_FOR_STACK_OVERFLOW 0 #define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_COUNTING_SEMAPHORES 1 #define configENABLE_BACKWARD_COMPATIBILITY 0 @@ -145,3 +145,7 @@ standard names. */ #define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1 #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION \ 1 /* required only for Keil but does not hurt otherwise */ + +#define traceTASK_SWITCHED_IN() \ + extern void furi_hal_mpu_set_stack_protection(uint32_t* stack); \ + furi_hal_mpu_set_stack_protection((uint32_t*)pxCurrentTCB->pxStack) diff --git a/firmware/targets/f7/furi_hal/furi_hal.c b/firmware/targets/f7/furi_hal/furi_hal.c index 0cef33ddf..23f409736 100644 --- a/firmware/targets/f7/furi_hal/furi_hal.c +++ b/firmware/targets/f7/furi_hal/furi_hal.c @@ -1,4 +1,5 @@ #include +#include #include @@ -35,6 +36,7 @@ void furi_hal_deinit_early() { } void furi_hal_init() { + furi_hal_mpu_init(); furi_hal_clock_init(); furi_hal_console_init(); furi_hal_rtc_init(); @@ -80,17 +82,6 @@ void furi_hal_init() { // FatFS driver initialization MX_FATFS_Init(); FURI_LOG_I(TAG, "FATFS OK"); - - // Partial null pointer dereference protection - LL_MPU_Disable(); - LL_MPU_ConfigRegion( - LL_MPU_REGION_NUMBER0, - 0x00, - 0x0, - LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | LL_MPU_ACCESS_BUFFERABLE | - LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_SHAREABLE | LL_MPU_TEX_LEVEL1 | - LL_MPU_INSTRUCTION_ACCESS_ENABLE); - LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); } void furi_hal_switch(void* address) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_interrupt.c b/firmware/targets/f7/furi_hal/furi_hal_interrupt.c index fa595921a..038ae9489 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_interrupt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_interrupt.c @@ -6,6 +6,7 @@ #include #include #include +#include #define TAG "FuriHalInterrupt" @@ -95,6 +96,10 @@ void furi_hal_interrupt_init() { LL_SYSCFG_DisableIT_FPU_IDC(); LL_SYSCFG_DisableIT_FPU_IXC(); + LL_HANDLER_EnableFault(LL_HANDLER_FAULT_USG); + LL_HANDLER_EnableFault(LL_HANDLER_FAULT_BUS); + LL_HANDLER_EnableFault(LL_HANDLER_FAULT_MEM); + FURI_LOG_I(TAG, "Init OK"); } @@ -241,6 +246,20 @@ void HardFault_Handler() { } void MemManage_Handler() { + if(FURI_BIT(SCB->CFSR, SCB_CFSR_MMARVALID_Pos)) { + uint32_t memfault_address = SCB->MMFAR; + if(memfault_address < (1024 * 1024)) { + // from 0x00 to 1MB, see FuriHalMpuRegionNULL + furi_crash("NULL pointer dereference"); + } else { + // write or read of MPU region 1 (FuriHalMpuRegionStack) + furi_crash("MPU fault, possibly stack overflow"); + } + } else if(FURI_BIT(SCB->CFSR, SCB_CFSR_MSTKERR_Pos)) { + // push to stack on MPU region 1 (FuriHalMpuRegionStack) + furi_crash("MemManage fault, possibly stack overflow"); + } + furi_crash("MemManage"); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_mpu.c b/firmware/targets/f7/furi_hal/furi_hal_mpu.c new file mode 100644 index 000000000..ea6cd55be --- /dev/null +++ b/firmware/targets/f7/furi_hal/furi_hal_mpu.c @@ -0,0 +1,66 @@ +#include +#include + +#define FURI_HAL_MPU_ATTRIBUTES \ + (LL_MPU_ACCESS_BUFFERABLE | LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_SHAREABLE | \ + LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_ENABLE) + +#define FURI_HAL_MPU_STACK_PROTECT_REGION FuriHalMPURegionSize32B + +void furi_hal_mpu_init() { + furi_hal_mpu_enable(); + + // NULL pointer dereference protection + furi_hal_mpu_protect_no_access(FuriHalMpuRegionNULL, 0x00, FuriHalMPURegionSize1MB); +} + +void furi_hal_mpu_enable() { + LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); +} + +void furi_hal_mpu_disable() { + LL_MPU_Disable(); +} + +void furi_hal_mpu_protect_no_access( + FuriHalMpuRegion region, + uint32_t address, + FuriHalMPURegionSize size) { + uint32_t size_ll = size; + size_ll = size_ll << MPU_RASR_SIZE_Pos; + + furi_hal_mpu_disable(); + LL_MPU_ConfigRegion( + region, 0x00, address, FURI_HAL_MPU_ATTRIBUTES | LL_MPU_REGION_NO_ACCESS | size_ll); + furi_hal_mpu_enable(); +} + +void furi_hal_mpu_protect_read_only( + FuriHalMpuRegion region, + uint32_t address, + FuriHalMPURegionSize size) { + uint32_t size_ll = size; + size_ll = size_ll << MPU_RASR_SIZE_Pos; + + furi_hal_mpu_disable(); + LL_MPU_ConfigRegion( + region, 0x00, address, FURI_HAL_MPU_ATTRIBUTES | LL_MPU_REGION_PRIV_RO_URO | size_ll); + furi_hal_mpu_enable(); +} + +void furi_hal_mpu_protect_disable(FuriHalMpuRegion region) { + furi_hal_mpu_disable(); + LL_MPU_DisableRegion(region); + furi_hal_mpu_enable(); +} + +void furi_hal_mpu_set_stack_protection(uint32_t* stack) { + // Protection area address must be aligned to region size + uint32_t stack_ptr = (uint32_t)stack; + uint32_t mask = ((1 << (FURI_HAL_MPU_STACK_PROTECT_REGION + 2)) - 1); + stack_ptr &= ~mask; + if(stack_ptr < (uint32_t)stack) stack_ptr += (mask + 1); + + furi_hal_mpu_protect_read_only( + FuriHalMpuRegionStack, stack_ptr, FURI_HAL_MPU_STACK_PROTECT_REGION); +} \ No newline at end of file diff --git a/firmware/targets/furi_hal_include/furi_hal_mpu.h b/firmware/targets/furi_hal_include/furi_hal_mpu.h new file mode 100644 index 000000000..5dddadeb6 --- /dev/null +++ b/firmware/targets/furi_hal_include/furi_hal_mpu.h @@ -0,0 +1,86 @@ +/** + * @file furi_hal_light.h + * Light control HAL API + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + FuriHalMpuRegionNULL = 0x00, // region 0 used to protect null pointer dereference + FuriHalMpuRegionStack = 0x01, // region 1 used to protect stack + FuriHalMpuRegion2 = 0x02, + FuriHalMpuRegion3 = 0x03, + FuriHalMpuRegion4 = 0x04, + FuriHalMpuRegion5 = 0x05, + FuriHalMpuRegion6 = 0x06, + FuriHalMpuRegion7 = 0x07, +} FuriHalMpuRegion; + +typedef enum { + FuriHalMPURegionSize32B = 0x04U, + FuriHalMPURegionSize64B = 0x05U, + FuriHalMPURegionSize128B = 0x06U, + FuriHalMPURegionSize256B = 0x07U, + FuriHalMPURegionSize512B = 0x08U, + FuriHalMPURegionSize1KB = 0x09U, + FuriHalMPURegionSize2KB = 0x0AU, + FuriHalMPURegionSize4KB = 0x0BU, + FuriHalMPURegionSize8KB = 0x0CU, + FuriHalMPURegionSize16KB = 0x0DU, + FuriHalMPURegionSize32KB = 0x0EU, + FuriHalMPURegionSize64KB = 0x0FU, + FuriHalMPURegionSize128KB = 0x10U, + FuriHalMPURegionSize256KB = 0x11U, + FuriHalMPURegionSize512KB = 0x12U, + FuriHalMPURegionSize1MB = 0x13U, + FuriHalMPURegionSize2MB = 0x14U, + FuriHalMPURegionSize4MB = 0x15U, + FuriHalMPURegionSize8MB = 0x16U, + FuriHalMPURegionSize16MB = 0x17U, + FuriHalMPURegionSize32MB = 0x18U, + FuriHalMPURegionSize64MB = 0x19U, + FuriHalMPURegionSize128MB = 0x1AU, + FuriHalMPURegionSize256MB = 0x1BU, + FuriHalMPURegionSize512MB = 0x1CU, + FuriHalMPURegionSize1GB = 0x1DU, + FuriHalMPURegionSize2GB = 0x1EU, + FuriHalMPURegionSize4GB = 0x1FU, +} FuriHalMPURegionSize; + +/** + * @brief Initialize memory protection unit + */ +void furi_hal_mpu_init(); + +/** +* @brief Enable memory protection unit +*/ +void furi_hal_mpu_enable(); + +/** +* @brief Disable memory protection unit +*/ +void furi_hal_mpu_disable(); + +void furi_hal_mpu_protect_no_access( + FuriHalMpuRegion region, + uint32_t address, + FuriHalMPURegionSize size); + +void furi_hal_mpu_protect_read_only( + FuriHalMpuRegion region, + uint32_t address, + FuriHalMPURegionSize size); + +void furi_hal_mpu_protect_disable(FuriHalMpuRegion region); + +#ifdef __cplusplus +} +#endif diff --git a/furi/core/memmgr.c b/furi/core/memmgr.c index 01cf573eb..80f87b930 100644 --- a/furi/core/memmgr.c +++ b/furi/core/memmgr.c @@ -36,10 +36,8 @@ void* calloc(size_t count, size_t size) { } char* strdup(const char* s) { - const char* s_null = s; - if(s_null == NULL) { - return NULL; - } + // arg s marked as non-null, so we need hack to check for NULL + furi_check(((uint32_t)s << 2) != 0); size_t siz = strlen(s) + 1; char* y = pvPortMalloc(siz); diff --git a/furi/core/thread.c b/furi/core/thread.c index 097cedef2..3b6708f66 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -88,7 +88,7 @@ void furi_thread_set_name(FuriThread* thread, const char* name) { furi_assert(thread); furi_assert(thread->state == FuriThreadStateStopped); if(thread->name) free((void*)thread->name); - thread->name = strdup(name); + thread->name = name ? strdup(name) : NULL; } void furi_thread_set_stack_size(FuriThread* thread, size_t stack_size) { From bc34689ed6e6a8c2c757be2da01984814468537a Mon Sep 17 00:00:00 2001 From: SG Date: Thu, 4 Aug 2022 02:00:17 +1000 Subject: [PATCH 13/22] Make printf great again (#1438) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Printf lib: wrap *printf* functions * Printf lib, FW: drop sprintf. Dolphin: dump timestamp as is, wo asctime. * FW: remove sniprintf, wrap assert functions * Printf lib: wrap putc, puts, putchar * Printf: a working but not thread-safe concept. * Poorly wrap fflush * stdglue: buffers * Core: thread local buffers * Core: move stdglue to thread api, add ability to get FuriThread instance of current thread. * RPC tests: replace sprintf with snprintf * Applications: use new stdout api * Printf lib: wrap more printf-like and stdout functions * Documentation * Apps: snprintf size fixes Co-authored-by: あく --- applications/cli/cli.c | 10 +- applications/cli/cli_i.h | 2 +- applications/cli/cli_vcp.c | 3 +- applications/debug_tools/keypad_test.c | 10 +- .../desktop/views/desktop_view_debug.c | 9 +- applications/infrared/infrared_cli.c | 8 +- applications/rpc/rpc_storage.c | 2 +- .../scenes/subghz_scene_receiver_config.c | 9 +- applications/unit_tests/rpc/rpc_test.c | 15 +- firmware.scons | 3 +- furi/core/stdglue.c | 102 -- furi/core/stdglue.h | 36 - furi/core/thread.c | 88 ++ furi/core/thread.h | 35 + furi/furi.c | 1 - furi/furi.h | 1 - lib/SConscript | 2 + lib/print/SConscript | 107 ++ lib/print/printf_tiny.c | 1037 +++++++++++++++++ lib/print/printf_tiny.h | 103 ++ lib/print/wrappers.c | 74 ++ lib/toolbox/random_name.c | 2 +- 22 files changed, 1484 insertions(+), 175 deletions(-) delete mode 100644 furi/core/stdglue.c delete mode 100644 furi/core/stdglue.h create mode 100644 lib/print/SConscript create mode 100644 lib/print/printf_tiny.c create mode 100644 lib/print/printf_tiny.h create mode 100644 lib/print/wrappers.c diff --git a/applications/cli/cli.c b/applications/cli/cli.c index 4d9b8a5f0..e554ac898 100644 --- a/applications/cli/cli.c +++ b/applications/cli/cli.c @@ -439,9 +439,9 @@ void cli_session_open(Cli* cli, void* session) { cli->session = session; if(cli->session != NULL) { cli->session->init(); - furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout); + furi_thread_set_stdout_callback(cli->session->tx_stdout); } else { - furi_stdglue_set_thread_stdout_callback(NULL); + furi_thread_set_stdout_callback(NULL); } furi_semaphore_release(cli->idle_sem); furi_check(furi_mutex_release(cli->mutex) == FuriStatusOk); @@ -455,7 +455,7 @@ void cli_session_close(Cli* cli) { cli->session->deinit(); } cli->session = NULL; - furi_stdglue_set_thread_stdout_callback(NULL); + furi_thread_set_stdout_callback(NULL); furi_check(furi_mutex_release(cli->mutex) == FuriStatusOk); } @@ -469,9 +469,9 @@ int32_t cli_srv(void* p) { furi_record_create(RECORD_CLI, cli); if(cli->session != NULL) { - furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout); + furi_thread_set_stdout_callback(cli->session->tx_stdout); } else { - furi_stdglue_set_thread_stdout_callback(NULL); + furi_thread_set_stdout_callback(NULL); } if(furi_hal_rtc_get_boot_mode() == FuriHalRtcBootModeNormal) { diff --git a/applications/cli/cli_i.h b/applications/cli/cli_i.h index 076dd75ed..8f0bd85d5 100755 --- a/applications/cli/cli_i.h +++ b/applications/cli/cli_i.h @@ -25,7 +25,7 @@ struct CliSession { void (*deinit)(void); size_t (*rx)(uint8_t* buffer, size_t size, uint32_t timeout); void (*tx)(const uint8_t* buffer, size_t size); - void (*tx_stdout)(void* _cookie, const char* data, size_t size); + void (*tx_stdout)(const char* data, size_t size); bool (*is_connected)(void); }; diff --git a/applications/cli/cli_vcp.c b/applications/cli/cli_vcp.c index 5d66b8f8d..5a8b44dcf 100644 --- a/applications/cli/cli_vcp.c +++ b/applications/cli/cli_vcp.c @@ -277,8 +277,7 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) { #endif } -static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) { - UNUSED(_cookie); +static void cli_vcp_tx_stdout(const char* data, size_t size) { cli_vcp_tx((const uint8_t*)data, size); } diff --git a/applications/debug_tools/keypad_test.c b/applications/debug_tools/keypad_test.c index 6708c82ba..2470baf8d 100644 --- a/applications/debug_tools/keypad_test.c +++ b/applications/debug_tools/keypad_test.c @@ -26,11 +26,11 @@ static void keypad_test_render_callback(Canvas* canvas, void* ctx) { canvas_clear(canvas); char strings[5][20]; - sprintf(strings[0], "Ok: %d", state->ok); - sprintf(strings[1], "L: %d", state->left); - sprintf(strings[2], "R: %d", state->right); - sprintf(strings[3], "U: %d", state->up); - sprintf(strings[4], "D: %d", state->down); + snprintf(strings[0], 20, "Ok: %d", state->ok); + snprintf(strings[1], 20, "L: %d", state->left); + snprintf(strings[2], 20, "R: %d", state->right); + snprintf(strings[3], 20, "U: %d", state->up); + snprintf(strings[4], 20, "D: %d", state->down); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 0, 10, "Keypad test"); diff --git a/applications/desktop/views/desktop_view_debug.c b/applications/desktop/views/desktop_view_debug.c index 68c054c2a..b69a6a2db 100644 --- a/applications/desktop/views/desktop_view_debug.c +++ b/applications/desktop/views/desktop_view_debug.c @@ -78,7 +78,6 @@ void desktop_debug_render(Canvas* canvas, void* model) { canvas_draw_str(canvas, 5, 50 + STATUS_BAR_Y_SHIFT, buffer); } else { - char buffer[64]; Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); DolphinStats stats = dolphin_stats(dolphin); furi_record_close(RECORD_DOLPHIN); @@ -87,18 +86,20 @@ void desktop_debug_render(Canvas* canvas, void* model) { uint32_t remaining = dolphin_state_xp_to_levelup(m->icounter); canvas_set_font(canvas, FontSecondary); - snprintf(buffer, 64, "Icounter: %ld Butthurt %ld", m->icounter, m->butthurt); + snprintf(buffer, sizeof(buffer), "Icounter: %ld Butthurt %ld", m->icounter, m->butthurt); canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer); snprintf( buffer, - 64, + sizeof(buffer), "Level: %ld To level up: %ld", current_lvl, (remaining == (uint32_t)(-1) ? remaining : 0)); canvas_draw_str(canvas, 5, 29 + STATUS_BAR_Y_SHIFT, buffer); - snprintf(buffer, 64, "%s", asctime(localtime((const time_t*)&m->timestamp))); + // even if timestamp is uint64_t, it's safe to cast it to uint32_t, because furi_hal_rtc_datetime_to_timestamp only returns uint32_t + snprintf(buffer, sizeof(buffer), "%ld", (uint32_t)m->timestamp); + canvas_draw_str(canvas, 5, 39 + STATUS_BAR_Y_SHIFT, buffer); canvas_draw_str(canvas, 0, 49 + STATUS_BAR_Y_SHIFT, "[< >] icounter value [ok] save"); } diff --git a/applications/infrared/infrared_cli.c b/applications/infrared/infrared_cli.c index c190aad3e..aae02e8fd 100644 --- a/applications/infrared/infrared_cli.c +++ b/applications/infrared/infrared_cli.c @@ -27,7 +27,7 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv if(infrared_worker_signal_is_decoded(received_signal)) { const InfraredMessage* message = infrared_worker_get_decoded_signal(received_signal); - buf_cnt = sniprintf( + buf_cnt = snprintf( buf, sizeof(buf), "%s, A:0x%0*lX, C:0x%0*lX%s\r\n", @@ -43,13 +43,13 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv size_t timings_cnt; infrared_worker_get_raw_signal(received_signal, &timings, &timings_cnt); - buf_cnt = sniprintf(buf, sizeof(buf), "RAW, %d samples:\r\n", timings_cnt); + buf_cnt = snprintf(buf, sizeof(buf), "RAW, %d samples:\r\n", timings_cnt); cli_write(cli, (uint8_t*)buf, buf_cnt); for(size_t i = 0; i < timings_cnt; ++i) { - buf_cnt = sniprintf(buf, sizeof(buf), "%lu ", timings[i]); + buf_cnt = snprintf(buf, sizeof(buf), "%lu ", timings[i]); cli_write(cli, (uint8_t*)buf, buf_cnt); } - buf_cnt = sniprintf(buf, sizeof(buf), "\r\n"); + buf_cnt = snprintf(buf, sizeof(buf), "\r\n"); cli_write(cli, (uint8_t*)buf, buf_cnt); } } diff --git a/applications/rpc/rpc_storage.c b/applications/rpc/rpc_storage.c index d2b43ff66..1e2920f5b 100644 --- a/applications/rpc/rpc_storage.c +++ b/applications/rpc/rpc_storage.c @@ -541,7 +541,7 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont (void)md5sum_size; furi_assert(hash_size <= ((md5sum_size - 1) / 2)); for(uint8_t i = 0; i < hash_size; i++) { - md5sum += sprintf(md5sum, "%02x", hash[i]); + md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]); } free(hash); diff --git a/applications/subghz/scenes/subghz_scene_receiver_config.c b/applications/subghz/scenes/subghz_scene_receiver_config.c index 590b51d15..bf2f0cdba 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/subghz/scenes/subghz_scene_receiver_config.c @@ -73,8 +73,9 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) { if(subghz->txrx->hopper_state == SubGhzHopperStateOFF) { char text_buf[10] = {0}; - sprintf( + snprintf( text_buf, + sizeof(text_buf), "%lu.%02lu", subghz_setting_get_frequency(subghz->setting, index) / 1000000, (subghz_setting_get_frequency(subghz->setting, index) % 1000000) / 10000); @@ -106,8 +107,9 @@ static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) variable_item_set_current_value_text(item, hopping_text[index]); if(hopping_value[index] == SubGhzHopperStateOFF) { char text_buf[10] = {0}; - sprintf( + snprintf( text_buf, + sizeof(text_buf), "%lu.%02lu", subghz_setting_get_default_frequency(subghz->setting) / 1000000, (subghz_setting_get_default_frequency(subghz->setting) % 1000000) / 10000); @@ -160,8 +162,9 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz->scene_manager, SubGhzSceneReceiverConfig, (uint32_t)item); variable_item_set_current_value_index(item, value_index); char text_buf[10] = {0}; - sprintf( + snprintf( text_buf, + sizeof(text_buf), "%lu.%02lu", subghz_setting_get_frequency(subghz->setting, value_index) / 1000000, (subghz_setting_get_frequency(subghz->setting, value_index) % 1000000) / 10000); diff --git a/applications/unit_tests/rpc/rpc_test.c b/applications/unit_tests/rpc/rpc_test.c index 69a0c434a..d31311af6 100644 --- a/applications/unit_tests/rpc/rpc_test.c +++ b/applications/unit_tests/rpc/rpc_test.c @@ -189,8 +189,9 @@ static void clean_directory(Storage* fs_api, const char* clean_dir) { FileInfo fileinfo; char* name = malloc(MAX_NAME_LENGTH + 1); while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) { - char* fullname = malloc(strlen(clean_dir) + strlen(name) + 1 + 1); - sprintf(fullname, "%s/%s", clean_dir, name); + size_t size = strlen(clean_dir) + strlen(name) + 1 + 1; + char* fullname = malloc(size); + snprintf(fullname, size, "%s/%s", clean_dir, name); if(fileinfo.flags & FSF_DIRECTORY) { clean_directory(fs_api, fullname); } @@ -1226,7 +1227,7 @@ MU_TEST(test_storage_mkdir) { mu_check(test_is_exists(TEST_DIR "dir2")); } -static void test_storage_calculate_md5sum(const char* path, char* md5sum) { +static void test_storage_calculate_md5sum(const char* path, char* md5sum, size_t md5sum_size) { Storage* api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(api); @@ -1247,7 +1248,7 @@ static void test_storage_calculate_md5sum(const char* path, char* md5sum) { free(md5_ctx); for(uint8_t i = 0; i < hash_size; i++) { - md5sum += sprintf(md5sum, "%02x", hash[i]); + md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]); } free(hash); @@ -1299,9 +1300,9 @@ MU_TEST(test_storage_md5sum) { test_create_file(TEST_DIR "file1.txt", 0); test_create_file(TEST_DIR "file2.txt", 1); test_create_file(TEST_DIR "file3.txt", 512); - test_storage_calculate_md5sum(TEST_DIR "file1.txt", md5sum1); - test_storage_calculate_md5sum(TEST_DIR "file2.txt", md5sum2); - test_storage_calculate_md5sum(TEST_DIR "file3.txt", md5sum3); + test_storage_calculate_md5sum(TEST_DIR "file1.txt", md5sum1, MD5SUM_SIZE * 2 + 1); + test_storage_calculate_md5sum(TEST_DIR "file2.txt", md5sum2, MD5SUM_SIZE * 2 + 1); + test_storage_calculate_md5sum(TEST_DIR "file3.txt", md5sum3, MD5SUM_SIZE * 2 + 1); test_storage_md5sum_run(TEST_DIR "file1.txt", ++command_id, md5sum1, PB_CommandStatus_OK); test_storage_md5sum_run(TEST_DIR "file1.txt", ++command_id, md5sum1, PB_CommandStatus_OK); diff --git a/firmware.scons b/firmware.scons index 76f0b52de..4eb76f520 100644 --- a/firmware.scons +++ b/firmware.scons @@ -164,8 +164,6 @@ fwenv.AppendUnique( "-Wl,--wrap,_free_r", "-Wl,--wrap,_calloc_r", "-Wl,--wrap,_realloc_r", - "-u", - "_printf_float", "-n", "-Xlinker", "-Map=${TARGET}.map", @@ -181,6 +179,7 @@ fwelf = fwenv["FW_ELF"] = fwenv.Program( "${FIRMWARE_BUILD_CFG}", sources, LIBS=[ + "print", "flipper${TARGET_HW}", "furi", "freertos", diff --git a/furi/core/stdglue.c b/furi/core/stdglue.c deleted file mode 100644 index 573277aa5..000000000 --- a/furi/core/stdglue.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "stdglue.h" -#include "check.h" -#include "memmgr.h" - -#include -#include - -#include -#include - -DICT_DEF2( - FuriStdglueCallbackDict, - uint32_t, - M_DEFAULT_OPLIST, - FuriStdglueWriteCallback, - M_PTR_OPLIST) - -typedef struct { - FuriMutex* mutex; - FuriStdglueCallbackDict_t thread_outputs; -} FuriStdglue; - -static FuriStdglue* furi_stdglue = NULL; - -static ssize_t stdout_write(void* _cookie, const char* data, size_t size) { - furi_assert(furi_stdglue); - bool consumed = false; - FuriThreadId task_id = furi_thread_get_current_id(); - if(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING && task_id && - furi_mutex_acquire(furi_stdglue->mutex, FuriWaitForever) == FuriStatusOk) { - // We are in the thread context - // Handle thread callbacks - FuriStdglueWriteCallback* callback_ptr = - FuriStdglueCallbackDict_get(furi_stdglue->thread_outputs, (uint32_t)task_id); - if(callback_ptr) { - (*callback_ptr)(_cookie, data, size); - consumed = true; - } - furi_check(furi_mutex_release(furi_stdglue->mutex) == FuriStatusOk); - } - // Flush - if(data == 0) { - /* - * This means that we should flush internal buffers. Since we - * don't we just return. (Remember, "handle" == -1 means that all - * handles should be flushed.) - */ - return 0; - } - // Debug uart - if(!consumed) furi_hal_console_tx((const uint8_t*)data, size); - // All data consumed - return size; -} - -void furi_stdglue_init() { - furi_stdglue = malloc(sizeof(FuriStdglue)); - // Init outputs structures - furi_stdglue->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - furi_check(furi_stdglue->mutex); - FuriStdglueCallbackDict_init(furi_stdglue->thread_outputs); - // Prepare and set stdout descriptor - FILE* fp = fopencookie( - NULL, - "w", - (cookie_io_functions_t){ - .read = NULL, - .write = stdout_write, - .seek = NULL, - .close = NULL, - }); - setvbuf(fp, NULL, _IOLBF, 0); - stdout = fp; -} - -bool furi_stdglue_set_thread_stdout_callback(FuriStdglueWriteCallback callback) { - furi_assert(furi_stdglue); - FuriThreadId task_id = furi_thread_get_current_id(); - if(task_id) { - furi_check(furi_mutex_acquire(furi_stdglue->mutex, FuriWaitForever) == FuriStatusOk); - if(callback) { - FuriStdglueCallbackDict_set_at( - furi_stdglue->thread_outputs, (uint32_t)task_id, callback); - } else { - FuriStdglueCallbackDict_erase(furi_stdglue->thread_outputs, (uint32_t)task_id); - } - furi_check(furi_mutex_release(furi_stdglue->mutex) == FuriStatusOk); - return true; - } else { - return false; - } -} - -void __malloc_lock(struct _reent* REENT) { - UNUSED(REENT); - vTaskSuspendAll(); -} - -void __malloc_unlock(struct _reent* REENT) { - UNUSED(REENT); - xTaskResumeAll(); -} diff --git a/furi/core/stdglue.h b/furi/core/stdglue.h deleted file mode 100644 index 800fcf928..000000000 --- a/furi/core/stdglue.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file stdglue.h - * Furi: stdlibc glue - */ - -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Write callback - * @param _cookie pointer to cookie (see stdio gnu extension) - * @param data pointer to data - * @param size data size @warnign your handler must consume everything - */ -typedef void (*FuriStdglueWriteCallback)(void* _cookie, const char* data, size_t size); - -/** Initialized std library glue code */ -void furi_stdglue_init(); - -/** Set STDOUT callback for your thread - * - * @param callback callback or NULL to clear - * - * @return true on success, otherwise fail - * @warning function is thread aware, use this API from the same thread - */ -bool furi_stdglue_set_thread_stdout_callback(FuriStdglueWriteCallback callback); - -#ifdef __cplusplus -} -#endif diff --git a/furi/core/thread.c b/furi/core/thread.c index 3b6708f66..044f83711 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -4,12 +4,21 @@ #include "memmgr_heap.h" #include "check.h" #include "common_defines.h" +#include "mutex.h" #include #include +#include #define THREAD_NOTIFY_INDEX 1 // Index 0 is used for stream buffers +typedef struct FuriThreadStdout FuriThreadStdout; + +struct FuriThreadStdout { + FuriThreadStdoutWriteCallback write_callback; + string_t buffer; +}; + struct FuriThread { FuriThreadState state; int32_t ret; @@ -27,8 +36,13 @@ struct FuriThread { TaskHandle_t task_handle; bool heap_trace_enabled; size_t heap_size; + + FuriThreadStdout output; }; +static size_t __furi_thread_stdout_write(FuriThread* thread, const char* data, size_t size); +static int32_t __furi_thread_stdout_flush(FuriThread* thread); + /** Catch threads that are trying to exit wrong way */ __attribute__((__noreturn__)) void furi_thread_catch() { asm volatile("nop"); // extra magic @@ -47,6 +61,10 @@ static void furi_thread_body(void* context) { furi_assert(context); FuriThread* thread = context; + // store thread instance to thread local storage + furi_assert(pvTaskGetThreadLocalStoragePointer(NULL, 0) == NULL); + vTaskSetThreadLocalStoragePointer(NULL, 0, thread); + furi_assert(thread->state == FuriThreadStateStarting); furi_thread_set_state(thread, FuriThreadStateRunning); @@ -66,12 +84,18 @@ static void furi_thread_body(void* context) { furi_assert(thread->state == FuriThreadStateRunning); furi_thread_set_state(thread, FuriThreadStateStopped); + // clear thread local storage + __furi_thread_stdout_flush(thread); + furi_assert(pvTaskGetThreadLocalStoragePointer(NULL, 0) != NULL); + vTaskSetThreadLocalStoragePointer(NULL, 0, NULL); + vTaskDelete(thread->task_handle); furi_thread_catch(); } FuriThread* furi_thread_alloc() { FuriThread* thread = malloc(sizeof(FuriThread)); + string_init(thread->output.buffer); return thread; } @@ -81,6 +105,8 @@ void furi_thread_free(FuriThread* thread) { furi_assert(thread->state == FuriThreadStateStopped); if(thread->name) free((void*)thread->name); + string_clear(thread->output.buffer); + free(thread); } @@ -199,6 +225,12 @@ FuriThreadId furi_thread_get_current_id() { return xTaskGetCurrentTaskHandle(); } +FuriThread* furi_thread_get_current() { + FuriThread* thread = pvTaskGetThreadLocalStoragePointer(NULL, 0); + furi_assert(thread != NULL); + return thread; +} + void furi_thread_yield() { furi_assert(!FURI_IS_IRQ_MODE()); taskYIELD(); @@ -408,3 +440,59 @@ uint32_t furi_thread_get_stack_space(FuriThreadId thread_id) { return (sz); } + +static size_t __furi_thread_stdout_write(FuriThread* thread, const char* data, size_t size) { + if(thread->output.write_callback != NULL) { + thread->output.write_callback(data, size); + } else { + furi_hal_console_tx((const uint8_t*)data, size); + } + return size; +} + +static int32_t __furi_thread_stdout_flush(FuriThread* thread) { + string_ptr buffer = thread->output.buffer; + size_t size = string_size(buffer); + if(size > 0) { + __furi_thread_stdout_write(thread, string_get_cstr(buffer), size); + string_reset(buffer); + } + return 0; +} + +bool furi_thread_set_stdout_callback(FuriThreadStdoutWriteCallback callback) { + FuriThread* thread = furi_thread_get_current(); + + __furi_thread_stdout_flush(thread); + thread->output.write_callback = callback; + + return true; +} + +size_t furi_thread_stdout_write(const char* data, size_t size) { + FuriThread* thread = furi_thread_get_current(); + + if(size == 0 || data == NULL) { + return __furi_thread_stdout_flush(thread); + } else { + if(data[size - 1] == '\n') { + // if the last character is a newline, we can flush buffer and write data as is, wo buffers + __furi_thread_stdout_flush(thread); + __furi_thread_stdout_write(thread, data, size); + } else { + // string_cat doesn't work here because we need to write the exact size data + for(size_t i = 0; i < size; i++) { + string_push_back(thread->output.buffer, data[i]); + if(data[i] == '\n') { + __furi_thread_stdout_flush(thread); + } + } + } + } + + return size; +} + +int32_t furi_thread_stdout_flush() { + return __furi_thread_stdout_flush(furi_thread_get_current()); +} \ No newline at end of file diff --git a/furi/core/thread.h b/furi/core/thread.h index 34eb39f03..7f746f03f 100644 --- a/furi/core/thread.h +++ b/furi/core/thread.h @@ -42,6 +42,12 @@ typedef void* FuriThreadId; */ typedef int32_t (*FuriThreadCallback)(void* context); +/** Write to stdout callback + * @param data pointer to data + * @param size data size @warning your handler must consume everything + */ +typedef void (*FuriThreadStdoutWriteCallback)(const char* data, size_t size); + /** FuriThread state change calback called upon thread state change * @param state new thread state * @param context callback context @@ -177,6 +183,12 @@ int32_t furi_thread_get_return_code(FuriThread* thread); */ FuriThreadId furi_thread_get_current_id(); +/** Get FuriThread instance for current thread + * + * @return FuriThread* + */ +FuriThread* furi_thread_get_current(); + /** Return control to scheduler */ void furi_thread_yield(); @@ -194,6 +206,29 @@ const char* furi_thread_get_name(FuriThreadId thread_id); uint32_t furi_thread_get_stack_space(FuriThreadId thread_id); +/** Set STDOUT callback for thread + * + * @param callback callback or NULL to clear + * + * @return true on success, otherwise fail + */ +bool furi_thread_set_stdout_callback(FuriThreadStdoutWriteCallback callback); + +/** Write data to buffered STDOUT + * + * @param data input data + * @param size input data size + * + * @return size_t written data size + */ +size_t furi_thread_stdout_write(const char* data, size_t size); + +/** Flush data to STDOUT + * + * @return int32_t error code + */ +int32_t furi_thread_stdout_flush(); + #ifdef __cplusplus } #endif diff --git a/furi/furi.c b/furi/furi.c index e6848624b..76aed024f 100644 --- a/furi/furi.c +++ b/furi/furi.c @@ -8,7 +8,6 @@ void furi_init() { furi_log_init(); furi_record_init(); - furi_stdglue_init(); } void furi_run() { diff --git a/furi/furi.h b/furi/furi.h index d78129a82..68914b502 100644 --- a/furi/furi.h +++ b/furi/furi.h @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/SConscript b/lib/SConscript index c5bc3947f..459a80d62 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -14,6 +14,7 @@ env.Append( "lib/toolbox", "lib/u8g2", "lib/update_util", + "lib/print", ] ) @@ -60,6 +61,7 @@ libs = env.BuildModules( [ "STM32CubeWB", "freertos", + "print", "microtar", "toolbox", "ST25RFAL002", diff --git a/lib/print/SConscript b/lib/print/SConscript new file mode 100644 index 000000000..412d17a66 --- /dev/null +++ b/lib/print/SConscript @@ -0,0 +1,107 @@ +Import("env") + +wrapped_fn_list = [ + # + # used by our firmware, so we provide their realizations + # + "fflush", + "printf", + "putc", # fallback from printf, thanks gcc + "putchar", # storage cli + "puts", # fallback from printf, thanks gcc + "snprintf", + "vsnprintf", # m-string + "__assert", # ??? + "__assert_func", # ??? + # + # wrap other functions to make sure they are not called + # realization is not provided + # + "setbuf", + "setvbuf", + "fprintf", + "vfprintf", + "vprintf", + "fputc", + "fputs", + "sprintf", # specially, because this function is dangerous + "asprintf", + "vasprintf", + "asiprintf", + "asniprintf", + "asnprintf", + "diprintf", + "fiprintf", + "iprintf", + "siprintf", + "sniprintf", + "vasiprintf", + "vasniprintf", + "vasnprintf", + "vdiprintf", + "vfiprintf", + "viprintf", + "vsiprintf", + "vsniprintf", + # + # Scanf is not implemented 4 now + # + # "fscanf", + # "scanf", + # "sscanf", + # "vsprintf", + # "fgetc", + # "fgets", + # "getc", + # "getchar", + # "gets", + # "ungetc", + # "vfscanf", + # "vscanf", + # "vsscanf", + # "fiscanf", + # "iscanf", + # "siscanf", + # "vfiscanf", + # "viscanf", + # "vsiscanf", + # + # File management + # + # "fclose", + # "freopen", + # "fread", + # "fwrite", + # "fgetpos", + # "fseek", + # "fsetpos", + # "ftell", + # "rewind", + # "feof", + # "ferror", + # "fopen", + # "remove", + # "rename", + # "fseeko", + # "ftello", +] + +for wrapped_fn in wrapped_fn_list: + env.Append( + LINKFLAGS=[ + "-Wl,--wrap," + wrapped_fn, + "-Wl,--wrap," + wrapped_fn + "_unlocked", + "-Wl,--wrap,_" + wrapped_fn + "_r", + "-Wl,--wrap,_" + wrapped_fn + "_unlocked_r", + ] + ) + +libenv = env.Clone(FW_LIB_NAME="print") +libenv.ApplyLibFlags() +libenv.Append(CCFLAGS=["-Wno-double-promotion"]) + +sources = libenv.GlobRecursive("*.c*", ".") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/print/printf_tiny.c b/lib/print/printf_tiny.c new file mode 100644 index 000000000..0db11922d --- /dev/null +++ b/lib/print/printf_tiny.c @@ -0,0 +1,1037 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "printf_tiny.h" + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + +// output function type +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_fct_wrap_type; + +// internal buffer output +static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) { + if(idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + +// internal null output +static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) { + (void)character; + (void)buffer; + (void)idx; + (void)maxlen; +} + +// internal _putchar wrapper +static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen) { + (void)buffer; + (void)idx; + (void)maxlen; + if(character) { + _putchar(character); + } +} + +// internal output function wrapper +static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) { + (void)idx; + (void)maxlen; + if(character) { + // buffer is the output fct pointer + ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg); + } +} + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int _strnlen_s(const char* str, size_t maxsize) { + const char* s; + for(s = str; *s && maxsize--; ++s) + ; + return (unsigned int)(s - str); +} + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) { + return (ch >= '0') && (ch <= '9'); +} + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char** str) { + unsigned int i = 0U; + while(_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev( + out_fct_type out, + char* buffer, + size_t idx, + size_t maxlen, + const char* buf, + size_t len, + unsigned int width, + unsigned int flags) { + const size_t start_idx = idx; + + // pad spaces up to given width + if(!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for(size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while(len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if(flags & FLAGS_LEFT) { + while(idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + +// internal itoa format +static size_t _ntoa_format( + out_fct_type out, + char* buffer, + size_t idx, + size_t maxlen, + char* buf, + size_t len, + bool negative, + unsigned int base, + unsigned int prec, + unsigned int width, + unsigned int flags) { + // pad leading zeros + if(!(flags & FLAGS_LEFT)) { + if(width && (flags & FLAGS_ZEROPAD) && + (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if(flags & FLAGS_HASH) { + if(!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if(len && (base == 16U)) { + len--; + } + } + if((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } else if((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } else if((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if(len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if(len < PRINTF_NTOA_BUFFER_SIZE) { + if(negative) { + buf[len++] = '-'; + } else if(flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if(flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + +// internal itoa for 'long' type +static size_t _ntoa_long( + out_fct_type out, + char* buffer, + size_t idx, + size_t maxlen, + unsigned long value, + bool negative, + unsigned long base, + unsigned int prec, + unsigned int width, + unsigned int flags) { + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if(!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if(!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : + (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while(value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format( + out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long( + out_fct_type out, + char* buffer, + size_t idx, + size_t maxlen, + unsigned long long value, + bool negative, + unsigned long long base, + unsigned int prec, + unsigned int width, + unsigned int flags) { + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if(!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if(!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : + (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while(value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format( + out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT +static size_t _etoa( + out_fct_type out, + char* buffer, + size_t idx, + size_t maxlen, + double value, + unsigned int prec, + unsigned int width, + unsigned int flags); +#endif + +// internal ftoa for fixed decimal floating point +static size_t _ftoa( + out_fct_type out, + char* buffer, + size_t idx, + size_t maxlen, + double value, + unsigned int prec, + unsigned int width, + unsigned int flags) { + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + + // test for special values + if(value != value) return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if(value < -DBL_MAX) return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if(value > DBL_MAX) + return _out_rev( + out, + buffer, + idx, + maxlen, + (flags & FLAGS_PLUS) ? "fni+" : "fni", + (flags & FLAGS_PLUS) ? 4U : 3U, + width, + flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad + if((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if(value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if(!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if(diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if(frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } else if(diff < 0.5) { + } else if((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if(prec == 0U) { + diff = value - (double)whole; + if((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while(len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if(!(frac /= 10U)) { + break; + } + } + // add extra 0s + while((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if(len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while(len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if(!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if(!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if(width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if(len < PRINTF_FTOA_BUFFER_SIZE) { + if(negative) { + buf[len++] = '-'; + } else if(flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if(flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t _etoa( + out_fct_type out, + char* buffer, + size_t idx, + size_t maxlen, + double value, + unsigned int prec, + unsigned int width, + unsigned int flags) { + // check for NaN and special values + if((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if(negative) { + value = -value; + } + + // default precision + if(!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | + (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + int expval = + (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if(value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of *significant figures* not decimals + if(flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if((value >= 1e-4) && (value < 1e6)) { + if((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } else { + // we use one sigfig for the whole part + if((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if(width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if(expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa( + out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if(minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = _ntoa_long( + out, + buffer, + idx, + maxlen, + (expval < 0) ? -expval : expval, + expval < 0, + 10, + 0, + minwidth - 1, + FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if(flags & FLAGS_LEFT) { + while(idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + +// internal vsnprintf +static int + _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) { + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if(!buffer) { + // use null output function + out = _out_null; + } + + while(*format) { + // format specifier? %[flags][width][.precision][length] + if(*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch(*format) { + case '0': + flags |= FLAGS_ZEROPAD; + format++; + n = 1U; + break; + case '-': + flags |= FLAGS_LEFT; + format++; + n = 1U; + break; + case '+': + flags |= FLAGS_PLUS; + format++; + n = 1U; + break; + case ' ': + flags |= FLAGS_SPACE; + format++; + n = 1U; + break; + case '#': + flags |= FLAGS_HASH; + format++; + n = 1U; + break; + default: + n = 0U; + break; + } + } while(n); + + // evaluate width field + width = 0U; + if(_is_digit(*format)) { + width = _atoi(&format); + } else if(*format == '*') { + const int w = va_arg(va, int); + if(w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if(*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if(_is_digit(*format)) { + precision = _atoi(&format); + } else if(*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch(*format) { + case 'l': + flags |= FLAGS_LONG; + format++; + if(*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h': + flags |= FLAGS_SHORT; + format++; + if(*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't': + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j': + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z': + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default: + break; + } + + // evaluate specifier + switch(*format) { + case 'd': + case 'i': + case 'u': + case 'x': + case 'X': + case 'o': + case 'b': { + // set the base + unsigned int base; + if(*format == 'x' || *format == 'X') { + base = 16U; + } else if(*format == 'o') { + base = 8U; + } else if(*format == 'b') { + base = 2U; + } else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if(*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if(flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if((*format == 'i') || (*format == 'd')) { + // signed + if(flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long( + out, + buffer, + idx, + maxlen, + (unsigned long long)(value > 0 ? value : 0 - value), + value < 0, + base, + precision, + width, + flags); +#endif + } else if(flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long( + out, + buffer, + idx, + maxlen, + (unsigned long)(value > 0 ? value : 0 - value), + value < 0, + base, + precision, + width, + flags); + } else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : + (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : + va_arg(va, int); + idx = _ntoa_long( + out, + buffer, + idx, + maxlen, + (unsigned int)(value > 0 ? value : 0 - value), + value < 0, + base, + precision, + width, + flags); + } + } else { + // unsigned + if(flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long( + out, + buffer, + idx, + maxlen, + va_arg(va, unsigned long long), + false, + base, + precision, + width, + flags); +#endif + } else if(flags & FLAGS_LONG) { + idx = _ntoa_long( + out, + buffer, + idx, + maxlen, + va_arg(va, unsigned long), + false, + base, + precision, + width, + flags); + } else { + const unsigned int value = + (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : + (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : + va_arg(va, unsigned int); + idx = _ntoa_long( + out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f': + case 'F': + if(*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if((*format == 'g') || (*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if((*format == 'E') || (*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c': { + unsigned int l = 1U; + // pre padding + if(!(flags & FLAGS_LEFT)) { + while(l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if(flags & FLAGS_LEFT) { + while(l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's': { + const char* p = va_arg(va, char*); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + // pre padding + if(flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if(!(flags & FLAGS_LEFT)) { + while(l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if(flags & FLAGS_LEFT) { + while(l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p': { + width = sizeof(void*) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if(is_ll) { + idx = _ntoa_long_long( + out, + buffer, + idx, + maxlen, + (uintptr_t)va_arg(va, void*), + false, + 16U, + precision, + width, + flags); + } else { +#endif + idx = _ntoa_long( + out, + buffer, + idx, + maxlen, + (unsigned long)((uintptr_t)va_arg(va, void*)), + false, + 16U, + precision, + width, + flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%': + out('%', buffer, idx++, maxlen); + format++; + break; + + default: + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + +/////////////////////////////////////////////////////////////////////////////// + +int printf_(const char* format, ...) { + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + +int sprintf_(char* buffer, const char* format, ...) { + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + +int snprintf_(char* buffer, size_t count, const char* format, ...) { + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} + +int vprintf_(const char* format, va_list va) { + char buffer[1]; + return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); +} + +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va) { + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) { + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = {out, arg}; + const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); + va_end(va); + return ret; +} diff --git a/lib/print/printf_tiny.h b/lib/print/printf_tiny.h new file mode 100644 index 000000000..8f292819e --- /dev/null +++ b/lib/print/printf_tiny.h @@ -0,0 +1,103 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. +// Use this instead of bloated standard/newlib printf. +// These routines are thread safe and reentrant. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _PRINTF_H_ +#define _PRINTF_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Output a character to a custom device like UART, used by the printf() function + * This function is declared here only. You have to write your custom implementation somewhere + * \param character Character to output + */ +void _putchar(char character); + +/** + * Tiny printf implementation + * You have to implement _putchar if you use printf() + * To avoid conflicts with the regular printf() API it is overridden by macro defines + * and internal underscore-appended functions like printf_() are used + * \param format A string that specifies the format of the output + * \return The number of characters that are written into the array, not counting the terminating null character + */ +int printf_(const char* format, ...); + +/** + * Tiny sprintf implementation + * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! + * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! + * \param format A string that specifies the format of the output + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +int sprintf_(char* buffer, const char* format, ...); + +/** + * Tiny snprintf/vsnprintf implementation + * \param buffer A pointer to the buffer where to store the formatted string + * \param count The maximum number of characters to store in the buffer, including a terminating null character + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that COULD have been written into the buffer, not counting the terminating + * null character. A value equal or larger than count indicates truncation. Only when the returned value + * is non-negative and less than count, the string has been completely written. + */ +int snprintf_(char* buffer, size_t count, const char* format, ...); +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); + +/** + * Tiny vprintf implementation + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +int vprintf_(const char* format, va_list va); + +/** + * printf with output function + * You may use this as dynamic alternative to printf() with its fixed _putchar() output + * \param out An output function which takes one character and an argument pointer + * \param arg An argument pointer for user data passed to output function + * \param format A string that specifies the format of the output + * \return The number of characters that are sent to the output function, not counting the terminating null character + */ +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); + +#ifdef __cplusplus +} +#endif + +#endif // _PRINTF_H_ diff --git a/lib/print/wrappers.c b/lib/print/wrappers.c new file mode 100644 index 000000000..3fe446657 --- /dev/null +++ b/lib/print/wrappers.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "printf_tiny.h" + +void _putchar(char character) { + furi_thread_stdout_write(&character, 1); +} + +int __wrap_printf(const char* format, ...) { + va_list args; + va_start(args, format); + int ret = vprintf_(format, args); + va_end(args); + + return ret; +} + +int __wrap_vsnprintf(char* str, size_t size, const char* format, va_list args) { + return vsnprintf_(str, size, format, args); +} + +int __wrap_puts(const char* str) { + size_t size = furi_thread_stdout_write(str, strlen(str)); + size += furi_thread_stdout_write("\n", 1); + return size; +} + +int __wrap_putchar(int ch) { + size_t size = furi_thread_stdout_write((char*)&ch, 1); + return size; +} + +int __wrap_putc(int ch, FILE* stream) { + UNUSED(stream); + size_t size = furi_thread_stdout_write((char*)&ch, 1); + return size; +} + +int __wrap_snprintf(char* str, size_t size, const char* format, ...) { + va_list args; + va_start(args, format); + int ret = __wrap_vsnprintf(str, size, format, args); + va_end(args); + + return ret; +} + +int __wrap_fflush(FILE* stream) { + UNUSED(stream); + furi_thread_stdout_flush(); + return 0; +} + +__attribute__((__noreturn__)) void __wrap___assert(const char* file, int line, const char* e) { + UNUSED(file); + UNUSED(line); + // TODO: message file and line number + furi_crash(e); +} + +__attribute__((__noreturn__)) void + __wrap___assert_func(const char* file, int line, const char* func, const char* e) { + UNUSED(file); + UNUSED(line); + UNUSED(func); + // TODO: message file and line number + furi_crash(e); +} \ No newline at end of file diff --git a/lib/toolbox/random_name.c b/lib/toolbox/random_name.c index b581bb979..4810a0675 100644 --- a/lib/toolbox/random_name.c +++ b/lib/toolbox/random_name.c @@ -36,7 +36,7 @@ void set_random_name(char* name, uint8_t max_name_size) { uint8_t prefix_i = rand() % COUNT_OF(prefix); uint8_t suffix_i = rand() % COUNT_OF(suffix); - sniprintf(name, max_name_size, "%s_%s", prefix[prefix_i], suffix[suffix_i]); + snprintf(name, max_name_size, "%s_%s", prefix[prefix_i], suffix[suffix_i]); // Set first symbol to upper case name[0] = name[0] - 0x20; } From 51f5641c5efa9a00f491d57574a4e7254add22a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Deisinger?= <41201503+zigad@users.noreply.github.com> Date: Wed, 3 Aug 2022 18:18:48 +0200 Subject: [PATCH 14/22] FIX: Fixed inconsistencies between texts (#1496) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FIX: Fixed inconsistencies between texts: I have changed inconsistencies. Sometimes there was a missing capital letter and sometimes there was dot instead of exclamation mark and so on. No other changes were made. I have made the correction based on how other text looks on Fliper and for headers most texts use Pascal Case. * FIX: Fixed inconsistencies between texts: Found 2 more texts with inconsistencies. Co-authored-by: あく --- applications/about/about.c | 8 ++++---- applications/bt/bt_hid_app/bt_hid.c | 4 ++-- .../scenes/bt_settings_scene_forget_dev_confirm.c | 4 ++-- applications/desktop/views/desktop_view_debug.c | 2 +- applications/desktop/views/desktop_view_lock_menu.c | 2 +- applications/gpio/views/gpio_test.c | 2 +- applications/ibutton/scenes/ibutton_scene_exit_confirm.c | 2 +- applications/ibutton/scenes/ibutton_scene_read.c | 2 +- applications/ibutton/scenes/ibutton_scene_retry_confirm.c | 2 +- applications/infrared/scenes/infrared_scene_ask_back.c | 6 +++--- applications/infrared/scenes/infrared_scene_ask_retry.c | 4 ++-- applications/infrared/scenes/infrared_scene_edit_delete.c | 4 ++-- applications/lfrfid/lfrfid_cli.cpp | 2 +- .../lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp | 4 ++-- .../lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp | 4 ++-- applications/nfc/scenes/nfc_scene_detect_reader.c | 2 +- applications/nfc/scenes/nfc_scene_exit_confirm.c | 4 ++-- .../nfc/scenes/nfc_scene_restore_original_confirm.c | 2 +- applications/nfc/scenes/nfc_scene_retry_confirm.c | 4 ++-- applications/power/battery_test_app/battery_test_app.c | 2 +- .../scenes/power_settings_scene_power_off.c | 2 +- applications/storage/storage_cli.c | 4 ++-- .../scenes/storage_settings_scene_benchmark.c | 4 ++-- .../scenes/storage_settings_scene_factory_reset.c | 2 +- .../scenes/storage_settings_scene_format_confirm.c | 6 +++--- .../scenes/storage_settings_scene_formatting.c | 2 +- .../scenes/storage_settings_scene_internal_info.c | 2 +- .../scenes/storage_settings_scene_sd_info.c | 2 +- .../scenes/storage_settings_scene_unmount_confirm.c | 4 ++-- .../scenes/storage_settings_scene_unmounted.c | 4 ++-- firmware/targets/f7/Src/dfu.c | 2 +- 31 files changed, 50 insertions(+), 50 deletions(-) diff --git a/applications/about/about.c b/applications/about/about.c index 26738fe06..f785c2e40 100644 --- a/applications/about/about.c +++ b/applications/about/about.c @@ -45,7 +45,7 @@ static DialogMessageButton compliance_screen(DialogsApp* dialogs, DialogMessage* DialogMessageButton result; const char* screen_text = "For all compliance\n" - "certificates please visit\n" + "certificates please visit:\n" "www.flipp.dev/compliance"; dialog_message_set_text(message, screen_text, 0, 0, AlignLeft, AlignTop); @@ -91,13 +91,13 @@ static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage* furi_hal_version_get_hw_region_name(), my_name ? my_name : "Unknown"); - string_cat_printf(buffer, "Serial number:\n"); + string_cat_printf(buffer, "Serial Number:\n"); const uint8_t* uid = furi_hal_version_uid(); for(size_t i = 0; i < furi_hal_version_uid_size(); i++) { string_cat_printf(buffer, "%02X", uid[i]); } - dialog_message_set_header(message, "HW Version info:", 0, 0, AlignLeft, AlignTop); + dialog_message_set_header(message, "HW Version Info:", 0, 0, AlignLeft, AlignTop); dialog_message_set_text(message, string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop); result = dialog_message_show(dialogs, message); dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop); @@ -133,7 +133,7 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage* version_get_gitbranch(ver)); } - dialog_message_set_header(message, "FW Version info:", 0, 0, AlignLeft, AlignTop); + dialog_message_set_header(message, "FW Version Info:", 0, 0, AlignLeft, AlignTop); dialog_message_set_text(message, string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop); result = dialog_message_show(dialogs, message); dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop); diff --git a/applications/bt/bt_hid_app/bt_hid.c b/applications/bt/bt_hid_app/bt_hid.c index 29a25c86f..b6f00e939 100755 --- a/applications/bt/bt_hid_app/bt_hid.c +++ b/applications/bt/bt_hid_app/bt_hid.c @@ -90,7 +90,7 @@ BtHid* bt_hid_app_alloc() { submenu_add_item( app->submenu, "Keyboard", BtHidSubmenuIndexKeyboard, bt_hid_submenu_callback, app); submenu_add_item( - app->submenu, "Media player", BtHidSubmenuIndexMedia, bt_hid_submenu_callback, app); + app->submenu, "Media Player", BtHidSubmenuIndexMedia, bt_hid_submenu_callback, app); submenu_add_item(app->submenu, "Mouse", BtHidSubmenuIndexMouse, bt_hid_submenu_callback, app); view_set_previous_callback(submenu_get_view(app->submenu), bt_hid_exit); view_dispatcher_add_view( @@ -103,7 +103,7 @@ BtHid* bt_hid_app_alloc() { dialog_ex_set_left_button_text(app->dialog, "Exit"); dialog_ex_set_right_button_text(app->dialog, "Stay"); dialog_ex_set_center_button_text(app->dialog, "Menu"); - dialog_ex_set_header(app->dialog, "Close current app?", 16, 12, AlignLeft, AlignTop); + dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop); view_dispatcher_add_view( app->view_dispatcher, BtHidViewExitConfirm, dialog_ex_get_view(app->dialog)); diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c index be9a7196c..964736b66 100755 --- a/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c @@ -10,9 +10,9 @@ void bt_settings_scene_forget_dev_confirm_dialog_callback(DialogExResult result, void bt_settings_scene_forget_dev_confirm_on_enter(void* context) { BtSettingsApp* app = context; DialogEx* dialog = app->dialog; - dialog_ex_set_header(dialog, "Unpair all devices?", 64, 3, AlignCenter, AlignTop); + dialog_ex_set_header(dialog, "Unpair All Devices?", 64, 3, AlignCenter, AlignTop); dialog_ex_set_text( - dialog, "All previous pairings\nwill be lost.", 64, 22, AlignCenter, AlignTop); + dialog, "All previous pairings\nwill be lost!", 64, 22, AlignCenter, AlignTop); dialog_ex_set_left_button_text(dialog, "Back"); dialog_ex_set_right_button_text(dialog, "Unpair"); dialog_ex_set_context(dialog, app); diff --git a/applications/desktop/views/desktop_view_debug.c b/applications/desktop/views/desktop_view_debug.c index b69a6a2db..e26411932 100644 --- a/applications/desktop/views/desktop_view_debug.c +++ b/applications/desktop/views/desktop_view_debug.c @@ -23,7 +23,7 @@ void desktop_debug_render(Canvas* canvas, void* model) { const Version* ver; char buffer[64]; - static const char* headers[] = {"FW Version info:", "Dolphin info:"}; + static const char* headers[] = {"FW Version Info:", "Dolphin Info:"}; canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontPrimary); diff --git a/applications/desktop/views/desktop_view_lock_menu.c b/applications/desktop/views/desktop_view_lock_menu.c index 1b2bd76b7..97d3c4898 100644 --- a/applications/desktop/views/desktop_view_lock_menu.c +++ b/applications/desktop/views/desktop_view_lock_menu.c @@ -67,7 +67,7 @@ void desktop_lock_menu_render(Canvas* canvas, void* model) { const char* str = Lockmenu_Items[i]; if(i == 1 && !m->pin_set) str = "Set PIN"; - if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not implemented"; + if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not Implemented"; if(str != NULL) canvas_draw_str_aligned( diff --git a/applications/gpio/views/gpio_test.c b/applications/gpio/views/gpio_test.c index 37c2f4083..89c09f864 100755 --- a/applications/gpio/views/gpio_test.c +++ b/applications/gpio/views/gpio_test.c @@ -20,7 +20,7 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event); static void gpio_test_draw_callback(Canvas* canvas, void* _model) { GpioTestModel* model = _model; canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Gpio Output mode test"); + elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "GPIO Output Mode Test"); canvas_set_font(canvas, FontSecondary); elements_multiline_text_aligned( canvas, 64, 16, AlignCenter, AlignTop, "Press < or > to change pin"); diff --git a/applications/ibutton/scenes/ibutton_scene_exit_confirm.c b/applications/ibutton/scenes/ibutton_scene_exit_confirm.c index c4e90892e..2367e1217 100644 --- a/applications/ibutton/scenes/ibutton_scene_exit_confirm.c +++ b/applications/ibutton/scenes/ibutton_scene_exit_confirm.c @@ -21,7 +21,7 @@ void ibutton_scene_exit_confirm_on_enter(void* context) { widget_add_string_element( widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to iButton menu?"); widget_add_string_element( - widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost."); + widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!"); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); } diff --git a/applications/ibutton/scenes/ibutton_scene_read.c b/applications/ibutton/scenes/ibutton_scene_read.c index c4eb15d36..7af351f06 100644 --- a/applications/ibutton/scenes/ibutton_scene_read.c +++ b/applications/ibutton/scenes/ibutton_scene_read.c @@ -14,7 +14,7 @@ void ibutton_scene_read_on_enter(void* context) { DOLPHIN_DEED(DolphinDeedIbuttonRead); popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); - popup_set_text(popup, "waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); + popup_set_text(popup, "Waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); diff --git a/applications/ibutton/scenes/ibutton_scene_retry_confirm.c b/applications/ibutton/scenes/ibutton_scene_retry_confirm.c index fa2e1dec9..7f8c95b1e 100644 --- a/applications/ibutton/scenes/ibutton_scene_retry_confirm.c +++ b/applications/ibutton/scenes/ibutton_scene_retry_confirm.c @@ -21,7 +21,7 @@ void ibutton_scene_retry_confirm_on_enter(void* context) { widget_add_string_element( widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?"); widget_add_string_element( - widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost."); + widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!"); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); } diff --git a/applications/infrared/scenes/infrared_scene_ask_back.c b/applications/infrared/scenes/infrared_scene_ask_back.c index c9c23684f..493458ade 100644 --- a/applications/infrared/scenes/infrared_scene_ask_back.c +++ b/applications/infrared/scenes/infrared_scene_ask_back.c @@ -10,13 +10,13 @@ void infrared_scene_ask_back_on_enter(void* context) { DialogEx* dialog_ex = infrared->dialog_ex; if(infrared->app_state.is_learning_new_remote) { - dialog_ex_set_header(dialog_ex, "Exit to Infrared menu?", 64, 0, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "Exit to Infrared Menu?", 64, 0, AlignCenter, AlignTop); } else { - dialog_ex_set_header(dialog_ex, "Exit to remote menu?", 64, 0, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "Exit to Remote Menu?", 64, 0, AlignCenter, AlignTop); } dialog_ex_set_text( - dialog_ex, "All unsaved data\nwill be lost.", 64, 31, AlignCenter, AlignCenter); + dialog_ex, "All unsaved data\nwill be lost!", 64, 31, AlignCenter, AlignCenter); dialog_ex_set_icon(dialog_ex, 0, 0, NULL); dialog_ex_set_left_button_text(dialog_ex, "Exit"); dialog_ex_set_center_button_text(dialog_ex, NULL); diff --git a/applications/infrared/scenes/infrared_scene_ask_retry.c b/applications/infrared/scenes/infrared_scene_ask_retry.c index 5157ee882..c87d9e6d3 100644 --- a/applications/infrared/scenes/infrared_scene_ask_retry.c +++ b/applications/infrared/scenes/infrared_scene_ask_retry.c @@ -9,9 +9,9 @@ void infrared_scene_ask_retry_on_enter(void* context) { Infrared* infrared = context; DialogEx* dialog_ex = infrared->dialog_ex; - dialog_ex_set_header(dialog_ex, "Return to reading?", 64, 0, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "Return to Reading?", 64, 0, AlignCenter, AlignTop); dialog_ex_set_text( - dialog_ex, "All unsaved data\nwill be lost.", 64, 31, AlignCenter, AlignCenter); + dialog_ex, "All unsaved data\nwill be lost!", 64, 31, AlignCenter, AlignCenter); dialog_ex_set_icon(dialog_ex, 0, 0, NULL); dialog_ex_set_left_button_text(dialog_ex, "Exit"); dialog_ex_set_center_button_text(dialog_ex, NULL); diff --git a/applications/infrared/scenes/infrared_scene_edit_delete.c b/applications/infrared/scenes/infrared_scene_edit_delete.c index 0842cd613..e79851486 100644 --- a/applications/infrared/scenes/infrared_scene_edit_delete.c +++ b/applications/infrared/scenes/infrared_scene_edit_delete.c @@ -16,7 +16,7 @@ void infrared_scene_edit_delete_on_enter(void* context) { int32_t current_button_index = infrared->app_state.current_button_index; furi_assert(current_button_index != InfraredButtonIndexNone); - dialog_ex_set_header(dialog_ex, "Delete button?", 64, 0, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "Delete Button?", 64, 0, AlignCenter, AlignTop); InfraredRemoteButton* current_button = infrared_remote_get_button(remote, current_button_index); InfraredSignal* signal = infrared_remote_button_get_signal(current_button); @@ -45,7 +45,7 @@ void infrared_scene_edit_delete_on_enter(void* context) { } } else if(edit_target == InfraredEditTargetRemote) { - dialog_ex_set_header(dialog_ex, "Delete remote?", 64, 0, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "Delete Remote?", 64, 0, AlignCenter, AlignTop); infrared_text_store_set( infrared, 0, diff --git a/applications/lfrfid/lfrfid_cli.cpp b/applications/lfrfid/lfrfid_cli.cpp index 7d1bb6d4a..732197e95 100644 --- a/applications/lfrfid/lfrfid_cli.cpp +++ b/applications/lfrfid/lfrfid_cli.cpp @@ -107,7 +107,7 @@ static void lfrfid_cli_write(Cli* cli, string_t args) { UNUSED(cli); UNUSED(args); // TODO implement rfid write - printf("Not implemented :(\r\n"); + printf("Not Implemented :(\r\n"); } static void lfrfid_cli_emulate(Cli* cli, string_t args) { diff --git a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp index bac0247d9..be070b40e 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp @@ -17,9 +17,9 @@ void LfRfidAppSceneExitConfirm::on_enter(LfRfidApp* app, bool /* need_restore */ auto line_1 = container->add(); auto line_2 = container->add(); - line_1->set_text("Exit to RFID menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary); + line_1->set_text("Exit to RFID Menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary); line_2->set_text( - "All unsaved data will be lost.", 64, 31, 0, AlignCenter, AlignBottom, FontSecondary); + "All unsaved data will be lost!", 64, 31, 0, AlignCenter, AlignBottom, FontSecondary); app->view_controller.switch_to(); } diff --git a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp index 39430b974..c18122323 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp @@ -17,9 +17,9 @@ void LfRfidAppSceneRetryConfirm::on_enter(LfRfidApp* app, bool /* need_restore * auto line_1 = container->add(); auto line_2 = container->add(); - line_1->set_text("Return to reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary); + line_1->set_text("Return to Reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary); line_2->set_text( - "All unsaved data will be lost.", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary); + "All unsaved data will be lost!", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary); app->view_controller.switch_to(); } diff --git a/applications/nfc/scenes/nfc_scene_detect_reader.c b/applications/nfc/scenes/nfc_scene_detect_reader.c index 4639735dc..f734f04cb 100644 --- a/applications/nfc/scenes/nfc_scene_detect_reader.c +++ b/applications/nfc/scenes/nfc_scene_detect_reader.c @@ -37,7 +37,7 @@ static void nfc_scene_detect_reader_widget_config(Nfc* nfc, bool data_received) widget_add_icon_element(widget, 0, 14, &I_Reader_detect); widget_add_string_element( - widget, 64, 3, AlignCenter, AlignTop, FontSecondary, "Hold near reader"); + widget, 64, 3, AlignCenter, AlignTop, FontSecondary, "Hold Near Reader"); widget_add_string_element(widget, 55, 22, AlignLeft, AlignTop, FontPrimary, "Emulating..."); if(data_received) { diff --git a/applications/nfc/scenes/nfc_scene_exit_confirm.c b/applications/nfc/scenes/nfc_scene_exit_confirm.c index 24942bcd1..b22dd42a1 100644 --- a/applications/nfc/scenes/nfc_scene_exit_confirm.c +++ b/applications/nfc/scenes/nfc_scene_exit_confirm.c @@ -12,9 +12,9 @@ void nfc_scene_exit_confirm_on_enter(void* context) { dialog_ex_set_left_button_text(dialog_ex, "Exit"); dialog_ex_set_right_button_text(dialog_ex, "Stay"); - dialog_ex_set_header(dialog_ex, "Exit to NFC menu?", 64, 11, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "Exit to NFC Menu?", 64, 11, AlignCenter, AlignTop); dialog_ex_set_text( - dialog_ex, "All unsaved data\nwill be lost.", 64, 25, AlignCenter, AlignTop); + dialog_ex, "All unsaved data\nwill be lost!", 64, 25, AlignCenter, AlignTop); dialog_ex_set_context(dialog_ex, nfc); dialog_ex_set_result_callback(dialog_ex, nfc_scene_exit_confirm_dialog_callback); diff --git a/applications/nfc/scenes/nfc_scene_restore_original_confirm.c b/applications/nfc/scenes/nfc_scene_restore_original_confirm.c index 70d161dd1..2c12749df 100644 --- a/applications/nfc/scenes/nfc_scene_restore_original_confirm.c +++ b/applications/nfc/scenes/nfc_scene_restore_original_confirm.c @@ -10,7 +10,7 @@ void nfc_scene_restore_original_confirm_on_enter(void* context) { Nfc* nfc = context; DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_set_header(dialog_ex, "Restore card data?", 64, 0, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "Restore Card Data?", 64, 0, AlignCenter, AlignTop); dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring); dialog_ex_set_text( dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop); diff --git a/applications/nfc/scenes/nfc_scene_retry_confirm.c b/applications/nfc/scenes/nfc_scene_retry_confirm.c index f7b3991ec..366582ea8 100644 --- a/applications/nfc/scenes/nfc_scene_retry_confirm.c +++ b/applications/nfc/scenes/nfc_scene_retry_confirm.c @@ -12,9 +12,9 @@ void nfc_scene_retry_confirm_on_enter(void* context) { dialog_ex_set_left_button_text(dialog_ex, "Retry"); dialog_ex_set_right_button_text(dialog_ex, "Stay"); - dialog_ex_set_header(dialog_ex, "Retry reading?", 64, 11, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "Retry Reading?", 64, 11, AlignCenter, AlignTop); dialog_ex_set_text( - dialog_ex, "All unsaved data will be\nlost.", 64, 25, AlignCenter, AlignTop); + dialog_ex, "All unsaved data will be\nlost!", 64, 25, AlignCenter, AlignTop); dialog_ex_set_context(dialog_ex, nfc); dialog_ex_set_result_callback(dialog_ex, nfc_scene_retry_confirm_dialog_callback); diff --git a/applications/power/battery_test_app/battery_test_app.c b/applications/power/battery_test_app/battery_test_app.c index 0b5bc578a..ab6889dc8 100755 --- a/applications/power/battery_test_app/battery_test_app.c +++ b/applications/power/battery_test_app/battery_test_app.c @@ -57,7 +57,7 @@ BatteryTestApp* battery_test_alloc() { battery_info_get_view(app->batery_info)); app->dialog = dialog_ex_alloc(); - dialog_ex_set_header(app->dialog, "Close battery test?", 64, 12, AlignCenter, AlignTop); + dialog_ex_set_header(app->dialog, "Close Battery Test?", 64, 12, AlignCenter, AlignTop); dialog_ex_set_left_button_text(app->dialog, "Exit"); dialog_ex_set_right_button_text(app->dialog, "Stay"); dialog_ex_set_result_callback(app->dialog, battery_test_dialog_callback); diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_power_off.c b/applications/power/power_settings_app/scenes/power_settings_scene_power_off.c index 83046743b..923ec250e 100644 --- a/applications/power/power_settings_app/scenes/power_settings_scene_power_off.c +++ b/applications/power/power_settings_app/scenes/power_settings_scene_power_off.c @@ -10,7 +10,7 @@ void power_settings_scene_power_off_on_enter(void* context) { PowerSettingsApp* app = context; DialogEx* dialog = app->dialog; - dialog_ex_set_header(dialog, "Turn off Device?", 64, 2, AlignCenter, AlignTop); + dialog_ex_set_header(dialog, "Turn Off Device?", 64, 2, AlignCenter, AlignTop); dialog_ex_set_text( dialog, " I will be\nwaiting for\n you here...", 78, 16, AlignLeft, AlignTop); dialog_ex_set_icon(dialog, 21, 13, &I_Cry_dolph_55x52); diff --git a/applications/storage/storage_cli.c b/applications/storage/storage_cli.c index 63b9a54b7..fd988da76 100644 --- a/applications/storage/storage_cli.c +++ b/applications/storage/storage_cli.c @@ -82,7 +82,7 @@ static void storage_cli_format(Cli* cli, string_t path) { if(string_cmp_str(path, STORAGE_INT_PATH_PREFIX) == 0) { storage_cli_print_error(FSE_NOT_IMPLEMENTED); } else if(string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) { - printf("Formatting SD card, all data will be lost. Are you sure (y/n)?\r\n"); + printf("Formatting SD card, All data will be lost! Are you sure (y/n)?\r\n"); char answer = cli_getc(cli); if(answer == 'y' || answer == 'Y') { Storage* api = furi_record_open(RECORD_STORAGE); @@ -581,7 +581,7 @@ void storage_cli(Cli* cli, string_t args, void* context) { static void storage_cli_factory_reset(Cli* cli, string_t args, void* context) { UNUSED(args); UNUSED(context); - printf("All data will be lost. Are you sure (y/n)?\r\n"); + printf("All data will be lost! Are you sure (y/n)?\r\n"); char c = cli_getc(cli); if(c == 'y' || c == 'Y') { printf("Data will be wiped after reboot.\r\n"); diff --git a/applications/storage_settings/scenes/storage_settings_scene_benchmark.c b/applications/storage_settings/scenes/storage_settings_scene_benchmark.c index 610696afc..615e07f8b 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_benchmark.c +++ b/applications/storage_settings/scenes/storage_settings_scene_benchmark.c @@ -75,7 +75,7 @@ static bool static void storage_settings_scene_benchmark(StorageSettings* app) { DialogEx* dialog_ex = app->dialog_ex; uint8_t* bench_data; - dialog_ex_set_header(dialog_ex, "Preparing data...", 64, 32, AlignCenter, AlignCenter); + dialog_ex_set_header(dialog_ex, "Preparing Data...", 64, 32, AlignCenter, AlignCenter); bench_data = malloc(BENCH_DATA_SIZE); for(size_t i = 0; i < BENCH_DATA_SIZE; i++) { @@ -123,7 +123,7 @@ void storage_settings_scene_benchmark_on_enter(void* context) { if(sd_status != FSE_OK) { dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); - dialog_ex_set_header(dialog_ex, "SD card not mounted", 64, 3, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop); dialog_ex_set_text( dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop); dialog_ex_set_center_button_text(dialog_ex, "Ok"); diff --git a/applications/storage_settings/scenes/storage_settings_scene_factory_reset.c b/applications/storage_settings/scenes/storage_settings_scene_factory_reset.c index 84119422a..a69479681 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_factory_reset.c +++ b/applications/storage_settings/scenes/storage_settings_scene_factory_reset.c @@ -24,7 +24,7 @@ void storage_settings_scene_factory_reset_on_enter(void* context) { dialog_ex_set_header(dialog_ex, "Confirm Factory Reset", 64, 10, AlignCenter, AlignCenter); dialog_ex_set_text( dialog_ex, - "Internal storage will be erased\r\nData and setting will be lost", + "Internal storage will be erased\r\nData and setting will be lost!", 64, 32, AlignCenter, diff --git a/applications/storage_settings/scenes/storage_settings_scene_format_confirm.c b/applications/storage_settings/scenes/storage_settings_scene_format_confirm.c index 6388a6826..ebf7dece4 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_format_confirm.c +++ b/applications/storage_settings/scenes/storage_settings_scene_format_confirm.c @@ -15,13 +15,13 @@ void storage_settings_scene_format_confirm_on_enter(void* context) { if(sd_status == FSE_NOT_READY) { dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); - dialog_ex_set_header(dialog_ex, "SD card not mounted", 64, 3, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop); dialog_ex_set_text( dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop); dialog_ex_set_center_button_text(dialog_ex, "Ok"); } else { - dialog_ex_set_header(dialog_ex, "Format SD card?", 64, 10, AlignCenter, AlignCenter); - dialog_ex_set_text(dialog_ex, "All data will be lost", 64, 32, AlignCenter, AlignCenter); + dialog_ex_set_header(dialog_ex, "Format SD Card?", 64, 10, AlignCenter, AlignCenter); + dialog_ex_set_text(dialog_ex, "All data will be lost!", 64, 32, AlignCenter, AlignCenter); dialog_ex_set_left_button_text(dialog_ex, "Cancel"); dialog_ex_set_right_button_text(dialog_ex, "Format"); } diff --git a/applications/storage_settings/scenes/storage_settings_scene_formatting.c b/applications/storage_settings/scenes/storage_settings_scene_formatting.c index c4e15b261..e0d8dfca8 100755 --- a/applications/storage_settings/scenes/storage_settings_scene_formatting.c +++ b/applications/storage_settings/scenes/storage_settings_scene_formatting.c @@ -43,7 +43,7 @@ void storage_settings_scene_formatting_on_enter(void* context) { dialog_ex_set_result_callback(dialog_ex, storage_settings_scene_formatting_dialog_callback); if(error != FSE_OK) { - dialog_ex_set_header(dialog_ex, "Cannot format SD Card", 64, 10, AlignCenter, AlignCenter); + dialog_ex_set_header(dialog_ex, "Cannot Format SD Card", 64, 10, AlignCenter, AlignCenter); dialog_ex_set_text( dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter); } else { diff --git a/applications/storage_settings/scenes/storage_settings_scene_internal_info.c b/applications/storage_settings/scenes/storage_settings_scene_internal_info.c index 74eecdb9f..76c7fd0ec 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_internal_info.c +++ b/applications/storage_settings/scenes/storage_settings_scene_internal_info.c @@ -21,7 +21,7 @@ void storage_settings_scene_internal_info_on_enter(void* context) { if(error != FSE_OK) { dialog_ex_set_header( - dialog_ex, "Internal storage error", 64, 10, AlignCenter, AlignCenter); + dialog_ex, "Internal Storage Error", 64, 10, AlignCenter, AlignCenter); dialog_ex_set_text( dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter); } else { diff --git a/applications/storage_settings/scenes/storage_settings_scene_sd_info.c b/applications/storage_settings/scenes/storage_settings_scene_sd_info.c index 1c861538a..485368c55 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_sd_info.c +++ b/applications/storage_settings/scenes/storage_settings_scene_sd_info.c @@ -19,7 +19,7 @@ void storage_settings_scene_sd_info_on_enter(void* context) { if(sd_status != FSE_OK) { dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); - dialog_ex_set_header(dialog_ex, "SD card not mounted", 64, 3, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop); dialog_ex_set_text( dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop); dialog_ex_set_center_button_text(dialog_ex, "Ok"); diff --git a/applications/storage_settings/scenes/storage_settings_scene_unmount_confirm.c b/applications/storage_settings/scenes/storage_settings_scene_unmount_confirm.c index 27f55251f..971870715 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_unmount_confirm.c +++ b/applications/storage_settings/scenes/storage_settings_scene_unmount_confirm.c @@ -15,12 +15,12 @@ void storage_settings_scene_unmount_confirm_on_enter(void* context) { if(sd_status == FSE_NOT_READY) { dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); - dialog_ex_set_header(dialog_ex, "SD card not mounted", 64, 3, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop); dialog_ex_set_text( dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop); dialog_ex_set_center_button_text(dialog_ex, "Ok"); } else { - dialog_ex_set_header(dialog_ex, "Unmount SD card?", 64, 10, AlignCenter, AlignCenter); + dialog_ex_set_header(dialog_ex, "Unmount SD Card?", 64, 10, AlignCenter, AlignCenter); dialog_ex_set_text( dialog_ex, "SD card will be\nunavailable", 64, 32, AlignCenter, AlignCenter); dialog_ex_set_left_button_text(dialog_ex, "Cancel"); diff --git a/applications/storage_settings/scenes/storage_settings_scene_unmounted.c b/applications/storage_settings/scenes/storage_settings_scene_unmounted.c index e5f69d45a..43f44583d 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_unmounted.c +++ b/applications/storage_settings/scenes/storage_settings_scene_unmounted.c @@ -16,11 +16,11 @@ void storage_settings_scene_unmounted_on_enter(void* context) { dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); if(error == FSE_OK) { - dialog_ex_set_header(dialog_ex, "SD card unmounted", 64, 3, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "SD Card Unmounted", 64, 3, AlignCenter, AlignTop); dialog_ex_set_text(dialog_ex, "You can remove\nSD card now.", 3, 22, AlignLeft, AlignTop); notification_message(app->notification, &sequence_blink_green_100); } else { - dialog_ex_set_header(dialog_ex, "Cannot unmount SD Card", 64, 3, AlignCenter, AlignTop); + dialog_ex_set_header(dialog_ex, "Cannot Unmount SD Card", 64, 3, AlignCenter, AlignTop); dialog_ex_set_text(dialog_ex, storage_error_get_desc(error), 3, 22, AlignLeft, AlignTop); notification_message(app->notification, &sequence_blink_red_100); } diff --git a/firmware/targets/f7/Src/dfu.c b/firmware/targets/f7/Src/dfu.c index 889c3c1ec..f32ac2ac4 100644 --- a/firmware/targets/f7/Src/dfu.c +++ b/firmware/targets/f7/Src/dfu.c @@ -19,7 +19,7 @@ void flipper_boot_dfu_show_splash() { u8g2_DrawXBM(fb, 0, 64 - 50, 128, 50, splash_data); u8g2_SetFont(fb, u8g2_font_helvB08_tr); u8g2_DrawStr(fb, 2, 8, "Update & Recovery Mode"); - u8g2_DrawStr(fb, 2, 21, "DFU started"); + u8g2_DrawStr(fb, 2, 21, "DFU Started"); u8g2_SetPowerSave(fb, 0); u8g2_SendBuffer(fb); } From 6499597586c9e5aff76bf4d58f8389c4d2fca0ee Mon Sep 17 00:00:00 2001 From: hedger Date: Wed, 3 Aug 2022 19:32:31 +0300 Subject: [PATCH 15/22] vscode: initial development configuration (#1520) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * vscode: initial development configuration; fbt: `vscode_dist` target for deploying vscode config * vscode: fixed fbt blackmagic command Co-authored-by: あく --- .vscode/.gitignore | 4 + .vscode/example/c_cpp_properties.json | 32 ++++++++ .vscode/example/launch.json | 87 ++++++++++++++++++++++ .vscode/example/settings.json | 22 ++++++ .vscode/example/tasks.json | 103 ++++++++++++++++++++++++++ .vscode/extensions.json | 15 ++++ SConstruct | 7 +- documentation/fbt.md | 15 +++- 8 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 .vscode/.gitignore create mode 100644 .vscode/example/c_cpp_properties.json create mode 100644 .vscode/example/launch.json create mode 100644 .vscode/example/settings.json create mode 100644 .vscode/example/tasks.json create mode 100644 .vscode/extensions.json diff --git a/.vscode/.gitignore b/.vscode/.gitignore new file mode 100644 index 000000000..670df7d48 --- /dev/null +++ b/.vscode/.gitignore @@ -0,0 +1,4 @@ +./c_cpp_properties.json +./launch.json +./settings.json +./tasks.json diff --git a/.vscode/example/c_cpp_properties.json b/.vscode/example/c_cpp_properties.json new file mode 100644 index 000000000..db08320c9 --- /dev/null +++ b/.vscode/example/c_cpp_properties.json @@ -0,0 +1,32 @@ +{ + "configurations": [ + { + "name": "Win32", + "compilerPath": "${workspaceFolder}/toolchain/i686-windows/bin/arm-none-eabi-gcc.exe", + "intelliSenseMode": "gcc-arm", + "compileCommands": "${workspaceFolder}/build/latest/compile_commands.json", + "configurationProvider": "ms-vscode.cpptools", + "cStandard": "gnu17", + "cppStandard": "c++17" + }, + { + "name": "Linux", + "compilerPath": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gcc", + "intelliSenseMode": "gcc-arm", + "compileCommands": "${workspaceFolder}/build/latest/compile_commands.json", + "configurationProvider": "ms-vscode.cpptools", + "cStandard": "gnu17", + "cppStandard": "c++17" + }, + { + "name": "Mac", + "compilerPath": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gcc", + "intelliSenseMode": "gcc-arm", + "compileCommands": "${workspaceFolder}/build/latest/compile_commands.json", + "configurationProvider": "ms-vscode.cpptools", + "cStandard": "gnu17", + "cppStandard": "c++17" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/example/launch.json b/.vscode/example/launch.json new file mode 100644 index 000000000..bdad04285 --- /dev/null +++ b/.vscode/example/launch.json @@ -0,0 +1,87 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "inputs": [ + { + "id": "BLACKMAGIC", + "type": "command", + "command": "shellCommand.execute", + "args": { + "command": "./fbt get_blackmagic", + "description": "Get Blackmagic device", + } + } + ], + "configurations": [ + { + "name": "Attach FW (ST-Link)", + "cwd": "${workspaceFolder}", + "executable": "./build/latest/firmware.elf", + "request": "attach", + "type": "cortex-debug", + "servertype": "openocd", + "device": "stlink", + "svdFile": "./debug/STM32WB55_CM4.svd", + "rtos": "FreeRTOS", + "configFiles": [ + "interface/stlink.cfg", + "./debug/stm32wbx.cfg", + ], + "postAttachCommands": [ + // "attach 1", + "compare-sections", + ] + // "showDevDebugOutput": "raw", + }, + { + "name": "Attach FW (blackmagic)", + "cwd": "${workspaceFolder}", + "executable": "./build/latest/firmware.elf", + "request": "attach", + "type": "cortex-debug", + "servertype": "external", + "gdbTarget": "${input:BLACKMAGIC}", + "svdFile": "./debug/STM32WB55_CM4.svd", + "rtos": "FreeRTOS", + "postAttachCommands": [ + "monitor swdp_scan", + "attach 1", + "set confirm off", + "set mem inaccessible-by-default off", + "compare-sections", + ] + // "showDevDebugOutput": "raw", + }, + { + "name": "Attach FW (JLink)", + "cwd": "${workspaceFolder}", + "executable": "./build/latest/firmware.elf", + "request": "attach", + "type": "cortex-debug", + "servertype": "jlink", + "interface": "swd", + "device": "STM32WB55RG", + "svdFile": "./debug/STM32WB55_CM4.svd", + "rtos": "FreeRTOS", + // "showDevDebugOutput": "raw", + }, + { + "name": "fbt debug", + "type": "python", + "request": "launch", + "program": "./lib/scons/scripts/scons.py", + "args": [ + "sdk" + ] + }, + { + "name": "python debug", + "type": "python", + "request": "launch", + "program": "${file}", + "args": [] + } + ] +} \ No newline at end of file diff --git a/.vscode/example/settings.json b/.vscode/example/settings.json new file mode 100644 index 000000000..925c2e076 --- /dev/null +++ b/.vscode/example/settings.json @@ -0,0 +1,22 @@ +{ + "C_Cpp.default.cStandard": "gnu17", + "C_Cpp.default.cppStandard": "c++17", + "python.formatting.provider": "black", + "workbench.tree.indent": 12, + "cortex-debug.enableTelemetry": false, + "cortex-debug.variableUseNaturalFormat": true, + "cortex-debug.showRTOS": true, + "cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/i686-windows/bin", + "cortex-debug.armToolchainPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin", + "cortex-debug.armToolchainPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin", + "cortex-debug.openocdPath.windows": "${workspaceFolder}/toolchain/i686-windows/openocd/bin/openocd.exe", + "cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd", + "cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd", + "editor.formatOnSave": true, + "files.associations": { + "*.scons": "python", + "SConscript": "python", + "SConstruct": "python", + "*.fam": "python", + } +} \ No newline at end of file diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json new file mode 100644 index 000000000..c124305cb --- /dev/null +++ b/.vscode/example/tasks.json @@ -0,0 +1,103 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "[Release] Build", + "group": "build", + "type": "shell", + "command": "./fbt COMPACT=1 DEBUG=0" + }, + { + "label": "[Debug] Build", + "group": "build", + "type": "shell", + "command": "./fbt" + }, + { + "label": "[Release] Flash (ST-Link)", + "group": "build", + "type": "shell", + "command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash" + }, + { + "label": "[Debug] Flash (ST-Link)", + "group": "build", + "type": "shell", + "command": "./fbt FORCE=1 flash" + }, + { + "label": "[Release] Flash (blackmagic)", + "group": "build", + "type": "shell", + "command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_blackmagic" + }, + { + "label": "[Debug] Flash (blackmagic)", + "group": "build", + "type": "shell", + "command": "./fbt FORCE=1 flash_blackmagic" + }, + { + "label": "[Release] Flash (JLink)", + "group": "build", + "type": "shell", + "command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 jflash" + }, + { + "label": "[Debug] Flash (JLink)", + "group": "build", + "type": "shell", + "command": "./fbt FORCE=1 jflash" + }, + { + "label": "[Release] Build update bundle", + "group": "build", + "type": "shell", + "command": "./fbt update_package COMPACT=1 DEBUG=0" + }, + { + "label": "[Debug] Build update bundle", + "group": "build", + "type": "shell", + "command": "./fbt update_package" + }, + { + "label": "[Release] Build updater", + "group": "build", + "type": "shell", + "command": "./fbt updater_all COMPACT=1 DEBUG=0" + }, + { + "label": "[Debug] Build updater", + "group": "build", + "type": "shell", + "command": "./fbt updater_all" + }, + { + "label": "[Debug] Flash (USB, w/o resources)", + "group": "build", + "type": "shell", + "command": "./fbt FORCE=1 flash_usb" + }, + { + "label": "[Release] Flash (USB, w/o resources)", + "group": "build", + "type": "shell", + "command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb" + }, + { + "label": "[Debug:unit_tests] Flash (USB)", + "group": "build", + "type": "shell", + "command": "./fbt FIRMWARE_APP_SET=unit_tests FORCE=1 flash_usb" + }, + { + "label": "[Release] Flash (USB, with resources)", + "group": "build", + "type": "shell", + "command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full" + }, + ] +} \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..b53ffc24c --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,15 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "ms-python.black-formatter", + "ms-vscode.cpptools", + "amiralizadeh9480.cpp-helper", + "marus25.cortex-debug", + "zxh404.vscode-proto3", + "augustocdias.tasks-shell-input" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [] +} \ No newline at end of file diff --git a/SConstruct b/SConstruct index fe731e357..52fe75a6a 100644 --- a/SConstruct +++ b/SConstruct @@ -274,8 +274,13 @@ distenv.PhonyTarget("cli", "${PYTHON3} scripts/serial_cli.py") # Find blackmagic probe - distenv.PhonyTarget( "get_blackmagic", "@echo $( ${BLACKMAGIC_ADDR} $)", ) + +# Prepare vscode environment +vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*")) +distenv.Precious(vscode_dist) +distenv.NoClean(vscode_dist) +distenv.Alias("vscode_dist", vscode_dist) diff --git a/documentation/fbt.md b/documentation/fbt.md index c658ce20e..53fc4b5e3 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -24,12 +24,25 @@ To build with FBT, call it specifying configuration options & targets to build. To run cleanup (think of `make clean`) for specified targets, add `-c` option. +## VSCode integration + +`fbt` includes basic development environment configuration for VSCode. To deploy it, run `./fbt vscode_dist`. That will copy initial environment configuration to `.vscode` folder. After that, you can use that configuration by starting VSCode and choosing firmware root folder in "File > Open Folder" menu. + + * On first start, you'll be prompted to install recommended plug-ins. Please install them for best development experience. _You can find a list of them in `.vscode/extensions.json`._ + * Basic build tasks are invoked in Ctrl+Shift+B menu. + * Debugging requires a supported probe. That includes: + * Wi-Fi devboard with stock firmware (blackmagic), + * ST-Link and compatible devices, + * J-Link for flashing and debugging (in VSCode only). _Note that J-Link tools are not included with our toolchain and you have to [download](https://www.segger.com/downloads/jlink/) them yourself and put on your system's PATH._ + * Without a supported probe, you can install firmware on Flipper using USB installation method. + + ## FBT targets FBT keeps track of internal dependencies, so you only need to build the highest-level target you need, and FBT will make sure everything they depend on is up-to-date. ### High-level (what you most likely need) - + - `fw_dist` - build & publish firmware to `dist` folder. This is a default target, when no other are specified - `updater_package`, `updater_minpackage` - build self-update package. Minimal version only inclues firmware's DFU file; full version also includes radio stack & resources for SD card - `copro_dist` - bundle Core2 FUS+stack binaries for qFlipper From 135fbd294bcc9e67eda18230df7547c1ef347645 Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Wed, 3 Aug 2022 19:43:14 +0300 Subject: [PATCH 16/22] [FL-2693] RW buffered streams (#1523) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add write methods for stream cache * Fix logical error * Implement write cache for buffered file streams * Minor code refactoring * Less ugly code * Better read() implementation * Intermediate implementation * Fix logical error * Code cleanup * Update FFF comments * Fix logical error * Github: rsync with delete Co-authored-by: あく --- .github/workflows/build.yml | 2 +- lib/flipper_format/flipper_format.h | 4 +- lib/toolbox/stream/buffered_file_stream.c | 131 +++++++++++++++++----- lib/toolbox/stream/buffered_file_stream.h | 14 ++- lib/toolbox/stream/stream_cache.c | 23 +++- lib/toolbox/stream/stream_cache.h | 17 +++ 6 files changed, 156 insertions(+), 35 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b491c600c..a1ae875a8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -113,7 +113,7 @@ jobs: run: | echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; chmod 600 ./deploy_key; - rsync -avzP --mkpath \ + rsync -avzP --delete --mkpath \ -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \ artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/"; rm ./deploy_key; diff --git a/lib/flipper_format/flipper_format.h b/lib/flipper_format/flipper_format.h index 09928c18c..6163dee0e 100644 --- a/lib/flipper_format/flipper_format.h +++ b/lib/flipper_format/flipper_format.h @@ -116,7 +116,7 @@ FlipperFormat* flipper_format_string_alloc(); FlipperFormat* flipper_format_file_alloc(Storage* storage); /** - * Allocate FlipperFormat as file, buffered read-only mode. + * Allocate FlipperFormat as file, buffered mode. * @return FlipperFormat* pointer to a FlipperFormat instance */ FlipperFormat* flipper_format_buffered_file_alloc(Storage* storage); @@ -131,7 +131,7 @@ FlipperFormat* flipper_format_buffered_file_alloc(Storage* storage); bool flipper_format_file_open_existing(FlipperFormat* flipper_format, const char* path); /** - * Open existing file, read-only with buffered read operations. + * Open existing file, buffered mode. * Use only if FlipperFormat allocated as a file. * @param flipper_format Pointer to a FlipperFormat instance * @param path File path diff --git a/lib/toolbox/stream/buffered_file_stream.c b/lib/toolbox/stream/buffered_file_stream.c index 2f2359a04..3b20a391c 100644 --- a/lib/toolbox/stream/buffered_file_stream.c +++ b/lib/toolbox/stream/buffered_file_stream.c @@ -1,6 +1,5 @@ #include "buffered_file_stream.h" -#include "core/check.h" #include "stream_i.h" #include "file_stream.h" #include "stream_cache.h" @@ -9,6 +8,7 @@ typedef struct { Stream stream_base; Stream* file_stream; StreamCache* cache; + bool sync_pending; } BufferedFileStream; static void buffered_file_stream_free(BufferedFileStream* stream); @@ -27,6 +27,9 @@ static bool buffered_file_stream_delete_and_insert( StreamWriteCB write_callback, const void* ctx); +static bool buffered_file_stream_flush(BufferedFileStream* stream); +static bool buffered_file_stream_unread(BufferedFileStream* stream); + const StreamVTable buffered_file_stream_vtable = { .free = (StreamFreeFn)buffered_file_stream_free, .eof = (StreamEOFFn)buffered_file_stream_eof, @@ -39,13 +42,12 @@ const StreamVTable buffered_file_stream_vtable = { .delete_and_insert = (StreamDeleteAndInsertFn)buffered_file_stream_delete_and_insert, }; -static bool buffered_file_stream_unread(BufferedFileStream* stream); - Stream* buffered_file_stream_alloc(Storage* storage) { BufferedFileStream* stream = malloc(sizeof(BufferedFileStream)); stream->file_stream = file_stream_alloc(storage); stream->cache = stream_cache_alloc(); + stream->sync_pending = false; stream->stream_base.vtable = &buffered_file_stream_vtable; return (Stream*)stream; @@ -58,7 +60,6 @@ bool buffered_file_stream_open( FS_OpenMode open_mode) { furi_assert(_stream); BufferedFileStream* stream = (BufferedFileStream*)_stream; - stream_cache_drop(stream->cache); furi_check(stream->stream_base.vtable == &buffered_file_stream_vtable); return file_stream_open(stream->file_stream, path, access_mode, open_mode); } @@ -67,7 +68,22 @@ bool buffered_file_stream_close(Stream* _stream) { furi_assert(_stream); BufferedFileStream* stream = (BufferedFileStream*)_stream; furi_check(stream->stream_base.vtable == &buffered_file_stream_vtable); - return file_stream_close(stream->file_stream); + bool success = false; + do { + if(!(stream->sync_pending ? buffered_file_stream_flush(stream) : + buffered_file_stream_unread(stream))) + break; + if(!file_stream_close(stream->file_stream)) break; + success = true; + } while(false); + return success; +} + +bool buffered_file_stream_sync(Stream* _stream) { + furi_assert(_stream); + BufferedFileStream* stream = (BufferedFileStream*)_stream; + furi_check(stream->stream_base.vtable == &buffered_file_stream_vtable); + return stream->sync_pending ? buffered_file_stream_flush(stream) : true; } FS_Error buffered_file_stream_get_error(Stream* _stream) { @@ -85,10 +101,23 @@ static void buffered_file_stream_free(BufferedFileStream* stream) { } static bool buffered_file_stream_eof(BufferedFileStream* stream) { - return stream_cache_at_end(stream->cache) && stream_eof(stream->file_stream); + bool ret; + const bool file_stream_eof = stream_eof(stream->file_stream); + const bool cache_at_end = stream_cache_at_end(stream->cache); + if(!stream->sync_pending) { + ret = file_stream_eof && cache_at_end; + } else { + const size_t remaining_size = + stream_size(stream->file_stream) - stream_tell(stream->file_stream); + ret = stream_cache_size(stream->cache) >= + (remaining_size ? cache_at_end : file_stream_eof); + } + return ret; } static void buffered_file_stream_clean(BufferedFileStream* stream) { + // Not syncing because data will be deleted anyway + stream->sync_pending = false; stream_cache_drop(stream->cache); stream_clean(stream->file_stream); } @@ -97,7 +126,7 @@ static bool buffered_file_stream_seek( BufferedFileStream* stream, int32_t offset, StreamOffset offset_type) { - bool success = false; + bool success = true; int32_t new_offset = offset; if(offset_type == StreamOffsetFromCurrent) { @@ -108,47 +137,71 @@ static bool buffered_file_stream_seek( } if((new_offset != 0) || (offset_type != StreamOffsetFromCurrent)) { - stream_cache_drop(stream->cache); - success = stream_seek(stream->file_stream, new_offset, offset_type); - } else { - success = true; + if(stream->sync_pending) { + success = buffered_file_stream_sync((Stream*)stream); + } else { + stream_cache_drop(stream->cache); + } + if(success) { + success = stream_seek(stream->file_stream, new_offset, offset_type); + } } return success; } static size_t buffered_file_stream_tell(BufferedFileStream* stream) { - return stream_tell(stream->file_stream) + stream_cache_pos(stream->cache) - - stream_cache_size(stream->cache); + size_t pos = stream_tell(stream->file_stream) + stream_cache_pos(stream->cache); + if(!stream->sync_pending) { + pos -= stream_cache_size(stream->cache); + } + return pos; } static size_t buffered_file_stream_size(BufferedFileStream* stream) { - return stream_cache_size(stream->cache) + stream_size(stream->file_stream); + size_t size = stream_size(stream->file_stream); + if(stream->sync_pending) { + const size_t remaining_size = size - stream_tell(stream->file_stream); + const size_t cache_size = stream_cache_size(stream->cache); + if(cache_size > remaining_size) { + size += (cache_size - remaining_size); + } + } + return size; } static size_t buffered_file_stream_write(BufferedFileStream* stream, const uint8_t* data, size_t size) { size_t need_to_write = size; do { - if(!buffered_file_stream_unread(stream)) break; - need_to_write -= stream_write(stream->file_stream, data, size); + if(!stream->sync_pending) { + if(!buffered_file_stream_unread(stream)) break; + } + while(need_to_write) { + stream->sync_pending = true; + need_to_write -= + stream_cache_write(stream->cache, data + (size - need_to_write), need_to_write); + if(need_to_write) { + stream->sync_pending = false; + if(!stream_cache_flush(stream->cache, stream->file_stream)) break; + } + } } while(false); return size - need_to_write; } static size_t buffered_file_stream_read(BufferedFileStream* stream, uint8_t* data, size_t size) { size_t need_to_read = size; - while(need_to_read) { need_to_read -= stream_cache_read(stream->cache, data + (size - need_to_read), need_to_read); if(need_to_read) { - if(!stream_cache_fill(stream->cache, stream->file_stream)) { - break; + if(stream->sync_pending) { + if(!buffered_file_stream_flush(stream)) break; } + if(!stream_cache_fill(stream->cache, stream->file_stream)) break; } } - return size - need_to_read; } @@ -157,19 +210,43 @@ static bool buffered_file_stream_delete_and_insert( size_t delete_size, StreamWriteCB write_callback, const void* ctx) { - return buffered_file_stream_unread(stream) && - stream_delete_and_insert(stream->file_stream, delete_size, write_callback, ctx); + bool success = false; + do { + if(!(stream->sync_pending ? buffered_file_stream_flush(stream) : + buffered_file_stream_unread(stream))) + break; + if(!stream_delete_and_insert(stream->file_stream, delete_size, write_callback, ctx)) break; + success = true; + } while(false); + return success; +} + +// Write the cache into the underlying stream and adjust seek position +static bool buffered_file_stream_flush(BufferedFileStream* stream) { + bool success = false; + do { + const int32_t offset = stream_cache_size(stream->cache) - stream_cache_pos(stream->cache); + if(!stream_cache_flush(stream->cache, stream->file_stream)) break; + if(offset > 0) { + if(!stream_seek(stream->file_stream, -offset, StreamOffsetFromCurrent)) break; + } + success = true; + } while(false); + stream->sync_pending = false; + return success; } // Drop read cache and adjust the underlying stream seek position static bool buffered_file_stream_unread(BufferedFileStream* stream) { bool success = true; const size_t cache_size = stream_cache_size(stream->cache); - const size_t cache_pos = stream_cache_pos(stream->cache); - if(cache_pos < cache_size) { - const int32_t offset = cache_size - cache_pos; - success = stream_seek(stream->file_stream, -offset, StreamOffsetFromCurrent); + if(cache_size > 0) { + const size_t cache_pos = stream_cache_pos(stream->cache); + if(cache_pos < cache_size) { + const int32_t offset = cache_size - cache_pos; + success = stream_seek(stream->file_stream, -offset, StreamOffsetFromCurrent); + } + stream_cache_drop(stream->cache); } - stream_cache_drop(stream->cache); return success; } diff --git a/lib/toolbox/stream/buffered_file_stream.h b/lib/toolbox/stream/buffered_file_stream.h index e6ad72091..54917b6a4 100644 --- a/lib/toolbox/stream/buffered_file_stream.h +++ b/lib/toolbox/stream/buffered_file_stream.h @@ -19,7 +19,7 @@ Stream* buffered_file_stream_alloc(Storage* storage); * @param path path to file * @param access_mode access mode from FS_AccessMode * @param open_mode open mode from FS_OpenMode - * @return success flag. You need to close the file even if the open operation failed. + * @return True on success, False on failure. You need to close the file even if the open operation failed. */ bool buffered_file_stream_open( Stream* stream, @@ -29,12 +29,18 @@ bool buffered_file_stream_open( /** * Closes the file. - * @param stream - * @return true - * @return false + * @param stream pointer to file stream object. + * @return True on success, False on failure. */ bool buffered_file_stream_close(Stream* stream); +/** + * Forces write from cache to the underlying file. + * @param stream pointer to file stream object. + * @return True on success, False on failure. + */ +bool buffered_file_stream_sync(Stream* stream); + /** * Retrieves the error id from the file object * @param stream pointer to stream object. diff --git a/lib/toolbox/stream/stream_cache.c b/lib/toolbox/stream/stream_cache.c index 164ac466c..f5e147dfe 100644 --- a/lib/toolbox/stream/stream_cache.c +++ b/lib/toolbox/stream/stream_cache.c @@ -46,6 +46,14 @@ size_t stream_cache_fill(StreamCache* cache, Stream* stream) { return size_read; } +bool stream_cache_flush(StreamCache* cache, Stream* stream) { + const size_t size_written = stream_write(stream, cache->data, cache->data_size); + const bool success = (size_written == cache->data_size); + cache->data_size = 0; + cache->position = 0; + return success; +} + size_t stream_cache_read(StreamCache* cache, uint8_t* data, size_t size) { furi_assert(cache->data_size >= cache->position); const size_t size_read = MIN(size, cache->data_size - cache->position); @@ -56,6 +64,19 @@ size_t stream_cache_read(StreamCache* cache, uint8_t* data, size_t size) { return size_read; } +size_t stream_cache_write(StreamCache* cache, const uint8_t* data, size_t size) { + furi_assert(cache->data_size >= cache->position); + const size_t size_written = MIN(size, STREAM_CACHE_MAX_SIZE - cache->position); + if(size_written > 0) { + memcpy(cache->data + cache->position, data, size_written); + cache->position += size_written; + if(cache->position > cache->data_size) { + cache->data_size = cache->position; + } + } + return size_written; +} + int32_t stream_cache_seek(StreamCache* cache, int32_t offset) { furi_assert(cache->data_size >= cache->position); int32_t actual_offset = 0; @@ -63,7 +84,7 @@ int32_t stream_cache_seek(StreamCache* cache, int32_t offset) { if(offset > 0) { actual_offset = MIN(cache->data_size - cache->position, (size_t)offset); } else if(offset < 0) { - actual_offset = -MIN(cache->position, (size_t)abs(offset)); + actual_offset = MAX(-((int32_t)cache->position), offset); } cache->position += actual_offset; diff --git a/lib/toolbox/stream/stream_cache.h b/lib/toolbox/stream/stream_cache.h index 20c18d802..f61e5e8f2 100644 --- a/lib/toolbox/stream/stream_cache.h +++ b/lib/toolbox/stream/stream_cache.h @@ -55,6 +55,14 @@ size_t stream_cache_pos(StreamCache* cache); */ size_t stream_cache_fill(StreamCache* cache, Stream* stream); +/** + * Write as much cached data as possible to a stream. + * @param cache Pointer to a StreamCache instance + * @param stream Pointer to a Stream instance + * @return True on success, False on failure. + */ +bool stream_cache_flush(StreamCache* cache, Stream* stream); + /** * Read cached data and advance the internal cursor. * @param cache Pointer to a StreamCache instance. @@ -64,6 +72,15 @@ size_t stream_cache_fill(StreamCache* cache, Stream* stream); */ size_t stream_cache_read(StreamCache* cache, uint8_t* data, size_t size); +/** + * Write to cached data and advance the internal cursor. + * @param cache Pointer to a StreamCache instance. + * @param data Pointer to a data buffer. + * @param size Maximum size in bytes to write to the cache. + * @return Actual size that was written. + */ +size_t stream_cache_write(StreamCache* cache, const uint8_t* data, size_t size); + /** * Move the internal cursor relatively to its current position. * @param cache Pointer to a StreamCache instance. From 284c56718bf808f8346a2e48fd26a9d8ee865e9d Mon Sep 17 00:00:00 2001 From: Ryan Murphy <57873842+fork-bombed@users.noreply.github.com> Date: Wed, 3 Aug 2022 18:00:17 +0100 Subject: [PATCH 17/22] NFC: Edit UID feature (#1513) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added option to edit UID in saved NFC files * Fixed bug with saved filename * Only show for data that can't be read Co-authored-by: あく --- applications/nfc/scenes/nfc_scene_saved_menu.c | 12 ++++++++++++ applications/nfc/scenes/nfc_scene_set_uid.c | 12 ++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/nfc/scenes/nfc_scene_saved_menu.c index 7c390f0b9..e6b08e71b 100644 --- a/applications/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/nfc/scenes/nfc_scene_saved_menu.c @@ -2,6 +2,7 @@ enum SubmenuIndex { SubmenuIndexEmulate, + SubmenuIndexEditUid, SubmenuIndexRename, SubmenuIndexDelete, SubmenuIndexInfo, @@ -27,6 +28,14 @@ void nfc_scene_saved_menu_on_enter(void* context) { SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc); + if(nfc->dev->dev_data.protocol == NfcDeviceProtocolUnknown) { + submenu_add_item( + submenu, + "Edit UID", + SubmenuIndexEditUid, + nfc_scene_saved_menu_submenu_callback, + nfc); + } } else if( nfc->dev->format == NfcDeviceSaveFormatMifareUl || nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { @@ -71,6 +80,9 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { } else if(event.event == SubmenuIndexRename) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); consumed = true; + } else if(event.event == SubmenuIndexEditUid) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid); + consumed = true; } else if(event.event == SubmenuIndexDelete) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete); consumed = true; diff --git a/applications/nfc/scenes/nfc_scene_set_uid.c b/applications/nfc/scenes/nfc_scene_set_uid.c index 6fe807ced..0ff289710 100755 --- a/applications/nfc/scenes/nfc_scene_set_uid.c +++ b/applications/nfc/scenes/nfc_scene_set_uid.c @@ -31,8 +31,16 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { DOLPHIN_DEED(DolphinDeedNfcAdd); - scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); - consumed = true; + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) { + nfc->dev->dev_data.nfc_data = nfc->dev_edit_data; + if(nfc_device_save(nfc->dev, nfc->dev->dev_name)) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); + consumed = true; + } + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + consumed = true; + } } } return consumed; From 3ee93e1a820fa0401b4de49de0e1050b83e53399 Mon Sep 17 00:00:00 2001 From: Fedor Indutny <238531+indutny@users.noreply.github.com> Date: Wed, 3 Aug 2022 10:07:35 -0700 Subject: [PATCH 18/22] nfc: make dict attack more interactive (#1462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc: deduplify dict attack worker code * nfc: make dict attack more interactive Co-authored-by: gornekich Co-authored-by: あく --- .../scenes/nfc_scene_mf_classic_dict_attack.c | 41 +++++++++++++++++-- applications/nfc/views/dict_attack.c | 37 ++++++++++++++++- applications/nfc/views/dict_attack.h | 4 ++ lib/nfc/nfc_device.h | 11 ++++- lib/nfc/nfc_worker.c | 35 ++++++++-------- lib/nfc/nfc_worker.h | 4 +- lib/nfc/nfc_worker_i.h | 3 +- 7 files changed, 107 insertions(+), 28 deletions(-) diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index 0736f0f16..d821c182d 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -1,5 +1,7 @@ #include "../nfc_i.h" +#define TAG "NfcMfClassicDictAttack" + typedef enum { DictAttackStateIdle, DictAttackStateUserDictInProgress, @@ -32,7 +34,9 @@ static void nfc_scene_mf_classic_dict_attack_update_view(Nfc* nfc) { static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackState state) { MfClassicData* data = &nfc->dev->dev_data.mf_classic_data; + NfcMfClassicDictAttackData* dict_attack_data = &nfc->dev->dev_data.mf_classic_dict_attack_data; NfcWorkerState worker_state = NfcWorkerStateReady; + MfClassicDict* dict = NULL; // Identify scene state if(state == DictAttackStateIdle) { @@ -47,16 +51,36 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt // Setup view if(state == DictAttackStateUserDictInProgress) { - worker_state = NfcWorkerStateMfClassicUserDictAttack; + worker_state = NfcWorkerStateMfClassicDictAttack; dict_attack_set_header(nfc->dict_attack, "Mf Classic User Dict."); - } else if(state == DictAttackStateFlipperDictInProgress) { - worker_state = NfcWorkerStateMfClassicFlipperDictAttack; - dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict."); + dict = mf_classic_dict_alloc(MfClassicDictTypeUser); + + // If failed to load user dictionary - try flipper dictionary + if(!dict) { + FURI_LOG_E(TAG, "User dictionary not found"); + state = DictAttackStateFlipperDictInProgress; + } } + if(state == DictAttackStateFlipperDictInProgress) { + worker_state = NfcWorkerStateMfClassicDictAttack; + dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict."); + dict = mf_classic_dict_alloc(MfClassicDictTypeFlipper); + if(!dict) { + FURI_LOG_E(TAG, "Flipper dictionary not found"); + // Pass through to let worker handle the failure + } + } + // Free previous dictionary + if(dict_attack_data->dict) { + mf_classic_dict_free(dict_attack_data->dict); + } + dict_attack_data->dict = dict; scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfClassicDictAttack, state); dict_attack_set_callback(nfc->dict_attack, nfc_dict_attack_dict_attack_result_callback, nfc); dict_attack_set_current_sector(nfc->dict_attack, 0); dict_attack_set_card_detected(nfc->dict_attack, data->type); + dict_attack_set_total_dict_keys( + nfc->dict_attack, dict ? mf_classic_dict_get_total_keys(dict) : 0); nfc_scene_mf_classic_dict_attack_update_view(nfc); nfc_worker_start( nfc->worker, worker_state, &nfc->dev->dev_data, nfc_dict_attack_worker_callback, nfc); @@ -112,6 +136,10 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent nfc_scene_mf_classic_dict_attack_update_view(nfc); dict_attack_inc_current_sector(nfc->dict_attack); consumed = true; + } else if(event.event == NfcWorkerEventNewDictKeyBatch) { + nfc_scene_mf_classic_dict_attack_update_view(nfc); + dict_attack_inc_current_dict_key(nfc->dict_attack, NFC_DICT_KEY_BATCH_SIZE); + consumed = true; } else if(event.event == NfcCustomEventDictAttackSkip) { if(state == DictAttackStateUserDictInProgress) { nfc_worker_stop(nfc->worker); @@ -130,8 +158,13 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { Nfc* nfc = context; + NfcMfClassicDictAttackData* dict_attack_data = &nfc->dev->dev_data.mf_classic_dict_attack_data; // Stop worker nfc_worker_stop(nfc->worker); + if(dict_attack_data->dict) { + mf_classic_dict_free(dict_attack_data->dict); + dict_attack_data->dict = NULL; + } dict_attack_reset(nfc->dict_attack); nfc_blink_stop(nfc); } diff --git a/applications/nfc/views/dict_attack.c b/applications/nfc/views/dict_attack.c index 256900059..b4674fd31 100644 --- a/applications/nfc/views/dict_attack.c +++ b/applications/nfc/views/dict_attack.c @@ -23,6 +23,8 @@ typedef struct { uint8_t sector_current; uint8_t keys_total; uint8_t keys_found; + uint16_t dict_keys_total; + uint16_t dict_keys_current; } DictAttackViewModel; static void dict_attack_draw_callback(Canvas* canvas, void* model) { @@ -38,8 +40,15 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { canvas_set_font(canvas, FontPrimary); canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, string_get_cstr(m->header)); canvas_set_font(canvas, FontSecondary); - float progress = - m->sectors_total == 0 ? 0 : (float)(m->sector_current) / (float)(m->sectors_total); + float dict_progress = m->dict_keys_total == 0 ? + 0 : + (float)(m->dict_keys_current) / (float)(m->dict_keys_total); + float progress = m->sectors_total == 0 ? 0 : + ((float)(m->sector_current) + dict_progress) / + (float)(m->sectors_total); + if(progress > 1.0) { + progress = 1.0; + } elements_progress_bar(canvas, 5, 15, 120, progress); canvas_set_font(canvas, FontSecondary); snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total); @@ -100,6 +109,8 @@ void dict_attack_reset(DictAttack* dict_attack) { model->sector_current = 0; model->keys_total = 0; model->keys_found = 0; + model->dict_keys_total = 0; + model->dict_keys_current = 0; string_reset(model->header); return false; }); @@ -171,6 +182,7 @@ void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec) { with_view_model( dict_attack->view, (DictAttackViewModel * model) { model->sector_current = curr_sec; + model->dict_keys_current = 0; return true; }); } @@ -181,6 +193,7 @@ void dict_attack_inc_current_sector(DictAttack* dict_attack) { dict_attack->view, (DictAttackViewModel * model) { if(model->sector_current < model->sectors_total) { model->sector_current++; + model->dict_keys_current = 0; } return true; }); @@ -196,3 +209,23 @@ void dict_attack_inc_keys_found(DictAttack* dict_attack) { return true; }); } + +void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total) { + furi_assert(dict_attack); + with_view_model( + dict_attack->view, (DictAttackViewModel * model) { + model->dict_keys_total = dict_keys_total; + return true; + }); +} + +void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried) { + furi_assert(dict_attack); + with_view_model( + dict_attack->view, (DictAttackViewModel * model) { + if(model->dict_keys_current + keys_tried < model->dict_keys_total) { + model->dict_keys_current += keys_tried; + } + return true; + }); +} diff --git a/applications/nfc/views/dict_attack.h b/applications/nfc/views/dict_attack.h index 3f557b19c..684f17f06 100644 --- a/applications/nfc/views/dict_attack.h +++ b/applications/nfc/views/dict_attack.h @@ -34,3 +34,7 @@ void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec); void dict_attack_inc_current_sector(DictAttack* dict_attack); void dict_attack_inc_keys_found(DictAttack* dict_attack); + +void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total); + +void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried); diff --git a/lib/nfc/nfc_device.h b/lib/nfc/nfc_device.h index e1ff6d42f..f9a0b24ba 100644 --- a/lib/nfc/nfc_device.h +++ b/lib/nfc/nfc_device.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #define NFC_DEV_NAME_MAX_LEN 22 #define NFC_READER_DATA_MAX_SIZE 64 +#define NFC_DICT_KEY_BATCH_SIZE 50 #define NFC_APP_FOLDER ANY_PATH("nfc") #define NFC_APP_EXTENSION ".nfc" @@ -41,10 +43,17 @@ typedef struct { uint16_t size; } NfcReaderRequestData; +typedef struct { + MfClassicDict* dict; +} NfcMfClassicDictAttackData; + typedef struct { FuriHalNfcDevData nfc_data; NfcProtocol protocol; - NfcReaderRequestData reader_data; + union { + NfcReaderRequestData reader_data; + NfcMfClassicDictAttackData mf_classic_dict_attack_data; + }; union { EmvData emv_data; MfUltralightData mf_ul_data; diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 3a45c3634..7c3c083b1 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -101,10 +101,8 @@ int32_t nfc_worker_task(void* context) { nfc_worker_emulate_mf_ultralight(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { nfc_worker_emulate_mf_classic(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) { - nfc_worker_mf_classic_dict_attack(nfc_worker, MfClassicDictTypeUser); - } else if(nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack) { - nfc_worker_mf_classic_dict_attack(nfc_worker, MfClassicDictTypeFlipper); + } else if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) { + nfc_worker_mf_classic_dict_attack(nfc_worker); } furi_hal_nfc_sleep(); nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); @@ -397,11 +395,13 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { } } -void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType type) { +void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { furi_assert(nfc_worker); furi_assert(nfc_worker->callback); MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; + NfcMfClassicDictAttackData* dict_attack_data = + &nfc_worker->dev_data->mf_classic_dict_attack_data; uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type); uint64_t key = 0; FuriHalNfcTxRxContext tx_rx = {}; @@ -409,15 +409,17 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType bool card_removed_notified = false; // Load dictionary - MfClassicDict* dict = mf_classic_dict_alloc(type); + MfClassicDict* dict = dict_attack_data->dict; if(!dict) { FURI_LOG_E(TAG, "Dictionary not found"); nfc_worker->callback(NfcWorkerEventNoDictFound, nfc_worker->context); - mf_classic_dict_free(dict); return; } - FURI_LOG_D(TAG, "Start Dictionary attack"); + FURI_LOG_D( + TAG, + "Start Dictionary attack, Key Count %d", + mf_classic_dict_get_total_keys(dict)); for(size_t i = 0; i < total_sectors; i++) { FURI_LOG_I(TAG, "Sector %d", i); nfc_worker->callback(NfcWorkerEventNewSector, nfc_worker->context); @@ -425,7 +427,11 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType if(mf_classic_is_sector_read(data, i)) continue; bool is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA); bool is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); + uint16_t key_index = 0; while(mf_classic_dict_get_next_key(dict, &key)) { + if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) { + nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context); + } furi_hal_nfc_sleep(); if(furi_hal_nfc_activate_nfca(200, NULL)) { furi_hal_nfc_sleep(); @@ -456,8 +462,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType } } if(is_key_a_found && is_key_b_found) break; - if(!((nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) || - (nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack))) + if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; } else { if(!card_removed_notified) { @@ -465,20 +470,16 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType card_removed_notified = true; card_found_notified = false; } - if(!((nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) || - (nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack))) + if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; } } - if(!((nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) || - (nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack))) + if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; mf_classic_read_sector(&tx_rx, data, i); mf_classic_dict_rewind(dict); } - mf_classic_dict_free(dict); - if((nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) || - (nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack)) { + if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) { nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); } else { nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context); diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index f6df406bf..a3326808b 100755 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -14,8 +14,7 @@ typedef enum { NfcWorkerStateUidEmulate, NfcWorkerStateMfUltralightEmulate, NfcWorkerStateMfClassicEmulate, - NfcWorkerStateMfClassicUserDictAttack, - NfcWorkerStateMfClassicFlipperDictAttack, + NfcWorkerStateMfClassicDictAttack, // Debug NfcWorkerStateEmulateApdu, NfcWorkerStateField, @@ -49,6 +48,7 @@ typedef enum { // Mifare Classic events NfcWorkerEventNoDictFound, NfcWorkerEventNewSector, + NfcWorkerEventNewDictKeyBatch, NfcWorkerEventFoundKeyA, NfcWorkerEventFoundKeyB, } NfcWorkerEvent; diff --git a/lib/nfc/nfc_worker_i.h b/lib/nfc/nfc_worker_i.h index f19f58d50..bb4c31ddb 100644 --- a/lib/nfc/nfc_worker_i.h +++ b/lib/nfc/nfc_worker_i.h @@ -13,7 +13,6 @@ #include #include -#include "helpers/mf_classic_dict.h" #include "helpers/nfc_debug_pcap.h" struct NfcWorker { @@ -43,6 +42,6 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker); void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker); -void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType type); +void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker); void nfc_worker_emulate_apdu(NfcWorker* nfc_worker); From 4c499d9045d0cda866b1820c731c63df3fb47092 Mon Sep 17 00:00:00 2001 From: HexPandaa <47880094+HexPandaa@users.noreply.github.com> Date: Wed, 3 Aug 2022 19:13:06 +0200 Subject: [PATCH 19/22] Fix directory name in lib readme (#1528) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- lib/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ReadMe.md b/lib/ReadMe.md index 0bdf3d63a..9cd846a0a 100644 --- a/lib/ReadMe.md +++ b/lib/ReadMe.md @@ -15,7 +15,7 @@ - `microtar` - TAR archive support library - `mlib` - Algorithms and containers - `nanopb` - Nano Protobuf library -- `nfc_protocols` - Nfc protocols library +- `nfc` - Nfc library - `one_wire` - One wire library - `qrcode` - Qr code generator library - `ST25RFAL002` - ST253916 driver and NFC hal From 4460010e76fba3626e0ef2c7e3e5c8149dda25c3 Mon Sep 17 00:00:00 2001 From: SG Date: Thu, 4 Aug 2022 14:34:04 +1000 Subject: [PATCH 20/22] Archive: fix null dereference #1531 (#1532) --- applications/archive/scenes/archive_scene_browser.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/applications/archive/scenes/archive_scene_browser.c b/applications/archive/scenes/archive_scene_browser.c index 74861beab..e22ac792f 100644 --- a/applications/archive/scenes/archive_scene_browser.c +++ b/applications/archive/scenes/archive_scene_browser.c @@ -92,8 +92,6 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { ArchiveBrowserView* browser = archive->browser; ArchiveFile_t* selected = archive_get_current_file(browser); - const char* name = archive_get_name(browser); - bool known_app = archive_is_known_app(selected->type); bool favorites = archive_get_tab(browser) == ArchiveTabFavorites; bool consumed = false; @@ -108,18 +106,19 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case ArchiveBrowserEventFileMenuRun: - if(known_app) { + if(archive_is_known_app(selected->type)) { archive_run_in_app(browser, selected); archive_show_file_menu(browser, false); } consumed = true; break; - case ArchiveBrowserEventFileMenuPin: + case ArchiveBrowserEventFileMenuPin: { + const char* name = archive_get_name(browser); if(favorites) { archive_favorites_delete(name); archive_file_array_rm_selected(browser); archive_show_file_menu(browser, false); - } else if(known_app) { + } else if(archive_is_known_app(selected->type)) { if(archive_is_favorite("%s", name)) { archive_favorites_delete("%s", name); } else { @@ -128,12 +127,12 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { archive_show_file_menu(browser, false); } consumed = true; - break; + } break; case ArchiveBrowserEventFileMenuRename: if(favorites) { browser->callback(ArchiveBrowserEventEnterFavMove, browser->context); - } else if((known_app) && (selected->is_app == false)) { + } else if((archive_is_known_app(selected->type)) && (selected->is_app == false)) { archive_show_file_menu(browser, false); scene_manager_set_scene_state( archive->scene_manager, ArchiveAppSceneBrowser, SCENE_STATE_NEED_REFRESH); From 8a370d70dc15ee90892d55232e9a3709c39cf8b6 Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Thu, 4 Aug 2022 15:11:01 +0300 Subject: [PATCH 21/22] [FL-2700] Fix IR hangup with short signals (#1535) * Do not use infrared worker callback for notifications * Remove tx callback * Port Infrared notifications to hardware blinker * Move all blink message definitions to notification_messages.h * Fix potential hangup after leaving debug scene --- applications/ibutton/ibutton.c | 19 -------- applications/infrared/infrared.c | 18 +++---- applications/infrared/infrared_i.h | 6 +-- .../common/infrared_scene_universal_common.c | 5 +- .../infrared/scenes/infrared_scene_debug.c | 1 + .../infrared/scenes/infrared_scene_learn.c | 7 ++- .../scenes/infrared_scene_learn_success.c | 7 +-- .../infrared/scenes/infrared_scene_remote.c | 4 +- .../infrared/scenes/infrared_scene_rpc.c | 3 +- .../lfrfid/scene/lfrfid_app_scene_emulate.cpp | 12 ----- .../lfrfid/scene/lfrfid_app_scene_rpc.cpp | 12 ----- applications/nfc/nfc.c | 12 ----- .../notification/notification_messages.c | 48 +++++++++++++++++++ .../notification/notification_messages.h | 9 ++++ applications/subghz/subghz.c | 12 ----- 15 files changed, 81 insertions(+), 94 deletions(-) diff --git a/applications/ibutton/ibutton.c b/applications/ibutton/ibutton.c index 6f690fce7..304c057a7 100644 --- a/applications/ibutton/ibutton.c +++ b/applications/ibutton/ibutton.c @@ -9,20 +9,6 @@ #define TAG "iButtonApp" -static const NotificationSequence sequence_blink_start_cyan = { - &message_blink_start_10, - &message_blink_set_color_cyan, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence sequence_blink_start_magenta = { - &message_blink_start_10, - &message_blink_set_color_magenta, - &message_do_not_reset, - NULL, -}; - static const NotificationSequence sequence_blink_set_yellow = { &message_blink_set_color_yellow, NULL, @@ -33,11 +19,6 @@ static const NotificationSequence sequence_blink_set_magenta = { NULL, }; -static const NotificationSequence sequence_blink_stop = { - &message_blink_stop, - NULL, -}; - static const NotificationSequence* ibutton_notification_sequences[] = { &sequence_error, &sequence_success, diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c index ddeaeecf3..aef14f9b8 100644 --- a/applications/infrared/infrared.c +++ b/applications/infrared/infrared.c @@ -7,10 +7,12 @@ static const NotificationSequence* infrared_notification_sequences[] = { &sequence_success, &sequence_set_only_green_255, &sequence_reset_green, - &sequence_blink_cyan_10, - &sequence_blink_magenta_10, &sequence_solid_yellow, - &sequence_reset_rgb}; + &sequence_reset_rgb, + &sequence_blink_start_cyan, + &sequence_blink_start_magenta, + &sequence_blink_stop, +}; static void infrared_make_app_folder(Infrared* infrared) { if(!storage_simply_mkdir(infrared->storage, INFRARED_APP_FOLDER)) { @@ -301,6 +303,7 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { DOLPHIN_DEED(DolphinDeedIrSend); infrared_worker_tx_start(infrared->worker); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend); } void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) { @@ -310,14 +313,17 @@ void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) { InfraredSignal* signal = infrared_remote_button_get_signal(button); infrared_tx_start_signal(infrared, signal); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend); } void infrared_tx_start_received(Infrared* infrared) { infrared_tx_start_signal(infrared, infrared->received_signal); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend); } void infrared_tx_stop(Infrared* infrared) { infrared_worker_tx_stop(infrared->worker); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); } void infrared_text_store_set(Infrared* infrared, uint32_t bank, const char* text, ...) { @@ -354,12 +360,6 @@ void infrared_show_loading_popup(Infrared* infrared, bool show) { } } -void infrared_signal_sent_callback(void* context) { - furi_assert(context); - Infrared* infrared = context; - infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkSend); -} - void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal) { furi_assert(context); Infrared* infrared = context; diff --git a/applications/infrared/infrared_i.h b/applications/infrared/infrared_i.h index d24cab064..4e9c79d51 100644 --- a/applications/infrared/infrared_i.h +++ b/applications/infrared/infrared_i.h @@ -115,10 +115,11 @@ typedef enum { InfraredNotificationMessageSuccess, InfraredNotificationMessageGreenOn, InfraredNotificationMessageGreenOff, - InfraredNotificationMessageBlinkRead, - InfraredNotificationMessageBlinkSend, InfraredNotificationMessageYellowOn, InfraredNotificationMessageYellowOff, + InfraredNotificationMessageBlinkStartRead, + InfraredNotificationMessageBlinkStartSend, + InfraredNotificationMessageBlinkStop, } InfraredNotificationMessage; bool infrared_add_remote_with_button(Infrared* infrared, const char* name, InfraredSignal* signal); @@ -132,7 +133,6 @@ void infrared_text_store_clear(Infrared* infrared, uint32_t bank); void infrared_play_notification_message(Infrared* infrared, uint32_t message); void infrared_show_loading_popup(Infrared* infrared, bool show); -void infrared_signal_sent_callback(void* context); void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal); void infrared_text_input_callback(void* context); void infrared_popup_closed_callback(void* context); diff --git a/applications/infrared/scenes/common/infrared_scene_universal_common.c b/applications/infrared/scenes/common/infrared_scene_universal_common.c index 7eff81eec..57ac81168 100644 --- a/applications/infrared/scenes/common/infrared_scene_universal_common.c +++ b/applications/infrared/scenes/common/infrared_scene_universal_common.c @@ -21,12 +21,14 @@ static void infrared_scene_universal_common_show_popup(Infrared* infrared, uint3 infrared_progress_view_set_back_callback( progress, infrared_scene_universal_common_progress_back_callback, infrared); view_stack_add_view(view_stack, infrared_progress_view_get_view(progress)); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend); } static void infrared_scene_universal_common_hide_popup(Infrared* infrared) { ViewStack* view_stack = infrared->view_stack; InfraredProgressView* progress = infrared->progress; view_stack_remove_view(view_stack, infrared_progress_view_get_view(progress)); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); } void infrared_scene_universal_common_on_enter(void* context) { @@ -42,7 +44,6 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e if(infrared_brute_force_is_started(brute_force)) { if(event.type == SceneManagerEventTypeTick) { - infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkSend); bool success = infrared_brute_force_send_next(brute_force); if(success) { success = infrared_progress_view_increase_progress(infrared->progress); @@ -71,8 +72,6 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e brute_force, infrared_custom_event_get_value(event.event), &record_count)) { DOLPHIN_DEED(DolphinDeedIrBruteForce); infrared_scene_universal_common_show_popup(infrared, record_count); - infrared_play_notification_message( - infrared, InfraredNotificationMessageBlinkSend); } else { scene_manager_next_scene(scene_manager, InfraredSceneErrorDatabases); } diff --git a/applications/infrared/scenes/infrared_scene_debug.c b/applications/infrared/scenes/infrared_scene_debug.c index ddb85644b..dd0609b56 100644 --- a/applications/infrared/scenes/infrared_scene_debug.c +++ b/applications/infrared/scenes/infrared_scene_debug.c @@ -65,4 +65,5 @@ void infrared_scene_debug_on_exit(void* context) { InfraredWorker* worker = infrared->worker; infrared_worker_rx_stop(worker); infrared_worker_rx_enable_blink_on_receiving(worker, false); + infrared_worker_rx_set_received_signal_callback(worker, NULL, NULL); } diff --git a/applications/infrared/scenes/infrared_scene_learn.c b/applications/infrared/scenes/infrared_scene_learn.c index d91b8676a..0edb74ca2 100644 --- a/applications/infrared/scenes/infrared_scene_learn.c +++ b/applications/infrared/scenes/infrared_scene_learn.c @@ -8,6 +8,7 @@ void infrared_scene_learn_on_enter(void* context) { infrared_worker_rx_set_received_signal_callback( worker, infrared_signal_received_callback, context); infrared_worker_rx_start(worker); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartRead); popup_set_icon(popup, 0, 32, &I_InfraredLearnShort_128x31); popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignCenter); @@ -22,10 +23,7 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) { Infrared* infrared = context; bool consumed = false; - if(event.type == SceneManagerEventTypeTick) { - infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkRead); - consumed = true; - } else if(event.type == SceneManagerEventTypeCustom) { + if(event.type == SceneManagerEventTypeCustom) { if(event.event == InfraredCustomEventTypeSignalReceived) { infrared_worker_rx_set_received_signal_callback(infrared->worker, NULL, NULL); infrared_play_notification_message(infrared, InfraredNotificationMessageSuccess); @@ -41,6 +39,7 @@ void infrared_scene_learn_on_exit(void* context) { Infrared* infrared = context; Popup* popup = infrared->popup; infrared_worker_rx_stop(infrared->worker); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); popup_set_icon(popup, 0, 0, NULL); popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignCenter); } diff --git a/applications/infrared/scenes/infrared_scene_learn_success.c b/applications/infrared/scenes/infrared_scene_learn_success.c index 1297ebcf9..49e2f45f0 100644 --- a/applications/infrared/scenes/infrared_scene_learn_success.c +++ b/applications/infrared/scenes/infrared_scene_learn_success.c @@ -23,8 +23,6 @@ void infrared_scene_learn_success_on_enter(void* context) { infrared_worker_tx_set_get_signal_callback( infrared->worker, infrared_worker_tx_get_signal_steady_callback, context); - infrared_worker_tx_set_signal_sent_callback( - infrared->worker, infrared_signal_sent_callback, context); if(infrared_signal_is_raw(signal)) { InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); @@ -104,6 +102,8 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateSending); infrared_tx_start_received(infrared); + infrared_play_notification_message( + infrared, InfraredNotificationMessageBlinkStartSend); } consumed = true; } else if(event.event == DialogExReleaseCenter) { @@ -111,6 +111,7 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even scene_manager_set_scene_state( scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle); infrared_tx_stop(infrared); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); } consumed = true; @@ -124,7 +125,7 @@ void infrared_scene_learn_success_on_exit(void* context) { Infrared* infrared = context; InfraredWorker* worker = infrared->worker; dialog_ex_reset(infrared->dialog_ex); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); infrared_worker_tx_set_get_signal_callback(worker, NULL, NULL); - infrared_worker_tx_set_signal_sent_callback(worker, NULL, NULL); } diff --git a/applications/infrared/scenes/infrared_scene_remote.c b/applications/infrared/scenes/infrared_scene_remote.c index 50f714889..3cd5a9aa4 100644 --- a/applications/infrared/scenes/infrared_scene_remote.c +++ b/applications/infrared/scenes/infrared_scene_remote.c @@ -33,8 +33,6 @@ void infrared_scene_remote_on_enter(void* context) { infrared_worker_tx_set_get_signal_callback( infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); - infrared_worker_tx_set_signal_sent_callback( - infrared->worker, infrared_signal_sent_callback, infrared); size_t button_count = infrared_remote_get_button_count(remote); for(size_t i = 0; i < button_count; ++i) { @@ -112,7 +110,7 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { void infrared_scene_remote_on_exit(void* context) { Infrared* infrared = context; + infrared_tx_stop(infrared); infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL); - infrared_worker_tx_set_signal_sent_callback(infrared->worker, NULL, NULL); button_menu_reset(infrared->button_menu); } diff --git a/applications/infrared/scenes/infrared_scene_rpc.c b/applications/infrared/scenes/infrared_scene_rpc.c index 1d970f6a8..bc9c8652f 100644 --- a/applications/infrared/scenes/infrared_scene_rpc.c +++ b/applications/infrared/scenes/infrared_scene_rpc.c @@ -36,8 +36,6 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { result = infrared_remote_load(infrared->remote, infrared->file_path); infrared_worker_tx_set_get_signal_callback( infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); - infrared_worker_tx_set_signal_sent_callback( - infrared->worker, infrared_signal_sent_callback, infrared); } const char* remote_name = infrared_remote_get_name(infrared->remote); @@ -74,5 +72,6 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { void infrared_scene_rpc_on_exit(void* context) { Infrared* infrared = context; + infrared_tx_stop(infrared); popup_reset(infrared->popup); } diff --git a/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp b/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp index 183361a0b..cad4f17c7 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp @@ -2,18 +2,6 @@ #include #include -static const NotificationSequence sequence_blink_start_magenta = { - &message_blink_start_10, - &message_blink_set_color_magenta, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence sequence_blink_stop = { - &message_blink_stop, - NULL, -}; - void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool /* need_restore */) { string_init(data_string); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp index a32982afb..43b236286 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp @@ -3,18 +3,6 @@ #include #include -static const NotificationSequence sequence_blink_start_magenta = { - &message_blink_start_10, - &message_blink_set_color_magenta, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence sequence_blink_stop = { - &message_blink_stop, - NULL, -}; - void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) { auto popup = app->view_controller.get(); diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index 93645cc13..9d32e8713 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -199,18 +199,6 @@ void nfc_text_store_clear(Nfc* nfc) { memset(nfc->text_store, 0, sizeof(nfc->text_store)); } -static const NotificationSequence sequence_blink_start_blue = { - &message_blink_start_10, - &message_blink_set_color_blue, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence sequence_blink_stop = { - &message_blink_stop, - NULL, -}; - void nfc_blink_start(Nfc* nfc) { notification_message(nfc->notifications, &sequence_blink_start_blue); } diff --git a/applications/notification/notification_messages.c b/applications/notification/notification_messages.c index b469cb5f1..d795c55d9 100644 --- a/applications/notification/notification_messages.c +++ b/applications/notification/notification_messages.c @@ -431,6 +431,54 @@ const NotificationSequence sequence_blink_white_100 = { NULL, }; +// Hardware blink +const NotificationSequence sequence_blink_start_blue = { + &message_blink_start_10, + &message_blink_set_color_blue, + &message_do_not_reset, + NULL, +}; + +const NotificationSequence sequence_blink_start_red = { + &message_blink_start_10, + &message_blink_set_color_red, + &message_do_not_reset, + NULL, +}; + +const NotificationSequence sequence_blink_start_green = { + &message_blink_start_10, + &message_blink_set_color_green, + &message_do_not_reset, + NULL, +}; + +const NotificationSequence sequence_blink_start_yellow = { + &message_blink_start_10, + &message_blink_set_color_yellow, + &message_do_not_reset, + NULL, +}; + +const NotificationSequence sequence_blink_start_cyan = { + &message_blink_start_10, + &message_blink_set_color_cyan, + &message_do_not_reset, + NULL, +}; + +const NotificationSequence sequence_blink_start_magenta = { + &message_blink_start_10, + &message_blink_set_color_magenta, + &message_do_not_reset, + NULL, +}; + +const NotificationSequence sequence_blink_stop = { + &message_blink_stop, + NULL, +}; + //General const NotificationSequence sequence_single_vibro = { &message_vibro_on, diff --git a/applications/notification/notification_messages.h b/applications/notification/notification_messages.h index 92a105f6a..100796917 100644 --- a/applications/notification/notification_messages.h +++ b/applications/notification/notification_messages.h @@ -122,6 +122,15 @@ extern const NotificationSequence sequence_blink_cyan_100; extern const NotificationSequence sequence_blink_magenta_100; extern const NotificationSequence sequence_blink_white_100; +// Hardware blink +extern const NotificationSequence sequence_blink_start_blue; +extern const NotificationSequence sequence_blink_start_red; +extern const NotificationSequence sequence_blink_start_green; +extern const NotificationSequence sequence_blink_start_yellow; +extern const NotificationSequence sequence_blink_start_cyan; +extern const NotificationSequence sequence_blink_start_magenta; +extern const NotificationSequence sequence_blink_stop; + // General extern const NotificationSequence sequence_single_vibro; extern const NotificationSequence sequence_double_vibro; diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 6edcd96d2..3770d52c1 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -5,18 +5,6 @@ #include "subghz_i.h" #include -static const NotificationSequence sequence_blink_start_magenta = { - &message_blink_start_10, - &message_blink_set_color_magenta, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence sequence_blink_stop = { - &message_blink_stop, - NULL, -}; - bool subghz_custom_event_callback(void* context, uint32_t event) { furi_assert(context); SubGhz* subghz = context; From 040558c8f989aa36a50f86276f847dfb73cfa8e2 Mon Sep 17 00:00:00 2001 From: TQMatvey <77576395+TQMatvey@users.noreply.github.com> Date: Thu, 4 Aug 2022 19:18:34 +0700 Subject: [PATCH 22/22] PicoPass: Fix Card Detection Visuals (#1511) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/picopass/scenes/picopass_scene_read_card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/picopass/scenes/picopass_scene_read_card.c b/applications/picopass/scenes/picopass_scene_read_card.c index add05e479..0867898a5 100644 --- a/applications/picopass/scenes/picopass_scene_read_card.c +++ b/applications/picopass/scenes/picopass_scene_read_card.c @@ -13,7 +13,7 @@ void picopass_scene_read_card_on_enter(void* context) { // Setup view Popup* popup = picopass->popup; - popup_set_header(popup, "Detecting\npicopass card", 70, 34, AlignLeft, AlignTop); + popup_set_header(popup, "Detecting\npicopass\ncard", 68, 30, AlignLeft, AlignTop); popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); // Start worker