From add2497a1cfdee50ff1cb8c6e24ad4f23f4ad851 Mon Sep 17 00:00:00 2001 From: hedger Date: Thu, 11 Aug 2022 11:28:57 +0300 Subject: [PATCH 01/26] rpc: additional verification of message data (#1576) * rpc: additional verification of message data * rpc: storage: fixed read handler * acessor: fixed record naming --- applications/accessor/accessor_app.cpp | 4 +-- .../accessor/accessor_view_manager.cpp | 3 +- applications/rpc/rpc_storage.c | 31 +++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/applications/accessor/accessor_app.cpp b/applications/accessor/accessor_app.cpp index f021a816e59..2e3e27ec456 100644 --- a/applications/accessor/accessor_app.cpp +++ b/applications/accessor/accessor_app.cpp @@ -32,14 +32,14 @@ void AccessorApp::run(void) { } AccessorApp::AccessorApp() { - notification = static_cast(furi_record_open("notification")); + notification = static_cast(furi_record_open(RECORD_NOTIFICATION)); onewire_host = onewire_host_alloc(); furi_hal_power_enable_otg(); } AccessorApp::~AccessorApp() { furi_hal_power_disable_otg(); - furi_record_close("notification"); + furi_record_close(RECORD_NOTIFICATION); onewire_host_free(onewire_host); } diff --git a/applications/accessor/accessor_view_manager.cpp b/applications/accessor/accessor_view_manager.cpp index 7c681cbba95..db723d68c23 100644 --- a/applications/accessor/accessor_view_manager.cpp +++ b/applications/accessor/accessor_view_manager.cpp @@ -15,7 +15,7 @@ AccessorAppViewManager::AccessorAppViewManager() { popup = popup_alloc(); add_view(ViewType::Popup, popup_get_view(popup)); - gui = static_cast(furi_record_open("gui")); + gui = static_cast(furi_record_open(RECORD_GUI)); view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); // set previous view callback for all views @@ -31,6 +31,7 @@ AccessorAppViewManager::~AccessorAppViewManager() { view_dispatcher, static_cast(AccessorAppViewManager::ViewType::Popup)); // free view modules + furi_record_close(RECORD_GUI); submenu_free(submenu); popup_free(popup); diff --git a/applications/rpc/rpc_storage.c b/applications/rpc/rpc_storage.c index 48ea9e998d0..468e1e08e54 100644 --- a/applications/rpc/rpc_storage.c +++ b/applications/rpc/rpc_storage.c @@ -297,9 +297,9 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex const char* path = request->content.storage_read_request.path; Storage* fs_api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(fs_api); - bool result = false; + bool fs_operation_success = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING); - if(storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) { + if(fs_operation_success) { size_t size_left = storage_file_size(file); do { response->command_id = request->command_id; @@ -310,28 +310,25 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex if(read_size) { response->content.storage_read_response.has_file = true; response->content.storage_read_response.file.data = - malloc(PB_BYTES_ARRAY_T_ALLOCSIZE()); - uint8_t* buffer = response->content.storage_read_response.file.data->bytes; + malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(read_size)); + uint8_t* buffer = &response->content.storage_read_response.file.data->bytes[0]; uint16_t* read_size_msg = &response->content.storage_read_response.file.data->size; *read_size_msg = storage_file_read(file, buffer, read_size); - size_left -= read_size; - result = (*read_size_msg == read_size); + size_left -= *read_size_msg; + fs_operation_success = (*read_size_msg == read_size); - response->has_next = result && (size_left > 0); + response->has_next = fs_operation_success && (size_left > 0); } else { response->content.storage_read_response.has_file = false; response->has_next = false; - result = true; + fs_operation_success = true; } + } while((size_left != 0) && fs_operation_success); + } - rpc_send_and_release(session, response); - } while((size_left != 0) && result); - - if(!result) { - rpc_send_and_release_empty( - session, request->command_id, rpc_system_storage_get_file_error(file)); - } + if(fs_operation_success) { + rpc_send_and_release(session, response); } else { rpc_send_and_release_empty( session, request->command_id, rpc_system_storage_get_file_error(file)); @@ -384,7 +381,9 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte bool send_response = false; if(fs_operation_success) { - if(request->content.storage_write_request.has_file) { + if(request->content.storage_write_request.has_file && + request->content.storage_write_request.file.data && + request->content.storage_write_request.file.data->size) { uint8_t* buffer = request->content.storage_write_request.file.data->bytes; size_t buffer_size = request->content.storage_write_request.file.data->size; uint16_t written_size = storage_file_write(file, buffer, buffer_size); From fae392d84eaa3f50d78e8d1b7fc3b19ac6f3c3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Thu, 11 Aug 2022 18:21:56 +0900 Subject: [PATCH 02/26] [FL-2677] SubGhz: region provisioning (#1574) * FuriHal: region HAL draft * FuriHal,SubGhz: complete region provisioning. * Rpc: fix null pointer dereference. * Cli: device info formatting * FuriHal: region provisioning fixes and documentation. --- applications/cli/cli_commands.c | 2 +- applications/loader/application.fam | 2 +- applications/subghz/subghz_cli.c | 95 +++++++++++- applications/subghz/subghz_i.c | 2 +- assets/protobuf | 2 +- firmware/targets/f7/furi_hal/furi_hal.c | 1 + firmware/targets/f7/furi_hal/furi_hal_info.c | 8 +- .../targets/f7/furi_hal/furi_hal_region.c | 135 ++++++++++++++++++ .../targets/f7/furi_hal/furi_hal_subghz.c | 47 +----- firmware/targets/furi_hal_include/furi_hal.h | 1 + .../furi_hal_include/furi_hal_region.h | 73 ++++++++++ .../furi_hal_include/furi_hal_subghz.h | 8 -- lib/subghz/subghz_tx_rx_worker.c | 2 +- 13 files changed, 318 insertions(+), 60 deletions(-) create mode 100644 firmware/targets/f7/furi_hal/furi_hal_region.c create mode 100644 firmware/targets/furi_hal_include/furi_hal_region.h diff --git a/applications/cli/cli_commands.c b/applications/cli/cli_commands.c index 1988779624c..177a274a106 100644 --- a/applications/cli/cli_commands.c +++ b/applications/cli/cli_commands.c @@ -15,7 +15,7 @@ void cli_command_device_info_callback(const char* key, const char* value, bool last, void* context) { UNUSED(context); UNUSED(last); - printf("%-24s: %s\r\n", key, value); + printf("%-30s: %s\r\n", key, value); } /* diff --git a/applications/loader/application.fam b/applications/loader/application.fam index 16351f8d1cb..c1ba4e5490b 100644 --- a/applications/loader/application.fam +++ b/applications/loader/application.fam @@ -5,6 +5,6 @@ App( entry_point="loader_srv", cdefines=["SRV_LOADER"], requires=["gui"], - stack_size=1 * 1024, + stack_size=2 * 1024, order=90, ) diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index 2b6fdd841f3..09dae0481fa 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -16,9 +16,14 @@ #include #include +#include +#include + #define SUBGHZ_FREQUENCY_RANGE_STR \ "299999755...348000000 or 386999938...464000000 or 778999847...928000000" +#define SUBGHZ_REGION_FILENAME "/int/.region_data" + void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { UNUSED(context); uint32_t frequency = 433920000; @@ -533,7 +538,7 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { return; } } - if(!furi_hal_subghz_is_tx_allowed(frequency)) { + if(!furi_hal_region_is_frequency_allowed(frequency)) { printf( "In your region, only reception on this frequency (%lu) is allowed,\r\n" "the actual operation of the application is not possible\r\n ", @@ -756,6 +761,46 @@ static void subghz_cli_command(Cli* cli, string_t args, void* context) { string_clear(cmd); } +static bool + subghz_on_system_start_istream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { + File* file = istream->state; + uint16_t ret = storage_file_read(file, buf, count); + return (count == ret); +} + +static bool subghz_on_system_start_istream_decode_band( + pb_istream_t* stream, + const pb_field_t* field, + void** arg) { + (void)field; + FuriHalRegion* region = *arg; + + PB_Region_Band band = {0}; + if(!pb_decode(stream, PB_Region_Band_fields, &band)) { + FURI_LOG_E("SubGhzOnStart", "PB Region band decode error: %s", PB_GET_ERROR(stream)); + return false; + } + + region->bands_count += 1; + region = + realloc(region, sizeof(FuriHalRegion) + sizeof(FuriHalRegionBand) * region->bands_count); + size_t pos = region->bands_count - 1; + region->bands[pos].start = band.start; + region->bands[pos].end = band.end; + region->bands[pos].power_limit = band.power_limit; + region->bands[pos].duty_cycle = band.duty_cycle; + *arg = region; + + FURI_LOG_I( + "SubGhzOnStart", + "Add allowed band: start %dHz, stop %dHz, power_limit %ddBm, duty_cycle %d%%", + band.start, + band.end, + band.power_limit, + band.duty_cycle); + return true; +} + void subghz_on_system_start() { #ifdef SRV_CLI Cli* cli = furi_record_open(RECORD_CLI); @@ -766,4 +811,52 @@ void subghz_on_system_start() { #else UNUSED(subghz_cli_command); #endif + +#ifdef SRV_STORAGE + Storage* storage = furi_record_open(RECORD_STORAGE); + File* file = storage_file_alloc(storage); + FileInfo fileinfo = {0}; + PB_Region pb_region = {0}; + pb_region.bands.funcs.decode = subghz_on_system_start_istream_decode_band; + + do { + if(storage_common_stat(storage, SUBGHZ_REGION_FILENAME, &fileinfo) != FSE_OK || + fileinfo.size == 0) { + FURI_LOG_W("SubGhzOnStart", "Region data is missing or empty"); + break; + } + + if(!storage_file_open(file, SUBGHZ_REGION_FILENAME, FSAM_READ, FSOM_OPEN_EXISTING)) { + FURI_LOG_E("SubGhzOnStart", "Unable to open region data"); + break; + } + + pb_istream_t istream = { + .callback = subghz_on_system_start_istream_read, + .state = file, + .errmsg = NULL, + .bytes_left = fileinfo.size, + }; + + pb_region.bands.arg = malloc(sizeof(FuriHalRegion)); + if(!pb_decode(&istream, PB_Region_fields, &pb_region)) { + FURI_LOG_E("SubGhzOnStart", "Invalid region data"); + free(pb_region.bands.arg); + break; + } + + FuriHalRegion* region = pb_region.bands.arg; + memcpy( + region->country_code, + pb_region.country_code->bytes, + pb_region.country_code->size < 4 ? pb_region.country_code->size : 3); + furi_hal_region_set(region); + } while(0); + + pb_release(PB_Region_fields, &pb_region); + storage_file_free(file); + furi_record_close(RECORD_STORAGE); +#else + UNUSED(subghz_cli_command); +#endif } diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index 00cc922c742..b08b658a4d8 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -278,7 +278,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { break; } - if(!furi_hal_subghz_is_tx_allowed(temp_data32)) { + if(!furi_hal_region_is_frequency_allowed(temp_data32)) { FURI_LOG_E(TAG, "This frequency can only be used for RX in your region"); load_key_state = SubGhzLoadKeyStateOnlyRx; break; diff --git a/assets/protobuf b/assets/protobuf index cc5918dc488..6727eaf287d 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit cc5918dc488ac3617012ce5377114e086b447324 +Subproject commit 6727eaf287db077dcd28719cd764f5804712223e diff --git a/firmware/targets/f7/furi_hal/furi_hal.c b/firmware/targets/f7/furi_hal/furi_hal.c index 23f4097368c..d0856127ac3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal.c +++ b/firmware/targets/f7/furi_hal/furi_hal.c @@ -49,6 +49,7 @@ void furi_hal_init() { FURI_LOG_I(TAG, "GPIO OK"); furi_hal_version_init(); + furi_hal_region_init(); furi_hal_spi_init(); diff --git a/firmware/targets/f7/furi_hal/furi_hal_info.c b/firmware/targets/f7/furi_hal/furi_hal_info.c index cf7140eb4e3..1f75ea331ea 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_info.c +++ b/firmware/targets/f7/furi_hal/furi_hal_info.c @@ -1,6 +1,11 @@ #include -#include +#include +#include +#include +#include + #include +#include #include void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) { @@ -45,6 +50,7 @@ void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) { out("hardware_color", string_get_cstr(value), false, context); string_printf(value, "%d", furi_hal_version_get_hw_region()); out("hardware_region", string_get_cstr(value), false, context); + out("hardware_region_provisioned", furi_hal_region_get_name(), false, context); const char* name = furi_hal_version_get_name_ptr(); if(name) { out("hardware_name", name, false, context); diff --git a/firmware/targets/f7/furi_hal/furi_hal_region.c b/firmware/targets/f7/furi_hal/furi_hal_region.c new file mode 100644 index 00000000000..143d5c18c2f --- /dev/null +++ b/firmware/targets/f7/furi_hal/furi_hal_region.c @@ -0,0 +1,135 @@ +#include +#include + +const FuriHalRegion furi_hal_region_zero = { + .country_code = "00", + .bands_count = 1, + .bands = { + { + .start = 0, + .end = 1000000000, + .power_limit = 12, + .duty_cycle = 50, + }, + }}; + +const FuriHalRegion furi_hal_region_eu_ru = { + .country_code = "EU", + .bands_count = 2, + .bands = { + { + .start = 433050000, + .end = 434790000, + .power_limit = 12, + .duty_cycle = 50, + }, + { + .start = 868150000, + .end = 868550000, + .power_limit = 12, + .duty_cycle = 50, + }}}; + +const FuriHalRegion furi_hal_region_us_ca_au = { + .country_code = "US", + .bands_count = 3, + .bands = { + { + .start = 304100000, + .end = 321950000, + .power_limit = 12, + .duty_cycle = 50, + }, + { + .start = 433050000, + .end = 434790000, + .power_limit = 12, + .duty_cycle = 50, + }, + { + .start = 915000000, + .end = 928000000, + .power_limit = 12, + .duty_cycle = 50, + }}}; + +const FuriHalRegion furi_hal_region_jp = { + .country_code = "JP", + .bands_count = 2, + .bands = { + { + .start = 312000000, + .end = 315250000, + .power_limit = 12, + .duty_cycle = 50, + }, + { + .start = 920500000, + .end = 923500000, + .power_limit = 12, + .duty_cycle = 50, + }}}; + +static const FuriHalRegion* furi_hal_region = NULL; + +void furi_hal_region_init() { + FuriHalVersionRegion region = furi_hal_version_get_hw_region(); + + if(region == FuriHalVersionRegionUnknown) { + furi_hal_region = &furi_hal_region_zero; + } else if(region == FuriHalVersionRegionEuRu) { + furi_hal_region = &furi_hal_region_eu_ru; + } else if(region == FuriHalVersionRegionUsCaAu) { + furi_hal_region = &furi_hal_region_us_ca_au; + } else if(region == FuriHalVersionRegionJp) { + furi_hal_region = &furi_hal_region_jp; + } +} + +const FuriHalRegion* furi_hal_region_get() { + return furi_hal_region; +} + +void furi_hal_region_set(FuriHalRegion* region) { + furi_hal_region = region; +} + +bool furi_hal_region_is_provisioned() { + return furi_hal_region != NULL; +} + +const char* furi_hal_region_get_name() { + if(furi_hal_region) { + return furi_hal_region->country_code; + } else { + return "--"; + } +} + +bool furi_hal_region_is_frequency_allowed(uint32_t frequency) { + if(!furi_hal_region) { + return false; + } + + const FuriHalRegionBand* band = furi_hal_region_get_band(frequency); + if(!band) { + return false; + } + + return true; +} + +const FuriHalRegionBand* furi_hal_region_get_band(uint32_t frequency) { + if(!furi_hal_region) { + return NULL; + } + + for(size_t i = 0; i < furi_hal_region->bands_count; i++) { + if(furi_hal_region->bands[i].start <= frequency && + furi_hal_region->bands[i].end >= frequency) { + return &furi_hal_region->bands[i]; + } + } + + return NULL; +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 650f8ac3321..ade46238982 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -1,6 +1,7 @@ #include "furi_hal_subghz.h" #include "furi_hal_subghz_configs.h" +#include #include #include #include @@ -308,52 +309,8 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { return value; } -bool furi_hal_subghz_is_tx_allowed(uint32_t value) { - //checking regional settings - bool is_allowed = false; - switch(furi_hal_version_get_hw_region()) { - case FuriHalVersionRegionEuRu: - //433,05..434,79; 868,15..868,55 - if(!(value >= 433050000 && value <= 434790000) && - !(value >= 868150000 && value <= 868550000)) { - } else { - is_allowed = true; - } - break; - case FuriHalVersionRegionUsCaAu: - //304,10..321,95; 433,05..434,79; 915,00..928,00 - if(!(value >= 304100000 && value <= 321950000) && - !(value >= 433050000 && value <= 434790000) && - !(value >= 915000000 && value <= 928000000)) { - } else { - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if((value >= 304100000 && value <= 321950000) && - ((furi_hal_subghz.preset == FuriHalSubGhzPresetOok270Async) || - (furi_hal_subghz.preset == FuriHalSubGhzPresetOok650Async))) { - furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable_au); - } - } - is_allowed = true; - } - break; - case FuriHalVersionRegionJp: - //312,00..315,25; 920,50..923,50 - if(!(value >= 312000000 && value <= 315250000) && - !(value >= 920500000 && value <= 923500000)) { - } else { - is_allowed = true; - } - break; - - default: - is_allowed = true; - break; - } - return is_allowed; -} - uint32_t furi_hal_subghz_set_frequency(uint32_t value) { - if(furi_hal_subghz_is_tx_allowed(value)) { + if(furi_hal_region_is_frequency_allowed(value)) { furi_hal_subghz.regulation = SubGhzRegulationTxRx; } else { furi_hal_subghz.regulation = SubGhzRegulationOnlyRx; diff --git a/firmware/targets/furi_hal_include/furi_hal.h b/firmware/targets/furi_hal_include/furi_hal.h index 4d1fc970405..2a372a6c3e6 100644 --- a/firmware/targets/furi_hal_include/furi_hal.h +++ b/firmware/targets/furi_hal_include/furi_hal.h @@ -18,6 +18,7 @@ template struct STOP_EXTERNING_ME {}; #include "furi_hal_sd.h" #include "furi_hal_i2c.h" #include "furi_hal_resources.h" +#include "furi_hal_region.h" #include "furi_hal_rtc.h" #include "furi_hal_speaker.h" #include "furi_hal_gpio.h" diff --git a/firmware/targets/furi_hal_include/furi_hal_region.h b/firmware/targets/furi_hal_include/furi_hal_region.h new file mode 100644 index 00000000000..10d519ab73c --- /dev/null +++ b/firmware/targets/furi_hal_include/furi_hal_region.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include +#include + +typedef struct { + uint32_t start; + uint32_t end; + int8_t power_limit; + uint8_t duty_cycle; +} FuriHalRegionBand; + +typedef struct { + char country_code[4]; + uint16_t bands_count; + FuriHalRegionBand bands[]; +} FuriHalRegion; + +/** Initialize region */ +void furi_hal_region_init(); + +/** Get Region Data. + * + * Region data may be allocated in Flash or in RAM. + * Keep in mind that we don't do memory management on our side. + * + * @return pointer to FuriHalRegion instance (in RAM or Flash, check before freeing on region update) + */ +const FuriHalRegion* furi_hal_region_get(); + +/** Set device region data + * + * @param region pointer to the FuriHalRegion + */ +void furi_hal_region_set(FuriHalRegion* region); + +/** Check if region data provisioned + * + * @return true if provisioned, false otherwise + */ +bool furi_hal_region_is_provisioned(); + +/** Get region name + * + * 2 letter Region code according to iso 3166 standard + * There are 2 extra values that we use in special cases: + * - "00" - developer edition, unlocked + * - "WW" - world wide, region provisioned by default + * - "--" - no provisioned region + * + * @return Pointer to string + */ +const char* furi_hal_region_get_name(); + +/** Сheck if transmission is allowed on this frequency for your flipper region + * + * @param[in] frequency The frequency + * @param value frequency in Hz + * + * @return true if allowed + */ +bool furi_hal_region_is_frequency_allowed(uint32_t frequency); + +/** Get band data for frequency + * + * + * + * @param[in] frequency The frequency + * + * @return { description_of_the_return_value } + */ +const FuriHalRegionBand* furi_hal_region_get_band(uint32_t frequency); diff --git a/firmware/targets/furi_hal_include/furi_hal_subghz.h b/firmware/targets/furi_hal_include/furi_hal_subghz.h index b6d132ac3f3..d610b01b7a7 100644 --- a/firmware/targets/furi_hal_include/furi_hal_subghz.h +++ b/firmware/targets/furi_hal_include/furi_hal_subghz.h @@ -180,14 +180,6 @@ bool furi_hal_subghz_is_frequency_valid(uint32_t value); */ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value); -/** Сheck if transmission is allowed on this frequency for your flipper region - * - * @param value frequency in Hz - * - * @return true if allowed - */ -bool furi_hal_subghz_is_tx_allowed(uint32_t value); - /** Set frequency * * @param value frequency in Hz diff --git a/lib/subghz/subghz_tx_rx_worker.c b/lib/subghz/subghz_tx_rx_worker.c index 74a6183cec5..78a18693155 100644 --- a/lib/subghz/subghz_tx_rx_worker.c +++ b/lib/subghz/subghz_tx_rx_worker.c @@ -237,7 +237,7 @@ bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency) { instance->worker_running = true; - if(furi_hal_subghz_is_tx_allowed(frequency)) { + if(furi_hal_region_is_frequency_allowed(frequency)) { instance->frequency = frequency; res = true; } From ba0502ae1bb3d73baa04717da1b160416ee591c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Thu, 11 Aug 2022 20:18:02 +0900 Subject: [PATCH 03/26] SubGhz: show region provisioning message (#1580) * SubGhz: region provisioning message * SubGhz: correct region warning text --- .../subghz/scenes/subghz_scene_show_only_rx.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/applications/subghz/scenes/subghz_scene_show_only_rx.c b/applications/subghz/scenes/subghz_scene_show_only_rx.c index 48fa751e020..22e68c97893 100644 --- a/applications/subghz/scenes/subghz_scene_show_only_rx.c +++ b/applications/subghz/scenes/subghz_scene_show_only_rx.c @@ -12,13 +12,11 @@ void subghz_scene_show_only_rx_on_enter(void* context) { // Setup view Popup* popup = subghz->popup; popup_set_icon(popup, 67, 12, &I_DolphinFirstStart7_61x51); - popup_set_text( - popup, - "This frequency can\nonly be used for RX\nin your region", - 38, - 40, - AlignCenter, - AlignBottom); + const char* text = "This frequency can\nonly be used for RX\nin your region"; + if(!furi_hal_region_is_provisioned()) { + text = "Update Flipper to unlock frequencies allowed in your region"; + } + popup_set_text(popup, text, 38, 40, AlignCenter, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, subghz); popup_set_callback(popup, subghz_scene_show_only_rx_popup_callback); From 79d9731ea52d0a5791e76151e5367d4e0e4417eb Mon Sep 17 00:00:00 2001 From: Vri <109021367+vrifox@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:47:18 +0200 Subject: [PATCH 04/26] fix: typo badusb demo windows (#1579) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: typo badusb demo windows: Fix a typo in the badusb demo script for Windows. * Assets: update manifest Co-authored-by: あく --- assets/resources/Manifest | 4 ++-- assets/resources/badusb/demo_windows.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/resources/Manifest b/assets/resources/Manifest index 7dbd077bebe..8bfdcef7e3b 100644 --- a/assets/resources/Manifest +++ b/assets/resources/Manifest @@ -1,5 +1,5 @@ V:0 -T:1659888302 +T:1660218073 D:badusb D:dolphin D:infrared @@ -8,7 +8,7 @@ D:nfc D:subghz D:u2f F:0e41ba26498b7511d7c9e6e6b5e3b149:1592:badusb/demo_macos.txt -F:e538ad2ce5a06ec45e1b5b24824901b1:1552:badusb/demo_windows.txt +F:46a332993ca94b9aa692030ebaa19c70:1552:badusb/demo_windows.txt D:dolphin/L1_Boxing_128x64 D:dolphin/L1_Cry_128x64 D:dolphin/L1_Furippa1_128x64 diff --git a/assets/resources/badusb/demo_windows.txt b/assets/resources/badusb/demo_windows.txt index 013e99e21b9..df43535105a 100644 --- a/assets/resources/badusb/demo_windows.txt +++ b/assets/resources/badusb/demo_windows.txt @@ -13,7 +13,7 @@ STRING Hello World! ENTER DEFAULT_DELAY 50 -REM Copy-Paste previuos string +REM Copy-Paste previous string UP HOME SHIFT DOWN From a39111ade2723e9ccf15866ab9cc8d90c5047546 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Thu, 11 Aug 2022 16:20:31 +0400 Subject: [PATCH 05/26] [FL-2723] SubGhz: add protocol Honeywell_WDB / Doorbell (#1560) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGhz: add protocol Honeywell_WDB (receive/save/load/transfer) * SubGhz: add parsing data honeywell * SubGhz: fix UI CAME TWEE * SubGhz: add unit_test honeywell_wdb Co-authored-by: あく --- applications/unit_tests/subghz/subghz_test.c | 18 +- assets/unit_tests/subghz/honeywell_wdb.sub | 7 + .../unit_tests/subghz/honeywell_wdb_raw.sub | 22 + assets/unit_tests/subghz/test_random_raw.sub | 7 +- lib/subghz/blocks/math.c | 8 + lib/subghz/blocks/math.h | 8 + lib/subghz/protocols/came_twee.c | 2 +- lib/subghz/protocols/honeywell_wdb.c | 399 ++++++++++++++++++ lib/subghz/protocols/honeywell_wdb.h | 111 +++++ lib/subghz/protocols/registry.c | 21 +- lib/subghz/protocols/registry.h | 1 + 11 files changed, 591 insertions(+), 13 deletions(-) create mode 100644 assets/unit_tests/subghz/honeywell_wdb.sub create mode 100644 assets/unit_tests/subghz/honeywell_wdb_raw.sub create mode 100644 lib/subghz/protocols/honeywell_wdb.c create mode 100644 lib/subghz/protocols/honeywell_wdb.h diff --git a/applications/unit_tests/subghz/subghz_test.c b/applications/unit_tests/subghz/subghz_test.c index fb3c7a4eb6f..f91d27234a9 100644 --- a/applications/unit_tests/subghz/subghz_test.c +++ b/applications/unit_tests/subghz/subghz_test.c @@ -13,7 +13,7 @@ #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") -#define TEST_RANDOM_COUNT_PARSE 158 +#define TEST_RANDOM_COUNT_PARSE 188 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -404,6 +404,14 @@ MU_TEST(subghz_decoder_phoenix_v2_test) { "Test decoder " SUBGHZ_PROTOCOL_PHOENIX_V2_NAME " error\r\n"); } +MU_TEST(subghz_decoder_honeywell_wdb_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/honeywell_wdb_raw.sub"), + SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME), + "Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -501,6 +509,12 @@ MU_TEST(subghz_encoder_phoenix_v2_test) { "Test encoder " SUBGHZ_PROTOCOL_PHOENIX_V2_NAME " error\r\n"); } +MU_TEST(subghz_encoder_honeywell_wdb_test) { + mu_assert( + subghz_encoder_test(EXT_PATH("unit_tests/subghz/honeywell_wdb.sub")), + "Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n"); +} + MU_TEST(subghz_random_test) { mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); } @@ -537,6 +551,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_bett_test); MU_RUN_TEST(subghz_decoder_doitrand_test); MU_RUN_TEST(subghz_decoder_phoenix_v2_test); + MU_RUN_TEST(subghz_decoder_honeywell_wdb_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); @@ -554,6 +569,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_bett_test); MU_RUN_TEST(subghz_encoder_doitrand_test); MU_RUN_TEST(subghz_encoder_phoenix_v2_test); + MU_RUN_TEST(subghz_encoder_honeywell_wdb_test); MU_RUN_TEST(subghz_random_test); subghz_test_deinit(); diff --git a/assets/unit_tests/subghz/honeywell_wdb.sub b/assets/unit_tests/subghz/honeywell_wdb.sub new file mode 100644 index 00000000000..bce11cd0d63 --- /dev/null +++ b/assets/unit_tests/subghz/honeywell_wdb.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 868350000 +Preset: FuriHalSubGhzPreset2FSKDev476Async +Protocol: Honeywell +Bit: 48 +Key: 00 00 0E DB 70 20 00 01 diff --git a/assets/unit_tests/subghz/honeywell_wdb_raw.sub b/assets/unit_tests/subghz/honeywell_wdb_raw.sub new file mode 100644 index 00000000000..0fbd6d23e43 --- /dev/null +++ b/assets/unit_tests/subghz/honeywell_wdb_raw.sub @@ -0,0 +1,22 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 868250000 +Preset: FuriHalSubGhzPreset2FSKDev476Async +Protocol: RAW +RAW_Data: 414 -1374 51 -108 79 -216 189 -584 53 -214 53 -400 215 -264 129 -322 77 -288 79 -54 107 -184 51 -446 53 -160 161 -305 263 -104 264 -134 53 -806 267 -80 187 -314 53 -158 83 -1172 243 -833 79 -188 345 -208 77 -182 225 -100 107 -106 187 -190 105 -432 176 -174 119 -328 79 -432 79 -102 99 -514 127 -218 79 -184 77 -52 101 -356 53 -615 243 -266 181 -102 212 -138 81 -486 205 -574 77 -256 155 -152 217 -78 75 -1010 393 -346 79 -488 107 -284 121 -72 215 -174 183 -54 257 -332 179 -52 79 -238 53 -636 161 -80 227 -950 346 -160 109 -564 295 -160 299 -160 435 -487 312 -52 105 -292 77 -246 137 -498 366 -104 255 -362 97 -210 53 -555 374 -206 129 -96 303 -280 179 -172 75 -102 99 -76 353 -228 131 -252 147 -130 79 -304 103 -82 139 -52 103 -183 77 -284 75 -454 55 -188 77 -222 161 -128 107 -136 187 -270 53 -371 184 -364 103 -284 129 -52 103 -321 81 -554 261 -1048 107 -106 243 -280 103 -478 215 -530 53 -108 53 -236 203 -180 51 -78 77 -338 81 -82 53 -231 75 -124 256 -232 227 -448 131 -340 131 -266 107 -346 51 -254 75 -134 210 -182 103 -280 127 -122 305 -310 255 -528 77 -513 79 -214 209 -102 53 -80 133 -1727 237 -78 79 -242 53 -296 133 -532 53 -513 53 -54 131 -190 53 -661 129 -218 107 -394 103 -554 157 -112 343 -314 103 -283 79 -304 135 -56 111 -272 189 -370 271 -270 105 -956 79 -184 77 -868 307 -156 129 -731 51 -200 161 -84 81 -326 51 -54 157 -168 369 -152 101 -188 81 -398 239 -132 215 -54 105 -182 317 -206 99 -198 97 -274 157 -271 121 -268 200 -330 499 -184 55 -434 133 -646 283 -152 255 -428 101 -350 199 -124 145 -304 308 -102 75 -386 107 -186 129 -534 101 -180 175 -100 151 -98 53 -78 133 -794 183 -150 83 -220 185 -280 83 -537 107 -308 55 -138 79 -714 79 -538 77 -106 133 -242 263 -236 75 -884 215 -136 81 -270 133 -624 105 -132 79 -848 291 -373 79 -244 55 -619 203 -202 77 -156 103 -176 99 -408 107 -318 77 -316 79 -500 55 -691 51 -340 129 -266 53 -486 103 -376 103 -185 51 -156 81 -106 77 -104 79 -502 208 -292 133 -432 105 -52 105 -80 51 -158 317 -372 181 -844 51 -270 107 -312 79 -302 83 -444 53 -640 77 -268 183 -138 85 -192 79 -158 131 -132 155 -220 81 -245 127 -386 185 -296 53 -608 77 -308 51 -822 105 -832 51 -850 155 -242 105 -422 79 -270 155 -76 77 -162 55 -414 +RAW_Data: 109 -630 77 -190 53 -52 131 -860 53 -1300 83 -1122 99 -432 53 -724 81 -390 159 -106 81 -2607 79 -474 75 -694 151 -146 73 -104 53 -380 77 -278 77 -128 73 -148 73 -248 99 -314 75 -154 97 -2225 51 -952 183 -970 77 -1210 51 -326 103 -368 151 -252 121 -784 51 -108 187 -256 227 -242 105 -104 150 -128 77 -1287 173 -2513 77 -1144 105 -1268 111 -3964 101 -1348 81 -2718 81 -302 79 -1999 55 -1268 57 -7269 53 -424 83 -3736 105 -1552 51 -8460 57 -5224 101 -244 121 -4124 103 -10775 133 -1858 73 -20679 51 -5532 97 -1718 103 -3764 51 -6496 79 -792 53 -13269 81 -18787 57 -9140 83 -3302 53 -11039 55 -26162 79 -1713 103 -5860 53 -9589 55 -8389 81 -254 85 -16287 73 -8336 53 -6237 75 -828 55 -19389 73 -8028 79 -6284 83 -3460 77 -13504 75 -3198 75 -1280 51 -1948 51 -758 79 -22076 75 -1681 73 -21693 57 -8106 53 -838 51 -10074 51 -4760 55 -492 79 -6558 79 -22996 75 -13904 53 -5564 55 -16578 83 -25603 77 -410 75 -16694 81 -606 53 -2987 53 -3898 107 -3248 79 -5168 55 -754 81 -20662 53 -11066 51 -8624 79 -26384 79 -2214 81 -7442 79 -12488 53 -1656 71 -4508 55 -15680 57 -6669 51 -5410 71 -6411 53 -6082 79 -13772 53 -5945 55 -574 73 -11921 51 -3472 55 -2323 55 -10414 51 -16069 81 -2678 77 -10775 53 -2106 110 -11794 55 -17082 51 -6184 71 -8376 79 -7152 77 -2691 53 -6332 53 -2074 57 -6804 51 -166 53 -2254 53 -452 51 -6771 53 -42749 53 -6658 73 -2034 111 -3440 109 -626 53 -7291 85 -2546 53 -5287 51 -9902 53 -10040 53 -366 79 -13848 51 -3739 77 -47536 51 -354 77 -228 77 -712 53 -530 53 -162 55 -12640 71 -1708 51 -1034 77 -12891 79 -3334 51 -7644 79 -12676 81 -3036 53 -2038 53 -180 57 -818 55 -21459 71 -3009 51 -6572 53 -4015 105 -642 77 -23618 53 -4921 83 -3026 73 -3672 53 -12654 81 -8632 51 -9419 171 -19195 105 -13041 55 -21910 51 -1051 77 -10292 51 -12884 51 -6589 53 -8718 51 -2510 103 -15406 55 -6014 99 -966 73 -2725 53 -12715 51 -4228 55 -3192 57 -8672 51 -14740 51 -17032 75 -11111 1761 -182 399 -106 215 -270 355 -132 329 -150 177 -312 315 -170 169 -290 331 -162 173 -286 187 -312 163 -300 329 -164 311 -162 171 -316 289 -176 297 -194 311 -164 143 -324 167 -314 163 -310 161 -312 163 -300 175 -300 331 -162 173 -312 161 -312 163 -314 161 -298 189 -300 165 -312 161 -312 189 -276 173 -316 193 -310 163 -312 161 -310 163 -300 175 -296 193 -284 191 -284 187 -310 163 -300 175 -300 169 -320 177 -314 485 -464 177 -292 353 -134 +RAW_Data: 171 -316 311 -154 187 -292 343 -134 337 -136 199 -286 311 -182 157 -294 327 -160 171 -316 161 -312 159 -314 333 -170 311 -164 141 -324 305 -164 299 -176 301 -170 167 -340 133 -338 163 -312 159 -294 189 -298 165 -314 311 -180 155 -294 189 -300 165 -312 187 -284 189 -312 159 -294 189 -296 167 -314 161 -310 189 -312 159 -292 189 -296 167 -312 161 -312 159 -314 193 -268 175 -304 193 -314 163 -312 159 -312 193 -294 495 -458 161 -338 301 -168 165 -304 331 -134 199 -286 309 -184 309 -170 141 -318 331 -162 143 -316 309 -182 157 -294 189 -302 163 -312 309 -184 311 -170 141 -318 331 -162 299 -150 319 -196 139 -314 165 -334 137 -340 159 -312 161 -302 149 -318 331 -162 173 -312 161 -312 163 -300 175 -296 195 -310 163 -312 159 -312 163 -312 159 -296 189 -300 193 -284 187 -284 189 -312 159 -292 189 -298 167 -312 161 -312 189 -300 173 -294 195 -282 191 -310 485 -472 167 -300 331 -134 171 -312 333 -170 169 -290 331 -162 299 -176 155 -300 333 -162 171 -300 323 -150 145 -340 159 -320 167 -302 319 -150 319 -166 169 -312 331 -162 299 -150 319 -194 139 -314 165 -308 163 -340 133 -338 163 -312 157 -296 327 -160 171 -316 163 -310 161 -312 163 -298 177 -302 193 -314 163 -310 161 -312 163 -300 173 -300 169 -318 177 -290 189 -300 165 -312 161 -312 189 -284 185 -292 189 -300 191 -286 187 -284 191 -312 471 -486 167 -314 313 -152 159 -300 335 -162 169 -308 319 -150 319 -166 169 -312 331 -162 143 -314 311 -180 157 -294 189 -300 165 -314 309 -182 311 -168 141 -318 333 -162 299 -174 295 -194 141 -314 165 -336 137 -338 135 -338 161 -312 159 -294 327 -160 171 -316 161 -312 159 -314 191 -270 201 -278 193 -314 163 -310 161 -312 163 -300 175 -300 169 -316 177 -292 189 -300 165 -312 161 -312 189 -284 183 -294 189 -298 193 -284 187 -312 163 -312 497 -460 145 -320 325 -168 171 -290 333 -162 171 -314 305 -160 317 -168 169 -290 333 -162 173 -312 283 -182 159 -294 189 -302 165 -312 309 -182 313 -168 143 -318 331 -162 301 -148 321 -194 141 -312 167 -334 135 -340 161 -310 163 -312 159 -294 327 -160 171 -316 163 -310 161 -312 163 -300 175 -302 195 -312 163 -312 159 -312 163 -300 175 -298 169 -318 177 -290 191 -300 165 -312 161 -310 189 -284 185 -292 189 -300 191 -286 187 -312 161 -300 487 -484 151 -318 335 -138 169 -322 305 -164 171 -314 305 -190 295 -166 171 -290 333 -162 173 -312 283 -182 159 -296 191 -300 +RAW_Data: 165 -312 333 -160 311 -170 141 -318 331 -164 299 -148 321 -194 139 -316 165 -336 135 -340 133 -338 163 -300 149 -320 329 -164 171 -314 159 -312 163 -300 175 -298 193 -310 163 -312 159 -312 163 -300 175 -296 193 -312 163 -312 159 -312 163 -300 175 -298 167 -320 175 -290 191 -296 193 -286 187 -310 163 -300 175 -296 501 -458 187 -288 347 -154 151 -316 325 -162 171 -316 313 -152 301 -194 141 -316 331 -162 143 -314 311 -182 155 -294 189 -302 163 -314 309 -182 311 -168 143 -318 331 -162 301 -174 295 -194 141 -314 165 -336 135 -340 133 -338 163 -312 159 -294 327 -158 173 -314 163 -312 159 -306 173 -314 165 -306 191 -284 189 -284 189 -312 157 -294 191 -300 163 -314 187 -284 189 -284 187 -292 189 -296 165 -314 161 -312 189 -284 185 -294 189 -298 193 -286 485 -492 167 -298 323 -150 175 -302 331 -164 171 -300 321 -150 317 -166 167 -308 331 -134 171 -316 309 -182 129 -318 189 -302 163 -314 309 -182 311 -170 141 -318 331 -162 301 -148 321 -194 139 -314 167 -334 137 -338 161 -310 163 -312 159 -294 327 -160 171 -316 161 -312 159 -312 193 -270 175 -304 193 -314 163 -312 159 -312 161 -314 161 -296 189 -304 165 -312 187 -284 189 -276 173 -318 195 -278 193 -284 187 -312 163 -300 175 -298 169 -318 511 -460 147 -318 327 -168 169 -292 331 -164 171 -314 305 -160 315 -168 171 -290 333 -162 171 -314 283 -182 159 -294 189 -300 165 -314 307 -184 311 -170 141 -318 333 -162 299 -150 319 -194 141 -314 165 -336 135 -340 133 -338 163 -312 157 -294 327 -160 171 -316 163 -310 161 -304 175 -314 167 -304 191 -286 187 -284 189 -284 187 -292 189 -300 165 -312 189 -284 187 -286 185 -294 189 -296 165 -314 161 -312 187 -286 185 -294 189 -298 193 -284 485 -494 167 -298 321 -150 177 -312 313 -168 171 -292 331 -164 299 -174 151 -316 325 -162 171 -316 289 -176 151 -316 187 -296 167 -312 311 -180 307 -170 141 -318 331 -162 299 -150 319 -196 139 -314 165 -334 137 -340 159 -312 161 -302 149 -320 329 -164 171 -314 159 -312 163 -300 175 -298 193 -310 163 -312 161 -310 163 -312 161 -296 189 -302 191 -286 187 -284 189 -312 159 -292 189 -296 167 -314 161 -310 189 -284 187 -292 189 -300 193 -284 485 -494 167 -296 323 -150 175 -312 313 -170 169 -292 333 -162 299 -176 151 -314 327 -160 171 -316 291 -176 149 -316 189 -296 165 -314 309 -182 307 -168 141 -318 331 -164 299 -148 321 -194 141 -314 165 -334 137 -338 161 -312 +RAW_Data: 161 -302 147 -320 331 -162 171 -314 161 -312 163 -300 175 -296 195 -310 163 -312 159 -312 163 -300 173 -296 193 -312 163 -312 159 -312 163 -300 175 -298 169 -318 177 -290 191 -296 195 -284 189 -284 189 -312 159 -296 513 -468 159 -300 333 -162 171 -300 323 -150 171 -314 325 -162 311 -164 171 -314 305 -160 159 -296 327 -160 171 -316 161 -312 161 -312 335 -170 311 -164 141 -324 321 -154 299 -194 309 -164 143 -326 167 -314 161 -312 159 -312 163 -302 173 -300 331 -162 173 -312 161 -312 163 -300 175 -300 167 -320 153 -312 191 -296 167 -312 161 -312 189 -312 159 -292 189 -298 167 -312 161 -312 159 -314 193 -268 177 -302 193 -316 161 -312 159 -312 193 -294 497 -456 187 -312 303 -166 165 -306 331 -132 201 -286 309 -182 313 -168 143 -318 331 -162 143 -314 311 -182 157 -294 189 -302 165 -312 309 -182 311 -170 141 -318 333 -162 299 -150 319 -194 141 -314 165 -334 137 -338 161 -312 161 -300 149 -320 331 -162 171 -314 161 -310 163 -302 173 -298 193 -310 165 -310 161 -310 163 -312 161 -296 189 -300 193 -286 187 -284 189 -312 157 -294 189 -298 165 -314 161 -310 189 -284 187 -292 189 -300 193 -284 485 -494 167 -298 321 -150 171 -318 323 -162 171 -314 289 -176 297 -194 141 -314 331 -162 143 -316 309 -182 155 -294 189 -302 163 -314 309 -182 311 -168 143 -318 331 -162 301 -148 321 -194 139 -314 167 -334 137 -338 161 -310 163 -300 149 -320 331 -162 171 -314 161 -312 163 -300 173 -298 193 -310 163 -312 159 -312 163 -300 175 -296 193 -312 163 -312 159 -312 163 -300 175 -298 167 -320 175 -290 191 -296 193 -286 187 -310 163 -312 161 -296 513 -468 159 -300 333 -162 171 -302 321 -150 175 -300 333 -162 311 -162 171 -316 289 -176 153 -314 327 -160 171 -316 163 -312 159 -312 307 -168 335 -138 169 -320 307 -164 297 -176 301 -194 141 -318 165 -336 137 -338 133 -338 163 -312 159 -294 327 -160 171 -316 161 -312 161 -312 163 -298 177 -302 169 -318 177 -292 189 -298 167 -312 189 -284 189 -312 157 -294 189 -298 167 -312 161 -312 159 -312 193 -270 203 -302 169 -314 161 -312 189 -310 467 -484 145 -318 327 -168 143 -316 331 -162 173 -312 307 -160 313 -170 141 -318 331 -164 143 -342 281 -184 157 -294 189 -302 165 -312 307 -184 313 -168 141 -320 331 -162 299 -150 319 -194 141 -314 165 -336 137 -338 135 -338 161 -312 159 -294 327 -158 173 -314 163 -310 161 -312 165 -298 175 -304 193 -312 163 -312 159 -312 +RAW_Data: 163 -300 175 -298 169 -318 177 -290 191 -298 165 -314 161 -310 189 -284 185 -292 189 -298 193 -284 189 -310 163 -312 497 -460 145 -320 325 -170 169 -290 333 -162 171 -314 307 -158 317 -168 169 -290 333 -162 171 -314 281 -182 159 -296 189 -300 165 -312 309 -182 313 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -336 137 -338 135 -338 161 -312 159 -294 327 -160 173 -314 163 -312 159 -312 163 -300 175 -302 195 -312 163 -312 159 -312 163 -300 175 -298 169 -318 175 -292 189 -300 165 -312 161 -312 187 -284 185 -292 189 -300 193 -284 187 -312 161 -314 471 -486 167 -314 313 -152 159 -300 335 -162 169 -308 321 -156 329 -170 127 -318 321 -176 155 -300 333 -164 169 -302 165 -314 161 -310 329 -168 299 -166 151 -328 311 -154 331 -168 299 -178 143 -318 153 -322 167 -332 149 -320 151 -318 165 -304 321 -156 181 -290 189 -300 173 -294 177 -294 189 -302 173 -294 177 -294 189 -302 173 -294 177 -318 193 -278 173 -294 179 -292 191 -302 173 -294 177 -294 189 -302 173 -320 177 -294 195 -278 175 -318 491 -460 163 -314 333 -158 159 -294 327 -160 171 -316 311 -180 307 -170 141 -318 331 -162 143 -316 309 -182 157 -294 189 -302 165 -312 309 -182 313 -168 141 -318 331 -164 299 -148 321 -194 141 -314 165 -334 137 -338 135 -338 161 -312 159 -294 329 -158 173 -314 163 -310 161 -306 173 -314 165 -304 193 -284 187 -286 189 -276 197 -294 193 -310 163 -312 161 -310 163 -300 175 -296 193 -310 165 -284 187 -310 163 -300 175 -300 169 -318 177 -316 483 -466 187 -292 341 -134 171 -308 319 -150 179 -300 333 -164 309 -162 171 -316 313 -152 153 -316 327 -160 171 -316 163 -310 161 -312 307 -166 337 -136 171 -322 305 -164 299 -174 301 -194 141 -318 165 -336 137 -338 161 -310 163 -300 149 -320 331 -162 171 -314 161 -312 163 -300 173 -296 195 -310 163 -312 159 -312 163 -312 159 -296 189 -302 165 -312 189 -284 189 -284 185 -294 189 -296 165 -314 161 -310 189 -284 187 -294 189 -298 193 -284 485 -494 167 -298 321 -150 177 -312 313 -168 171 -290 333 -162 299 -176 151 -316 325 -162 171 -316 289 -176 151 -314 189 -296 165 -314 309 -182 305 -170 141 -318 333 -162 299 -150 319 -194 141 -314 165 -334 137 -340 133 -338 161 -302 149 -320 329 -164 171 -286 187 -312 163 -300 173 -298 193 -310 163 -312 159 -312 163 -312 159 -296 189 -302 191 -286 187 -284 189 -312 159 -292 191 -296 165 -314 161 -310 189 -284 187 -292 +RAW_Data: 189 -300 193 -284 485 -494 167 -298 321 -150 177 -300 327 -150 167 -328 305 -160 319 -168 171 -290 333 -162 171 -314 281 -184 159 -296 189 -300 165 -314 307 -184 311 -170 141 -318 333 -162 299 -150 319 -194 139 -314 167 -334 135 -340 133 -338 163 -312 159 -294 327 -158 173 -314 163 -312 159 -312 165 -298 177 -302 193 -314 163 -310 161 -312 163 -300 173 -300 167 -318 177 -292 189 -300 165 -312 161 -312 187 -284 185 -292 189 -300 191 -286 187 -284 189 -300 487 -484 149 -320 333 -138 171 -322 321 -154 151 -316 327 -160 311 -164 173 -312 307 -160 161 -298 355 -132 173 -314 163 -310 161 -312 335 -170 311 -164 143 -322 307 -164 323 -150 301 -196 141 -318 165 -334 137 -338 161 -312 161 -302 147 -320 331 -162 173 -312 161 -312 163 -300 173 -298 195 -310 163 -312 159 -312 163 -312 159 -296 189 -300 193 -284 189 -284 189 -284 185 -294 189 -296 165 -314 161 -312 189 -284 185 -294 189 -298 193 -286 485 -468 193 -296 323 -150 147 -340 313 -168 171 -292 331 -164 299 -174 151 -316 325 -160 173 -316 289 -176 149 -316 189 -294 165 -314 309 -182 307 -170 141 -318 331 -164 299 -148 321 -194 139 -314 167 -306 165 -338 133 -338 163 -312 159 -294 327 -160 173 -314 163 -312 161 -310 165 -300 175 -300 169 -318 177 -290 189 -298 165 -314 187 -284 189 -312 159 -294 189 -298 165 -314 161 -310 161 -306 173 -316 193 -280 191 -312 159 -312 163 -300 515 -460 161 -312 305 -190 135 -328 329 -134 201 -286 309 -182 311 -168 143 -318 331 -162 143 -316 309 -182 157 -294 189 -300 165 -312 309 -184 311 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -334 137 -340 159 -312 163 -300 149 -318 331 -162 173 -312 161 -312 163 -300 175 -296 195 -310 163 -312 159 -312 163 -300 173 -296 193 -312 163 -312 159 -312 163 -312 161 -298 189 -300 165 -312 161 -312 189 -312 159 -292 191 -300 191 -286 485 -468 193 -298 323 -148 147 -342 323 -160 173 -314 289 -176 297 -196 139 -314 331 -162 143 -314 311 -180 157 -292 191 -300 165 -312 311 -182 309 -170 141 -318 333 -162 299 -150 319 -194 141 -314 165 -334 137 -338 161 -312 161 -312 159 -294 329 -158 173 -314 163 -310 161 -312 165 -298 175 -304 193 -312 163 -310 161 -310 163 -302 173 -300 169 -318 175 -292 189 -300 165 -312 161 -310 189 -278 173 -316 195 -280 191 -312 159 -312 163 -300 515 -460 163 -310 305 -190 137 -328 329 -134 199 -288 309 -182 311 -168 143 -318 +RAW_Data: 331 -162 143 -316 309 -182 157 -292 191 -300 165 -312 309 -182 313 -168 141 -318 331 -164 299 -174 295 -194 141 -314 165 -334 137 -340 133 -338 163 -312 159 -292 327 -160 171 -316 163 -310 161 -312 165 -298 175 -304 193 -312 163 -312 159 -312 163 -300 175 -300 169 -316 177 -292 189 -298 167 -312 161 -310 189 -278 173 -316 193 -282 191 -312 159 -312 163 -300 515 -460 163 -310 305 -190 137 -326 331 -132 201 -286 309 -184 309 -170 141 -318 333 -162 143 -314 311 -180 159 -294 189 -300 165 -312 309 -184 311 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -336 135 -340 159 -312 163 -300 149 -320 329 -164 171 -314 159 -312 163 -300 175 -296 195 -310 163 -312 159 -312 163 -300 175 -294 195 -310 163 -312 161 -310 163 -300 175 -298 169 -318 153 -314 191 -296 193 -286 187 -284 189 -312 161 -294 509 -468 159 -298 335 -162 169 -304 323 -150 175 -300 335 -162 311 -160 173 -316 313 -152 151 -316 327 -160 171 -316 163 -312 159 -312 307 -168 335 -138 169 -322 305 -164 299 -176 299 -194 141 -316 167 -334 137 -340 159 -312 161 -302 147 -320 331 -162 173 -312 161 -312 163 -300 175 -296 193 -310 165 -310 161 -312 161 -302 173 -296 195 -310 163 -312 161 -310 163 -300 175 -298 169 -318 177 -290 189 -296 193 -286 187 -310 163 -300 175 -296 501 -484 161 -288 347 -154 151 -316 325 -160 173 -314 313 -152 301 -196 141 -314 331 -162 143 -316 309 -182 157 -294 189 -300 165 -314 309 -182 311 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -336 137 -338 133 -338 163 -312 159 -294 327 -158 173 -316 161 -312 159 -312 163 -298 177 -302 193 -314 163 -312 159 -312 163 -300 175 -298 169 -318 177 -290 191 -298 165 -314 161 -310 189 -284 193 -292 179 -308 167 -314 161 -312 189 -302 481 -460 173 -320 303 -168 169 -294 331 -164 171 -314 307 -160 319 -168 169 -292 331 -162 143 -342 283 -182 159 -294 189 -302 165 -312 309 -184 311 -168 143 -318 331 -162 299 -150 319 -194 141 -314 165 -336 135 -340 133 -338 163 -312 159 -294 327 -158 173 -316 161 -312 159 -312 165 -298 177 -302 193 -312 163 -312 161 -310 163 -314 161 -296 189 -302 165 -312 187 -284 189 -284 185 -294 189 -296 165 -314 187 -284 189 -302 173 -294 195 -310 491 -458 163 -318 319 -156 153 -314 327 -160 171 -316 311 -152 327 -170 141 -316 331 -164 143 -314 309 -182 157 -294 189 -300 165 -314 309 -182 311 -168 143 -316 333 -162 299 -150 +RAW_Data: 319 -194 141 -314 165 -336 135 -340 133 -338 163 -312 159 -294 327 -160 171 -316 161 -312 159 -314 163 -300 175 -302 193 -314 163 -310 161 -310 163 -300 175 -300 167 -318 177 -290 191 -300 165 -312 161 -312 187 -284 185 -292 189 -300 191 -286 187 -310 163 -300 487 -484 149 -320 335 -138 169 -322 305 -164 171 -314 305 -190 293 -168 169 -292 333 -162 171 -314 281 -184 159 -296 189 -300 165 -312 309 -184 311 -170 141 -318 331 -162 299 -150 319 -196 139 -314 165 -336 137 -338 133 -338 163 -312 159 -294 327 -160 171 -316 161 -312 159 -312 165 -298 177 -302 193 -314 163 -310 161 -310 163 -314 161 -296 189 -302 165 -312 187 -286 189 -276 173 -318 193 -280 191 -284 189 -310 163 -300 175 -300 167 -318 513 -460 167 -314 311 -152 161 -324 311 -162 169 -310 329 -160 293 -190 137 -330 329 -132 173 -316 311 -180 129 -318 189 -300 165 -312 309 -182 311 -168 141 -320 329 -164 299 -174 295 -194 141 -314 167 -334 137 -340 133 -338 161 -312 159 -294 329 -158 173 -314 163 -310 161 -312 163 -300 175 -302 195 -312 163 -312 159 -312 163 -300 175 -298 169 -318 177 -290 189 -300 165 -312 161 -312 189 -284 183 -292 189 -300 193 -284 187 -284 189 -314 471 -486 145 -318 327 -168 171 -290 331 -162 173 -312 307 -158 317 -168 169 -290 333 -162 143 -342 283 -182 159 -294 189 -300 165 -312 309 -182 313 -168 143 -318 331 -162 299 -176 293 -196 139 -314 167 -334 137 -338 161 -310 163 -300 149 -320 331 -162 171 -314 161 -312 163 -300 173 -296 195 -310 163 -312 159 -312 163 -312 159 -296 189 -302 193 -284 187 -284 189 -302 149 -318 193 -280 191 -284 189 -284 189 -300 173 -300 169 -316 177 -316 483 -476 153 -320 329 -134 201 -286 309 -182 157 -294 355 -132 339 -136 169 -320 315 -162 171 -302 323 -148 171 -318 159 -318 147 -318 327 -168 313 -164 169 -302 321 -150 317 -166 305 -164 169 -324 169 -314 163 -310 161 -310 163 -300 175 -296 331 -164 171 -314 161 -312 163 -300 175 -298 195 -310 163 -312 159 -312 163 -300 173 -296 193 -312 163 -312 159 -312 163 -300 175 -298 169 -318 177 -290 189 -298 195 -284 187 -284 189 -314 159 -294 513 -470 159 -300 333 -162 171 -300 323 -150 169 -316 325 -160 311 -164 173 -312 307 -158 161 -294 329 -158 173 -314 163 -312 159 -312 335 -170 311 -164 141 -324 305 -164 323 -152 301 -194 141 -318 165 -336 137 -338 161 -312 161 -312 159 -294 329 -158 173 -314 163 -310 161 -312 +RAW_Data: 165 -298 175 -304 169 -318 175 -290 191 -298 165 -314 187 -284 189 -312 159 -294 191 -296 167 -312 161 -312 159 -314 193 -270 201 -304 167 -314 163 -312 159 -312 493 -486 145 -318 325 -170 141 -316 331 -162 173 -314 305 -160 313 -170 141 -318 331 -162 143 -342 283 -182 159 -294 189 -302 165 -312 309 -182 313 -168 141 -318 331 -162 301 -148 321 -194 141 -314 165 -334 137 -340 159 -312 161 -302 147 -320 331 -162 173 -312 161 -312 163 -300 175 -296 193 -310 165 -310 161 -310 163 -302 173 -296 193 -312 161 -312 159 -312 163 -300 175 -300 167 -320 177 -290 189 -298 193 -286 187 -284 189 -312 161 -294 513 -468 159 -300 333 -162 171 -302 321 -150 171 -316 323 -162 311 -164 171 -314 307 -158 159 -296 327 -160 171 -316 163 -310 161 -306 321 -168 339 -134 171 -306 321 -150 317 -166 337 -164 143 -324 167 -314 163 -312 159 -312 163 -300 175 -298 331 -162 173 -312 161 -312 163 -300 175 -300 193 -310 163 -312 161 -310 163 -312 161 -296 189 -300 193 -284 189 -284 189 -284 185 -294 189 -296 165 -314 161 -312 187 -286 185 -292 191 -298 193 -284 485 -494 167 -298 321 -150 177 -312 313 -146 167 -344 305 -158 315 -168 143 -318 331 -162 143 -342 283 -182 159 -294 189 -302 163 -314 307 -184 311 -168 141 -318 333 -162 299 -174 295 -194 141 -314 167 -334 137 -338 161 -312 161 -312 159 -294 329 -160 171 -316 163 -310 161 -312 163 -300 175 -302 169 -318 175 -290 191 -298 165 -312 189 -284 189 -312 159 -292 189 -298 165 -314 161 -312 189 -282 195 -268 203 -304 169 -312 163 -312 187 -278 507 -460 173 -320 303 -166 171 -294 331 -164 171 -314 305 -160 319 -168 169 -292 331 -164 171 -314 281 -182 159 -294 191 -300 165 -312 309 -182 313 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -336 135 -340 133 -338 163 -312 159 -294 327 -160 171 -316 161 -312 159 -314 163 -300 175 -302 193 -312 163 -312 159 -312 163 -300 175 -298 169 -318 177 -292 189 -300 165 -312 161 -310 189 -284 193 -292 179 -308 167 -314 161 -312 189 -302 483 -458 173 -320 303 -168 169 -294 331 -164 171 -314 307 -158 319 -168 169 -292 331 -164 171 -314 283 -182 159 -294 191 -300 165 -312 309 -182 313 -168 143 -316 331 -164 299 -150 319 -194 141 -314 165 -334 137 -340 133 -338 161 -312 159 -294 327 -160 171 -316 161 -312 159 -314 163 -298 177 -304 193 -312 163 -312 161 -310 163 -314 161 -296 189 -302 163 -314 161 -310 189 -284 +RAW_Data: 185 -294 189 -296 165 -314 189 -284 189 -312 157 -294 189 -300 497 -456 189 -284 345 -154 153 -316 325 -160 173 -314 315 -150 325 -170 141 -314 331 -164 143 -314 309 -182 157 -294 189 -302 163 -314 307 -184 311 -168 141 -318 333 -162 299 -174 295 -194 141 -314 165 -334 137 -340 159 -312 163 -300 149 -318 331 -164 171 -314 159 -312 163 -300 175 -298 193 -310 163 -312 159 -312 163 -312 159 -296 189 -300 165 -314 187 -284 189 -312 157 -294 189 -298 165 -314 161 -310 189 -284 187 -292 189 -300 193 -284 485 -468 193 -296 323 -150 175 -312 313 -168 171 -292 331 -164 299 -176 149 -316 325 -162 171 -316 289 -176 151 -314 189 -296 165 -314 309 -182 307 -168 143 -316 331 -164 299 -150 319 -194 141 -312 167 -334 137 -338 161 -310 163 -300 149 -320 331 -162 171 -314 161 -312 163 -300 173 -298 193 -310 163 -312 159 -312 163 -300 173 -296 169 -318 177 -292 189 -300 165 -312 161 -312 189 -284 183 -294 189 -294 195 -284 187 -284 191 -300 173 -296 499 -482 163 -314 321 -154 153 -316 325 -160 173 -314 313 -152 301 -196 139 -316 331 -162 143 -314 311 -182 155 -294 189 -302 163 -314 309 -182 311 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -336 135 -340 159 -312 163 -300 149 -320 329 -164 171 -314 159 -312 163 -300 175 -296 193 -310 165 -310 161 -312 161 -302 173 -296 169 -316 177 -292 189 -300 165 -314 161 -310 189 -284 185 -292 189 -296 193 -286 187 -284 189 -300 175 -294 499 -482 163 -314 321 -154 153 -316 325 -160 171 -316 313 -152 325 -170 141 -314 331 -164 143 -314 311 -180 157 -294 191 -300 165 -312 309 -182 311 -168 141 -320 329 -164 299 -174 295 -194 141 -314 165 -336 135 -340 133 -338 163 -312 159 -294 327 -160 173 -314 163 -312 159 -312 163 -300 175 -302 195 -310 163 -312 159 -312 163 -300 175 -298 169 -318 177 -292 189 -298 165 -314 161 -310 189 -284 185 -292 189 -298 193 -284 187 -286 189 -312 471 -486 145 -320 325 -168 171 -290 331 -162 173 -312 307 -160 315 -168 169 -292 331 -162 143 -342 283 -182 159 -294 189 -302 165 -312 309 -182 311 -170 141 -318 331 -164 299 -148 319 -196 139 -314 167 -334 135 -340 161 -310 163 -300 149 -320 331 -162 171 -314 161 -310 163 -314 161 -296 189 -296 165 -314 161 -310 189 -284 185 -292 189 -298 165 -312 161 -312 189 -276 173 -318 193 -278 191 -286 187 -284 189 -300 175 -298 169 -318 177 -314 483 -466 187 -294 339 -136 169 -306 +RAW_Data: 321 -150 177 -300 333 -164 311 -160 173 -314 313 -152 155 -314 327 -160 171 -316 163 -312 159 -312 307 -166 337 -138 169 -322 305 -164 299 -176 301 -194 141 -316 165 -336 137 -338 161 -310 163 -300 149 -320 331 -162 171 -314 161 -312 163 -300 173 -298 193 -310 163 -312 159 -312 163 -300 175 -294 169 -318 177 -292 189 -300 165 -312 161 -312 189 -284 183 -292 189 -296 193 -286 187 -284 189 -302 173 -296 499 -458 187 -312 321 -154 153 -316 325 -162 171 -316 313 -152 301 -194 141 -314 331 -162 143 -316 309 -182 157 -292 189 -302 163 -314 309 -182 311 -170 141 -318 331 -162 311 -160 295 -190 163 -302 165 -304 165 -312 161 -338 163 -312 157 -294 327 -160 171 -316 161 -312 159 -312 165 -298 177 -302 193 -312 163 -312 159 -312 163 -300 175 -298 169 -318 177 -290 191 -298 165 -314 159 -312 189 -284 185 -290 189 -300 193 -284 189 -284 189 -312 471 -460 483 -2128 125 -52 75 -102 75 -154 101 -100 147 -272 149 -328 75 -228 511 -441 77 -212 87 -114 189 -54 263 -156 171 -393 127 -102 183 -110 293 -242 395 -320 107 -52 81 -346 53 -572 155 -381 305 -234 101 -126 228 -156 195 -102 281 -126 518 -52 313 -240 187 -54 79 -316 133 -136 213 -108 79 -80 185 -464 181 -76 379 -80 81 -506 233 -318 103 -78 53 -559 51 -240 53 -106 207 -136 163 -136 81 -218 187 -104 349 -266 51 -266 129 -80 107 -450 131 -331 127 -359 641 -108 472 -100 547 -82 79 -246 107 -560 567 -130 403 -389 149 -179 77 -526 235 -108 81 -78 51 -455 75 -106 105 -240 101 -557 183 -184 255 -102 311 -130 147 -174 457 -354 75 -442 81 -344 331 -76 51 -106 133 -54 161 -560 77 -130 77 -294 257 -52 99 -126 73 -565 51 -242 131 -497 55 -354 347 -404 81 -108 540 -286 185 -465 219 -264 296 -106 77 -294 193 -110 567 -52 287 -134 53 -106 55 -330 263 -210 83 -86 109 -134 349 -80 221 -80 207 -260 279 -76 75 -74 75 -76 99 -130 443 -78 77 -338 129 -226 179 -280 129 -228 75 -617 185 -324 423 -160 259 -673 159 -188 362 -212 205 -383 151 -316 235 -240 183 -188 79 -56 107 -80 53 -154 417 -158 211 -238 109 -80 79 -218 215 -108 105 -354 215 -112 191 -56 103 -132 77 -236 605 -152 51 -78 185 -78 127 -126 551 -156 135 -186 127 -724 131 -56 81 -378 345 -182 109 -316 107 -316 337 -128 151 -294 101 -1002 101 -52 335 -256 51 -330 81 -448 153 -158 127 -272 131 -160 105 -220 767 -132 +RAW_Data: 75 -210 131 -78 181 -243 345 -108 107 -80 105 -160 107 -218 127 -82 537 -266 239 -340 181 -76 105 -78 421 -482 53 -132 321 -134 51 -262 77 -480 103 -271 475 -154 159 -80 313 -132 79 -282 235 -126 75 -202 175 -226 151 -198 901 -210 51 -78 235 -348 79 -130 103 -584 107 -456 105 -54 431 -54 79 -106 133 -242 105 -486 155 -104 129 -228 147 -100 77 -618 357 -154 531 -104 51 -160 105 -136 109 -140 269 -366 51 -832 53 -270 135 -108 51 -186 51 -160 535 -130 77 -296 51 -182 131 -106 341 -56 135 -194 530 -294 181 -562 75 -179 127 -364 207 -74 125 -332 149 -76 129 -102 103 -102 51 -128 173 -122 482 -474 229 -200 97 -790 105 -104 79 -104 341 -262 101 -110 111 -82 109 -433 271 -210 51 -346 245 -54 209 -284 157 -106 293 -234 77 -826 157 -52 127 -228 299 -490 159 -140 137 -164 247 -294 135 -52 131 -266 77 -128 385 -158 81 -276 356 -476 53 -170 55 -463 79 -190 53 -808 51 -80 159 -106 161 -162 83 -225 187 -341 101 -520 159 -54 428 -182 341 -108 79 -274 77 -108 431 -392 77 -132 131 -138 83 -58 135 -274 305 -300 83 -398 79 -534 131 -528 263 -52 261 -264 437 -342 77 -102 389 -332 103 -130 131 -322 105 -106 53 -134 183 -188 79 -82 81 -104 53 -316 269 -56 347 -286 341 -270 161 -52 131 -136 223 -110 341 -318 469 -138 143 -110 83 -80 53 -54 183 -346 385 -906 51 -382 75 -154 51 -52 207 -186 53 -78 51 -106 293 -52 155 -126 306 -130 412 -416 187 -82 339 -160 135 -194 163 -136 81 -78 281 -426 229 -76 227 -532 177 -528 51 -244 269 -616 75 -52 418 -136 53 -82 51 -154 97 -126 233 -52 51 -740 77 -162 81 -304 263 -162 217 -448 275 -164 185 -138 139 -54 277 -348 531 -642 376 -274 267 -182 75 -126 103 -615 103 -236 81 -380 77 -52 241 -80 105 -438 111 -192 181 -54 135 -186 113 -58 243 -140 57 -385 189 -158 133 -675 231 -80 241 -236 131 -106 109 -108 55 -136 555 -132 303 -494 341 -316 135 -112 302 -366 97 -98 101 -310 177 -78 427 -297 151 -579 163 -314 129 -78 51 -233 105 -210 103 -202 217 -180 121 -229 125 -302 221 -52 235 -158 187 -110 135 -162 51 -108 105 -398 221 -82 297 -110 53 -1400 213 -106 51 -454 723 -368 79 -104 79 -134 81 -323 51 -372 79 -80 235 -132 549 -164 81 -104 129 -602 371 -160 129 -536 179 -234 133 -210 236 -489 159 -52 237 -210 129 -264 53 -242 105 -106 53 -114 +RAW_Data: 193 -290 191 -436 343 -311 207 -322 53 -400 51 -882 135 -678 375 -244 317 -192 380 -558 260 -154 710 -80 237 -218 109 -250 81 -372 107 -160 646 -286 125 -178 269 -726 51 -106 79 -298 523 -682 159 -498 265 -465 127 -592 177 -100 149 -687 103 -78 357 -102 53 -158 105 -240 79 -618 105 -130 79 -478 77 -154 450 -186 53 -192 137 -1038 105 -160 266 -136 51 -345 53 -80 157 -108 235 -102 483 -54 109 -234 327 -376 51 -462 366 -289 163 -108 75 -262 261 -134 81 -78 105 -136 81 -378 105 -272 139 -106 209 -80 205 -184 101 -76 101 -180 229 -427 99 -430 125 -100 103 -469 125 -102 221 -130 209 -106 105 -104 201 -274 332 -232 105 -166 161 -104 275 -80 131 -1000 321 -156 189 -166 81 -130 367 -262 153 -258 75 -260 127 -542 127 -464 107 -80 107 -108 303 -240 77 -238 181 -282 77 -76 224 -104 75 -74 225 -554 131 -56 55 -164 51 -318 247 -130 159 -158 77 -76 285 -354 133 -52 135 -420 155 -256 129 -78 265 -831 103 -231 107 -674 285 -653 337 -102 257 -182 101 -146 147 -303 75 -206 365 -268 157 -54 81 -504 133 -472 107 -82 161 -80 133 -461 81 -825 79 -798 101 -206 207 -80 185 -980 209 -56 247 -246 51 -106 131 -78 79 -236 53 -106 51 -98 101 -206 127 -78 151 -98 279 -155 157 -468 131 -72 173 -372 329 -212 79 -52 101 -375 77 -286 51 -188 185 -308 191 -56 555 -320 179 -86 193 -490 105 -214 81 -138 53 -216 211 -112 57 -134 213 -212 131 -714 73 -128 155 -590 51 -452 189 -261 247 -162 105 -404 167 -56 77 -354 81 -56 215 -316 129 -372 366 -288 133 -56 295 -294 51 -822 53 -482 295 -340 321 -188 459 -631 147 -212 201 -100 173 -258 305 -261 51 -208 97 -124 103 -598 159 -206 77 -710 213 -190 241 -158 133 -186 385 -266 219 -350 133 -52 157 -78 51 -156 403 -162 189 -300 259 -202 103 -760 179 -258 173 -82 431 -164 161 -373 133 -208 191 -82 237 -52 135 -384 131 -192 55 -52 285 -52 79 -274 57 -140 109 -306 53 -132 133 -240 53 -104 51 -214 79 -158 123 -98 99 -126 77 -178 173 -334 178 -518 129 -236 337 -206 230 -100 225 -52 152 -102 103 -308 51 -52 203 -114 139 -318 211 -396 183 -78 51 -106 77 -164 83 -380 133 -234 237 -54 79 -158 83 -84 137 -136 323 -158 365 -128 157 -108 81 -194 109 -618 155 -363 191 -190 109 -110 55 -80 163 -224 79 -82 105 -270 133 -314 159 -106 153 -356 77 -76 75 -458 149 -74 +RAW_Data: 101 -128 53 -130 153 -212 447 -230 171 -636 75 -98 324 -362 51 -160 217 -218 51 -310 101 -152 379 -280 151 -176 203 -210 51 -130 336 -232 179 -596 629 -298 55 -1302 261 -108 109 -80 77 -162 237 -52 125 -52 75 -100 125 -148 297 -426 107 -110 133 -238 155 -228 123 -100 247 -74 179 -126 99 -148 99 -134 81 -194 81 -248 53 -164 135 -82 109 -717 53 -220 81 -234 79 -344 53 -474 79 -154 51 -618 109 -142 83 -593 135 -134 105 -136 81 -243 413 -228 121 -174 125 -328 53 -658 361 -74 401 -280 131 -132 85 -56 139 -298 157 -481 51 -52 129 -76 75 -152 127 -507 321 -486 185 -264 103 -54 325 -76 183 -104 53 -246 81 -78 185 -210 155 -112 55 -80 77 -720 103 -54 51 -450 51 -104 107 -246 185 -78 267 -482 221 -580 113 -222 365 -80 135 -138 199 -296 261 -164 107 -80 131 -134 107 -272 323 -1120 51 -476 81 -106 211 -132 107 -352 183 -134 133 -108 215 -220 55 -666 131 -218 79 -82 253 -56 103 -52 235 -106 103 -134 185 -532 111 -188 361 -399 183 -693 238 -104 567 -106 113 -280 107 -52 287 -106 161 -908 103 -376 339 -180 73 -200 101 -330 209 -54 107 -220 315 -132 216 -138 159 -438 135 -190 73 -130 510 -244 53 -294 81 -84 171 -138 53 -460 515 -82 219 -315 291 -54 107 -270 107 -54 53 -160 79 -374 209 -154 97 -74 233 -454 125 -144 119 -96 99 -542 75 -1200 103 -204 99 -172 95 -98 127 -78 75 -102 103 -320 241 -820 77 -78 105 -326 135 -264 53 -216 133 -517 211 -228 103 -52 257 -455 127 -74 77 -78 235 -436 151 -102 75 -152 75 -76 75 -303 51 -254 177 -284 103 -152 207 -156 79 -302 53 -610 79 -214 133 -80 243 -110 107 -108 185 -286 155 -212 187 -384 75 -128 77 -80 129 -130 99 -76 156 -104 185 -82 81 -242 217 -380 81 -294 157 -182 161 -134 131 -104 77 -52 181 -150 75 -98 147 -230 129 -760 161 -273 137 -84 111 -674 53 -80 127 -317 265 -210 79 -242 297 -238 75 -328 105 -244 345 -342 131 -254 151 -378 103 -335 101 -288 75 -154 275 -498 75 -224 372 -80 157 -190 395 -268 81 -52 105 -160 277 -510 107 -262 105 -192 109 -188 81 -586 105 -78 123 -98 201 -182 55 -614 101 -170 175 -285 79 -222 191 -658 161 -194 135 -532 107 -810 77 -134 241 -128 147 -150 276 -200 97 -230 157 -104 171 -282 77 -212 77 -80 406 -714 259 -182 131 -128 161 -112 81 -380 79 -290 135 -777 345 -370 385 -178 51 -364 +RAW_Data: 215 -189 53 -108 83 -320 209 -530 51 -265 51 -54 109 -242 351 -362 51 -102 51 -156 173 -247 255 -100 99 -176 99 -52 224 -262 53 -80 279 -356 51 -76 379 -176 75 -220 77 -52 129 -208 129 -304 101 -378 157 -52 53 -102 179 -228 255 -311 131 -192 235 -52 51 -126 273 -721 53 -294 161 -170 55 -376 81 -268 131 -98 129 -268 81 -158 107 -80 161 -214 129 -110 501 -220 185 -688 79 -132 325 -212 53 -295 105 -104 51 -106 79 -372 153 -106 137 -84 193 -741 51 -561 51 -402 390 -126 149 -250 327 -338 177 -202 177 -931 105 -271 423 -768 53 -430 159 -110 217 -104 161 -460 249 -82 79 -186 79 -104 53 -132 79 -218 55 -298 53 -214 81 -354 51 -108 107 -196 273 -80 79 -104 153 -100 175 -76 131 -220 81 -56 131 -368 217 -116 137 -82 169 -342 209 -106 319 -396 75 -104 253 -130 149 -430 127 -130 81 -196 55 -404 105 -726 181 -224 199 -106 79 -220 159 -180 75 -126 201 -128 75 -833 127 -128 125 -230 249 -184 51 -218 79 -240 163 -222 135 -82 103 -80 159 -765 107 -276 237 -438 207 -162 133 -128 135 -316 105 -312 137 -486 181 -158 77 -769 183 -764 533 -186 77 -100 173 -128 202 -174 174 -102 185 -52 51 -128 177 -358 101 -96 145 -126 75 -184 135 -558 51 -186 211 -241 237 -154 203 -508 103 -562 171 -320 99 -148 127 -212 53 -472 77 -128 147 -100 105 -136 111 -322 206 -238 79 -162 51 -559 109 -198 113 -461 53 -849 159 -230 51 -306 121 -316 105 -78 105 -182 153 -234 131 -226 83 -800 105 -104 215 -52 185 -572 235 -660 97 -922 53 -517 53 -80 133 -302 53 -134 345 -78 111 -374 133 -80 157 -106 185 -184 373 -110 55 -292 129 -140 247 -240 347 -130 73 -227 75 -648 153 -128 75 -1002 155 -335 169 -404 101 -76 175 -126 103 -373 79 -402 217 -218 101 -171 301 -158 204 -76 123 -100 51 -148 251 -334 77 -211 103 -304 359 -78 105 -52 99 -560 101 -288 303 -436 131 -234 179 -252 131 -656 51 -260 129 -160 79 -106 51 -184 203 -152 103 -234 155 -200 235 -52 133 -164 324 -106 107 -82 107 -348 313 -188 79 -372 79 -549 185 -82 79 -246 265 -720 107 -788 77 -585 79 -128 75 -130 203 -76 75 -206 228 -234 79 -180 101 -532 210 -282 229 -412 103 -140 55 -54 77 -316 151 -356 51 -102 75 -272 51 -506 51 -744 329 -340 129 -104 135 -300 167 -1318 107 -186 51 -136 107 -603 107 -338 105 -492 131 -250 107 -80 109 -170 79 -162 +RAW_Data: 101 -102 109 -306 181 -330 209 -76 101 -286 79 -126 51 -156 103 -78 357 -248 77 -260 51 -76 99 -320 323 -76 99 -124 199 -632 105 -220 290 -260 125 -234 75 -272 103 -252 423 -623 81 -80 105 -264 77 -1040 51 -106 107 -1561 81 -732 107 -82 167 -327 159 -626 53 -162 53 -162 107 -238 235 -106 163 -108 105 -104 105 -136 133 -306 51 -430 129 -152 109 -86 111 -56 81 -616 161 -130 51 -514 107 -236 208 -110 193 -638 133 -82 109 -543 216 -457 111 -84 169 -1168 201 -52 75 -78 289 -284 103 -874 105 -166 81 -244 129 -54 214 -398 81 -56 137 -410 81 -268 159 -372 103 -106 83 -814 207 -230 177 -280 75 -966 51 -823 77 -102 105 -394 139 -112 81 -1292 75 -727 183 -734 51 -590 83 -242 77 -1674 105 -562 107 -484 103 -104 107 -2114 77 -2326 51 -1052 207 -594 129 -232 177 -895 51 -506 203 -671 75 -206 101 -328 77 -104 105 -132 77 -370 186 -82 79 -846 77 -1272 53 -1609 177 -406 51 -226 121 -330 51 -280 73 -3094 75 -802 236 -3347 53 -2218 51 -1176 107 -212 75 -1460 51 -714 81 -1643 105 -4782 55 -5096 51 -7167 53 -17412 53 -6530 51 -20019 51 -12370 71 -442 103 -10796 55 -1320 105 -660 51 -1854 135 -16801 77 -5863 87 -12342 119 -24656 81 -7111 101 -15641 79 -3617 75 -10578 127 -5573 77 -16152 53 -5624 51 -13975 71 -7720 79 -3760 51 -9739 77 -1892 73 -2638 153 -4570 51 -5265 53 -3429 79 -1982 53 -2154 51 -7158 53 -12468 161 -12934 79 -14244 77 -3871 105 -2482 79 -4568 99 -218 79 -17125 53 -2368 53 -10101 55 -15958 81 -2358 109 -3584 51 -6886 85 -6834 51 -4154 53 -218 53 -826 55 -7583 51 -11429 216 -1346 71 -1856 79 -982 55 -2072 51 -4033 105 -7186 79 -1506 81 -8082 53 -6530 83 -6380 109 -192 135 -6058 51 -3274 79 -6105 57 -18103 53 -1142 55 -4687 57 -12931 99 -344 53 -9300 79 -7717 75 -3774 81 -3691 105 -2780 51 -2764 75 -1030 79 -29043 79 -3611 53 -1934 79 -4819 75 -6538 53 -7104 53 -3542 55 -1969 53 -2426 105 -7239 81 -516 79 -14563 123 -2246 53 -3012 71 -900 55 -1196 51 -7049 51 -1790 53 -10358 53 -3988 81 -1214 107 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index 4759ed4db4f..0a7d529ce64 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -122,4 +122,9 @@ RAW_Data: -130 84629 -16530 199 -594 163 -562 65 -164 65 -230 1383 -100 1031 -66 RAW_Data: 12477 16271 -64 12623 -102 40819 -98 3729 -66 14371 -66 14943 -64 5931 -66 11147 -68 74641 -102 54299 -70 18441 -66 82993 -100 66161 -68 61869 -66 6627 -66 12987 -68 30427 -68 25761 -98 6305 -66 5019 -64 30857 -132 23929 -68 25129 -39378 317 -2020 311 -2010 2033 -312 2017 -282 325 -2018 291 -2024 2035 -316 2023 -276 319 -2028 297 -2032 2029 -284 2023 -314 321 -2016 319 -2012 2003 -310 2015 -318 321 -1984 327 -16000 351 -1974 321 -2020 2041 -276 2047 -288 327 -1992 327 -2000 2055 -282 2053 -274 305 -2022 301 -2014 2049 -286 2055 -274 319 -1992 329 -2006 2065 -282 2023 -316 323 -1988 303 -16008 323 -2014 315 -1990 2053 -284 2061 -274 319 -1988 319 -2038 2033 -286 2055 -264 339 -2008 289 -2034 2035 -284 2061 -262 339 -2008 287 -2040 2037 -286 2035 -268 347 -2006 317 -15988 311 -2014 343 -2014 2027 -300 2031 -258 311 -2024 323 -2028 2023 -280 2051 -318 285 -2024 309 -2002 2039 -312 2017 -318 289 -2020 293 -2028 2035 -316 2023 -276 321 -2030 299 -15982 345 -1988 345 -2014 2029 -268 2069 -258 337 -1998 321 -2024 2025 -320 2025 -276 321 -1994 331 -2000 2057 -282 2043 -282 305 -2034 291 -2024 2039 -320 2019 -278 323 -1992 333 -15976 389 -1978 321 -1986 2069 -276 2053 -288 303 -2020 315 -1980 2067 -258 2075 -258 337 -1996 321 -2030 2027 -284 2059 -274 319 -2004 319 -2016 2033 -282 2059 -264 345 -2006 289 -16006 355 -1984 315 -2018 2033 -312 2015 -284 327 -2000 329 -2000 2063 -282 2049 -284 327 -1984 319 -2018 2035 -284 2057 -264 343 -2004 289 -2032 2059 -280 2019 -316 323 -1984 321 -15968 387 -1978 321 -1984 2069 -276 2049 -288 325 -1996 303 -2004 2055 -284 2049 -278 325 -2018 321 -1984 2075 -276 2049 -288 327 -1990 325 -1996 2031 -318 2025 -278 323 -2018 289 -16010 357 -1982 315 -2018 2035 -278 2053 -288 307 -2022 321 -2000 2049 -274 2045 -284 327 -2022 311 -2014 2033 -276 2053 -286 327 -2000 323 -2000 2061 -282 2015 -316 325 -2002 289 -15994 353 -1980 357 -1990 2035 -312 2015 -286 327 -2020 289 -2022 2033 -318 2019 -278 323 -2004 319 -2016 2059 -282 2023 -316 327 -1970 321 -2018 2059 -280 2019 -318 325 -1972 321 -15988 353 -1982 357 -1972 2071 -276 2051 -288 327 -1988 323 -1996 2061 -280 2053 -284 325 -1984 321 -2014 2031 -282 2059 -276 321 -2018 289 -2036 2031 -282 2059 -276 321 -2018 319 -15984 341 -1984 343 -2016 2029 -298 2033 -258 309 -2028 321 -2032 2035 -284 2017 -298 337 -2008 289 -2034 2027 -314 2023 -310 285 -2016 321 -2014 2035 -282 2027 -308 317 -2026 297 -15982 357 -1984 345 -1982 2067 -264 2057 -258 341 -1996 317 -2026 2057 -282 2017 -318 325 -1972 319 -2018 2059 -280 2029 -302 315 -2006 319 -2006 2059 -274 2047 -276 307 RAW_Data: -2024 311 -15984 349 -2004 317 -2012 2029 -276 2047 -312 305 -2018 311 -2018 2037 -258 2077 -258 337 -1998 321 -2026 2031 -278 2043 -284 327 -2020 311 -2018 2031 -278 2051 -288 325 -2004 323 -15962 353 -2018 317 -2014 2007 -308 2019 -320 287 -2024 325 -1998 2035 -314 2025 -302 311 -2004 319 -2010 2027 -312 2011 -310 309 -2028 303 -2018 2027 -304 2007 -294 309 -2024 323 -16002 361 -1946 347 -2008 2027 -286 2045 -312 325 -1978 319 -2024 2043 -276 2049 -286 325 -1988 341 -1978 2061 -278 2049 -284 327 -1990 321 -2020 2029 -318 2021 -278 323 -2008 321 -15990 355 -1982 355 -1984 2031 -284 2049 -278 325 -2018 321 -2000 2047 -276 2049 -286 327 -1994 341 -1976 2067 -274 2043 -284 303 -2018 341 -1982 2061 -266 2069 -258 339 -1998 321 -16002 311 -2014 329 -2012 2027 -318 1999 -298 339 -2008 287 -2042 2031 -282 2027 -306 317 -2012 291 -2044 2037 -284 2033 -302 315 -2004 321 -2012 2037 -282 2027 -306 317 -2028 297 -15980 345 -2018 285 -2026 2037 -320 2017 -278 323 -2024 299 -2002 2069 -278 2055 -286 325 -2002 289 -2024 2037 -282 2063 -276 321 -2016 287 -2036 2025 -320 2023 -278 323 -2018 287 -16006 355 -1982 355 -1986 2033 -302 2039 -282 307 -2032 309 -2014 2043 -264 2057 -258 341 -1992 319 -2036 2033 -284 2029 -306 319 -2000 319 -2014 2035 -282 2061 -266 343 -2006 289 -16018 331 -2010 313 -2014 2021 -320 2017 -278 323 -2010 321 -2016 2037 -284 2033 -304 317 -2018 287 -2036 2037 -284 2025 -296 339 -1978 321 -2028 2057 -282 2021 -278 359 -1972 321 -15990 355 -1978 355 -1990 2035 -300 2015 -312 305 -2016 315 -2016 2053 -290 2013 -316 277 -2020 353 -1980 2059 -256 2077 -276 307 -2020 311 -2012 2047 -258 2073 -256 341 -1998 321 -15976 369 -1976 313 -2018 2051 -280 2043 -290 317 -2004 321 -2024 2023 -282 2053 -282 327 -2020 313 -2020 2035 -278 2055 -284 325 -1986 321 -2016 2033 -280 2049 -282 325 -2020 313 -15986 315 -2026 319 -2028 2003 -318 2013 -294 339 -2008 289 -2032 2027 -316 2019 -302 311 -2004 321 -2014 2033 -314 1995 -308 317 -2028 297 -2032 2035 -276 2023 -316 321 -2014 289 -15998 347 -2014 283 -2020 2035 -292 2031 -288 311 -2024 321 -2036 2001 -310 2027 -318 275 -2054 277 -2026 2029 -296 2027 -292 311 -2024 321 -2030 2031 -282 2033 -304 313 -2004 321 -15992 329 -2010 349 -1980 2037 -292 2051 -256 339 -1998 319 -2034 2029 -286 2055 -264 339 -1978 321 -2030 2027 -280 2043 -316 327 -1984 315 -2016 2063 -278 2041 -288 327 -1990 325 -15964 389 -1978 319 -1984 2063 -256 2055 -292 307 -2016 323 -2028 2027 -286 2057 -274 319 -2010 319 -2010 2033 -282 2061 -276 321 -2018 289 -2032 2027 -318 2021 -278 321 -2020 319 -15974 355 -1980 357 -2000 2035 RAW_Data: -254 2079 -276 309 -2016 309 -2012 2035 -296 2063 -258 337 -1992 321 -2030 2037 -286 2027 -294 333 -1978 321 -2034 2029 -286 2031 -306 315 -2008 321 -15972 355 -1984 315 -2014 2037 -310 2011 -318 323 -1984 329 -2002 2033 -316 2029 -278 323 -2026 299 -2030 2035 -278 2019 -316 325 -1980 323 -2018 2053 -252 2075 -280 327 -1984 355 -15954 345 -2008 309 -2016 2045 -266 2065 -258 341 -235740 101 -202 65 -734 133 -372 401 -68 269 -236 505 -68 235 -234 875 -68 13969 -100 14297 -70 3863 -96 59337 -104 11859 -68 17409 -68 7317 -66 11443 -64 15589 -66 4381 -98 32297 -168 45445 -100 59295 -100 41417 -66 1539 -66 23001 - +RAW_Data: 171 -316 311 -154 187 -292 343 -134 337 -136 199 -286 311 -182 157 -294 327 -160 171 -316 161 -312 159 -314 333 -170 311 -164 141 -324 305 -164 299 -176 301 -170 167 -340 133 -338 163 -312 159 -294 189 -298 165 -314 311 -180 155 -294 189 -300 165 -312 187 -284 189 -312 159 -294 189 -296 167 -314 161 -310 189 -312 159 -292 189 -296 167 -312 161 -312 159 -314 193 -268 175 -304 193 -314 163 -312 159 -312 193 -294 495 -458 161 -338 301 -168 165 -304 331 -134 199 -286 309 -184 309 -170 141 -318 331 -162 143 -316 309 -182 157 -294 189 -302 163 -312 309 -184 311 -170 141 -318 331 -162 299 -150 319 -196 139 -314 165 -334 137 -340 159 -312 161 -302 149 -318 331 -162 173 -312 161 -312 163 -300 175 -296 195 -310 163 -312 159 -312 163 -312 159 -296 189 -300 193 -284 187 -284 189 -312 159 -292 189 -298 167 -312 161 -312 189 -300 173 -294 195 -282 191 -310 485 -472 167 -300 331 -134 171 -312 333 -170 169 -290 331 -162 299 -176 155 -300 333 -162 171 -300 323 -150 145 -340 159 -320 167 -302 319 -150 319 -166 169 -312 331 -162 299 -150 319 -194 139 -314 165 -308 163 -340 133 -338 163 -312 157 -296 327 -160 171 -316 163 -310 161 -312 163 -298 177 -302 193 -314 163 -310 161 -312 163 -300 173 -300 169 -318 177 -290 189 -300 165 -312 161 -312 189 -284 185 -292 189 -300 191 -286 187 -284 191 -312 471 -486 167 -314 313 -152 159 -300 335 -162 169 -308 319 -150 319 -166 169 -312 331 -162 143 -314 311 -180 157 -294 189 -300 165 -314 309 -182 311 -168 141 -318 333 -162 299 -174 295 -194 141 -314 165 -336 137 -338 135 -338 161 -312 159 -294 327 -160 171 -316 161 -312 159 -314 191 -270 201 -278 193 -314 163 -310 161 -312 163 -300 175 -300 169 -316 177 -292 189 -300 165 -312 161 -312 189 -284 183 -294 189 -298 193 -284 187 -312 163 -312 497 -460 145 -320 325 -168 171 -290 333 -162 171 -314 305 -160 317 -168 169 -290 333 -162 173 -312 283 -182 159 -294 189 -302 165 -312 309 -182 313 -168 143 -318 331 -162 301 -148 321 -194 141 -312 167 -334 135 -340 161 -310 163 -312 159 -294 327 -160 171 -316 163 -310 161 -312 163 -300 175 -302 195 -312 163 -312 159 -312 163 -300 175 -298 169 -318 177 -290 191 -300 165 -312 161 -310 189 -284 185 -292 189 -300 191 -286 187 -312 161 -300 487 -484 151 -318 335 -138 169 -322 305 -164 171 -314 305 -190 295 -166 171 -290 333 -162 173 -312 283 -182 159 -296 191 -300 +RAW_Data: 165 -312 333 -160 311 -170 141 -318 331 -164 299 -148 321 -194 139 -316 165 -336 135 -340 133 -338 163 -300 149 -320 329 -164 171 -314 159 -312 163 -300 175 -298 193 -310 163 -312 159 -312 163 -300 175 -296 193 -312 163 -312 159 -312 163 -300 175 -298 167 -320 175 -290 191 -296 193 -286 187 -310 163 -300 175 -296 501 -458 187 -288 347 -154 151 -316 325 -162 171 -316 313 -152 301 -194 141 -316 331 -162 143 -314 311 -182 155 -294 189 -302 163 -314 309 -182 311 -168 143 -318 331 -162 301 -174 295 -194 141 -314 165 -336 135 -340 133 -338 163 -312 159 -294 327 -158 173 -314 163 -312 159 -306 173 -314 165 -306 191 -284 189 -284 189 -312 157 -294 191 -300 163 -314 187 -284 189 -284 187 -292 189 -296 165 -314 161 -312 189 -284 185 -294 189 -298 193 -286 485 -492 167 -298 323 -150 175 -302 331 -164 171 -300 321 -150 317 -166 167 -308 331 -134 171 -316 309 -182 129 -318 189 -302 163 -314 309 -182 311 -170 141 -318 331 -162 301 -148 321 -194 139 -314 167 -334 137 -338 161 -310 163 -312 159 -294 327 -160 171 -316 161 -312 159 -312 193 -270 175 -304 193 -314 163 -312 159 -312 161 -314 161 -296 189 -304 165 -312 187 -284 189 -276 173 -318 195 -278 193 -284 187 -312 163 -300 175 -298 169 -318 511 -460 147 -318 327 -168 169 -292 331 -164 171 -314 305 -160 315 -168 171 -290 333 -162 171 -314 283 -182 159 -294 189 -300 165 -314 307 -184 311 -170 141 -318 333 -162 299 -150 319 -194 141 -314 165 -336 135 -340 133 -338 163 -312 157 -294 327 -160 171 -316 163 -310 161 -304 175 -314 167 -304 191 -286 187 -284 189 -284 187 -292 189 -300 165 -312 189 -284 187 -286 185 -294 189 -296 165 -314 161 -312 187 -286 185 -294 189 -298 193 -284 485 -494 167 -298 321 -150 177 -312 313 -168 171 -292 331 -164 299 -174 151 -316 325 -162 171 -316 289 -176 151 -316 187 -296 167 -312 311 -180 307 -170 141 -318 331 -162 299 -150 319 -196 139 -314 165 -334 137 -340 159 -312 161 -302 149 -320 329 -164 171 -314 159 -312 163 -300 175 -298 193 -310 163 -312 161 -310 163 -312 161 -296 189 -302 191 -286 187 -284 189 -312 159 -292 189 -296 167 -314 161 -310 189 -284 187 -292 189 -300 193 -284 485 -494 167 -296 323 -150 175 -312 313 -170 169 -292 333 -162 299 -176 151 -314 327 -160 171 -316 291 -176 149 -316 189 -296 165 -314 309 -182 307 -168 141 -318 331 -164 299 -148 321 -194 141 -314 165 -334 137 -338 161 -312 +RAW_Data: 161 -302 147 -320 331 -162 171 -314 161 -312 163 -300 175 -296 195 -310 163 -312 159 -312 163 -300 173 -296 193 -312 163 -312 159 -312 163 -300 175 -298 169 -318 177 -290 191 -296 195 -284 189 -284 189 -312 159 -296 513 -468 159 -300 333 -162 171 -300 323 -150 171 -314 325 -162 311 -164 171 -314 305 -160 159 -296 327 -160 171 -316 161 -312 161 -312 335 -170 311 -164 141 -324 321 -154 299 -194 309 -164 143 -326 167 -314 161 -312 159 -312 163 -302 173 -300 331 -162 173 -312 161 -312 163 -300 175 -300 167 -320 153 -312 191 -296 167 -312 161 -312 189 -312 159 -292 189 -298 167 -312 161 -312 159 -314 193 -268 177 -302 193 -316 161 -312 159 -312 193 -294 497 -456 187 -312 303 -166 165 -306 331 -132 201 -286 309 -182 313 -168 143 -318 331 -162 143 -314 311 -182 157 -294 189 -302 165 -312 309 -182 311 -170 141 -318 333 -162 299 -150 319 -194 141 -314 165 -334 137 -338 161 -312 161 -300 149 -320 331 -162 171 -314 161 -310 163 -302 173 -298 193 -310 165 -310 161 -310 163 -312 161 -296 189 -300 193 -286 187 -284 189 -312 157 -294 189 -298 165 -314 161 -310 189 -284 187 -292 189 -300 193 -284 485 -494 167 -298 321 -150 171 -318 323 -162 171 -314 289 -176 297 -194 141 -314 331 -162 143 -316 309 -182 155 -294 189 -302 163 -314 309 -182 311 -168 143 -318 331 -162 301 -148 321 -194 139 -314 167 -334 137 -338 161 -310 163 -300 149 -320 331 -162 171 -314 161 -312 163 -300 173 -298 193 -310 163 -312 159 -312 163 -300 175 -296 193 -312 163 -312 159 -312 163 -300 175 -298 167 -320 175 -290 191 -296 193 -286 187 -310 163 -312 161 -296 513 -468 159 -300 333 -162 171 -302 321 -150 175 -300 333 -162 311 -162 171 -316 289 -176 153 -314 327 -160 171 -316 163 -312 159 -312 307 -168 335 -138 169 -320 307 -164 297 -176 301 -194 141 -318 165 -336 137 -338 133 -338 163 -312 159 -294 327 -160 171 -316 161 -312 161 -312 163 -298 177 -302 169 -318 177 -292 189 -298 167 -312 189 -284 189 -312 157 -294 189 -298 167 -312 161 -312 159 -312 193 -270 203 -302 169 -314 161 -312 189 -310 467 -484 145 -318 327 -168 143 -316 331 -162 173 -312 307 -160 313 -170 141 -318 331 -164 143 -342 281 -184 157 -294 189 -302 165 -312 307 -184 313 -168 141 -320 331 -162 299 -150 319 -194 141 -314 165 -336 137 -338 135 -338 161 -312 159 -294 327 -158 173 -314 163 -310 161 -312 165 -298 175 -304 193 -312 163 -312 159 -312 +RAW_Data: 163 -300 175 -298 169 -318 177 -290 191 -298 165 -314 161 -310 189 -284 185 -292 189 -298 193 -284 189 -310 163 -312 497 -460 145 -320 325 -170 169 -290 333 -162 171 -314 307 -158 317 -168 169 -290 333 -162 171 -314 281 -182 159 -296 189 -300 165 -312 309 -182 313 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -336 137 -338 135 -338 161 -312 159 -294 327 -160 173 -314 163 -312 159 -312 163 -300 175 -302 195 -312 163 -312 159 -312 163 -300 175 -298 169 -318 175 -292 189 -300 165 -312 161 -312 187 -284 185 -292 189 -300 193 -284 187 -312 161 -314 471 -486 167 -314 313 -152 159 -300 335 -162 169 -308 321 -156 329 -170 127 -318 321 -176 155 -300 333 -164 169 -302 165 -314 161 -310 329 -168 299 -166 151 -328 311 -154 331 -168 299 -178 143 -318 153 -322 167 -332 149 -320 151 -318 165 -304 321 -156 181 -290 189 -300 173 -294 177 -294 189 -302 173 -294 177 -294 189 -302 173 -294 177 -318 193 -278 173 -294 179 -292 191 -302 173 -294 177 -294 189 -302 173 -320 177 -294 195 -278 175 -318 491 -460 163 -314 333 -158 159 -294 327 -160 171 -316 311 -180 307 -170 141 -318 331 -162 143 -316 309 -182 157 -294 189 -302 165 -312 309 -182 313 -168 141 -318 331 -164 299 -148 321 -194 141 -314 165 -334 137 -338 135 -338 161 -312 159 -294 329 -158 173 -314 163 -310 161 -306 173 -314 165 -304 193 -284 187 -286 189 -276 197 -294 193 -310 163 -312 161 -310 163 -300 175 -296 193 -310 165 -284 187 -310 163 -300 175 -300 169 -318 177 -316 483 -466 187 -292 341 -134 171 -308 319 -150 179 -300 333 -164 309 -162 171 -316 313 -152 153 -316 327 -160 171 -316 163 -310 161 -312 307 -166 337 -136 171 -322 305 -164 299 -174 301 -194 141 -318 165 -336 137 -338 161 -310 163 -300 149 -320 331 -162 171 -314 161 -312 163 -300 173 -296 195 -310 163 -312 159 -312 163 -312 159 -296 189 -302 165 -312 189 -284 189 -284 185 -294 189 -296 165 -314 161 -310 189 -284 187 -294 189 -298 193 -284 485 -494 167 -298 321 -150 177 -312 313 -168 171 -290 333 -162 299 -176 151 -316 325 -162 171 -316 289 -176 151 -314 189 -296 165 -314 309 -182 305 -170 141 -318 333 -162 299 -150 319 -194 141 -314 165 -334 137 -340 133 -338 161 -302 149 -320 329 -164 171 -286 187 -312 163 -300 173 -298 193 -310 163 -312 159 -312 163 -312 159 -296 189 -302 191 -286 187 -284 189 -312 159 -292 191 -296 165 -314 161 -310 189 -284 187 -292 +RAW_Data: 189 -300 193 -284 485 -494 167 -298 321 -150 177 -300 327 -150 167 -328 305 -160 319 -168 171 -290 333 -162 171 -314 281 -184 159 -296 189 -300 165 -314 307 -184 311 -170 141 -318 333 -162 299 -150 319 -194 139 -314 167 -334 135 -340 133 -338 163 -312 159 -294 327 -158 173 -314 163 -312 159 -312 165 -298 177 -302 193 -314 163 -310 161 -312 163 -300 173 -300 167 -318 177 -292 189 -300 165 -312 161 -312 187 -284 185 -292 189 -300 191 -286 187 -284 189 -300 487 -484 149 -320 333 -138 171 -322 321 -154 151 -316 327 -160 311 -164 173 -312 307 -160 161 -298 355 -132 173 -314 163 -310 161 -312 335 -170 311 -164 143 -322 307 -164 323 -150 301 -196 141 -318 165 -334 137 -338 161 -312 161 -302 147 -320 331 -162 173 -312 161 -312 163 -300 173 -298 195 -310 163 -312 159 -312 163 -312 159 -296 189 -300 193 -284 189 -284 189 -284 185 -294 189 -296 165 -314 161 -312 189 -284 185 -294 189 -298 193 -286 485 -468 193 -296 323 -150 147 -340 313 -168 171 -292 331 -164 299 -174 151 -316 325 -160 173 -316 289 -176 149 -316 189 -294 165 -314 309 -182 307 -170 141 -318 331 -164 299 -148 321 -194 139 -314 167 -306 165 -338 133 -338 163 -312 159 -294 327 -160 173 -314 163 -312 161 -310 165 -300 175 -300 169 -318 177 -290 189 -298 165 -314 187 -284 189 -312 159 -294 189 -298 165 -314 161 -310 161 -306 173 -316 193 -280 191 -312 159 -312 163 -300 515 -460 161 -312 305 -190 135 -328 329 -134 201 -286 309 -182 311 -168 143 -318 331 -162 143 -316 309 -182 157 -294 189 -300 165 -312 309 -184 311 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -334 137 -340 159 -312 163 -300 149 -318 331 -162 173 -312 161 -312 163 -300 175 -296 195 -310 163 -312 159 -312 163 -300 173 -296 193 -312 163 -312 159 -312 163 -312 161 -298 189 -300 165 -312 161 -312 189 -312 159 -292 191 -300 191 -286 485 -468 193 -298 323 -148 147 -342 323 -160 173 -314 289 -176 297 -196 139 -314 331 -162 143 -314 311 -180 157 -292 191 -300 165 -312 311 -182 309 -170 141 -318 333 -162 299 -150 319 -194 141 -314 165 -334 137 -338 161 -312 161 -312 159 -294 329 -158 173 -314 163 -310 161 -312 165 -298 175 -304 193 -312 163 -310 161 -310 163 -302 173 -300 169 -318 175 -292 189 -300 165 -312 161 -310 189 -278 173 -316 195 -280 191 -312 159 -312 163 -300 515 -460 163 -310 305 -190 137 -328 329 -134 199 -288 309 -182 311 -168 143 -318 +RAW_Data: 331 -162 143 -316 309 -182 157 -292 191 -300 165 -312 309 -182 313 -168 141 -318 331 -164 299 -174 295 -194 141 -314 165 -334 137 -340 133 -338 163 -312 159 -292 327 -160 171 -316 163 -310 161 -312 165 -298 175 -304 193 -312 163 -312 159 -312 163 -300 175 -300 169 -316 177 -292 189 -298 167 -312 161 -310 189 -278 173 -316 193 -282 191 -312 159 -312 163 -300 515 -460 163 -310 305 -190 137 -326 331 -132 201 -286 309 -184 309 -170 141 -318 333 -162 143 -314 311 -180 159 -294 189 -300 165 -312 309 -184 311 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -336 135 -340 159 -312 163 -300 149 -320 329 -164 171 -314 159 -312 163 -300 175 -296 195 -310 163 -312 159 -312 163 -300 175 -294 195 -310 163 -312 161 -310 163 -300 175 -298 169 -318 153 -314 191 -296 193 -286 187 -284 189 -312 161 -294 509 -468 159 -298 335 -162 169 -304 323 -150 175 -300 335 -162 311 -160 173 -316 313 -152 151 -316 327 -160 171 -316 163 -312 159 -312 307 -168 335 -138 169 -322 305 -164 299 -176 299 -194 141 -316 167 -334 137 -340 159 -312 161 -302 147 -320 331 -162 173 -312 161 -312 163 -300 175 -296 193 -310 165 -310 161 -312 161 -302 173 -296 195 -310 163 -312 161 -310 163 -300 175 -298 169 -318 177 -290 189 -296 193 -286 187 -310 163 -300 175 -296 501 -484 161 -288 347 -154 151 -316 325 -160 173 -314 313 -152 301 -196 141 -314 331 -162 143 -316 309 -182 157 -294 189 -300 165 -314 309 -182 311 -168 143 -318 331 -162 301 -148 319 -196 139 -314 165 -336 137 -338 133 -338 163 -312 159 -294 327 -158 173 -316 161 -312 159 -312 163 -298 177 -302 193 -314 163 -312 159 -312 163 -300 175 -298 169 -318 177 -290 191 -298 165 -314 161 -310 189 -284 193 -292 179 -308 167 -314 161 -312 189 -302 481 -460 173 -320 303 -168 169 -294 331 -164 171 -314 307 -160 319 -168 169 -292 331 -162 143 -342 283 -182 159 -294 189 -302 165 -312 309 -184 311 -168 143 -318 331 -162 299 -150 319 -194 141 -314 165 -336 135 -340 133 -338 163 -312 159 -294 327 -158 173 -316 161 -312 159 -312 165 -298 177 -302 193 -312 163 -312 161 -310 163 -314 161 -296 189 -302 165 -312 187 -284 189 -284 185 -294 189 -296 165 -314 187 -284 189 -302 173 -294 195 -310 491 -458 163 -318 319 -156 153 -314 327 -160 171 -316 311 -152 327 -170 141 -316 331 -164 143 -314 309 -182 157 -294 189 -300 165 -314 309 -182 311 -168 143 -316 333 -162 299 -150 diff --git a/lib/subghz/blocks/math.c b/lib/subghz/blocks/math.c index 55ad7cc805a..fca50c8f8df 100644 --- a/lib/subghz/blocks/math.c +++ b/lib/subghz/blocks/math.c @@ -7,3 +7,11 @@ uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t count_bit) { } return key_reverse; } + +uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit) { + uint8_t parity = 0; + for(uint8_t i = 0; i < count_bit; i++) { + parity += bit_read(key, i); + } + return parity & 0x01; +} \ No newline at end of file diff --git a/lib/subghz/blocks/math.h b/lib/subghz/blocks/math.h index fde5191bd60..85b146ebc7e 100644 --- a/lib/subghz/blocks/math.h +++ b/lib/subghz/blocks/math.h @@ -17,3 +17,11 @@ * @return Reverse data */ uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t count_bit); + +/** + * Get parity the data bitwise. + * @param key In data + * @param count_bit number of data bits + * @return parity + */ +uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit); diff --git a/lib/subghz/protocols/came_twee.c b/lib/subghz/protocols/came_twee.c index ef352bf6061..9bf87ea2bdc 100644 --- a/lib/subghz/protocols/came_twee.c +++ b/lib/subghz/protocols/came_twee.c @@ -455,7 +455,7 @@ void subghz_protocol_decoder_came_twee_get_string(void* context, string_t output string_cat_printf( output, - "%s %dbit\r\n" + "%s %db\r\n" "Key:0x%lX%08lX\r\n" "Btn:%lX\r\n" "DIP:" DIP_PATTERN "\r\n", diff --git a/lib/subghz/protocols/honeywell_wdb.c b/lib/subghz/protocols/honeywell_wdb.c new file mode 100644 index 00000000000..2922291307c --- /dev/null +++ b/lib/subghz/protocols/honeywell_wdb.c @@ -0,0 +1,399 @@ +#include "honeywell_wdb.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocolHoneywellWDB" + +/* + * + * https://github.com/klohner/honeywell-wireless-doorbell + * + */ + +static const SubGhzBlockConst subghz_protocol_honeywell_wdb_const = { + .te_short = 160, + .te_long = 320, + .te_delta = 60, + .min_count_bit_for_found = 48, +}; + +struct SubGhzProtocolDecoderHoneywell_WDB { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + const char* device_type; + const char* alert; + uint8_t secret_knock; + uint8_t relay; + uint8_t lowbat; +}; + +struct SubGhzProtocolEncoderHoneywell_WDB { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + Honeywell_WDBDecoderStepReset = 0, + Honeywell_WDBDecoderStepFoundStartBit, + Honeywell_WDBDecoderStepSaveDuration, + Honeywell_WDBDecoderStepCheckDuration, +} Honeywell_WDBDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_honeywell_wdb_decoder = { + .alloc = subghz_protocol_decoder_honeywell_wdb_alloc, + .free = subghz_protocol_decoder_honeywell_wdb_free, + + .feed = subghz_protocol_decoder_honeywell_wdb_feed, + .reset = subghz_protocol_decoder_honeywell_wdb_reset, + + .get_hash_data = subghz_protocol_decoder_honeywell_wdb_get_hash_data, + .serialize = subghz_protocol_decoder_honeywell_wdb_serialize, + .deserialize = subghz_protocol_decoder_honeywell_wdb_deserialize, + .get_string = subghz_protocol_decoder_honeywell_wdb_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_honeywell_wdb_encoder = { + .alloc = subghz_protocol_encoder_honeywell_wdb_alloc, + .free = subghz_protocol_encoder_honeywell_wdb_free, + + .deserialize = subghz_protocol_encoder_honeywell_wdb_deserialize, + .stop = subghz_protocol_encoder_honeywell_wdb_stop, + .yield = subghz_protocol_encoder_honeywell_wdb_yield, +}; + +const SubGhzProtocol subghz_protocol_honeywell_wdb = { + .name = SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | + SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | + SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_honeywell_wdb_decoder, + .encoder = &subghz_protocol_honeywell_wdb_encoder, +}; + +void* subghz_protocol_encoder_honeywell_wdb_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderHoneywell_WDB* instance = + malloc(sizeof(SubGhzProtocolEncoderHoneywell_WDB)); + + instance->base.protocol = &subghz_protocol_honeywell_wdb; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 128; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_runing = false; + return instance; +} + +void subghz_protocol_encoder_honeywell_wdb_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderHoneywell_WDB* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance + * @return true On success + */ +static bool subghz_protocol_encoder_honeywell_wdb_get_upload( + SubGhzProtocolEncoderHoneywell_WDB* instance) { + furi_assert(instance); + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2) + 2; + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + //Send header + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_honeywell_wdb_const.te_short * 3); + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_honeywell_wdb_const.te_long); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_honeywell_wdb_const.te_short); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_honeywell_wdb_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_honeywell_wdb_const.te_long); + } + } + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_honeywell_wdb_const.te_short * 3); + return true; +} + +bool subghz_protocol_encoder_honeywell_wdb_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderHoneywell_WDB* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_honeywell_wdb_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); + + subghz_protocol_encoder_honeywell_wdb_get_upload(instance); + instance->encoder.is_runing = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_honeywell_wdb_stop(void* context) { + SubGhzProtocolEncoderHoneywell_WDB* instance = context; + instance->encoder.is_runing = false; +} + +LevelDuration subghz_protocol_encoder_honeywell_wdb_yield(void* context) { + SubGhzProtocolEncoderHoneywell_WDB* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { + instance->encoder.is_runing = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_honeywell_wdb_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderHoneywell_WDB* instance = + malloc(sizeof(SubGhzProtocolDecoderHoneywell_WDB)); + instance->base.protocol = &subghz_protocol_honeywell_wdb; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_honeywell_wdb_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell_WDB* instance = context; + free(instance); +} + +void subghz_protocol_decoder_honeywell_wdb_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell_WDB* instance = context; + instance->decoder.parser_step = Honeywell_WDBDecoderStepReset; +} + +void subghz_protocol_decoder_honeywell_wdb_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell_WDB* instance = context; + switch(instance->decoder.parser_step) { + case Honeywell_WDBDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_honeywell_wdb_const.te_short * 3) < + subghz_protocol_honeywell_wdb_const.te_delta)) { + //Found header Honeywell_WDB + instance->decoder.decode_count_bit = 0; + instance->decoder.decode_data = 0; + instance->decoder.parser_step = Honeywell_WDBDecoderStepSaveDuration; + } + break; + case Honeywell_WDBDecoderStepSaveDuration: + if(level) { //save interval + if(DURATION_DIFF(duration, subghz_protocol_honeywell_wdb_const.te_short * 3) < + subghz_protocol_honeywell_wdb_const.te_delta) { + if((instance->decoder.decode_count_bit == + subghz_protocol_honeywell_wdb_const.min_count_bit_for_found) && + ((instance->decoder.decode_data & 0x01) == + subghz_protocol_blocks_get_parity( + instance->decoder.decode_data >> 1, + subghz_protocol_honeywell_wdb_const.min_count_bit_for_found - 1))) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + instance->decoder.parser_step = Honeywell_WDBDecoderStepReset; + break; + } + instance->decoder.te_last = duration; + instance->decoder.parser_step = Honeywell_WDBDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = Honeywell_WDBDecoderStepReset; + } + break; + case Honeywell_WDBDecoderStepCheckDuration: + if(!level) { + if((DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_honeywell_wdb_const.te_short) < + subghz_protocol_honeywell_wdb_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_honeywell_wdb_const.te_long) < + subghz_protocol_honeywell_wdb_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = Honeywell_WDBDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_honeywell_wdb_const.te_long) < + subghz_protocol_honeywell_wdb_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_honeywell_wdb_const.te_short) < + subghz_protocol_honeywell_wdb_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = Honeywell_WDBDecoderStepSaveDuration; + } else + instance->decoder.parser_step = Honeywell_WDBDecoderStepReset; + } else { + instance->decoder.parser_step = Honeywell_WDBDecoderStepReset; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzProtocolDecoderHoneywell_WDB* instance + */ +static void subghz_protocol_honeywell_wdb_check_remote_controller( + SubGhzProtocolDecoderHoneywell_WDB* instance) { + /* + * + * Frame bits used in Honeywell RCWL300A, RCWL330A, Series 3, 5, 9 and all Decor Series Wireless Chimes + * 0000 0000 1111 1111 2222 2222 3333 3333 4444 4444 5555 5555 + * 7654 3210 7654 3210 7654 3210 7654 3210 7654 3210 7654 3210 + * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XX.. XXX. .... KEY DATA (any change and receiver doesn't seem to recognize signal) + * XXXX XXXX XXXX XXXX XXXX .... .... .... .... .... .... .... KEY ID (different for each transmitter) + * .... .... .... .... .... 0000 00.. 0000 0000 00.. 000. .... KEY UNKNOWN 0 (always 0 in devices I've tested) + * .... .... .... .... .... .... ..XX .... .... .... .... .... DEVICE TYPE (10 = doorbell, 01 = PIR Motion sensor) + * .... .... .... .... .... .... .... .... .... ..XX ...X XXX. FLAG DATA (may be modified for possible effects on receiver) + * .... .... .... .... .... .... .... .... .... ..XX .... .... ALERT (00 = normal, 01 or 10 = right-left halo light pattern, 11 = full volume alarm) + * .... .... .... .... .... .... .... .... .... .... ...X .... SECRET KNOCK (0 = default, 1 if doorbell is pressed 3x rapidly) + * .... .... .... .... .... .... .... .... .... .... .... X... RELAY (1 if signal is a retransmission of a received transmission, only some models) + * .... .... .... .... .... .... .... .... .... .... .... .X.. FLAG UNKNOWN (0 = default, but 1 is accepted and I don't observe any effects) + * .... .... .... .... .... .... .... .... .... .... .... ..X. LOWBAT (1 if battery is low, receiver gives low battery alert) + * .... .... .... .... .... .... .... .... .... .... .... ...X PARITY (LSB of count of set bits in previous 47 bits) + * + */ + + instance->generic.serial = (instance->generic.data >> 28) & 0xFFFFF; + switch((instance->generic.data >> 20) & 0x3) { + case 0x02: + instance->device_type = "Doorbell"; + break; + case 0x01: + instance->device_type = "PIR-Motion"; + break; + default: + instance->device_type = "Unknown"; + break; + } + + switch((instance->generic.data >> 16) & 0x3) { + case 0x00: + instance->alert = "Normal"; + break; + case 0x01: + case 0x02: + instance->alert = "High"; + break; + case 0x03: + instance->alert = "Full"; + break; + default: + instance->alert = "Unknown"; + break; + } + + instance->secret_knock = (uint8_t)((instance->generic.data >> 4) & 0x1); + instance->relay = (uint8_t)((instance->generic.data >> 3) & 0x1); + instance->lowbat = (uint8_t)((instance->generic.data >> 1) & 0x1); +} + +uint8_t subghz_protocol_decoder_honeywell_wdb_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell_WDB* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_honeywell_wdb_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzPresetDefinition* preset) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell_WDB* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool subghz_protocol_decoder_honeywell_wdb_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell_WDB* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_honeywell_wdb_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_honeywell_wdb_get_string(void* context, string_t output) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell_WDB* instance = context; + subghz_protocol_honeywell_wdb_check_remote_controller(instance); + + string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Sn:0x%05lX\r\n" + "DT:%s Al:%s\r\n" + "SK:%01lX R:%01lX LBat:%01lX\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)((instance->generic.data >> 32) & 0xFFFFFFFF), + (uint32_t)(instance->generic.data & 0xFFFFFFFF), + instance->generic.serial, + instance->device_type, + instance->alert, + instance->secret_knock, + instance->relay, + instance->lowbat); +} diff --git a/lib/subghz/protocols/honeywell_wdb.h b/lib/subghz/protocols/honeywell_wdb.h new file mode 100644 index 00000000000..012b3699674 --- /dev/null +++ b/lib/subghz/protocols/honeywell_wdb.h @@ -0,0 +1,111 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME "Honeywell" + +typedef struct SubGhzProtocolDecoderHoneywell_WDB SubGhzProtocolDecoderHoneywell_WDB; +typedef struct SubGhzProtocolEncoderHoneywell_WDB SubGhzProtocolEncoderHoneywell_WDB; + +extern const SubGhzProtocolDecoder subghz_protocol_honeywell_wdb_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_honeywell_wdb_encoder; +extern const SubGhzProtocol subghz_protocol_honeywell_wdb; + +/** + * Allocate SubGhzProtocolEncoderHoneywell_WDB. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderHoneywell_WDB* pointer to a SubGhzProtocolEncoderHoneywell_WDB instance + */ +void* subghz_protocol_encoder_honeywell_wdb_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderHoneywell_WDB. + * @param context Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance + */ +void subghz_protocol_encoder_honeywell_wdb_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_honeywell_wdb_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance + */ +void subghz_protocol_encoder_honeywell_wdb_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_honeywell_wdb_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderHoneywell_WDB. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderHoneywell_WDB* pointer to a SubGhzProtocolDecoderHoneywell_WDB instance + */ +void* subghz_protocol_decoder_honeywell_wdb_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderHoneywell_WDB. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance + */ +void subghz_protocol_decoder_honeywell_wdb_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderHoneywell_WDB. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance + */ +void subghz_protocol_decoder_honeywell_wdb_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_honeywell_wdb_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_honeywell_wdb_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderHoneywell_WDB. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzPresetDefinition + * @return true On success + */ +bool subghz_protocol_decoder_honeywell_wdb_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzPresetDefinition* preset); + +/** + * Deserialize data SubGhzProtocolDecoderHoneywell_WDB. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_honeywell_wdb_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance + * @param output Resulting text + */ +void subghz_protocol_decoder_honeywell_wdb_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/registry.c b/lib/subghz/protocols/registry.c index 89394730408..19b03cebcfd 100644 --- a/lib/subghz/protocols/registry.c +++ b/lib/subghz/protocols/registry.c @@ -1,16 +1,17 @@ #include "registry.h" const SubGhzProtocol* subghz_protocol_registry[] = { - &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, - &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, - &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, - &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, - &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, - &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, - &subghz_protocol_raw, &subghz_protocol_linear, &subghz_protocol_secplus_v2, - &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, - &subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec, - &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, + &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, + &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, + &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, + &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, + &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, + &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, + &subghz_protocol_raw, &subghz_protocol_linear, &subghz_protocol_secplus_v2, + &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, + &subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec, + &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, + &subghz_protocol_honeywell_wdb, }; diff --git a/lib/subghz/protocols/registry.h b/lib/subghz/protocols/registry.h index 97a1376d6dd..d7569513298 100644 --- a/lib/subghz/protocols/registry.h +++ b/lib/subghz/protocols/registry.h @@ -32,6 +32,7 @@ #include "bett.h" #include "doitrand.h" #include "phoenix_v2.h" +#include "honeywell_wdb.h" /** * Registration by name SubGhzProtocol. From 874eb46c93864fad91adb2b805da8bd486b5071c Mon Sep 17 00:00:00 2001 From: hedger Date: Thu, 11 Aug 2022 17:51:31 +0300 Subject: [PATCH 06/26] rpc: fixed missing read blocks (#1581) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * rpc: fixed missing read blocks * rpc: storage: restored old behavior * rpc: allocating 0 bytes for empty read Co-authored-by: あく --- applications/rpc/rpc_storage.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/applications/rpc/rpc_storage.c b/applications/rpc/rpc_storage.c index 468e1e08e54..ad6191b2fd7 100644 --- a/applications/rpc/rpc_storage.c +++ b/applications/rpc/rpc_storage.c @@ -320,16 +320,21 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex response->has_next = fs_operation_success && (size_left > 0); } else { - response->content.storage_read_response.has_file = false; + response->content.storage_read_response.file.data = + malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(0)); + response->content.storage_read_response.file.data->size = 0; + response->content.storage_read_response.has_file = true; response->has_next = false; fs_operation_success = true; } + + if(fs_operation_success) { + rpc_send_and_release(session, response); + } } while((size_left != 0) && fs_operation_success); } - if(fs_operation_success) { - rpc_send_and_release(session, response); - } else { + if(!fs_operation_success) { rpc_send_and_release_empty( session, request->command_id, rpc_system_storage_get_file_error(file)); } From aab8ce5e3a3ba044e8257d2741b2d51e7cf570d1 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Thu, 11 Aug 2022 18:16:47 +0300 Subject: [PATCH 07/26] Skip empty lines in favorites.txt (#1571) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/archive/helpers/archive_favorites.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/applications/archive/helpers/archive_favorites.c b/applications/archive/helpers/archive_favorites.c index fc0cad575f6..35199242e95 100644 --- a/applications/archive/helpers/archive_favorites.c +++ b/applications/archive/helpers/archive_favorites.c @@ -64,7 +64,7 @@ uint16_t archive_favorites_count(void* context) { break; } if(!string_size(buffer)) { - break; + continue; // Skip empty lines } ++lines; } @@ -93,7 +93,7 @@ static bool archive_favourites_rescan() { break; } if(!string_size(buffer)) { - break; + continue; } if(string_search(buffer, "/app:") == 0) { @@ -152,7 +152,7 @@ bool archive_favorites_read(void* context) { break; } if(!string_size(buffer)) { - break; + continue; } if(string_search(buffer, "/app:") == 0) { @@ -215,7 +215,7 @@ bool archive_favorites_delete(const char* format, ...) { break; } if(!string_size(buffer)) { - break; + continue; } if(string_search(buffer, filename)) { @@ -259,7 +259,7 @@ bool archive_is_favorite(const char* format, ...) { break; } if(!string_size(buffer)) { - break; + continue; } if(!string_search(buffer, filename)) { found = true; @@ -299,7 +299,7 @@ bool archive_favorites_rename(const char* src, const char* dst) { break; } if(!string_size(buffer)) { - break; + continue; } archive_file_append( From 36b8dfe655dce5310099e33aff16aa5cfa8d7453 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Thu, 11 Aug 2022 19:21:13 +0400 Subject: [PATCH 08/26] [FL-2729] SubGhz: fix bett decoder (#1573) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGhz: fix bett decoder * SubGhz: fix duration preamble bett protocol Co-authored-by: あく --- lib/subghz/protocols/bett.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/subghz/protocols/bett.c b/lib/subghz/protocols/bett.c index e32679d2790..bd3b45feb66 100644 --- a/lib/subghz/protocols/bett.c +++ b/lib/subghz/protocols/bett.c @@ -231,16 +231,16 @@ void subghz_protocol_decoder_bett_feed(void* context, bool level, uint32_t durat switch(instance->decoder.parser_step) { case BETTDecoderStepReset: - if((!level) && (DURATION_DIFF(duration, subghz_protocol_bett_const.te_short * 42) < - subghz_protocol_bett_const.te_delta * 21)) { + if((!level) && (DURATION_DIFF(duration, subghz_protocol_bett_const.te_short * 44) < + (subghz_protocol_bett_const.te_delta * 15))) { //Found Preambula instance->decoder.parser_step = BETTDecoderStepCheckDuration; } break; case BETTDecoderStepSaveDuration: if(!level) { - if(duration >= ((uint32_t)subghz_protocol_bett_const.te_short * 10 + - subghz_protocol_bett_const.te_delta)) { + if(DURATION_DIFF(duration, subghz_protocol_bett_const.te_short * 44) < + (subghz_protocol_bett_const.te_delta * 15)) { instance->decoder.parser_step = BETTDecoderStepSaveDuration; if(instance->decoder.decode_count_bit == subghz_protocol_bett_const.min_count_bit_for_found) { From a5a79c5da35b9c0fa17413d6bf11ce7fe2080510 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Thu, 11 Aug 2022 18:37:23 +0300 Subject: [PATCH 09/26] [FL-2705] RPC APP fixes #1568 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/ibutton/ibutton.c | 2 + .../ibutton/scenes/ibutton_scene_rpc.c | 10 ++-- applications/infrared/infrared.c | 2 + .../infrared/scenes/infrared_scene_rpc.c | 47 ++++++++++++++----- applications/lfrfid/lfrfid_app.cpp | 6 +++ applications/lfrfid/lfrfid_app.h | 1 - .../lfrfid/scene/lfrfid_app_scene_rpc.cpp | 32 +++++-------- .../lfrfid_debug/lfrfid_debug_app.cpp | 1 + applications/nfc/nfc.c | 2 + applications/nfc/scenes/nfc_scene_rpc.c | 14 +++--- applications/subghz/scenes/subghz_scene_rpc.c | 45 +++++++++++------- applications/subghz/subghz.c | 2 + lib/app-scened-template/view_controller.hpp | 5 +- 13 files changed, 105 insertions(+), 64 deletions(-) diff --git a/applications/ibutton/ibutton.c b/applications/ibutton/ibutton.c index b30a4c61f19..7ee1110e149 100644 --- a/applications/ibutton/ibutton.c +++ b/applications/ibutton/ibutton.c @@ -87,6 +87,8 @@ static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context) if(event == RpcAppEventSessionClose) { view_dispatcher_send_custom_event( ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose); + rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL); + ibutton->rpc_ctx = NULL; } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit); } else if(event == RpcAppEventLoadFile) { diff --git a/applications/ibutton/scenes/ibutton_scene_rpc.c b/applications/ibutton/scenes/ibutton_scene_rpc.c index a3f5eeee45b..0755c8ff81d 100644 --- a/applications/ibutton/scenes/ibutton_scene_rpc.c +++ b/applications/ibutton/scenes/ibutton_scene_rpc.c @@ -29,7 +29,7 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.event == iButtonCustomEventRpcLoad) { const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx); bool result = false; - if(arg) { + if(arg && (string_empty_p(ibutton->file_path))) { 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); @@ -51,17 +51,17 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { string_clear(key_name); result = true; + } else { + string_reset(ibutton->file_path); } } 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); + scene_manager_stop(ibutton->scene_manager); 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); + scene_manager_stop(ibutton->scene_manager); view_dispatcher_stop(ibutton->view_dispatcher); } } diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c index aef14f9b89c..3b4da647fa4 100644 --- a/applications/infrared/infrared.c +++ b/applications/infrared/infrared.c @@ -46,6 +46,8 @@ static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context if(event == RpcAppEventSessionClose) { view_dispatcher_send_custom_event( infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose); + rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL); + infrared->rpc_ctx = NULL; } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event( infrared->view_dispatcher, InfraredCustomEventTypeRpcExit); diff --git a/applications/infrared/scenes/infrared_scene_rpc.c b/applications/infrared/scenes/infrared_scene_rpc.c index bc9c8652ff2..cb5535fed9b 100644 --- a/applications/infrared/scenes/infrared_scene_rpc.c +++ b/applications/infrared/scenes/infrared_scene_rpc.c @@ -1,20 +1,28 @@ #include "../infrared_i.h" #include "gui/canvas.h" +typedef enum { + InfraredRpcStateIdle, + InfraredRpcStateLoaded, + InfraredRpcStateSending, +} InfraredRpcState; + void infrared_scene_rpc_on_enter(void* context) { Infrared* infrared = context; Popup* popup = infrared->popup; - popup_set_header(popup, "Infrared", 82, 28, AlignCenter, AlignBottom); - popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop); + popup_set_header(popup, "Infrared", 89, 42, AlignCenter, AlignBottom); + popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); - popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon + popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61); popup_set_context(popup, context); popup_set_callback(popup, infrared_popup_closed_callback); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); + scene_manager_set_scene_state(infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateIdle); + notification_message(infrared->notifications, &sequence_display_backlight_on); } @@ -24,6 +32,8 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; + InfraredRpcState state = + scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneRpc); if(event.event == InfraredCustomEventTypeBackPressed) { view_dispatcher_stop(infrared->view_dispatcher); } else if(event.event == InfraredCustomEventTypePopupClosed) { @@ -31,39 +41,51 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { } else if(event.event == InfraredCustomEventTypeRpcLoad) { bool result = false; const char* arg = rpc_system_app_get_data(infrared->rpc_ctx); - if(arg) { + if(arg && (state == InfraredRpcStateIdle)) { 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); + if(result) { + scene_manager_set_scene_state( + infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded); + } } 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); + infrared->popup, infrared->text_store[0], 89, 44, 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) { + if(arg && (state == InfraredRpcStateLoaded)) { 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; + scene_manager_set_scene_state( + infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateSending); } } 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); + bool result = false; + if(state == InfraredRpcStateSending) { + infrared_tx_stop(infrared); + result = true; + scene_manager_set_scene_state( + infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded); + } + rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result); } else if(event.event == InfraredCustomEventTypeRpcExit) { + scene_manager_stop(infrared->scene_manager); 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; + scene_manager_stop(infrared->scene_manager); view_dispatcher_stop(infrared->view_dispatcher); } } @@ -72,6 +94,9 @@ 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); + if(scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneRpc) == + InfraredRpcStateSending) { + infrared_tx_stop(infrared); + } popup_reset(infrared->popup); } diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp index 5b762ae1d90..f1a575de540 100644 --- a/applications/lfrfid/lfrfid_app.cpp +++ b/applications/lfrfid/lfrfid_app.cpp @@ -56,6 +56,9 @@ static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) { LfRfidApp::Event event; event.type = LfRfidApp::EventType::RpcSessionClose; app->view_controller.send_event(&event); + // Detach RPC + rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL); + app->rpc_ctx = NULL; } else if(rpc_event == RpcAppEventAppExit) { LfRfidApp::Event event; event.type = LfRfidApp::EventType::Exit; @@ -80,16 +83,19 @@ void LfRfidApp::run(void* _args) { rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr; rpc_system_app_set_callback(rpc_ctx, rpc_command_callback, this); rpc_system_app_send_started(rpc_ctx); + view_controller.attach_to_gui(ViewDispatcherTypeDesktop); scene_controller.add_scene(SceneType::Rpc, new LfRfidAppSceneRpc()); scene_controller.process(100, SceneType::Rpc); } else { string_set_str(file_path, args); load_key_data(file_path, &worker.key, true); + view_controller.attach_to_gui(ViewDispatcherTypeFullscreen); scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate()); scene_controller.process(100, SceneType::Emulate); } } else { + view_controller.attach_to_gui(ViewDispatcherTypeFullscreen); scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart()); scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead()); scene_controller.add_scene(SceneType::RetryConfirm, new LfRfidAppSceneRetryConfirm()); diff --git a/applications/lfrfid/lfrfid_app.h b/applications/lfrfid/lfrfid_app.h index b0d4c5898a2..db022c9aaef 100644 --- a/applications/lfrfid/lfrfid_app.h +++ b/applications/lfrfid/lfrfid_app.h @@ -101,5 +101,4 @@ class LfRfidApp { bool save_key_data(string_t path, RfidKey* key); void make_app_folder(); - //bool rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context); }; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp index 43b23628617..54a57c9a2ec 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp @@ -6,9 +6,9 @@ void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) { auto popup = app->view_controller.get(); - popup->set_header("LF RFID", 89, 30, AlignCenter, AlignTop); - popup->set_text("RPC mode", 89, 43, AlignCenter, AlignTop); - popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61); + popup->set_header("LF RFID", 89, 42, AlignCenter, AlignBottom); + popup->set_text("RPC mode", 89, 44, AlignCenter, AlignTop); + popup->set_icon(0, 12, &I_RFIDDolphinSend_97x61); app->view_controller.switch_to(); @@ -27,33 +27,25 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) { 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; - emulating = true; - - app->text_store.set("emulating\n%s", app->worker.key.get_name()); - 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); + consumed = true; bool result = false; - if(arg) { + if(arg && !emulating) { 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(); + emulating = true; + + auto popup = app->view_controller.get(); + app->text_store.set("emulating\n%s", app->worker.key.get_name()); + popup->set_text(app->text_store.text, 89, 44, AlignCenter, AlignTop); + + notification_message(app->notification, &sequence_blink_start_magenta); result = true; } } diff --git a/applications/lfrfid_debug/lfrfid_debug_app.cpp b/applications/lfrfid_debug/lfrfid_debug_app.cpp index 9cd9dcad8fb..ef970e3617a 100644 --- a/applications/lfrfid_debug/lfrfid_debug_app.cpp +++ b/applications/lfrfid_debug/lfrfid_debug_app.cpp @@ -10,6 +10,7 @@ LfRfidDebugApp::~LfRfidDebugApp() { } void LfRfidDebugApp::run() { + view_controller.attach_to_gui(ViewDispatcherTypeFullscreen); scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart()); scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune()); scene_controller.process(100); diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index 9d32e8713df..6b8843db22b 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -21,6 +21,8 @@ static void nfc_rpc_command_callback(RpcAppSystemEvent event, void* context) { if(event == RpcAppEventSessionClose) { view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcSessionClose); + rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); + nfc->rpc_ctx = NULL; } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); } else if(event == RpcAppEventLoadFile) { diff --git a/applications/nfc/scenes/nfc_scene_rpc.c b/applications/nfc/scenes/nfc_scene_rpc.c index 94beccc6b28..7a9eb450339 100644 --- a/applications/nfc/scenes/nfc_scene_rpc.c +++ b/applications/nfc/scenes/nfc_scene_rpc.c @@ -4,10 +4,10 @@ void nfc_scene_rpc_on_enter(void* context) { Nfc* nfc = context; Popup* popup = nfc->popup; - popup_set_header(popup, "NFC", 82, 28, AlignCenter, AlignBottom); - popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop); + popup_set_header(popup, "NFC", 89, 42, AlignCenter, AlignBottom); + popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); - popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon + popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); @@ -31,13 +31,11 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { consumed = true; if(event.event == NfcCustomEventViewExit) { rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventAppExit, true); + scene_manager_stop(nfc->scene_manager); 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; + scene_manager_stop(nfc->scene_manager); view_dispatcher_stop(nfc->view_dispatcher); - nfc_blink_stop(nfc); } else if(event.event == NfcCustomEventRpcLoad) { bool result = false; const char* arg = rpc_system_app_get_data(nfc->rpc_ctx); @@ -66,7 +64,7 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { 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); + popup_set_text(popup, nfc->text_store, 89, 44, AlignCenter, AlignTop); } } diff --git a/applications/subghz/scenes/subghz_scene_rpc.c b/applications/subghz/scenes/subghz_scene_rpc.c index c6f7df268b3..652499d0576 100644 --- a/applications/subghz/scenes/subghz_scene_rpc.c +++ b/applications/subghz/scenes/subghz_scene_rpc.c @@ -1,16 +1,23 @@ #include "../subghz_i.h" +typedef enum { + SubGhzRpcStateIdle, + SubGhzRpcStateLoaded, +} SubGhzRpcState; + void subghz_scene_rpc_on_enter(void* context) { SubGhz* subghz = context; Popup* popup = subghz->popup; - popup_set_header(popup, "Sub-GHz", 82, 28, AlignCenter, AlignBottom); - popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop); + popup_set_header(popup, "Sub-GHz", 89, 42, AlignCenter, AlignBottom); + popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); - popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon + popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdPopup); + scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateIdle); + notification_message(subghz->notifications, &sequence_display_backlight_on); } @@ -18,28 +25,21 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; Popup* popup = subghz->popup; bool consumed = false; + SubGhzRpcState state = scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneRpc); if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == SubGhzCustomEventSceneExit) { - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - subghz_sleep(subghz); - } + scene_manager_stop(subghz->scene_manager); 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); + scene_manager_stop(subghz->scene_manager); + view_dispatcher_stop(subghz->view_dispatcher); } else if(event.event == SubGhzCustomEventSceneRpcButtonPress) { bool result = false; - if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) { + if((subghz->txrx->txrx_state == SubGhzTxRxStateSleep) && + (state == SubGhzRpcStateLoaded)) { subghz_blink_start(subghz); result = subghz_tx_start(subghz, subghz->txrx->fff_data); result = true; @@ -57,8 +57,10 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { } else if(event.event == SubGhzCustomEventSceneRpcLoad) { bool result = false; const char* arg = rpc_system_app_get_data(subghz->rpc_ctx); - if(arg) { + if(arg && (state == SubGhzRpcStateIdle)) { if(subghz_key_load(subghz, arg, false)) { + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateLoaded); string_set_str(subghz->file_path, arg); result = true; string_t file_name; @@ -70,7 +72,7 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { SUBGHZ_MAX_LEN_NAME, "loaded\n%s", string_get_cstr(file_name)); - popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop); + popup_set_text(popup, subghz->file_name_tmp, 89, 44, AlignCenter, AlignTop); string_clear(file_name); } @@ -83,6 +85,13 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { void subghz_scene_rpc_on_exit(void* context) { SubGhz* subghz = context; + + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_tx_stop(subghz); + subghz_sleep(subghz); + subghz_blink_stop(subghz); + } + Popup* popup = subghz->popup; popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 3770d52c14e..4eb4bbd689c 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -32,6 +32,8 @@ static void subghz_rpc_command_callback(RpcAppSystemEvent event, void* context) if(event == RpcAppEventSessionClose) { view_dispatcher_send_custom_event( subghz->view_dispatcher, SubGhzCustomEventSceneRpcSessionClose); + rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL); + subghz->rpc_ctx = NULL; } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit); } else if(event == RpcAppEventLoadFile) { diff --git a/lib/app-scened-template/view_controller.hpp b/lib/app-scened-template/view_controller.hpp index d08751c581f..15028f533f9 100644 --- a/lib/app-scened-template/view_controller.hpp +++ b/lib/app-scened-template/view_controller.hpp @@ -26,7 +26,6 @@ template class ViewController { 0)...); gui = static_cast(furi_record_open("gui")); - view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); }; ~ViewController() { @@ -96,6 +95,10 @@ template class ViewController { furi_check(result == FuriStatusOk); } + void attach_to_gui(ViewDispatcherType type) { + view_dispatcher_attach_to_gui(view_dispatcher, gui, type); + } + private: /** * @brief ViewModulesHolder From e0b184c057db27e3fa873b9a05bf3e5a3820dff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Fri, 12 Aug 2022 01:10:50 +0900 Subject: [PATCH 10/26] Scripts: add new region to otp generator (#1582) --- scripts/otp.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/otp.py b/scripts/otp.py index 7b2378d1205..48056fd2ac9 100755 --- a/scripts/otp.py +++ b/scripts/otp.py @@ -24,6 +24,7 @@ "eu_ru": 0x01, "us_ca_au": 0x02, "jp": 0x03, + "world": 0x04, } OTP_DISPLAYS = { From 1db7632041687a546ffbdc7ddfc75aaceb48bc09 Mon Sep 17 00:00:00 2001 From: Yukai Li Date: Fri, 12 Aug 2022 03:01:25 -0600 Subject: [PATCH 11/26] fbt: clear PYTHONPATH in env setup (#1585) --- scripts/toolchain/fbtenv.cmd | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/toolchain/fbtenv.cmd b/scripts/toolchain/fbtenv.cmd index 471ce835cb1..aac2a33091a 100644 --- a/scripts/toolchain/fbtenv.cmd +++ b/scripts/toolchain/fbtenv.cmd @@ -31,6 +31,7 @@ if not "%REAL_TOOLCHAIN_VERSION%" == "%FLIPPER_TOOLCHAIN_VERSION%" ( set "HOME=%USERPROFILE%" set "PYTHONHOME=%FBT_TOOLCHAIN_ROOT%\python" +set "PYTHONPATH=" set "PATH=%FBT_TOOLCHAIN_ROOT%\python;%FBT_TOOLCHAIN_ROOT%\bin;%FBT_TOOLCHAIN_ROOT%\protoc\bin;%FBT_TOOLCHAIN_ROOT%\openocd\bin;%PATH%" set "PROMPT=(fbt) %PROMPT%" From 6ee2c15854c3f29490697cdf85388ae5754eeba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Fri, 12 Aug 2022 19:19:29 +0900 Subject: [PATCH 12/26] FuriHal,About,Desktop: show provisioned region (#1589) Co-authored-by: hedger --- applications/about/about.c | 4 +++- applications/desktop/views/desktop_view_debug.c | 3 ++- firmware/targets/f7/furi_hal/furi_hal_version.c | 2 ++ firmware/targets/furi_hal_include/furi_hal_version.h | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/applications/about/about.c b/applications/about/about.c index f785c2e40b1..6b4489f0a3d 100644 --- a/applications/about/about.c +++ b/applications/about/about.c @@ -5,6 +5,7 @@ #include #include #include +#include #include typedef DialogMessageButton (*AboutDialogScreen)(DialogsApp* dialogs, DialogMessage* message); @@ -83,12 +84,13 @@ static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage* string_cat_printf( buffer, - "%d.F%dB%dC%d %s %s\n", + "%d.F%dB%dC%d %s:%s %s\n", furi_hal_version_get_hw_version(), furi_hal_version_get_hw_target(), furi_hal_version_get_hw_body(), furi_hal_version_get_hw_connect(), furi_hal_version_get_hw_region_name(), + furi_hal_region_get_name(), my_name ? my_name : "Unknown"); string_cat_printf(buffer, "Serial Number:\n"); diff --git a/applications/desktop/views/desktop_view_debug.c b/applications/desktop/views/desktop_view_debug.c index e2641193235..69c82bdbe2a 100644 --- a/applications/desktop/views/desktop_view_debug.c +++ b/applications/desktop/views/desktop_view_debug.c @@ -36,12 +36,13 @@ void desktop_debug_render(Canvas* canvas, void* model) { snprintf( buffer, sizeof(buffer), - "%d.F%dB%dC%d %s %s", + "%d.F%dB%dC%d %s:%s %s", furi_hal_version_get_hw_version(), furi_hal_version_get_hw_target(), furi_hal_version_get_hw_body(), furi_hal_version_get_hw_connect(), furi_hal_version_get_hw_region_name(), + furi_hal_region_get_name(), my_name ? my_name : "Unknown"); canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer); diff --git a/firmware/targets/f7/furi_hal/furi_hal_version.c b/firmware/targets/f7/furi_hal/furi_hal_version.c index 7abee281f34..0d87c807313 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_version.c +++ b/firmware/targets/f7/furi_hal/furi_hal_version.c @@ -262,6 +262,8 @@ const char* furi_hal_version_get_hw_region_name() { return "R02"; case FuriHalVersionRegionJp: return "R03"; + case FuriHalVersionRegionWorld: + return "R04"; } return "R??"; } diff --git a/firmware/targets/furi_hal_include/furi_hal_version.h b/firmware/targets/furi_hal_include/furi_hal_version.h index 500e0d8139b..720fdfd173b 100644 --- a/firmware/targets/furi_hal_include/furi_hal_version.h +++ b/firmware/targets/furi_hal_include/furi_hal_version.h @@ -41,6 +41,7 @@ typedef enum { FuriHalVersionRegionEuRu = 0x01, FuriHalVersionRegionUsCaAu = 0x02, FuriHalVersionRegionJp = 0x03, + FuriHalVersionRegionWorld = 0x04, } FuriHalVersionRegion; /** Device Display */ From c846bca280425ee463bc132f507c8f3ddd78ee29 Mon Sep 17 00:00:00 2001 From: hedger Date: Fri, 12 Aug 2022 16:40:28 +0300 Subject: [PATCH 13/26] FuriHal: do not enable LSECSS if BORRST is active (#1590) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- firmware/targets/f7/furi_hal/furi_hal_clock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.c b/firmware/targets/f7/furi_hal/furi_hal_clock.c index 09efe76dd13..a7c9b4d031d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_clock.c +++ b/firmware/targets/f7/furi_hal/furi_hal_clock.c @@ -75,7 +75,10 @@ void furi_hal_clock_init() { LL_EXTI_LINE_18); /* Why? Because that's why. See RM0434, Table 61. CPU1 vector table. */ LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_18); LL_RCC_EnableIT_LSECSS(); - LL_RCC_LSE_EnableCSS(); + /* ES0394, extended case of 2.2.2 */ + if(!LL_RCC_IsActiveFlag_BORRST()) { + LL_RCC_LSE_EnableCSS(); + } /* Main PLL configuration and activation */ LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_2, 8, LL_RCC_PLLR_DIV_2); From 1655366ef49a111af697aa9f10cc6fa6c0d5f55d Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Fri, 12 Aug 2022 16:50:04 +0300 Subject: [PATCH 14/26] [FL-2728] Fix Null Pointer Dereference errors in IR #1583 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/infrared/infrared.c | 21 ++++++++- applications/infrared/infrared_i.h | 2 + .../scenes/infrared_scene_learn_success.c | 43 ++++--------------- .../infrared/scenes/infrared_scene_remote.c | 37 +++++++++------- .../infrared/scenes/infrared_scene_rpc.c | 2 - 5 files changed, 51 insertions(+), 54 deletions(-) diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c index 3b4da647fa4..60809e7871e 100644 --- a/applications/infrared/infrared.c +++ b/applications/infrared/infrared.c @@ -295,6 +295,13 @@ bool infrared_rename_current_remote(Infrared* infrared, const char* name) { } void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { + if(infrared->app_state.is_transmitting) { + FURI_LOG_D(INFRARED_LOG_TAG, "Transmitter is already active"); + return; + } else { + infrared->app_state.is_transmitting = true; + } + if(infrared_signal_is_raw(signal)) { InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size); @@ -304,8 +311,11 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { } DOLPHIN_DEED(DolphinDeedIrSend); - infrared_worker_tx_start(infrared->worker); infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend); + + infrared_worker_tx_set_get_signal_callback( + infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); + infrared_worker_tx_start(infrared->worker); } void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) { @@ -324,7 +334,16 @@ void infrared_tx_start_received(Infrared* infrared) { } void infrared_tx_stop(Infrared* infrared) { + if(!infrared->app_state.is_transmitting) { + FURI_LOG_D(INFRARED_LOG_TAG, "Transmitter is already stopped"); + return; + } else { + infrared->app_state.is_transmitting = false; + } + infrared_worker_tx_stop(infrared->worker); + infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); } diff --git a/applications/infrared/infrared_i.h b/applications/infrared/infrared_i.h index 4e9c79d510a..9521525875f 100644 --- a/applications/infrared/infrared_i.h +++ b/applications/infrared/infrared_i.h @@ -43,6 +43,7 @@ #define INFRARED_APP_EXTENSION ".ir" #define INFRARED_DEFAULT_REMOTE_NAME "Remote" +#define INFRARED_LOG_TAG "InfraredApp" typedef enum { InfraredButtonIndexNone = -1, @@ -63,6 +64,7 @@ typedef enum { typedef struct { bool is_learning_new_remote; bool is_debug_enabled; + bool is_transmitting; InfraredEditTarget edit_target : 8; InfraredEditMode edit_mode : 8; int32_t current_button_index; diff --git a/applications/infrared/scenes/infrared_scene_learn_success.c b/applications/infrared/scenes/infrared_scene_learn_success.c index 49e2f45f009..9368c8499ad 100644 --- a/applications/infrared/scenes/infrared_scene_learn_success.c +++ b/applications/infrared/scenes/infrared_scene_learn_success.c @@ -2,11 +2,6 @@ #include -typedef enum { - InfraredSceneLearnSuccessStateIdle = 0, - InfraredSceneLearnSuccessStateSending = 1, -} InfraredSceneLearnSuccessState; - static void infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) { Infrared* infrared = context; @@ -21,9 +16,6 @@ void infrared_scene_learn_success_on_enter(void* context) { DOLPHIN_DEED(DolphinDeedIrLearnSuccess); infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn); - infrared_worker_tx_set_get_signal_callback( - infrared->worker, infrared_worker_tx_get_signal_steady_callback, context); - if(infrared_signal_is_raw(signal)) { InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter); @@ -63,57 +55,42 @@ void infrared_scene_learn_success_on_enter(void* context) { dialog_ex_set_context(dialog_ex, context); dialog_ex_enable_extended_events(dialog_ex); - scene_manager_set_scene_state( - infrared->scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx); } bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) { Infrared* infrared = context; SceneManager* scene_manager = infrared->scene_manager; - uint32_t scene_state = scene_manager_get_scene_state(scene_manager, InfraredSceneLearnSuccess); + const bool is_transmitter_idle = !infrared->app_state.is_transmitting; bool consumed = false; if(event.type == SceneManagerEventTypeTick) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { + if(is_transmitter_idle) { infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn); } consumed = true; } else if(event.type == SceneManagerEventTypeBack) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { + if(is_transmitter_idle) { scene_manager_next_scene(scene_manager, InfraredSceneAskBack); } consumed = true; } else if(event.type == SceneManagerEventTypeCustom) { if(event.event == DialogExResultLeft) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { + if(is_transmitter_idle) { scene_manager_next_scene(scene_manager, InfraredSceneAskRetry); } consumed = true; } else if(event.event == DialogExResultRight) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { + if(is_transmitter_idle) { scene_manager_next_scene(scene_manager, InfraredSceneLearnEnterName); } consumed = true; } else if(event.event == DialogExPressCenter) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { - scene_manager_set_scene_state( - scene_manager, - InfraredSceneLearnSuccess, - InfraredSceneLearnSuccessStateSending); - infrared_tx_start_received(infrared); - infrared_play_notification_message( - infrared, InfraredNotificationMessageBlinkStartSend); - } + infrared_tx_start_received(infrared); consumed = true; } else if(event.event == DialogExReleaseCenter) { - if(scene_state == InfraredSceneLearnSuccessStateSending) { - 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); - } + infrared_tx_stop(infrared); + infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); consumed = true; } } @@ -123,9 +100,5 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even 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); } diff --git a/applications/infrared/scenes/infrared_scene_remote.c b/applications/infrared/scenes/infrared_scene_remote.c index bcac58819a8..c1f5b6627ce 100644 --- a/applications/infrared/scenes/infrared_scene_remote.c +++ b/applications/infrared/scenes/infrared_scene_remote.c @@ -31,9 +31,6 @@ void infrared_scene_remote_on_enter(void* context) { ButtonMenu* button_menu = infrared->button_menu; SceneManager* scene_manager = infrared->scene_manager; - infrared_worker_tx_set_get_signal_callback( - infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); - size_t button_count = infrared_remote_get_button_count(remote); for(size_t i = 0; i < button_count; ++i) { InfraredRemoteButton* button = infrared_remote_get_button(remote, i); @@ -73,12 +70,17 @@ void infrared_scene_remote_on_enter(void* context) { bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { Infrared* infrared = context; SceneManager* scene_manager = infrared->scene_manager; + const bool is_transmitter_idle = !infrared->app_state.is_transmitting; bool consumed = false; if(event.type == SceneManagerEventTypeBack) { - const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; - consumed = scene_manager_search_and_switch_to_previous_scene_one_of( - scene_manager, possible_scenes, COUNT_OF(possible_scenes)); + if(is_transmitter_idle) { + const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; + consumed = scene_manager_search_and_switch_to_previous_scene_one_of( + scene_manager, possible_scenes, COUNT_OF(possible_scenes)); + } else { + consumed = true; + } } else if(event.type == SceneManagerEventTypeCustom) { const uint16_t custom_type = infrared_custom_event_get_type(event.event); const int16_t button_index = infrared_custom_event_get_value(event.event); @@ -92,14 +94,19 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { consumed = true; } else if(custom_type == InfraredCustomEventTypeMenuSelected) { furi_assert(button_index < 0); - scene_manager_set_scene_state( - scene_manager, InfraredSceneRemote, (unsigned)button_index); - if(button_index == ButtonIndexPlus) { - infrared->app_state.is_learning_new_remote = false; - scene_manager_next_scene(scene_manager, InfraredSceneLearn); - consumed = true; - } else if(button_index == ButtonIndexEdit) { - scene_manager_next_scene(scene_manager, InfraredSceneEdit); + if(is_transmitter_idle) { + scene_manager_set_scene_state( + scene_manager, InfraredSceneRemote, (unsigned)button_index); + if(button_index == ButtonIndexPlus) { + infrared->app_state.is_learning_new_remote = false; + scene_manager_next_scene(scene_manager, InfraredSceneLearn); + consumed = true; + } else if(button_index == ButtonIndexEdit) { + scene_manager_next_scene(scene_manager, InfraredSceneEdit); + consumed = true; + } + + } else { consumed = true; } } @@ -110,7 +117,5 @@ 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); 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 cb5535fed9b..ca7bbd8df45 100644 --- a/applications/infrared/scenes/infrared_scene_rpc.c +++ b/applications/infrared/scenes/infrared_scene_rpc.c @@ -44,8 +44,6 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(arg && (state == InfraredRpcStateIdle)) { 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); if(result) { scene_manager_set_scene_state( infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded); From 9e452d2b26acfff2e12289f925c2b609bd2a6544 Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Fri, 12 Aug 2022 17:40:26 +0300 Subject: [PATCH 15/26] [FL-2735] IR green LED fix (#1591) * Fix incorrect LED behaviour * Turn green LED off before blinking --- applications/infrared/scenes/infrared_scene_learn_success.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/applications/infrared/scenes/infrared_scene_learn_success.c b/applications/infrared/scenes/infrared_scene_learn_success.c index 9368c8499ad..466627144a0 100644 --- a/applications/infrared/scenes/infrared_scene_learn_success.c +++ b/applications/infrared/scenes/infrared_scene_learn_success.c @@ -86,11 +86,11 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even } consumed = true; } else if(event.event == DialogExPressCenter) { + infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); infrared_tx_start_received(infrared); consumed = true; } else if(event.event == DialogExReleaseCenter) { infrared_tx_stop(infrared); - infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); consumed = true; } } @@ -101,4 +101,5 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even void infrared_scene_learn_success_on_exit(void* context) { Infrared* infrared = context; dialog_ex_reset(infrared->dialog_ex); + infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); } From e1ffb4ac4d7380ed289ac75af0314e4fdcfcbf6b Mon Sep 17 00:00:00 2001 From: hedger Date: Sat, 13 Aug 2022 01:17:11 +0300 Subject: [PATCH 16/26] fbt: support for LOADER_AUTOSTART; post-build size stats (#1594) * fbt: restored LOADER_AUTOSTART support * scripts: added fwsize.py wrapper for size command; fbt: changed size post-build stats to fwsize.py call * fbt: removed size wrapper * fbt: added stats for binary flash size in pages * fbt: hint on build options details * scripts: fixed fwsize.py for *nix --- applications/applications.h | 2 ++ applications/loader/loader.c | 6 ++-- fbt_options.py | 5 +++ firmware.scons | 12 +++++-- scripts/fwsize.py | 52 +++++++++++++++++++++++++++++++ site_scons/commandline.scons | 6 ++++ site_scons/fbt/appmanifest.py | 9 ++++-- site_scons/site_tools/crosscc.py | 4 +-- site_scons/site_tools/fbt_apps.py | 2 +- site_scons/site_tools/size.py | 24 -------------- 10 files changed, 87 insertions(+), 35 deletions(-) create mode 100644 scripts/fwsize.py delete mode 100644 site_scons/site_tools/size.py diff --git a/applications/applications.h b/applications/applications.h index bebe438ab30..012e80ddb67 100644 --- a/applications/applications.h +++ b/applications/applications.h @@ -18,6 +18,8 @@ typedef struct { typedef void (*FlipperOnStartHook)(void); +extern const char* FLIPPER_AUTORUN_APP_NAME; + /* Services list * Spawned on startup */ diff --git a/applications/loader/loader.c b/applications/loader/loader.c index 3f4e876f392..9ece7f27144 100644 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -466,9 +466,9 @@ int32_t loader_srv(void* p) { furi_record_create(RECORD_LOADER, loader_instance); -#ifdef LOADER_AUTOSTART - loader_start(loader_instance, LOADER_AUTOSTART, NULL); -#endif + if(FLIPPER_AUTORUN_APP_NAME && strlen(FLIPPER_AUTORUN_APP_NAME)) { + loader_start(loader_instance, FLIPPER_AUTORUN_APP_NAME, NULL); + } while(1) { uint32_t flags = diff --git a/fbt_options.py b/fbt_options.py index 7276f579e21..b154d26aa46 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -1,5 +1,7 @@ import posixpath +# For more details on these options, run 'fbt -h' + # Default hardware target TARGET_HW = 7 @@ -59,6 +61,9 @@ # Look for blackmagic probe on serial ports and local network BLACKMAGIC = "auto" +# Application to start on boot +LOADER_AUTOSTART = "" + FIRMWARE_APPS = { "default": [ "crypto_start", diff --git a/firmware.scons b/firmware.scons index 064e0ddab63..863b35fca9f 100644 --- a/firmware.scons +++ b/firmware.scons @@ -139,7 +139,7 @@ fwenv.AppendUnique( # Depends on virtual value-only node, so it only gets rebuilt when set of apps changes apps_c = fwenv.ApplicationsC( "applications/applications.c", - Value(fwenv["APPS"]), + [Value(fwenv["APPS"]), Value(fwenv["LOADER_AUTOSTART"])], ) # Adding dependency on manifest files so apps.c is rebuilt when any manifest is changed fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", "#/applications")) @@ -210,11 +210,19 @@ fwelf = fwenv["FW_ELF"] = fwenv.Program( Depends(fwelf, lib_targets) # Output extra details after building firmware AddPostAction(fwelf, fwenv["APPBUILD_DUMP"]) -AddPostAction(fwelf, Action("@$SIZECOM")) +AddPostAction( + fwelf, + Action('${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" elf ${TARGET}', "Firmware size"), +) # Produce extra firmware files fwhex = fwenv["FW_HEX"] = fwenv.HEXBuilder("${FIRMWARE_BUILD_CFG}") fwbin = fwenv["FW_BIN"] = fwenv.BINBuilder("${FIRMWARE_BUILD_CFG}") +AddPostAction( + fwbin, + Action('@${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" bin ${TARGET}'), +) + fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}") Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_dfu", fwdfu) diff --git a/scripts/fwsize.py b/scripts/fwsize.py new file mode 100644 index 00000000000..b381f6e9a57 --- /dev/null +++ b/scripts/fwsize.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +from flipper.app import App +import subprocess +import os +import math + + +class Main(App): + def init(self): + self.subparsers = self.parser.add_subparsers(help="sub-command help") + + self.parser_elfsize = self.subparsers.add_parser("elf", help="Dump elf stats") + self.parser_elfsize.add_argument("elfname", action="store") + self.parser_elfsize.set_defaults(func=self.process_elf) + + self.parser_binsize = self.subparsers.add_parser("bin", help="Dump bin stats") + self.parser_binsize.add_argument("binname", action="store") + self.parser_binsize.set_defaults(func=self.process_bin) + + def process_elf(self): + all_sizes = subprocess.check_output( + ["arm-none-eabi-size", "-A", self.args.elfname], shell=False + ) + all_sizes = all_sizes.splitlines() + + sections_to_keep = (".text", ".rodata", ".data", ".bss", ".free_flash") + for line in all_sizes: + line = line.decode("utf-8") + parts = line.split() + if len(parts) != 3: + continue + section, size, _ = parts + if section not in sections_to_keep: + continue + print(f"{section:<11} {size:>8} ({(int(size)/1024):6.2f} K)") + + return 0 + + def process_bin(self): + PAGE_SIZE = 4096 + binsize = os.path.getsize(self.args.binname) + pages = math.ceil(binsize / PAGE_SIZE) + last_page_state = (binsize % PAGE_SIZE) * 100 / PAGE_SIZE + print( + f"{os.path.basename(self.args.binname):<11}: {pages:>4} flash pages (last page {last_page_state:.02f}% full)" + ) + return 0 + + +if __name__ == "__main__": + Main()() diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index 5a7a0dd2d55..4c96268b693 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -174,6 +174,12 @@ vars.Add( default="update_default", ) +vars.Add( + "LOADER_AUTOSTART", + help="Application name to automatically run on Flipper boot", + default="", +) + vars.Add( "FIRMWARE_APPS", diff --git a/site_scons/fbt/appmanifest.py b/site_scons/fbt/appmanifest.py index 990bd5b3b0c..aacf248eccd 100644 --- a/site_scons/fbt/appmanifest.py +++ b/site_scons/fbt/appmanifest.py @@ -200,8 +200,9 @@ class ApplicationsCGenerator: FlipperAppType.STARTUP: ("FlipperOnStartHook", "FLIPPER_ON_SYSTEM_START"), } - def __init__(self, buildset: AppBuildset): + def __init__(self, buildset: AppBuildset, autorun_app: str = ""): self.buildset = buildset + self.autorun = autorun_app def get_app_ep_forward(self, app: FlipperApplication): if app.apptype == FlipperAppType.STARTUP: @@ -219,7 +220,11 @@ def get_app_descr(self, app: FlipperApplication): .flags = {'|'.join(f"FlipperApplicationFlag{flag}" for flag in app.flags)} }}""" def generate(self): - contents = ['#include "applications.h"', "#include "] + contents = [ + '#include "applications.h"', + "#include ", + f'const char* FLIPPER_AUTORUN_APP_NAME = "{self.autorun}";', + ] for apptype in self.APP_TYPE_MAP: contents.extend( map(self.get_app_ep_forward, self.buildset.get_apps_of_type(apptype)) diff --git a/site_scons/site_tools/crosscc.py b/site_scons/site_tools/crosscc.py index dbedf5c0795..aacda58c6b3 100644 --- a/site_scons/site_tools/crosscc.py +++ b/site_scons/site_tools/crosscc.py @@ -7,7 +7,6 @@ import strip import gdb import objdump -import size from SCons.Action import _subproc import subprocess @@ -38,7 +37,7 @@ def _get_tool_version(env, tool): def generate(env, **kw): - for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump, size): + for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump): orig_tool.generate(env) env.SetDefault( TOOLCHAIN_PREFIX=kw.get("toolchain_prefix"), @@ -57,7 +56,6 @@ def generate(env, **kw): "GDB", "GDBPY", "OBJDUMP", - "SIZE", ], ) # Call CC to check version diff --git a/site_scons/site_tools/fbt_apps.py b/site_scons/site_tools/fbt_apps.py index 2cd63b70baa..3dc35049b63 100644 --- a/site_scons/site_tools/fbt_apps.py +++ b/site_scons/site_tools/fbt_apps.py @@ -51,7 +51,7 @@ def DumpApplicationConfig(target, source, env): def build_apps_c(target, source, env): target_file_name = target[0].path - gen = ApplicationsCGenerator(env["APPBUILD"]) + gen = ApplicationsCGenerator(env["APPBUILD"], env.subst("$LOADER_AUTOSTART")) with open(target_file_name, "w") as file: file.write(gen.generate()) diff --git a/site_scons/site_tools/size.py b/site_scons/site_tools/size.py deleted file mode 100644 index 56d4f3c9ef0..00000000000 --- a/site_scons/site_tools/size.py +++ /dev/null @@ -1,24 +0,0 @@ -from SCons.Builder import Builder -from SCons.Action import Action - - -def generate(env): - env.SetDefault( - SIZE="size", - SIZEFLAGS=[], - SIZECOM="$SIZE $SIZEFLAGS $TARGETS", - ) - env.Append( - BUILDERS={ - "ELFSize": Builder( - action=Action( - "${SIZECOM}", - "${SIZECOMSTR}", - ), - ), - } - ) - - -def exists(env): - return True From b3d7583f9b326adf9f4db4d80c2a57ad54364087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Tue, 16 Aug 2022 00:53:08 +0900 Subject: [PATCH 17/26] SubGhz: update notification messages (#1602) * SubGhz: update notification messages * Assets: update default notification dolphin. SubGhz: update prohibited frequency text. * FuriHal: finalize version and region link --- .../lfrfid/scene/lfrfid_app_scene_write.cpp | 2 +- .../nfc_scene_mf_ultralight_read_auth.c | 2 +- .../nfc_scene_mf_ultralight_unlock_warn.c | 2 +- .../scenes/storage_settings_scene_benchmark.c | 2 +- .../storage_settings_scene_format_confirm.c | 2 +- .../storage_settings_scene_formatting.c | 2 +- .../scenes/storage_settings_scene_sd_info.c | 2 +- .../storage_settings_scene_unmount_confirm.c | 2 +- .../scenes/storage_settings_scene_unmounted.c | 2 +- .../subghz/scenes/subghz_scene_need_saving.c | 2 +- .../scenes/subghz_scene_receiver_info.c | 2 +- .../scenes/subghz_scene_show_error_sub.c | 2 +- .../subghz/scenes/subghz_scene_show_only_rx.c | 14 ++++++++++---- applications/subghz/subghz.c | 6 ++++++ applications/subghz/subghz_i.c | 18 +++++++++--------- assets/icons/Dolphin/DolphinCommon_56x48.png | Bin 0 -> 1416 bytes .../Dolphin/DolphinFirstStart7_61x51.png | Bin 544 -> 0 bytes .../Dolphin/DolphinFirstStart8_56x51.png | Bin 1340 -> 0 bytes 18 files changed, 37 insertions(+), 25 deletions(-) create mode 100644 assets/icons/Dolphin/DolphinCommon_56x48.png delete mode 100644 assets/icons/Dolphin/DolphinFirstStart7_61x51.png delete mode 100644 assets/icons/Dolphin/DolphinFirstStart8_56x51.png diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write.cpp b/applications/lfrfid/scene/lfrfid_app_scene_write.cpp index ff7b49a4dce..274ba31582f 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_write.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_write.cpp @@ -41,7 +41,7 @@ bool LfRfidAppSceneWrite::on_event(LfRfidApp* app, LfRfidApp::Event* event) { case RfidWorker::WriteResult::NotWritable: if(!card_not_supported) { auto popup = app->view_controller.get(); - popup->set_icon(72, 14, &I_DolphinFirstStart8_56x51); + popup->set_icon(72, 17, &I_DolphinCommon_56x48); popup->set_header("Still trying to write...", 64, 3, AlignCenter, AlignTop); popup->set_text( "Make sure this\ncard is writable\nand not\nprotected.", diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c index 968157bdbf7..853ccb05570 100644 --- a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c @@ -43,7 +43,7 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState 22, AlignLeft, AlignTop); - popup_set_icon(nfc->popup, 73, 17, &I_DolphinFirstStart8_56x51); + popup_set_icon(nfc->popup, 73, 20, &I_DolphinCommon_56x48); } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadAuth, state); } diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_unlock_warn.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_unlock_warn.c index 00df98e754d..58e081db94b 100644 --- a/applications/nfc/scenes/nfc_scene_mf_ultralight_unlock_warn.c +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_unlock_warn.c @@ -16,7 +16,7 @@ void nfc_scene_mf_ultralight_unlock_warn_on_enter(void* context) { dialog_ex_set_header(dialog_ex, "Risky function!", 64, 4, AlignCenter, AlignTop); dialog_ex_set_text( dialog_ex, "Wrong password\ncan block your\ncard.", 4, 18, AlignLeft, AlignTop); - dialog_ex_set_icon(dialog_ex, 73, 17, &I_DolphinFirstStart8_56x51); + dialog_ex_set_icon(dialog_ex, 73, 20, &I_DolphinCommon_56x48); dialog_ex_set_center_button_text(dialog_ex, "OK"); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); diff --git a/applications/storage_settings/scenes/storage_settings_scene_benchmark.c b/applications/storage_settings/scenes/storage_settings_scene_benchmark.c index 615e07f8b3b..ddeea4eba02 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_benchmark.c +++ b/applications/storage_settings/scenes/storage_settings_scene_benchmark.c @@ -122,7 +122,7 @@ void storage_settings_scene_benchmark_on_enter(void* context) { view_dispatcher_switch_to_view(app->view_dispatcher, StorageSettingsViewDialogEx); if(sd_status != FSE_OK) { - dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); + dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48); 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); 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 ebf7dece42a..261ef1997d0 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_format_confirm.c +++ b/applications/storage_settings/scenes/storage_settings_scene_format_confirm.c @@ -14,7 +14,7 @@ void storage_settings_scene_format_confirm_on_enter(void* context) { FS_Error sd_status = storage_sd_status(app->fs_api); if(sd_status == FSE_NOT_READY) { - dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); + dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48); 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); diff --git a/applications/storage_settings/scenes/storage_settings_scene_formatting.c b/applications/storage_settings/scenes/storage_settings_scene_formatting.c index e0d8dfca8d4..df5e3cc17d5 100755 --- a/applications/storage_settings/scenes/storage_settings_scene_formatting.c +++ b/applications/storage_settings/scenes/storage_settings_scene_formatting.c @@ -47,7 +47,7 @@ void storage_settings_scene_formatting_on_enter(void* context) { dialog_ex_set_text( dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter); } else { - dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); + dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48); dialog_ex_set_header(dialog_ex, "Format\ncomplete!", 14, 15, AlignLeft, AlignTop); } dialog_ex_set_center_button_text(dialog_ex, "OK"); 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 485368c5541..cfb4f310dc5 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_sd_info.c +++ b/applications/storage_settings/scenes/storage_settings_scene_sd_info.c @@ -18,7 +18,7 @@ void storage_settings_scene_sd_info_on_enter(void* context) { dialog_ex_set_result_callback(dialog_ex, storage_settings_scene_sd_info_dialog_callback); if(sd_status != FSE_OK) { - dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); + dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48); 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); 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 97187071524..2b485b7f719 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_unmount_confirm.c +++ b/applications/storage_settings/scenes/storage_settings_scene_unmount_confirm.c @@ -14,7 +14,7 @@ void storage_settings_scene_unmount_confirm_on_enter(void* context) { FS_Error sd_status = storage_sd_status(app->fs_api); if(sd_status == FSE_NOT_READY) { - dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); + dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48); 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); diff --git a/applications/storage_settings/scenes/storage_settings_scene_unmounted.c b/applications/storage_settings/scenes/storage_settings_scene_unmounted.c index 43f44583d77..486f07603ad 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_unmounted.c +++ b/applications/storage_settings/scenes/storage_settings_scene_unmounted.c @@ -13,7 +13,7 @@ void storage_settings_scene_unmounted_on_enter(void* context) { DialogEx* dialog_ex = app->dialog_ex; dialog_ex_set_center_button_text(dialog_ex, "OK"); - dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51); + dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48); if(error == FSE_OK) { dialog_ex_set_header(dialog_ex, "SD Card Unmounted", 64, 3, AlignCenter, AlignTop); diff --git a/applications/subghz/scenes/subghz_scene_need_saving.c b/applications/subghz/scenes/subghz_scene_need_saving.c index eb70223a7fc..53bffedc844 100644 --- a/applications/subghz/scenes/subghz_scene_need_saving.c +++ b/applications/subghz/scenes/subghz_scene_need_saving.c @@ -16,7 +16,7 @@ void subghz_scene_need_saving_on_enter(void* context) { SubGhz* subghz = context; widget_add_string_multiline_element( - subghz->widget, 64, 13, AlignCenter, AlignCenter, FontPrimary, "Exit to Sub-Ghz menu?"); + subghz->widget, 64, 13, AlignCenter, AlignCenter, FontPrimary, "Exit to Sub-GHz menu?"); widget_add_string_multiline_element( subghz->widget, 64, diff --git a/applications/subghz/scenes/subghz_scene_receiver_info.c b/applications/subghz/scenes/subghz_scene_receiver_info.c index cbda1bc7bf0..6f3e6fd1f9c 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/subghz/scenes/subghz_scene_receiver_info.c @@ -102,7 +102,7 @@ void subghz_scene_receiver_info_on_enter(void* context) { subghz); } } else { - widget_add_icon_element(subghz->widget, 32, 12, &I_DolphinFirstStart7_61x51); + widget_add_icon_element(subghz->widget, 37, 15, &I_DolphinCommon_56x48); widget_add_string_element( subghz->widget, 13, 8, AlignLeft, AlignBottom, FontSecondary, "Error history parse."); } diff --git a/applications/subghz/scenes/subghz_scene_show_error_sub.c b/applications/subghz/scenes/subghz_scene_show_error_sub.c index 697588d0e27..74e034323e9 100644 --- a/applications/subghz/scenes/subghz_scene_show_error_sub.c +++ b/applications/subghz/scenes/subghz_scene_show_error_sub.c @@ -11,7 +11,7 @@ void subghz_scene_show_error_sub_on_enter(void* context) { // Setup view Popup* popup = subghz->popup; - popup_set_icon(popup, 72, 14, &I_DolphinFirstStart8_56x51); + popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48); popup_set_header(popup, string_get_cstr(subghz->error_str), 14, 15, AlignLeft, AlignTop); popup_set_timeout(popup, 1500); popup_set_context(popup, subghz); diff --git a/applications/subghz/scenes/subghz_scene_show_only_rx.c b/applications/subghz/scenes/subghz_scene_show_only_rx.c index 22e68c97893..3bc08e5b4da 100644 --- a/applications/subghz/scenes/subghz_scene_show_only_rx.c +++ b/applications/subghz/scenes/subghz_scene_show_only_rx.c @@ -11,12 +11,18 @@ void subghz_scene_show_only_rx_on_enter(void* context) { // Setup view Popup* popup = subghz->popup; - popup_set_icon(popup, 67, 12, &I_DolphinFirstStart7_61x51); - const char* text = "This frequency can\nonly be used for RX\nin your region"; + + const char* header_text = "Transmission is blocked"; + const char* message_text = "Transmission on\nthis frequency is\nrestricted in\nyour region"; if(!furi_hal_region_is_provisioned()) { - text = "Update Flipper to unlock frequencies allowed in your region"; + header_text = "Firmware update needed"; + message_text = "Please update\nfirmware before\nusing this feature\nflipp.dev/upd"; } - popup_set_text(popup, text, 38, 40, AlignCenter, AlignBottom); + + popup_set_header(popup, header_text, 63, 3, AlignCenter, AlignTop); + popup_set_text(popup, message_text, 0, 17, AlignLeft, AlignTop); + popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48); + popup_set_timeout(popup, 1500); popup_set_context(popup, subghz); popup_set_callback(popup, subghz_scene_show_only_rx_popup_callback); diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 4eb4bbd689c..61960218b32 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -304,6 +304,12 @@ void subghz_free(SubGhz* subghz) { int32_t subghz_app(void* p) { SubGhz* subghz = subghz_alloc(); + if(!furi_hal_region_is_provisioned()) { + subghz_dialog_message_show_only_rx(subghz); + subghz_free(subghz); + return 1; + } + //Load database bool load_database = subghz_environment_load_keystore( subghz->txrx->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index b08b658a4d8..de2df681cef 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -219,17 +219,17 @@ void subghz_dialog_message_show_only_rx(SubGhz* subghz) { DialogsApp* dialogs = subghz->dialogs; DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header(message, "Transmission is blocked", 63, 3, AlignCenter, AlignTop); + const char* header_text = "Transmission is blocked"; + const char* message_text = "Transmission on\nthis frequency is\nrestricted in\nyour region"; + if(!furi_hal_region_is_provisioned()) { + header_text = "Firmware update needed"; + message_text = "Please update\nfirmware before\nusing this feature\nflipp.dev/upd"; + } - dialog_message_set_text( - message, - "This frequency\nis restricted to\nreceiving only\nin your region.", - 3, - 17, - AlignLeft, - AlignTop); + dialog_message_set_header(message, header_text, 63, 3, AlignCenter, AlignTop); + dialog_message_set_text(message, message_text, 0, 17, AlignLeft, AlignTop); - dialog_message_set_icon(message, &I_DolphinFirstStart8_56x51, 72, 14); + dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17); dialog_message_show(dialogs, message); dialog_message_free(message); diff --git a/assets/icons/Dolphin/DolphinCommon_56x48.png b/assets/icons/Dolphin/DolphinCommon_56x48.png new file mode 100644 index 0000000000000000000000000000000000000000..089aaed83507431993a76ca25d32fdd9664c1c84 GIT binary patch literal 1416 zcmaJ>eNYr-7(dh;KXS5&nWVIBjS_NizYg|x=Pr^vz*7zxJO|P-dw2IeZq?gec9-rD zoPZchQ_6}yP{Slc4I!!28K==nodOJ_nsCY-(wOq2uZbLx!rlYU{KIi)_Wj!D_j`WN z^FGgREXdEDF)ewT&1Re7Tj(uBvlG44lnH3;I%IzsO|z`*Vr!`uv?9QOwgs{#Ld+Ki zC9n_zxxBOkx@@+IwMwAaD)#3Ik`}gun2kLe))Crfb7e+#AgzHGCc+X$b>qJuIf`S7 z?8b}I{ghw#z>uiaLknQh@LJUrqHcVYS3v97F^OZN zCe|7^J|?QzUx0Zu17e(=CM1fYFpjtLk|a4~$g}e?hGH0!VoBOT&<=s(1ct%J9~?O} z$)jW_dkX9yTX~%W*i_IM%0{ z7EmP^_pKn`<5>E(SixgJU};7`)7Hidp&+DLnizsebUk}_-GfgbN^il9b`v)f+ z{o5Zry)d<7`fHQ^uw_;+x>mcPw0&8iW69x{k92O{Q}`yFdH=5d$pbf49w1&NS)G+vhr6y}5TMsofQirRDUmKilk5=(KGouJ{H9hW=$X zgi;)vI!jl!_4H3jD(?Jz=8By|i47I&tKA1y9{nfp;_|FxKBDNWp{hN9hJ1nU?z%J6 z?>UxyzWvO}Pgc~rCZ#5%Eq+_hNS~bBdiGlT&f%%e`hHjSySR2=JuK2^+%;$R3#Wz~ z=e_mfqW23bPa0fhe)HdE5+GelU&!jS3ckUZOQ)CC5?mo zo=tzG_4|RuvPUO|mhCwA>y)1c%SWC%a4?a-x|J*?ch~+n=R7o@>p6J2dE=$stKZmK z-xoTRwET2^Wu)&1U7!Ebw!!D?x`xwQX3pMnrRwCT?`4GHt4&?|cIiI{_^XYp-np>6 xE^lPSXzOYCC4X`6tl@OB1M5_S7jml-Y~(TPp{aTIejNKZ`m*!Atyxdk{0EAy49frj literal 0 HcmV?d00001 diff --git a/assets/icons/Dolphin/DolphinFirstStart7_61x51.png b/assets/icons/Dolphin/DolphinFirstStart7_61x51.png deleted file mode 100644 index a6dd02d26fcf4e88754996db5ce6c8b0e650d87e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^wm@vm2qYMIgl$cL6id3JuOkD)#(wTUiL5}rLb6AY zF9SoB8UsT^3j@P1pisjL28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwXFy8GFUIOHC z7I;J!Gca%qfiUBxyLEqng6t)pzOL*~8D;s5^~`e*Ph((U6!vs+43W5OdePAPu!98K zgXlSPWR4u&xZnr>94m{Gk_iuHc*@8aS-en~7f|r>!u$!gr+YZ&%>Gr{C zOVgHS#W@P^E~ppCPHI(?Nl*L9Y{<|RWWe$+`JmXuJ%YCn+})YbyyHc|Hn)qaN4Idz z$mMd|bBK#A^RB}O4(S4o^8z*>&uE*Lg)>gi6DoKtXu&!@?$h{_XvN4ok{x3MNQ4x{4fSjGWfI zdxOVv4ukpG9_J(eF-NdPojWXP-vyw!2~3Im1DYqlw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6H#24v4 zq}24xJX@vryZ0+8WTx0Eg`4^s_!c;)W@LI)6{QAO`Gq7`WhYyvDB0U7*i={n4aiL` zNmQuF&B-gas<2f8n`;GRgM{^!6u?SKvTcwn|Gtf;oFfdRsx715X zOiD~nO43m-20B&qvF*KZjA*NrESfFpHX8`gOOrftYexucqiS6q^qmz?V9Vygr+LN7Bj#md6T%)s2##lY3c#mUgn)ydMy#K6+j z&BVpgz}&^f!V;#}B|o_|H#M&WrZ)wl7pMz|UQlAlEdbi=l3J8mmYU*Ll%J~r_On$c zPPaI_;xrGcHwC9#oZWEh)dxC89~84lF%1&}CLa(Jo^XL2c+yYJ1E%*PV8Tw7bKzlN zU|i?v;uunK>&lGVe1{b{+SDKZjo+D_w#~GQgX2oo#qMLTo}YKjucrd z!w!F@Ky~iIi{gQ*L34Hf2<+83tEY10Xtn0k9UGXRihh?#Q8;8bCH&4j(Xz!d8xOTj zQPJKbXO!S?Ssf_9SmU13^Q%99TwS%|x$xxH%%G~DJ$tmTB=oBNHfUS5$Z6JHNiWaT z4!zO~Ntzm(ag8?LUmWV)cg$_}y!(fA4<1Q=*)?h6ig#X<1D^&=c@pz+*P<4inZ6hA z2Oauy@3+Z}?LFRGQl4yG|I72NbeeAE8{@ODGHSP|3eH|`c1=NCawP*>^!kYXLRUg^ zb6lTTT@C$p=8^R8E&YC)Pg^4sY_*o`X?=g*K-D9|MkV^eGpBQom#uaz)iaqKv_ssc z$!K?a6emN9UY^l>{jRmYRQHPb{4HITrF-VN%i7mpwubsm?d=v#kGkPlSDM3q_T}Rw z;kuuFzUwb6JDC(ADPPJ{sb~9j&En+?mzEgs?fQB>+{EAgROR_4mo6>XB{e0oFY#@( zNLt#OMZT|32($#P`ah+oL-O_UXMv)HF-xo)CawH<>UkXV9##p4P5i1Q70uBvLFJjJ LtDnm{r-UW|7?|u3 From 560ea5f995df0a179632bcdae9075599d97a214f Mon Sep 17 00:00:00 2001 From: gornekich Date: Wed, 17 Aug 2022 18:08:13 +0300 Subject: [PATCH 18/26] [FL-2714] New NFC info screens (#1605) * nfc: add scroll element for info * widget: format lines for scroll text element * widget: fix new line generation * widget: finish element text scroll * nfc: rework ultralight and NTAG info scenes * nfc: rework mf classic info screens * nfc: rework nfca info scenes * nfc: fix mf ultralight navigation * widget: add documentation * nfc: rework bank card infO * nfc: rework device info scene * nfc: fix incorrect atqa order * mf ultralight: remove unused function * widget: add mutex for model protection * widget: fix memory leak * nfc: rework delete scene * nfc: fix selected item in saved menu scene * widget: fix naming in text scroll element * nfc: fix navigation from delete success * nfc: add dictionary icon * widget: fix memory leak --- applications/gui/modules/widget.c | 13 + applications/gui/modules/widget.h | 21 ++ .../widget_elements/widget_element_i.h | 8 + .../widget_element_text_scroll.c | 245 ++++++++++++++++++ applications/nfc/nfc.c | 9 - applications/nfc/nfc_i.h | 4 +- applications/nfc/scenes/nfc_scene_config.h | 6 +- applications/nfc/scenes/nfc_scene_delete.c | 67 ++--- .../nfc/scenes/nfc_scene_delete_success.c | 2 +- .../nfc/scenes/nfc_scene_device_info.c | 215 +++------------ applications/nfc/scenes/nfc_scene_emv_menu.c | 54 ++++ .../nfc/scenes/nfc_scene_emv_read_success.c | 102 +++----- .../nfc/scenes/nfc_scene_file_select.c | 1 + .../nfc/scenes/nfc_scene_mf_classic_info.c | 72 ----- .../nfc/scenes/nfc_scene_mf_classic_keys.c | 1 + .../nfc/scenes/nfc_scene_mf_classic_menu.c | 2 +- .../nfc_scene_mf_classic_read_success.c | 43 +-- .../nfc/scenes/nfc_scene_mf_desfire_menu.c | 17 ++ .../nfc_scene_mf_desfire_read_success.c | 101 ++++---- .../nfc/scenes/nfc_scene_mf_ultralight_data.c | 32 +++ .../nfc/scenes/nfc_scene_mf_ultralight_menu.c | 7 + .../nfc_scene_mf_ultralight_read_success.c | 74 +----- .../nfc/scenes/nfc_scene_nfc_data_info.c | 133 ++++++++++ applications/nfc/scenes/nfc_scene_nfca_menu.c | 62 +++++ .../nfc/scenes/nfc_scene_nfca_read_success.c | 72 +++++ applications/nfc/scenes/nfc_scene_read.c | 7 +- .../nfc/scenes/nfc_scene_read_card_success.c | 43 +-- .../nfc/scenes/nfc_scene_saved_menu.c | 18 +- applications/nfc/views/bank_card.c | 80 ------ applications/nfc/views/bank_card.h | 26 -- assets/icons/NFC/Keychain.png | Bin 0 -> 3750 bytes lib/nfc/nfc_device.c | 1 + lib/nfc/nfc_worker.c | 2 +- lib/nfc/parsers/nfc_supported_card.c | 14 + lib/nfc/parsers/nfc_supported_card.h | 5 +- lib/nfc/parsers/troyka_parser.c | 42 +-- lib/nfc/parsers/troyka_parser.h | 2 +- lib/nfc/protocols/mifare_ultralight.c | 44 +--- lib/nfc/protocols/mifare_ultralight.h | 12 - 39 files changed, 915 insertions(+), 744 deletions(-) create mode 100644 applications/gui/modules/widget_elements/widget_element_text_scroll.c create mode 100644 applications/nfc/scenes/nfc_scene_emv_menu.c delete mode 100644 applications/nfc/scenes/nfc_scene_mf_classic_info.c create mode 100644 applications/nfc/scenes/nfc_scene_mf_ultralight_data.c create mode 100644 applications/nfc/scenes/nfc_scene_nfc_data_info.c create mode 100644 applications/nfc/scenes/nfc_scene_nfca_menu.c create mode 100644 applications/nfc/scenes/nfc_scene_nfca_read_success.c delete mode 100755 applications/nfc/views/bank_card.c delete mode 100644 applications/nfc/views/bank_card.h create mode 100644 assets/icons/NFC/Keychain.png diff --git a/applications/gui/modules/widget.c b/applications/gui/modules/widget.c index 8d7acb013e8..b37a64701f7 100644 --- a/applications/gui/modules/widget.c +++ b/applications/gui/modules/widget.c @@ -162,6 +162,19 @@ void widget_add_text_box_element( widget_add_element(widget, text_box_element); } +void widget_add_text_scroll_element( + Widget* widget, + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + const char* text) { + furi_assert(widget); + WidgetElement* text_scroll_element = + widget_element_text_scroll_create(x, y, width, height, text); + widget_add_element(widget, text_scroll_element); +} + void widget_add_button_element( Widget* widget, GuiButtonType button_type, diff --git a/applications/gui/modules/widget.h b/applications/gui/modules/widget.h index 55af59d7c0c..587fa3c65be 100755 --- a/applications/gui/modules/widget.h +++ b/applications/gui/modules/widget.h @@ -105,6 +105,27 @@ void widget_add_text_box_element( const char* text, bool strip_to_dots); +/** Add Text Scroll Element + * + * @param widget Widget instance + * @param x x coordinate + * @param y y coordinate + * @param width width to fit text + * @param height height to fit text + * @param[in] text Formatted text. Default format: align left, Secondary font. + * The following formats are available: + * "\e#Bold text" - sets bold font before until next '\n' symbol + * "\ecBold text" - sets center horizontal align before until next '\n' symbol + * "\erBold text" - sets right horizontal align before until next '\n' symbol + */ +void widget_add_text_scroll_element( + Widget* widget, + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + const char* text); + /** Add Button Element * * @param widget Widget instance diff --git a/applications/gui/modules/widget_elements/widget_element_i.h b/applications/gui/modules/widget_elements/widget_element_i.h index bcbd4afdbc8..316ed740069 100755 --- a/applications/gui/modules/widget_elements/widget_element_i.h +++ b/applications/gui/modules/widget_elements/widget_element_i.h @@ -29,6 +29,7 @@ struct WidgetElement { // generic model holder void* model; + FuriMutex* model_mutex; // pointer to widget that hold our element Widget* parent; @@ -80,3 +81,10 @@ WidgetElement* widget_element_frame_create( uint8_t width, uint8_t height, uint8_t radius); + +WidgetElement* widget_element_text_scroll_create( + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + const char* text); diff --git a/applications/gui/modules/widget_elements/widget_element_text_scroll.c b/applications/gui/modules/widget_elements/widget_element_text_scroll.c new file mode 100644 index 00000000000..6682b106a88 --- /dev/null +++ b/applications/gui/modules/widget_elements/widget_element_text_scroll.c @@ -0,0 +1,245 @@ +#include "widget_element_i.h" +#include +#include +#include + +#define WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET (4) + +typedef struct { + Font font; + Align horizontal; + string_t text; +} TextScrollLineArray; + +ARRAY_DEF(TextScrollLineArray, TextScrollLineArray, M_POD_OPLIST) + +typedef struct { + TextScrollLineArray_t line_array; + uint8_t x; + uint8_t y; + uint8_t width; + uint8_t height; + string_t text; + uint8_t scroll_pos_total; + uint8_t scroll_pos_current; + bool text_formatted; +} WidgetElementTextScrollModel; + +static bool + widget_element_text_scroll_process_ctrl_symbols(TextScrollLineArray* line, string_t text) { + bool processed = false; + + do { + if(string_get_char(text, 0) != '\e') break; + char ctrl_symbol = string_get_char(text, 1); + if(ctrl_symbol == 'c') { + line->horizontal = AlignCenter; + } else if(ctrl_symbol == 'r') { + line->horizontal = AlignRight; + } else if(ctrl_symbol == '#') { + line->font = FontPrimary; + } + string_right(text, 2); + processed = true; + } while(false); + + return processed; +} + +void widget_element_text_scroll_add_line(WidgetElement* element, TextScrollLineArray* line) { + WidgetElementTextScrollModel* model = element->model; + TextScrollLineArray new_line; + new_line.font = line->font; + new_line.horizontal = line->horizontal; + string_init_set(new_line.text, line->text); + TextScrollLineArray_push_back(model->line_array, new_line); +} + +static void widget_element_text_scroll_fill_lines(Canvas* canvas, WidgetElement* element) { + WidgetElementTextScrollModel* model = element->model; + TextScrollLineArray line_tmp; + bool all_text_processed = false; + string_init(line_tmp.text); + bool reached_new_line = true; + uint16_t total_height = 0; + + while(!all_text_processed) { + if(reached_new_line) { + // Set default line properties + line_tmp.font = FontSecondary; + line_tmp.horizontal = AlignLeft; + string_reset(line_tmp.text); + // Process control symbols + while(widget_element_text_scroll_process_ctrl_symbols(&line_tmp, model->text)) + ; + } + // Set canvas font + canvas_set_font(canvas, line_tmp.font); + CanvasFontParameters* params = canvas_get_font_params(canvas, line_tmp.font); + total_height += params->height; + if(total_height > model->height) { + model->scroll_pos_total++; + } + + uint8_t line_width = 0; + uint16_t char_i = 0; + while(true) { + char next_char = string_get_char(model->text, char_i++); + if(next_char == '\0') { + string_push_back(line_tmp.text, '\0'); + widget_element_text_scroll_add_line(element, &line_tmp); + total_height += params->leading_default - params->height; + all_text_processed = true; + break; + } else if(next_char == '\n') { + string_push_back(line_tmp.text, '\0'); + widget_element_text_scroll_add_line(element, &line_tmp); + string_right(model->text, char_i); + total_height += params->leading_default - params->height; + reached_new_line = true; + break; + } else { + line_width += canvas_glyph_width(canvas, next_char); + if(line_width > model->width) { + string_push_back(line_tmp.text, '\0'); + widget_element_text_scroll_add_line(element, &line_tmp); + string_right(model->text, char_i - 1); + string_reset(line_tmp.text); + total_height += params->leading_default - params->height; + reached_new_line = false; + break; + } else { + string_push_back(line_tmp.text, next_char); + } + } + } + } + + string_clear(line_tmp.text); +} + +static void widget_element_text_scroll_draw(Canvas* canvas, WidgetElement* element) { + furi_assert(canvas); + furi_assert(element); + + furi_mutex_acquire(element->model_mutex, FuriWaitForever); + + WidgetElementTextScrollModel* model = element->model; + if(!model->text_formatted) { + widget_element_text_scroll_fill_lines(canvas, element); + model->text_formatted = true; + } + + uint8_t y = model->y; + uint8_t x = model->x; + uint16_t curr_line = 0; + if(TextScrollLineArray_size(model->line_array)) { + TextScrollLineArray_it_t it; + for(TextScrollLineArray_it(it, model->line_array); !TextScrollLineArray_end_p(it); + TextScrollLineArray_next(it), curr_line++) { + if(curr_line < model->scroll_pos_current) continue; + TextScrollLineArray* line = TextScrollLineArray_ref(it); + CanvasFontParameters* params = canvas_get_font_params(canvas, line->font); + if(y + params->descender > model->y + model->height) break; + canvas_set_font(canvas, line->font); + if(line->horizontal == AlignLeft) { + x = model->x; + } else if(line->horizontal == AlignCenter) { + x = (model->x + model->width) / 2; + } else if(line->horizontal == AlignRight) { + x = model->x + model->width; + } + canvas_draw_str_aligned( + canvas, x, y, line->horizontal, AlignTop, string_get_cstr(line->text)); + y += params->leading_default; + } + // Draw scroll bar + if(model->scroll_pos_total > 1) { + elements_scrollbar_pos( + canvas, + model->x + model->width + WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET, + model->y, + model->height, + model->scroll_pos_current, + model->scroll_pos_total); + } + } + + furi_mutex_release(element->model_mutex); +} + +static bool widget_element_text_scroll_input(InputEvent* event, WidgetElement* element) { + furi_assert(event); + furi_assert(element); + + furi_mutex_acquire(element->model_mutex, FuriWaitForever); + + WidgetElementTextScrollModel* model = element->model; + bool consumed = false; + + if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { + if(event->key == InputKeyUp) { + if(model->scroll_pos_current > 0) { + model->scroll_pos_current--; + } + consumed = true; + } else if(event->key == InputKeyDown) { + if((model->scroll_pos_total > 1) && + (model->scroll_pos_current < model->scroll_pos_total - 1)) { + model->scroll_pos_current++; + } + consumed = true; + } + } + + furi_mutex_release(element->model_mutex); + + return consumed; +} + +static void widget_element_text_scroll_free(WidgetElement* text_scroll) { + furi_assert(text_scroll); + + WidgetElementTextScrollModel* model = text_scroll->model; + TextScrollLineArray_it_t it; + for(TextScrollLineArray_it(it, model->line_array); !TextScrollLineArray_end_p(it); + TextScrollLineArray_next(it)) { + TextScrollLineArray* line = TextScrollLineArray_ref(it); + string_clear(line->text); + } + TextScrollLineArray_clear(model->line_array); + string_clear(model->text); + free(text_scroll->model); + furi_mutex_free(text_scroll->model_mutex); + free(text_scroll); +} + +WidgetElement* widget_element_text_scroll_create( + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + const char* text) { + furi_assert(text); + + // Allocate and init model + WidgetElementTextScrollModel* model = malloc(sizeof(WidgetElementTextScrollModel)); + model->x = x; + model->y = y; + model->width = width - WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET; + model->height = height; + model->scroll_pos_current = 0; + model->scroll_pos_total = 1; + TextScrollLineArray_init(model->line_array); + string_init_set_str(model->text, text); + + WidgetElement* text_scroll = malloc(sizeof(WidgetElement)); + text_scroll->parent = NULL; + text_scroll->draw = widget_element_text_scroll_draw; + text_scroll->input = widget_element_text_scroll_input; + text_scroll->free = widget_element_text_scroll_free; + text_scroll->model = model; + text_scroll->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); + + return text_scroll; +} diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index 6b8843db22b..3422e91af85 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -89,11 +89,6 @@ Nfc* nfc_alloc() { nfc->widget = widget_alloc(); view_dispatcher_add_view(nfc->view_dispatcher, NfcViewWidget, widget_get_view(nfc->widget)); - // Bank Card - nfc->bank_card = bank_card_alloc(); - view_dispatcher_add_view( - nfc->view_dispatcher, NfcViewBankCard, bank_card_get_view(nfc->bank_card)); - // Mifare Classic Dict Attack nfc->dict_attack = dict_attack_alloc(); view_dispatcher_add_view( @@ -159,10 +154,6 @@ void nfc_free(Nfc* nfc) { view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget); widget_free(nfc->widget); - // Bank Card - view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewBankCard); - bank_card_free(nfc->bank_card); - // Mifare Classic Dict Attack view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDictAttack); dict_attack_free(nfc->dict_attack); diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 5a916e803c4..bcfe4a21921 100644 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -25,8 +25,8 @@ #include #include #include +#include -#include "views/bank_card.h" #include "views/dict_attack.h" #include @@ -70,7 +70,6 @@ struct Nfc { ByteInput* byte_input; TextBox* text_box; Widget* widget; - BankCard* bank_card; DictAttack* dict_attack; const NfcGenerator* generator; @@ -85,7 +84,6 @@ typedef enum { NfcViewByteInput, NfcViewTextBox, NfcViewWidget, - NfcViewBankCard, NfcViewDictAttack, } NfcView; diff --git a/applications/nfc/scenes/nfc_scene_config.h b/applications/nfc/scenes/nfc_scene_config.h index 2b5cb5cf16b..ff34a11d84c 100755 --- a/applications/nfc/scenes/nfc_scene_config.h +++ b/applications/nfc/scenes/nfc_scene_config.h @@ -12,7 +12,10 @@ ADD_SCENE(nfc, save_name, SaveName) ADD_SCENE(nfc, save_success, SaveSuccess) ADD_SCENE(nfc, file_select, FileSelect) ADD_SCENE(nfc, emulate_uid, EmulateUid) +ADD_SCENE(nfc, nfca_read_success, NfcaReadSuccess) +ADD_SCENE(nfc, nfca_menu, NfcaMenu) ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess) +ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData) ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu) ADD_SCENE(nfc, mf_ultralight_emulate, MfUltralightEmulate) ADD_SCENE(nfc, mf_ultralight_read_auth, MfUltralightReadAuth) @@ -25,13 +28,13 @@ ADD_SCENE(nfc, mf_desfire_menu, MfDesfireMenu) ADD_SCENE(nfc, mf_desfire_data, MfDesfireData) ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp) ADD_SCENE(nfc, mf_classic_read_success, MfClassicReadSuccess) -ADD_SCENE(nfc, mf_classic_info, MfClassicInfo) ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu) ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate) ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys) ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd) ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack) ADD_SCENE(nfc, emv_read_success, EmvReadSuccess) +ADD_SCENE(nfc, emv_menu, EmvMenu) ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence) ADD_SCENE(nfc, device_info, DeviceInfo) ADD_SCENE(nfc, delete, Delete) @@ -45,3 +48,4 @@ ADD_SCENE(nfc, rpc, Rpc) ADD_SCENE(nfc, exit_confirm, ExitConfirm) ADD_SCENE(nfc, retry_confirm, RetryConfirm) ADD_SCENE(nfc, detect_reader, DetectReader) +ADD_SCENE(nfc, nfc_data_info, NfcDataInfo) diff --git a/applications/nfc/scenes/nfc_scene_delete.c b/applications/nfc/scenes/nfc_scene_delete.c index 1946b9290c8..987927e19c4 100755 --- a/applications/nfc/scenes/nfc_scene_delete.c +++ b/applications/nfc/scenes/nfc_scene_delete.c @@ -9,58 +9,43 @@ void nfc_scene_delete_widget_callback(GuiButtonType result, InputType type, void void nfc_scene_delete_on_enter(void* context) { Nfc* nfc = context; + FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; // Setup Custom Widget view - char temp_str[64]; - snprintf(temp_str, sizeof(temp_str), "\e#Delete %s?\e#", nfc->dev->dev_name); + string_t temp_str; + string_init(temp_str); + + string_printf(temp_str, "\e#Delete %s?\e#", nfc->dev->dev_name); widget_add_text_box_element( - nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, temp_str, false); + nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, string_get_cstr(temp_str), false); widget_add_button_element( - nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc); + nfc->widget, GuiButtonTypeLeft, "Cancel", nfc_scene_delete_widget_callback, nfc); widget_add_button_element( nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc); - FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; - if(data->uid_len == 4) { - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X", - data->uid[0], - data->uid[1], - data->uid[2], - data->uid[3]); - } else if(data->uid_len == 7) { - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X %02X %02X %02X", - data->uid[0], - data->uid[1], - data->uid[2], - data->uid[3], - data->uid[4], - data->uid[5], - data->uid[6]); + + string_set_str(temp_str, "UID:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); } - widget_add_string_element(nfc->widget, 64, 23, AlignCenter, AlignTop, FontSecondary, temp_str); + widget_add_string_element( + nfc->widget, 64, 24, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str)); - const char* protocol_name = NULL; NfcProtocol protocol = nfc->dev->dev_data.protocol; if(protocol == NfcDeviceProtocolEMV) { - protocol_name = nfc_guess_protocol(protocol); + string_set_str(temp_str, "EMV bank card"); } else if(protocol == NfcDeviceProtocolMifareUl) { - protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false); - } - if(protocol_name) { - widget_add_string_element( - nfc->widget, 10, 33, AlignLeft, AlignTop, FontSecondary, protocol_name); + string_set_str(temp_str, nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, true)); + } else if(protocol == NfcDeviceProtocolMifareClassic) { + string_set_str(temp_str, nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type)); + } else if(protocol == NfcDeviceProtocolMifareDesfire) { + string_set_str(temp_str, "MIFARE DESFire"); + } else { + string_set_str(temp_str, "Unknown ISO tag"); } - // TODO change dinamically - widget_add_string_element(nfc->widget, 118, 33, AlignRight, AlignTop, FontSecondary, "NFC-A"); - snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak); - widget_add_string_element(nfc->widget, 10, 43, AlignLeft, AlignTop, FontSecondary, temp_str); - snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]); - widget_add_string_element(nfc->widget, 118, 43, AlignRight, AlignTop, FontSecondary, temp_str); + widget_add_string_element( + nfc->widget, 64, 34, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str)); + widget_add_string_element(nfc->widget, 64, 44, AlignCenter, AlignTop, FontSecondary, "NFC-A"); + string_clear(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -71,7 +56,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { - return scene_manager_previous_scene(nfc->scene_manager); + consumed = scene_manager_previous_scene(nfc->scene_manager); } else if(event.event == GuiButtonTypeRight) { if(nfc_device_delete(nfc->dev, true)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess); diff --git a/applications/nfc/scenes/nfc_scene_delete_success.c b/applications/nfc/scenes/nfc_scene_delete_success.c index 547aeab7e0c..713b99ebf8a 100755 --- a/applications/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/nfc/scenes/nfc_scene_delete_success.c @@ -26,7 +26,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneStart); + nfc->scene_manager, NfcSceneFileSelect); } } return consumed; diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c index b79c51046a4..8228c7ea3b6 100644 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -1,11 +1,6 @@ #include "../nfc_i.h" #include "../helpers/nfc_emv_parser.h" -enum { - NfcSceneDeviceInfoUid, - NfcSceneDeviceInfoData, -}; - void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, void* context) { Nfc* nfc = context; if(type == InputTypeShort) { @@ -13,197 +8,65 @@ void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, } } -void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) { - Nfc* nfc = context; - if(result == DialogExResultLeft) { - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); - } -} - -void nfc_scene_device_info_bank_card_callback(GuiButtonType result, InputType type, void* context) { - UNUSED(result); - Nfc* nfc = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); - } -} - void nfc_scene_device_info_on_enter(void* context) { Nfc* nfc = context; + NfcDeviceData* dev_data = &nfc->dev->dev_data; - bool data_display_supported = (nfc->dev->format == NfcDeviceSaveFormatUid) || - (nfc->dev->format == NfcDeviceSaveFormatMifareUl) || - (nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) || - (nfc->dev->format == NfcDeviceSaveFormatBankCard); - // Setup Custom Widget view - widget_add_text_box_element( - nfc->widget, 0, 0, 128, 22, AlignCenter, AlignTop, nfc->dev->dev_name, false); - widget_add_button_element( - nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc); - if(data_display_supported) { - widget_add_button_element( - nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc); - } - char temp_str[32]; - FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; - if(data->uid_len == 4) { - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X", - data->uid[0], - data->uid[1], - data->uid[2], - data->uid[3]); - } else if(data->uid_len == 7) { - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X %02X %02X %02X", - data->uid[0], - data->uid[1], - data->uid[2], - data->uid[3], - data->uid[4], - data->uid[5], - data->uid[6]); - } - widget_add_string_element(nfc->widget, 64, 21, AlignCenter, AlignTop, FontSecondary, temp_str); + string_t temp_str; + string_init(temp_str); - const char* protocol_name = NULL; - NfcProtocol protocol = nfc->dev->dev_data.protocol; - if(protocol == NfcDeviceProtocolEMV || protocol == NfcDeviceProtocolMifareDesfire) { - protocol_name = nfc_guess_protocol(protocol); - } else if(protocol == NfcDeviceProtocolMifareUl) { - protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false); - } else if(protocol == NfcDeviceProtocolMifareClassic) { - protocol_name = nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type); - } - if(protocol_name) { - widget_add_string_element( - nfc->widget, 10, 32, AlignLeft, AlignTop, FontSecondary, protocol_name); - } - // TODO change dinamically - widget_add_string_element(nfc->widget, 118, 32, AlignRight, AlignTop, FontSecondary, "NFC-A"); - snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak); - widget_add_string_element(nfc->widget, 10, 42, AlignLeft, AlignTop, FontSecondary, temp_str); - snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]); - widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, temp_str); + if(dev_data->protocol == NfcDeviceProtocolEMV) { + EmvData* emv_data = &dev_data->emv_data; + string_printf(temp_str, "\e#%s\n", emv_data->name); + for(uint8_t i = 0; i < emv_data->number_len; i += 2) { + string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); + } + string_strim(temp_str); - // Setup Data View - if(nfc->dev->format == NfcDeviceSaveFormatUid) { - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_set_left_button_text(dialog_ex, "Back"); - dialog_ex_set_text(dialog_ex, "No data", 64, 32, AlignCenter, AlignCenter); - dialog_ex_set_context(dialog_ex, nfc); - dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback); - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; - TextBox* text_box = nfc->text_box; - text_box_set_font(text_box, TextBoxFontHex); - for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) { - if(!(i % 8) && i) { - string_push_back(nfc->text_box_store, '\n'); - } - string_cat_printf( - nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]); + // Add expiration date + if(emv_data->exp_mon) { + string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); } - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) { - MifareDesfireData* mf_df_data = &nfc->dev->dev_data.mf_df_data; - uint16_t n_apps = 0; - uint16_t n_files = 0; - for(MifareDesfireApplication* app = mf_df_data->app_head; app; app = app->next) { - n_apps++; - for(MifareDesfireFile* file = app->file_head; file; file = file->next) { - n_files++; + // Parse currency code + if((emv_data->currency_code)) { + string_t currency_name; + string_init(currency_name); + if(nfc_emv_parser_get_currency_name( + nfc->dev->storage, emv_data->currency_code, currency_name)) { + string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name)); } + string_clear(currency_name); } - nfc_text_store_set( - nfc, - "%d application%s, %d file%s", - n_apps, - n_apps == 1 ? "" : "s", - n_files, - n_files == 1 ? "" : "s"); - widget_add_string_element( - nfc->widget, 64, 17, AlignCenter, AlignBottom, FontSecondary, nfc->text_store); - } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { - EmvData* emv_data = &nfc->dev->dev_data.emv_data; - BankCard* bank_card = nfc->bank_card; - bank_card_set_name(bank_card, emv_data->name); - bank_card_set_number(bank_card, emv_data->number, emv_data->number_len); - bank_card_set_back_callback(bank_card, nfc_scene_device_info_bank_card_callback, nfc); - if(emv_data->exp_mon) { - bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year); - } - string_t display_str; - string_init(display_str); - if(emv_data->country_code) { + // Parse country code + if((emv_data->country_code)) { string_t country_name; string_init(country_name); if(nfc_emv_parser_get_country_name( nfc->dev->storage, emv_data->country_code, country_name)) { - string_printf(display_str, "Reg:%s", string_get_cstr(country_name)); - bank_card_set_country_name(bank_card, string_get_cstr(display_str)); + string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name)); } string_clear(country_name); } - if(emv_data->currency_code) { - string_t currency_name; - string_init(currency_name); - if(nfc_emv_parser_get_currency_name( - nfc->dev->storage, emv_data->country_code, currency_name)) { - string_printf(display_str, "Cur:%s", string_get_cstr(currency_name)); - bank_card_set_currency_name(bank_card, string_get_cstr(display_str)); - } - string_clear(currency_name); - } - string_clear(display_str); + } else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { + string_set(temp_str, nfc->dev->dev_data.parsed_data); } - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); + + widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); + + widget_add_button_element( + nfc->widget, GuiButtonTypeRight, "More", nfc_scene_device_info_widget_callback, nfc); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDeviceInfo); if(event.type == SceneManagerEventTypeCustom) { - if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeLeft)) { - consumed = scene_manager_previous_scene(nfc->scene_manager); - } else if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeRight)) { - if(nfc->dev->format == NfcDeviceSaveFormatUid) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); - consumed = true; - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); - consumed = true; - } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard); - consumed = true; - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData); - consumed = true; - } - } else if(state == NfcSceneDeviceInfoData && event.event == NfcCustomEventViewExit) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - if(state == NfcSceneDeviceInfoData) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); consumed = true; } } @@ -215,12 +78,4 @@ void nfc_scene_device_info_on_exit(void* context) { // Clear views widget_reset(nfc->widget); - if(nfc->dev->format == NfcDeviceSaveFormatUid) { - dialog_ex_reset(nfc->dialog_ex); - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - text_box_reset(nfc->text_box); - string_reset(nfc->text_box_store); - } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { - bank_card_clear(nfc->bank_card); - } } diff --git a/applications/nfc/scenes/nfc_scene_emv_menu.c b/applications/nfc/scenes/nfc_scene_emv_menu.c new file mode 100644 index 00000000000..1da630fcf13 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_emv_menu.c @@ -0,0 +1,54 @@ +#include "../nfc_i.h" + +enum SubmenuIndex { + SubmenuIndexSave, + SubmenuIndexInfo, +}; + +void nfc_scene_emv_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_emv_menu_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + submenu_add_item(submenu, "Save", SubmenuIndexSave, nfc_scene_emv_menu_submenu_callback, nfc); + submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_emv_menu_submenu_callback, nfc); + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmvMenu)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_emv_menu_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexSave) { + nfc->dev->format = NfcDeviceSaveFormatBankCard; + // Clear device name + nfc_device_set_name(nfc->dev, ""); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneEmvMenu, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_emv_menu_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + submenu_reset(nfc->submenu); +} diff --git a/applications/nfc/scenes/nfc_scene_emv_read_success.c b/applications/nfc/scenes/nfc_scene_emv_read_success.c index eefe560e38d..9cf7ff9e903 100644 --- a/applications/nfc/scenes/nfc_scene_emv_read_success.c +++ b/applications/nfc/scenes/nfc_scene_emv_read_success.c @@ -15,86 +15,49 @@ void nfc_scene_emv_read_success_widget_callback( void nfc_scene_emv_read_success_on_enter(void* context) { Nfc* nfc = context; EmvData* emv_data = &nfc->dev->dev_data.emv_data; - FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; DOLPHIN_DEED(DolphinDeedNfcReadSuccess); // Setup Custom Widget view - // Add frame - widget_add_frame_element(nfc->widget, 0, 0, 128, 64, 6); - // Add buttons widget_add_button_element( nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_emv_read_success_widget_callback, nfc); widget_add_button_element( - nfc->widget, GuiButtonTypeRight, "Save", nfc_scene_emv_read_success_widget_callback, nfc); - // Add card name - widget_add_string_element( - nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name); - // Add card number - string_t pan_str; - string_init(pan_str); + nfc->widget, GuiButtonTypeRight, "More", nfc_scene_emv_read_success_widget_callback, nfc); + + string_t temp_str; + string_init_printf(temp_str, "\e#%s\n", emv_data->name); for(uint8_t i = 0; i < emv_data->number_len; i += 2) { - string_cat_printf(pan_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); + string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); } - string_strim(pan_str); - widget_add_string_element( - nfc->widget, 64, 13, AlignCenter, AlignTop, FontSecondary, string_get_cstr(pan_str)); - string_clear(pan_str); - // Parse country code - string_t country_name; - string_init(country_name); - if((emv_data->country_code) && - nfc_emv_parser_get_country_name(nfc->dev->storage, emv_data->country_code, country_name)) { - string_t disp_country; - string_init_printf(disp_country, "Reg:%s", country_name); - widget_add_string_element( - nfc->widget, 7, 23, AlignLeft, AlignTop, FontSecondary, string_get_cstr(disp_country)); - string_clear(disp_country); + string_strim(temp_str); + + // Add expiration date + if(emv_data->exp_mon) { + string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); } - string_clear(country_name); // Parse currency code - string_t currency_name; - string_init(currency_name); - if((emv_data->currency_code) && - nfc_emv_parser_get_currency_name( - nfc->dev->storage, emv_data->currency_code, currency_name)) { - string_t disp_currency; - string_init_printf(disp_currency, "Cur:%s", currency_name); - widget_add_string_element( - nfc->widget, - 121, - 23, - AlignRight, - AlignTop, - FontSecondary, - string_get_cstr(disp_currency)); - string_clear(disp_currency); + if((emv_data->currency_code)) { + string_t currency_name; + string_init(currency_name); + if(nfc_emv_parser_get_currency_name( + nfc->dev->storage, emv_data->currency_code, currency_name)) { + string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name)); + } + string_clear(currency_name); } - string_clear(currency_name); - char temp_str[32]; - // Add ATQA - snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", nfc_data->atqa[0], nfc_data->atqa[1]); - widget_add_string_element(nfc->widget, 121, 32, AlignRight, AlignTop, FontSecondary, temp_str); - // Add UID - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X", - nfc_data->uid[0], - nfc_data->uid[1], - nfc_data->uid[2], - nfc_data->uid[3]); - widget_add_string_element(nfc->widget, 7, 42, AlignLeft, AlignTop, FontSecondary, temp_str); - // Add SAK - snprintf(temp_str, sizeof(temp_str), "SAK: %02X", nfc_data->sak); - widget_add_string_element(nfc->widget, 121, 42, AlignRight, AlignTop, FontSecondary, temp_str); - // Add expiration date - if(emv_data->exp_mon) { - char exp_str[16]; - snprintf( - exp_str, sizeof(exp_str), "Exp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); - widget_add_string_element(nfc->widget, 7, 32, AlignLeft, AlignTop, FontSecondary, exp_str); + // Parse country code + if((emv_data->country_code)) { + string_t country_name; + string_init(country_name); + if(nfc_emv_parser_get_country_name( + nfc->dev->storage, emv_data->country_code, country_name)) { + string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name)); + } + string_clear(country_name); } + widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -107,10 +70,7 @@ bool nfc_scene_emv_read_success_on_event(void* context, SceneManagerEvent event) scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); consumed = true; } else if(event.event == GuiButtonTypeRight) { - // Clear device name - nfc_device_set_name(nfc->dev, ""); - nfc->dev->format = NfcDeviceSaveFormatBankCard; - scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvMenu); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { diff --git a/applications/nfc/scenes/nfc_scene_file_select.c b/applications/nfc/scenes/nfc_scene_file_select.c index 0278c3b9ce4..693fdec2052 100755 --- a/applications/nfc/scenes/nfc_scene_file_select.c +++ b/applications/nfc/scenes/nfc_scene_file_select.c @@ -6,6 +6,7 @@ void nfc_scene_file_select_on_enter(void* context) { // Process file_select return nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc); if(nfc_file_select(nfc->dev)) { + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, 0); scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu); } else { scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart); diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_info.c b/applications/nfc/scenes/nfc_scene_mf_classic_info.c deleted file mode 100644 index b658dfa488b..00000000000 --- a/applications/nfc/scenes/nfc_scene_mf_classic_info.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "../nfc_i.h" - -void nfc_scene_mf_classic_info_widget_callback(GuiButtonType result, InputType type, void* context) { - furi_assert(context); - Nfc* nfc = context; - - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc->view_dispatcher, result); - } -} - -void nfc_scene_mf_classic_info_on_enter(void* context) { - Nfc* nfc = context; - NfcDeviceData* dev_data = &nfc->dev->dev_data; - MfClassicData* mf_data = &dev_data->mf_classic_data; - string_t str_tmp; - string_init(str_tmp); - - // Setup view - Widget* widget = nfc->widget; - - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontSecondary, mf_classic_get_type_str(mf_data->type)); - widget_add_string_element( - widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)"); - string_printf(str_tmp, "UID:"); - for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) { - string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]); - } - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - string_printf( - str_tmp, - "ATQA: %02X %02X SAK: %02X", - dev_data->nfc_data.atqa[0], - dev_data->nfc_data.atqa[1], - dev_data->nfc_data.sak); - widget_add_string_element( - widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type); - uint8_t keys_total = sectors_total * 2; - uint8_t keys_found = 0; - uint8_t sectors_read = 0; - mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found); - string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total); - widget_add_string_element( - widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total); - widget_add_string_element( - widget, 0, 55, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - - string_clear(str_tmp); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); -} - -bool nfc_scene_mf_classic_info_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_previous_scene(nfc->scene_manager); - } - - return consumed; -} - -void nfc_scene_mf_classic_info_on_exit(void* context) { - Nfc* nfc = context; - - // Clear view - widget_reset(nfc->widget); -} diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/nfc/scenes/nfc_scene_mf_classic_keys.c index 0faa7367364..fcb8bc189f7 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_keys.c +++ b/applications/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -34,6 +34,7 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str); widget_add_button_element( nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc); + widget_add_icon_element(nfc->widget, 90, 12, &I_Keychain); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_menu.c b/applications/nfc/scenes/nfc_scene_mf_classic_menu.c index 6ee0ad86818..76d02e01ea1 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_menu.c +++ b/applications/nfc/scenes/nfc_scene_mf_classic_menu.c @@ -50,7 +50,7 @@ bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event) } else if(event.event == SubmenuIndexInfo) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexInfo); - scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicInfo); + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c b/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c index bd782305cf6..efe676706d4 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c +++ b/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c @@ -17,8 +17,6 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) { Nfc* nfc = context; NfcDeviceData* dev_data = &nfc->dev->dev_data; MfClassicData* mf_data = &dev_data->mf_classic_data; - string_t str_tmp; - string_init(str_tmp); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); @@ -29,48 +27,27 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) { widget_add_button_element( widget, GuiButtonTypeRight, "More", nfc_scene_mf_classic_read_success_widget_callback, nfc); + string_t temp_str; if(string_size(nfc->dev->dev_data.parsed_data)) { - widget_add_text_box_element( - nfc->widget, - 0, - 0, - 128, - 32, - AlignLeft, - AlignTop, - string_get_cstr(nfc->dev->dev_data.parsed_data), - true); + string_init_set(temp_str, nfc->dev->dev_data.parsed_data); } else { - widget_add_string_element( - widget, - 0, - 0, - AlignLeft, - AlignTop, - FontSecondary, - mf_classic_get_type_str(mf_data->type)); - widget_add_string_element( - widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)"); - string_printf(str_tmp, "UID:"); + string_init_printf(temp_str, "\e#%s\n", nfc_mf_classic_type(mf_data->type)); + string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) { - string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]); + string_cat_printf(temp_str, " %02X", dev_data->nfc_data.uid[i]); } - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type); uint8_t keys_total = sectors_total * 2; uint8_t keys_found = 0; uint8_t sectors_read = 0; mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found); - string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total); - widget_add_string_element( - widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total); - widget_add_string_element( - widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); + string_cat_printf(temp_str, "\nKeys Found: %d/%d", keys_found, keys_total); + string_cat_printf(temp_str, "\nSectors Read: %d/%d", sectors_read, sectors_total); } - string_clear(str_tmp); + widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } diff --git a/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c b/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c index f1525114339..1e2f2d2f29d 100644 --- a/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c +++ b/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c @@ -2,6 +2,8 @@ enum SubmenuIndex { SubmenuIndexSave, + SubmenuIndexEmulateUid, + SubmenuIndexInfo, }; void nfc_scene_mf_desfire_menu_submenu_callback(void* context, uint32_t index) { @@ -16,6 +18,15 @@ void nfc_scene_mf_desfire_menu_on_enter(void* context) { submenu_add_item( submenu, "Save", SubmenuIndexSave, nfc_scene_mf_desfire_menu_submenu_callback, nfc); + submenu_add_item( + submenu, + "Emulate UID", + SubmenuIndexEmulateUid, + nfc_scene_mf_desfire_menu_submenu_callback, + nfc); + submenu_add_item( + submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_desfire_menu_submenu_callback, nfc); + submenu_set_selected_item( nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireMenu)); @@ -35,6 +46,12 @@ bool nfc_scene_mf_desfire_menu_on_event(void* context, SceneManagerEvent event) nfc_device_set_name(nfc->dev, ""); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); consumed = true; + } else if(event.event == SubmenuIndexEmulateUid) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); + consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; } } diff --git a/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c b/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c index a04f4e55c06..4827c28513d 100644 --- a/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c +++ b/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c @@ -1,90 +1,85 @@ #include "../nfc_i.h" #include -#define NFC_SCENE_READ_SUCCESS_SHIFT " " - -enum { - MfDesfireReadSuccessStateShowUID, - MfDesfireReadSuccessStateShowData, -}; - -void nfc_scene_mf_desfire_read_success_dialog_callback(DialogExResult result, void* context) { +void nfc_scene_mf_desfire_read_success_widget_callback( + GuiButtonType result, + InputType type, + void* context) { Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } } void nfc_scene_mf_desfire_read_success_on_enter(void* context) { Nfc* nfc = context; + FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data; - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_center_button_text(dialog_ex, "Data"); - dialog_ex_set_right_button_text(dialog_ex, "More"); - dialog_ex_set_icon(dialog_ex, 8, 16, &I_Medium_chip_22x21); + Widget* widget = nfc->widget; + + // Prepare string for data display + string_t temp_str; + string_init_printf(temp_str, "\e#MIFARE DESfire\n"); + string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + + uint32_t bytes_total = 1 << (data->version.sw_storage >> 1); + uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0; + string_cat_printf(temp_str, "\n%d", bytes_total); + if(data->version.sw_storage & 1) { + string_push_back(temp_str, '+'); + } + string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free); uint16_t n_apps = 0; uint16_t n_files = 0; - for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { n_apps++; for(MifareDesfireFile* file = app->file_head; file; file = file->next) { n_files++; } } + string_cat_printf(temp_str, "%d Application", n_apps); + if(n_apps != 1) { + string_push_back(temp_str, 's'); + } + string_cat_printf(temp_str, ", %d file", n_files); + if(n_files != 1) { + string_push_back(temp_str, 's'); + } - // TODO rework info view - nfc_text_store_set( - nfc, - NFC_SCENE_READ_SUCCESS_SHIFT "Mifare DESFire\n" NFC_SCENE_READ_SUCCESS_SHIFT - "%d%s bytes\n" NFC_SCENE_READ_SUCCESS_SHIFT "%d bytes free\n" - "%d application%s, %d file%s", - 1 << (data->version.sw_storage >> 1), - (data->version.sw_storage & 1) ? "+" : "", - data->free_memory ? data->free_memory->bytes : 0, - n_apps, - n_apps == 1 ? "" : "s", - n_files, - n_files == 1 ? "" : "s"); - dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 6, AlignLeft, AlignTop); - dialog_ex_set_context(dialog_ex, nfc); - dialog_ex_set_result_callback(dialog_ex, nfc_scene_mf_desfire_read_success_dialog_callback); + // Add text scroll element + widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfDesfireReadSuccess, MfDesfireReadSuccessStateShowUID); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); + // Add button elements + widget_add_button_element( + widget, GuiButtonTypeLeft, "Retry", nfc_scene_mf_desfire_read_success_widget_callback, nfc); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_scene_mf_desfire_read_success_widget_callback, nfc); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } bool nfc_scene_mf_desfire_read_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - uint32_t state = - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireReadSuccess); if(event.type == SceneManagerEventTypeCustom) { - if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultLeft) { + if(event.event == GuiButtonTypeLeft) { scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); consumed = true; - } else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultCenter) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData); - consumed = true; - } else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultRight) { + } else if(event.event == GuiButtonTypeRight) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireMenu); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { - if(state == MfDesfireReadSuccessStateShowData) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); - scene_manager_set_scene_state( - nfc->scene_manager, - NfcSceneMfDesfireReadSuccess, - MfDesfireReadSuccessStateShowUID); - consumed = true; - } else { - scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); - consumed = true; - } + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; } return consumed; @@ -94,5 +89,5 @@ void nfc_scene_mf_desfire_read_success_on_exit(void* context) { Nfc* nfc = context; // Clean dialog - dialog_ex_reset(nfc->dialog_ex); + widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_data.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_data.c new file mode 100644 index 00000000000..d4184a6b41a --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_data.c @@ -0,0 +1,32 @@ +#include "../nfc_i.h" + +void nfc_scene_mf_ultralight_data_on_enter(void* context) { + Nfc* nfc = context; + MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data; + TextBox* text_box = nfc->text_box; + + text_box_set_font(text_box, TextBoxFontHex); + for(uint16_t i = 0; i < data->data_size; i += 2) { + if(!(i % 8) && i) { + string_push_back(nfc->text_box_store, '\n'); + } + string_cat_printf(nfc->text_box_store, "%02X%02X ", data->data[i], data->data[i + 1]); + } + text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); +} + +bool nfc_scene_mf_ultralight_data_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void nfc_scene_mf_ultralight_data_on_exit(void* context) { + Nfc* nfc = context; + + // Clean view + text_box_reset(nfc->text_box); + string_reset(nfc->text_box_store); +} \ No newline at end of file diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c index 9174a8b191a..ba9f2233887 100644 --- a/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c @@ -4,6 +4,7 @@ enum SubmenuIndex { SubmenuIndexUnlock, SubmenuIndexSave, SubmenuIndexEmulate, + SubmenuIndexInfo, }; void nfc_scene_mf_ultralight_menu_submenu_callback(void* context, uint32_t index) { @@ -33,6 +34,9 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) { SubmenuIndexEmulate, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); + submenu_set_selected_item( nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu)); @@ -56,6 +60,9 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even } else if(event.event == SubmenuIndexUnlock) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu, event.event); diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c index 65750b963c3..d775bb71d90 100644 --- a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c @@ -1,11 +1,6 @@ #include "../nfc_i.h" #include -enum { - ReadMifareUlStateShowInfo, - ReadMifareUlStateShowData, -}; - void nfc_scene_mf_ultralight_read_success_widget_callback( GuiButtonType result, InputType type, @@ -31,12 +26,6 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) { "Retry", nfc_scene_mf_ultralight_read_success_widget_callback, nfc); - widget_add_button_element( - widget, - GuiButtonTypeCenter, - "Data", - nfc_scene_mf_ultralight_read_success_widget_callback, - nfc); widget_add_button_element( widget, GuiButtonTypeRight, @@ -44,71 +33,38 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) { nfc_scene_mf_ultralight_read_success_widget_callback, nfc); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontSecondary, nfc_mf_ul_type(mf_ul_data->type, true)); - string_t data_str; - string_init_printf(data_str, "UID:"); + string_t temp_str; + string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true)); + string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < data->uid_len; i++) { - string_cat_printf(data_str, " %02X", data->uid[i]); + string_cat_printf(temp_str, " %02X", data->uid[i]); } - widget_add_string_element( - widget, 0, 13, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str)); - string_printf( - data_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); - widget_add_string_element( - widget, 0, 24, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str)); + string_cat_printf( + temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); if(mf_ul_data->data_read != mf_ul_data->data_size) { - widget_add_string_element( - widget, 0, 35, AlignLeft, AlignTop, FontSecondary, "Password-protected pages!"); - } - string_clear(data_str); - - // Setup TextBox view - TextBox* text_box = nfc->text_box; - text_box_set_font(text_box, TextBoxFontHex); - for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) { - if(!(i % 8) && i) { - string_push_back(nfc->text_box_store, '\n'); - } - string_cat_printf( - nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]); + string_cat_printf(temp_str, "\nPassword-protected pages!"); } - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); + widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - uint32_t state = - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadSuccess); if(event.type == SceneManagerEventTypeCustom) { - if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeLeft) { + if(event.event == GuiButtonTypeLeft) { scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); consumed = true; - } else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeRight) { + } else if(event.event == GuiButtonTypeRight) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightMenu); consumed = true; - } else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeCenter) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowData); - consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { - if(state == ReadMifareUlStateShowData) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo); - consumed = true; - } else { - scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); - consumed = true; - } + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; } return consumed; @@ -117,8 +73,6 @@ bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEv void nfc_scene_mf_ultralight_read_success_on_exit(void* context) { Nfc* nfc = context; - // Clean views + // Clean view widget_reset(nfc->widget); - text_box_reset(nfc->text_box); - string_reset(nfc->text_box_store); } diff --git a/applications/nfc/scenes/nfc_scene_nfc_data_info.c b/applications/nfc/scenes/nfc_scene_nfc_data_info.c new file mode 100644 index 00000000000..33f5e44af6e --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_nfc_data_info.c @@ -0,0 +1,133 @@ +#include "../nfc_i.h" + +void nfc_scene_nfc_data_info_widget_callback(GuiButtonType result, InputType type, void* context) { + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_nfc_data_info_on_enter(void* context) { + Nfc* nfc = context; + Widget* widget = nfc->widget; + FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; + NfcDeviceData* dev_data = &nfc->dev->dev_data; + NfcProtocol protocol = dev_data->protocol; + uint8_t text_scroll_height = 0; + if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl)) { + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc); + text_scroll_height = 52; + } else { + text_scroll_height = 64; + } + + string_t temp_str; + string_init(temp_str); + // Set name if present + if(nfc->dev->dev_name[0] != '\0') { + string_printf(temp_str, "\ec%s\n", nfc->dev->dev_name); + } + + // Set tag type + if(protocol == NfcDeviceProtocolEMV) { + string_cat_printf(temp_str, "\e#EMV Bank Card\n"); + } else if(protocol == NfcDeviceProtocolMifareUl) { + string_cat_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(dev_data->mf_ul_data.type, true)); + } else if(protocol == NfcDeviceProtocolMifareClassic) { + string_cat_printf( + temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type)); + } else if(protocol == NfcDeviceProtocolMifareDesfire) { + string_cat_printf(temp_str, "\e#MIFARE DESfire\n"); + } else { + string_cat_printf(temp_str, "\e#Unknown ISO tag\n"); + } + + // Set tag iso data + char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3'; + string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); + string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]); + string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak); + + // Set application specific data + if(protocol == NfcDeviceProtocolMifareDesfire) { + MifareDesfireData* data = &dev_data->mf_df_data; + uint32_t bytes_total = 1 << (data->version.sw_storage >> 1); + uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0; + string_cat_printf(temp_str, "\n%d", bytes_total); + if(data->version.sw_storage & 1) { + string_push_back(temp_str, '+'); + } + string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free); + + uint16_t n_apps = 0; + uint16_t n_files = 0; + for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { + n_apps++; + for(MifareDesfireFile* file = app->file_head; file; file = file->next) { + n_files++; + } + } + string_cat_printf(temp_str, "%d Application", n_apps); + if(n_apps != 1) { + string_push_back(temp_str, 's'); + } + string_cat_printf(temp_str, ", %d file", n_files); + if(n_files != 1) { + string_push_back(temp_str, 's'); + } + } else if(protocol == NfcDeviceProtocolMifareUl) { + MfUltralightData* data = &dev_data->mf_ul_data; + string_cat_printf( + temp_str, "\nPages Read %d/%d", data->data_read / 4, data->data_size / 4); + if(data->data_size > data->data_read) { + string_cat_printf(temp_str, "\nPassword-protected"); + } + } else if(protocol == NfcDeviceProtocolMifareClassic) { + MfClassicData* data = &dev_data->mf_classic_data; + uint8_t sectors_total = mf_classic_get_total_sectors_num(data->type); + uint8_t keys_total = sectors_total * 2; + uint8_t keys_found = 0; + uint8_t sectors_read = 0; + mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found); + string_cat_printf(temp_str, "\nKeys Found %d/%d", keys_found, keys_total); + string_cat_printf(temp_str, "\nSectors Read %d/%d", sectors_read, sectors_total); + } + + // Add text scroll widget + widget_add_text_scroll_element( + widget, 0, 0, 128, text_scroll_height, string_get_cstr(temp_str)); + string_clear(temp_str); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_nfc_data_info_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + NfcProtocol protocol = nfc->dev->dev_data.protocol; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeRight) { + if(protocol == NfcDeviceProtocolMifareDesfire) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireApp); + consumed = true; + } else if(protocol == NfcDeviceProtocolMifareUl) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightData); + consumed = true; + } + } + } + + return consumed; +} + +void nfc_scene_nfc_data_info_on_exit(void* context) { + Nfc* nfc = context; + + widget_reset(nfc->widget); +} \ No newline at end of file diff --git a/applications/nfc/scenes/nfc_scene_nfca_menu.c b/applications/nfc/scenes/nfc_scene_nfca_menu.c new file mode 100644 index 00000000000..00d0d943dc0 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_nfca_menu.c @@ -0,0 +1,62 @@ +#include "../nfc_i.h" + +enum SubmenuIndex { + SubmenuIndexSaveUid, + SubmenuIndexEmulateUid, + SubmenuIndexInfo, +}; + +void nfc_scene_nfca_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_nfca_menu_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + submenu_add_item( + submenu, "Save UID", SubmenuIndexSaveUid, nfc_scene_nfca_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Emulate UID", SubmenuIndexEmulateUid, nfc_scene_nfca_menu_submenu_callback, nfc); + submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_nfca_menu_submenu_callback, nfc); + + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcaMenu)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_nfca_menu_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexSaveUid) { + nfc->dev->format = NfcDeviceSaveFormatUid; + // Clear device name + nfc_device_set_name(nfc->dev, ""); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + consumed = true; + } else if(event.event == SubmenuIndexEmulateUid) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); + consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcaMenu, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_nfca_menu_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + submenu_reset(nfc->submenu); +} diff --git a/applications/nfc/scenes/nfc_scene_nfca_read_success.c b/applications/nfc/scenes/nfc_scene_nfca_read_success.c new file mode 100644 index 00000000000..3467a03b634 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_nfca_read_success.c @@ -0,0 +1,72 @@ +#include "../nfc_i.h" +#include + +void nfc_scene_nfca_read_success_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + furi_assert(context); + Nfc* nfc = context; + + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_nfca_read_success_on_enter(void* context) { + Nfc* nfc = context; + + DOLPHIN_DEED(DolphinDeedNfcReadSuccess); + + // Setup view + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; + Widget* widget = nfc->widget; + + string_t temp_str; + string_init_set_str(temp_str, "\e#Unknown ISO tag\n"); + + char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3'; + string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); + string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", data->uid[i]); + } + string_cat_printf(temp_str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]); + string_cat_printf(temp_str, " SAK: %02X", data->sak); + + widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); + + widget_add_button_element( + widget, GuiButtonTypeLeft, "Retry", nfc_scene_nfca_read_success_widget_callback, nfc); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_scene_nfca_read_success_widget_callback, nfc); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_nfca_read_success_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); + consumed = true; + } else if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaMenu); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; + } + return consumed; +} + +void nfc_scene_nfca_read_success_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + widget_reset(nfc->widget); +} diff --git a/applications/nfc/scenes/nfc_scene_read.c b/applications/nfc/scenes/nfc_scene_read.c index 491b419ef5e..00b7c8fac76 100644 --- a/applications/nfc/scenes/nfc_scene_read.c +++ b/applications/nfc/scenes/nfc_scene_read.c @@ -59,11 +59,14 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if((event.event == NfcWorkerEventReadUidNfcB) || (event.event == NfcWorkerEventReadUidNfcF) || - (event.event == NfcWorkerEventReadUidNfcV) || - (event.event == NfcWorkerEventReadUidNfcA)) { + (event.event == NfcWorkerEventReadUidNfcV)) { notification_message(nfc->notifications, &sequence_success); scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess); consumed = true; + } else if(event.event == NfcWorkerEventReadUidNfcA) { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaReadSuccess); + consumed = true; } else if(event.event == NfcWorkerEventReadMfUltralight) { notification_message(nfc->notifications, &sequence_success); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess); diff --git a/applications/nfc/scenes/nfc_scene_read_card_success.c b/applications/nfc/scenes/nfc_scene_read_card_success.c index b889ce08dfd..0cb38cbdf43 100755 --- a/applications/nfc/scenes/nfc_scene_read_card_success.c +++ b/applications/nfc/scenes/nfc_scene_read_card_success.c @@ -16,44 +16,26 @@ void nfc_scene_read_card_success_widget_callback( void nfc_scene_read_card_success_on_enter(void* context) { Nfc* nfc = context; - string_t data_str; - string_t uid_str; - string_init(data_str); - string_init(uid_str); + string_t temp_str; + string_init(temp_str); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); // Setup view FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; Widget* widget = nfc->widget; - string_set_str(data_str, nfc_get_dev_type(data->type)); - string_set_str(uid_str, "UID:"); + string_set_str(temp_str, nfc_get_dev_type(data->type)); + widget_add_string_element( + widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, string_get_cstr(temp_str)); + string_set_str(temp_str, "UID:"); for(uint8_t i = 0; i < data->uid_len; i++) { - string_cat_printf(uid_str, " %02X", data->uid[i]); + string_cat_printf(temp_str, " %02X", data->uid[i]); } - + widget_add_string_element( + widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(temp_str)); widget_add_button_element( widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_card_success_widget_callback, nfc); - if(data->type == FuriHalNfcTypeA) { - widget_add_button_element( - widget, GuiButtonTypeRight, "Save", nfc_scene_read_card_success_widget_callback, nfc); - widget_add_icon_element(widget, 8, 13, &I_Medium_chip_22x21); - widget_add_string_element( - widget, 37, 12, AlignLeft, AlignBottom, FontPrimary, string_get_cstr(data_str)); - string_printf( - data_str, "ATQA: %02X%02X\nSAK: %02X", data->atqa[0], data->atqa[1], data->sak); - widget_add_string_multiline_element( - widget, 37, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str)); - widget_add_string_element( - widget, 64, 46, AlignCenter, AlignBottom, FontSecondary, string_get_cstr(uid_str)); - } else { - widget_add_string_element( - widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, string_get_cstr(data_str)); - widget_add_string_element( - widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(uid_str)); - } - string_clear(data_str); - string_clear(uid_str); + string_clear(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -65,11 +47,6 @@ bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { consumed = scene_manager_previous_scene(nfc->scene_manager); - } else if(event.event == GuiButtonTypeRight) { - nfc->dev->format = NfcDeviceSaveFormatUid; - nfc_device_set_name(nfc->dev, ""); - scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); - consumed = true; } } return consumed; diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/nfc/scenes/nfc_scene_saved_menu.c index e6b08e71b4c..c7aec5d8713 100644 --- a/applications/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/nfc/scenes/nfc_scene_saved_menu.c @@ -44,8 +44,6 @@ void nfc_scene_saved_menu_on_enter(void* context) { } submenu_add_item( submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc); - submenu_set_selected_item( - nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu)); if(nfc->dev->shadow_file_exist) { submenu_add_item( submenu, @@ -58,12 +56,15 @@ void nfc_scene_saved_menu_on_enter(void* context) { submenu, "Rename", SubmenuIndexRename, nfc_scene_saved_menu_submenu_callback, nfc); submenu_add_item( submenu, "Delete", SubmenuIndexDelete, nfc_scene_saved_menu_submenu_callback, nfc); + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu)); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; + NfcDeviceData* dev_data = &nfc->dev->dev_data; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -87,7 +88,18 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete); consumed = true; } else if(event.event == SubmenuIndexInfo) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); + bool application_info_present = false; + if(dev_data->protocol == NfcDeviceProtocolEMV) { + application_info_present = true; + } else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { + application_info_present = nfc_supported_card_verify_and_parse(dev_data); + } + + if(application_info_present) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + } consumed = true; } else if(event.event == SubmenuIndexRestoreOriginal) { scene_manager_next_scene(nfc->scene_manager, NfcSceneRestoreOriginalConfirm); diff --git a/applications/nfc/views/bank_card.c b/applications/nfc/views/bank_card.c deleted file mode 100755 index 31cc56ee8c3..00000000000 --- a/applications/nfc/views/bank_card.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "bank_card.h" -#include "../helpers/nfc_emv_parser.h" -#include - -struct BankCard { - Widget* widget; -}; - -BankCard* bank_card_alloc() { - BankCard* bank_card = malloc(sizeof(BankCard)); - bank_card->widget = widget_alloc(); - return bank_card; -} - -void bank_card_free(BankCard* bank_card) { - furi_assert(bank_card); - widget_free(bank_card->widget); - free(bank_card); -} - -View* bank_card_get_view(BankCard* bank_card) { - furi_assert(bank_card); - return widget_get_view(bank_card->widget); -} - -void bank_card_clear(BankCard* bank_card) { - furi_assert(bank_card); - widget_reset(bank_card->widget); -} - -void bank_card_set_name(BankCard* bank_card, char* name) { - furi_assert(bank_card); - furi_assert(name); - widget_add_string_element( - bank_card->widget, 64, 6, AlignCenter, AlignTop, FontSecondary, name); -} - -void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len) { - furi_assert(bank_card); - furi_assert(number); - string_t num_str; - string_init(num_str); - for(uint8_t i = 0; i < len; i += 2) { - string_cat_printf(num_str, "%02X%02X ", number[i], number[i + 1]); - } - // Add number - widget_add_string_element( - bank_card->widget, 64, 32, AlignCenter, AlignTop, FontSecondary, string_get_cstr(num_str)); - string_clear(num_str); - // Add icon - widget_add_icon_element(bank_card->widget, 8, 15, &I_Detailed_chip_17x13); - // Add frame - widget_add_frame_element(bank_card->widget, 0, 0, 128, 64, 6); -} - -void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context) { - furi_assert(bank_card); - furi_assert(callback); - widget_add_button_element(bank_card->widget, GuiButtonTypeLeft, "Back", callback, context); -} - -void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) { - furi_assert(bank_card); - char exp_date_str[16]; - snprintf(exp_date_str, sizeof(exp_date_str), "Exp: %02X/%02X", mon, year); - widget_add_string_element( - bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str); -} - -void bank_card_set_country_name(BankCard* bank_card, const char* country_name) { - furi_assert(bank_card); - widget_add_string_element( - bank_card->widget, 120, 18, AlignRight, AlignTop, FontSecondary, country_name); -} - -void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name) { - furi_assert(bank_card); - widget_add_string_element( - bank_card->widget, 31, 18, AlignLeft, AlignTop, FontSecondary, currency_name); -} diff --git a/applications/nfc/views/bank_card.h b/applications/nfc/views/bank_card.h deleted file mode 100644 index 628d9deb8e5..00000000000 --- a/applications/nfc/views/bank_card.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include -#include - -typedef struct BankCard BankCard; - -BankCard* bank_card_alloc(); - -void bank_card_free(BankCard* bank_card); - -void bank_card_clear(BankCard* bank_card); - -View* bank_card_get_view(BankCard* bank_card); - -void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context); - -void bank_card_set_name(BankCard* bank_card, char* name); - -void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len); - -void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year); - -void bank_card_set_country_name(BankCard* bank_card, const char* country_name); - -void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name); diff --git a/assets/icons/NFC/Keychain.png b/assets/icons/NFC/Keychain.png new file mode 100644 index 0000000000000000000000000000000000000000..7ba1b11da6fde4e2b4b148a35593937f2a2ac471 GIT binary patch literal 3750 zcmaJ@c{r5&+kYIguVo48j3ryln6WiupT!bG7#T?!j3JE~V`?lVlr0^Soruc5Bx-6b zWy_KfqU;Gt4o;RR;T`99I=}aixA(c8=lOoW_jP|h_vc=o>w4l&*jfnj%kTpLAY^5U zc3`h6>_>x_ll|_iwQmIgevB^)b;1gT0#RucZ{PDo00u!Mb+7zV>7+mRQ`nUD~EL&9D|@H+oHo*DVO30LpM zUVphY6?)HasD9&P_s-+D#&hMXIW@gJjl6?q}5i}sc3p8T08?_F_?23FwW}fBPdaAJ8!ir* zh9n>h0aJ61@SF@~M<9<2aPRW;m=6~H26zPlE&JFgHGnG=aPLr53<9oY z0^;T?&W2x(R*KH4vn!QZZOBrBVIbsHOlgMGx!S(SX#*gd1>& zlXvbOS>p0JBanAtBi_4O#Pl(cH$URMO5LjsCjTaDczAYZ=H2mDq$}a2^W_~<^Vvq{ z?epKl41a8_zkl{YDFWseVZpWezWLRfO~IkwTYT3%#y%!m{CFa;`$KL(q1DQRg;y7! zw%;F+fX=$H3M){EL*7z*aio9O>%*kR7N_x~E>LyOm?Jbvv)Ij(^Q*OrD4yQL^WbRCzhWeXdURGIp0uwk`6G0O8(Nw*mm*3|a|{ds$=B&Ih6#?rgA!s_CC?cRAF$l(^Fw1 zs>pW&Z*G%neFPtuSqJX{g8WD2WcTAi`lYOS}!<_MK%h=#Y|**a)9KALljuW)+3xV(UlBwPN2|4|>3$ zF?dT2#i9L)2Oy%Mv8YykrTuXzm)WD9&q?Wb0VUC?;U#t;;Wmbls;OH!52KFD*BB+WSZAj76mdLUl99jB!aUC5Zr6v?DG;nkVymn4#2 z@~0k8RZf*vhu}&|3ri6T5MYEQ1|Wg9-f`9ZvzQ5QJ$&h+dR@l0 zTwT0TX-PgDrF~r6xyE5N#oL5uIwN57HrtdQ|4BdSGLA}#x7+! zU|EG~g$6bTHtpT7y6<)mW$I=dLEpmWvgfkjW=}qGKNWOJgIUacO0=q;IaTPg#H{y^ zIt6zrz&o9Ct1++0sW>uJS5a3aR>ZPRwk^vYBDGX~VRkZ0o=8{CzT+OPWRjVe2_z3G z(vugJElbG_$(L&{|FLbvBNQ_%Tqbu)E-dg7O&oC&F_G1Cd&%VTi?y_Q2npXS+WSs> znt7m0t<^WjF?+y*Bt>EcUR{likF$>K0;d~;vt`@HI~rz=)7Jysrb7DHbFyo)n-_~m zA1vuD`7Xtb-Fc;RM=jSyJMeW&2kO23Y@dn1om4Hq$?`BelwAbr@th*W6O!ay@wVzo z0i$$-uqu+0|A(!NzCzv2ciC?RS7tL zBJ9)9YaYT!LVQb@ph{FslykI60yP#d(+5r0W%P}q0w>Ym(P`+3Y!cKC{y_7%uDWq4 z_?+R0eyvWeNgLSP<<%fQ2XA%W`VbtfUa9AQ{@LV@#nqS(IUfY3L!~kx9d6X%{GR5u zs3OS{@O}+MnyF2!?Xi@<%tY0TC2t&AIlwrQz#rT!*Gy7?^y&4*zC)c>KWw{Vsg4b~ z^=DGOZm`k|?E;Ni)-{!qoAowAHsjfdT*<79ATrDd(Ez=AE9qtcvQ!?M%p`p#ee}NA zRZfhm-g)64{{(V4m8a9M=4Sam7fpU9vhWk`l`S?@LLdY;-8JWyfF55(ajDIahZHf_#T}jYb+6Wy;6KsDqZ5r zJJqqES=kuM%jcP6DUV9ZT3KGb-u>S5A15?(U4_$1(?6yQ`wI<^JQA8b`Dk(dD`pgu z-mN-Xca@1^-Ft5Mw4PYh+0$)cg1e7f!+po;E%lE-CcNGB?^}`$t^ca?=isPo{l>O& z=d)2K4kzrO_aJf0YO7|$q%y8_elu;0>{ek*4p?mG?C0F(Q50srWxW}c>o>wVBn};2 zun=zl{n<{=GDA~HPsr(y+if2dsp#OD`3=6wjl)8Sk&8D%%cpn-e!nP3l7pN>X02qI zXFFzXxq7(P+PyOF8~QvE^21{EcahsVhAzR!S8<)bBlD31$)uIu8#$>tm&3r{#@t8m zGDGJ)dnV6`P?l>&=~Mlf-S|0!dV`+RD^KYw)uXcqoS!;pJwTi#f2Myn+({m=Yp=Uq zmsQC+?Z;XQX?Ps!y)iGFtKT!e))4$fa(8Gj7j87(uo^&0GRqQQh_V_HfK?pVhnMfyqg2?Cn0}(++3V-t=*!w**L;>`-3*FC1;Xk7A*b^WWg+>JF zgQ1$9T3T8leK?rtMSyu|dlNi0Krk&B6ar=6`kGLE1WX$Ng@gXN6xac2Ufu`?wD~{b z*e4?eA3B|ifIt`w2AH7@rqD#!lXu%*bm?qmpGceenP6*QU4^;fgfF=fd(tN3O zUy46ykCEU(xj;8kV2k}v7G&zbwEltrREk|QNDzSvfr7R6vij+W#s2@UWb(h>fpiDr zfA#*K#DTbADiPv945VD3d9r)wt+*G8ia^nb1UiL=qfpNOEaV9v3Y`+@L!p9T+F&S1 z6-)5+_209o{SCol5mx?zbb`Mp(F$#(z$O9v`g$Ss%rQ{yW6)z-x|m~7CjrXGG2U~bFwXi~nObWxEF+N1LG)vAL*y4V znZdc7@J&n`SL#XXY9}k7)0r8V0;wPHVQ>|=|K$#i_yQ>PR>QbidiqjLu%1ovk{e`n zvwDI75yjixLswvHKnnpN;w1fRT6NKTL0;1J>92DXdev_data); dev->format = NfcDeviceSaveFormatUid; string_reset(dev->load_path); diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index a92f148a25e..45bbc5f41a4 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -143,7 +143,7 @@ static bool nfc_worker_read_mf_classic(NfcWorker* nfc_worker, FuriHalNfcTxRxCont if(nfc_supported_card[i].verify(nfc_worker, tx_rx)) { if(nfc_supported_card[i].read(nfc_worker, tx_rx)) { read_success = true; - nfc_supported_card[i].parse(nfc_worker); + nfc_supported_card[i].parse(nfc_worker->dev_data); } } } diff --git a/lib/nfc/parsers/nfc_supported_card.c b/lib/nfc/parsers/nfc_supported_card.c index 59482a12346..480c970e7ec 100644 --- a/lib/nfc/parsers/nfc_supported_card.c +++ b/lib/nfc/parsers/nfc_supported_card.c @@ -11,3 +11,17 @@ NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd] = { .parse = troyka_parser_parse, }, }; + +bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data) { + furi_assert(dev_data); + + bool card_parsed = false; + for(size_t i = 0; i < COUNT_OF(nfc_supported_card); i++) { + if(nfc_supported_card[i].parse(dev_data)) { + card_parsed = true; + break; + } + } + + return card_parsed; +} diff --git a/lib/nfc/parsers/nfc_supported_card.h b/lib/nfc/parsers/nfc_supported_card.h index 5c94c78cd89..9b5d1c05326 100644 --- a/lib/nfc/parsers/nfc_supported_card.h +++ b/lib/nfc/parsers/nfc_supported_card.h @@ -2,6 +2,7 @@ #include #include "../nfc_worker.h" +#include "../nfc_device.h" #include @@ -15,7 +16,7 @@ typedef bool (*NfcSupportedCardVerify)(NfcWorker* nfc_worker, FuriHalNfcTxRxCont typedef bool (*NfcSupportedCardRead)(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); -typedef bool (*NfcSupportedCardParse)(NfcWorker* nfc_worker); +typedef bool (*NfcSupportedCardParse)(NfcDeviceData* dev_data); typedef struct { NfcProtocol protocol; @@ -25,3 +26,5 @@ typedef struct { } NfcSupportedCard; extern NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd]; + +bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data); diff --git a/lib/nfc/parsers/troyka_parser.c b/lib/nfc/parsers/troyka_parser.c index 3167b5181cf..51ffa42e14f 100644 --- a/lib/nfc/parsers/troyka_parser.c +++ b/lib/nfc/parsers/troyka_parser.c @@ -49,23 +49,31 @@ bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 16; } -bool troyka_parser_parse(NfcWorker* nfc_worker) { - MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; - uint8_t* temp_ptr = &data->block[8 * 4 + 1].value[5]; - uint16_t balance = ((temp_ptr[0] << 8) | temp_ptr[1]) / 25; - temp_ptr = &data->block[8 * 4].value[3]; - uint32_t number = 0; - for(size_t i = 0; i < 4; i++) { - number <<= 8; - number |= temp_ptr[i]; - } - number >>= 4; +bool troyka_parser_parse(NfcDeviceData* dev_data) { + MfClassicData* data = &dev_data->mf_classic_data; + bool troyka_parsed = false; + + do { + // Verify key + MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 8); + uint64_t key = nfc_util_bytes2num(sec_tr->key_a, 6); + if(key != troyka_keys[8].key_a) break; + + // Parse data + uint8_t* temp_ptr = &data->block[8 * 4 + 1].value[5]; + uint16_t balance = ((temp_ptr[0] << 8) | temp_ptr[1]) / 25; + temp_ptr = &data->block[8 * 4].value[3]; + uint32_t number = 0; + for(size_t i = 0; i < 4; i++) { + number <<= 8; + number |= temp_ptr[i]; + } + number >>= 4; - string_printf( - nfc_worker->dev_data->parsed_data, - "Troyka Transport card\nNumber: %ld\nBalance: %d rub", - number, - balance); + string_printf( + dev_data->parsed_data, "\e#Troyka\nNum: %ld\nBalance: %d rur.", number, balance); + troyka_parsed = true; + } while(false); - return true; + return troyka_parsed; } diff --git a/lib/nfc/parsers/troyka_parser.h b/lib/nfc/parsers/troyka_parser.h index 0d5cee2332a..445fe40e55a 100644 --- a/lib/nfc/parsers/troyka_parser.h +++ b/lib/nfc/parsers/troyka_parser.h @@ -6,4 +6,4 @@ bool troyka_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); -bool troyka_parser_parse(NfcWorker* nfc_worker); +bool troyka_parser_parse(NfcDeviceData* dev_data); diff --git a/lib/nfc/protocols/mifare_ultralight.c b/lib/nfc/protocols/mifare_ultralight.c index c043f2069f8..f637d378a70 100644 --- a/lib/nfc/protocols/mifare_ultralight.c +++ b/lib/nfc/protocols/mifare_ultralight.c @@ -191,7 +191,7 @@ bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint } if(pack != NULL) { - *pack = (tx_rx->rx_data[0] << 8) | tx_rx->rx_data[1]; + *pack = (tx_rx->rx_data[1] << 8) | tx_rx->rx_data[0]; } FURI_LOG_I(TAG, "Auth success. Password: %08X. PACK: %04X", key, *pack); @@ -697,48 +697,6 @@ bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* return counter_read == (is_single_counter ? 1 : 3); } -int16_t mf_ultralight_get_authlim( - FuriHalNfcTxRxContext* tx_rx, - MfUltralightReader* reader, - MfUltralightData* data) { - mf_ultralight_read_version(tx_rx, reader, data); - if(!(reader->supported_features & MfUltralightSupportAuth)) { - // No authentication - return -2; - } - - uint8_t config_pages_index; - if(data->type >= MfUltralightTypeUL11 && data->type <= MfUltralightTypeNTAG216) { - config_pages_index = reader->pages_to_read - 4; - } else if( - data->type >= MfUltralightTypeNTAGI2CPlus1K && - data->type <= MfUltralightTypeNTAGI2CPlus1K) { - config_pages_index = 0xe3; - } else { - // No config pages - return -2; - } - - if(!mf_ultralight_read_pages_direct(tx_rx, config_pages_index, data->data)) { - // Config pages are not readable due to protection - return -1; - } - - MfUltralightConfigPages* config_pages = (MfUltralightConfigPages*)&data->data; - if(config_pages->auth0 >= reader->pages_to_read) { - // Authentication is not configured - return -2; - } - - int16_t authlim = config_pages->access.authlim; - if(authlim > 0 && data->type >= MfUltralightTypeNTAGI2CPlus1K && - data->type <= MfUltralightTypeNTAGI2CPlus2K) { - authlim = 1 << authlim; - } - - return authlim; -} - bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data) { uint8_t flag_read = 0; diff --git a/lib/nfc/protocols/mifare_ultralight.h b/lib/nfc/protocols/mifare_ultralight.h index 727bffab2f9..9642824f702 100644 --- a/lib/nfc/protocols/mifare_ultralight.h +++ b/lib/nfc/protocols/mifare_ultralight.h @@ -56,13 +56,6 @@ typedef enum { MfUltralightTypeNum, } MfUltralightType; -typedef enum { - MfUltralightAuthLimitUnknown, - MfUltralightAuthLimitNotSupported, - MfUltralightAuthLimitConfigured, - MfUltralightAuthLimitNotConfigured, -} MfUltralightAuthLimit; - typedef enum { MfUltralightSupportNone = 0, MfUltralightSupportFastRead = 1 << 0, @@ -245,11 +238,6 @@ bool mf_ul_prepare_emulation_response( uint32_t* data_type, void* context); -int16_t mf_ultralight_get_authlim( - FuriHalNfcTxRxContext* tx_rx, - MfUltralightReader* reader, - MfUltralightData* data); - uint32_t mf_ul_pwdgen_amiibo(FuriHalNfcDevData* data); uint32_t mf_ul_pwdgen_xiaomi(FuriHalNfcDevData* data); From 6c268ec58190d2296cb0101be9d063e70fc896ef Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Wed, 17 Aug 2022 18:40:06 +0300 Subject: [PATCH 19/26] U2F: counter file migration (#1604) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/u2f/u2f_data.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/applications/u2f/u2f_data.c b/applications/u2f/u2f_data.c index 0419fc7e1ee..117fbdbe36d 100644 --- a/applications/u2f/u2f_data.c +++ b/applications/u2f/u2f_data.c @@ -1,5 +1,5 @@ #include -#include "u2f_hid.h" +#include "u2f_data.h" #include #include #include @@ -28,7 +28,8 @@ #define U2F_DEVICE_KEY_VERSION 1 #define U2F_COUNTER_FILE_TYPE "Flipper U2F Counter File" -#define U2F_COUNTER_VERSION 1 +#define U2F_COUNTER_VERSION 2 +#define U2F_COUNTER_VERSION_OLD 1 #define U2F_COUNTER_CONTROL_VAL 0xAA5500FF @@ -359,6 +360,7 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { furi_assert(cnt_val); bool state = false; + bool old_counter = false; uint8_t iv[16]; U2fCounterData cnt; uint8_t cnt_encr[48]; @@ -376,9 +378,16 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { FURI_LOG_E(TAG, "Missing or incorrect header"); break; } - if(strcmp(string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0 || - version != U2F_COUNTER_VERSION) { - FURI_LOG_E(TAG, "Type or version mismatch"); + if(strcmp(string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0) { + FURI_LOG_E(TAG, "Type mismatch"); + break; + } + if(version == U2F_COUNTER_VERSION_OLD) { + // Counter is from previous U2F app version with endianness bug + FURI_LOG_W(TAG, "Counter from old version"); + old_counter = true; + } else if(version != U2F_COUNTER_VERSION) { + FURI_LOG_E(TAG, "Version mismatch"); break; } if(!flipper_format_read_hex(flipper_format, "IV", iv, 16)) { @@ -409,6 +418,13 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { flipper_format_free(flipper_format); furi_record_close(RECORD_STORAGE); string_clear(filetype); + + if(old_counter && state) { + // Change counter endianness and rewrite counter file + *cnt_val = __REV(cnt.counter); + state = u2f_data_cnt_write(*cnt_val); + } + return state; } From 831da59ed012e56a5d629837e3fd33550b575e6f Mon Sep 17 00:00:00 2001 From: Walter Doekes Date: Wed, 17 Aug 2022 17:44:08 +0200 Subject: [PATCH 20/26] Fix U2F counter endianness (#1592) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/u2f/u2f.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/applications/u2f/u2f.c b/applications/u2f/u2f.c index 051dca696fd..94fd9f2dad8 100644 --- a/applications/u2f/u2f.c +++ b/applications/u2f/u2f.c @@ -4,6 +4,7 @@ #include "u2f_data.h" #include #include +#include // for lfs_tobe32 #include "toolbox/sha256.h" #include "toolbox/hmac_sha256.h" @@ -256,6 +257,7 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { uint8_t flags = 0; uint8_t hash[32]; uint8_t signature[64]; + uint32_t be_u2f_counter; if(u2f_data_check(false) == false) { U2F->ready = false; @@ -275,11 +277,14 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { } U2F->user_present = false; + // The 4 byte counter is represented in big endian + be_u2f_counter = lfs_tobe32(U2F->counter); + // Generate hash sha256_start(&sha_ctx); sha256_update(&sha_ctx, req->app_id, 32); sha256_update(&sha_ctx, &flags, 1); - sha256_update(&sha_ctx, (uint8_t*)&(U2F->counter), 4); + sha256_update(&sha_ctx, (uint8_t*)&(be_u2f_counter), 4); sha256_update(&sha_ctx, req->challenge, 32); sha256_finish(&sha_ctx, hash); @@ -309,7 +314,7 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { uECC_sign(priv_key, hash, 32, signature, U2F->p_curve); resp->user_present = flags; - resp->counter = U2F->counter; + resp->counter = be_u2f_counter; uint8_t signature_len = u2f_der_encode_signature(resp->signature, signature); memcpy(resp->signature + signature_len, state_no_error, 2); From c964099c8cbaff194e3f6db66be820771e7a2482 Mon Sep 17 00:00:00 2001 From: Walter Doekes Date: Wed, 17 Aug 2022 18:23:13 +0200 Subject: [PATCH 21/26] Increment U2F counter before authentication (#1595) * Fix U2F counter endianness * Increment U2F counter before using it * U2F: increment counter before use * U2F: don't increment on U2fCheckOnly Co-authored-by: Aleksandr Kutuzov --- applications/u2f/u2f.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/applications/u2f/u2f.c b/applications/u2f/u2f.c index 94fd9f2dad8..767733ce65b 100644 --- a/applications/u2f/u2f.c +++ b/applications/u2f/u2f.c @@ -277,8 +277,8 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { } U2F->user_present = false; - // The 4 byte counter is represented in big endian - be_u2f_counter = lfs_tobe32(U2F->counter); + // The 4 byte counter is represented in big endian. Increment it before use + be_u2f_counter = lfs_tobe32(U2F->counter + 1); // Generate hash sha256_start(&sha_ctx); @@ -318,8 +318,8 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { uint8_t signature_len = u2f_der_encode_signature(resp->signature, signature); memcpy(resp->signature + signature_len, state_no_error, 2); - FURI_LOG_D(TAG, "Counter: %lu", U2F->counter); U2F->counter++; + FURI_LOG_D(TAG, "Counter: %lu", U2F->counter); u2f_data_cnt_write(U2F->counter); if(U2F->callback != NULL) U2F->callback(U2fNotifyAuthSuccess, U2F->context); From 9b138424671e0e1bdea7e93ca152703427af6bee Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:40:09 +0300 Subject: [PATCH 22/26] Fix typos in subghz (#1588) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .../subghz/scenes/subghz_scene_receiver_config.c | 4 ++-- applications/subghz/subghz_i.c | 2 +- lib/subghz/blocks/encoder.h | 2 +- lib/subghz/protocols/bett.c | 10 +++++----- lib/subghz/protocols/came.c | 10 +++++----- lib/subghz/protocols/came_twee.c | 10 +++++----- lib/subghz/protocols/chamberlain_code.c | 10 +++++----- lib/subghz/protocols/doitrand.c | 10 +++++----- lib/subghz/protocols/gate_tx.c | 10 +++++----- lib/subghz/protocols/holtek.c | 10 +++++----- lib/subghz/protocols/honeywell_wdb.c | 10 +++++----- lib/subghz/protocols/hormann.c | 10 +++++----- lib/subghz/protocols/keeloq.c | 10 +++++----- lib/subghz/protocols/linear.c | 10 +++++----- lib/subghz/protocols/marantec.c | 10 +++++----- lib/subghz/protocols/megacode.c | 10 +++++----- lib/subghz/protocols/nero_radio.c | 10 +++++----- lib/subghz/protocols/nero_sketch.c | 10 +++++----- lib/subghz/protocols/nice_flo.c | 10 +++++----- lib/subghz/protocols/phoenix_v2.c | 10 +++++----- lib/subghz/protocols/power_smart.c | 10 +++++----- lib/subghz/protocols/princeton.c | 10 +++++----- lib/subghz/protocols/raw.c | 12 ++++++------ lib/subghz/protocols/scher_khan.c | 6 +++--- lib/subghz/protocols/secplus_v1.c | 10 +++++----- lib/subghz/protocols/secplus_v2.c | 10 +++++----- 26 files changed, 118 insertions(+), 118 deletions(-) diff --git a/applications/subghz/scenes/subghz_scene_receiver_config.c b/applications/subghz/scenes/subghz_scene_receiver_config.c index bf2f0cdba6b..c59630f7ea4 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/subghz/scenes/subghz_scene_receiver_config.c @@ -100,7 +100,7 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) { subghz_setting_get_preset_data_size(subghz->setting, index)); } -static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) { +static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -176,7 +176,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz->variable_item_list, "Hopping:", HOPPING_COUNT, - subghz_scene_receiver_config_set_hopping_runing, + subghz_scene_receiver_config_set_hopping_running, subghz); value_index = subghz_scene_receiver_config_hopper_value_index( subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz); diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index de2df681cef..dc0d71e56cb 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -296,7 +296,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { //Todo add Custom_preset_module - //delete peset if it already exists + //delete preset if it already exists subghz_setting_delete_custom_preset( subghz->setting, string_get_cstr(subghz->txrx->preset->name)); //load custom preset from file diff --git a/lib/subghz/blocks/encoder.h b/lib/subghz/blocks/encoder.h index 80ffe49005e..6ad734cbdd2 100644 --- a/lib/subghz/blocks/encoder.h +++ b/lib/subghz/blocks/encoder.h @@ -7,7 +7,7 @@ #include typedef struct { - bool is_runing; + bool is_running; size_t repeat; size_t front; size_t size_upload; diff --git a/lib/subghz/protocols/bett.c b/lib/subghz/protocols/bett.c index bd3b45feb66..aca8b8c4f7e 100644 --- a/lib/subghz/protocols/bett.c +++ b/lib/subghz/protocols/bett.c @@ -94,7 +94,7 @@ void* subghz_protocol_encoder_bett_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -174,7 +174,7 @@ bool subghz_protocol_encoder_bett_deserialize(void* context, FlipperFormat* flip flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_bett_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -184,14 +184,14 @@ bool subghz_protocol_encoder_bett_deserialize(void* context, FlipperFormat* flip void subghz_protocol_encoder_bett_stop(void* context) { SubGhzProtocolEncoderBETT* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_bett_yield(void* context) { SubGhzProtocolEncoderBETT* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/came.c b/lib/subghz/protocols/came.c index d28b735c5b9..37048017e3f 100644 --- a/lib/subghz/protocols/came.c +++ b/lib/subghz/protocols/came.c @@ -85,7 +85,7 @@ void* subghz_protocol_encoder_came_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -157,7 +157,7 @@ bool subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flip flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_came_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -167,14 +167,14 @@ bool subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flip void subghz_protocol_encoder_came_stop(void* context) { SubGhzProtocolEncoderCame* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_came_yield(void* context) { SubGhzProtocolEncoderCame* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/came_twee.c b/lib/subghz/protocols/came_twee.c index 9bf87ea2bdc..b5b409c5904 100644 --- a/lib/subghz/protocols/came_twee.c +++ b/lib/subghz/protocols/came_twee.c @@ -112,7 +112,7 @@ void* subghz_protocol_encoder_came_twee_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 1536; //max upload 92*14 = 1288 !!!! instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -261,7 +261,7 @@ bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* subghz_protocol_came_twee_remote_controller(&instance->generic); subghz_protocol_encoder_came_twee_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -271,14 +271,14 @@ bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_came_twee_stop(void* context) { SubGhzProtocolEncoderCameTwee* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_came_twee_yield(void* context) { SubGhzProtocolEncoderCameTwee* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 3128b71ec65..6c99d84519e 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -108,7 +108,7 @@ void* subghz_protocol_encoder_chamb_code_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 24; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -225,7 +225,7 @@ bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_chamb_code_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -235,14 +235,14 @@ bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_chamb_code_stop(void* context) { SubGhzProtocolEncoderChamb_Code* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_chamb_code_yield(void* context) { SubGhzProtocolEncoderChamb_Code* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/doitrand.c b/lib/subghz/protocols/doitrand.c index c26cbc5b6b0..9a0a58190df 100644 --- a/lib/subghz/protocols/doitrand.c +++ b/lib/subghz/protocols/doitrand.c @@ -85,7 +85,7 @@ void* subghz_protocol_encoder_doitrand_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -155,7 +155,7 @@ bool subghz_protocol_encoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_doitrand_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -165,14 +165,14 @@ bool subghz_protocol_encoder_doitrand_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_doitrand_stop(void* context) { SubGhzProtocolEncoderDoitrand* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_doitrand_yield(void* context) { SubGhzProtocolEncoderDoitrand* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/gate_tx.c b/lib/subghz/protocols/gate_tx.c index 66174d01138..d7efb3862cb 100644 --- a/lib/subghz/protocols/gate_tx.c +++ b/lib/subghz/protocols/gate_tx.c @@ -78,7 +78,7 @@ void* subghz_protocol_encoder_gate_tx_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -148,7 +148,7 @@ bool subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* f flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_gate_tx_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -158,14 +158,14 @@ bool subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* f void subghz_protocol_encoder_gate_tx_stop(void* context) { SubGhzProtocolEncoderGateTx* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_gate_tx_yield(void* context) { SubGhzProtocolEncoderGateTx* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c index ed5e4fb54d8..137ba85d388 100644 --- a/lib/subghz/protocols/holtek.c +++ b/lib/subghz/protocols/holtek.c @@ -89,7 +89,7 @@ void* subghz_protocol_encoder_holtek_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -161,7 +161,7 @@ bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* fl flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_holtek_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -171,14 +171,14 @@ bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* fl void subghz_protocol_encoder_holtek_stop(void* context) { SubGhzProtocolEncoderHoltek* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_holtek_yield(void* context) { SubGhzProtocolEncoderHoltek* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/honeywell_wdb.c b/lib/subghz/protocols/honeywell_wdb.c index 2922291307c..e1e21426d2a 100644 --- a/lib/subghz/protocols/honeywell_wdb.c +++ b/lib/subghz/protocols/honeywell_wdb.c @@ -91,7 +91,7 @@ void* subghz_protocol_encoder_honeywell_wdb_alloc(SubGhzEnvironment* environment instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -163,7 +163,7 @@ bool subghz_protocol_encoder_honeywell_wdb_deserialize( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_honeywell_wdb_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -173,14 +173,14 @@ bool subghz_protocol_encoder_honeywell_wdb_deserialize( void subghz_protocol_encoder_honeywell_wdb_stop(void* context) { SubGhzProtocolEncoderHoneywell_WDB* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_honeywell_wdb_yield(void* context) { SubGhzProtocolEncoderHoneywell_WDB* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index ac6312511f2..0197f59e6b5 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -81,7 +81,7 @@ void* subghz_protocol_encoder_hormann_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 2048; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -164,7 +164,7 @@ bool subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* f flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_hormann_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -174,14 +174,14 @@ bool subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* f void subghz_protocol_encoder_hormann_stop(void* context) { SubGhzProtocolEncoderHormann* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_hormann_yield(void* context) { SubGhzProtocolEncoderHormann* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 526a6b34e04..88738f3fb4b 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -102,7 +102,7 @@ void* subghz_protocol_encoder_keeloq_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -295,7 +295,7 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl break; } - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -305,14 +305,14 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl void subghz_protocol_encoder_keeloq_stop(void* context) { SubGhzProtocolEncoderKeeloq* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_keeloq_yield(void* context) { SubGhzProtocolEncoderKeeloq* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/linear.c b/lib/subghz/protocols/linear.c index c989a6183c8..92ba02a8fbd 100644 --- a/lib/subghz/protocols/linear.c +++ b/lib/subghz/protocols/linear.c @@ -84,7 +84,7 @@ void* subghz_protocol_encoder_linear_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 28; //max 10bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -166,7 +166,7 @@ bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* fl flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_linear_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -176,14 +176,14 @@ bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* fl void subghz_protocol_encoder_linear_stop(void* context) { SubGhzProtocolEncoderLinear* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_linear_yield(void* context) { SubGhzProtocolEncoderLinear* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/marantec.c b/lib/subghz/protocols/marantec.c index d469272469e..bdce6593dbd 100644 --- a/lib/subghz/protocols/marantec.c +++ b/lib/subghz/protocols/marantec.c @@ -80,7 +80,7 @@ void* subghz_protocol_encoder_marantec_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -208,7 +208,7 @@ bool subghz_protocol_encoder_marantec_deserialize(void* context, FlipperFormat* subghz_protocol_marantec_remote_controller(&instance->generic); subghz_protocol_encoder_marantec_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -218,14 +218,14 @@ bool subghz_protocol_encoder_marantec_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_marantec_stop(void* context) { SubGhzProtocolEncoderMarantec* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_marantec_yield(void* context) { SubGhzProtocolEncoderMarantec* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c index bfe1a76b94f..909e721714e 100644 --- a/lib/subghz/protocols/megacode.c +++ b/lib/subghz/protocols/megacode.c @@ -90,7 +90,7 @@ void* subghz_protocol_encoder_megacode_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -194,7 +194,7 @@ bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_megacode_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -204,14 +204,14 @@ bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_megacode_stop(void* context) { SubGhzProtocolEncoderMegaCode* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_megacode_yield(void* context) { SubGhzProtocolEncoderMegaCode* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index b6b1587ff73..69326f5a088 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -80,7 +80,7 @@ void* subghz_protocol_encoder_nero_radio_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -173,7 +173,7 @@ bool subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_nero_radio_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -183,14 +183,14 @@ bool subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_nero_radio_stop(void* context) { SubGhzProtocolEncoderNeroRadio* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_nero_radio_yield(void* context) { SubGhzProtocolEncoderNeroRadio* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/nero_sketch.c b/lib/subghz/protocols/nero_sketch.c index 0b87ec11b2f..c93b36a53a5 100644 --- a/lib/subghz/protocols/nero_sketch.c +++ b/lib/subghz/protocols/nero_sketch.c @@ -79,7 +79,7 @@ void* subghz_protocol_encoder_nero_sketch_alloc(SubGhzEnvironment* environment) instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -167,7 +167,7 @@ bool subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperForma flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_nero_sketch_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -177,14 +177,14 @@ bool subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperForma void subghz_protocol_encoder_nero_sketch_stop(void* context) { SubGhzProtocolEncoderNeroSketch* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_nero_sketch_yield(void* context) { SubGhzProtocolEncoderNeroSketch* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/nice_flo.c b/lib/subghz/protocols/nice_flo.c index 236b4222338..07b18e3ea37 100644 --- a/lib/subghz/protocols/nice_flo.c +++ b/lib/subghz/protocols/nice_flo.c @@ -78,7 +78,7 @@ void* subghz_protocol_encoder_nice_flo_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -150,7 +150,7 @@ bool subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_nice_flo_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -160,14 +160,14 @@ bool subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_nice_flo_stop(void* context) { SubGhzProtocolEncoderNiceFlo* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_nice_flo_yield(void* context) { SubGhzProtocolEncoderNiceFlo* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/phoenix_v2.c b/lib/subghz/protocols/phoenix_v2.c index e71e28349c3..3d2796e441b 100644 --- a/lib/subghz/protocols/phoenix_v2.c +++ b/lib/subghz/protocols/phoenix_v2.c @@ -80,7 +80,7 @@ void* subghz_protocol_encoder_phoenix_v2_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -151,7 +151,7 @@ bool subghz_protocol_encoder_phoenix_v2_deserialize(void* context, FlipperFormat flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_phoenix_v2_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -161,14 +161,14 @@ bool subghz_protocol_encoder_phoenix_v2_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_phoenix_v2_stop(void* context) { SubGhzProtocolEncoderPhoenix_V2* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_phoenix_v2_yield(void* context) { SubGhzProtocolEncoderPhoenix_V2* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/power_smart.c b/lib/subghz/protocols/power_smart.c index 53e9f338001..bd009d88725 100644 --- a/lib/subghz/protocols/power_smart.c +++ b/lib/subghz/protocols/power_smart.c @@ -87,7 +87,7 @@ void* subghz_protocol_encoder_power_smart_alloc(SubGhzEnvironment* environment) instance->encoder.repeat = 10; instance->encoder.size_upload = 1024; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -212,7 +212,7 @@ bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperForma subghz_protocol_power_smart_remote_controller(&instance->generic); subghz_protocol_encoder_power_smart_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -222,14 +222,14 @@ bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperForma void subghz_protocol_encoder_power_smart_stop(void* context) { SubGhzProtocolEncoderPowerSmart* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_power_smart_yield(void* context) { SubGhzProtocolEncoderPowerSmart* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index 3fdeaae9469..2ddfa2cb683 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -89,7 +89,7 @@ void* subghz_protocol_encoder_princeton_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -168,7 +168,7 @@ bool subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_princeton_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -178,14 +178,14 @@ bool subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_princeton_stop(void* context) { SubGhzProtocolEncoderPrinceton* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_princeton_yield(void* context) { SubGhzProtocolEncoderPrinceton* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index 9ab649a7b8b..0419a39a0b1 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -37,7 +37,7 @@ struct SubGhzProtocolDecoderRAW { struct SubGhzProtocolEncoderRAW { SubGhzProtocolEncoderBase base; - bool is_runing; + bool is_running; string_t file_name; SubGhzFileEncoderWorker* file_worker_encoder; }; @@ -269,13 +269,13 @@ void* subghz_protocol_encoder_raw_alloc(SubGhzEnvironment* environment) { instance->base.protocol = &subghz_protocol_raw; string_init(instance->file_name); - instance->is_runing = false; + instance->is_running = false; return instance; } void subghz_protocol_encoder_raw_stop(void* context) { SubGhzProtocolEncoderRAW* instance = context; - instance->is_runing = false; + instance->is_running = false; if(subghz_file_encoder_worker_is_running(instance->file_worker_encoder)) { subghz_file_encoder_worker_stop(instance->file_worker_encoder); subghz_file_encoder_worker_free(instance->file_worker_encoder); @@ -308,11 +308,11 @@ static bool subghz_protocol_encoder_raw_worker_init(SubGhzProtocolEncoderRAW* in instance->file_worker_encoder, string_get_cstr(instance->file_name))) { //the worker needs a file in order to open and read part of the file furi_delay_ms(100); - instance->is_runing = true; + instance->is_running = true; } else { subghz_protocol_encoder_raw_stop(instance); } - return instance->is_runing; + return instance->is_running; } void subghz_protocol_raw_gen_fff_data(FlipperFormat* flipper_format, const char* file_path) { @@ -357,6 +357,6 @@ bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipp LevelDuration subghz_protocol_encoder_raw_yield(void* context) { SubGhzProtocolEncoderRAW* instance = context; - if(!instance->is_runing) return level_duration_reset(); + if(!instance->is_running) return level_duration_reset(); return subghz_file_encoder_worker_get_level_duration(instance->file_worker_encoder); } diff --git a/lib/subghz/protocols/scher_khan.c b/lib/subghz/protocols/scher_khan.c index dd8d4c8face..1c044e9db3e 100644 --- a/lib/subghz/protocols/scher_khan.c +++ b/lib/subghz/protocols/scher_khan.c @@ -210,7 +210,7 @@ static void subghz_protocol_scher_khan_check_remote_controller( SubGhzBlockGeneric* instance, const char** protocol_name) { /* - * MAGICAR 51 bit 00000001A99121DE83C3 MAGIC CODE, Dinamic + * MAGICAR 51 bit 00000001A99121DE83C3 MAGIC CODE, Dynamic * 0E8C1619E830C -> 000011101000110000010110 0001 1001 1110 1000001100001100 * 0E8C1629D830D -> 000011101000110000010110 0010 1001 1101 1000001100001101 * 0E8C1649B830E -> 000011101000110000010110 0100 1001 1011 1000001100001110 @@ -222,8 +222,8 @@ static void subghz_protocol_scher_khan_check_remote_controller( // case 35: //MAGIC CODE, Static // instance->protocol_name = "MAGIC CODE, Static"; // break; - case 51: //MAGIC CODE, Dinamic - *protocol_name = "MAGIC CODE, Dinamic"; + case 51: //MAGIC CODE, Dynamic + *protocol_name = "MAGIC CODE, Dynamic"; instance->serial = ((instance->data >> 24) & 0xFFFFFF0) | ((instance->data >> 20) & 0x0F); instance->btn = (instance->data >> 24) & 0x0F; instance->cnt = instance->data & 0xFFFF; diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index 25c35ce5599..77a0c62a2e9 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -101,7 +101,7 @@ void* subghz_protocol_encoder_secplus_v1_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -298,7 +298,7 @@ bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat break; } - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -308,14 +308,14 @@ bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_secplus_v1_stop(void* context) { SubGhzProtocolEncoderSecPlus_v1* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_secplus_v1_yield(void* context) { SubGhzProtocolEncoderSecPlus_v1* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index 37dc1c82317..c242d0b4d90 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -93,7 +93,7 @@ void* subghz_protocol_encoder_secplus_v2_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -555,7 +555,7 @@ bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat break; } - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -565,14 +565,14 @@ bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_secplus_v2_stop(void* context) { SubGhzProtocolEncoderSecPlus_v2* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_secplus_v2_yield(void* context) { SubGhzProtocolEncoderSecPlus_v2* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } From e243a0e0e4ee588a48c1be1b7ac3c26a1577a7c0 Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Thu, 18 Aug 2022 15:43:28 +0300 Subject: [PATCH 23/26] Add MFC 1/4K 4/7bUID to "Add Manually" (#1584) * Add MFC 1/4K 4/7bUID to the "Add Manually" section * Small cleanup * Improve readability * Fix comment on the text box element * Review fixes --- applications/gui/modules/widget.h | 4 +- applications/nfc/helpers/nfc_generators.c | 167 ++++++++++++++++++++-- 2 files changed, 156 insertions(+), 15 deletions(-) diff --git a/applications/gui/modules/widget.h b/applications/gui/modules/widget.h index 587fa3c65be..03586165c2d 100755 --- a/applications/gui/modules/widget.h +++ b/applications/gui/modules/widget.h @@ -115,8 +115,8 @@ void widget_add_text_box_element( * @param[in] text Formatted text. Default format: align left, Secondary font. * The following formats are available: * "\e#Bold text" - sets bold font before until next '\n' symbol - * "\ecBold text" - sets center horizontal align before until next '\n' symbol - * "\erBold text" - sets right horizontal align before until next '\n' symbol + * "\ecCenter-aligned text" - sets center horizontal align until the next '\n' symbol + * "\erRight-aligned text" - sets right horizontal align until the next '\n' symbol */ void widget_add_text_scroll_element( Widget* widget, diff --git a/applications/nfc/helpers/nfc_generators.c b/applications/nfc/helpers/nfc_generators.c index 3ec78a127d8..b94adbd7b03 100644 --- a/applications/nfc/helpers/nfc_generators.c +++ b/applications/nfc/helpers/nfc_generators.c @@ -25,6 +25,39 @@ static void nfc_generate_mf_ul_uid(uint8_t* uid) { uid[6] |= 0x80; } +static void nfc_generate_mf_classic_uid(uint8_t* uid, uint8_t length) { + uid[0] = NXP_MANUFACTURER_ID; + furi_hal_random_fill_buf(&uid[1], length - 1); +} + +static void nfc_generate_mf_classic_block_0(uint8_t* block, uint8_t uid_len) { + // Block length is always 16 bytes, and the UID can be either 4 or 7 bytes + furi_assert(uid_len == 4 || uid_len == 7); + furi_assert(block); + nfc_generate_mf_classic_uid(block, uid_len); + for(int i = uid_len; i < 16; i++) { + block[i] = 0xFF; + } +} + +static void nfc_generate_mf_classic_sector_trailer(MfClassicData* data, uint8_t block) { + // All keys are set to FFFF FFFF FFFFh at chip delivery and the bytes 6, 7 and 8 are set to FF0780h. + MfClassicSectorTrailer* sec_tr = (MfClassicSectorTrailer*)data->block[block].value; + sec_tr->access_bits[0] = 0xFF; + sec_tr->access_bits[1] = 0x07; + sec_tr->access_bits[2] = 0x80; + sec_tr->access_bits[3] = 0x69; // Nice + + memset(sec_tr->key_a, 0xff, sizeof(sec_tr->key_a)); + memset(sec_tr->key_b, 0xff, sizeof(sec_tr->key_b)); + + mf_classic_set_block_read(data, block, &data->block[block]); + mf_classic_set_key_found( + data, mf_classic_get_sector_by_block(block), MfClassicKeyA, 0xFFFFFFFFFFFF); + mf_classic_set_key_found( + data, mf_classic_get_sector_by_block(block), MfClassicKeyB, 0xFFFFFFFFFFFF); +} + static void nfc_generate_mf_ul_common(NfcDeviceData* data) { data->nfc_data.type = FuriHalNfcTypeA; data->nfc_data.interface = FuriHalNfcInterfaceRf; @@ -36,6 +69,19 @@ static void nfc_generate_mf_ul_common(NfcDeviceData* data) { data->protocol = NfcDeviceProtocolMifareUl; } +static void + nfc_generate_mf_classic_common(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) { + data->nfc_data.type = FuriHalNfcTypeA; + data->nfc_data.interface = FuriHalNfcInterfaceRf; + data->nfc_data.uid_len = uid_len; + nfc_generate_mf_classic_block_0(data->mf_classic_data.block[0].value, uid_len); + data->nfc_data.atqa[0] = 0x44; + data->nfc_data.atqa[1] = 0x00; + data->nfc_data.sak = 0x08; + data->protocol = NfcDeviceProtocolMifareClassic; + data->mf_classic_data.type = type; +} + static void nfc_generate_calc_bcc(uint8_t* uid, uint8_t* bcc0, uint8_t* bcc1) { *bcc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; *bcc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; @@ -268,70 +314,161 @@ static void nfc_generate_ntag_i2c_plus_2k(NfcDeviceData* data) { mful->version.storage_size = 0x15; } +static void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) { + nfc_generate_common_start(data); + nfc_generate_mf_classic_common(data, uid_len, type); + + // Set the UID + data->nfc_data.uid[0] = NXP_MANUFACTURER_ID; + for(int i = 1; i < uid_len; i++) { + data->nfc_data.uid[i] = data->mf_classic_data.block[0].value[i]; + } + + MfClassicData* mfc = &data->mf_classic_data; + mf_classic_set_block_read(mfc, 0, &mfc->block[0]); + + if(type == MfClassicType4k) { + // Set every block to 0xFF + for(uint16_t i = 1; i < 256; i += 1) { + if(mf_classic_is_sector_trailer(i)) { + nfc_generate_mf_classic_sector_trailer(mfc, i); + } else { + memset(&mfc->block[i].value, 0xFF, 16); + } + mf_classic_set_block_read(mfc, i, &mfc->block[i]); + } + } else if(type == MfClassicType1k) { + // Set every block to 0xFF + for(uint16_t i = 1; i < MF_CLASSIC_1K_TOTAL_SECTORS_NUM * 4; i += 1) { + if(mf_classic_is_sector_trailer(i)) { + nfc_generate_mf_classic_sector_trailer(mfc, i); + } else { + memset(&mfc->block[i].value, 0xFF, 16); + } + mf_classic_set_block_read(mfc, i, &mfc->block[i]); + } + } + + mfc->type = type; +} + +static void nfc_generate_mf_classic_1k_4b_uid(NfcDeviceData* data) { + nfc_generate_mf_classic(data, 4, MfClassicType1k); +} + +static void nfc_generate_mf_classic_1k_7b_uid(NfcDeviceData* data) { + nfc_generate_mf_classic(data, 7, MfClassicType1k); +} + +static void nfc_generate_mf_classic_4k_4b_uid(NfcDeviceData* data) { + nfc_generate_mf_classic(data, 4, MfClassicType4k); +} + +static void nfc_generate_mf_classic_4k_7b_uid(NfcDeviceData* data) { + nfc_generate_mf_classic(data, 7, MfClassicType4k); +} + static const NfcGenerator mf_ul_generator = { .name = "Mifare Ultralight", .generator_func = nfc_generate_mf_ul_orig, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator mf_ul_11_generator = { .name = "Mifare Ultralight EV1 11", .generator_func = nfc_generate_mf_ul_11, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator mf_ul_h11_generator = { .name = "Mifare Ultralight EV1 H11", .generator_func = nfc_generate_mf_ul_h11, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator mf_ul_21_generator = { .name = "Mifare Ultralight EV1 21", .generator_func = nfc_generate_mf_ul_21, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator mf_ul_h21_generator = { .name = "Mifare Ultralight EV1 H21", .generator_func = nfc_generate_mf_ul_h21, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator ntag203_generator = { .name = "NTAG203", .generator_func = nfc_generate_mf_ul_ntag203, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator ntag213_generator = { .name = "NTAG213", .generator_func = nfc_generate_ntag213, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator ntag215_generator = { .name = "NTAG215", .generator_func = nfc_generate_ntag215, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator ntag216_generator = { .name = "NTAG216", .generator_func = nfc_generate_ntag216, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator ntag_i2c_1k_generator = { .name = "NTAG I2C 1k", .generator_func = nfc_generate_ntag_i2c_1k, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator ntag_i2c_2k_generator = { .name = "NTAG I2C 2k", .generator_func = nfc_generate_ntag_i2c_2k, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator ntag_i2c_plus_1k_generator = { .name = "NTAG I2C Plus 1k", .generator_func = nfc_generate_ntag_i2c_plus_1k, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; static const NfcGenerator ntag_i2c_plus_2k_generator = { .name = "NTAG I2C Plus 2k", .generator_func = nfc_generate_ntag_i2c_plus_2k, - .next_scene = NfcSceneMfUltralightMenu}; + .next_scene = NfcSceneMfUltralightMenu, +}; + +static const NfcGenerator mifare_classic_1k_4b_uid_generator = { + .name = "Mifare Classic 1k 4byte UID", + .generator_func = nfc_generate_mf_classic_1k_4b_uid, + .next_scene = NfcSceneMfClassicMenu, +}; + +static const NfcGenerator mifare_classic_1k_7b_uid_generator = { + .name = "Mifare Classic 1k 7byte UID", + .generator_func = nfc_generate_mf_classic_1k_7b_uid, + .next_scene = NfcSceneMfClassicMenu, +}; + +static const NfcGenerator mifare_classic_4k_4b_uid_generator = { + .name = "Mifare Classic 4k 4byte UID", + .generator_func = nfc_generate_mf_classic_4k_4b_uid, + .next_scene = NfcSceneMfClassicMenu, +}; + +static const NfcGenerator mifare_classic_4k_7b_uid_generator = { + .name = "Mifare Classic 4k 7byte UID", + .generator_func = nfc_generate_mf_classic_4k_7b_uid, + .next_scene = NfcSceneMfClassicMenu, +}; const NfcGenerator* const nfc_generators[] = { &mf_ul_generator, @@ -347,5 +484,9 @@ const NfcGenerator* const nfc_generators[] = { &ntag_i2c_2k_generator, &ntag_i2c_plus_1k_generator, &ntag_i2c_plus_2k_generator, + &mifare_classic_1k_4b_uid_generator, + &mifare_classic_1k_7b_uid_generator, + &mifare_classic_4k_4b_uid_generator, + &mifare_classic_4k_7b_uid_generator, NULL, }; From 2e993b0a58153b0848387783761d1e3be0116eef Mon Sep 17 00:00:00 2001 From: hedger Date: Thu, 18 Aug 2022 19:46:43 +0300 Subject: [PATCH 24/26] [FL-2748] disabled automatic poweroff for single-frame slideshows #1621 --- applications/desktop/helpers/slideshow.c | 4 ++++ applications/desktop/helpers/slideshow.h | 1 + .../desktop/views/desktop_view_slideshow.c | 14 +++++++++----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/applications/desktop/helpers/slideshow.c b/applications/desktop/helpers/slideshow.c index 63bd42b55d0..b4d85cb9075 100644 --- a/applications/desktop/helpers/slideshow.c +++ b/applications/desktop/helpers/slideshow.c @@ -94,6 +94,10 @@ bool slideshow_is_loaded(Slideshow* slideshow) { return slideshow->loaded; } +bool slideshow_is_one_page(Slideshow* slideshow) { + return slideshow->loaded && (slideshow->icon.frame_count == 1); +} + bool slideshow_advance(Slideshow* slideshow) { uint8_t next_frame = slideshow->current_frame + 1; if(next_frame < slideshow->icon.frame_count) { diff --git a/applications/desktop/helpers/slideshow.h b/applications/desktop/helpers/slideshow.h index eeaac0e8b40..9083e0dcfa4 100644 --- a/applications/desktop/helpers/slideshow.h +++ b/applications/desktop/helpers/slideshow.h @@ -9,6 +9,7 @@ Slideshow* slideshow_alloc(); void slideshow_free(Slideshow* slideshow); bool slideshow_load(Slideshow* slideshow, const char* fspath); bool slideshow_is_loaded(Slideshow* slideshow); +bool slideshow_is_one_page(Slideshow* slideshow); void slideshow_goback(Slideshow* slideshow); bool slideshow_advance(Slideshow* slideshow); void slideshow_draw(Slideshow* slideshow, Canvas* canvas, uint8_t x, uint8_t y); diff --git a/applications/desktop/views/desktop_view_slideshow.c b/applications/desktop/views/desktop_view_slideshow.c index 26ae95eae44..58a8f6d0c1b 100644 --- a/applications/desktop/views/desktop_view_slideshow.c +++ b/applications/desktop/views/desktop_view_slideshow.c @@ -35,8 +35,9 @@ static bool desktop_view_slideshow_input(InputEvent* event, void* context) { furi_assert(event); DesktopSlideshowView* instance = context; + DesktopSlideshowViewModel* model = view_get_model(instance->view); + bool update_view = false; if(event->type == InputTypeShort) { - DesktopSlideshowViewModel* model = view_get_model(instance->view); bool end_slideshow = false; switch(event->key) { case InputKeyLeft: @@ -54,15 +55,18 @@ static bool desktop_view_slideshow_input(InputEvent* event, void* context) { if(end_slideshow) { instance->callback(DesktopSlideshowCompleted, instance->context); } - view_commit_model(instance->view, true); + update_view = true; } else if(event->key == InputKeyOk) { if(event->type == InputTypePress) { furi_timer_start(instance->timer, DESKTOP_SLIDESHOW_POWEROFF_SHORT); } else if(event->type == InputTypeRelease) { furi_timer_stop(instance->timer); - furi_timer_start(instance->timer, DESKTOP_SLIDESHOW_POWEROFF_LONG); + if(!slideshow_is_one_page(model->slideshow)) { + furi_timer_start(instance->timer, DESKTOP_SLIDESHOW_POWEROFF_LONG); + } } } + view_commit_model(instance->view, update_view); return true; } @@ -79,12 +83,12 @@ static void desktop_view_slideshow_enter(void* context) { instance->timer = furi_timer_alloc(desktop_first_start_timer_callback, FuriTimerTypeOnce, instance); - furi_timer_start(instance->timer, DESKTOP_SLIDESHOW_POWEROFF_LONG); - DesktopSlideshowViewModel* model = view_get_model(instance->view); model->slideshow = slideshow_alloc(); if(!slideshow_load(model->slideshow, SLIDESHOW_FS_PATH)) { instance->callback(DesktopSlideshowCompleted, instance->context); + } else if(!slideshow_is_one_page(model->slideshow)) { + furi_timer_start(instance->timer, DESKTOP_SLIDESHOW_POWEROFF_LONG); } view_commit_model(instance->view, false); } From 2a452063c62e35111073cf68623322d7388dc1e5 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Thu, 18 Aug 2022 19:54:17 +0300 Subject: [PATCH 25/26] [FL-2747, FL-2745] Browser worker fix, Device Info screen update #1620 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/desktop/views/desktop_view_debug.c | 15 ++++++++------- applications/gui/modules/file_browser_worker.c | 5 +++++ firmware/targets/f7/ble_glue/ble_glue.c | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/applications/desktop/views/desktop_view_debug.c b/applications/desktop/views/desktop_view_debug.c index 69c82bdbe2a..c965432f17c 100644 --- a/applications/desktop/views/desktop_view_debug.c +++ b/applications/desktop/views/desktop_view_debug.c @@ -23,11 +23,12 @@ 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[] = {"Device Info:", "Dolphin Info:"}; canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 2, 9 + STATUS_BAR_Y_SHIFT, headers[m->screen]); + canvas_draw_str_aligned( + canvas, 64, 1 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignTop, headers[m->screen]); canvas_set_font(canvas, FontSecondary); if(m->screen != DesktopViewStatsMeta) { @@ -44,7 +45,7 @@ void desktop_debug_render(Canvas* canvas, void* model) { furi_hal_version_get_hw_region_name(), furi_hal_region_get_name(), my_name ? my_name : "Unknown"); - canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer); + canvas_draw_str(canvas, 0, 19 + STATUS_BAR_Y_SHIFT, buffer); ver = furi_hal_version_get_firmware_version(); const BleGlueC2Info* c2_ver = NULL; @@ -52,7 +53,7 @@ void desktop_debug_render(Canvas* canvas, void* model) { c2_ver = ble_glue_get_c2_info(); #endif if(!ver) { - canvas_draw_str(canvas, 5, 29 + STATUS_BAR_Y_SHIFT, "No info"); + canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, "No info"); return; } @@ -62,7 +63,7 @@ void desktop_debug_render(Canvas* canvas, void* model) { "%s [%s]", version_get_version(ver), version_get_builddate(ver)); - canvas_draw_str(canvas, 5, 28 + STATUS_BAR_Y_SHIFT, buffer); + canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, buffer); snprintf( buffer, @@ -72,11 +73,11 @@ void desktop_debug_render(Canvas* canvas, void* model) { version_get_githash(ver), version_get_gitbranchnum(ver), c2_ver ? c2_ver->StackTypeString : ""); - canvas_draw_str(canvas, 5, 39 + STATUS_BAR_Y_SHIFT, buffer); + canvas_draw_str(canvas, 0, 40 + STATUS_BAR_Y_SHIFT, buffer); snprintf( buffer, sizeof(buffer), "[%d] %s", version_get_target(ver), version_get_gitbranch(ver)); - canvas_draw_str(canvas, 5, 50 + STATUS_BAR_Y_SHIFT, buffer); + canvas_draw_str(canvas, 0, 50 + STATUS_BAR_Y_SHIFT, buffer); } else { Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); diff --git a/applications/gui/modules/file_browser_worker.c b/applications/gui/modules/file_browser_worker.c index d705e5c3a16..36df6cc83c7 100644 --- a/applications/gui/modules/file_browser_worker.c +++ b/applications/gui/modules/file_browser_worker.c @@ -99,6 +99,11 @@ static bool browser_folder_check_and_switch(string_t path) { FileInfo file_info; Storage* storage = furi_record_open(RECORD_STORAGE); bool is_root = false; + + if(string_search_rchar(path, '/') == 0) { + is_root = true; + } + while(1) { // Check if folder is existing and navigate back if not if(storage_common_stat(storage, string_get_cstr(path), &file_info) == FSE_OK) { diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index be2ae0ee504..585a8982027 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -156,7 +156,7 @@ static void ble_glue_update_c2_fw_info() { snprintf( local_info->StackTypeString, BLE_GLUE_MAX_VERSION_STRING_LEN, - "%d.%d.%d.%s", + "%d.%d.%d:%s", local_info->VersionMajor, local_info->VersionMinor, local_info->VersionSub, From fdb181b1586f69af7a39c5a99ba5cad255127d0b Mon Sep 17 00:00:00 2001 From: Max Andreev Date: Fri, 19 Aug 2022 14:31:45 +0300 Subject: [PATCH 26/26] Fix BT Remote 'stay' button on first launch bug (#1626) --- applications/bt/bt_hid_app/bt_hid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/applications/bt/bt_hid_app/bt_hid.c b/applications/bt/bt_hid_app/bt_hid.c index b6f00e9394a..3189042c0e9 100755 --- a/applications/bt/bt_hid_app/bt_hid.c +++ b/applications/bt/bt_hid_app/bt_hid.c @@ -134,7 +134,8 @@ BtHid* bt_hid_app_alloc() { app->view_dispatcher, BtHidViewMouse, bt_hid_mouse_get_view(app->bt_hid_mouse)); // TODO switch to menu after Media is done - view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewKeynote); + app->view_id = BtHidViewKeynote; + view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); return app; }