diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a9d90cf6b..329dfdc0d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: steps: - name: 'Checkout code' - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} diff --git a/SConstruct b/SConstruct index 698ea85ec..248fcf1d1 100644 --- a/SConstruct +++ b/SConstruct @@ -67,22 +67,22 @@ if GetOption("fullenv") or any( # Target for self-update package dist_basic_arguments = [ "--bundlever", - '"${UPDATE_VERSION_STRING}"', + "${UPDATE_VERSION_STRING}", ] dist_radio_arguments = [ "--radio", - '"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"', + "${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}", "--radiotype", "${COPRO_STACK_TYPE}", "${COPRO_DISCLAIMER}", "--obdata", - '"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"', + "${ROOT_DIR.abspath}/${COPRO_OB_DATA}", "--stackversion", "${COPRO_CUBE_VERSION}", ] dist_resource_arguments = [ "-r", - '"${ROOT_DIR.abspath}/assets/resources"', + firmware_env.subst("${RESOURCES_ROOT}"), ] dist_splash_arguments = ( [ @@ -95,7 +95,7 @@ if GetOption("fullenv") or any( selfupdate_dist = distenv.DistCommand( "updater_package", - (distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]), + (distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES_MANIFEST"]), DIST_EXTRA=[ *dist_basic_arguments, *dist_radio_arguments, @@ -128,7 +128,8 @@ if GetOption("fullenv") or any( # Installation over USB & CLI usb_update_package = distenv.AddUsbFlashTarget( - "#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist) + "#build/usbinstall.flag", + (firmware_env["FW_RESOURCES_MANIFEST"], selfupdate_dist), ) distenv.Alias("flash_usb_full", usb_update_package) @@ -166,17 +167,25 @@ Depends( list(app_artifact.validator for app_artifact in external_app_list), ) Alias("fap_dist", fap_dist) -# distenv.Default(fap_dist) - -distenv.Depends(firmware_env["FW_RESOURCES"], external_apps_artifacts.resources_dist) # Copy all faps to device fap_deploy = distenv.PhonyTarget( "fap_deploy", - "${PYTHON3} ${FBT_SCRIPT_DIR}/storage.py -p ${FLIP_PORT} send ${SOURCE} /ext/apps", - source=Dir("#/assets/resources/apps"), + [ + [ + "${PYTHON3}", + "${FBT_SCRIPT_DIR}/storage.py", + "-p", + "${FLIP_PORT}", + "send", + "${SOURCE}", + "/ext/apps", + ] + ], + source=firmware_env.Dir(("${RESOURCES_ROOT}/apps")), ) +Depends(fap_deploy, firmware_env["FW_RESOURCES_MANIFEST"]) # Target for bundling core2 package for qFlipper @@ -314,9 +323,7 @@ distenv.PhonyTarget( ) # Start Flipper CLI via PySerial's miniterm -distenv.PhonyTarget( - "cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py -p ${FLIP_PORT}" -) +distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py -p ${FLIP_PORT}") # Update WiFi devboard firmware distenv.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py") diff --git a/applications/debug/direct_draw/direct_draw.c b/applications/debug/direct_draw/direct_draw.c index 71c65eab1..63e03530a 100644 --- a/applications/debug/direct_draw/direct_draw.c +++ b/applications/debug/direct_draw/direct_draw.c @@ -71,7 +71,7 @@ static void direct_draw_run(DirectDraw* instance) { size_t counter = 0; float fps = 0; - vTaskPrioritySet(furi_thread_get_current_id(), FuriThreadPriorityIdle); + furi_thread_set_current_priority(FuriThreadPriorityIdle); do { size_t elapsed = DWT->CYCCNT - start; diff --git a/applications/debug/rpc_debug_app/rpc_debug_app.c b/applications/debug/rpc_debug_app/rpc_debug_app.c index 314be5e72..2a0756383 100644 --- a/applications/debug/rpc_debug_app/rpc_debug_app.c +++ b/applications/debug/rpc_debug_app/rpc_debug_app.c @@ -21,22 +21,51 @@ static void rpc_debug_app_tick_event_callback(void* context) { scene_manager_handle_tick_event(app->scene_manager); } -static void rpc_debug_app_rpc_command_callback(RpcAppSystemEvent event, void* context) { +static void + rpc_debug_app_format_hex(const uint8_t* data, size_t data_size, char* buf, size_t buf_size) { + if(data == NULL || data_size == 0) { + strncpy(buf, "", buf_size); + return; + } + + const size_t byte_width = 3; + const size_t line_width = 7; + + data_size = MIN(data_size, buf_size / (byte_width + 1)); + + for(size_t i = 0; i < data_size; ++i) { + char* p = buf + (i * byte_width); + char sep = !((i + 1) % line_width) ? '\n' : ' '; + snprintf(p, byte_width + 1, "%02X%c", data[i], sep); + } + + buf[buf_size - 1] = '\0'; +} + +static void rpc_debug_app_rpc_command_callback(const RpcAppSystemEvent* event, void* context) { furi_assert(context); RpcDebugApp* app = context; furi_assert(app->rpc); - if(event == RpcAppEventSessionClose) { + if(event->type == RpcAppEventTypeSessionClose) { scene_manager_stop(app->scene_manager); view_dispatcher_stop(app->view_dispatcher); rpc_system_app_set_callback(app->rpc, NULL, NULL); app->rpc = NULL; - } else if(event == RpcAppEventAppExit) { + } else if(event->type == RpcAppEventTypeAppExit) { scene_manager_stop(app->scene_manager); view_dispatcher_stop(app->view_dispatcher); - rpc_system_app_confirm(app->rpc, RpcAppEventAppExit, true); + rpc_system_app_confirm(app->rpc, true); + } else if(event->type == RpcAppEventTypeDataExchange) { + furi_assert(event->data.type == RpcAppSystemEventDataTypeBytes); + + rpc_debug_app_format_hex( + event->data.bytes.ptr, event->data.bytes.size, app->text_store, TEXT_STORE_SIZE); + + view_dispatcher_send_custom_event( + app->view_dispatcher, RpcDebugAppCustomEventRpcDataExchange); } else { - rpc_system_app_confirm(app->rpc, event, false); + rpc_system_app_confirm(app->rpc, false); } } diff --git a/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_receive_data_exchange.c b/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_receive_data_exchange.c index 98bafff8a..10d5e36f6 100644 --- a/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_receive_data_exchange.c +++ b/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_receive_data_exchange.c @@ -1,40 +1,5 @@ #include "../rpc_debug_app.h" -static void rpc_debug_app_scene_start_format_hex( - const uint8_t* data, - size_t data_size, - char* buf, - size_t buf_size) { - furi_assert(data); - furi_assert(buf); - - const size_t byte_width = 3; - const size_t line_width = 7; - - data_size = MIN(data_size, buf_size / (byte_width + 1)); - - for(size_t i = 0; i < data_size; ++i) { - char* p = buf + (i * byte_width); - char sep = !((i + 1) % line_width) ? '\n' : ' '; - snprintf(p, byte_width + 1, "%02X%c", data[i], sep); - } - - buf[buf_size - 1] = '\0'; -} - -static void rpc_debug_app_scene_receive_data_exchange_callback( - const uint8_t* data, - size_t data_size, - void* context) { - RpcDebugApp* app = context; - if(data) { - rpc_debug_app_scene_start_format_hex(data, data_size, app->text_store, TEXT_STORE_SIZE); - } else { - strncpy(app->text_store, "", TEXT_STORE_SIZE); - } - view_dispatcher_send_custom_event(app->view_dispatcher, RpcDebugAppCustomEventRpcDataExchange); -} - void rpc_debug_app_scene_receive_data_exchange_on_enter(void* context) { RpcDebugApp* app = context; strncpy(app->text_store, "Received data will appear here...", TEXT_STORE_SIZE); @@ -42,8 +7,6 @@ void rpc_debug_app_scene_receive_data_exchange_on_enter(void* context) { text_box_set_text(app->text_box, app->text_store); text_box_set_font(app->text_box, TextBoxFontHex); - rpc_system_app_set_data_exchange_callback( - app->rpc, rpc_debug_app_scene_receive_data_exchange_callback, app); view_dispatcher_switch_to_view(app->view_dispatcher, RpcDebugAppViewTextBox); } @@ -53,6 +16,7 @@ bool rpc_debug_app_scene_receive_data_exchange_on_event(void* context, SceneMana if(event.type == SceneManagerEventTypeCustom) { if(event.event == RpcDebugAppCustomEventRpcDataExchange) { + rpc_system_app_confirm(app->rpc, true); notification_message(app->notifications, &sequence_blink_cyan_100); notification_message(app->notifications, &sequence_display_backlight_on); text_box_set_text(app->text_box, app->text_store); @@ -66,5 +30,4 @@ bool rpc_debug_app_scene_receive_data_exchange_on_event(void* context, SceneMana void rpc_debug_app_scene_receive_data_exchange_on_exit(void* context) { RpcDebugApp* app = context; text_box_reset(app->text_box); - rpc_system_app_set_data_exchange_callback(app->rpc, NULL, NULL); } diff --git a/applications/debug/unit_tests/application.fam b/applications/debug/unit_tests/application.fam index ad9a278f3..aa25dab27 100644 --- a/applications/debug/unit_tests/application.fam +++ b/applications/debug/unit_tests/application.fam @@ -5,6 +5,7 @@ App( cdefines=["APP_UNIT_TESTS"], requires=["system_settings"], provides=["delay_test"], + resources="resources", order=100, ) diff --git a/applications/debug/unit_tests/bt/bt_test.c b/applications/debug/unit_tests/bt/bt_test.c index 2cbfd684a..32cf6533f 100644 --- a/applications/debug/unit_tests/bt/bt_test.c +++ b/applications/debug/unit_tests/bt/bt_test.c @@ -28,7 +28,7 @@ void bt_test_alloc() { } void bt_test_free() { - furi_assert(bt_test); + furi_check(bt_test); free(bt_test->nvm_ram_buff_ref); free(bt_test->nvm_ram_buff_dut); bt_keys_storage_free(bt_test->bt_keys_storage); @@ -89,7 +89,7 @@ static void bt_test_keys_remove_test_file() { } MU_TEST(bt_test_keys_storage_serial_profile) { - furi_assert(bt_test); + furi_check(bt_test); bt_test_keys_remove_test_file(); bt_test_keys_storage_profile(); diff --git a/applications/debug/unit_tests/infrared/infrared_test.c b/applications/debug/unit_tests/infrared/infrared_test.c index b2acad470..294c2da9a 100644 --- a/applications/debug/unit_tests/infrared/infrared_test.c +++ b/applications/debug/unit_tests/infrared/infrared_test.c @@ -27,7 +27,7 @@ static void infrared_test_alloc() { } static void infrared_test_free() { - furi_assert(test); + furi_check(test); infrared_free_decoder(test->decoder_handler); infrared_free_encoder(test->encoder_handler); flipper_format_free(test->ff); diff --git a/applications/debug/unit_tests/manifest/manifest.c b/applications/debug/unit_tests/manifest/manifest.c index 0b24ad1ed..19370b0e1 100644 --- a/applications/debug/unit_tests/manifest/manifest.c +++ b/applications/debug/unit_tests/manifest/manifest.c @@ -22,7 +22,7 @@ MU_TEST(manifest_iteration_test) { ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(storage); do { // Open manifest file - if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("unit_tests/Manifest"))) { + if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("unit_tests/Manifest_test"))) { result = false; break; } diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c index e7406fab8..2d647f8ef 100644 --- a/applications/debug/unit_tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/nfc/nfc_test.c @@ -34,7 +34,7 @@ static void nfc_test_alloc() { } static void nfc_test_free() { - furi_assert(nfc_test); + furi_check(nfc_test); furi_record_close(RECORD_STORAGE); free(nfc_test); diff --git a/applications/debug/unit_tests/nfc/nfc_transport.c b/applications/debug/unit_tests/nfc/nfc_transport.c index ee2657bea..e2e313fde 100644 --- a/applications/debug/unit_tests/nfc/nfc_transport.c +++ b/applications/debug/unit_tests/nfc/nfc_transport.c @@ -122,7 +122,7 @@ Nfc* nfc_alloc() { } void nfc_free(Nfc* instance) { - furi_assert(instance); + furi_check(instance); free(instance); } @@ -165,9 +165,9 @@ NfcError nfc_iso14443a_listener_set_col_res_data( uint8_t uid_len, uint8_t* atqa, uint8_t sak) { - furi_assert(instance); - furi_assert(uid); - furi_assert(atqa); + furi_check(instance); + furi_check(uid); + furi_check(atqa); nfc_prepare_col_res_data(instance, uid, uid_len, atqa, sak); @@ -176,7 +176,7 @@ NfcError nfc_iso14443a_listener_set_col_res_data( static int32_t nfc_worker_poller(void* context) { Nfc* instance = context; - furi_assert(instance->callback); + furi_check(instance->callback); instance->state = NfcStateReady; NfcCommand command = NfcCommandContinue; @@ -196,7 +196,7 @@ static int32_t nfc_worker_poller(void* context) { } static void nfc_worker_listener_pass_col_res(Nfc* instance, uint8_t* rx_data, uint16_t rx_bits) { - furi_assert(instance->col_res_status != Iso14443_3aColResStatusDone); + furi_check(instance->col_res_status != Iso14443_3aColResStatusDone); BitBuffer* tx_buffer = bit_buffer_alloc(NFC_MAX_BUFFER_SIZE); bool processed = false; @@ -255,7 +255,7 @@ static void nfc_worker_listener_pass_col_res(Nfc* instance, uint8_t* rx_data, ui static int32_t nfc_worker_listener(void* context) { Nfc* instance = context; - furi_assert(instance->callback); + furi_check(instance->callback); NfcMessage message = {}; @@ -295,17 +295,17 @@ static int32_t nfc_worker_listener(void* context) { } void nfc_start(Nfc* instance, NfcEventCallback callback, void* context) { - furi_assert(instance); - furi_assert(instance->worker_thread == NULL); + furi_check(instance); + furi_check(instance->worker_thread == NULL); if(instance->mode == NfcModeListener) { - furi_assert(listener_queue == NULL); + furi_check(listener_queue == NULL); // Check that poller didn't start - furi_assert(poller_queue == NULL); + furi_check(poller_queue == NULL); } else { - furi_assert(poller_queue == NULL); + furi_check(poller_queue == NULL); // Check that poller is started after listener - furi_assert(listener_queue); + furi_check(listener_queue); } instance->callback = callback; @@ -334,8 +334,8 @@ void nfc_start(Nfc* instance, NfcEventCallback callback, void* context) { } void nfc_stop(Nfc* instance) { - furi_assert(instance); - furi_assert(instance->worker_thread); + furi_check(instance); + furi_check(instance->worker_thread); if(instance->mode == NfcModeListener) { NfcMessage message = {.type = NfcMessageTypeAbort}; @@ -361,10 +361,10 @@ void nfc_stop(Nfc* instance) { // Called from worker thread NfcError nfc_listener_tx(Nfc* instance, const BitBuffer* tx_buffer) { - furi_assert(instance); - furi_assert(poller_queue); - furi_assert(listener_queue); - furi_assert(tx_buffer); + furi_check(instance); + furi_check(poller_queue); + furi_check(listener_queue); + furi_check(tx_buffer); NfcMessage message = {}; message.type = NfcMessageTypeTx; @@ -382,11 +382,11 @@ NfcError nfc_iso14443a_listener_tx_custom_parity(Nfc* instance, const BitBuffer* NfcError nfc_poller_trx(Nfc* instance, const BitBuffer* tx_buffer, BitBuffer* rx_buffer, uint32_t fwt) { - furi_assert(instance); - furi_assert(tx_buffer); - furi_assert(rx_buffer); - furi_assert(poller_queue); - furi_assert(listener_queue); + furi_check(instance); + furi_check(tx_buffer); + furi_check(rx_buffer); + furi_check(poller_queue); + furi_check(listener_queue); UNUSED(fwt); NfcError error = NfcErrorNone; @@ -396,7 +396,7 @@ NfcError message.data.data_bits = bit_buffer_get_size(tx_buffer); bit_buffer_write_bytes(tx_buffer, message.data.data, bit_buffer_get_size_bytes(tx_buffer)); // Tx - furi_assert(furi_message_queue_put(listener_queue, &message, FuriWaitForever) == FuriStatusOk); + furi_check(furi_message_queue_put(listener_queue, &message, FuriWaitForever) == FuriStatusOk); // Rx FuriStatus status = furi_message_queue_get(poller_queue, &message, 50); diff --git a/assets/unit_tests/Manifest b/applications/debug/unit_tests/resources/unit_tests/Manifest_test similarity index 100% rename from assets/unit_tests/Manifest rename to applications/debug/unit_tests/resources/unit_tests/Manifest_test diff --git a/assets/unit_tests/infrared/test_kaseikyo.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_kaseikyo.irtest similarity index 100% rename from assets/unit_tests/infrared/test_kaseikyo.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_kaseikyo.irtest diff --git a/assets/unit_tests/infrared/test_nec.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_nec.irtest similarity index 100% rename from assets/unit_tests/infrared/test_nec.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_nec.irtest diff --git a/assets/unit_tests/infrared/test_nec42.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_nec42.irtest similarity index 100% rename from assets/unit_tests/infrared/test_nec42.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_nec42.irtest diff --git a/assets/unit_tests/infrared/test_nec42ext.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_nec42ext.irtest similarity index 100% rename from assets/unit_tests/infrared/test_nec42ext.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_nec42ext.irtest diff --git a/assets/unit_tests/infrared/test_necext.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_necext.irtest similarity index 100% rename from assets/unit_tests/infrared/test_necext.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_necext.irtest diff --git a/assets/unit_tests/infrared/test_rc5.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_rc5.irtest similarity index 100% rename from assets/unit_tests/infrared/test_rc5.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_rc5.irtest diff --git a/assets/unit_tests/infrared/test_rc5x.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_rc5x.irtest similarity index 100% rename from assets/unit_tests/infrared/test_rc5x.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_rc5x.irtest diff --git a/assets/unit_tests/infrared/test_rc6.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_rc6.irtest similarity index 100% rename from assets/unit_tests/infrared/test_rc6.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_rc6.irtest diff --git a/assets/unit_tests/infrared/test_rca.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_rca.irtest similarity index 100% rename from assets/unit_tests/infrared/test_rca.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_rca.irtest diff --git a/assets/unit_tests/infrared/test_samsung32.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_samsung32.irtest similarity index 100% rename from assets/unit_tests/infrared/test_samsung32.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_samsung32.irtest diff --git a/assets/unit_tests/infrared/test_sirc.irtest b/applications/debug/unit_tests/resources/unit_tests/infrared/test_sirc.irtest similarity index 100% rename from assets/unit_tests/infrared/test_sirc.irtest rename to applications/debug/unit_tests/resources/unit_tests/infrared/test_sirc.irtest diff --git a/assets/unit_tests/nfc/Ntag213_locked.nfc b/applications/debug/unit_tests/resources/unit_tests/nfc/Ntag213_locked.nfc similarity index 100% rename from assets/unit_tests/nfc/Ntag213_locked.nfc rename to applications/debug/unit_tests/resources/unit_tests/nfc/Ntag213_locked.nfc diff --git a/assets/unit_tests/nfc/Ntag215.nfc b/applications/debug/unit_tests/resources/unit_tests/nfc/Ntag215.nfc similarity index 100% rename from assets/unit_tests/nfc/Ntag215.nfc rename to applications/debug/unit_tests/resources/unit_tests/nfc/Ntag215.nfc diff --git a/assets/unit_tests/nfc/Ntag216.nfc b/applications/debug/unit_tests/resources/unit_tests/nfc/Ntag216.nfc similarity index 100% rename from assets/unit_tests/nfc/Ntag216.nfc rename to applications/debug/unit_tests/resources/unit_tests/nfc/Ntag216.nfc diff --git a/assets/unit_tests/nfc/Ultralight_11.nfc b/applications/debug/unit_tests/resources/unit_tests/nfc/Ultralight_11.nfc similarity index 100% rename from assets/unit_tests/nfc/Ultralight_11.nfc rename to applications/debug/unit_tests/resources/unit_tests/nfc/Ultralight_11.nfc diff --git a/assets/unit_tests/nfc/Ultralight_21.nfc b/applications/debug/unit_tests/resources/unit_tests/nfc/Ultralight_21.nfc similarity index 100% rename from assets/unit_tests/nfc/Ultralight_21.nfc rename to applications/debug/unit_tests/resources/unit_tests/nfc/Ultralight_21.nfc diff --git a/assets/unit_tests/nfc/nfc_nfca_signal_long.nfc b/applications/debug/unit_tests/resources/unit_tests/nfc/nfc_nfca_signal_long.nfc similarity index 100% rename from assets/unit_tests/nfc/nfc_nfca_signal_long.nfc rename to applications/debug/unit_tests/resources/unit_tests/nfc/nfc_nfca_signal_long.nfc diff --git a/assets/unit_tests/nfc/nfc_nfca_signal_short.nfc b/applications/debug/unit_tests/resources/unit_tests/nfc/nfc_nfca_signal_short.nfc similarity index 100% rename from assets/unit_tests/nfc/nfc_nfca_signal_short.nfc rename to applications/debug/unit_tests/resources/unit_tests/nfc/nfc_nfca_signal_short.nfc diff --git a/assets/unit_tests/storage/md5.txt b/applications/debug/unit_tests/resources/unit_tests/storage/md5.txt similarity index 100% rename from assets/unit_tests/storage/md5.txt rename to applications/debug/unit_tests/resources/unit_tests/storage/md5.txt diff --git a/assets/unit_tests/subghz/acurite_592txr.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/acurite_592txr.sub similarity index 100% rename from assets/unit_tests/subghz/acurite_592txr.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/acurite_592txr.sub diff --git a/assets/unit_tests/subghz/alutech_at_4n_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/alutech_at_4n_raw.sub similarity index 100% rename from assets/unit_tests/subghz/alutech_at_4n_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/alutech_at_4n_raw.sub diff --git a/assets/unit_tests/subghz/ansonic.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/ansonic.sub similarity index 100% rename from assets/unit_tests/subghz/ansonic.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/ansonic.sub diff --git a/assets/unit_tests/subghz/ansonic_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/ansonic_raw.sub similarity index 100% rename from assets/unit_tests/subghz/ansonic_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/ansonic_raw.sub diff --git a/assets/unit_tests/subghz/bett.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/bett.sub similarity index 100% rename from assets/unit_tests/subghz/bett.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/bett.sub diff --git a/assets/unit_tests/subghz/bett_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/bett_raw.sub similarity index 100% rename from assets/unit_tests/subghz/bett_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/bett_raw.sub diff --git a/assets/unit_tests/subghz/came.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/came.sub similarity index 100% rename from assets/unit_tests/subghz/came.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/came.sub diff --git a/assets/unit_tests/subghz/came_atomo_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/came_atomo_raw.sub similarity index 100% rename from assets/unit_tests/subghz/came_atomo_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/came_atomo_raw.sub diff --git a/assets/unit_tests/subghz/came_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/came_raw.sub similarity index 100% rename from assets/unit_tests/subghz/came_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/came_raw.sub diff --git a/assets/unit_tests/subghz/came_twee.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/came_twee.sub similarity index 100% rename from assets/unit_tests/subghz/came_twee.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/came_twee.sub diff --git a/assets/unit_tests/subghz/came_twee_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/came_twee_raw.sub similarity index 100% rename from assets/unit_tests/subghz/came_twee_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/came_twee_raw.sub diff --git a/assets/unit_tests/subghz/cenmax_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/cenmax_raw.sub similarity index 100% rename from assets/unit_tests/subghz/cenmax_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/cenmax_raw.sub diff --git a/assets/unit_tests/subghz/clemsa.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/clemsa.sub similarity index 100% rename from assets/unit_tests/subghz/clemsa.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/clemsa.sub diff --git a/assets/unit_tests/subghz/clemsa_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/clemsa_raw.sub similarity index 100% rename from assets/unit_tests/subghz/clemsa_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/clemsa_raw.sub diff --git a/assets/unit_tests/subghz/doitrand.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/doitrand.sub similarity index 100% rename from assets/unit_tests/subghz/doitrand.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/doitrand.sub diff --git a/assets/unit_tests/subghz/doitrand_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/doitrand_raw.sub similarity index 100% rename from assets/unit_tests/subghz/doitrand_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/doitrand_raw.sub diff --git a/assets/unit_tests/subghz/doorhan.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/doorhan.sub similarity index 100% rename from assets/unit_tests/subghz/doorhan.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/doorhan.sub diff --git a/assets/unit_tests/subghz/doorhan_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/doorhan_raw.sub similarity index 100% rename from assets/unit_tests/subghz/doorhan_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/doorhan_raw.sub diff --git a/assets/unit_tests/subghz/dooya.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/dooya.sub similarity index 100% rename from assets/unit_tests/subghz/dooya.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/dooya.sub diff --git a/assets/unit_tests/subghz/dooya_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/dooya_raw.sub similarity index 100% rename from assets/unit_tests/subghz/dooya_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/dooya_raw.sub diff --git a/assets/unit_tests/subghz/faac_slh_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/faac_slh_raw.sub similarity index 100% rename from assets/unit_tests/subghz/faac_slh_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/faac_slh_raw.sub diff --git a/assets/unit_tests/subghz/gate_tx.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/gate_tx.sub similarity index 100% rename from assets/unit_tests/subghz/gate_tx.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/gate_tx.sub diff --git a/assets/unit_tests/subghz/gate_tx_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/gate_tx_raw.sub similarity index 100% rename from assets/unit_tests/subghz/gate_tx_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/gate_tx_raw.sub diff --git a/assets/unit_tests/subghz/holtek.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/holtek.sub similarity index 100% rename from assets/unit_tests/subghz/holtek.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/holtek.sub diff --git a/assets/unit_tests/subghz/holtek_ht12x.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/holtek_ht12x.sub similarity index 100% rename from assets/unit_tests/subghz/holtek_ht12x.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/holtek_ht12x.sub diff --git a/assets/unit_tests/subghz/holtek_ht12x_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/holtek_ht12x_raw.sub similarity index 100% rename from assets/unit_tests/subghz/holtek_ht12x_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/holtek_ht12x_raw.sub diff --git a/assets/unit_tests/subghz/holtek_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/holtek_raw.sub similarity index 100% rename from assets/unit_tests/subghz/holtek_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/holtek_raw.sub diff --git a/assets/unit_tests/subghz/honeywell_wdb.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/honeywell_wdb.sub similarity index 100% rename from assets/unit_tests/subghz/honeywell_wdb.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/honeywell_wdb.sub diff --git a/assets/unit_tests/subghz/honeywell_wdb_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/honeywell_wdb_raw.sub similarity index 100% rename from assets/unit_tests/subghz/honeywell_wdb_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/honeywell_wdb_raw.sub diff --git a/assets/unit_tests/subghz/hormann_hsm_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/hormann_hsm_raw.sub similarity index 100% rename from assets/unit_tests/subghz/hormann_hsm_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/hormann_hsm_raw.sub diff --git a/assets/unit_tests/subghz/ido_117_111_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/ido_117_111_raw.sub similarity index 100% rename from assets/unit_tests/subghz/ido_117_111_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/ido_117_111_raw.sub diff --git a/assets/unit_tests/subghz/intertechno_v3.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/intertechno_v3.sub similarity index 100% rename from assets/unit_tests/subghz/intertechno_v3.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/intertechno_v3.sub diff --git a/assets/unit_tests/subghz/intertechno_v3_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/intertechno_v3_raw.sub similarity index 100% rename from assets/unit_tests/subghz/intertechno_v3_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/intertechno_v3_raw.sub diff --git a/assets/unit_tests/subghz/kia_seed_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/kia_seed_raw.sub similarity index 100% rename from assets/unit_tests/subghz/kia_seed_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/kia_seed_raw.sub diff --git a/assets/unit_tests/subghz/kinggates_stylo4k_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/kinggates_stylo4k_raw.sub similarity index 100% rename from assets/unit_tests/subghz/kinggates_stylo4k_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/kinggates_stylo4k_raw.sub diff --git a/assets/unit_tests/subghz/linear.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/linear.sub similarity index 100% rename from assets/unit_tests/subghz/linear.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/linear.sub diff --git a/assets/unit_tests/subghz/linear_delta3.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/linear_delta3.sub similarity index 100% rename from assets/unit_tests/subghz/linear_delta3.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/linear_delta3.sub diff --git a/assets/unit_tests/subghz/linear_delta3_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/linear_delta3_raw.sub similarity index 100% rename from assets/unit_tests/subghz/linear_delta3_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/linear_delta3_raw.sub diff --git a/assets/unit_tests/subghz/linear_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/linear_raw.sub similarity index 100% rename from assets/unit_tests/subghz/linear_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/linear_raw.sub diff --git a/assets/unit_tests/subghz/magellan.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/magellan.sub similarity index 100% rename from assets/unit_tests/subghz/magellan.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/magellan.sub diff --git a/assets/unit_tests/subghz/magellan_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/magellan_raw.sub similarity index 100% rename from assets/unit_tests/subghz/magellan_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/magellan_raw.sub diff --git a/assets/unit_tests/subghz/marantec.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/marantec.sub similarity index 100% rename from assets/unit_tests/subghz/marantec.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/marantec.sub diff --git a/assets/unit_tests/subghz/marantec_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/marantec_raw.sub similarity index 100% rename from assets/unit_tests/subghz/marantec_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/marantec_raw.sub diff --git a/assets/unit_tests/subghz/megacode.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/megacode.sub similarity index 100% rename from assets/unit_tests/subghz/megacode.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/megacode.sub diff --git a/assets/unit_tests/subghz/megacode_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/megacode_raw.sub similarity index 100% rename from assets/unit_tests/subghz/megacode_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/megacode_raw.sub diff --git a/assets/unit_tests/subghz/nero_radio_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/nero_radio_raw.sub similarity index 100% rename from assets/unit_tests/subghz/nero_radio_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/nero_radio_raw.sub diff --git a/assets/unit_tests/subghz/nero_sketch_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/nero_sketch_raw.sub similarity index 100% rename from assets/unit_tests/subghz/nero_sketch_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/nero_sketch_raw.sub diff --git a/assets/unit_tests/subghz/nice_flo.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/nice_flo.sub similarity index 100% rename from assets/unit_tests/subghz/nice_flo.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/nice_flo.sub diff --git a/assets/unit_tests/subghz/nice_flo_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/nice_flo_raw.sub similarity index 100% rename from assets/unit_tests/subghz/nice_flo_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/nice_flo_raw.sub diff --git a/assets/unit_tests/subghz/nice_flor_s_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/nice_flor_s_raw.sub similarity index 100% rename from assets/unit_tests/subghz/nice_flor_s_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/nice_flor_s_raw.sub diff --git a/assets/unit_tests/subghz/nice_one_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/nice_one_raw.sub similarity index 100% rename from assets/unit_tests/subghz/nice_one_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/nice_one_raw.sub diff --git a/assets/unit_tests/subghz/phoenix_v2.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/phoenix_v2.sub similarity index 100% rename from assets/unit_tests/subghz/phoenix_v2.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/phoenix_v2.sub diff --git a/assets/unit_tests/subghz/phoenix_v2_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/phoenix_v2_raw.sub similarity index 100% rename from assets/unit_tests/subghz/phoenix_v2_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/phoenix_v2_raw.sub diff --git a/assets/unit_tests/subghz/power_smart.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/power_smart.sub similarity index 100% rename from assets/unit_tests/subghz/power_smart.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/power_smart.sub diff --git a/assets/unit_tests/subghz/power_smart_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/power_smart_raw.sub similarity index 100% rename from assets/unit_tests/subghz/power_smart_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/power_smart_raw.sub diff --git a/assets/unit_tests/subghz/princeton.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/princeton.sub similarity index 100% rename from assets/unit_tests/subghz/princeton.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/princeton.sub diff --git a/assets/unit_tests/subghz/princeton_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/princeton_raw.sub similarity index 100% rename from assets/unit_tests/subghz/princeton_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/princeton_raw.sub diff --git a/assets/unit_tests/subghz/scher_khan_magic_code.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/scher_khan_magic_code.sub similarity index 100% rename from assets/unit_tests/subghz/scher_khan_magic_code.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/scher_khan_magic_code.sub diff --git a/assets/unit_tests/subghz/security_pls_1_0.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/security_pls_1_0.sub similarity index 100% rename from assets/unit_tests/subghz/security_pls_1_0.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/security_pls_1_0.sub diff --git a/assets/unit_tests/subghz/security_pls_1_0_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/security_pls_1_0_raw.sub similarity index 100% rename from assets/unit_tests/subghz/security_pls_1_0_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/security_pls_1_0_raw.sub diff --git a/assets/unit_tests/subghz/security_pls_2_0.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/security_pls_2_0.sub similarity index 100% rename from assets/unit_tests/subghz/security_pls_2_0.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/security_pls_2_0.sub diff --git a/assets/unit_tests/subghz/security_pls_2_0_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/security_pls_2_0_raw.sub similarity index 100% rename from assets/unit_tests/subghz/security_pls_2_0_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/security_pls_2_0_raw.sub diff --git a/assets/unit_tests/subghz/smc5326.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/smc5326.sub similarity index 100% rename from assets/unit_tests/subghz/smc5326.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/smc5326.sub diff --git a/assets/unit_tests/subghz/smc5326_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/smc5326_raw.sub similarity index 100% rename from assets/unit_tests/subghz/smc5326_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/smc5326_raw.sub diff --git a/assets/unit_tests/subghz/somfy_keytis_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/somfy_keytis_raw.sub similarity index 100% rename from assets/unit_tests/subghz/somfy_keytis_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/somfy_keytis_raw.sub diff --git a/assets/unit_tests/subghz/somfy_telis_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/somfy_telis_raw.sub similarity index 100% rename from assets/unit_tests/subghz/somfy_telis_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/somfy_telis_raw.sub diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/test_random_raw.sub similarity index 100% rename from assets/unit_tests/subghz/test_random_raw.sub rename to applications/debug/unit_tests/resources/unit_tests/subghz/test_random_raw.sub diff --git a/applications/debug/unit_tests/rpc/rpc_test.c b/applications/debug/unit_tests/rpc/rpc_test.c index dfded7784..f9871d6b2 100644 --- a/applications/debug/unit_tests/rpc/rpc_test.c +++ b/applications/debug/unit_tests/rpc/rpc_test.c @@ -18,6 +18,8 @@ #include #include #include + +#include #include LIST_DEF(MsgList, PB_Main, M_POD_OPLIST) @@ -36,7 +38,7 @@ typedef struct { FuriStreamBuffer* output_stream; SemaphoreHandle_t close_session_semaphore; SemaphoreHandle_t terminate_semaphore; - TickType_t timeout; + uint32_t timeout; } RpcSessionContext; static RpcSessionContext rpc_session[TEST_RPC_SESSIONS]; @@ -544,7 +546,7 @@ static bool test_rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_ RpcSessionContext* session_context = istream->state; size_t bytes_received = 0; - TickType_t now = xTaskGetTickCount(); + uint32_t now = furi_get_tick(); int32_t time_left = session_context->timeout - now; time_left = MAX(time_left, 0); bytes_received = @@ -688,7 +690,7 @@ static void test_rpc_decode_and_compare(MsgList_t expected_msg_list, uint8_t ses furi_check(!MsgList_empty_p(expected_msg_list)); furi_check(session < TEST_RPC_SESSIONS); - rpc_session[session].timeout = xTaskGetTickCount() + MAX_RECEIVE_OUTPUT_TIMEOUT; + rpc_session[session].timeout = furi_get_tick() + MAX_RECEIVE_OUTPUT_TIMEOUT; pb_istream_t istream = { .callback = test_rpc_pb_stream_read, .state = &rpc_session[session], @@ -712,7 +714,7 @@ static void test_rpc_decode_and_compare(MsgList_t expected_msg_list, uint8_t ses pb_release(&PB_Main_msg, &result); } - rpc_session[session].timeout = xTaskGetTickCount() + 50; + rpc_session[session].timeout = furi_get_tick() + 50; if(pb_decode_ex(&istream, &PB_Main_msg, &result, PB_DECODE_DELIMITED)) { mu_fail("decoded more than expected"); } diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index edaf950c5..7c1b6b444 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -65,8 +65,8 @@ const UnitTest unit_tests[] = { void minunit_print_progress() { static const char progress[] = {'\\', '|', '/', '-'}; static uint8_t progress_counter = 0; - static TickType_t last_tick = 0; - TickType_t current_tick = xTaskGetTickCount(); + static uint32_t last_tick = 0; + uint32_t current_tick = furi_get_tick(); if(current_tick - last_tick > 20) { last_tick = current_tick; printf("[%c]\033[3D", progress[++progress_counter % COUNT_OF(progress)]); diff --git a/applications/examples/example_plugins/application.fam b/applications/examples/example_plugins/application.fam index a6e3c2078..d9a36da56 100644 --- a/applications/examples/example_plugins/application.fam +++ b/applications/examples/example_plugins/application.fam @@ -5,6 +5,7 @@ App( entry_point="example_plugins_app", stack_size=2 * 1024, fap_category="Examples", + sources=["*.c", "!plugin*.c"], ) App( @@ -21,6 +22,7 @@ App( apptype=FlipperAppType.PLUGIN, entry_point="example_plugin1_ep", requires=["example_plugins", "example_plugins_multi"], + sources=["plugin1.c"], ) App( @@ -28,4 +30,5 @@ App( apptype=FlipperAppType.PLUGIN, entry_point="example_plugin2_ep", requires=["example_plugins_multi"], + sources=["plugin2.c"], ) diff --git a/applications/examples/example_plugins_advanced/application.fam b/applications/examples/example_plugins_advanced/application.fam index d40c0dde2..0c7e3e3b9 100644 --- a/applications/examples/example_plugins_advanced/application.fam +++ b/applications/examples/example_plugins_advanced/application.fam @@ -5,6 +5,7 @@ App( entry_point="example_advanced_plugins_app", stack_size=2 * 1024, fap_category="Examples", + sources=["*.c*", "!plugin*.c"], ) App( diff --git a/applications/external/wiiec/wii_i2c.c b/applications/external/wiiec/wii_i2c.c index f5d6840d9..6fa27d007 100644 --- a/applications/external/wiiec/wii_i2c.c +++ b/applications/external/wiiec/wii_i2c.c @@ -170,7 +170,7 @@ bool ecInit(wiiEC_t* pec, const uint8_t* encKey) { #if 0 //! i2c workaround // May become relevant when the i2c issues are resolved // Take control of the i2c bus [which returns void !?] - // --> firmware/targets/f7/furi_hal/furi_hal_i2c.c + // --> targets/f7/furi_hal/furi_hal_i2c.c furi_hal_i2c_acquire(i2cBus); #endif diff --git a/applications/external/wiiec/wii_i2c.h b/applications/external/wiiec/wii_i2c.h index efebefcf9..d0071188c 100644 --- a/applications/external/wiiec/wii_i2c.h +++ b/applications/external/wiiec/wii_i2c.h @@ -25,7 +25,7 @@ // When we read: After we send the read command, we wait for i2cReadWait uS before reading the data // -// firmware/targets/f7/furi_hal/furi_hal_i2c_types.h +// targets/f7/furi_hal/furi_hal_i2c_types.h #define i2cBus (&furi_hal_i2c_handle_external) // FZ external i2c bus #define i2cAddr (ec_i2cAddr << 1) #define i2cTimeout (3) // in mS diff --git a/applications/main/bad_kb/application.fam b/applications/main/bad_kb/application.fam index 4591625ec..24c90ce28 100644 --- a/applications/main/bad_kb/application.fam +++ b/applications/main/bad_kb/application.fam @@ -6,6 +6,7 @@ App( stack_size=2 * 1024, icon="A_BadKb_14", order=70, + resources="resources", fap_icon="icon.png", fap_category="Tools", ) diff --git a/assets/resources/badkb/assets/layouts/ba-BA.kl b/applications/main/bad_kb/resources/assets/layouts/ba-BA.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/ba-BA.kl rename to applications/main/bad_kb/resources/assets/layouts/ba-BA.kl diff --git a/assets/resources/badkb/assets/layouts/cz_CS.kl b/applications/main/bad_kb/resources/assets/layouts/cz_CS.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/cz_CS.kl rename to applications/main/bad_kb/resources/assets/layouts/cz_CS.kl diff --git a/assets/resources/badkb/assets/layouts/da-DA.kl b/applications/main/bad_kb/resources/assets/layouts/da-DA.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/da-DA.kl rename to applications/main/bad_kb/resources/assets/layouts/da-DA.kl diff --git a/assets/resources/badkb/assets/layouts/de-CH.kl b/applications/main/bad_kb/resources/assets/layouts/de-CH.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/de-CH.kl rename to applications/main/bad_kb/resources/assets/layouts/de-CH.kl diff --git a/assets/resources/badkb/assets/layouts/de-DE.kl b/applications/main/bad_kb/resources/assets/layouts/de-DE.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/de-DE.kl rename to applications/main/bad_kb/resources/assets/layouts/de-DE.kl diff --git a/assets/resources/badkb/assets/layouts/dvorak.kl b/applications/main/bad_kb/resources/assets/layouts/dvorak.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/dvorak.kl rename to applications/main/bad_kb/resources/assets/layouts/dvorak.kl diff --git a/assets/resources/badkb/assets/layouts/en-UK.kl b/applications/main/bad_kb/resources/assets/layouts/en-UK.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/en-UK.kl rename to applications/main/bad_kb/resources/assets/layouts/en-UK.kl diff --git a/assets/resources/badkb/assets/layouts/en-US.kl b/applications/main/bad_kb/resources/assets/layouts/en-US.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/en-US.kl rename to applications/main/bad_kb/resources/assets/layouts/en-US.kl diff --git a/assets/resources/badkb/assets/layouts/es-ES.kl b/applications/main/bad_kb/resources/assets/layouts/es-ES.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/es-ES.kl rename to applications/main/bad_kb/resources/assets/layouts/es-ES.kl diff --git a/assets/resources/badkb/assets/layouts/fr-BE.kl b/applications/main/bad_kb/resources/assets/layouts/fr-BE.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/fr-BE.kl rename to applications/main/bad_kb/resources/assets/layouts/fr-BE.kl diff --git a/assets/resources/badkb/assets/layouts/fr-CA.kl b/applications/main/bad_kb/resources/assets/layouts/fr-CA.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/fr-CA.kl rename to applications/main/bad_kb/resources/assets/layouts/fr-CA.kl diff --git a/assets/resources/badkb/assets/layouts/fr-CH.kl b/applications/main/bad_kb/resources/assets/layouts/fr-CH.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/fr-CH.kl rename to applications/main/bad_kb/resources/assets/layouts/fr-CH.kl diff --git a/assets/resources/badkb/assets/layouts/fr-FR-mac.kl b/applications/main/bad_kb/resources/assets/layouts/fr-FR-mac.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/fr-FR-mac.kl rename to applications/main/bad_kb/resources/assets/layouts/fr-FR-mac.kl diff --git a/assets/resources/badkb/assets/layouts/fr-FR.kl b/applications/main/bad_kb/resources/assets/layouts/fr-FR.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/fr-FR.kl rename to applications/main/bad_kb/resources/assets/layouts/fr-FR.kl diff --git a/assets/resources/badkb/assets/layouts/hr-HR.kl b/applications/main/bad_kb/resources/assets/layouts/hr-HR.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/hr-HR.kl rename to applications/main/bad_kb/resources/assets/layouts/hr-HR.kl diff --git a/assets/resources/badkb/assets/layouts/hu-HU.kl b/applications/main/bad_kb/resources/assets/layouts/hu-HU.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/hu-HU.kl rename to applications/main/bad_kb/resources/assets/layouts/hu-HU.kl diff --git a/assets/resources/badkb/assets/layouts/it-IT.kl b/applications/main/bad_kb/resources/assets/layouts/it-IT.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/it-IT.kl rename to applications/main/bad_kb/resources/assets/layouts/it-IT.kl diff --git a/assets/resources/badkb/assets/layouts/nb-NO.kl b/applications/main/bad_kb/resources/assets/layouts/nb-NO.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/nb-NO.kl rename to applications/main/bad_kb/resources/assets/layouts/nb-NO.kl diff --git a/assets/resources/badkb/assets/layouts/nl-NL.kl b/applications/main/bad_kb/resources/assets/layouts/nl-NL.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/nl-NL.kl rename to applications/main/bad_kb/resources/assets/layouts/nl-NL.kl diff --git a/assets/resources/badkb/assets/layouts/pt-BR.kl b/applications/main/bad_kb/resources/assets/layouts/pt-BR.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/pt-BR.kl rename to applications/main/bad_kb/resources/assets/layouts/pt-BR.kl diff --git a/assets/resources/badkb/assets/layouts/pt-PT.kl b/applications/main/bad_kb/resources/assets/layouts/pt-PT.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/pt-PT.kl rename to applications/main/bad_kb/resources/assets/layouts/pt-PT.kl diff --git a/assets/resources/badkb/assets/layouts/si-SI.kl b/applications/main/bad_kb/resources/assets/layouts/si-SI.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/si-SI.kl rename to applications/main/bad_kb/resources/assets/layouts/si-SI.kl diff --git a/assets/resources/badkb/assets/layouts/sk-SK.kl b/applications/main/bad_kb/resources/assets/layouts/sk-SK.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/sk-SK.kl rename to applications/main/bad_kb/resources/assets/layouts/sk-SK.kl diff --git a/assets/resources/badkb/assets/layouts/sv-SE.kl b/applications/main/bad_kb/resources/assets/layouts/sv-SE.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/sv-SE.kl rename to applications/main/bad_kb/resources/assets/layouts/sv-SE.kl diff --git a/assets/resources/badkb/assets/layouts/tr-TR.kl b/applications/main/bad_kb/resources/assets/layouts/tr-TR.kl similarity index 100% rename from assets/resources/badkb/assets/layouts/tr-TR.kl rename to applications/main/bad_kb/resources/assets/layouts/tr-TR.kl diff --git a/assets/resources/badkb/demo_android.txt b/applications/main/bad_kb/resources/demo_android.txt similarity index 100% rename from assets/resources/badkb/demo_android.txt rename to applications/main/bad_kb/resources/demo_android.txt diff --git a/assets/resources/badkb/demo_ios.txt b/applications/main/bad_kb/resources/demo_ios.txt similarity index 100% rename from assets/resources/badkb/demo_ios.txt rename to applications/main/bad_kb/resources/demo_ios.txt diff --git a/assets/resources/badkb/demo_macos.txt b/applications/main/bad_kb/resources/demo_macos.txt similarity index 100% rename from assets/resources/badkb/demo_macos.txt rename to applications/main/bad_kb/resources/demo_macos.txt diff --git a/assets/resources/badkb/demo_windows.txt b/applications/main/bad_kb/resources/demo_windows.txt similarity index 100% rename from assets/resources/badkb/demo_windows.txt rename to applications/main/bad_kb/resources/demo_windows.txt diff --git a/applications/main/ibutton/application.fam b/applications/main/ibutton/application.fam index 5df50fcf2..4f57148f8 100644 --- a/applications/main/ibutton/application.fam +++ b/applications/main/ibutton/application.fam @@ -16,5 +16,6 @@ App( apptype=FlipperAppType.STARTUP, targets=["f7"], entry_point="ibutton_on_system_start", + sources=["ibutton_cli.c"], order=60, ) diff --git a/applications/main/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c index 3075d3acd..6658d7670 100644 --- a/applications/main/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -40,23 +40,23 @@ static void ibutton_make_app_folder(iButton* ibutton) { furi_record_close(RECORD_STORAGE); } -// Callback function for handling RPC commands -static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context) { +static void ibutton_rpc_command_callback(const RpcAppSystemEvent* event, void* context) { furi_assert(context); iButton* ibutton = context; - if(event == RpcAppEventSessionClose) { - // Send a custom event and detach from RPC on session close, load, and exit + if(event->type == RpcAppEventTypeSessionClose) { view_dispatcher_send_custom_event( ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose); rpc_system_app_set_callback(ibutton->rpc, NULL, NULL); ibutton->rpc = NULL; - } else if(event == RpcAppEventAppExit) { + } else if(event->type == RpcAppEventTypeAppExit) { view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit); - } else if(event == RpcAppEventLoadFile) { - view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoad); + } else if(event->type == RpcAppEventTypeLoadFile) { + furi_assert(event->data.type == RpcAppSystemEventDataTypeString); + furi_string_set(ibutton->file_path, event->data.string); + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoadFile); } else { - rpc_system_app_confirm(ibutton->rpc, event, false); + rpc_system_app_confirm(ibutton->rpc, false); } } @@ -79,7 +79,6 @@ void ibutton_tick_event_callback(void* context) { scene_manager_handle_tick_event(ibutton->scene_manager); } -// Allocate memory and initialize the iButton structure iButton* ibutton_alloc() { iButton* ibutton = malloc(sizeof(iButton)); @@ -137,7 +136,6 @@ iButton* ibutton_alloc() { void ibutton_free(iButton* ibutton) { furi_assert(ibutton); - // Remove and free views, then free the view dispatcher and scene manager view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewLoading); loading_free(ibutton->loading); @@ -159,7 +157,6 @@ void ibutton_free(iButton* ibutton) { view_dispatcher_free(ibutton->view_dispatcher); scene_manager_free(ibutton->scene_manager); - // Close records and free worker and key furi_record_close(RECORD_NOTIFICATION); ibutton->notifications = NULL; @@ -182,7 +179,6 @@ void ibutton_free(iButton* ibutton) { bool ibutton_load_key(iButton* ibutton) { view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewLoading); - // Attempt to load the key using protocols const bool success = ibutton_protocols_load( ibutton->protocols, ibutton->key, furi_string_get_cstr(ibutton->file_path)); @@ -190,7 +186,6 @@ bool ibutton_load_key(iButton* ibutton) { dialog_message_show_storage_error(ibutton->dialogs, "Cannot load\nkey file"); } else { - // Extract and store the key name FuriString* tmp = furi_string_alloc(); path_extract_filename(ibutton->file_path, tmp, true); @@ -202,7 +197,6 @@ bool ibutton_load_key(iButton* ibutton) { return success; } -// Select and load a key for iButton using the file browser bool ibutton_select_and_load_key(iButton* ibutton) { DialogsFileBrowserOptions browser_options; bool success = false; @@ -263,7 +257,6 @@ void ibutton_notification_message(iButton* ibutton, uint32_t message) { notification_message(ibutton->notifications, ibutton_notification_sequences[message]); } -// Callback functions for submenu and widget actions void ibutton_submenu_callback(void* context, uint32_t index) { iButton* ibutton = context; view_dispatcher_send_custom_event(ibutton->view_dispatcher, index); @@ -288,12 +281,10 @@ int32_t ibutton_app(char* arg) { if(sscanf(arg, "RPC %lX", (uint32_t*)&ibutton->rpc) == 1) { FURI_LOG_D(TAG, "Running in RPC mode"); - // Attach to RPC and handle RPC events rpc_system_app_set_callback(ibutton->rpc, ibutton_rpc_command_callback, ibutton); rpc_system_app_send_started(ibutton->rpc); } else { - // Set the file_path and attempt to load the key furi_string_set(ibutton->file_path, (const char*)arg); key_loaded = ibutton_load_key(ibutton); } @@ -306,7 +297,6 @@ int32_t ibutton_app(char* arg) { dolphin_deed(DolphinDeedIbuttonEmulate); } else { - // Attach to GUI (fullscreen) and set the initial scene based on key loading view_dispatcher_attach_to_gui( ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen); if(key_loaded) { //-V547 @@ -324,7 +314,6 @@ int32_t ibutton_app(char* arg) { } if(ibutton->rpc) { - // Detach from RPC and handle RPC exit rpc_system_app_set_callback(ibutton->rpc, NULL, NULL); rpc_system_app_send_exited(ibutton->rpc); } diff --git a/applications/main/ibutton/ibutton_custom_event.h b/applications/main/ibutton/ibutton_custom_event.h index 28bcb94a0..b0246d310 100644 --- a/applications/main/ibutton/ibutton_custom_event.h +++ b/applications/main/ibutton/ibutton_custom_event.h @@ -1,6 +1,6 @@ #pragma once -enum iButtonCustomEvent { +typedef enum { // Reserve first 100 events for button types and indexes, starting from 0 iButtonCustomEventReserved = 100, @@ -10,8 +10,12 @@ enum iButtonCustomEvent { iButtonCustomEventByteEditResult, iButtonCustomEventWorkerEmulated, iButtonCustomEventWorkerRead, + iButtonCustomEventWorkerWriteOK, + iButtonCustomEventWorkerWriteSameKey, + iButtonCustomEventWorkerWriteNoDetect, + iButtonCustomEventWorkerWriteCannotWrite, - iButtonCustomEventRpcLoad, + iButtonCustomEventRpcLoadFile, iButtonCustomEventRpcExit, iButtonCustomEventRpcSessionClose, -}; +} iButtonCustomEvent; diff --git a/applications/main/ibutton/scenes/ibutton_scene_rpc.c b/applications/main/ibutton/scenes/ibutton_scene_rpc.c index 9205eb4b4..7106fefaa 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_rpc.c +++ b/applications/main/ibutton/scenes/ibutton_scene_rpc.c @@ -23,28 +23,23 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; - if(event.event == iButtonCustomEventRpcLoad) { + if(event.event == iButtonCustomEventRpcLoadFile) { bool result = false; - const char* file_path = rpc_system_app_get_data(ibutton->rpc); - if(file_path && (furi_string_empty(ibutton->file_path))) { - furi_string_set(ibutton->file_path, file_path); + if(ibutton_load_key(ibutton)) { + popup_set_text(popup, ibutton->key_name, 82, 32, AlignCenter, AlignTop); + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); - if(ibutton_load_key(ibutton)) { - popup_set_text(popup, ibutton->key_name, 82, 32, AlignCenter, AlignTop); - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); + ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); + ibutton_worker_emulate_start(ibutton->worker, ibutton->key); - ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); - ibutton_worker_emulate_start(ibutton->worker, ibutton->key); - - result = true; - } + result = true; } - rpc_system_app_confirm(ibutton->rpc, RpcAppEventLoadFile, result); + rpc_system_app_confirm(ibutton->rpc, result); } else if(event.event == iButtonCustomEventRpcExit) { - rpc_system_app_confirm(ibutton->rpc, RpcAppEventAppExit, true); + rpc_system_app_confirm(ibutton->rpc, true); scene_manager_stop(ibutton->scene_manager); view_dispatcher_stop(ibutton->view_dispatcher); diff --git a/applications/main/ibutton/scenes/ibutton_scene_write.c b/applications/main/ibutton/scenes/ibutton_scene_write.c index 541aa1c52..63be63506 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_write.c +++ b/applications/main/ibutton/scenes/ibutton_scene_write.c @@ -5,9 +5,26 @@ typedef enum { iButtonSceneWriteStateBlinkYellow, } iButtonSceneWriteState; +static inline iButtonCustomEvent + ibutton_scene_write_to_custom_event(iButtonWorkerWriteResult result) { + switch(result) { + case iButtonWorkerWriteOK: + return iButtonCustomEventWorkerWriteOK; + case iButtonWorkerWriteSameKey: + return iButtonCustomEventWorkerWriteSameKey; + case iButtonWorkerWriteNoDetect: + return iButtonCustomEventWorkerWriteNoDetect; + case iButtonWorkerWriteCannotWrite: + return iButtonCustomEventWorkerWriteCannotWrite; + default: + furi_crash(); + } +} + static void ibutton_scene_write_callback(void* context, iButtonWorkerWriteResult result) { iButton* ibutton = context; - view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); + view_dispatcher_send_custom_event( + ibutton->view_dispatcher, ibutton_scene_write_to_custom_event(result)); } void ibutton_scene_write_on_enter(void* context) { @@ -61,16 +78,14 @@ bool ibutton_scene_write_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; - if((event.event == iButtonWorkerWriteOK) || (event.event == iButtonWorkerWriteSameKey)) { + if((event.event == iButtonCustomEventWorkerWriteOK) || + (event.event == iButtonCustomEventWorkerWriteSameKey)) { scene_manager_next_scene(scene_manager, iButtonSceneWriteSuccess); - } else if(event.event == iButtonWorkerWriteNoDetect) { + } else if(event.event == iButtonCustomEventWorkerWriteNoDetect) { ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateBlink); - } else if(event.event == iButtonWorkerWriteCannotWrite) { + } else if(event.event == iButtonCustomEventWorkerWriteCannotWrite) { ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink); } - - } else if(event.type == SceneManagerEventTypeTick) { - consumed = true; } return consumed; diff --git a/applications/main/infrared/application.fam b/applications/main/infrared/application.fam index d669e4298..57e3f9ce6 100644 --- a/applications/main/infrared/application.fam +++ b/applications/main/infrared/application.fam @@ -7,6 +7,8 @@ App( icon="A_Infrared_14", stack_size=3 * 1024, order=40, + sources=["*.c", "!infrared_cli.c"], + resources="resources", fap_icon="icon.png", fap_category="Infrared", ) @@ -16,5 +18,10 @@ App( apptype=FlipperAppType.STARTUP, targets=["f7"], entry_point="infrared_on_system_start", + sources=[ + "infrared_cli.c", + "infrared_brute_force.c", + "infrared_signal.c", + ], order=20, ) diff --git a/applications/main/infrared/infrared.h b/applications/main/infrared/infrared.h deleted file mode 100644 index e5eeb1177..000000000 --- a/applications/main/infrared/infrared.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -typedef struct Infrared Infrared; diff --git a/applications/main/infrared/infrared.c b/applications/main/infrared/infrared_app.c similarity index 68% rename from applications/main/infrared/infrared.c rename to applications/main/infrared/infrared_app.c index f7f4779ca..368be8777 100644 --- a/applications/main/infrared/infrared.c +++ b/applications/main/infrared/infrared_app.c @@ -1,69 +1,85 @@ -#include "infrared_i.h" +#include "infrared_app_i.h" #include +#include #include +#define TAG "InfraredApp" + #define INFRARED_TX_MIN_INTERVAL_MS 50U -static const NotificationSequence* infrared_notification_sequences[] = { - &sequence_success, - &sequence_set_only_green_255, - &sequence_reset_green, - &sequence_solid_yellow, - &sequence_reset_rgb, - &sequence_blink_start_cyan, - &sequence_blink_start_magenta, - &sequence_blink_stop, +static const NotificationSequence* + infrared_notification_sequences[InfraredNotificationMessageCount] = { + &sequence_success, + &sequence_set_only_green_255, + &sequence_reset_green, + &sequence_solid_yellow, + &sequence_reset_rgb, + &sequence_blink_start_cyan, + &sequence_blink_start_magenta, + &sequence_blink_stop, }; -static void infrared_make_app_folder(Infrared* infrared) { +static void infrared_make_app_folder(InfraredApp* infrared) { if(!storage_simply_mkdir(infrared->storage, INFRARED_APP_FOLDER)) { - dialog_message_show_storage_error(infrared->dialogs, "Cannot create\napp folder"); + infrared_show_error_message(infrared, "Cannot create\napp folder"); } } static bool infrared_custom_event_callback(void* context, uint32_t event) { furi_assert(context); - Infrared* infrared = context; + InfraredApp* infrared = context; return scene_manager_handle_custom_event(infrared->scene_manager, event); } static bool infrared_back_event_callback(void* context) { furi_assert(context); - Infrared* infrared = context; + InfraredApp* infrared = context; return scene_manager_handle_back_event(infrared->scene_manager); } static void infrared_tick_event_callback(void* context) { furi_assert(context); - Infrared* infrared = context; + InfraredApp* infrared = context; scene_manager_handle_tick_event(infrared->scene_manager); } -static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context) { +static void infrared_rpc_command_callback(const RpcAppSystemEvent* event, void* context) { furi_assert(context); - Infrared* infrared = context; + InfraredApp* infrared = context; furi_assert(infrared->rpc_ctx); - if(event == RpcAppEventSessionClose) { + if(event->type == RpcAppEventTypeSessionClose) { 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) { + } else if(event->type == RpcAppEventTypeAppExit) { view_dispatcher_send_custom_event( infrared->view_dispatcher, InfraredCustomEventTypeRpcExit); - } else if(event == RpcAppEventLoadFile) { + } else if(event->type == RpcAppEventTypeLoadFile) { + furi_assert(event->data.type == RpcAppSystemEventDataTypeString); + furi_string_set(infrared->file_path, event->data.string); view_dispatcher_send_custom_event( - infrared->view_dispatcher, InfraredCustomEventTypeRpcLoad); - } else if(event == RpcAppEventButtonPress) { - view_dispatcher_send_custom_event( - infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPress); - } else if(event == RpcAppEventButtonRelease) { + infrared->view_dispatcher, InfraredCustomEventTypeRpcLoadFile); + } else if(event->type == RpcAppEventTypeButtonPress) { + furi_assert( + event->data.type == RpcAppSystemEventDataTypeString || + event->data.type == RpcAppSystemEventDataTypeInt32); + if(event->data.type == RpcAppSystemEventDataTypeString) { + furi_string_set(infrared->button_name, event->data.string); + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPressName); + } else { + infrared->app_state.current_button_index = event->data.i32; + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPressIndex); + } + } else if(event->type == RpcAppEventTypeButtonRelease) { view_dispatcher_send_custom_event( infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonRelease); } else { - rpc_system_app_confirm(infrared->rpc_ctx, event, false); + rpc_system_app_confirm(infrared->rpc_ctx, false); } } @@ -109,10 +125,11 @@ static void infrared_find_vacant_remote_name(FuriString* name, const char* path) furi_record_close(RECORD_STORAGE); } -static Infrared* infrared_alloc() { - Infrared* infrared = malloc(sizeof(Infrared)); +static InfraredApp* infrared_alloc() { + InfraredApp* infrared = malloc(sizeof(InfraredApp)); infrared->file_path = furi_string_alloc(); + infrared->button_name = furi_string_alloc(); InfraredAppState* app_state = &infrared->app_state; app_state->is_learning_new_remote = false; @@ -139,7 +156,7 @@ static Infrared* infrared_alloc() { infrared->worker = infrared_worker_alloc(); infrared->remote = infrared_remote_alloc(); - infrared->received_signal = infrared_signal_alloc(); + infrared->current_signal = infrared_signal_alloc(); infrared->brute_force = infrared_brute_force_alloc(); infrared->submenu = submenu_alloc(); @@ -190,7 +207,7 @@ static Infrared* infrared_alloc() { return infrared; } -static void infrared_free(Infrared* infrared) { +static void infrared_free(InfraredApp* infrared) { furi_assert(infrared); ViewDispatcher* view_dispatcher = infrared->view_dispatcher; InfraredAppState* app_state = &infrared->app_state; @@ -238,7 +255,7 @@ static void infrared_free(Infrared* infrared) { scene_manager_free(infrared->scene_manager); infrared_brute_force_free(infrared->brute_force); - infrared_signal_free(infrared->received_signal); + infrared_signal_free(infrared->current_signal); infrared_remote_free(infrared->remote); infrared_worker_free(infrared->worker); @@ -252,6 +269,7 @@ static void infrared_free(Infrared* infrared) { infrared->gui = NULL; furi_string_free(infrared->file_path); + furi_string_free(infrared->button_name); // Disable 5v power if was enabled for external module if(furi_hal_power_is_otg_enabled()) { @@ -262,65 +280,61 @@ static void infrared_free(Infrared* infrared) { } bool infrared_add_remote_with_button( - Infrared* infrared, + const InfraredApp* infrared, const char* button_name, - InfraredSignal* signal) { + const InfraredSignal* signal) { InfraredRemote* remote = infrared->remote; - FuriString *new_name, *new_path; - new_name = furi_string_alloc_set(INFRARED_DEFAULT_REMOTE_NAME); - new_path = furi_string_alloc_set(INFRARED_APP_FOLDER); + FuriString* new_name = furi_string_alloc_set(INFRARED_DEFAULT_REMOTE_NAME); + FuriString* new_path = furi_string_alloc_set(INFRARED_APP_FOLDER); infrared_find_vacant_remote_name(new_name, furi_string_get_cstr(new_path)); furi_string_cat_printf( new_path, "/%s%s", furi_string_get_cstr(new_name), INFRARED_APP_EXTENSION); - infrared_remote_reset(remote); - infrared_remote_set_name(remote, furi_string_get_cstr(new_name)); - infrared_remote_set_path(remote, furi_string_get_cstr(new_path)); + bool success = false; + + do { + if(!infrared_remote_create(remote, furi_string_get_cstr(new_path))) break; + if(!infrared_remote_append_signal(remote, signal, button_name)) break; + success = true; + } while(false); furi_string_free(new_name); furi_string_free(new_path); - return infrared_remote_add_button(remote, button_name, signal); + + return success; } -bool infrared_rename_current_remote(Infrared* infrared, const char* name) { +bool infrared_rename_current_remote(const InfraredApp* infrared, const char* new_name) { InfraredRemote* remote = infrared->remote; - const char* remote_path = infrared_remote_get_path(remote); + const char* old_path = infrared_remote_get_path(remote); - if(!strcmp(infrared_remote_get_name(remote), name)) { + if(!strcmp(infrared_remote_get_name(remote), new_name)) { return true; } - FuriString* new_name; - new_name = furi_string_alloc_set(name); + FuriString* new_name_fstr = furi_string_alloc_set(new_name); + FuriString* new_path_fstr = furi_string_alloc_set(old_path); - infrared_find_vacant_remote_name(new_name, remote_path); + infrared_find_vacant_remote_name(new_name_fstr, old_path); - FuriString* new_path; - new_path = furi_string_alloc_set(infrared_remote_get_path(remote)); - if(furi_string_end_with(new_path, INFRARED_APP_EXTENSION)) { - size_t filename_start = furi_string_search_rchar(new_path, '/'); - furi_string_left(new_path, filename_start); + if(furi_string_end_with(new_path_fstr, INFRARED_APP_EXTENSION)) { + path_extract_dirname(old_path, new_path_fstr); } - furi_string_cat_printf( - new_path, "/%s%s", furi_string_get_cstr(new_name), INFRARED_APP_EXTENSION); - Storage* storage = furi_record_open(RECORD_STORAGE); + path_append(new_path_fstr, furi_string_get_cstr(new_name_fstr)); + furi_string_cat(new_path_fstr, INFRARED_APP_EXTENSION); - FS_Error status = storage_common_rename( - storage, infrared_remote_get_path(remote), furi_string_get_cstr(new_path)); - infrared_remote_set_name(remote, furi_string_get_cstr(new_name)); - infrared_remote_set_path(remote, furi_string_get_cstr(new_path)); + const bool success = infrared_remote_rename(remote, furi_string_get_cstr(new_path_fstr)); - furi_string_free(new_name); - furi_string_free(new_path); + furi_string_free(new_name_fstr); + furi_string_free(new_path_fstr); - furi_record_close(RECORD_STORAGE); - return status == FSE_OK; + return success; } -void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { +void infrared_tx_start(InfraredApp* infrared) { if(infrared->app_state.is_transmitting) { return; } @@ -331,12 +345,12 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { return; } - if(infrared_signal_is_raw(signal)) { - InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + if(infrared_signal_is_raw(infrared->current_signal)) { + const InfraredRawSignal* raw = infrared_signal_get_raw_signal(infrared->current_signal); infrared_worker_set_raw_signal( infrared->worker, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle); } else { - InfraredMessage* message = infrared_signal_get_message(signal); + const InfraredMessage* message = infrared_signal_get_message(infrared->current_signal); infrared_worker_set_decoded_signal(infrared->worker, message); } @@ -350,20 +364,20 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { infrared->app_state.is_transmitting = true; } -void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) { - furi_assert(button_index < infrared_remote_get_button_count(infrared->remote)); +void infrared_tx_start_button_index(InfraredApp* infrared, size_t button_index) { + furi_assert(button_index < infrared_remote_get_signal_count(infrared->remote)); - InfraredRemoteButton* button = infrared_remote_get_button(infrared->remote, button_index); - InfraredSignal* signal = infrared_remote_button_get_signal(button); - - infrared_tx_start_signal(infrared, signal); + if(infrared_remote_load_signal(infrared->remote, infrared->current_signal, button_index)) { + infrared_tx_start(infrared); + } else { + infrared_show_error_message( + infrared, + "Failed to load\n\"%s\"", + infrared_remote_get_signal_name(infrared->remote, button_index)); + } } -void infrared_tx_start_received(Infrared* infrared) { - infrared_tx_start_signal(infrared, infrared->received_signal); -} - -void infrared_tx_stop(Infrared* infrared) { +void infrared_tx_stop(InfraredApp* infrared) { if(!infrared->app_state.is_transmitting) { return; } @@ -377,53 +391,65 @@ void infrared_tx_stop(Infrared* infrared) { infrared->app_state.last_transmit_time = furi_get_tick(); } -void infrared_text_store_set(Infrared* infrared, uint32_t bank, const char* text, ...) { +void infrared_text_store_set(InfraredApp* infrared, uint32_t bank, const char* fmt, ...) { va_list args; - va_start(args, text); + va_start(args, fmt); - vsnprintf(infrared->text_store[bank], INFRARED_TEXT_STORE_SIZE, text, args); + vsnprintf(infrared->text_store[bank], INFRARED_TEXT_STORE_SIZE, fmt, args); va_end(args); } -void infrared_text_store_clear(Infrared* infrared, uint32_t bank) { +void infrared_text_store_clear(InfraredApp* infrared, uint32_t bank) { memset(infrared->text_store[bank], 0, INFRARED_TEXT_STORE_SIZE + 1); } -void infrared_play_notification_message(Infrared* infrared, uint32_t message) { - furi_assert(message < sizeof(infrared_notification_sequences) / sizeof(NotificationSequence*)); +void infrared_play_notification_message( + const InfraredApp* infrared, + InfraredNotificationMessage message) { + furi_assert(message < InfraredNotificationMessageCount); notification_message(infrared->notifications, infrared_notification_sequences[message]); } -void infrared_show_loading_popup(Infrared* infrared, bool show) { - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); +void infrared_show_loading_popup(const InfraredApp* infrared, bool show) { ViewStack* view_stack = infrared->view_stack; Loading* loading = infrared->loading; if(show) { // Raise timer priority so that animations can play - vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); + furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated); view_stack_add_view(view_stack, loading_get_view(loading)); } else { view_stack_remove_view(view_stack, loading_get_view(loading)); // Restore default timer priority - vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); + furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal); } } +void infrared_show_error_message(const InfraredApp* infrared, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + + FuriString* message = furi_string_alloc_vprintf(fmt, args); + dialog_message_show_storage_error(infrared->dialogs, furi_string_get_cstr(message)); + + furi_string_free(message); + va_end(args); +} + void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal) { furi_assert(context); - Infrared* infrared = context; + InfraredApp* infrared = context; if(infrared_worker_signal_is_decoded(received_signal)) { infrared_signal_set_message( - infrared->received_signal, infrared_worker_get_decoded_signal(received_signal)); + infrared->current_signal, infrared_worker_get_decoded_signal(received_signal)); } else { const uint32_t* timings; size_t timings_size; infrared_worker_get_raw_signal(received_signal, &timings, &timings_size); infrared_signal_set_raw_signal( - infrared->received_signal, + infrared->current_signal, timings, timings_size, INFRARED_COMMON_CARRIER_FREQUENCY, @@ -436,20 +462,20 @@ void infrared_signal_received_callback(void* context, InfraredWorkerSignal* rece void infrared_text_input_callback(void* context) { furi_assert(context); - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event( infrared->view_dispatcher, InfraredCustomEventTypeTextEditDone); } void infrared_popup_closed_callback(void* context) { furi_assert(context); - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event( infrared->view_dispatcher, InfraredCustomEventTypePopupClosed); } int32_t infrared_app(char* p) { - Infrared* infrared = infrared_alloc(); + InfraredApp* infrared = infrared_alloc(); infrared_make_app_folder(infrared); @@ -465,13 +491,15 @@ int32_t infrared_app(char* p) { rpc_system_app_send_started(infrared->rpc_ctx); is_rpc_mode = true; } else { - furi_string_set(infrared->file_path, (const char*)p); - is_remote_loaded = infrared_remote_load(infrared->remote, infrared->file_path); + const char* file_path = (const char*)p; + is_remote_loaded = infrared_remote_load(infrared->remote, file_path); + if(!is_remote_loaded) { - dialog_message_show_storage_error( - infrared->dialogs, "Failed to load\nselected remote"); + infrared_show_error_message(infrared, "Failed to load\n\"%s\"", file_path); return -1; } + + furi_string_set(infrared->file_path, file_path); } } diff --git a/applications/main/infrared/infrared_app.h b/applications/main/infrared/infrared_app.h new file mode 100644 index 000000000..a6f87402a --- /dev/null +++ b/applications/main/infrared/infrared_app.h @@ -0,0 +1,15 @@ +/** + * @file infrared_app.h + * @brief Infrared application - start here. + * + * @see infrared_app_i.h for the main application data structure and functions. + * @see infrared_signal.h for the infrared signal library - loading, storing and transmitting signals. + * @see infrared_remote.hl for the infrared remote library - loading, storing and manipulating remotes. + * @see infrared_brute_force.h for the infrared brute force - loading and transmitting multiple signals. + */ +#pragma once + +/** + * @brief InfraredApp opaque type declaration. + */ +typedef struct InfraredApp InfraredApp; diff --git a/applications/main/infrared/infrared_app_i.h b/applications/main/infrared/infrared_app_i.h new file mode 100644 index 000000000..c35d3fa41 --- /dev/null +++ b/applications/main/infrared/infrared_app_i.h @@ -0,0 +1,289 @@ +/** + * @file infrared_app_i.h + * @brief Main Infrared application types and functions. + */ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include "infrared_app.h" +#include "infrared_remote.h" +#include "infrared_brute_force.h" +#include "infrared_custom_event.h" + +#include "scenes/infrared_scene.h" +#include "views/infrared_progress_view.h" +#include "views/infrared_debug_view.h" +#include "views/infrared_move_view.h" + +#include "rpc/rpc_app.h" + +#define INFRARED_FILE_NAME_SIZE 100 +#define INFRARED_TEXT_STORE_NUM 2 +#define INFRARED_TEXT_STORE_SIZE 128 + +#define INFRARED_MAX_BUTTON_NAME_LENGTH 22 +#define INFRARED_MAX_REMOTE_NAME_LENGTH 22 + +#define INFRARED_APP_FOLDER ANY_PATH("infrared") +#define INFRARED_APP_EXTENSION ".ir" + +#define INFRARED_DEFAULT_REMOTE_NAME "Remote" +#define INFRARED_LOG_TAG "InfraredApp" + +/** + * @brief Enumeration of invalid remote button indices. + */ +typedef enum { + InfraredButtonIndexNone = -1, /**< No button is currently selected. */ +} InfraredButtonIndex; + +/** + * @brief Enumeration of editing targets. + */ +typedef enum { + InfraredEditTargetNone, /**< No editing target is selected. */ + InfraredEditTargetRemote, /**< Whole remote is selected as editing target. */ + InfraredEditTargetButton, /**< Single button is selected as editing target. */ +} InfraredEditTarget; + +/** + * @brief Enumeration of editing modes. + */ +typedef enum { + InfraredEditModeNone, /**< No editing mode is selected. */ + InfraredEditModeRename, /**< Rename mode is selected. */ + InfraredEditModeDelete, /**< Delete mode is selected. */ +} InfraredEditMode; + +/** + * @brief Infrared application state type. + */ +typedef struct { + bool is_learning_new_remote; /**< Learning new remote or adding to an existing one. */ + bool is_debug_enabled; /**< Whether to enable or disable debugging features. */ + bool is_transmitting; /**< Whether a signal is currently being transmitted. */ + InfraredEditTarget edit_target : 8; /**< Selected editing target (a remote or a button). */ + InfraredEditMode edit_mode : 8; /**< Selected editing operation (rename or delete). */ + int32_t current_button_index; /**< Selected button index (move destination). */ + int32_t prev_button_index; /**< Previous button index (move source). */ + uint32_t last_transmit_time; /**< Lat time a signal was transmitted. */ +} InfraredAppState; + +/** + * @brief Infrared application type. + */ +struct InfraredApp { + SceneManager* scene_manager; /**< Pointer to a SceneManager instance. */ + ViewDispatcher* view_dispatcher; /**< Pointer to a ViewDispatcher instance. */ + + Gui* gui; /**< Pointer to a Gui instance. */ + Storage* storage; /**< Pointer to a Storage instance. */ + DialogsApp* dialogs; /**< Pointer to a DialogsApp instance. */ + NotificationApp* notifications; /**< Pointer to a NotificationApp instance. */ + InfraredWorker* worker; /**< Used to send or receive signals. */ + InfraredRemote* remote; /**< Holds the currently loaded remote. */ + InfraredSignal* current_signal; /**< Holds the currently loaded signal. */ + InfraredBruteForce* brute_force; /**< Used for the Universal Remote feature. */ + + Submenu* submenu; /**< Standard view for displaying application menus. */ + TextInput* text_input; /**< Standard view for receiving user text input. */ + DialogEx* dialog_ex; /**< Standard view for displaying dialogs. */ + ButtonMenu* button_menu; /**< Custom view for interacting with IR remotes. */ + Popup* popup; /**< Standard view for displaying messages. */ + + ViewStack* view_stack; /**< Standard view for displaying stacked interfaces. */ + InfraredDebugView* debug_view; /**< Custom view for displaying debug information. */ + InfraredMoveView* move_view; /**< Custom view for rearranging buttons in a remote. */ + + ButtonPanel* button_panel; /**< Standard view for displaying control panels. */ + Loading* loading; /**< Standard view for informing about long operations. */ + InfraredProgressView* progress; /**< Custom view for showing brute force progress. */ + + FuriString* file_path; /**< Full path to the currently loaded file. */ + FuriString* button_name; /** Name of the button requested in RPC mode. */ + /** Arbitrary text storage for various inputs. */ + char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1]; + InfraredAppState app_state; /**< Application state. */ + + void* rpc_ctx; /**< Pointer to the RPC context object. */ +}; + +/** + * @brief Enumeration of all used view types. + */ +typedef enum { + InfraredViewSubmenu, + InfraredViewTextInput, + InfraredViewDialogEx, + InfraredViewButtonMenu, + InfraredViewPopup, + InfraredViewStack, + InfraredViewDebugView, + InfraredViewMove, +} InfraredView; + +/** + * @brief Enumeration of all notification message types. + */ +typedef enum { + InfraredNotificationMessageSuccess, /**< Play a short happy tune. */ + InfraredNotificationMessageGreenOn, /**< Turn green LED on. */ + InfraredNotificationMessageGreenOff, /**< Turn green LED off. */ + InfraredNotificationMessageYellowOn, /**< Turn yellow LED on. */ + InfraredNotificationMessageYellowOff, /**< Turn yellow LED off. */ + InfraredNotificationMessageBlinkStartRead, /**< Blink the LED to indicate receiver mode. */ + InfraredNotificationMessageBlinkStartSend, /**< Blink the LED to indicate transmitter mode. */ + InfraredNotificationMessageBlinkStop, /**< Stop blinking the LED. */ + InfraredNotificationMessageCount, /**< Special value equal to the message type count. */ +} InfraredNotificationMessage; + +/** + * @brief Add a new remote with a single signal. + * + * The filename will be automatically generated depending on + * the names and number of other files in the infrared data directory. + * + * @param[in] infrared pointer to the application instance. + * @param[in] name pointer to a zero-terminated string containing the signal name. + * @param[in] signal pointer to the signal to be added. + * @return true if the remote was successfully created, false otherwise. + */ +bool infrared_add_remote_with_button( + const InfraredApp* infrared, + const char* name, + const InfraredSignal* signal); + +/** + * @brief Rename the currently loaded remote. + * + * @param[in] infrared pointer to the application instance. + * @param[in] new_name pointer to a zero-terminated string containing the new remote name. + * @return true if the remote was successfully renamed, false otherwise. + */ +bool infrared_rename_current_remote(const InfraredApp* infrared, const char* new_name); + +/** + * @brief Begin transmission of the currently loaded signal. + * + * The signal will be repeated indefinitely until stopped. + * + * @param[in,out] infrared pointer to the application instance. + */ +void infrared_tx_start(InfraredApp* infrared); + +/** + * @brief Load a signal under the given index and begin transmission. + * + * The signal will be repeated indefinitely until stopped. + * + * @param[in,out] infrared pointer to the application instance. + * @param[in] button_index index of the signal to be loaded. + * @returns true if the signal could be loaded, false otherwise. + */ +void infrared_tx_start_button_index(InfraredApp* infrared, size_t button_index); + +/** + * @brief Stop transmission of the currently loaded signal. + * + * @param[in,out] infrared pointer to the application instance. + */ +void infrared_tx_stop(InfraredApp* infrared); + +/** + * @brief Set the internal text store with formatted text. + * + * @param[in,out] infrared pointer to the application instance. + * @param[in] bank index of text store bank (0 or 1). + * @param[in] fmt pointer to a zero-terminated string containing the format text. + * @param[in] ... additional arguments. + */ +void infrared_text_store_set(InfraredApp* infrared, uint32_t bank, const char* fmt, ...) + _ATTRIBUTE((__format__(__printf__, 3, 4))); + +/** + * @brief Clear the internal text store. + * + * @param[in,out] infrared pointer to the application instance. + * @param[in] bank index of text store bank (0 or 1). + */ +void infrared_text_store_clear(InfraredApp* infrared, uint32_t bank); + +/** + * @brief Play a sound and/or blink the LED. + * + * @param[in] infrared pointer to the application instance. + * @param[in] message type of the message to play. + */ +void infrared_play_notification_message( + const InfraredApp* infrared, + InfraredNotificationMessage message); + +/** + * @brief Show a loading pop-up screen. + * + * In order for this to work, a Stack view must be currently active and + * the main view must be added to it. + * + * @param[in] infrared pointer to the application instance. + * @param[in] show whether to show or hide the pop-up. + */ +void infrared_show_loading_popup(const InfraredApp* infrared, bool show); + +/** + * @brief Show a formatted error messsage. + * + * @param[in] infrared pointer to the application instance. + * @param[in] fmt pointer to a zero-terminated string containing the format text. + * @param[in] ... additional arguments. + */ +void infrared_show_error_message(const InfraredApp* infrared, const char* fmt, ...) + _ATTRIBUTE((__format__(__printf__, 2, 3))); + +/** + * @brief Common received signal callback. + * + * Called when the worker has received a complete infrared signal. + * + * @param[in,out] context pointer to the user-specified context object. + * @param[in] received_signal pointer to the received signal. + */ +void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal); + +/** + * @brief Common text input callback. + * + * Called when the input has been accepted by the user. + * + * @param[in,out] context pointer to the user-specified context object. + */ +void infrared_text_input_callback(void* context); + +/** + * @brief Common popup close callback. + * + * Called when the popup has been closed either by the user or after a timeout. + * + * @param[in,out] context pointer to the user-specified context object. + */ +void infrared_popup_closed_callback(void* context); diff --git a/applications/main/infrared/infrared_brute_force.c b/applications/main/infrared/infrared_brute_force.c index 3ca5c409f..373c7270f 100644 --- a/applications/main/infrared/infrared_brute_force.c +++ b/applications/main/infrared/infrared_brute_force.c @@ -111,7 +111,7 @@ bool infrared_brute_force_start( return success; } -bool infrared_brute_force_is_started(InfraredBruteForce* brute_force) { +bool infrared_brute_force_is_started(const InfraredBruteForce* brute_force) { return brute_force->is_started; } @@ -128,8 +128,10 @@ void infrared_brute_force_stop(InfraredBruteForce* brute_force) { bool infrared_brute_force_send_next(InfraredBruteForce* brute_force) { furi_assert(brute_force->is_started); - const bool success = infrared_signal_search_and_read( - brute_force->current_signal, brute_force->ff, brute_force->current_record_name); + const bool success = infrared_signal_search_by_name_and_read( + brute_force->current_signal, + brute_force->ff, + furi_string_get_cstr(brute_force->current_record_name)); if(success) { infrared_signal_transmit(brute_force->current_signal); } diff --git a/applications/main/infrared/infrared_brute_force.h b/applications/main/infrared/infrared_brute_force.h index b6c48e3f6..33677d2ec 100644 --- a/applications/main/infrared/infrared_brute_force.h +++ b/applications/main/infrared/infrared_brute_force.h @@ -1,23 +1,110 @@ +/** + * @file infrared_brute_force.h + * @brief Infrared signal brute-forcing library. + * + * The BruteForce library is used to send large quantities of signals, + * sorted by a category. It is used to implement the Universal Remote + * feature. + */ #pragma once #include #include +/** + * @brief InfraredBruteForce opaque type declaration. + */ typedef struct InfraredBruteForce InfraredBruteForce; +/** + * @brief Create a new InfraredBruteForce instance. + * + * @returns pointer to the created instance. + */ InfraredBruteForce* infrared_brute_force_alloc(); + +/** + * @brief Delete an InfraredBruteForce instance. + * + * @param[in,out] brute_force pointer to the instance to be deleted. + */ void infrared_brute_force_free(InfraredBruteForce* brute_force); + +/** + * @brief Set an InfraredBruteForce instance to use a signal database contained in a file. + * + * @param[in,out] brute_force pointer to the instance to be configured. + * @param[in] db_filename pointer to a zero-terminated string containing a full path to the database file. + */ void infrared_brute_force_set_db_filename(InfraredBruteForce* brute_force, const char* db_filename); + +/** + * @brief Build a signal dictionary from a previously set database file. + * + * This function must be called each time after setting the database via + * a infrared_brute_force_set_db_filename() call. + * + * @param[in,out] brute_force pointer to the instance to be updated. + * @returns true on success, false otherwise. + */ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force); + +/** + * @brief Start transmitting signals from a category stored in an InfraredBruteForce's instance dictionary. + * + * @param[in,out] brute_force pointer to the instance to be started. + * @param[in] index index of the signal category in the dictionary. + * @returns true on success, false otherwise. + */ bool infrared_brute_force_start( InfraredBruteForce* brute_force, uint32_t index, uint32_t* record_count); -bool infrared_brute_force_is_started(InfraredBruteForce* brute_force); + +/** + * @brief Determine whether the transmission was started. + * + * @param[in] brute_force pointer to the instance to be tested. + * @returns true if transmission was started, false otherwise. + */ +bool infrared_brute_force_is_started(const InfraredBruteForce* brute_force); + +/** + * @brief Stop transmitting the signals. + * + * @param[in] brute_force pointer to the instance to be stopped. + */ void infrared_brute_force_stop(InfraredBruteForce* brute_force); + +/** + * @brief Send the next signal from the chosen category. + * + * This function is called repeatedly until no more signals are left + * in the chosen signal category. + * + * @warning Transmission must be started first by calling infrared_brute_force_start() + * before calling this function. + * + * @param[in,out] brute_force pointer to the instance to be used. + * @returns true if the next signal existed and could be transmitted, false otherwise. + */ bool infrared_brute_force_send_next(InfraredBruteForce* brute_force); -void infrared_brute_force_reset(InfraredBruteForce* brute_force); + +/** + * @brief Add a signal category to an InfraredBruteForce instance's dictionary. + * + * @param[in,out] brute_force pointer to the instance to be updated. + * @param[in] index index of the category to be added. + * @param[in] name name of the category to be added. + */ void infrared_brute_force_add_record( InfraredBruteForce* brute_force, uint32_t index, const char* name); + +/** + * @brief Reset an InfraredBruteForce instance. + * + * @param[in,out] brute_force pointer to the instance to be reset. + */ +void infrared_brute_force_reset(InfraredBruteForce* brute_force); diff --git a/applications/main/infrared/infrared_cli.c b/applications/main/infrared/infrared_cli.c index 54b5cabab..c960ffa28 100644 --- a/applications/main/infrared/infrared_cli.c +++ b/applications/main/infrared/infrared_cli.c @@ -202,7 +202,7 @@ static bool } static bool infrared_cli_decode_raw_signal( - InfraredRawSignal* raw_signal, + const InfraredRawSignal* raw_signal, InfraredDecoderHandler* decoder, FlipperFormat* output_file, const char* signal_name) { @@ -274,7 +274,7 @@ static bool infrared_cli_decode_file(FlipperFormat* input_file, FlipperFormat* o continue; } } - InfraredRawSignal* raw_signal = infrared_signal_get_raw_signal(signal); + const InfraredRawSignal* raw_signal = infrared_signal_get_raw_signal(signal); printf( "Raw signal: %s, %zu samples\r\n", furi_string_get_cstr(tmp), diff --git a/applications/main/infrared/infrared_custom_event.h b/applications/main/infrared/infrared_custom_event.h index 09440ddec..30bb0f729 100644 --- a/applications/main/infrared/infrared_custom_event.h +++ b/applications/main/infrared/infrared_custom_event.h @@ -15,9 +15,10 @@ enum InfraredCustomEventType { InfraredCustomEventTypeButtonSelected, InfraredCustomEventTypeBackPressed, - InfraredCustomEventTypeRpcLoad, + InfraredCustomEventTypeRpcLoadFile, InfraredCustomEventTypeRpcExit, - InfraredCustomEventTypeRpcButtonPress, + InfraredCustomEventTypeRpcButtonPressName, + InfraredCustomEventTypeRpcButtonPressIndex, InfraredCustomEventTypeRpcButtonRelease, InfraredCustomEventTypeRpcSessionClose, }; diff --git a/applications/main/infrared/infrared_i.h b/applications/main/infrared/infrared_i.h deleted file mode 100644 index 4e69b886e..000000000 --- a/applications/main/infrared/infrared_i.h +++ /dev/null @@ -1,149 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#include "infrared.h" -#include "infrared_remote.h" -#include "infrared_brute_force.h" -#include "infrared_custom_event.h" - -#include "scenes/infrared_scene.h" -#include "views/infrared_progress_view.h" -#include "views/infrared_debug_view.h" -#include "views/infrared_move_view.h" - -#include "rpc/rpc_app.h" - -#define INFRARED_FILE_NAME_SIZE 100 -#define INFRARED_TEXT_STORE_NUM 2 -#define INFRARED_TEXT_STORE_SIZE 128 - -#define INFRARED_MAX_BUTTON_NAME_LENGTH 22 -#define INFRARED_MAX_REMOTE_NAME_LENGTH 22 - -#define INFRARED_APP_FOLDER ANY_PATH("infrared") -#define INFRARED_APP_EXTENSION ".ir" - -#define INFRARED_DEFAULT_REMOTE_NAME "Remote" -#define INFRARED_LOG_TAG "InfraredApp" - -typedef enum { - InfraredButtonIndexNone = -1, -} InfraredButtonIndex; - -typedef enum { - InfraredEditTargetNone, - InfraredEditTargetRemote, - InfraredEditTargetButton, -} InfraredEditTarget; - -typedef enum { - InfraredEditModeNone, - InfraredEditModeRename, - InfraredEditModeDelete, -} InfraredEditMode; - -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; - int32_t current_button_index_move_orig; - uint32_t last_transmit_time; -} InfraredAppState; - -struct Infrared { - SceneManager* scene_manager; - ViewDispatcher* view_dispatcher; - - Gui* gui; - Storage* storage; - DialogsApp* dialogs; - NotificationApp* notifications; - InfraredWorker* worker; - InfraredRemote* remote; - InfraredSignal* received_signal; - InfraredBruteForce* brute_force; - - Submenu* submenu; - TextInput* text_input; - VariableItemList* variable_item_list; - DialogEx* dialog_ex; - ButtonMenu* button_menu; - Popup* popup; - - ViewStack* view_stack; - InfraredDebugView* debug_view; - InfraredMoveView* move_view; - - ButtonPanel* button_panel; - Loading* loading; - InfraredProgressView* progress; - - FuriString* file_path; - char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1]; - InfraredAppState app_state; - - void* rpc_ctx; -}; - -typedef enum { - InfraredViewSubmenu, - InfraredViewTextInput, - InfraredViewVariableItemList, - InfraredViewDialogEx, - InfraredViewButtonMenu, - InfraredViewPopup, - InfraredViewStack, - InfraredViewDebugView, - InfraredViewMove, -} InfraredView; - -typedef enum { - InfraredNotificationMessageSuccess, - InfraredNotificationMessageGreenOn, - InfraredNotificationMessageGreenOff, - InfraredNotificationMessageYellowOn, - InfraredNotificationMessageYellowOff, - InfraredNotificationMessageBlinkStartRead, - InfraredNotificationMessageBlinkStartSend, - InfraredNotificationMessageBlinkStop, -} InfraredNotificationMessage; - -bool infrared_add_remote_with_button(Infrared* infrared, const char* name, InfraredSignal* signal); -bool infrared_rename_current_remote(Infrared* infrared, const char* name); -void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal); -void infrared_tx_start_button_index(Infrared* infrared, size_t button_index); -void infrared_tx_start_received(Infrared* infrared); -void infrared_tx_stop(Infrared* infrared); -void infrared_text_store_set(Infrared* infrared, uint32_t bank, const char* text, ...); -void infrared_text_store_clear(Infrared* infrared, uint32_t bank); -void infrared_play_notification_message(Infrared* infrared, uint32_t message); -void infrared_show_loading_popup(Infrared* infrared, bool show); - -void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal); -void infrared_text_input_callback(void* context); -void infrared_popup_closed_callback(void* context); diff --git a/applications/main/infrared/infrared_remote.c b/applications/main/infrared/infrared_remote.c index 70d1b59ef..cab241c12 100644 --- a/applications/main/infrared/infrared_remote.c +++ b/applications/main/infrared/infrared_remote.c @@ -1,197 +1,427 @@ #include "infrared_remote.h" -#include -#include -#include #include + +#include #include #include -#include #define TAG "InfraredRemote" -ARRAY_DEF(InfraredButtonArray, InfraredRemoteButton*, M_PTR_OPLIST); +#define INFRARED_FILE_HEADER "IR signals file" +#define INFRARED_FILE_VERSION (1) + +ARRAY_DEF(StringArray, const char*, M_CSTR_DUP_OPLIST); //-V575 struct InfraredRemote { - InfraredButtonArray_t buttons; + StringArray_t signal_names; FuriString* name; FuriString* path; }; -static void infrared_remote_clear_buttons(InfraredRemote* remote) { - InfraredButtonArray_it_t it; - for(InfraredButtonArray_it(it, remote->buttons); !InfraredButtonArray_end_p(it); - InfraredButtonArray_next(it)) { - infrared_remote_button_free(*InfraredButtonArray_cref(it)); - } - InfraredButtonArray_reset(remote->buttons); -} +typedef struct { + InfraredRemote* remote; + FlipperFormat* ff_in; + FlipperFormat* ff_out; + FuriString* signal_name; + InfraredSignal* signal; + size_t signal_index; +} InfraredBatch; + +typedef struct { + size_t signal_index; + const char* signal_name; + const InfraredSignal* signal; +} InfraredBatchTarget; + +typedef bool ( + *InfraredBatchCallback)(const InfraredBatch* batch, const InfraredBatchTarget* target); InfraredRemote* infrared_remote_alloc() { InfraredRemote* remote = malloc(sizeof(InfraredRemote)); - InfraredButtonArray_init(remote->buttons); + StringArray_init(remote->signal_names); remote->name = furi_string_alloc(); remote->path = furi_string_alloc(); return remote; } void infrared_remote_free(InfraredRemote* remote) { - infrared_remote_clear_buttons(remote); - InfraredButtonArray_clear(remote->buttons); + StringArray_clear(remote->signal_names); furi_string_free(remote->path); furi_string_free(remote->name); free(remote); } void infrared_remote_reset(InfraredRemote* remote) { - infrared_remote_clear_buttons(remote); + StringArray_reset(remote->signal_names); furi_string_reset(remote->name); furi_string_reset(remote->path); } -void infrared_remote_set_name(InfraredRemote* remote, const char* name) { - furi_string_set(remote->name, name); -} - -const char* infrared_remote_get_name(InfraredRemote* remote) { +const char* infrared_remote_get_name(const InfraredRemote* remote) { return furi_string_get_cstr(remote->name); } -void infrared_remote_set_path(InfraredRemote* remote, const char* path) { +static void infrared_remote_set_path(InfraredRemote* remote, const char* path) { furi_string_set(remote->path, path); + path_extract_filename(remote->path, remote->name, true); } -const char* infrared_remote_get_path(InfraredRemote* remote) { +const char* infrared_remote_get_path(const InfraredRemote* remote) { return furi_string_get_cstr(remote->path); } -size_t infrared_remote_get_button_count(InfraredRemote* remote) { - return InfraredButtonArray_size(remote->buttons); +size_t infrared_remote_get_signal_count(const InfraredRemote* remote) { + return StringArray_size(remote->signal_names); } -InfraredRemoteButton* infrared_remote_get_button(InfraredRemote* remote, size_t index) { - furi_assert(index < InfraredButtonArray_size(remote->buttons)); - return *InfraredButtonArray_get(remote->buttons, index); +const char* infrared_remote_get_signal_name(const InfraredRemote* remote, size_t index) { + furi_assert(index < infrared_remote_get_signal_count(remote)); + return *StringArray_cget(remote->signal_names, index); } -bool infrared_remote_find_button_by_name(InfraredRemote* remote, const char* name, size_t* index) { - for(size_t i = 0; i < InfraredButtonArray_size(remote->buttons); i++) { - InfraredRemoteButton* button = *InfraredButtonArray_get(remote->buttons, i); - if(!strcmp(infrared_remote_button_get_name(button), name)) { +bool infrared_remote_load_signal( + const InfraredRemote* remote, + InfraredSignal* signal, + size_t index) { + furi_assert(index < infrared_remote_get_signal_count(remote)); + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); + + bool success = false; + + do { + const char* path = furi_string_get_cstr(remote->path); + if(!flipper_format_buffered_file_open_existing(ff, path)) break; + + if(!infrared_signal_search_by_index_and_read(signal, ff, index)) { + const char* signal_name = infrared_remote_get_signal_name(remote, index); + FURI_LOG_E(TAG, "Failed to load signal '%s' from file '%s'", signal_name, path); + break; + } + + success = true; + } while(false); + + flipper_format_free(ff); + furi_record_close(RECORD_STORAGE); + + return success; +} + +bool infrared_remote_get_signal_index( + const InfraredRemote* remote, + const char* name, + size_t* index) { + uint32_t i = 0; + StringArray_it_t it; + + for(StringArray_it(it, remote->signal_names); !StringArray_end_p(it); + StringArray_next(it), ++i) { + if(strcmp(*StringArray_cref(it), name) == 0) { *index = i; return true; } } + return false; } -bool infrared_remote_add_button(InfraredRemote* remote, const char* name, InfraredSignal* signal) { - InfraredRemoteButton* button = infrared_remote_button_alloc(); - infrared_remote_button_set_name(button, name); - infrared_remote_button_set_signal(button, signal); - InfraredButtonArray_push_back(remote->buttons, button); - return infrared_remote_store(remote); -} - -bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name, size_t index) { - furi_assert(index < InfraredButtonArray_size(remote->buttons)); - InfraredRemoteButton* button = *InfraredButtonArray_get(remote->buttons, index); - infrared_remote_button_set_name(button, new_name); - return infrared_remote_store(remote); -} - -bool infrared_remote_delete_button(InfraredRemote* remote, size_t index) { - furi_assert(index < InfraredButtonArray_size(remote->buttons)); - InfraredRemoteButton* button; - InfraredButtonArray_pop_at(&button, remote->buttons, index); - infrared_remote_button_free(button); - return infrared_remote_store(remote); -} - -void infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest) { - furi_assert(index_orig < InfraredButtonArray_size(remote->buttons)); - furi_assert(index_dest < InfraredButtonArray_size(remote->buttons)); - - InfraredRemoteButton* button; - InfraredButtonArray_pop_at(&button, remote->buttons, index_orig); - InfraredButtonArray_push_at(remote->buttons, index_dest, button); -} - -bool infrared_remote_store(InfraredRemote* remote) { +bool infrared_remote_append_signal( + InfraredRemote* remote, + const InfraredSignal* signal, + const char* name) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* ff = flipper_format_file_alloc(storage); + + bool success = false; const char* path = furi_string_get_cstr(remote->path); - FURI_LOG_I(TAG, "store file: \'%s\'", path); - - bool success = flipper_format_file_open_always(ff, path) && - flipper_format_write_header_cstr(ff, "IR signals file", 1); - if(success) { - InfraredButtonArray_it_t it; - for(InfraredButtonArray_it(it, remote->buttons); !InfraredButtonArray_end_p(it); - InfraredButtonArray_next(it)) { - InfraredRemoteButton* button = *InfraredButtonArray_cref(it); - success = infrared_signal_save( - infrared_remote_button_get_signal(button), - ff, - infrared_remote_button_get_name(button)); - if(!success) { - break; - } - } - } - - flipper_format_free(ff); - furi_record_close(RECORD_STORAGE); - return success; -} - -bool infrared_remote_load(InfraredRemote* remote, FuriString* path) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); - - FuriString* buf; - buf = furi_string_alloc(); - - FURI_LOG_I(TAG, "load file: \'%s\'", furi_string_get_cstr(path)); - bool success = false; - do { - if(!flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(path))) break; - uint32_t version; - if(!flipper_format_read_header(ff, buf, &version)) break; - if(!furi_string_equal(buf, "IR signals file") || (version != 1)) break; + if(!flipper_format_file_open_append(ff, path)) break; + if(!infrared_signal_save(signal, ff, name)) break; - path_extract_filename(path, buf, true); - infrared_remote_clear_buttons(remote); - infrared_remote_set_name(remote, furi_string_get_cstr(buf)); - infrared_remote_set_path(remote, furi_string_get_cstr(path)); - - for(bool can_read = true; can_read;) { - InfraredRemoteButton* button = infrared_remote_button_alloc(); - can_read = infrared_signal_read(infrared_remote_button_get_signal(button), ff, buf); - if(can_read) { - infrared_remote_button_set_name(button, furi_string_get_cstr(buf)); - InfraredButtonArray_push_back(remote->buttons, button); - } else { - infrared_remote_button_free(button); - } - } + StringArray_push_back(remote->signal_names, name); success = true; } while(false); - furi_string_free(buf); flipper_format_free(ff); furi_record_close(RECORD_STORAGE); + + return success; +} + +static bool infrared_remote_batch_start( + InfraredRemote* remote, + InfraredBatchCallback batch_callback, + const InfraredBatchTarget* target) { + FuriString* tmp = furi_string_alloc(); + Storage* storage = furi_record_open(RECORD_STORAGE); + + InfraredBatch batch_context = { + .remote = remote, + .ff_in = flipper_format_buffered_file_alloc(storage), + .ff_out = flipper_format_buffered_file_alloc(storage), + .signal_name = furi_string_alloc(), + .signal = infrared_signal_alloc(), + .signal_index = 0, + }; + + const char* path_in = furi_string_get_cstr(remote->path); + const char* path_out; + + FS_Error status; + + do { + furi_string_printf(tmp, "%s.temp%08x.swp", path_in, rand()); + path_out = furi_string_get_cstr(tmp); + status = storage_common_stat(storage, path_out, NULL); + } while(status == FSE_OK || status == FSE_EXIST); + + bool success = false; + + do { + if(!flipper_format_buffered_file_open_existing(batch_context.ff_in, path_in)) break; + if(!flipper_format_buffered_file_open_always(batch_context.ff_out, path_out)) break; + if(!flipper_format_write_header_cstr( + batch_context.ff_out, INFRARED_FILE_HEADER, INFRARED_FILE_VERSION)) + break; + + const size_t signal_count = infrared_remote_get_signal_count(remote); + + for(; batch_context.signal_index < signal_count; ++batch_context.signal_index) { + if(!infrared_signal_read( + batch_context.signal, batch_context.ff_in, batch_context.signal_name)) + break; + if(!batch_callback(&batch_context, target)) break; + } + + if(batch_context.signal_index != signal_count) break; + + if(!flipper_format_buffered_file_close(batch_context.ff_out)) break; + if(!flipper_format_buffered_file_close(batch_context.ff_in)) break; + + const FS_Error status = storage_common_rename(storage, path_out, path_in); + success = (status == FSE_OK || status == FSE_EXIST); + } while(false); + + infrared_signal_free(batch_context.signal); + furi_string_free(batch_context.signal_name); + flipper_format_free(batch_context.ff_out); + flipper_format_free(batch_context.ff_in); + furi_string_free(tmp); + + furi_record_close(RECORD_STORAGE); + + return success; +} + +static bool infrared_remote_insert_signal_callback( + const InfraredBatch* batch, + const InfraredBatchTarget* target) { + // Insert a signal under the specified index + if(batch->signal_index == target->signal_index) { + if(!infrared_signal_save(target->signal, batch->ff_out, target->signal_name)) return false; + StringArray_push_at( + batch->remote->signal_names, target->signal_index, target->signal_name); + } + + // Write the rest normally + return infrared_signal_save( + batch->signal, batch->ff_out, furi_string_get_cstr(batch->signal_name)); +} + +bool infrared_remote_insert_signal( + InfraredRemote* remote, + const InfraredSignal* signal, + const char* name, + size_t index) { + if(index >= infrared_remote_get_signal_count(remote)) { + return infrared_remote_append_signal(remote, signal, name); + } + + const InfraredBatchTarget insert_target = { + .signal_index = index, + .signal_name = name, + .signal = signal, + }; + + return infrared_remote_batch_start( + remote, infrared_remote_insert_signal_callback, &insert_target); +} + +static bool infrared_remote_rename_signal_callback( + const InfraredBatch* batch, + const InfraredBatchTarget* target) { + const char* signal_name; + + if(batch->signal_index == target->signal_index) { + // Rename the signal at requested index + signal_name = target->signal_name; + StringArray_set_at(batch->remote->signal_names, batch->signal_index, signal_name); + } else { + // Use the original name otherwise + signal_name = furi_string_get_cstr(batch->signal_name); + } + + return infrared_signal_save(batch->signal, batch->ff_out, signal_name); +} + +bool infrared_remote_rename_signal(InfraredRemote* remote, size_t index, const char* new_name) { + furi_assert(index < infrared_remote_get_signal_count(remote)); + + const InfraredBatchTarget rename_target = { + .signal_index = index, + .signal_name = new_name, + .signal = NULL, + }; + + return infrared_remote_batch_start( + remote, infrared_remote_rename_signal_callback, &rename_target); +} + +static bool infrared_remote_delete_signal_callback( + const InfraredBatch* batch, + const InfraredBatchTarget* target) { + if(batch->signal_index == target->signal_index) { + // Do not save the signal to be deleted, remove it from the signal name list instead + StringArray_remove_v( + batch->remote->signal_names, batch->signal_index, batch->signal_index + 1); + } else { + // Pass other signals through + return infrared_signal_save( + batch->signal, batch->ff_out, furi_string_get_cstr(batch->signal_name)); + } + + return true; +} + +bool infrared_remote_delete_signal(InfraredRemote* remote, size_t index) { + furi_assert(index < infrared_remote_get_signal_count(remote)); + + const InfraredBatchTarget delete_target = { + .signal_index = index, + .signal_name = NULL, + .signal = NULL, + }; + + return infrared_remote_batch_start( + remote, infrared_remote_delete_signal_callback, &delete_target); +} + +bool infrared_remote_move_signal(InfraredRemote* remote, size_t index, size_t new_index) { + const size_t signal_count = infrared_remote_get_signal_count(remote); + furi_assert(index < signal_count); + furi_assert(new_index < signal_count); + + if(index == new_index) return true; + + InfraredSignal* signal = infrared_signal_alloc(); + char* signal_name = strdup(infrared_remote_get_signal_name(remote, index)); + + bool success = false; + + do { + if(!infrared_remote_load_signal(remote, signal, index)) break; + if(!infrared_remote_delete_signal(remote, index)) break; + if(!infrared_remote_insert_signal(remote, signal, signal_name, new_index)) break; + + success = true; + } while(false); + + free(signal_name); + infrared_signal_free(signal); + + return success; +} + +bool infrared_remote_create(InfraredRemote* remote, const char* path) { + FURI_LOG_I(TAG, "Creating new file: '%s'", path); + + infrared_remote_reset(remote); + infrared_remote_set_path(remote, path); + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* ff = flipper_format_file_alloc(storage); + + bool success = false; + + do { + if(!flipper_format_file_open_always(ff, path)) break; + if(!flipper_format_write_header_cstr(ff, INFRARED_FILE_HEADER, INFRARED_FILE_VERSION)) + break; + + success = true; + } while(false); + + flipper_format_free(ff); + furi_record_close(RECORD_STORAGE); + + return success; +} + +bool infrared_remote_load(InfraredRemote* remote, const char* path) { + FURI_LOG_I(TAG, "Loading file: '%s'", path); + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); + + FuriString* tmp = furi_string_alloc(); + bool success = false; + + do { + if(!flipper_format_buffered_file_open_existing(ff, path)) break; + + uint32_t version; + if(!flipper_format_read_header(ff, tmp, &version)) break; + + if(!furi_string_equal(tmp, INFRARED_FILE_HEADER) || (version != INFRARED_FILE_VERSION)) + break; + + infrared_remote_set_path(remote, path); + StringArray_reset(remote->signal_names); + + while(infrared_signal_read_name(ff, tmp)) { + StringArray_push_back(remote->signal_names, furi_string_get_cstr(tmp)); + } + + success = true; + } while(false); + + furi_string_free(tmp); + flipper_format_free(ff); + furi_record_close(RECORD_STORAGE); + + return success; +} + +bool infrared_remote_rename(InfraredRemote* remote, const char* new_path) { + const char* old_path = infrared_remote_get_path(remote); + + Storage* storage = furi_record_open(RECORD_STORAGE); + const FS_Error status = storage_common_rename(storage, old_path, new_path); + furi_record_close(RECORD_STORAGE); + + const bool success = (status == FSE_OK || status == FSE_EXIST); + + if(success) { + infrared_remote_set_path(remote, new_path); + } + return success; } bool infrared_remote_remove(InfraredRemote* remote) { Storage* storage = furi_record_open(RECORD_STORAGE); - - FS_Error status = storage_common_remove(storage, furi_string_get_cstr(remote->path)); - infrared_remote_reset(remote); - + const FS_Error status = storage_common_remove(storage, infrared_remote_get_path(remote)); furi_record_close(RECORD_STORAGE); - return (status == FSE_OK || status == FSE_NOT_EXIST); + + const bool success = (status == FSE_OK || status == FSE_NOT_EXIST); + + if(success) { + infrared_remote_reset(remote); + } + + return success; } diff --git a/applications/main/infrared/infrared_remote.h b/applications/main/infrared/infrared_remote.h index 47aa77e2e..7477cd3b5 100644 --- a/applications/main/infrared/infrared_remote.h +++ b/applications/main/infrared/infrared_remote.h @@ -1,30 +1,229 @@ +/** + * @file infrared_remote.h + * @brief Infrared remote library. + * + * An infrared remote contains zero or more infrared signals which + * have a (possibly non-unique) name each. + * + * The current implementation does load only the names into the memory, + * while the signals themselves are loaded on-demand one by one. In theory, + * this should allow for quite large remotes with relatively bulky signals. + */ #pragma once -#include - -#include "infrared_remote_button.h" +#include "infrared_signal.h" +/** + * @brief InfraredRemote opaque type declaration. + */ typedef struct InfraredRemote InfraredRemote; +/** + * @brief Create a new InfraredRemote instance. + * + * @returns pointer to the created instance. + */ InfraredRemote* infrared_remote_alloc(); + +/** + * @brief Delete an InfraredRemote instance. + * + * @param[in,out] remote pointer to the instance to be deleted. + */ void infrared_remote_free(InfraredRemote* remote); + +/** + * @brief Reset an InfraredRemote instance. + * + * Resetting a remote clears its signal name list and + * the associated file path. + * + * @param[in,out] remote pointer to the instance to be deleted. + */ void infrared_remote_reset(InfraredRemote* remote); -void infrared_remote_set_name(InfraredRemote* remote, const char* name); -const char* infrared_remote_get_name(InfraredRemote* remote); +/** + * @brief Get an InfraredRemote instance's name. + * + * The name is deduced from the file path. + * + * The return value remains valid unless one of the following functions is called: + * - infrared_remote_reset() + * - infrared_remote_load() + * - infrared_remote_create() + * + * @param[in] remote pointer to the instance to be queried. + * @returns pointer to a zero-terminated string containing the name. + */ +const char* infrared_remote_get_name(const InfraredRemote* remote); -void infrared_remote_set_path(InfraredRemote* remote, const char* path); -const char* infrared_remote_get_path(InfraredRemote* remote); +/** + * @brief Get an InfraredRemote instance's file path. + * + * Same return value validity considerations as infrared_remote_get_name(). + * + * @param[in] remote pointer to the instance to be queried. + * @returns pointer to a zero-terminated string containing the path. + */ +const char* infrared_remote_get_path(const InfraredRemote* remote); -size_t infrared_remote_get_button_count(InfraredRemote* remote); -InfraredRemoteButton* infrared_remote_get_button(InfraredRemote* remote, size_t index); -bool infrared_remote_find_button_by_name(InfraredRemote* remote, const char* name, size_t* index); +/** + * @brief Get the number of signals listed in an InfraredRemote instance. + * + * @param[in] remote pointer to the instance to be queried. + * @returns number of signals, zero or more + */ +size_t infrared_remote_get_signal_count(const InfraredRemote* remote); -bool infrared_remote_add_button(InfraredRemote* remote, const char* name, InfraredSignal* signal); -bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name, size_t index); -bool infrared_remote_delete_button(InfraredRemote* remote, size_t index); -void infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest); +/** + * @brief Get the name of a signal listed in an InfraredRemote instance. + * + * @param[in] remote pointer to the instance to be queried. + * @param[in] index index of the signal in question. Must be less than the total signal count. + */ +const char* infrared_remote_get_signal_name(const InfraredRemote* remote, size_t index); -bool infrared_remote_store(InfraredRemote* remote); -bool infrared_remote_load(InfraredRemote* remote, FuriString* path); +/** + * @brief Get the index of a signal listed in an InfraredRemote instance by its name. + * + * @param[in] remote pointer to the instance to be queried. + * @param[in] name pointer to a zero-terminated string containig the name of the signal in question. + * @param[out] index pointer to the variable to hold the signal index. + * @returns true if a signal with the given name was found, false otherwise. + */ +bool infrared_remote_get_signal_index( + const InfraredRemote* remote, + const char* name, + size_t* index); + +/** + * @brief Load a signal listed in an InfraredRemote instance. + * + * As mentioned above, the signals are loaded on-demand. The user code must call this function + * each time it wants to interact with a new signal. + * + * @param[in] remote pointer to the instance to load from. + * @param[out] signal pointer to the signal to load into. Must be allocated. + * @param[in] index index of the signal to be loaded. Must be less than the total signal count. + * @return true if the signal was successfully loaded, false otherwise. + */ +bool infrared_remote_load_signal( + const InfraredRemote* remote, + InfraredSignal* signal, + size_t index); + +/** + * @brief Append a signal to the file associated with an InfraredRemote instance. + * + * The file path must be somehow initialised first by calling either infrared_remote_load() or + * infrared_remote_create(). As the name suggests, the signal will be put in the end of the file. + * + * @param[in,out] remote pointer to the instance to append to. + * @param[in] signal pointer to the signal to be appended. + * @param[in] name pointer to a zero-terminated string containing the name of the signal. + * @returns true if the signal was successfully appended, false otherwise. + */ +bool infrared_remote_append_signal( + InfraredRemote* remote, + const InfraredSignal* signal, + const char* name); + +/** + * @brief Insert a signal to the file associated with an InfraredRemote instance. + * + * Same behaviour as infrared_remote_append_signal(), but the user code can decide where to + * put the signal in the file. + * + * Index values equal to or greater than the total signal count will result in behaviour + * identical to infrared_remote_append_signal(). + * + * @param[in,out] remote pointer to the instance to insert to. + * @param[in] signal pointer to the signal to be inserted. + * @param[in] name pointer to a zero-terminated string containing the name of the signal. + * @param[in] index the index under which the signal shall be inserted. + * @returns true if the signal was successfully inserted, false otherwise. + */ +bool infrared_remote_insert_signal( + InfraredRemote* remote, + const InfraredSignal* signal, + const char* name, + size_t index); + +/** + * @brief Rename a signal in the file associated with an InfraredRemote instance. + * + * Only changes the signal's name, but neither its position nor contents. + * + * @param[in,out] remote pointer to the instance to be modified. + * @param[in] index index of the signal to be renamed. Must be less than the total signal count. + * @param[in] new_name pointer to a zero-terminated string containig the signal's new name. + * @returns true if the signal was successfully renamed, false otherwise. + */ +bool infrared_remote_rename_signal(InfraredRemote* remote, size_t index, const char* new_name); + +/** + * @brief Change a signal's position in the file associated with an InfraredRemote instance. + * + * Only changes the signal's position (index), but neither its name nor contents. + * + * @param[in,out] remote pointer to the instance to be modified. + * @param[in] index index of the signal to be moved. Must be less than the total signal count. + * @param[in] new_index index of the signal to be moved. Must be less than the total signal count. + */ +bool infrared_remote_move_signal(InfraredRemote* remote, size_t index, size_t new_index); + +/** + * @brief Delete a signal in the file associated with an InfraredRemote instance. + * + * @param[in,out] remote pointer to the instance to be modified. + * @param[in] index index of the signal to be deleted. Must be less than the total signal count. + * @returns true if the signal was successfully deleted, false otherwise. + */ +bool infrared_remote_delete_signal(InfraredRemote* remote, size_t index); + +/** + * @brief Create a new file and associate it with an InfraredRemote instance. + * + * The instance will be reset and given a new empty file with just the header. + * + * @param[in,out] remote pointer to the instance to be assigned with a new file. + * @param[in] path pointer to a zero-terminated string containing the full file path. + * @returns true if the file was successfully created, false otherwise. + */ +bool infrared_remote_create(InfraredRemote* remote, const char* path); + +/** + * @brief Associate an InfraredRemote instance with a file and load the signal names from it. + * + * The instance will be reset and fill its signal name list from the given file. + * The file must already exist and be valid. + * + * @param[in,out] remote pointer to the instance to be assigned with an existing file. + * @param[in] path pointer to a zero-terminated string containing the full file path. + * @returns true if the file was successfully loaded, false otherwise. + */ +bool infrared_remote_load(InfraredRemote* remote, const char* path); + +/** + * @brief Rename the file associated with an InfraredRemote instance. + * + * Only renames the file, no signals are added, moved or deleted. + * + * @param[in,out] remote pointer to the instance to be modified. + * @param[in] new_path pointer to a zero-terminated string containing the new full file path. + * @returns true if the file was successfully renamed, false otherwise. + */ +bool infrared_remote_rename(InfraredRemote* remote, const char* new_path); + +/** + * @brief Remove the file associated with an InfraredRemote instance. + * + * This operation is irreversible and fully deletes the remote file + * from the underlying filesystem. + * After calling this function, the instance becomes invalid until + * infrared_remote_create() or infrared_remote_load() are successfully executed. + * + * @param[in,out] remote pointer to the instance to be modified. + * @returns true if the file was successfully removed, false otherwise. + */ bool infrared_remote_remove(InfraredRemote* remote); diff --git a/applications/main/infrared/infrared_remote_button.c b/applications/main/infrared/infrared_remote_button.c deleted file mode 100644 index 1f6315ec5..000000000 --- a/applications/main/infrared/infrared_remote_button.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "infrared_remote_button.h" - -#include - -struct InfraredRemoteButton { - FuriString* name; - InfraredSignal* signal; -}; - -InfraredRemoteButton* infrared_remote_button_alloc() { - InfraredRemoteButton* button = malloc(sizeof(InfraredRemoteButton)); - button->name = furi_string_alloc(); - button->signal = infrared_signal_alloc(); - return button; -} - -void infrared_remote_button_free(InfraredRemoteButton* button) { - furi_string_free(button->name); - infrared_signal_free(button->signal); - free(button); -} - -void infrared_remote_button_set_name(InfraredRemoteButton* button, const char* name) { - furi_string_set(button->name, name); -} - -const char* infrared_remote_button_get_name(InfraredRemoteButton* button) { - return furi_string_get_cstr(button->name); -} - -void infrared_remote_button_set_signal(InfraredRemoteButton* button, InfraredSignal* signal) { - infrared_signal_set_signal(button->signal, signal); -} - -InfraredSignal* infrared_remote_button_get_signal(InfraredRemoteButton* button) { - return button->signal; -} diff --git a/applications/main/infrared/infrared_remote_button.h b/applications/main/infrared/infrared_remote_button.h deleted file mode 100644 index f25b759b5..000000000 --- a/applications/main/infrared/infrared_remote_button.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "infrared_signal.h" - -typedef struct InfraredRemoteButton InfraredRemoteButton; - -InfraredRemoteButton* infrared_remote_button_alloc(); -void infrared_remote_button_free(InfraredRemoteButton* button); - -void infrared_remote_button_set_name(InfraredRemoteButton* button, const char* name); -const char* infrared_remote_button_get_name(InfraredRemoteButton* button); - -void infrared_remote_button_set_signal(InfraredRemoteButton* button, InfraredSignal* signal); -InfraredSignal* infrared_remote_button_get_signal(InfraredRemoteButton* button); diff --git a/applications/main/infrared/infrared_signal.c b/applications/main/infrared/infrared_signal.c index 3f9a51908..1bd4780d6 100644 --- a/applications/main/infrared/infrared_signal.c +++ b/applications/main/infrared/infrared_signal.c @@ -8,6 +8,8 @@ #define TAG "InfraredSignal" +#define INFRARED_SIGNAL_NAME_KEY "name" + struct InfraredSignal { bool is_raw; union { @@ -24,7 +26,7 @@ static void infrared_signal_clear_timings(InfraredSignal* signal) { } } -static bool infrared_signal_is_message_valid(InfraredMessage* message) { +static bool infrared_signal_is_message_valid(const InfraredMessage* message) { if(!infrared_is_protocol_valid(message->protocol)) { FURI_LOG_E(TAG, "Unknown protocol"); return false; @@ -57,7 +59,7 @@ static bool infrared_signal_is_message_valid(InfraredMessage* message) { return true; } -static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) { +static bool infrared_signal_is_raw_valid(const InfraredRawSignal* raw) { if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) { FURI_LOG_E( TAG, @@ -83,7 +85,8 @@ static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) { return true; } -static inline bool infrared_signal_save_message(InfraredMessage* message, FlipperFormat* ff) { +static inline bool + infrared_signal_save_message(const InfraredMessage* message, FlipperFormat* ff) { const char* protocol_name = infrared_get_protocol_name(message->protocol); return flipper_format_write_string_cstr(ff, "type", "parsed") && flipper_format_write_string_cstr(ff, "protocol", protocol_name) && @@ -91,7 +94,7 @@ static inline bool infrared_signal_save_message(InfraredMessage* message, Flippe flipper_format_write_hex(ff, "command", (uint8_t*)&message->command, 4); } -static inline bool infrared_signal_save_raw(InfraredRawSignal* raw, FlipperFormat* ff) { +static inline bool infrared_signal_save_raw(const InfraredRawSignal* raw, FlipperFormat* ff) { furi_assert(raw->timings_size <= MAX_TIMINGS_AMOUNT); return flipper_format_write_string_cstr(ff, "type", "raw") && flipper_format_write_uint32(ff, "frequency", &raw->frequency, 1) && @@ -180,11 +183,11 @@ void infrared_signal_free(InfraredSignal* signal) { free(signal); } -bool infrared_signal_is_raw(InfraredSignal* signal) { +bool infrared_signal_is_raw(const InfraredSignal* signal) { return signal->is_raw; } -bool infrared_signal_is_valid(InfraredSignal* signal) { +bool infrared_signal_is_valid(const InfraredSignal* signal) { return signal->is_raw ? infrared_signal_is_raw_valid(&signal->payload.raw) : infrared_signal_is_message_valid(&signal->payload.message); } @@ -233,7 +236,7 @@ void infrared_signal_set_raw_signal( memcpy(signal->payload.raw.timings, timings, timings_size * sizeof(uint32_t)); } -InfraredRawSignal* infrared_signal_get_raw_signal(InfraredSignal* signal) { +const InfraredRawSignal* infrared_signal_get_raw_signal(const InfraredSignal* signal) { furi_assert(signal->is_raw); return &signal->payload.raw; } @@ -245,14 +248,14 @@ void infrared_signal_set_message(InfraredSignal* signal, const InfraredMessage* signal->payload.message = *message; } -InfraredMessage* infrared_signal_get_message(InfraredSignal* signal) { +const InfraredMessage* infrared_signal_get_message(const InfraredSignal* signal) { furi_assert(!signal->is_raw); return &signal->payload.message; } -bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name) { +bool infrared_signal_save(const InfraredSignal* signal, FlipperFormat* ff, const char* name) { if(!flipper_format_write_comment_cstr(ff, "") || - !flipper_format_write_string_cstr(ff, "name", name)) { + !flipper_format_write_string_cstr(ff, INFRARED_SIGNAL_NAME_KEY, name)) { return false; } else if(signal->is_raw) { return infrared_signal_save_raw(&signal->payload.raw, ff); @@ -262,46 +265,61 @@ bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* } bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name) { - FuriString* tmp = furi_string_alloc(); - bool success = false; do { - if(!flipper_format_read_string(ff, "name", tmp)) break; - furi_string_set(name, tmp); + if(!infrared_signal_read_name(ff, name)) break; if(!infrared_signal_read_body(signal, ff)) break; - success = true; - } while(0); - furi_string_free(tmp); - return success; -} - -bool infrared_signal_search_and_read( - InfraredSignal* signal, - FlipperFormat* ff, - const FuriString* name) { - bool success = false; - FuriString* tmp = furi_string_alloc(); - - do { - bool is_name_found = false; - while(flipper_format_read_string(ff, "name", tmp)) { - is_name_found = furi_string_equal(name, tmp); - if(is_name_found) break; - } - if(!is_name_found) break; //-V547 - if(!infrared_signal_read_body(signal, ff)) break; //-V779 - success = true; + success = true; //-V779 } while(false); + return success; +} + +bool infrared_signal_read_name(FlipperFormat* ff, FuriString* name) { + return flipper_format_read_string(ff, INFRARED_SIGNAL_NAME_KEY, name); +} + +bool infrared_signal_search_by_name_and_read( + InfraredSignal* signal, + FlipperFormat* ff, + const char* name) { + bool success = false; + FuriString* tmp = furi_string_alloc(); + + while(infrared_signal_read_name(ff, tmp)) { + if(furi_string_equal(tmp, name)) { + success = infrared_signal_read_body(signal, ff); + break; + } + } + furi_string_free(tmp); return success; } -void infrared_signal_transmit(InfraredSignal* signal) { +bool infrared_signal_search_by_index_and_read( + InfraredSignal* signal, + FlipperFormat* ff, + size_t index) { + bool success = false; + FuriString* tmp = furi_string_alloc(); + + for(uint32_t i = 0; infrared_signal_read_name(ff, tmp); ++i) { + if(i == index) { + success = infrared_signal_read_body(signal, ff); + break; + } + } + + furi_string_free(tmp); + return success; +} + +void infrared_signal_transmit(const InfraredSignal* signal) { if(signal->is_raw) { - InfraredRawSignal* raw_signal = &signal->payload.raw; + const InfraredRawSignal* raw_signal = &signal->payload.raw; infrared_send_raw_ext( raw_signal->timings, raw_signal->timings_size, @@ -309,7 +327,7 @@ void infrared_signal_transmit(InfraredSignal* signal) { raw_signal->frequency, raw_signal->duty_cycle); } else { - InfraredMessage* message = &signal->payload.message; + const InfraredMessage* message = &signal->payload.message; infrared_send(message, 1); } } diff --git a/applications/main/infrared/infrared_signal.h b/applications/main/infrared/infrared_signal.h index 29c661938..cfa4cfa94 100644 --- a/applications/main/infrared/infrared_signal.h +++ b/applications/main/infrared/infrared_signal.h @@ -1,45 +1,205 @@ +/** + * @file infrared_signal.h + * @brief Infrared signal library. + * + * Infrared signals may be of two types: + * - known to the infrared signal decoder, or *parsed* signals + * - the rest, or *raw* signals, which are treated merely as a set of timings. + */ #pragma once -#include -#include -#include - -#include #include +#include +/** + * @brief InfraredSignal opaque type declaration. + */ typedef struct InfraredSignal InfraredSignal; +/** + * @brief Raw signal type definition. + * + * Measurement units used: + * - time: microseconds (uS) + * - frequency: Hertz (Hz) + * - duty_cycle: no units, fraction between 0 and 1. + */ typedef struct { - size_t timings_size; - uint32_t* timings; - uint32_t frequency; - float duty_cycle; + size_t timings_size; /**< Number of elements in the timings array. */ + uint32_t* timings; /**< Pointer to an array of timings describing the signal. */ + uint32_t frequency; /**< Carrier frequency of the signal. */ + float duty_cycle; /**< Duty cycle of the signal. */ } InfraredRawSignal; +/** + * @brief Create a new InfraredSignal instance. + * + * @returns pointer to the instance created. + */ InfraredSignal* infrared_signal_alloc(); + +/** + * @brief Delete an InfraredSignal instance. + * + * @param[in,out] signal pointer to the instance to be deleted. + */ void infrared_signal_free(InfraredSignal* signal); -bool infrared_signal_is_raw(InfraredSignal* signal); -bool infrared_signal_is_valid(InfraredSignal* signal); +/** + * @brief Test whether an InfraredSignal instance holds a raw signal. + * + * @param[in] signal pointer to the instance to be tested. + * @returns true if the instance holds a raw signal, false otherwise. + */ +bool infrared_signal_is_raw(const InfraredSignal* signal); +/** + * @brief Test whether an InfraredSignal instance holds any signal. + * + * @param[in] signal pointer to the instance to be tested. + * @returns true if the instance holds raw signal, false otherwise. + */ +bool infrared_signal_is_valid(const InfraredSignal* signal); + +/** + * @brief Set an InfraredInstance to hold the signal from another one. + * + * Any instance's previous contents will be automatically deleted before + * copying the source instance's contents. + * + * @param[in,out] signal pointer to the destination instance. + * @param[in] other pointer to the source instance. + */ void infrared_signal_set_signal(InfraredSignal* signal, const InfraredSignal* other); +/** + * @brief Set an InfraredInstance to hold a raw signal. + * + * Any instance's previous contents will be automatically deleted before + * copying the raw signal. + * + * After this call, infrared_signal_is_raw() will return true. + * + * @param[in,out] signal pointer to the destination instance. + * @param[in] timings pointer to an array containing the raw signal timings. + * @param[in] timings_size number of elements in the timings array. + * @param[in] frequency signal carrier frequency, in Hertz. + * @param[in] duty_cycle signal duty cycle, fraction between 0 and 1. + */ void infrared_signal_set_raw_signal( InfraredSignal* signal, const uint32_t* timings, size_t timings_size, uint32_t frequency, float duty_cycle); -InfraredRawSignal* infrared_signal_get_raw_signal(InfraredSignal* signal); +/** + * @brief Get the raw signal held by an InfraredSignal instance. + * + * @warning the instance MUST hold a *raw* signal, otherwise undefined behaviour will occur. + * + * @param[in] signal pointer to the instance to be queried. + * @returns pointer to the raw signal structure held by the instance. + */ +const InfraredRawSignal* infrared_signal_get_raw_signal(const InfraredSignal* signal); + +/** + * @brief Set an InfraredInstance to hold a parsed signal. + * + * Any instance's previous contents will be automatically deleted before + * copying the raw signal. + * + * After this call, infrared_signal_is_raw() will return false. + * + * @param[in,out] signal pointer to the destination instance. + * @param[in] message pointer to the message containing the parsed signal. + */ void infrared_signal_set_message(InfraredSignal* signal, const InfraredMessage* message); -InfraredMessage* infrared_signal_get_message(InfraredSignal* signal); -bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name); +/** + * @brief Get the parsed signal held by an InfraredSignal instance. + * + * @warning the instance MUST hold a *parsed* signal, otherwise undefined behaviour will occur. + * + * @param[in] signal pointer to the instance to be queried. + * @returns pointer to the parsed signal structure held by the instance. + */ +const InfraredMessage* infrared_signal_get_message(const InfraredSignal* signal); + +/** + * @brief Read a signal from a FlipperFormat file into an InfraredSignal instance. + * + * The file must be allocated and open prior to this call. The seek position determines + * which signal will be read (if there is more than one in the file). Calling this function + * repeatedly will result in all signals in the file to be read until no more are left. + * + * @param[in,out] signal pointer to the instance to be read into. + * @param[in,out] ff pointer to the FlipperFormat file instance to read from. + * @param[out] name pointer to the string to hold the signal name. Must be properly allocated. + * @returns true if a signal was successfully read, false otherwise (e.g. no more signals to read). + */ bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name); -bool infrared_signal_search_and_read( + +/** + * @brief Read a signal name from a FlipperFormat file. + * + * Same behaviour as infrared_signal_read(), but only the name is read. + * + * @param[in,out] ff pointer to the FlipperFormat file instance to read from. + * @param[out] name pointer to the string to hold the signal name. Must be properly allocated. + * @returns true if a signal name was successfully read, false otherwise (e.g. no more signals to read). + */ +bool infrared_signal_read_name(FlipperFormat* ff, FuriString* name); + +/** + * @brief Read a signal with a particular name from a FlipperFormat file into an InfraredSignal instance. + * + * This function will look for a signal with the given name and if found, attempt to read it. + * Same considerations apply as to infrared_signal_read(). + * + * @param[in,out] signal pointer to the instance to be read into. + * @param[in,out] ff pointer to the FlipperFormat file instance to read from. + * @param[in] name pointer to a zero-terminated string containing the requested signal name. + * @returns true if a signal was found and successfully read, false otherwise (e.g. the signal was not found). + */ +bool infrared_signal_search_by_name_and_read( InfraredSignal* signal, FlipperFormat* ff, - const FuriString* name); + const char* name); -void infrared_signal_transmit(InfraredSignal* signal); +/** + * @brief Read a signal with a particular index from a FlipperFormat file into an InfraredSignal instance. + * + * This function will look for a signal with the given index and if found, attempt to read it. + * Same considerations apply as to infrared_signal_read(). + * + * @param[in,out] signal pointer to the instance to be read into. + * @param[in,out] ff pointer to the FlipperFormat file instance to read from. + * @param[in] index the requested signal index. + * @returns true if a signal was found and successfully read, false otherwise (e.g. the signal was not found). + */ +bool infrared_signal_search_by_index_and_read( + InfraredSignal* signal, + FlipperFormat* ff, + size_t index); + +/** + * @brief Save a signal contained in an InfraredSignal instance to a FlipperFormat file. + * + * The file must be allocated and open prior to this call. Additionally, an appropriate header + * must be already written into the file. + * + * @param[in] signal pointer to the instance holding the signal to be saved. + * @param[in,out] ff pointer to the FlipperFormat file instance to write to. + * @param[in] name pointer to a zero-terminated string contating the name of the signal. + */ +bool infrared_signal_save(const InfraredSignal* signal, FlipperFormat* ff, const char* name); + +/** + * @brief Transmit a signal contained in an InfraredSignal instance. + * + * The transmission happens once per call using the built-in hardware (via HAL calls). + * + * @param[in] signal pointer to the instance holding the signal to be transmitted. + */ +void infrared_signal_transmit(const InfraredSignal* signal); diff --git a/assets/resources/infrared/Roku.ir b/applications/main/infrared/resources/infrared/Roku.ir similarity index 100% rename from assets/resources/infrared/Roku.ir rename to applications/main/infrared/resources/infrared/Roku.ir diff --git a/assets/resources/infrared/Samsung.ir b/applications/main/infrared/resources/infrared/Samsung.ir similarity index 100% rename from assets/resources/infrared/Samsung.ir rename to applications/main/infrared/resources/infrared/Samsung.ir diff --git a/assets/resources/infrared/assets/ac.ir b/applications/main/infrared/resources/infrared/assets/ac.ir similarity index 100% rename from assets/resources/infrared/assets/ac.ir rename to applications/main/infrared/resources/infrared/assets/ac.ir diff --git a/assets/resources/infrared/assets/audio.ir b/applications/main/infrared/resources/infrared/assets/audio.ir similarity index 100% rename from assets/resources/infrared/assets/audio.ir rename to applications/main/infrared/resources/infrared/assets/audio.ir diff --git a/assets/resources/infrared/assets/digital_sign.ir b/applications/main/infrared/resources/infrared/assets/digital_sign.ir similarity index 100% rename from assets/resources/infrared/assets/digital_sign.ir rename to applications/main/infrared/resources/infrared/assets/digital_sign.ir diff --git a/assets/resources/infrared/assets/fans.ir b/applications/main/infrared/resources/infrared/assets/fans.ir similarity index 100% rename from assets/resources/infrared/assets/fans.ir rename to applications/main/infrared/resources/infrared/assets/fans.ir diff --git a/assets/resources/infrared/assets/led.ir b/applications/main/infrared/resources/infrared/assets/led.ir similarity index 100% rename from assets/resources/infrared/assets/led.ir rename to applications/main/infrared/resources/infrared/assets/led.ir diff --git a/assets/resources/infrared/assets/monitor.ir b/applications/main/infrared/resources/infrared/assets/monitor.ir similarity index 100% rename from assets/resources/infrared/assets/monitor.ir rename to applications/main/infrared/resources/infrared/assets/monitor.ir diff --git a/assets/resources/infrared/assets/projectors.ir b/applications/main/infrared/resources/infrared/assets/projector.ir similarity index 100% rename from assets/resources/infrared/assets/projectors.ir rename to applications/main/infrared/resources/infrared/assets/projector.ir diff --git a/applications/main/infrared/resources/infrared/assets/projectors.ir b/applications/main/infrared/resources/infrared/assets/projectors.ir new file mode 100644 index 000000000..2fef79ee4 --- /dev/null +++ b/applications/main/infrared/resources/infrared/assets/projectors.ir @@ -0,0 +1,1497 @@ +Filetype: IR library file +Version: 1 +# Last Updated 1st Oct, 2023 +# Last Checked 1st Oct, 2023 +# +# TEMP FIX FOR POWER +# +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 310 27591 171 27662 241 27731 307 27575 107 27749 306 27551 130 55520 243 27614 217 55584 129 27743 119 27756 115 27747 163 27712 308 27502 243 27650 217 27732 175 27693 167 27698 166 27689 171 27622 215 27712 133 27658 216 27716 129 27732 162 27698 305 27571 131 27753 310 27570 170 27707 162 27707 175 10960 9194 4518 618 542 618 543 725 434 672 1623 671 1647 646 514 592 568 592 568 592 1702 592 568 592 567 593 1702 592 568 618 1676 618 1676 618 1676 618 543 617 543 617 543 617 1677 617 544 616 544 616 544 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1679 615 1678 616 1678 616 40239 9196 2250 617 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 310 27591 171 27662 241 27731 307 27575 107 27749 306 27551 130 55520 243 27614 217 55584 129 27743 119 27756 115 27747 163 27712 308 27502 243 27650 217 27732 175 27693 167 27698 166 27689 171 27622 215 27712 133 27658 216 27716 129 27732 162 27698 305 27571 131 27753 310 27570 170 27707 162 27707 175 10960 9194 4518 618 542 618 543 725 434 672 1623 671 1647 646 514 592 568 592 568 592 1702 592 568 592 567 593 1702 592 568 618 1676 618 1676 618 1676 618 543 617 543 617 543 617 1677 617 544 616 544 616 544 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1679 615 1678 616 1678 616 40239 9196 2250 617 +# +name: Vol_up +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 48 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 49 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 14 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 0B 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 0B 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 40 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 48 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 44 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 83 7C 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 82 7D 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 08 13 00 00 +command: 87 78 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9055 4338 672 1551 669 1553 618 1603 619 481 617 482 616 481 617 507 591 1605 645 479 619 1577 645 1578 644 1578 644 479 619 480 618 1581 641 480 617 1605 617 1606 616 1606 615 483 615 1608 614 484 614 484 614 484 614 484 614 484 614 484 614 1609 614 484 614 1609 614 1609 613 1609 613 40058 9000 2068 614 95467 9022 2068 614 +# +name: Power +type: parsed +protocol: NECext +address: 08 13 00 00 +command: 87 78 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9055 4338 672 1551 669 1553 618 1603 619 481 617 482 616 481 617 507 591 1605 645 479 619 1577 645 1578 644 1578 644 479 619 480 618 1581 641 480 617 1605 617 1606 616 1606 615 483 615 1608 614 484 614 484 614 484 614 484 614 484 614 484 614 1609 614 484 614 1609 614 1609 613 1609 613 40058 9000 2068 614 95467 9022 2068 614 +# +name: Mute +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 29 D6 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 08 F7 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 04 FB 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 93 6C 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 15 00 00 00 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9032 4462 598 501 627 1604 627 530 598 531 677 423 706 422 706 421 707 451 677 1554 677 451 598 1633 598 1634 597 1634 598 1634 598 1634 625 1606 681 1550 626 502 598 530 599 529 600 1632 600 528 600 528 601 528 601 528 601 1631 600 1631 625 1607 625 504 625 1607 624 1608 624 1608 623 +# +name: Mute +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 1D 00 00 00 +# +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9096 4436 620 505 647 478 648 501 623 1599 647 1624 623 502 623 503 621 504 619 1628 618 507 617 507 617 1630 617 508 616 1630 617 1630 617 1631 616 508 616 508 617 508 616 1631 616 508 617 508 617 508 616 508 616 1630 616 1630 616 1631 616 508 616 1630 617 1630 617 1630 617 1631 617 509 616 508 616 509 616 509 616 509 616 509 615 509 616 508 617 1631 616 1631 615 1631 616 1631 616 1631 616 1631 616 1631 615 1631 616 14435 9093 2186 615 96359 9095 2184 617 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 1D 00 00 00 +# +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9096 4436 620 505 647 478 648 501 623 1599 647 1624 623 502 623 503 621 504 619 1628 618 507 617 507 617 1630 617 508 616 1630 617 1630 617 1631 616 508 616 508 617 508 616 1631 616 508 617 508 617 508 616 508 616 1630 616 1630 616 1631 616 508 616 1630 617 1630 617 1630 617 1631 617 509 616 508 616 509 616 509 616 509 616 509 615 509 616 508 617 1631 616 1631 615 1631 616 1631 616 1631 616 1631 616 1631 615 1631 616 14435 9093 2186 615 96359 9095 2184 617 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9091 4465 594 530 595 530 594 530 594 1651 595 1652 595 529 621 504 620 504 619 1628 618 507 617 508 616 1631 616 509 615 1631 616 1631 616 1632 615 509 616 509 616 509 615 1631 616 509 616 508 616 1631 616 509 616 1631 615 1631 616 1631 617 508 616 1631 616 1631 616 508 616 1631 617 508 617 509 616 509 616 509 616 509 616 509 616 509 616 509 616 1631 616 1631 616 1631 616 1631 616 1631 615 1631 615 1631 615 1631 616 14435 9090 2190 615 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9092 4439 620 506 619 506 618 530 593 1627 620 1630 643 504 620 505 618 506 617 1630 617 508 616 508 616 1632 616 508 617 1631 616 1631 616 1631 616 1631 616 509 616 508 616 1631 616 509 616 509 615 1632 616 509 616 508 616 1631 616 1631 616 508 616 1631 615 1631 616 509 615 1632 615 509 616 509 616 509 616 509 616 509 616 510 615 509 616 509 616 1631 616 1631 615 1631 616 1631 615 1631 615 1631 615 1631 615 1631 615 14434 9088 2191 615 96339 9115 2189 616 96343 9117 2189 616 96343 9114 2189 616 +# AV-Mute +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9092 4439 620 506 618 506 618 530 594 1627 619 1629 643 505 619 505 619 506 617 1629 617 508 616 508 616 1631 616 508 616 1630 616 1630 616 1630 617 1630 616 1630 616 1631 616 508 616 508 616 508 616 1631 616 508 617 508 616 508 616 508 616 1630 616 1631 615 1631 616 508 616 1631 616 508 617 508 616 509 615 509 616 508 616 509 615 509 616 508 616 1631 615 1631 615 1631 616 1631 615 1631 615 1631 615 1631 615 1631 616 14433 9088 2191 615 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9014 4332 661 1570 661 471 660 473 658 474 657 476 655 498 633 498 634 502 633 499 633 1599 632 1599 632 1599 632 1599 632 1599 632 1600 631 1603 632 500 632 501 631 501 631 501 631 501 631 501 631 1601 631 504 631 1601 631 1601 631 1601 631 1601 631 1601 630 1601 630 501 631 1601 631 38177 8983 2149 630 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9014 4332 661 1570 661 471 660 473 658 474 657 476 655 498 633 498 634 502 633 499 633 1599 632 1599 632 1599 632 1599 632 1599 632 1600 631 1603 632 500 632 501 631 501 631 501 631 501 631 501 631 1601 631 504 631 1601 631 1601 631 1601 631 1601 631 1601 630 1601 630 501 631 1601 631 38177 8983 2149 630 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 11 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 4C 00 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9042 4306 690 1541 665 468 664 468 664 469 663 470 662 471 660 495 636 499 636 497 634 1597 634 1598 633 1598 633 1599 633 1599 632 1599 633 1603 632 1599 633 499 633 499 633 500 632 499 633 500 632 1600 632 503 633 500 632 1600 632 1600 632 1600 633 1600 632 1600 632 500 632 1600 632 37912 8986 2145 633 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3522 1701 472 426 444 1269 472 426 444 426 443 427 443 427 443 426 444 427 443 426 444 427 442 428 441 429 440 431 438 1304 437 433 437 433 438 433 437 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1305 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 459 411 459 411 459 411 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 459 411 459 411 1330 411 1330 411 460 410 1330 411 1330 411 1331 410 1330 411 74392 3516 1736 436 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 435 435 1305 436 435 435 435 435 1306 435 435 435 435 435 435 435 436 434 436 434 436 434 435 435 436 434 436 434 436 434 1330 411 1331 410 1330 411 1330 411 1330 411 459 411 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 435 436 434 436 1306 435 435 435 435 435 1306 435 435 435 435 435 435 435 435 435 435 435 436 434 436 434 435 435 436 434 435 435 1306 435 1330 411 1307 434 1331 410 1308 433 436 434 436 434 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 435 435 434 436 434 436 434 436 434 436 434 436 1306 435 435 435 435 435 435 435 1306 435 435 435 436 434 1306 435 435 435 436 434 436 434 435 435 436 434 436 434 460 410 460 410 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 434 436 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 435 435 435 435 434 436 1306 435 434 436 435 435 435 435 1306 435 436 434 435 435 1306 435 435 435 436 434 436 434 436 434 436 434 460 410 437 433 459 411 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3514 1736 437 434 436 1304 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 435 435 434 436 434 436 435 435 434 436 1305 436 435 435 435 435 435 435 1306 435 435 435 435 435 1306 435 435 435 436 434 435 435 459 411 436 434 435 435 459 411 459 411 459 411 459 411 1330 411 1306 435 1330 411 1330 411 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 529 7218 126 6585 219 703 180 5362 427 18618 177 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3522 1701 472 426 444 1269 472 426 444 426 443 427 443 427 443 426 444 427 443 426 444 427 442 428 441 429 440 431 438 1304 437 433 437 433 438 433 437 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1305 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 459 411 459 411 459 411 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 459 411 459 411 1330 411 1330 411 460 410 1330 411 1330 411 1331 410 1330 411 74392 3516 1736 436 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 435 435 1305 436 435 435 435 435 1306 435 435 435 435 435 435 435 436 434 436 434 436 434 435 435 436 434 436 434 436 434 1330 411 1331 410 1330 411 1330 411 1330 411 459 411 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 435 436 434 436 1306 435 435 435 435 435 1306 435 435 435 435 435 435 435 435 435 435 435 436 434 436 434 435 435 436 434 435 435 1306 435 1330 411 1307 434 1331 410 1308 433 436 434 436 434 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 435 435 434 436 434 436 434 436 434 436 434 436 1306 435 435 435 435 435 435 435 1306 435 435 435 436 434 1306 435 435 435 436 434 436 434 435 435 436 434 436 434 460 410 460 410 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 434 436 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 435 435 435 435 434 436 1306 435 434 436 435 435 435 435 1306 435 436 434 435 435 1306 435 435 435 436 434 436 434 436 434 436 434 460 410 437 433 459 411 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3514 1736 437 434 436 1304 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 435 435 434 436 434 436 435 435 434 436 1305 436 435 435 435 435 435 435 1306 435 435 435 435 435 1306 435 435 435 436 434 435 435 459 411 436 434 435 435 459 411 459 411 459 411 459 411 1330 411 1306 435 1330 411 1330 411 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 529 7218 126 6585 219 703 180 5362 427 18618 177 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9069 4362 622 486 621 487 621 491 622 1608 623 1603 622 487 621 487 621 491 622 1604 621 487 622 491 622 1604 621 491 622 1608 622 1609 621 1604 622 486 622 487 621 491 621 1605 621 487 621 491 622 1604 622 491 621 1609 621 1609 621 1604 622 491 621 1609 622 1604 621 491 621 1604 622 487 621 487 622 486 622 487 621 488 621 487 621 488 620 491 621 1609 622 1609 620 1609 621 1609 621 1609 621 1609 621 1609 621 1618 621 14330 9047 2137 620 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9047 4362 621 486 622 463 645 490 622 1609 622 1604 622 487 620 487 621 491 622 1604 622 484 625 490 621 1605 649 463 621 1609 620 1611 621 1608 622 1605 621 486 622 491 622 1604 621 487 621 492 620 1604 621 488 621 492 620 1609 622 1604 621 492 622 1609 620 1605 621 491 622 1603 622 488 621 488 620 488 620 488 621 488 620 487 622 485 621 492 596 1635 621 1609 622 1585 643 1611 620 1608 621 1610 619 1611 620 1619 619 14332 9074 2109 647 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9073 4336 648 461 647 484 624 489 623 1607 623 1603 622 486 622 486 622 491 622 1604 621 487 621 491 622 1604 622 491 621 1609 621 1609 621 1609 621 1608 622 1609 621 1604 621 486 622 486 622 491 622 1604 622 486 622 487 621 487 621 491 622 1608 622 1609 621 1604 622 491 621 1604 621 487 621 486 622 487 621 487 621 487 621 487 621 487 621 491 622 1608 622 1608 622 1609 621 1608 622 1608 622 1608 622 1609 621 1617 622 14330 9047 2137 620 +# ON +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4F B0 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 10 EF 00 00 +# ON +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4F B0 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 10 EF 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 1C E3 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 46 B9 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 80 00 00 00 +command: 51 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 40 40 00 00 +command: 0A F5 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 4E B1 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 80 00 00 00 +command: 51 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 40 40 00 00 +command: 0A F5 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 4E B1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 0E F1 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 0D F2 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 4F B0 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 4F B0 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 14 EB 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 08 16 00 00 +command: 87 78 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 08 16 00 00 +command: 87 78 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 08 16 00 00 +command: C8 37 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 01 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 01 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 02 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 28 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 29 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 84 F4 00 00 +command: 0B F4 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 00 FF 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 84 F4 00 00 +command: 0B F4 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 00 FF 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 1E E1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 1D E2 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 0B F4 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 90 6F 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 90 6F 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 99 66 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 98 67 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 1C E3 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 1C E3 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 4F B0 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 4B B4 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 2E 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 2E 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 52 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 41 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 41 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 51 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 56 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 5A 00 00 00 +# +name: Power +type: parsed +protocol: SIRC15 +address: 54 00 00 00 +command: 15 00 00 00 +# +name: Power +type: parsed +protocol: SIRC15 +address: 54 00 00 00 +command: 15 00 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 82 7D 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 83 7C 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 14 EB 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 91 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 90 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 91 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 90 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 31 00 00 00 +command: D0 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 89 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 00 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 00 00 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 30 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 31 00 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 32 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 30 00 00 00 +command: 00 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 0D 00 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9032 4479 597 560 572 558 564 566 566 1666 589 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 1669 596 560 562 1671 594 1666 588 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 566 566 563 569 1664 591 1669 596 1664 590 565 567 1667 598 1661 593 1666 588 1671 594 562 570 560 562 568 564 565 567 563 569 560 562 568 564 565 567 1666 588 1671 594 1665 589 1670 595 1665 590 1669 596 1664 590 1668 597 13983 9029 2222 599 96237 9030 2221 589 96244 9034 2217 594 96244 9033 2218 592 96249 9038 2213 597 96239 9037 2214 596 96238 9028 2223 598 96221 9032 2215 595 +# +name: Power +type: parsed +protocol: NECext +address: 30 00 00 00 +command: 00 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 0D 00 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9032 4479 597 560 572 558 564 566 566 1666 589 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 1669 596 560 562 1671 594 1666 588 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 566 566 563 569 1664 591 1669 596 1664 590 565 567 1667 598 1661 593 1666 588 1671 594 562 570 560 562 568 564 565 567 563 569 560 562 568 564 565 567 1666 588 1671 594 1665 589 1670 595 1665 590 1669 596 1664 590 1668 597 13983 9029 2222 599 96237 9030 2221 589 96244 9034 2217 594 96244 9033 2218 592 96249 9038 2213 597 96239 9037 2214 596 96238 9028 2223 598 96221 9032 2215 595 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9034 4482 593 563 569 561 571 559 563 1698 566 1694 570 559 563 568 564 566 566 1695 569 560 572 559 563 1671 593 563 569 1692 562 1671 593 1693 571 558 564 567 565 565 567 1693 571 532 590 567 565 1695 569 560 562 1698 566 1694 570 1663 591 539 593 1693 571 1688 566 564 568 1691 563 567 565 565 567 563 569 561 571 559 563 567 565 565 567 563 569 1690 564 1695 569 1691 563 1696 568 1691 563 1697 567 1692 562 1697 567 13988 9030 2223 597 96250 9035 2219 591 96245 9032 2221 589 96240 9038 2215 595 96235 9033 2220 590 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9028 4482 593 563 569 561 571 558 564 1696 568 1690 564 566 566 563 569 561 571 1688 566 563 569 561 571 1688 566 563 569 1690 564 1695 569 1689 565 1668 596 560 562 568 564 1695 569 560 562 568 564 1695 569 560 562 568 564 1695 569 1690 564 566 566 1692 572 1687 567 563 569 1690 564 566 566 564 568 562 570 559 563 567 565 565 567 562 570 560 562 1696 568 1665 589 1670 594 1665 589 1670 594 1664 590 1669 647 1612 590 13987 9031 2220 590 96223 9033 2217 593 96223 9034 2218 592 96225 9032 2219 591 96221 9087 2164 595 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9031 4479 596 560 572 558 564 566 566 1693 571 1688 566 563 569 561 571 559 563 1696 568 561 571 559 563 1697 567 562 570 1689 565 1694 570 1688 566 1693 571 1661 593 1693 571 558 564 566 566 564 568 1691 563 541 591 564 568 562 570 560 562 1697 567 1692 562 1696 568 562 570 1689 565 564 568 561 571 559 563 567 565 564 568 562 570 560 562 567 565 1694 570 1689 565 1694 570 1688 566 1693 571 1688 566 1693 571 1662 592 13987 9031 2220 590 96231 9034 2217 593 96234 9030 2222 588 96247 9037 2215 595 +# +name: Vol_up +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 11 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 14 00 00 00 +# OFF +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4E B1 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 1D 00 00 00 +# OFF +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4E B1 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 1D 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 11 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 15 00 00 00 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9075 4307 677 433 675 456 651 461 651 1579 650 1576 649 459 649 460 648 465 648 1578 647 461 622 491 622 1604 647 465 647 1583 622 1608 647 1579 647 461 647 466 622 1604 647 465 647 1579 647 461 645 463 648 465 648 1583 646 1580 646 466 647 1579 622 491 647 1583 622 1608 647 1579 647 461 647 461 622 486 622 486 647 461 647 462 646 462 622 491 646 1584 622 1608 647 1584 621 1608 647 1583 646 1584 647 1584 646 1592 622 14330 9047 2137 621 +# +name: Power +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: E6 00 00 00 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9075 4307 677 433 675 456 651 461 651 1579 650 1576 649 459 649 460 648 465 648 1578 647 461 622 491 622 1604 647 465 647 1583 622 1608 647 1579 647 461 647 466 622 1604 647 465 647 1579 647 461 645 463 648 465 648 1583 646 1580 646 466 647 1579 622 491 647 1583 622 1608 647 1579 647 461 647 461 622 486 622 486 647 461 647 462 646 462 622 491 646 1584 622 1608 647 1584 621 1608 647 1583 646 1584 647 1584 646 1592 622 14330 9047 2137 621 +# +name: Power +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: E6 00 00 00 +# +name: Vol_up +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 07 00 00 00 +# +name: Vol_dn +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 0B 00 00 00 +# +name: Mute +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 0F 00 00 00 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3523 1701 472 426 444 1269 472 426 444 426 442 429 443 427 443 426 444 426 444 426 443 427 442 429 440 430 439 432 438 1304 437 433 437 432 438 432 438 433 437 433 437 433 437 433 437 433 437 433 437 1304 437 433 437 433 437 433 437 1304 437 433 437 433 437 1304 437 433 437 434 436 433 437 434 436 434 436 434 436 433 437 433 437 434 436 1304 437 1305 436 1305 436 1305 436 1305 436 1305 436 434 436 434 436 1305 436 1305 436 1305 436 434 436 1305 436 1305 436 1306 435 1306 435 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 1304 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 436 434 435 435 1307 434 1331 410 1307 434 1307 434 1330 411 1307 434 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 434 436 433 437 433 437 1304 437 434 436 434 436 434 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 435 435 434 436 1305 436 434 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1306 435 1307 434 1307 434 1307 434 1331 410 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 1304 437 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 437 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3523 1701 472 426 444 1269 472 426 444 426 442 429 443 427 443 426 444 426 444 426 443 427 442 429 440 430 439 432 438 1304 437 433 437 432 438 432 438 433 437 433 437 433 437 433 437 433 437 433 437 1304 437 433 437 433 437 433 437 1304 437 433 437 433 437 1304 437 433 437 434 436 433 437 434 436 434 436 434 436 433 437 433 437 434 436 1304 437 1305 436 1305 436 1305 436 1305 436 1305 436 434 436 434 436 1305 436 1305 436 1305 436 434 436 1305 436 1305 436 1306 435 1306 435 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 1304 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 436 434 435 435 1307 434 1331 410 1307 434 1307 434 1330 411 1307 434 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 434 436 433 437 433 437 1304 437 434 436 434 436 434 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 435 435 434 436 1305 436 434 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1306 435 1307 434 1307 434 1307 434 1331 410 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 1304 437 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 437 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9093 4441 620 507 618 530 594 531 593 1652 595 1653 620 505 620 505 619 506 617 1630 616 508 616 508 616 1632 615 509 615 1631 616 1632 615 1632 615 510 615 509 615 1632 615 509 615 1632 615 510 615 510 614 509 615 1632 614 1633 614 509 615 1633 614 509 615 1632 615 1632 614 1633 614 510 614 510 615 510 615 510 614 510 614 510 615 510 615 510 614 1632 615 1632 614 1632 615 1632 615 1632 615 1632 615 1632 615 1633 614 14439 9088 2192 614 96349 9112 2190 616 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9093 4441 620 507 618 530 594 531 593 1652 595 1653 620 505 620 505 619 506 617 1630 616 508 616 508 616 1632 615 509 615 1631 616 1632 615 1632 615 510 615 509 615 1632 615 509 615 1632 615 510 615 510 614 509 615 1632 614 1633 614 509 615 1633 614 509 615 1632 615 1632 614 1633 614 510 614 510 615 510 615 510 614 510 614 510 615 510 615 510 614 1632 615 1632 614 1632 615 1632 615 1632 615 1632 615 1632 615 1633 614 14439 9088 2192 614 96349 9112 2190 616 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 243 27700 170 27632 246 27694 282 27595 307 27497 241 27696 177 27710 164 27644 245 27629 246 27712 174 27638 211 27736 131 27741 306 27504 214 27727 135 27749 132 27761 126 27744 131 27753 127 27764 121 27767 132 27773 307 27577 131 27706 213 27761 129 27759 128 27770 125 27694 213 27751 307 27578 131 27737 131 27745 304 27575 335 27540 124 27752 132 27749 132 27747 134 27757 134 27758 127 27762 131 27748 131 27750 122 27749 130 27748 125 27772 131 27774 136 27762 135 27686 215 27742 131 27749 132 27756 133 27764 126 24073 9255 4460 672 488 618 541 619 541 619 1675 619 1676 618 542 618 542 618 542 618 1676 618 542 618 543 617 1678 616 568 592 1702 592 1702 592 1703 617 543 617 543 617 1677 617 543 617 1678 615 544 616 544 616 544 616 1678 616 1679 615 544 616 1679 615 545 615 1679 615 1679 615 1679 615 40240 9173 2273 591 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 243 27700 170 27632 246 27694 282 27595 307 27497 241 27696 177 27710 164 27644 245 27629 246 27712 174 27638 211 27736 131 27741 306 27504 214 27727 135 27749 132 27761 126 27744 131 27753 127 27764 121 27767 132 27773 307 27577 131 27706 213 27761 129 27759 128 27770 125 27694 213 27751 307 27578 131 27737 131 27745 304 27575 335 27540 124 27752 132 27749 132 27747 134 27757 134 27758 127 27762 131 27748 131 27750 122 27749 130 27748 125 27772 131 27774 136 27762 135 27686 215 27742 131 27749 132 27756 133 27764 126 24073 9255 4460 672 488 618 541 619 541 619 1675 619 1676 618 542 618 542 618 542 618 1676 618 542 618 543 617 1678 616 568 592 1702 592 1702 592 1703 617 543 617 543 617 1677 617 543 617 1678 615 544 616 544 616 544 616 1678 616 1679 615 544 616 1679 615 545 615 1679 615 1679 615 1679 615 40240 9173 2273 591 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 219 27658 217 27663 216 27658 216 27634 216 27642 215 27646 217 27662 217 27637 216 27649 216 27649 218 27656 217 27658 215 27640 214 27636 217 27649 216 27644 218 27635 217 27630 215 27645 216 27631 215 27632 216 27650 216 27628 217 27630 214 27627 217 27623 215 27632 215 27641 216 27634 214 27633 215 27648 215 27648 217 27651 215 27635 216 27629 216 27630 216 2021 9254 4461 618 542 618 542 618 542 618 1675 619 1676 618 541 619 541 619 542 618 1677 617 543 617 543 617 1678 616 568 592 1702 592 1702 618 1676 618 542 618 542 618 543 617 1677 617 543 617 544 616 1678 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1678 616 544 616 1678 616 40239 9200 2247 617 99930 110 27739 119 27738 123 27750 126 27738 175 27617 214 27716 203 27604 213 27639 217 27631 214 27722 136 27753 119 27736 175 27618 246 27683 177 27619 245 27685 171 55486 244 27693 158 27635 241 27695 170 27693 129 27717 340 27530 113 27757 106 27751 124 27728 172 27707 126 27666 215 27708 123 27733 123 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 18 E9 00 00 +command: 49 B6 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 14 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 14 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 48 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 40 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 18 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 0C F3 00 00 +# +name: Power +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 0C F3 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 0D F2 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 1E E1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 1F E0 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 81 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 81 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 8F 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 8C 00 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9066 4428 608 507 609 1622 609 507 609 507 609 1623 608 1623 609 507 609 506 610 1623 609 507 609 1622 610 1623 608 507 609 506 610 1622 609 1623 609 506 610 1622 610 506 610 1623 637 478 690 425 638 478 637 1594 637 1594 664 451 636 1594 610 506 610 1621 611 1621 610 1621 610 505 611 40183 9065 2156 637 95953 9037 2185 608 +# +name: Power +type: parsed +protocol: NEC +address: 00 00 00 00 +command: A8 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 00 00 00 00 +command: A8 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 88 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 9C 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 8C 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 17 E8 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 17 E8 00 00 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9064 4354 666 1559 666 1562 662 1586 638 475 636 477 635 477 635 478 635 1590 635 1591 634 478 635 1591 634 478 634 478 635 478 634 1591 635 478 634 1591 634 478 635 478 634 478 635 1591 634 478 634 1591 635 478 634 478 634 1591 634 1591 635 1591 634 478 635 1591 634 478 634 1591 635 40957 9035 2144 634 95483 9047 2155 632 95484 9048 2153 633 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 50 AF 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9034 4385 638 1587 664 1562 663 1587 637 476 635 478 634 478 635 478 635 1591 634 1591 634 478 635 1591 635 478 634 478 635 478 635 1591 635 478 634 478 634 1591 634 478 635 479 634 1591 635 478 634 1591 635 478 634 1592 634 478 634 1591 635 1591 635 478 634 1592 634 478 634 1591 634 40958 9033 2144 635 +# +name: Power +type: parsed +protocol: NECext +address: FF FF 00 00 +command: E8 17 00 00 +# +name: Power +type: parsed +protocol: NECext +address: FF FF 00 00 +command: E8 17 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: FF FF 00 00 +command: BD 42 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: FF FF 00 00 +command: F2 0D 00 00 +# +name: Power +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 05 00 00 00 +# +name: Power +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 05 00 00 00 +# +name: Vol_up +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 70 01 00 00 +# +name: Vol_dn +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 71 01 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 81 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 17 E8 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 81 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 17 E8 00 00 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9010 4413 532 1617 532 1617 533 489 533 489 533 489 558 464 558 465 557 1593 557 465 557 466 556 1594 555 467 555 1595 529 1621 554 1595 581 1569 581 441 581 1569 581 441 581 441 581 441 581 441 581 441 581 1569 581 1569 581 441 581 1569 580 1569 580 1570 580 1595 554 1595 555 468 554 42156 8983 2135 556 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9032 4390 556 1592 559 1591 559 463 559 463 558 464 557 465 556 465 557 1593 583 440 581 441 580 1569 581 441 581 1569 580 1569 581 1569 581 1570 580 1596 554 1596 554 468 554 468 554 468 554 442 580 442 580 1596 554 469 553 469 553 1596 554 1596 553 1597 550 1598 553 1598 552 469 551 42155 9008 2107 531 95218 9006 2108 582 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9011 4388 557 1617 532 1617 532 489 533 489 558 464 558 440 582 440 582 1593 556 466 556 466 556 1594 556 467 555 1595 555 1595 529 1620 554 1596 554 467 554 468 555 1595 579 443 581 1569 581 441 581 441 580 442 581 1569 581 1569 581 441 581 1569 580 441 581 1569 581 1569 581 1570 579 42152 8957 2159 556 +# +name: Power +type: parsed +protocol: NECext +address: 4F 50 00 00 +command: 02 FD 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 4F 50 00 00 +command: 02 FD 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 4F 50 00 00 +command: 08 F7 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 4F 50 00 00 +command: 0B F4 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 81 03 00 00 +command: F0 0F 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 51 AE 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 52 AD 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8811 4222 530 1580 531 1579 531 507 531 507 531 507 531 508 531 508 530 1582 528 1583 527 535 503 1608 502 536 501 1609 501 537 501 1610 500 538 500 1611 499 538 500 539 500 538 500 1611 500 539 499 538 500 1611 499 539 499 1611 499 1611 500 1611 499 539 499 1611 500 1611 500 539 499 35437 8784 4252 500 1611 500 1612 500 539 500 539 500 539 500 539 500 539 500 1611 500 1612 499 539 500 1612 500 539 500 1612 499 539 500 1612 500 539 500 1612 499 539 500 539 500 539 499 1612 499 540 499 539 500 1612 499 539 500 1612 499 1613 499 1612 499 539 500 1612 500 1612 500 539 500 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8811 4222 530 1580 531 1579 531 507 531 507 531 507 531 508 531 508 530 1582 528 1583 527 535 503 1608 502 536 501 1609 501 537 501 1610 500 538 500 1611 499 538 500 539 500 538 500 1611 500 539 499 538 500 1611 499 539 499 1611 499 1611 500 1611 499 539 499 1611 500 1611 500 539 499 35437 8784 4252 500 1611 500 1612 500 539 500 539 500 539 500 539 500 539 500 1611 500 1612 499 539 500 1612 500 539 500 1612 499 539 500 1612 500 539 500 1612 499 539 500 539 500 539 499 1612 499 540 499 539 500 1612 499 539 500 1612 499 1613 499 1612 499 539 500 1612 500 1612 500 539 500 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 06 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 09 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 1A 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 00 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 00 00 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9035 4437 563 548 563 548 563 522 594 1645 591 1639 592 518 593 548 563 552 563 1640 592 548 563 553 562 1668 564 524 592 1642 594 1674 562 1673 563 1639 593 548 563 552 564 1669 562 548 563 520 615 529 586 1645 587 529 587 1650 586 1646 586 529 586 1650 586 1649 587 1646 586 524 587 524 587 524 587 524 587 525 643 467 644 440 671 467 644 472 643 1592 644 1593 643 1593 642 1594 641 1594 587 1649 585 1651 563 1682 562 14430 9008 2205 562 +# +name: Vol_up +type: parsed +protocol: NECext +address: 84 F4 00 00 +command: 2C D3 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 84 F4 00 00 +command: 2F D0 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 4F 50 00 00 +command: 0F F0 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 12 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 12 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 06 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 00 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 04 B1 00 00 +command: 58 A7 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 04 B1 00 00 +command: 58 A7 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9107 4376 681 1573 681 472 655 472 654 474 652 475 652 476 651 476 652 476 651 476 651 1604 651 1604 651 1604 651 1603 652 1604 651 1604 651 1604 651 1604 650 476 651 477 650 477 650 476 651 477 651 1604 650 476 651 477 650 1604 651 1604 650 1604 651 1604 650 1604 651 477 650 1604 650 39498 9079 2178 651 +# +name: Power +type: parsed +protocol: NECext +address: 8B CA 00 00 +command: 12 ED 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 8B CA 00 00 +command: 12 ED 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 8B CA 00 00 +command: 44 BB 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 8B CA 00 00 +command: 46 B9 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 8B CA 00 00 +command: 11 EE 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 81 03 00 00 +command: F0 0F 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 40 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 01 FE 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 40 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 01 FE 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 10 EF 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 0C F3 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 6A 95 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 11 00 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 51 AE 00 00 +# +name: Pause +type: parsed +protocol: NECext +address: 00 30 00 00 +command: A8 57 00 00 +# +name: Play +type: parsed +protocol: NECext +address: 00 30 00 00 +command: A9 56 00 00 +# +name: Play +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 5E A1 00 00 +# +name: Pause +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 5B A4 00 00 +# +name: Play +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 93 00 00 00 +# +name: Pause +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 93 00 00 00 +# +name: Play +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 15 00 00 00 +# +name: Pause +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 15 00 00 00 +# +name: Play +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 18 E7 00 00 +# +name: Play +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 8981 4411 532 1616 557 1592 557 465 556 465 556 466 555 467 554 468 554 1595 554 467 554 468 554 1595 554 467 580 1569 581 1568 581 1568 581 1569 580 441 581 1569 580 442 580 1570 579 1594 555 467 555 443 579 442 580 1594 554 467 555 1594 555 467 555 468 554 1595 554 1595 528 1620 529 42169 9008 2106 531 +# +name: Pause +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 8981 4411 532 1616 557 1592 557 465 556 465 556 466 555 467 554 468 554 1595 554 467 554 468 554 1595 554 467 580 1569 581 1568 581 1568 581 1569 580 441 581 1569 580 442 580 1570 579 1594 555 467 555 443 579 442 580 1594 554 467 555 1594 555 467 555 468 554 1595 554 1595 528 1620 529 42169 9008 2106 531 +# +name: Play +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 41 00 00 00 +# +name: Pause +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 41 00 00 00 +# +name: Play +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 03 00 00 00 +# +name: Pause +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 03 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 17 E8 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 17 E8 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 4F 50 00 00 +command: 07 F8 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 4F 50 00 00 +command: 0A F5 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 293 1801 296 753 295 1801 296 1801 296 752 296 754 294 1801 296 1800 297 752 296 1802 295 752 296 1801 296 753 295 1800 297 752 296 42709 296 1800 297 753 295 1800 297 1800 297 753 295 1802 295 753 295 753 295 1801 296 753 295 1801 296 754 294 1802 295 753 295 1801 296 42694 295 1800 297 752 296 1803 294 1803 294 753 295 753 295 1801 296 1802 295 752 296 1802 295 752 296 1801 296 753 295 1802 295 753 295 42709 295 1802 295 753 295 1803 294 1801 296 753 295 1802 295 752 296 752 296 1801 296 752 296 1803 294 754 294 1803 294 754 294 1804 293 42694 294 1802 294 755 293 1803 294 1804 268 779 269 779 269 1828 269 1828 269 780 268 1829 268 778 270 1829 323 725 268 1829 268 781 324 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 293 1801 296 753 295 1801 296 1801 296 752 296 754 294 1801 296 1800 297 752 296 1802 295 752 296 1801 296 753 295 1800 297 752 296 42709 296 1800 297 753 295 1800 297 1800 297 753 295 1802 295 753 295 753 295 1801 296 753 295 1801 296 754 294 1802 295 753 295 1801 296 42694 295 1800 297 752 296 1803 294 1803 294 753 295 753 295 1801 296 1802 295 752 296 1802 295 752 296 1801 296 753 295 1802 295 753 295 42709 295 1802 295 753 295 1803 294 1801 296 753 295 1802 295 752 296 752 296 1801 296 752 296 1803 294 754 294 1803 294 754 294 1804 293 42694 294 1802 294 755 293 1803 294 1804 268 779 269 779 269 1828 269 1828 269 780 268 1829 268 778 270 1829 323 725 268 1829 268 781 324 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 363 1732 365 685 363 1734 363 1735 362 686 362 1735 362 687 361 685 362 1735 363 686 267 1830 362 1734 363 686 268 1830 361 687 267 42739 267 1829 268 780 268 1830 267 1829 268 781 267 781 267 1832 265 1830 267 780 268 1830 267 781 267 780 268 1830 267 781 267 1830 267 42723 267 1830 267 781 362 1735 267 1829 268 781 267 1830 267 782 266 780 268 1830 267 781 267 1831 266 1830 267 781 267 1829 268 782 266 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 270 1825 272 780 268 1827 349 1747 350 699 349 698 351 698 350 1748 350 698 350 1748 349 699 349 697 351 699 349 1746 351 698 350 44740 349 1745 352 698 350 1747 350 1747 350 698 350 1747 355 1742 355 692 356 1742 355 694 355 1743 354 1742 355 1742 355 694 354 1742 355 40555 355 1742 355 693 355 1742 355 1743 354 693 355 694 354 693 355 1743 354 693 355 1742 355 693 355 692 357 693 355 1741 356 694 354 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 353 1742 355 693 355 1742 355 1742 355 693 355 1744 353 694 354 1743 354 693 355 1743 354 694 354 693 355 694 354 1742 355 695 353 43687 354 1743 354 696 352 1744 353 1744 353 694 354 695 353 1742 355 694 354 1743 354 694 354 1743 354 1742 355 1742 355 694 354 1744 353 41606 351 1745 352 696 352 1746 351 1746 351 697 351 1747 350 696 352 1745 352 698 350 1746 351 698 350 696 352 698 350 1746 351 699 349 +# +name: Power +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 02 00 00 00 +# +name: Mute +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: D1 00 00 00 diff --git a/assets/resources/infrared/assets/tv.ir b/applications/main/infrared/resources/infrared/assets/tv.ir similarity index 100% rename from assets/resources/infrared/assets/tv.ir rename to applications/main/infrared/resources/infrared/assets/tv.ir diff --git a/assets/resources/infrared/remote/Roku.txt b/applications/main/infrared/resources/infrared/remote/Roku.txt similarity index 100% rename from assets/resources/infrared/remote/Roku.txt rename to applications/main/infrared/resources/infrared/remote/Roku.txt diff --git a/assets/resources/infrared/remote/SamsungGeneric.txt b/applications/main/infrared/resources/infrared/remote/SamsungGeneric.txt similarity index 100% rename from assets/resources/infrared/remote/SamsungGeneric.txt rename to applications/main/infrared/resources/infrared/remote/SamsungGeneric.txt diff --git a/assets/resources/infrared/remote/example_remote.txt b/applications/main/infrared/resources/infrared/remote/example_remote.txt similarity index 100% rename from assets/resources/infrared/remote/example_remote.txt rename to applications/main/infrared/resources/infrared/remote/example_remote.txt diff --git a/applications/main/infrared/scenes/common/infrared_scene_universal_common.c b/applications/main/infrared/scenes/common/infrared_scene_universal_common.c index 96f28cc48..4967d1956 100644 --- a/applications/main/infrared/scenes/common/infrared_scene_universal_common.c +++ b/applications/main/infrared/scenes/common/infrared_scene_universal_common.c @@ -1,20 +1,21 @@ -#include "../../infrared_i.h" +#include "../../infrared_app_i.h" #include void infrared_scene_universal_common_item_callback(void* context, uint32_t index) { - Infrared* infrared = context; + InfraredApp* infrared = context; uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypeButtonSelected, index); view_dispatcher_send_custom_event(infrared->view_dispatcher, event); } static void infrared_scene_universal_common_progress_back_callback(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypeBackPressed, -1); view_dispatcher_send_custom_event(infrared->view_dispatcher, event); } -static void infrared_scene_universal_common_show_popup(Infrared* infrared, uint32_t record_count) { +static void + infrared_scene_universal_common_show_popup(InfraredApp* infrared, uint32_t record_count) { ViewStack* view_stack = infrared->view_stack; InfraredProgressView* progress = infrared->progress; infrared_progress_view_set_progress_total(progress, record_count); @@ -24,7 +25,7 @@ static void infrared_scene_universal_common_show_popup(Infrared* infrared, uint3 infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend); } -static void infrared_scene_universal_common_hide_popup(Infrared* infrared) { +static void infrared_scene_universal_common_hide_popup(InfraredApp* infrared) { ViewStack* view_stack = infrared->view_stack; InfraredProgressView* progress = infrared->progress; view_stack_remove_view(view_stack, infrared_progress_view_get_view(progress)); @@ -32,12 +33,12 @@ static void infrared_scene_universal_common_hide_popup(Infrared* infrared) { } void infrared_scene_universal_common_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_stack_add_view(infrared->view_stack, button_panel_get_view(infrared->button_panel)); } bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; InfraredBruteForce* brute_force = infrared->brute_force; bool consumed = false; @@ -84,7 +85,7 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e } void infrared_scene_universal_common_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; view_stack_remove_view(infrared->view_stack, button_panel_get_view(button_panel)); infrared_brute_force_reset(infrared->brute_force); diff --git a/applications/main/infrared/scenes/infrared_scene_ask_back.c b/applications/main/infrared/scenes/infrared_scene_ask_back.c index 77fc97f98..f97a38bb0 100644 --- a/applications/main/infrared/scenes/infrared_scene_ask_back.c +++ b/applications/main/infrared/scenes/infrared_scene_ask_back.c @@ -1,12 +1,12 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" static void infrared_scene_dialog_result_callback(DialogExResult result, void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event(infrared->view_dispatcher, result); } void infrared_scene_ask_back_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; DialogEx* dialog_ex = infrared->dialog_ex; if(infrared->app_state.is_learning_new_remote) { @@ -28,7 +28,7 @@ void infrared_scene_ask_back_on_enter(void* context) { } bool infrared_scene_ask_back_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; bool consumed = false; @@ -54,6 +54,6 @@ bool infrared_scene_ask_back_on_event(void* context, SceneManagerEvent event) { } void infrared_scene_ask_back_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; dialog_ex_reset(infrared->dialog_ex); } diff --git a/applications/main/infrared/scenes/infrared_scene_ask_retry.c b/applications/main/infrared/scenes/infrared_scene_ask_retry.c index 602e470c7..365ed5c81 100644 --- a/applications/main/infrared/scenes/infrared_scene_ask_retry.c +++ b/applications/main/infrared/scenes/infrared_scene_ask_retry.c @@ -1,12 +1,12 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" static void infrared_scene_dialog_result_callback(DialogExResult result, void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event(infrared->view_dispatcher, result); } void infrared_scene_ask_retry_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; DialogEx* dialog_ex = infrared->dialog_ex; dialog_ex_set_header(dialog_ex, "Retry Reading?", 64, 11, AlignCenter, AlignTop); @@ -23,7 +23,7 @@ void infrared_scene_ask_retry_on_enter(void* context) { } bool infrared_scene_ask_retry_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; bool consumed = false; @@ -43,6 +43,6 @@ bool infrared_scene_ask_retry_on_event(void* context, SceneManagerEvent event) { } void infrared_scene_ask_retry_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; dialog_ex_reset(infrared->dialog_ex); } diff --git a/applications/main/infrared/scenes/infrared_scene_debug.c b/applications/main/infrared/scenes/infrared_scene_debug.c index 204978697..adffbc83a 100644 --- a/applications/main/infrared/scenes/infrared_scene_debug.c +++ b/applications/main/infrared/scenes/infrared_scene_debug.c @@ -1,7 +1,7 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" void infrared_scene_debug_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; InfraredWorker* worker = infrared->worker; infrared_worker_rx_set_received_signal_callback( @@ -14,16 +14,16 @@ void infrared_scene_debug_on_enter(void* context) { } bool infrared_scene_debug_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == InfraredCustomEventTypeSignalReceived) { InfraredDebugView* debug_view = infrared->debug_view; - InfraredSignal* signal = infrared->received_signal; + InfraredSignal* signal = infrared->current_signal; if(infrared_signal_is_raw(signal)) { - InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + const InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); infrared_debug_view_set_text(debug_view, "RAW\n%d samples\n", raw->timings_size); printf("RAW, %zu samples:\r\n", raw->timings_size); @@ -33,7 +33,7 @@ bool infrared_scene_debug_on_event(void* context, SceneManagerEvent event) { printf("\r\n"); } else { - InfraredMessage* message = infrared_signal_get_message(signal); + const InfraredMessage* message = infrared_signal_get_message(signal); infrared_debug_view_set_text( debug_view, "%s\nA:0x%0*lX\nC:0x%0*lX\n%s\n", @@ -61,7 +61,7 @@ bool infrared_scene_debug_on_event(void* context, SceneManagerEvent event) { } void infrared_scene_debug_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; InfraredWorker* worker = infrared->worker; infrared_worker_rx_stop(worker); infrared_worker_rx_enable_blink_on_receiving(worker, false); diff --git a/applications/main/infrared/scenes/infrared_scene_debug_settings.c b/applications/main/infrared/scenes/infrared_scene_debug_settings.c index bef666275..16bd158af 100644 --- a/applications/main/infrared/scenes/infrared_scene_debug_settings.c +++ b/applications/main/infrared/scenes/infrared_scene_debug_settings.c @@ -1,4 +1,4 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include uint8_t value_index_ir; @@ -35,12 +35,12 @@ static void infrared_scene_debug_settings_power_changed(VariableItem* item) { } static void infrared_debug_settings_start_var_list_enter_callback(void* context, uint32_t index) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event(infrared->view_dispatcher, index); } void infrared_scene_debug_settings_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; VariableItemList* variable_item_list = infrared->variable_item_list; @@ -72,7 +72,7 @@ void infrared_scene_debug_settings_on_enter(void* context) { } bool infrared_scene_debug_settings_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; UNUSED(infrared); UNUSED(event); @@ -80,6 +80,6 @@ bool infrared_scene_debug_settings_on_event(void* context, SceneManagerEvent eve } void infrared_scene_debug_settings_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; variable_item_list_reset(infrared->variable_item_list); } diff --git a/applications/main/infrared/scenes/infrared_scene_edit.c b/applications/main/infrared/scenes/infrared_scene_edit.c index 02bba7a3f..c22e95396 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit.c +++ b/applications/main/infrared/scenes/infrared_scene_edit.c @@ -1,4 +1,4 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" typedef enum { SubmenuIndexAddButton, @@ -10,12 +10,12 @@ typedef enum { } SubmenuIndex; static void infrared_scene_edit_submenu_callback(void* context, uint32_t index) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event(infrared->view_dispatcher, index); } void infrared_scene_edit_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Submenu* submenu = infrared->submenu; SceneManager* scene_manager = infrared->scene_manager; @@ -64,7 +64,7 @@ void infrared_scene_edit_on_enter(void* context) { } bool infrared_scene_edit_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; bool consumed = false; @@ -106,6 +106,6 @@ bool infrared_scene_edit_on_event(void* context, SceneManagerEvent event) { } void infrared_scene_edit_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; submenu_reset(infrared->submenu); } diff --git a/applications/main/infrared/scenes/infrared_scene_edit_button_select.c b/applications/main/infrared/scenes/infrared_scene_edit_button_select.c index 5f5a1d8fa..3fd59b579 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_button_select.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_button_select.c @@ -1,12 +1,12 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" static void infrared_scene_edit_button_select_submenu_callback(void* context, uint32_t index) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event(infrared->view_dispatcher, index); } void infrared_scene_edit_button_select_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Submenu* submenu = infrared->submenu; InfraredRemote* remote = infrared->remote; InfraredAppState* app_state = &infrared->app_state; @@ -16,16 +16,16 @@ void infrared_scene_edit_button_select_on_enter(void* context) { "Delete Button:"; submenu_set_header(submenu, header); - const size_t button_count = infrared_remote_get_button_count(remote); + const size_t button_count = infrared_remote_get_signal_count(remote); for(size_t i = 0; i < button_count; ++i) { - InfraredRemoteButton* button = infrared_remote_get_button(remote, i); submenu_add_item( submenu, - infrared_remote_button_get_name(button), + infrared_remote_get_signal_name(remote, i), i, infrared_scene_edit_button_select_submenu_callback, context); } + if(button_count && app_state->current_button_index != InfraredButtonIndexNone) { submenu_set_selected_item(submenu, app_state->current_button_index); app_state->current_button_index = InfraredButtonIndexNone; @@ -35,7 +35,7 @@ void infrared_scene_edit_button_select_on_enter(void* context) { } bool infrared_scene_edit_button_select_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; InfraredAppState* app_state = &infrared->app_state; SceneManager* scene_manager = infrared->scene_manager; bool consumed = false; @@ -48,7 +48,7 @@ bool infrared_scene_edit_button_select_on_event(void* context, SceneManagerEvent } else if(edit_mode == InfraredEditModeDelete) { scene_manager_next_scene(scene_manager, InfraredSceneEditDelete); } else { - furi_assert(0); + furi_crash(); } consumed = true; } @@ -57,6 +57,6 @@ bool infrared_scene_edit_button_select_on_event(void* context, SceneManagerEvent } void infrared_scene_edit_button_select_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; submenu_reset(infrared->submenu); } diff --git a/applications/main/infrared/scenes/infrared_scene_edit_delete.c b/applications/main/infrared/scenes/infrared_scene_edit_delete.c index 4dfc054fb..0cb88efdb 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_delete.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_delete.c @@ -1,42 +1,49 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" static void infrared_scene_edit_delete_dialog_result_callback(DialogExResult result, void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event(infrared->view_dispatcher, result); } void infrared_scene_edit_delete_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; DialogEx* dialog_ex = infrared->dialog_ex; InfraredRemote* remote = infrared->remote; const InfraredEditTarget edit_target = infrared->app_state.edit_target; if(edit_target == InfraredEditTargetButton) { - int32_t current_button_index = infrared->app_state.current_button_index; - furi_assert(current_button_index != InfraredButtonIndexNone); - dialog_ex_set_header(dialog_ex, "Delete Button?", 64, 0, AlignCenter, AlignTop); - InfraredRemoteButton* current_button = - infrared_remote_get_button(remote, current_button_index); - InfraredSignal* signal = infrared_remote_button_get_signal(current_button); - if(infrared_signal_is_raw(signal)) { - const InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + const int32_t current_button_index = infrared->app_state.current_button_index; + furi_check(current_button_index != InfraredButtonIndexNone); + + if(!infrared_remote_load_signal(remote, infrared->current_signal, current_button_index)) { + infrared_show_error_message( + infrared, + "Failed to load\n\"%s\"", + infrared_remote_get_signal_name(remote, current_button_index)); + scene_manager_previous_scene(infrared->scene_manager); + return; + } + + if(infrared_signal_is_raw(infrared->current_signal)) { + const InfraredRawSignal* raw = + infrared_signal_get_raw_signal(infrared->current_signal); infrared_text_store_set( infrared, 0, - "%s\nRAW\n%ld samples", - infrared_remote_button_get_name(current_button), + "%s\nRAW\n%zu samples", + infrared_remote_get_signal_name(remote, current_button_index), raw->timings_size); } else { - const InfraredMessage* message = infrared_signal_get_message(signal); + const InfraredMessage* message = infrared_signal_get_message(infrared->current_signal); infrared_text_store_set( infrared, 0, "%s\n%s\nA=0x%0*lX C=0x%0*lX", - infrared_remote_button_get_name(current_button), + infrared_remote_get_signal_name(remote, current_button_index), infrared_get_protocol_name(message->protocol), ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4), message->address, @@ -49,11 +56,11 @@ void infrared_scene_edit_delete_on_enter(void* context) { infrared_text_store_set( infrared, 0, - "%s\n with %lu buttons", + "%s\n with %zu buttons", infrared_remote_get_name(remote), - infrared_remote_get_button_count(remote)); + infrared_remote_get_signal_count(remote)); } else { - furi_assert(0); + furi_crash(); } dialog_ex_set_text(dialog_ex, infrared->text_store[0], 64, 31, AlignCenter, AlignCenter); @@ -63,11 +70,14 @@ void infrared_scene_edit_delete_on_enter(void* context) { dialog_ex_set_result_callback(dialog_ex, infrared_scene_edit_delete_dialog_result_callback); dialog_ex_set_context(dialog_ex, context); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx); + view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationHorizontal); + view_stack_add_view(infrared->view_stack, dialog_ex_get_view(infrared->dialog_ex)); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); } bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; bool consumed = false; @@ -83,18 +93,24 @@ bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event) if(edit_target == InfraredEditTargetButton) { furi_assert(app_state->current_button_index != InfraredButtonIndexNone); - success = infrared_remote_delete_button(remote, app_state->current_button_index); + infrared_show_loading_popup(infrared, true); + success = infrared_remote_delete_signal(remote, app_state->current_button_index); + infrared_show_loading_popup(infrared, false); app_state->current_button_index = InfraredButtonIndexNone; } else if(edit_target == InfraredEditTargetRemote) { success = infrared_remote_remove(remote); app_state->current_button_index = InfraredButtonIndexNone; } else { - furi_assert(0); + furi_crash(); } if(success) { scene_manager_next_scene(scene_manager, InfraredSceneEditDeleteDone); } else { + infrared_show_error_message( + infrared, + "Failed to\ndelete %s", + edit_target == InfraredEditTargetButton ? "button" : "file"); const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; scene_manager_search_and_switch_to_previous_scene_one_of( scene_manager, possible_scenes, COUNT_OF(possible_scenes)); @@ -107,6 +123,6 @@ bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event) } void infrared_scene_edit_delete_on_exit(void* context) { - Infrared* infrared = context; - UNUSED(infrared); + InfraredApp* infrared = context; + view_stack_remove_view(infrared->view_stack, dialog_ex_get_view(infrared->dialog_ex)); } diff --git a/applications/main/infrared/scenes/infrared_scene_edit_delete_done.c b/applications/main/infrared/scenes/infrared_scene_edit_delete_done.c index 49a299d2a..9205db4c4 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_delete_done.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_delete_done.c @@ -1,7 +1,7 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" void infrared_scene_edit_delete_done_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Popup* popup = infrared->popup; popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); @@ -16,7 +16,7 @@ void infrared_scene_edit_delete_done_on_enter(void* context) { } bool infrared_scene_edit_delete_done_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; bool consumed = false; @@ -33,7 +33,7 @@ bool infrared_scene_edit_delete_done_on_event(void* context, SceneManagerEvent e view_dispatcher_stop(infrared->view_dispatcher); } } else { - furi_assert(0); + furi_crash(); } consumed = true; } @@ -43,6 +43,6 @@ bool infrared_scene_edit_delete_done_on_event(void* context, SceneManagerEvent e } void infrared_scene_edit_delete_done_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; UNUSED(infrared); } diff --git a/applications/main/infrared/scenes/infrared_scene_edit_move.c b/applications/main/infrared/scenes/infrared_scene_edit_move.c index 370c352db..4959a8310 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_move.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_move.c @@ -1,44 +1,69 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" -static void infrared_scene_move_button(uint32_t index_old, uint32_t index_new, void* context) { - InfraredRemote* remote = context; - furi_assert(remote); - infrared_remote_move_button(remote, index_old, index_new); -} +static void infrared_scene_edit_move_button_callback( + uint32_t index_old, + uint32_t index_new, + void* context) { + InfraredApp* infrared = context; + furi_assert(infrared); -static const char* infrared_scene_get_btn_name(uint32_t index, void* context) { - InfraredRemote* remote = context; - furi_assert(remote); - InfraredRemoteButton* button = infrared_remote_get_button(remote, index); - return (infrared_remote_button_get_name(button)); + infrared->app_state.prev_button_index = index_old; + infrared->app_state.current_button_index = index_new; + + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeButtonSelected); } void infrared_scene_edit_move_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; InfraredRemote* remote = infrared->remote; - infrared_move_view_set_callback(infrared->move_view, infrared_scene_move_button); + for(size_t i = 0; i < infrared_remote_get_signal_count(remote); ++i) { + infrared_move_view_add_item( + infrared->move_view, infrared_remote_get_signal_name(remote, i)); + } - uint32_t btn_count = infrared_remote_get_button_count(remote); - infrared_move_view_list_init( - infrared->move_view, btn_count, infrared_scene_get_btn_name, remote); - infrared_move_view_list_update(infrared->move_view); + infrared_move_view_set_callback( + infrared->move_view, infrared_scene_edit_move_button_callback, infrared); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewMove); + view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationHorizontal); + view_stack_add_view(infrared->view_stack, infrared_move_view_get_view(infrared->move_view)); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); } bool infrared_scene_edit_move_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; bool consumed = false; - UNUSED(event); - UNUSED(infrared); + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypeButtonSelected) { + infrared_show_loading_popup(infrared, true); + const bool button_moved = infrared_remote_move_signal( + infrared->remote, + infrared->app_state.prev_button_index, + infrared->app_state.current_button_index); + infrared_show_loading_popup(infrared, false); + + if(!button_moved) { + infrared_show_error_message( + infrared, + "Failed to move\n\"%s\"", + infrared_remote_get_signal_name( + infrared->remote, infrared->app_state.current_button_index)); + scene_manager_search_and_switch_to_previous_scene( + infrared->scene_manager, InfraredSceneRemoteList); + } + + consumed = true; + } + } return consumed; } void infrared_scene_edit_move_on_exit(void* context) { - Infrared* infrared = context; - InfraredRemote* remote = infrared->remote; - infrared_remote_store(remote); + InfraredApp* infrared = context; + view_stack_remove_view(infrared->view_stack, infrared_move_view_get_view(infrared->move_view)); + infrared_move_view_reset(infrared->move_view); } diff --git a/applications/main/infrared/scenes/infrared_scene_edit_rename.c b/applications/main/infrared/scenes/infrared_scene_edit_rename.c index a2199215d..178690926 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_rename.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_rename.c @@ -1,10 +1,10 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include #include void infrared_scene_edit_rename_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; InfraredRemote* remote = infrared->remote; TextInput* text_input = infrared->text_input; size_t enter_name_length = 0; @@ -14,14 +14,12 @@ void infrared_scene_edit_rename_on_enter(void* context) { text_input_set_header_text(text_input, "Name the button"); const int32_t current_button_index = infrared->app_state.current_button_index; - furi_assert(current_button_index != InfraredButtonIndexNone); + furi_check(current_button_index != InfraredButtonIndexNone); - InfraredRemoteButton* current_button = - infrared_remote_get_button(remote, current_button_index); enter_name_length = INFRARED_MAX_BUTTON_NAME_LENGTH; strncpy( infrared->text_store[0], - infrared_remote_button_get_name(current_button), + infrared_remote_get_signal_name(remote, current_button_index), enter_name_length); } else if(edit_target == InfraredEditTargetRemote) { @@ -44,7 +42,7 @@ void infrared_scene_edit_rename_on_enter(void* context) { furi_string_free(folder_path); } else { - furi_assert(0); + furi_crash(); } text_input_set_result_callback( @@ -55,11 +53,14 @@ void infrared_scene_edit_rename_on_enter(void* context) { enter_name_length, false); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewTextInput); + view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationHorizontal); + view_stack_add_view(infrared->view_stack, text_input_get_view(infrared->text_input)); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); } bool infrared_scene_edit_rename_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; InfraredRemote* remote = infrared->remote; SceneManager* scene_manager = infrared->scene_manager; InfraredAppState* app_state = &infrared->app_state; @@ -72,18 +73,24 @@ bool infrared_scene_edit_rename_on_event(void* context, SceneManagerEvent event) if(edit_target == InfraredEditTargetButton) { const int32_t current_button_index = app_state->current_button_index; furi_assert(current_button_index != InfraredButtonIndexNone); - success = infrared_remote_rename_button( - remote, infrared->text_store[0], current_button_index); + infrared_show_loading_popup(infrared, true); + success = infrared_remote_rename_signal( + remote, current_button_index, infrared->text_store[0]); + infrared_show_loading_popup(infrared, false); app_state->current_button_index = InfraredButtonIndexNone; } else if(edit_target == InfraredEditTargetRemote) { success = infrared_rename_current_remote(infrared, infrared->text_store[0]); } else { - furi_assert(0); + furi_crash(); } if(success) { scene_manager_next_scene(scene_manager, InfraredSceneEditRenameDone); } else { + infrared_show_error_message( + infrared, + "Failed to\nrename %s", + edit_target == InfraredEditTargetButton ? "button" : "file"); scene_manager_search_and_switch_to_previous_scene( scene_manager, InfraredSceneRemoteList); } @@ -95,9 +102,11 @@ bool infrared_scene_edit_rename_on_event(void* context, SceneManagerEvent event) } void infrared_scene_edit_rename_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; TextInput* text_input = infrared->text_input; + view_stack_remove_view(infrared->view_stack, text_input_get_view(text_input)); + void* validator_context = text_input_get_validator_callback_context(text_input); text_input_set_validator(text_input, NULL, NULL); diff --git a/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c b/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c index 6c7096e17..35f515989 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c @@ -1,7 +1,7 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" void infrared_scene_edit_rename_done_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Popup* popup = infrared->popup; popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); @@ -16,7 +16,7 @@ void infrared_scene_edit_rename_done_on_enter(void* context) { } bool infrared_scene_edit_rename_done_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -33,6 +33,6 @@ bool infrared_scene_edit_rename_done_on_event(void* context, SceneManagerEvent e } void infrared_scene_edit_rename_done_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; UNUSED(infrared); } diff --git a/applications/main/infrared/scenes/infrared_scene_error_databases.c b/applications/main/infrared/scenes/infrared_scene_error_databases.c index 4ed4dee58..f51f83f25 100644 --- a/applications/main/infrared/scenes/infrared_scene_error_databases.c +++ b/applications/main/infrared/scenes/infrared_scene_error_databases.c @@ -1,7 +1,7 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" void infrared_scene_error_databases_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Popup* popup = infrared->popup; popup_set_icon(popup, 5, 11, &I_SDQuestion_35x43); @@ -16,7 +16,7 @@ void infrared_scene_error_databases_on_enter(void* context) { } bool infrared_scene_error_databases_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -31,7 +31,7 @@ bool infrared_scene_error_databases_on_event(void* context, SceneManagerEvent ev } void infrared_scene_error_databases_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; popup_reset(infrared->popup); infrared_play_notification_message(infrared, InfraredNotificationMessageYellowOff); } diff --git a/applications/main/infrared/scenes/infrared_scene_learn.c b/applications/main/infrared/scenes/infrared_scene_learn.c index 46646c6d6..bcd0a2cd0 100644 --- a/applications/main/infrared/scenes/infrared_scene_learn.c +++ b/applications/main/infrared/scenes/infrared_scene_learn.c @@ -1,8 +1,8 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include void infrared_scene_learn_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Popup* popup = infrared->popup; InfraredWorker* worker = infrared->worker; @@ -21,7 +21,7 @@ void infrared_scene_learn_on_enter(void* context) { } bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -37,7 +37,7 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) { } void infrared_scene_learn_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Popup* popup = infrared->popup; infrared_worker_rx_set_received_signal_callback(infrared->worker, NULL, NULL); infrared_worker_rx_stop(infrared->worker); diff --git a/applications/main/infrared/scenes/infrared_scene_learn_done.c b/applications/main/infrared/scenes/infrared_scene_learn_done.c index 48431c5db..846370c5c 100644 --- a/applications/main/infrared/scenes/infrared_scene_learn_done.c +++ b/applications/main/infrared/scenes/infrared_scene_learn_done.c @@ -1,7 +1,7 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" void infrared_scene_learn_done_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Popup* popup = infrared->popup; popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); @@ -20,7 +20,7 @@ void infrared_scene_learn_done_on_enter(void* context) { } bool infrared_scene_learn_done_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -37,7 +37,7 @@ bool infrared_scene_learn_done_on_event(void* context, SceneManagerEvent event) } void infrared_scene_learn_done_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; infrared->app_state.is_learning_new_remote = false; popup_set_header(infrared->popup, NULL, 0, 0, AlignLeft, AlignTop); } diff --git a/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c b/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c index 104a4cb7b..be46a8691 100644 --- a/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c +++ b/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c @@ -1,16 +1,16 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include void infrared_scene_learn_enter_name_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; TextInput* text_input = infrared->text_input; - InfraredSignal* signal = infrared->received_signal; + InfraredSignal* signal = infrared->current_signal; if(infrared_signal_is_raw(signal)) { - InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); - infrared_text_store_set(infrared, 0, "RAW_%d", raw->timings_size); + const InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + infrared_text_store_set(infrared, 0, "RAW_%zu", raw->timings_size); } else { - InfraredMessage* message = infrared_signal_get_message(signal); + const InfraredMessage* message = infrared_signal_get_message(signal); infrared_text_store_set( infrared, 0, @@ -28,31 +28,32 @@ void infrared_scene_learn_enter_name_on_enter(void* context) { infrared->text_store[0], INFRARED_MAX_BUTTON_NAME_LENGTH, true); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewTextInput); } bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; - InfraredSignal* signal = infrared->received_signal; + InfraredApp* infrared = context; + InfraredSignal* signal = infrared->current_signal; SceneManager* scene_manager = infrared->scene_manager; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == InfraredCustomEventTypeTextEditDone) { - bool success = false; - if(infrared->app_state.is_learning_new_remote) { - success = - infrared_add_remote_with_button(infrared, infrared->text_store[0], signal); - } else { - success = - infrared_remote_add_button(infrared->remote, infrared->text_store[0], signal); - } + const char* signal_name = infrared->text_store[0]; + const bool success = + infrared->app_state.is_learning_new_remote ? + infrared_add_remote_with_button(infrared, signal_name, signal) : + infrared_remote_append_signal(infrared->remote, signal, signal_name); if(success) { scene_manager_next_scene(scene_manager, InfraredSceneLearnDone); dolphin_deed(DolphinDeedIrSave); } else { - dialog_message_show_storage_error(infrared->dialogs, "Failed to save file"); + infrared_show_error_message( + infrared, + "Failed to\n%s", + infrared->app_state.is_learning_new_remote ? "create file" : "add signal"); const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; scene_manager_search_and_switch_to_previous_scene_one_of( scene_manager, possible_scenes, COUNT_OF(possible_scenes)); @@ -65,6 +66,6 @@ bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent e } void infrared_scene_learn_enter_name_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; UNUSED(infrared); } diff --git a/applications/main/infrared/scenes/infrared_scene_learn_success.c b/applications/main/infrared/scenes/infrared_scene_learn_success.c index 469d4de9e..deb54bb5e 100644 --- a/applications/main/infrared/scenes/infrared_scene_learn_success.c +++ b/applications/main/infrared/scenes/infrared_scene_learn_success.c @@ -1,26 +1,26 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" static void infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event(infrared->view_dispatcher, result); } void infrared_scene_learn_success_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; DialogEx* dialog_ex = infrared->dialog_ex; - InfraredSignal* signal = infrared->received_signal; + InfraredSignal* signal = infrared->current_signal; infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn); if(infrared_signal_is_raw(signal)) { - InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + const InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter); - infrared_text_store_set(infrared, 0, "%d samples", raw->timings_size); + infrared_text_store_set(infrared, 0, "%zu samples", raw->timings_size); dialog_ex_set_text(dialog_ex, infrared->text_store[0], 75, 23, AlignLeft, AlignTop); } else { - InfraredMessage* message = infrared_signal_get_message(signal); + const InfraredMessage* message = infrared_signal_get_message(signal); uint8_t addr_digits = ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4); uint8_t cmd_digits = @@ -56,7 +56,7 @@ void infrared_scene_learn_success_on_enter(void* context) { } bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; const bool is_transmitter_idle = !infrared->app_state.is_transmitting; bool consumed = false; @@ -84,7 +84,7 @@ 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); + infrared_tx_start(infrared); consumed = true; } else if(event.event == DialogExReleaseCenter) { infrared_tx_stop(infrared); @@ -96,7 +96,7 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even } void infrared_scene_learn_success_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; dialog_ex_reset(infrared->dialog_ex); infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); } diff --git a/applications/main/infrared/scenes/infrared_scene_remote.c b/applications/main/infrared/scenes/infrared_scene_remote.c index c1f5b6627..6c1d1ec4e 100644 --- a/applications/main/infrared/scenes/infrared_scene_remote.c +++ b/applications/main/infrared/scenes/infrared_scene_remote.c @@ -1,14 +1,14 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" typedef enum { - ButtonIndexPlus = -2, + ButtonIndexLearn = -2, ButtonIndexEdit = -1, ButtonIndexNA = 0, } ButtonIndex; static void infrared_scene_remote_button_menu_callback(void* context, int32_t index, InputType type) { - Infrared* infrared = context; + InfraredApp* infrared = context; uint16_t custom_type; if(type == InputTypePress) { @@ -26,17 +26,15 @@ static void } void infrared_scene_remote_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; InfraredRemote* remote = infrared->remote; ButtonMenu* button_menu = infrared->button_menu; SceneManager* scene_manager = infrared->scene_manager; - 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); + for(size_t i = 0; i < infrared_remote_get_signal_count(remote); ++i) { button_menu_add_item( button_menu, - infrared_remote_button_get_name(button), + infrared_remote_get_signal_name(remote, i), i, infrared_scene_remote_button_menu_callback, ButtonMenuItemTypeCommon, @@ -46,7 +44,7 @@ void infrared_scene_remote_on_enter(void* context) { button_menu_add_item( button_menu, "+", - ButtonIndexPlus, + ButtonIndexLearn, infrared_scene_remote_button_menu_callback, ButtonMenuItemTypeControl, context); @@ -68,7 +66,7 @@ void infrared_scene_remote_on_enter(void* context) { } bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; const bool is_transmitter_idle = !infrared->app_state.is_transmitting; bool consumed = false; @@ -97,7 +95,7 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { if(is_transmitter_idle) { scene_manager_set_scene_state( scene_manager, InfraredSceneRemote, (unsigned)button_index); - if(button_index == ButtonIndexPlus) { + if(button_index == ButtonIndexLearn) { infrared->app_state.is_learning_new_remote = false; scene_manager_next_scene(scene_manager, InfraredSceneLearn); consumed = true; @@ -116,6 +114,6 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { } void infrared_scene_remote_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; button_menu_reset(infrared->button_menu); } diff --git a/applications/main/infrared/scenes/infrared_scene_remote_list.c b/applications/main/infrared/scenes/infrared_scene_remote_list.c index 55f14416b..2276e270a 100644 --- a/applications/main/infrared/scenes/infrared_scene_remote_list.c +++ b/applications/main/infrared/scenes/infrared_scene_remote_list.c @@ -1,31 +1,34 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" void infrared_scene_remote_list_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; ViewDispatcher* view_dispatcher = infrared->view_dispatcher; + view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); + view_dispatcher_switch_to_view(view_dispatcher, InfraredViewStack); + DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, INFRARED_APP_EXTENSION, &I_ir_10px); browser_options.base_path = INFRARED_APP_FOLDER; - bool success = dialog_file_browser_show( - infrared->dialogs, infrared->file_path, infrared->file_path, &browser_options); - - if(success) { - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(view_dispatcher, InfraredViewStack); + while(dialog_file_browser_show( + infrared->dialogs, infrared->file_path, infrared->file_path, &browser_options)) { + const char* file_path = furi_string_get_cstr(infrared->file_path); infrared_show_loading_popup(infrared, true); - success = infrared_remote_load(infrared->remote, infrared->file_path); + const bool remote_loaded = infrared_remote_load(infrared->remote, file_path); infrared_show_loading_popup(infrared, false); + + if(remote_loaded) { + scene_manager_next_scene(scene_manager, InfraredSceneRemote); + return; + } else { + infrared_show_error_message(infrared, "Failed to load\n\"%s\"", file_path); + } } - if(success) { - scene_manager_next_scene(scene_manager, InfraredSceneRemote); - } else { - scene_manager_previous_scene(scene_manager); - } + scene_manager_previous_scene(scene_manager); } bool infrared_scene_remote_list_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/infrared/scenes/infrared_scene_rpc.c b/applications/main/infrared/scenes/infrared_scene_rpc.c index 04f17416d..f3408fba4 100644 --- a/applications/main/infrared/scenes/infrared_scene_rpc.c +++ b/applications/main/infrared/scenes/infrared_scene_rpc.c @@ -1,6 +1,8 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include +#define TAG "InfraredApp" + typedef enum { InfraredRpcStateIdle, InfraredRpcStateLoaded, @@ -8,7 +10,7 @@ typedef enum { } InfraredRpcState; void infrared_scene_rpc_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Popup* popup = infrared->popup; popup_set_header(popup, "Infrared", 89, 42, AlignCenter, AlignBottom); @@ -27,7 +29,7 @@ void infrared_scene_rpc_on_enter(void* context) { } bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -38,12 +40,11 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { view_dispatcher_stop(infrared->view_dispatcher); } else if(event.event == InfraredCustomEventTypePopupClosed) { view_dispatcher_stop(infrared->view_dispatcher); - } else if(event.event == InfraredCustomEventTypeRpcLoad) { + } else if(event.event == InfraredCustomEventTypeRpcLoadFile) { bool result = false; - const char* arg = rpc_system_app_get_data(infrared->rpc_ctx); - if(arg && (state == InfraredRpcStateIdle)) { - furi_string_set(infrared->file_path, arg); - result = infrared_remote_load(infrared->remote, infrared->file_path); + if(state == InfraredRpcStateIdle) { + result = infrared_remote_load( + infrared->remote, furi_string_get_cstr(infrared->file_path)); if(result) { scene_manager_set_scene_state( infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded); @@ -55,20 +56,35 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { popup_set_text( infrared->popup, infrared->text_store[0], 89, 44, AlignCenter, AlignTop); - rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventLoadFile, result); - } else if(event.event == InfraredCustomEventTypeRpcButtonPress) { + rpc_system_app_confirm(infrared->rpc_ctx, result); + } else if( + event.event == InfraredCustomEventTypeRpcButtonPressName || + event.event == InfraredCustomEventTypeRpcButtonPressIndex) { bool result = false; - const char* arg = rpc_system_app_get_data(infrared->rpc_ctx); - 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; + if(state == InfraredRpcStateLoaded) { + if(event.event == InfraredCustomEventTypeRpcButtonPressName) { + const char* button_name = furi_string_get_cstr(infrared->button_name); + size_t index; + const bool index_found = + infrared_remote_get_signal_index(infrared->remote, button_name, &index); + infrared->app_state.current_button_index = + index_found ? (signed)index : InfraredButtonIndexNone; + FURI_LOG_D(TAG, "Sending signal with name \"%s\"", button_name); + } else { + FURI_LOG_D( + TAG, + "Sending signal with index \"%ld\"", + infrared->app_state.current_button_index); + } + if(infrared->app_state.current_button_index != InfraredButtonIndexNone) { + infrared_tx_start_button_index( + infrared, infrared->app_state.current_button_index); scene_manager_set_scene_state( infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateSending); + result = true; } } - rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result); + rpc_system_app_confirm(infrared->rpc_ctx, result); } else if(event.event == InfraredCustomEventTypeRpcButtonRelease) { bool result = false; if(state == InfraredRpcStateSending) { @@ -77,11 +93,11 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { scene_manager_set_scene_state( infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded); } - rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result); + rpc_system_app_confirm(infrared->rpc_ctx, 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); + rpc_system_app_confirm(infrared->rpc_ctx, true); } else if(event.event == InfraredCustomEventTypeRpcSessionClose) { scene_manager_stop(infrared->scene_manager); view_dispatcher_stop(infrared->view_dispatcher); @@ -91,7 +107,7 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { } void infrared_scene_rpc_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; if(scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneRpc) == InfraredRpcStateSending) { infrared_tx_stop(infrared); diff --git a/applications/main/infrared/scenes/infrared_scene_start.c b/applications/main/infrared/scenes/infrared_scene_start.c index 422b7cce8..3f35802e5 100644 --- a/applications/main/infrared/scenes/infrared_scene_start.c +++ b/applications/main/infrared/scenes/infrared_scene_start.c @@ -1,4 +1,4 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" enum SubmenuIndex { SubmenuIndexUniversalRemotes, @@ -10,12 +10,12 @@ enum SubmenuIndex { }; static void infrared_scene_start_submenu_callback(void* context, uint32_t index) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event(infrared->view_dispatcher, index); } void infrared_scene_start_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Submenu* submenu = infrared->submenu; SceneManager* scene_manager = infrared->scene_manager; @@ -70,7 +70,7 @@ void infrared_scene_start_on_enter(void* context) { } bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; bool consumed = false; @@ -108,6 +108,6 @@ bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) { } void infrared_scene_start_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; submenu_reset(infrared->submenu); } diff --git a/applications/main/infrared/scenes/infrared_scene_universal.c b/applications/main/infrared/scenes/infrared_scene_universal.c index 60d9d058b..1e00232aa 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal.c +++ b/applications/main/infrared/scenes/infrared_scene_universal.c @@ -1,4 +1,4 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" typedef enum { SubmenuIndexUniversalTV, @@ -12,12 +12,12 @@ typedef enum { } SubmenuIndex; static void infrared_scene_universal_submenu_callback(void* context, uint32_t index) { - Infrared* infrared = context; + InfraredApp* infrared = context; view_dispatcher_send_custom_event(infrared->view_dispatcher, index); } void infrared_scene_universal_on_enter(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; Submenu* submenu = infrared->submenu; submenu_add_item( @@ -83,7 +83,7 @@ void infrared_scene_universal_on_enter(void* context) { } bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) { - Infrared* infrared = context; + InfraredApp* infrared = context; SceneManager* scene_manager = infrared->scene_manager; bool consumed = false; @@ -120,6 +120,6 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) { } void infrared_scene_universal_on_exit(void* context) { - Infrared* infrared = context; + InfraredApp* infrared = context; submenu_reset(infrared->submenu); } diff --git a/applications/main/infrared/scenes/infrared_scene_universal_ac.c b/applications/main/infrared/scenes/infrared_scene_universal_ac.c index 790ae46bd..c691aef43 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_ac.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_ac.c @@ -1,11 +1,11 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_ac_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); - Infrared* infrared = context; + InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; diff --git a/applications/main/infrared/scenes/infrared_scene_universal_audio.c b/applications/main/infrared/scenes/infrared_scene_universal_audio.c index 769aee73b..11f84acc4 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_audio.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_audio.c @@ -1,11 +1,11 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_audio_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); - Infrared* infrared = context; + InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; diff --git a/applications/main/infrared/scenes/infrared_scene_universal_digital_sign.c b/applications/main/infrared/scenes/infrared_scene_universal_digital_sign.c index d15aa5d62..37f86e71b 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_digital_sign.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_digital_sign.c @@ -1,11 +1,11 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_digital_sign_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); - Infrared* infrared = context; + InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; diff --git a/applications/main/infrared/scenes/infrared_scene_universal_fan.c b/applications/main/infrared/scenes/infrared_scene_universal_fan.c index 4e8834bb5..ef3e819fd 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_fan.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_fan.c @@ -1,11 +1,11 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_fan_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); - Infrared* infrared = context; + InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; diff --git a/applications/main/infrared/scenes/infrared_scene_universal_led.c b/applications/main/infrared/scenes/infrared_scene_universal_led.c index bd5de3bad..ca50a4a38 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_led.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_led.c @@ -1,11 +1,11 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_led_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); - Infrared* infrared = context; + InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; diff --git a/applications/main/infrared/scenes/infrared_scene_universal_monitor.c b/applications/main/infrared/scenes/infrared_scene_universal_monitor.c index ab643af2a..65e2f790c 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_monitor.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_monitor.c @@ -1,11 +1,11 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_monitor_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); - Infrared* infrared = context; + InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; diff --git a/applications/main/infrared/scenes/infrared_scene_universal_projector.c b/applications/main/infrared/scenes/infrared_scene_universal_projector.c index 72b53413c..0e6b462fd 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_projector.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_projector.c @@ -1,11 +1,11 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_projector_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); - Infrared* infrared = context; + InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; diff --git a/applications/main/infrared/scenes/infrared_scene_universal_tv.c b/applications/main/infrared/scenes/infrared_scene_universal_tv.c index 44025a564..c7e755848 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_tv.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_tv.c @@ -1,11 +1,11 @@ -#include "../infrared_i.h" +#include "../infrared_app_i.h" #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_tv_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); - Infrared* infrared = context; + InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; diff --git a/applications/main/infrared/views/infrared_move_view.c b/applications/main/infrared/views/infrared_move_view.c index d838a5f82..374a65a44 100644 --- a/applications/main/infrared/views/infrared_move_view.c +++ b/applications/main/infrared/views/infrared_move_view.c @@ -1,10 +1,11 @@ #include "infrared_move_view.h" +#include + #include #include -#include -#include +#include #define LIST_ITEMS 4U #define LIST_LINE_H 13U @@ -13,42 +14,41 @@ struct InfraredMoveView { View* view; - InfraredMoveCallback move_cb; - void* cb_context; + InfraredMoveCallback callback; + void* callback_context; }; -typedef struct { - const char** btn_names; - uint32_t btn_number; - int32_t list_offset; - int32_t item_idx; - bool is_moving; +ARRAY_DEF(InfraredMoveViewItemArray, const char*, M_CSTR_DUP_OPLIST); //-V575 - InfraredMoveGetItemCallback get_item_cb; +typedef struct { + InfraredMoveViewItemArray_t labels; + int32_t list_offset; + int32_t current_idx; + int32_t start_idx; + bool is_moving; } InfraredMoveViewModel; static void infrared_move_view_draw_callback(Canvas* canvas, void* _model) { InfraredMoveViewModel* model = _model; - UNUSED(model); - canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned( canvas, canvas_width(canvas) / 2, 0, AlignCenter, AlignTop, "Select a button to move"); - bool show_scrollbar = model->btn_number > LIST_ITEMS; + const size_t btn_number = InfraredMoveViewItemArray_size(model->labels); + const bool show_scrollbar = btn_number > LIST_ITEMS; canvas_set_font(canvas, FontSecondary); - for(uint32_t i = 0; i < MIN(model->btn_number, LIST_ITEMS); i++) { - int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->btn_number, 0u); - uint8_t x_offset = (model->is_moving && model->item_idx == idx) ? MOVE_X_OFFSET : 0; + for(uint32_t i = 0; i < MIN(btn_number, LIST_ITEMS); i++) { + int32_t idx = CLAMP((uint32_t)(i + model->list_offset), btn_number, 0U); + uint8_t x_offset = (model->is_moving && model->current_idx == idx) ? MOVE_X_OFFSET : 0; uint8_t y_offset = HEADER_H + i * LIST_LINE_H; uint8_t box_end_x = canvas_width(canvas) - (show_scrollbar ? 6 : 1); canvas_set_color(canvas, ColorBlack); - if(model->item_idx == idx) { + if(model->current_idx == idx) { canvas_draw_box(canvas, x_offset, y_offset, box_end_x - x_offset, LIST_LINE_H); canvas_set_color(canvas, ColorWhite); @@ -60,7 +60,12 @@ static void infrared_move_view_draw_callback(Canvas* canvas, void* _model) { canvas_draw_dot(canvas, box_end_x - 1, y_offset + LIST_LINE_H - 1); } canvas_draw_str_aligned( - canvas, x_offset + 3, y_offset + 3, AlignLeft, AlignTop, model->btn_names[idx]); + canvas, + x_offset + 3, + y_offset + 3, + AlignLeft, + AlignTop, + *InfraredMoveViewItemArray_cget(model->labels, idx)); } if(show_scrollbar) { @@ -69,22 +74,22 @@ static void infrared_move_view_draw_callback(Canvas* canvas, void* _model) { canvas_width(canvas), HEADER_H, canvas_height(canvas) - HEADER_H, - model->item_idx, - model->btn_number); + model->current_idx, + btn_number); } } static void update_list_offset(InfraredMoveViewModel* model) { - int32_t bounds = model->btn_number > (LIST_ITEMS - 1) ? 2 : model->btn_number; + const size_t btn_number = InfraredMoveViewItemArray_size(model->labels); + const int32_t bounds = btn_number > (LIST_ITEMS - 1) ? 2 : btn_number; - if((model->btn_number > (LIST_ITEMS - 1)) && - (model->item_idx >= ((int32_t)model->btn_number - 1))) { - model->list_offset = model->item_idx - (LIST_ITEMS - 1); - } else if(model->list_offset < model->item_idx - bounds) { - model->list_offset = CLAMP( - model->item_idx - (int32_t)(LIST_ITEMS - 2), (int32_t)model->btn_number - bounds, 0); - } else if(model->list_offset > model->item_idx - bounds) { - model->list_offset = CLAMP(model->item_idx - 1, (int32_t)model->btn_number - bounds, 0); + if((btn_number > (LIST_ITEMS - 1)) && (model->current_idx >= ((int32_t)btn_number - 1))) { + model->list_offset = model->current_idx - (LIST_ITEMS - 1); + } else if(model->list_offset < model->current_idx - bounds) { + model->list_offset = + CLAMP(model->current_idx - (int32_t)(LIST_ITEMS - 2), (int32_t)btn_number - bounds, 0); + } else if(model->list_offset > model->current_idx - bounds) { + model->list_offset = CLAMP(model->current_idx - 1, (int32_t)btn_number - bounds, 0); } } @@ -95,117 +100,130 @@ static bool infrared_move_view_input_callback(InputEvent* event, void* context) if(((event->type == InputTypeShort || event->type == InputTypeRepeat)) && ((event->key == InputKeyUp) || (event->key == InputKeyDown))) { - bool is_moving = false; - uint32_t index_old = 0; - uint32_t index_new = 0; with_view_model( move_view->view, InfraredMoveViewModel * model, { - is_moving = model->is_moving; - index_old = model->item_idx; + const size_t btn_number = InfraredMoveViewItemArray_size(model->labels); + const int32_t item_idx_prev = model->current_idx; + if(event->key == InputKeyUp) { - if(model->item_idx <= 0) { - model->item_idx = model->btn_number; + if(model->current_idx <= 0) { + model->current_idx = btn_number; } - model->item_idx--; + model->current_idx--; + } else if(event->key == InputKeyDown) { - model->item_idx++; - if(model->item_idx >= (int32_t)(model->btn_number)) { - model->item_idx = 0; + model->current_idx++; + if(model->current_idx >= (int32_t)(btn_number)) { + model->current_idx = 0; } } - index_new = model->item_idx; + + if(model->is_moving) { + InfraredMoveViewItemArray_swap_at( + model->labels, item_idx_prev, model->current_idx); + } + update_list_offset(model); }, - !is_moving); - if((is_moving) && (move_view->move_cb)) { - move_view->move_cb(index_old, index_new, move_view->cb_context); - infrared_move_view_list_update(move_view); - } - consumed = true; - } + true); - if((event->key == InputKeyOk) && (event->type == InputTypeShort)) { + consumed = true; + + } else if((event->key == InputKeyOk) && (event->type == InputTypeShort)) { with_view_model( move_view->view, InfraredMoveViewModel * model, - { model->is_moving = !(model->is_moving); }, + { + if(!model->is_moving) { + model->start_idx = model->current_idx; + } else if(move_view->callback) { + move_view->callback( + model->start_idx, model->current_idx, move_view->callback_context); + } + model->is_moving = !(model->is_moving); + }, true); + consumed = true; + + } else if(event->key == InputKeyBack) { + with_view_model( + move_view->view, + InfraredMoveViewModel * model, + { + if(model->is_moving && move_view->callback) { + move_view->callback( + model->start_idx, model->current_idx, move_view->callback_context); + } + model->is_moving = false; + }, + false); + + // Not consuming, Back event is passed thru } + return consumed; } -static void infrared_move_view_on_exit(void* context) { - furi_assert(context); - InfraredMoveView* move_view = context; - - with_view_model( - move_view->view, - InfraredMoveViewModel * model, - { - if(model->btn_names) { - free(model->btn_names); - model->btn_names = NULL; - } - model->btn_number = 0; - model->get_item_cb = NULL; - }, - false); - move_view->cb_context = NULL; -} - -void infrared_move_view_set_callback(InfraredMoveView* move_view, InfraredMoveCallback callback) { - furi_assert(move_view); - move_view->move_cb = callback; -} - -void infrared_move_view_list_init( +void infrared_move_view_set_callback( InfraredMoveView* move_view, - uint32_t item_count, - InfraredMoveGetItemCallback load_cb, + InfraredMoveCallback callback, void* context) { furi_assert(move_view); - move_view->cb_context = context; - with_view_model( - move_view->view, - InfraredMoveViewModel * model, - { - furi_assert(model->btn_names == NULL); - model->btn_names = malloc(sizeof(char*) * item_count); - model->btn_number = item_count; - model->get_item_cb = load_cb; - }, - false); + move_view->callback = callback; + move_view->callback_context = context; } -void infrared_move_view_list_update(InfraredMoveView* move_view) { - furi_assert(move_view); +void infrared_move_view_add_item(InfraredMoveView* move_view, const char* label) { + with_view_model( + move_view->view, + InfraredMoveViewModel * model, + { InfraredMoveViewItemArray_push_back(model->labels, label); }, + true); +} + +void infrared_move_view_reset(InfraredMoveView* move_view) { with_view_model( move_view->view, InfraredMoveViewModel * model, { - for(uint32_t i = 0; i < model->btn_number; i++) { - if(!model->get_item_cb) break; - model->btn_names[i] = model->get_item_cb(i, move_view->cb_context); - } + InfraredMoveViewItemArray_reset(model->labels); + model->list_offset = 0; + model->start_idx = 0; + model->current_idx = 0; + model->is_moving = false; }, - true); + false); + move_view->callback_context = NULL; } InfraredMoveView* infrared_move_view_alloc(void) { InfraredMoveView* move_view = malloc(sizeof(InfraredMoveView)); + move_view->view = view_alloc(); view_allocate_model(move_view->view, ViewModelTypeLocking, sizeof(InfraredMoveViewModel)); view_set_draw_callback(move_view->view, infrared_move_view_draw_callback); view_set_input_callback(move_view->view, infrared_move_view_input_callback); - view_set_exit_callback(move_view->view, infrared_move_view_on_exit); view_set_context(move_view->view, move_view); + + with_view_model( + move_view->view, + InfraredMoveViewModel * model, + { InfraredMoveViewItemArray_init(model->labels); }, + true); + return move_view; } void infrared_move_view_free(InfraredMoveView* move_view) { + with_view_model( + move_view->view, + InfraredMoveViewModel * model, + { InfraredMoveViewItemArray_clear(model->labels); }, + true); + view_free(move_view->view); free(move_view); } diff --git a/applications/main/infrared/views/infrared_move_view.h b/applications/main/infrared/views/infrared_move_view.h index b9b0cd864..0ab15ce0d 100644 --- a/applications/main/infrared/views/infrared_move_view.h +++ b/applications/main/infrared/views/infrared_move_view.h @@ -6,20 +6,17 @@ typedef struct InfraredMoveView InfraredMoveView; typedef void (*InfraredMoveCallback)(uint32_t index_old, uint32_t index_new, void* context); -typedef const char* (*InfraredMoveGetItemCallback)(uint32_t index, void* context); - InfraredMoveView* infrared_move_view_alloc(void); void infrared_move_view_free(InfraredMoveView* debug_view); View* infrared_move_view_get_view(InfraredMoveView* debug_view); -void infrared_move_view_set_callback(InfraredMoveView* move_view, InfraredMoveCallback callback); - -void infrared_move_view_list_init( +void infrared_move_view_set_callback( InfraredMoveView* move_view, - uint32_t item_count, - InfraredMoveGetItemCallback load_cb, + InfraredMoveCallback callback, void* context); -void infrared_move_view_list_update(InfraredMoveView* move_view); \ No newline at end of file +void infrared_move_view_add_item(InfraredMoveView* move_view, const char* label); + +void infrared_move_view_reset(InfraredMoveView* move_view); diff --git a/applications/main/lfrfid/application.fam b/applications/main/lfrfid/application.fam index 76eeaf9d8..b44430323 100644 --- a/applications/main/lfrfid/application.fam +++ b/applications/main/lfrfid/application.fam @@ -16,5 +16,6 @@ App( targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="lfrfid_on_system_start", + sources=["lfrfid_cli.c"], order=50, ) diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c index cea4a8256..854e09487 100644 --- a/applications/main/lfrfid/lfrfid.c +++ b/applications/main/lfrfid/lfrfid.c @@ -14,21 +14,23 @@ static bool lfrfid_debug_back_event_callback(void* context) { return scene_manager_handle_back_event(app->scene_manager); } -static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) { +static void rpc_command_callback(const RpcAppSystemEvent* event, void* context) { furi_assert(context); LfRfid* app = (LfRfid*)context; - if(rpc_event == RpcAppEventSessionClose) { + if(event->type == RpcAppEventTypeSessionClose) { view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventRpcSessionClose); // Detach RPC rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL); app->rpc_ctx = NULL; - } else if(rpc_event == RpcAppEventAppExit) { + } else if(event->type == RpcAppEventTypeAppExit) { view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventExit); - } else if(rpc_event == RpcAppEventLoadFile) { + } else if(event->type == RpcAppEventTypeLoadFile) { + furi_assert(event->data.type == RpcAppSystemEventDataTypeString); + furi_string_set(app->file_path, event->data.string); view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventRpcLoadFile); } else { - rpc_system_app_confirm(app->rpc_ctx, rpc_event, false); + rpc_system_app_confirm(app->rpc_ctx, false); } } diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c b/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c index 156dd97af..906218d74 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c @@ -24,17 +24,15 @@ bool lfrfid_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == LfRfidEventExit) { - rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true); + rpc_system_app_confirm(app->rpc_ctx, true); scene_manager_stop(app->scene_manager); view_dispatcher_stop(app->view_dispatcher); } else if(event.event == LfRfidEventRpcSessionClose) { scene_manager_stop(app->scene_manager); view_dispatcher_stop(app->view_dispatcher); } else if(event.event == LfRfidEventRpcLoadFile) { - const char* arg = rpc_system_app_get_data(app->rpc_ctx); bool result = false; - if(arg && (app->rpc_state == LfRfidRpcStateIdle)) { - furi_string_set(app->file_path, arg); + if(app->rpc_state == LfRfidRpcStateIdle) { if(lfrfid_load_key_data(app, app->file_path, false)) { lfrfid_worker_start_thread(app->lfworker); lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id); @@ -48,7 +46,7 @@ bool lfrfid_scene_rpc_on_event(void* context, SceneManagerEvent event) { result = true; } } - rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result); + rpc_system_app_confirm(app->rpc_ctx, result); } } return consumed; diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 10bb5bf8e..166283149 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -7,6 +7,12 @@ App( icon="A_NFC_14", stack_size=5 * 1024, order=30, + resources="resources", + sources=[ + "*.c", + "!plugins", + "!nfc_cli.c", + ], fap_icon="icon.png", fap_category="NFC", ) @@ -19,6 +25,7 @@ App( entry_point="all_in_one_plugin_ep", targets=["f7"], requires=["nfc"], + sources=["plugins/supported_cards/all_in_one.c"], ) App( @@ -27,6 +34,7 @@ App( entry_point="opal_plugin_ep", targets=["f7"], requires=["nfc"], + sources=["plugins/supported_cards/opal.c"], ) App( @@ -35,6 +43,7 @@ App( entry_point="myki_plugin_ep", targets=["f7"], requires=["nfc"], + sources=["plugins/supported_cards/myki.c"], ) App( @@ -43,6 +52,7 @@ App( entry_point="troika_plugin_ep", targets=["f7"], requires=["nfc"], + sources=["plugins/supported_cards/troika.c"], ) App( @@ -51,6 +61,7 @@ App( entry_point="plantain_plugin_ep", targets=["f7"], requires=["nfc"], + sources=["plugins/supported_cards/plantain.c"], ) App( @@ -59,6 +70,7 @@ App( entry_point="two_cities_plugin_ep", targets=["f7"], requires=["nfc"], + sources=["plugins/supported_cards/two_cities.c"], ) App( @@ -66,5 +78,6 @@ App( targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="nfc_on_system_start", + sources=["nfc_cli.c"], order=30, ) diff --git a/applications/main/nfc/helpers/nfc_custom_event.h b/applications/main/nfc/helpers/nfc_custom_event.h index 2a3b13e1a..16fbc4749 100644 --- a/applications/main/nfc/helpers/nfc_custom_event.h +++ b/applications/main/nfc/helpers/nfc_custom_event.h @@ -21,7 +21,7 @@ typedef enum { NfcCustomEventTextInputDone, NfcCustomEventDictAttackDone, - NfcCustomEventRpcLoad, + NfcCustomEventRpcLoadFile, NfcCustomEventRpcExit, NfcCustomEventRpcSessionClose, diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c index bf6c0842f..87fbe9f08 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c @@ -694,15 +694,17 @@ static bool nfc_protocol_support_scene_rpc_on_event(NfcApp* instance, SceneManag bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventRpcLoad && instance->rpc_state == NfcRpcStateIdle) { - furi_string_set(instance->file_path, rpc_system_app_get_data(instance->rpc_ctx)); - const bool load_success = nfc_load_file(instance, instance->file_path, false); - if(load_success) { - nfc_protocol_support_scene_rpc_setup_ui_and_emulate(instance); + if(event.event == NfcCustomEventRpcLoadFile) { + bool success = false; + if(instance->rpc_state == NfcRpcStateIdle) { + if(nfc_load_file(instance, instance->file_path, false)) { + nfc_protocol_support_scene_rpc_setup_ui_and_emulate(instance); + success = true; + } } - rpc_system_app_confirm(instance->rpc_ctx, RpcAppEventLoadFile, load_success); + rpc_system_app_confirm(instance->rpc_ctx, success); } else if(event.event == NfcCustomEventRpcExit) { - rpc_system_app_confirm(instance->rpc_ctx, RpcAppEventAppExit, true); + rpc_system_app_confirm(instance->rpc_ctx, true); scene_manager_stop(instance->scene_manager); view_dispatcher_stop(instance->view_dispatcher); } else if(event.event == NfcCustomEventRpcSessionClose) { diff --git a/applications/main/nfc/nfc_app.c b/applications/main/nfc/nfc_app.c index fe680aa32..141a67e5c 100644 --- a/applications/main/nfc/nfc_app.c +++ b/applications/main/nfc/nfc_app.c @@ -14,22 +14,24 @@ bool nfc_back_event_callback(void* context) { return scene_manager_handle_back_event(nfc->scene_manager); } -static void nfc_app_rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) { +static void nfc_app_rpc_command_callback(const RpcAppSystemEvent* event, void* context) { furi_assert(context); NfcApp* nfc = (NfcApp*)context; furi_assert(nfc->rpc_ctx); - if(rpc_event == RpcAppEventSessionClose) { + if(event->type == RpcAppEventTypeSessionClose) { 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(rpc_event == RpcAppEventAppExit) { + } else if(event->type == RpcAppEventTypeAppExit) { view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcExit); - } else if(rpc_event == RpcAppEventLoadFile) { - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad); + } else if(event->type == RpcAppEventTypeLoadFile) { + furi_assert(event->data.type == RpcAppSystemEventDataTypeString); + furi_string_set(nfc->file_path, event->data.string); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoadFile); } else { - rpc_system_app_confirm(nfc->rpc_ctx, rpc_event, false); + rpc_system_app_confirm(nfc->rpc_ctx, false); } } @@ -411,15 +413,14 @@ bool nfc_load_from_file_select(NfcApp* instance) { void nfc_show_loading_popup(void* context, bool show) { NfcApp* nfc = context; - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); if(show) { // Raise timer priority so that animations can play - vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); + furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewLoading); } else { // Restore default timer priority - vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); + furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal); } } diff --git a/assets/resources/nfc/RickRoll.nfc b/applications/main/nfc/resources/nfc/RickRoll.nfc similarity index 100% rename from assets/resources/nfc/RickRoll.nfc rename to applications/main/nfc/resources/nfc/RickRoll.nfc diff --git a/assets/resources/nfc/assets/aid.nfc b/applications/main/nfc/resources/nfc/assets/aid.nfc similarity index 100% rename from assets/resources/nfc/assets/aid.nfc rename to applications/main/nfc/resources/nfc/assets/aid.nfc diff --git a/assets/resources/nfc/assets/country_code.nfc b/applications/main/nfc/resources/nfc/assets/country_code.nfc similarity index 100% rename from assets/resources/nfc/assets/country_code.nfc rename to applications/main/nfc/resources/nfc/assets/country_code.nfc diff --git a/assets/resources/nfc/assets/currency_code.nfc b/applications/main/nfc/resources/nfc/assets/currency_code.nfc similarity index 100% rename from assets/resources/nfc/assets/currency_code.nfc rename to applications/main/nfc/resources/nfc/assets/currency_code.nfc diff --git a/assets/resources/nfc/assets/mf_classic_dict.nfc b/applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc similarity index 100% rename from assets/resources/nfc/assets/mf_classic_dict.nfc rename to applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index cc0da1533..d57ba2aff 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -17,6 +17,12 @@ App( icon="A_Sub1ghz_14", stack_size=3 * 1024, order=10, + sources=[ + "*.c", + "!subghz_cli.c", + "!helpers/subghz_chat.c", + ], + resources="resources", fap_libs=["hwdrivers"], fap_icon="icon.png", fap_category="Sub-GHz", @@ -27,6 +33,7 @@ App( targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="subghz_on_system_start", + sources=["subghz_cli.c", "helpers/subghz_chat.c"], requires=["subghz"], order=40, ) diff --git a/assets/resources/subghz/assets/README.md b/applications/main/subghz/resources/subghz/assets/README.md similarity index 100% rename from assets/resources/subghz/assets/README.md rename to applications/main/subghz/resources/subghz/assets/README.md diff --git a/assets/resources/subghz/assets/alutech_at_4n b/applications/main/subghz/resources/subghz/assets/alutech_at_4n similarity index 100% rename from assets/resources/subghz/assets/alutech_at_4n rename to applications/main/subghz/resources/subghz/assets/alutech_at_4n diff --git a/applications/main/subghz/resources/subghz/assets/came_atomo b/applications/main/subghz/resources/subghz/assets/came_atomo new file mode 100644 index 000000000..0952f3f20 --- /dev/null +++ b/applications/main/subghz/resources/subghz/assets/came_atomo @@ -0,0 +1,6 @@ +Filetype: Flipper SubGhz Keystore RAW File +Version: 0 +Encryption: 1 +IV: 47 69 6D 6D 65 20 74 68 65 63 6F 6F 6B 69 65 73 +Encrypt_data: RAW +E0BDF15D68F29AE787E7FCEE6C3611C90A92305D677B8FFFBE225196F5DC04CAEAE1102B4AB830E76C9C14DBA7FA5BD1F30864ABAF51387222FDCC0BA87E4FF709812D5C59DD953859AFD698A0EA2ECEFA0DC49652861EF4CF1864843F135DB8680E0C5C9EEC3BC548E2EB696DC8CA1B0F627347D2C476B410CF03A0F4D1EFB36DFB0574FE8F48FB61910CA539EC04583CA170A51822225A1D3E86C07219FE92E5DE9F557A45E611D74028BAF56E7F2C53DBA8DC53DA89B642FAC0A9A0BAC1756BDA0833ACB09F56E0FA3080CBE9E6A04B235F3AC82BB955FBFD779C59725E6D1875E04E0E84ABD0C3C1C8FAB247EC2755ACEC9961244E0D79AE710E4C7D33E9 \ No newline at end of file diff --git a/assets/resources/subghz/assets/keeloq_mfcodes b/applications/main/subghz/resources/subghz/assets/keeloq_mfcodes similarity index 100% rename from assets/resources/subghz/assets/keeloq_mfcodes rename to applications/main/subghz/resources/subghz/assets/keeloq_mfcodes diff --git a/assets/resources/subghz/assets/keeloq_mfcodes_user.example b/applications/main/subghz/resources/subghz/assets/keeloq_mfcodes_user.example similarity index 100% rename from assets/resources/subghz/assets/keeloq_mfcodes_user.example rename to applications/main/subghz/resources/subghz/assets/keeloq_mfcodes_user.example diff --git a/assets/resources/subghz/assets/nice_flor_s b/applications/main/subghz/resources/subghz/assets/nice_flor_s similarity index 100% rename from assets/resources/subghz/assets/nice_flor_s rename to applications/main/subghz/resources/subghz/assets/nice_flor_s diff --git a/assets/resources/subghz/assets/setting_user.example b/applications/main/subghz/resources/subghz/assets/setting_user.example similarity index 100% rename from assets/resources/subghz/assets/setting_user.example rename to applications/main/subghz/resources/subghz/assets/setting_user.example diff --git a/applications/main/subghz/scenes/subghz_scene_rpc.c b/applications/main/subghz/scenes/subghz_scene_rpc.c index 724abaf3e..2f8a1f03f 100644 --- a/applications/main/subghz/scenes/subghz_scene_rpc.c +++ b/applications/main/subghz/scenes/subghz_scene_rpc.c @@ -35,13 +35,13 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.event == SubGhzCustomEventSceneExit) { scene_manager_stop(subghz->scene_manager); view_dispatcher_stop(subghz->view_dispatcher); - rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventAppExit, true); + rpc_system_app_confirm(subghz->rpc_ctx, true); } else if(event.event == SubGhzCustomEventSceneRpcSessionClose) { scene_manager_stop(subghz->scene_manager); view_dispatcher_stop(subghz->view_dispatcher); } else if(event.event == SubGhzCustomEventSceneRpcButtonPress) { bool result = false; - if((state == SubGhzRpcStateLoaded)) { + if(state == SubGhzRpcStateLoaded) { switch( subghz_txrx_tx_start(subghz->txrx, subghz_txrx_get_fff_data(subghz->txrx))) { case SubGhzTxRxStartTxStateErrorOnlyRx: @@ -63,7 +63,7 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { break; } } - rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result); + rpc_system_app_confirm(subghz->rpc_ctx, result); } else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) { bool result = false; if(state == SubGhzRpcStateTx) { @@ -72,15 +72,13 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { result = true; } state = SubGhzRpcStateIdle; - rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonRelease, result); + rpc_system_app_confirm(subghz->rpc_ctx, result); } else if(event.event == SubGhzCustomEventSceneRpcLoad) { bool result = false; - const char* arg = rpc_system_app_get_data(subghz->rpc_ctx); - if(arg && (state == SubGhzRpcStateIdle)) { - if(subghz_key_load(subghz, arg, false)) { + if(state == SubGhzRpcStateIdle) { + if(subghz_key_load(subghz, furi_string_get_cstr(subghz->file_path), false)) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateLoaded); - furi_string_set(subghz->file_path, arg); result = true; FuriString* file_name = furi_string_alloc(); path_extract_filename(subghz->file_path, file_name, true); @@ -98,7 +96,7 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { rpc_system_app_set_error_text(subghz->rpc_ctx, "Cannot parse file"); } } - rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventLoadFile, result); + rpc_system_app_confirm(subghz->rpc_ctx, result); } } return consumed; diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index ab78c9c7c..eee4ed360 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -28,29 +28,31 @@ void subghz_tick_event_callback(void* context) { scene_manager_handle_tick_event(subghz->scene_manager); } -static void subghz_rpc_command_callback(RpcAppSystemEvent event, void* context) { +static void subghz_rpc_command_callback(const RpcAppSystemEvent* event, void* context) { furi_assert(context); SubGhz* subghz = context; furi_assert(subghz->rpc_ctx); - if(event == RpcAppEventSessionClose) { + if(event->type == RpcAppEventTypeSessionClose) { 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) { + } else if(event->type == RpcAppEventTypeAppExit) { view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit); - } else if(event == RpcAppEventLoadFile) { + } else if(event->type == RpcAppEventTypeLoadFile) { + furi_assert(event->data.type == RpcAppSystemEventDataTypeString); + furi_string_set(subghz->file_path, event->data.string); view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad); - } else if(event == RpcAppEventButtonPress) { + } else if(event->type == RpcAppEventTypeButtonPress) { view_dispatcher_send_custom_event( subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonPress); - } else if(event == RpcAppEventButtonRelease) { + } else if(event->type == RpcAppEventTypeButtonRelease) { view_dispatcher_send_custom_event( subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonRelease); } else { - rpc_system_app_confirm(subghz->rpc_ctx, event, false); + rpc_system_app_confirm(subghz->rpc_ctx, false); } } diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index 010e47062..f1d0324fc 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -111,7 +111,7 @@ void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, bool loc SubGhzViewReceiverModel * model, { model->bar_show = SubGhzViewReceiverBarShowLock; }, true); - furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(1000)); + furi_timer_start(subghz_receiver->timer, 1000); } else { with_view_model( subghz_receiver->view, @@ -453,7 +453,7 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) { { model->bar_show = SubGhzViewReceiverBarShowToUnlockPress; }, true); if(subghz_receiver->lock_count == 0) { - furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(1000)); + furi_timer_start(subghz_receiver->timer, 1000); } if(event->key == InputKeyBack && event->type == InputTypeShort) { subghz_receiver->lock_count++; @@ -467,7 +467,7 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) { { model->bar_show = SubGhzViewReceiverBarShowUnlock; }, true); //subghz_receiver->lock = false; - furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(650)); + furi_timer_start(subghz_receiver->timer, 650); } return true; diff --git a/applications/main/u2f/application.fam b/applications/main/u2f/application.fam index a60f0721f..979389341 100644 --- a/applications/main/u2f/application.fam +++ b/applications/main/u2f/application.fam @@ -6,6 +6,7 @@ App( stack_size=2 * 1024, icon="A_U2F_14", order=80, - fap_icon="icon.png", + resources="resources", fap_category="USB", + fap_icon="icon.png", ) diff --git a/assets/resources/u2f/assets/cert.der b/applications/main/u2f/resources/u2f/assets/cert.der similarity index 100% rename from assets/resources/u2f/assets/cert.der rename to applications/main/u2f/resources/u2f/assets/cert.der diff --git a/assets/resources/u2f/assets/cert_key.u2f b/applications/main/u2f/resources/u2f/assets/cert_key.u2f similarity index 100% rename from assets/resources/u2f/assets/cert_key.u2f rename to applications/main/u2f/resources/u2f/assets/cert_key.u2f diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index dcc60bad1..14f5d98c6 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -477,13 +476,13 @@ void animation_manager_unload_and_stall_animation(AnimationManager* animation_ma animation_manager->state = AnimationManagerStateFreezedIdle; animation_manager->freezed_animation_time_left = - xTimerGetExpiryTime(animation_manager->idle_animation_timer) - xTaskGetTickCount(); + furi_timer_get_expire_time(animation_manager->idle_animation_timer) - furi_get_tick(); if(animation_manager->freezed_animation_time_left < 0) { animation_manager->freezed_animation_time_left = 0; } furi_timer_stop(animation_manager->idle_animation_timer); } else { - furi_assert(0); + furi_crash(); } FURI_LOG_I( @@ -561,7 +560,7 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m } } else { /* Unknown state is an error. But not in release version.*/ - furi_assert(0); + furi_crash(); } /* if can't restore previous animation - select new */ diff --git a/applications/services/desktop/animations/animation_storage.c b/applications/services/desktop/animations/animation_storage.c index 101140699..edd1291f1 100644 --- a/applications/services/desktop/animations/animation_storage.c +++ b/applications/services/desktop/animations/animation_storage.c @@ -334,7 +334,7 @@ static bool animation_storage_load_frames( if(file_info.size > max_filesize) { FURI_LOG_E( TAG, - "Filesize %lld, max: %d (width %d, height %d)", + "Filesize %llu, max: %zu (width %u, height %u)", file_info.size, max_filesize, width, @@ -359,7 +359,7 @@ static bool animation_storage_load_frames( if(!frames_ok) { FURI_LOG_E( TAG, - "Load \'%s\' failed, %dx%d, size: %lld", + "Load \'%s\' failed, %ux%u, size: %llu", furi_string_get_cstr(filename), width, height, diff --git a/applications/services/desktop/animations/views/bubble_animation_view.c b/applications/services/desktop/animations/views/bubble_animation_view.c index 199f7cd71..29cd617ca 100644 --- a/applications/services/desktop/animations/views/bubble_animation_view.c +++ b/applications/services/desktop/animations/views/bubble_animation_view.c @@ -23,7 +23,7 @@ typedef struct { uint8_t active_bubbles; uint8_t passive_bubbles; uint8_t active_shift; - TickType_t active_ended_at; + uint32_t active_ended_at; Icon* freeze_frame; } BubbleAnimationViewModel; @@ -154,7 +154,7 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) { if(model->current != NULL) { if(!force) { if((model->active_ended_at + model->current->active_cooldown * 1000) > - xTaskGetTickCount()) { + furi_get_tick()) { activate = false; } else if(model->active_shift) { activate = false; @@ -215,7 +215,7 @@ static void bubble_animation_next_frame(BubbleAnimationViewModel* model) { model->active_cycle = 0; model->current_frame = 0; model->current_bubble = bubble_animation_pick_bubble(model, false); - model->active_ended_at = xTaskGetTickCount(); + model->active_ended_at = furi_get_tick(); } if(model->current_bubble) { @@ -355,7 +355,7 @@ void bubble_animation_view_set_animation( furi_assert(model); model->current = new_animation; - model->active_ended_at = xTaskGetTickCount() - (model->current->active_cooldown * 1000); + model->active_ended_at = furi_get_tick() - (model->current->active_cooldown * 1000); model->active_bubbles = 0; model->passive_bubbles = 0; for(int i = 0; i < new_animation->frame_bubble_sequences_count; ++i) { diff --git a/applications/services/desktop/animations/views/one_shot_animation_view.c b/applications/services/desktop/animations/views/one_shot_animation_view.c index e76856288..3be66ee5f 100644 --- a/applications/services/desktop/animations/views/one_shot_animation_view.c +++ b/applications/services/desktop/animations/views/one_shot_animation_view.c @@ -1,7 +1,6 @@ #include "one_shot_animation_view.h" #include -#include #include #include #include @@ -11,7 +10,7 @@ typedef void (*OneShotInteractCallback)(void*); struct OneShotView { View* view; - TimerHandle_t update_timer; + FuriTimer* update_timer; OneShotInteractCallback interact_callback; void* interact_callback_context; }; @@ -22,8 +21,8 @@ typedef struct { bool block_input; } OneShotViewModel; -static void one_shot_view_update_timer_callback(TimerHandle_t xTimer) { - OneShotView* view = (void*)pvTimerGetTimerID(xTimer); +static void one_shot_view_update_timer_callback(void* context) { + OneShotView* view = context; OneShotViewModel* model = view_get_model(view->view); if((model->index + 1) < model->icon->frame_count) { @@ -81,7 +80,7 @@ OneShotView* one_shot_view_alloc(void) { OneShotView* view = malloc(sizeof(OneShotView)); view->view = view_alloc(); view->update_timer = - xTimerCreate(NULL, 1000, pdTRUE, view, one_shot_view_update_timer_callback); + furi_timer_alloc(one_shot_view_update_timer_callback, FuriTimerTypePeriodic, view); view_allocate_model(view->view, ViewModelTypeLocking, sizeof(OneShotViewModel)); view_set_context(view->view, view); @@ -94,7 +93,7 @@ OneShotView* one_shot_view_alloc(void) { void one_shot_view_free(OneShotView* view) { furi_assert(view); - xTimerDelete(view->update_timer, portMAX_DELAY); + furi_timer_free(view->update_timer); view_free(view->view); view->view = NULL; free(view); @@ -120,7 +119,7 @@ void one_shot_view_start_animation(OneShotView* view, const Icon* icon) { model->icon = icon; model->block_input = true; view_commit_model(view->view, true); - xTimerChangePeriod(view->update_timer, 1000 / model->icon->frame_rate, portMAX_DELAY); + furi_timer_start(view->update_timer, 1000 / model->icon->frame_rate); } View* one_shot_view_get_view(OneShotView* view) { diff --git a/applications/services/desktop/scenes/desktop_scene_locked.c b/applications/services/desktop/scenes/desktop_scene_locked.c index a96041a8a..513359f7e 100644 --- a/applications/services/desktop/scenes/desktop_scene_locked.c +++ b/applications/services/desktop/scenes/desktop_scene_locked.c @@ -3,7 +3,6 @@ #include #include #include -#include #include "../desktop.h" #include "../desktop_i.h" diff --git a/applications/services/desktop/scenes/desktop_scene_pin_input.c b/applications/services/desktop/scenes/desktop_scene_pin_input.c index 360d2cf7d..a0e621bcc 100644 --- a/applications/services/desktop/scenes/desktop_scene_pin_input.c +++ b/applications/services/desktop/scenes/desktop_scene_pin_input.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -21,7 +20,7 @@ #define INPUT_PIN_VIEW_TIMEOUT 15000 typedef struct { - TimerHandle_t timer; + FuriTimer* timer; } DesktopScenePinInputState; static void desktop_scene_locked_light_red(bool value) { @@ -34,17 +33,16 @@ static void desktop_scene_locked_light_red(bool value) { furi_record_close(RECORD_NOTIFICATION); } -static void - desktop_scene_pin_input_set_timer(Desktop* desktop, bool enable, TickType_t new_period) { +static void desktop_scene_pin_input_set_timer(Desktop* desktop, bool enable, uint32_t new_period) { furi_assert(desktop); DesktopScenePinInputState* state = (DesktopScenePinInputState*)scene_manager_get_scene_state( desktop->scene_manager, DesktopScenePinInput); furi_assert(state); if(enable) { - xTimerChangePeriod(state->timer, new_period, portMAX_DELAY); + furi_timer_start(state->timer, new_period); } else { - xTimerStop(state->timer, portMAX_DELAY); + furi_timer_stop(state->timer); } } @@ -72,8 +70,8 @@ static void desktop_scene_pin_input_done_callback(const PinCode* pin_code, void* } } -static void desktop_scene_pin_input_timer_callback(TimerHandle_t timer) { - Desktop* desktop = pvTimerGetTimerID(timer); +static void desktop_scene_pin_input_timer_callback(void* context) { + Desktop* desktop = context; view_dispatcher_send_custom_event( desktop->view_dispatcher, DesktopPinInputEventResetWrongPinLabel); @@ -92,7 +90,7 @@ void desktop_scene_pin_input_on_enter(void* context) { DesktopScenePinInputState* state = malloc(sizeof(DesktopScenePinInputState)); state->timer = - xTimerCreate(NULL, 10000, pdFALSE, desktop, desktop_scene_pin_input_timer_callback); + furi_timer_alloc(desktop_scene_pin_input_timer_callback, FuriTimerTypeOnce, desktop); scene_manager_set_scene_state(desktop->scene_manager, DesktopScenePinInput, (uint32_t)state); desktop_view_pin_input_hide_pin(desktop->pin_input_view, true); @@ -157,10 +155,7 @@ void desktop_scene_pin_input_on_exit(void* context) { DesktopScenePinInputState* state = (DesktopScenePinInputState*)scene_manager_get_scene_state( desktop->scene_manager, DesktopScenePinInput); - xTimerStop(state->timer, portMAX_DELAY); - while(xTimerIsTimerActive(state->timer)) { - furi_delay_tick(1); - } - xTimerDelete(state->timer, portMAX_DELAY); + + furi_timer_free(state->timer); free(state); } diff --git a/applications/services/desktop/scenes/desktop_scene_pin_timeout.c b/applications/services/desktop/scenes/desktop_scene_pin_timeout.c index 2f009e7d2..e3336ad76 100644 --- a/applications/services/desktop/scenes/desktop_scene_pin_timeout.c +++ b/applications/services/desktop/scenes/desktop_scene_pin_timeout.c @@ -1,6 +1,5 @@ #include #include -#include #include #include "../desktop_i.h" diff --git a/applications/services/desktop/views/desktop_view_locked.c b/applications/services/desktop/views/desktop_view_locked.c index 7c677fb31..88cbc7d55 100644 --- a/applications/services/desktop/views/desktop_view_locked.c +++ b/applications/services/desktop/views/desktop_view_locked.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -28,7 +27,7 @@ struct DesktopViewLocked { DesktopViewLockedCallback callback; void* context; - TimerHandle_t timer; + FuriTimer* timer; uint8_t lock_count; uint32_t lock_lastpress; }; @@ -58,8 +57,8 @@ void desktop_view_locked_set_callback( locked_view->context = context; } -static void locked_view_timer_callback(TimerHandle_t timer) { - DesktopViewLocked* locked_view = pvTimerGetTimerID(timer); +static void locked_view_timer_callback(void* context) { + DesktopViewLocked* locked_view = context; locked_view->callback(DesktopLockedEventUpdate, locked_view->context); } @@ -155,7 +154,7 @@ static void desktop_view_locked_update_hint_icon_timeout(DesktopViewLocked* lock model->view_state = DesktopViewLockedStateLockedHintShown; } view_commit_model(locked_view->view, change_state); - xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(LOCKED_HINT_TIMEOUT_MS), portMAX_DELAY); + furi_timer_start(locked_view->timer, LOCKED_HINT_TIMEOUT_MS); } void desktop_view_locked_update(DesktopViewLocked* locked_view) { @@ -182,7 +181,7 @@ void desktop_view_locked_update(DesktopViewLocked* locked_view) { if(view_state != DesktopViewLockedStateCoverClosing && view_state != DesktopViewLockedStateCoverOpening) { - xTimerStop(locked_view->timer, portMAX_DELAY); + furi_timer_stop(locked_view->timer); } } @@ -209,7 +208,7 @@ static bool desktop_view_locked_input(InputEvent* event, void* context) { furi_assert(context); bool is_changed = false; - const uint32_t press_time = xTaskGetTickCount(); + const uint32_t press_time = furi_get_tick(); DesktopViewLocked* locked_view = context; DesktopViewLockedModel* model = view_get_model(locked_view->view); if(model->view_state == DesktopViewLockedStateUnlockedHintShown && @@ -269,7 +268,7 @@ DesktopViewLocked* desktop_view_locked_alloc() { DesktopViewLocked* locked_view = malloc(sizeof(DesktopViewLocked)); locked_view->view = view_alloc(); locked_view->timer = - xTimerCreate(NULL, 1000 / 16, pdTRUE, locked_view, locked_view_timer_callback); + furi_timer_alloc(locked_view_timer_callback, FuriTimerTypePeriodic, locked_view); view_allocate_model(locked_view->view, ViewModelTypeLocking, sizeof(DesktopViewLockedModel)); view_set_context(locked_view->view, locked_view); @@ -292,7 +291,7 @@ void desktop_view_locked_close_cover(DesktopViewLocked* locked_view) { model->view_state = DesktopViewLockedStateCoverClosing; model->cover_offset = COVER_OFFSET_START; view_commit_model(locked_view->view, true); - xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(COVER_MOVING_INTERVAL_MS), portMAX_DELAY); + furi_timer_start(locked_view->timer, COVER_MOVING_INTERVAL_MS); } void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked) { @@ -310,7 +309,7 @@ void desktop_view_locked_unlock(DesktopViewLocked* locked_view) { model->cover_offset = COVER_OFFSET_END; model->pin_locked = false; view_commit_model(locked_view->view, true); - xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(COVER_MOVING_INTERVAL_MS), portMAX_DELAY); + furi_timer_start(locked_view->timer, COVER_MOVING_INTERVAL_MS); } bool desktop_view_locked_is_locked_hint_visible(DesktopViewLocked* locked_view) { diff --git a/applications/services/desktop/views/desktop_view_main.c b/applications/services/desktop/views/desktop_view_main.c index 1b8518aa1..8b84c6012 100644 --- a/applications/services/desktop/views/desktop_view_main.c +++ b/applications/services/desktop/views/desktop_view_main.c @@ -13,7 +13,7 @@ struct DesktopMainView { View* view; DesktopMainViewCallback callback; void* context; - TimerHandle_t _poweroff_timer; // Unused, kept for compatibility + FuriTimer* _poweroff_timer; // Unused, kept for compatibility bool _dummy_mode; // Unused, kept for compatibility }; diff --git a/applications/services/desktop/views/desktop_view_pin_input.c b/applications/services/desktop/views/desktop_view_pin_input.c index d3dadd7d7..0894bb776 100644 --- a/applications/services/desktop/views/desktop_view_pin_input.c +++ b/applications/services/desktop/views/desktop_view_pin_input.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "desktop_view_pin_input.h" #include @@ -21,7 +20,7 @@ struct DesktopViewPinInput { DesktopViewPinInputCallback timeout_callback; DesktopViewPinInputDoneCallback done_callback; void* context; - TimerHandle_t timer; + FuriTimer* timer; }; typedef struct { @@ -78,7 +77,7 @@ static bool desktop_view_pin_input_input(InputEvent* event, void* context) { } break; default: - furi_assert(0); + furi_crash(); break; } } @@ -90,7 +89,7 @@ static bool desktop_view_pin_input_input(InputEvent* event, void* context) { pin_input->back_callback(pin_input->context); } - xTimerStart(pin_input->timer, 0); + furi_timer_start(pin_input->timer, NO_ACTIVITY_TIMEOUT); return true; } @@ -129,7 +128,7 @@ static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInpu canvas_draw_icon_ex(canvas, x + 2, y + 3, &I_Pin_arrow_up_7x9, IconRotation90); break; default: - furi_assert(0); + furi_crash(); break; } } @@ -170,8 +169,8 @@ static void desktop_view_pin_input_draw(Canvas* canvas, void* context) { } } -void desktop_view_pin_input_timer_callback(TimerHandle_t timer) { - DesktopViewPinInput* pin_input = pvTimerGetTimerID(timer); +void desktop_view_pin_input_timer_callback(void* context) { + DesktopViewPinInput* pin_input = context; if(pin_input->timeout_callback) { pin_input->timeout_callback(pin_input->context); @@ -180,12 +179,12 @@ void desktop_view_pin_input_timer_callback(TimerHandle_t timer) { static void desktop_view_pin_input_enter(void* context) { DesktopViewPinInput* pin_input = context; - xTimerStart(pin_input->timer, portMAX_DELAY); + furi_timer_start(pin_input->timer, NO_ACTIVITY_TIMEOUT); } static void desktop_view_pin_input_exit(void* context) { DesktopViewPinInput* pin_input = context; - xTimerStop(pin_input->timer, portMAX_DELAY); + furi_timer_stop(pin_input->timer); } DesktopViewPinInput* desktop_view_pin_input_alloc(void) { @@ -195,12 +194,8 @@ DesktopViewPinInput* desktop_view_pin_input_alloc(void) { view_set_context(pin_input->view, pin_input); view_set_draw_callback(pin_input->view, desktop_view_pin_input_draw); view_set_input_callback(pin_input->view, desktop_view_pin_input_input); - pin_input->timer = xTimerCreate( - NULL, - pdMS_TO_TICKS(NO_ACTIVITY_TIMEOUT), - pdFALSE, - pin_input, - desktop_view_pin_input_timer_callback); + pin_input->timer = + furi_timer_alloc(desktop_view_pin_input_timer_callback, FuriTimerTypeOnce, pin_input); view_set_enter_callback(pin_input->view, desktop_view_pin_input_enter); view_set_exit_callback(pin_input->view, desktop_view_pin_input_exit); @@ -216,11 +211,7 @@ DesktopViewPinInput* desktop_view_pin_input_alloc(void) { void desktop_view_pin_input_free(DesktopViewPinInput* pin_input) { furi_assert(pin_input); - xTimerStop(pin_input->timer, portMAX_DELAY); - while(xTimerIsTimerActive(pin_input->timer)) { - furi_delay_tick(1); - } - xTimerDelete(pin_input->timer, portMAX_DELAY); + furi_timer_free(pin_input->timer); view_free(pin_input->view); free(pin_input); diff --git a/applications/services/desktop/views/desktop_view_pin_timeout.c b/applications/services/desktop/views/desktop_view_pin_timeout.c index e64c264ff..f24ecc8ea 100644 --- a/applications/services/desktop/views/desktop_view_pin_timeout.c +++ b/applications/services/desktop/views/desktop_view_pin_timeout.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -13,7 +12,7 @@ struct DesktopViewPinTimeout { View* view; - TimerHandle_t timer; + FuriTimer* timer; DesktopViewPinTimeoutDoneCallback callback; void* context; }; @@ -32,8 +31,8 @@ void desktop_view_pin_timeout_set_callback( instance->context = context; } -static void desktop_view_pin_timeout_timer_callback(TimerHandle_t timer) { - DesktopViewPinTimeout* instance = pvTimerGetTimerID(timer); +static void desktop_view_pin_timeout_timer_callback(void* context) { + DesktopViewPinTimeout* instance = context; bool stop = false; DesktopViewPinTimeoutModel* model = view_get_model(instance->view); @@ -45,7 +44,7 @@ static void desktop_view_pin_timeout_timer_callback(TimerHandle_t timer) { view_commit_model(instance->view, true); if(stop) { - xTimerStop(instance->timer, portMAX_DELAY); + furi_timer_stop(instance->timer); instance->callback(instance->context); } } @@ -73,15 +72,15 @@ static void desktop_view_pin_timeout_draw(Canvas* canvas, void* _model) { void desktop_view_pin_timeout_free(DesktopViewPinTimeout* instance) { view_free(instance->view); - xTimerDelete(instance->timer, portMAX_DELAY); + furi_timer_free(instance->timer); free(instance); } DesktopViewPinTimeout* desktop_view_pin_timeout_alloc(void) { DesktopViewPinTimeout* instance = malloc(sizeof(DesktopViewPinTimeout)); - instance->timer = xTimerCreate( - NULL, pdMS_TO_TICKS(1000), pdTRUE, instance, desktop_view_pin_timeout_timer_callback); + instance->timer = + furi_timer_alloc(desktop_view_pin_timeout_timer_callback, FuriTimerTypePeriodic, instance); instance->view = view_alloc(); view_allocate_model(instance->view, ViewModelTypeLockFree, sizeof(DesktopViewPinTimeoutModel)); @@ -101,7 +100,7 @@ void desktop_view_pin_timeout_start(DesktopViewPinTimeout* instance, uint32_t ti model->time_left = time_left; view_commit_model(instance->view, true); - xTimerStart(instance->timer, portMAX_DELAY); + furi_timer_start(instance->timer, 1000); } View* desktop_view_pin_timeout_get_view(DesktopViewPinTimeout* instance) { diff --git a/applications/services/dolphin/dolphin.c b/applications/services/dolphin/dolphin.c index 224af1df6..0120591bb 100644 --- a/applications/services/dolphin/dolphin.c +++ b/applications/services/dolphin/dolphin.c @@ -1,7 +1,6 @@ #include "dolphin/dolphin.h" #include "dolphin/helpers/dolphin_state.h" #include "dolphin_i.h" -#include "portmacro.h" #include "projdefs.h" #include #include @@ -10,7 +9,7 @@ #define DOLPHIN_LOCK_EVENT_FLAG (0x1) #define TAG "Dolphin" -#define HOURS_IN_TICKS(x) ((x)*60 * 60 * 1000) +#define HOURS_IN_TICKS(x) ((x) * 60 * 60 * 1000) static void dolphin_update_clear_limits_timer_period(Dolphin* dolphin); @@ -46,8 +45,8 @@ void dolphin_flush(Dolphin* dolphin) { dolphin_event_send_wait(dolphin, &event); } -void dolphin_butthurt_timer_callback(TimerHandle_t xTimer) { - Dolphin* dolphin = pvTimerGetTimerID(xTimer); +void dolphin_butthurt_timer_callback(void* context) { + Dolphin* dolphin = context; furi_assert(dolphin); DolphinEvent event; @@ -55,8 +54,8 @@ void dolphin_butthurt_timer_callback(TimerHandle_t xTimer) { dolphin_event_send_async(dolphin, &event); } -void dolphin_flush_timer_callback(TimerHandle_t xTimer) { - Dolphin* dolphin = pvTimerGetTimerID(xTimer); +void dolphin_flush_timer_callback(void* context) { + Dolphin* dolphin = context; furi_assert(dolphin); DolphinEvent event; @@ -64,11 +63,11 @@ void dolphin_flush_timer_callback(TimerHandle_t xTimer) { dolphin_event_send_async(dolphin, &event); } -void dolphin_clear_limits_timer_callback(TimerHandle_t xTimer) { - Dolphin* dolphin = pvTimerGetTimerID(xTimer); +void dolphin_clear_limits_timer_callback(void* context) { + Dolphin* dolphin = context; furi_assert(dolphin); - xTimerChangePeriod(dolphin->clear_limits_timer, HOURS_IN_TICKS(24), portMAX_DELAY); + furi_timer_start(dolphin->clear_limits_timer, HOURS_IN_TICKS(24)); DolphinEvent event; event.type = DolphinEventTypeClearLimits; @@ -81,17 +80,12 @@ Dolphin* dolphin_alloc() { dolphin->state = dolphin_state_alloc(); dolphin->event_queue = furi_message_queue_alloc(8, sizeof(DolphinEvent)); dolphin->pubsub = furi_pubsub_alloc(); - uint32_t butthurt_timer = xtreme_settings.butthurt_timer; - dolphin->butthurt_timer = xTimerCreate( - NULL, - butthurt_timer ? ((int32_t)butthurt_timer * 1000) : -1, - pdTRUE, - dolphin, - dolphin_butthurt_timer_callback); + dolphin->butthurt_timer = + furi_timer_alloc(dolphin_butthurt_timer_callback, FuriTimerTypePeriodic, dolphin); dolphin->flush_timer = - xTimerCreate(NULL, 30 * 1000, pdFALSE, dolphin, dolphin_flush_timer_callback); - dolphin->clear_limits_timer = xTimerCreate( - NULL, HOURS_IN_TICKS(24), pdTRUE, dolphin, dolphin_clear_limits_timer_callback); + furi_timer_alloc(dolphin_flush_timer_callback, FuriTimerTypeOnce, dolphin); + dolphin->clear_limits_timer = + furi_timer_alloc(dolphin_clear_limits_timer_callback, FuriTimerTypePeriodic, dolphin); return dolphin; } @@ -131,14 +125,14 @@ FuriPubSub* dolphin_get_pubsub(Dolphin* dolphin) { static void dolphin_update_clear_limits_timer_period(Dolphin* dolphin) { furi_assert(dolphin); - TickType_t now_ticks = xTaskGetTickCount(); - TickType_t timer_expires_at = xTimerGetExpiryTime(dolphin->clear_limits_timer); + uint32_t now_ticks = furi_get_tick(); + uint32_t timer_expires_at = furi_timer_get_expire_time(dolphin->clear_limits_timer); if((timer_expires_at - now_ticks) > HOURS_IN_TICKS(0.1)) { FuriHalRtcDateTime date; furi_hal_rtc_get_datetime(&date); - TickType_t now_time_in_ms = ((date.hour * 60 + date.minute) * 60 + date.second) * 1000; - TickType_t time_to_clear_limits = 0; + uint32_t now_time_in_ms = ((date.hour * 60 + date.minute) * 60 + date.second) * 1000; + uint32_t time_to_clear_limits = 0; if(date.hour < 5) { time_to_clear_limits = HOURS_IN_TICKS(5) - now_time_in_ms; @@ -146,7 +140,7 @@ static void dolphin_update_clear_limits_timer_period(Dolphin* dolphin) { time_to_clear_limits = HOURS_IN_TICKS(24 + 5) - now_time_in_ms; } - xTimerChangePeriod(dolphin->clear_limits_timer, time_to_clear_limits, portMAX_DELAY); + furi_timer_start(dolphin->clear_limits_timer, time_to_clear_limits); } } @@ -162,9 +156,10 @@ int32_t dolphin_srv(void* p) { furi_record_create(RECORD_DOLPHIN, dolphin); dolphin_state_load(dolphin->state); - xTimerReset(dolphin->butthurt_timer, portMAX_DELAY); + uint32_t butthurt_interval = xtreme_settings.butthurt_timer * 1000; + if(butthurt_interval) furi_timer_restart(dolphin->butthurt_timer, butthurt_interval); dolphin_update_clear_limits_timer_period(dolphin); - xTimerReset(dolphin->clear_limits_timer, portMAX_DELAY); + furi_timer_restart(dolphin->clear_limits_timer, HOURS_IN_TICKS(24)); DolphinEvent event; while(1) { @@ -174,8 +169,9 @@ int32_t dolphin_srv(void* p) { dolphin_state_on_deed(dolphin->state, event.deed); DolphinPubsubEvent event = DolphinPubsubEventUpdate; furi_pubsub_publish(dolphin->pubsub, &event); - xTimerReset(dolphin->butthurt_timer, portMAX_DELAY); - xTimerReset(dolphin->flush_timer, portMAX_DELAY); + if(butthurt_interval) + furi_timer_restart(dolphin->butthurt_timer, butthurt_interval); + furi_timer_restart(dolphin->flush_timer, 30 * 1000); } else if(event.type == DolphinEventTypeStats) { event.stats->icounter = dolphin->state->data.icounter; event.stats->butthurt = dolphin->state->data.butthurt; diff --git a/applications/services/dolphin/dolphin_i.h b/applications/services/dolphin/dolphin_i.h index ceeff1e1a..2d716c181 100644 --- a/applications/services/dolphin/dolphin_i.h +++ b/applications/services/dolphin/dolphin_i.h @@ -30,9 +30,9 @@ struct Dolphin { // Queue FuriMessageQueue* event_queue; FuriPubSub* pubsub; - TimerHandle_t butthurt_timer; - TimerHandle_t flush_timer; - TimerHandle_t clear_limits_timer; + FuriTimer* butthurt_timer; + FuriTimer* flush_timer; + FuriTimer* clear_limits_timer; }; Dolphin* dolphin_alloc(); diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 42814fb47..1eed4e2e3 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -174,7 +174,7 @@ void canvas_set_font(Canvas* canvas, Font font) { u8g2_SetFont(&canvas->fb, u8g2_font_eurocorp_tr); break; default: - furi_crash(NULL); + furi_crash(); break; } } @@ -215,7 +215,7 @@ void canvas_draw_str_aligned( x -= (u8g2_GetStrWidth(&canvas->fb, str) / 2); break; default: - furi_crash(NULL); + furi_crash(); break; } @@ -229,7 +229,7 @@ void canvas_draw_str_aligned( y += (u8g2_GetAscent(&canvas->fb) / 2); break; default: - furi_crash(NULL); + furi_crash(); break; } @@ -587,7 +587,7 @@ void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation) { rotate_cb = U8G2_R1; break; default: - furi_assert(0); + furi_crash(); } if(need_swap) FURI_SWAP(canvas->width, canvas->height); diff --git a/applications/services/gui/elements.c b/applications/services/gui/elements.c index 849bf18b6..49d2ef501 100644 --- a/applications/services/gui/elements.c +++ b/applications/services/gui/elements.c @@ -255,7 +255,7 @@ static size_t } else if(horizontal == AlignRight) { px_left = x; } else { - furi_assert(0); + furi_crash(); } if(len_px > px_left) { diff --git a/applications/services/gui/icon_animation.c b/applications/services/gui/icon_animation.c index b63d233f3..a39ef2e25 100644 --- a/applications/services/gui/icon_animation.c +++ b/applications/services/gui/icon_animation.c @@ -15,7 +15,6 @@ IconAnimation* icon_animation_alloc(const Icon* icon) { void icon_animation_free(IconAnimation* instance) { furi_assert(instance); icon_animation_stop(instance); - while(xTimerIsTimerActive(instance->timer) == pdTRUE) furi_delay_tick(1); furi_timer_free(instance->timer); free(instance); } @@ -67,10 +66,9 @@ void icon_animation_start(IconAnimation* instance) { instance->animating = true; furi_assert(instance->icon->frame_rate); furi_check( - xTimerChangePeriod( + furi_timer_start( instance->timer, - (furi_kernel_get_tick_frequency() / instance->icon->frame_rate), - portMAX_DELAY) == pdPASS); + (furi_kernel_get_tick_frequency() / instance->icon->frame_rate)) == FuriStatusOk); } } @@ -78,7 +76,7 @@ void icon_animation_stop(IconAnimation* instance) { furi_assert(instance); if(instance->animating) { instance->animating = false; - furi_check(xTimerStop(instance->timer, portMAX_DELAY) == pdPASS); + furi_timer_stop(instance->timer); instance->frame = 0; } } diff --git a/applications/services/gui/modules/byte_input.c b/applications/services/gui/modules/byte_input.c index 012400472..a597ca77a 100644 --- a/applications/services/gui/modules/byte_input.c +++ b/applications/services/gui/modules/byte_input.c @@ -79,7 +79,7 @@ static uint8_t byte_input_get_row_size(uint8_t row_index) { row_size = COUNT_OF(keyboard_keys_row_2); break; default: - furi_crash(NULL); + furi_crash(); } return row_size; @@ -102,7 +102,7 @@ static const ByteInputKey* byte_input_get_row(uint8_t row_index) { row = keyboard_keys_row_2; break; default: - furi_crash(NULL); + furi_crash(); } return row; diff --git a/applications/services/gui/modules/popup.c b/applications/services/gui/modules/popup.c index ad26b2691..520efceef 100644 --- a/applications/services/gui/modules/popup.c +++ b/applications/services/gui/modules/popup.c @@ -98,8 +98,8 @@ void popup_start_timer(void* context) { if(timer_period == 0) timer_period = 1; if(furi_timer_start(popup->timer, timer_period) != FuriStatusOk) { - furi_assert(0); - } + furi_crash(); + }; } } diff --git a/applications/services/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c index c961dcd19..671ca5ac0 100644 --- a/applications/services/gui/modules/text_input.c +++ b/applications/services/gui/modules/text_input.c @@ -189,7 +189,7 @@ static uint8_t get_row_size(const Keyboard* keyboard, uint8_t row_index) { row_size = COUNT_OF(symbol_keyboard_keys_row_3); break; default: - furi_crash(NULL); + furi_crash(); } } else { switch(row_index + 1) { @@ -203,7 +203,7 @@ static uint8_t get_row_size(const Keyboard* keyboard, uint8_t row_index) { row_size = COUNT_OF(keyboard_keys_row_3); break; default: - furi_crash(NULL); + furi_crash(); } } @@ -215,7 +215,7 @@ static const TextInputKey* get_row(const Keyboard* keyboard, uint8_t row_index) if(row_index < 3) { row = keyboard->rows[row_index]; } else { - furi_crash(NULL); + furi_crash(); } return row; diff --git a/applications/services/gui/view.c b/applications/services/gui/view.c index 07ae072a1..316f5c612 100644 --- a/applications/services/gui/view.c +++ b/applications/services/gui/view.c @@ -82,7 +82,7 @@ void view_allocate_model(View* view, ViewModelType type, size_t size) { model->data = malloc(size); view->model = model; } else { - furi_crash(NULL); + furi_crash(); } } @@ -99,7 +99,7 @@ void view_free_model(View* view) { free(model); view->model = NULL; } else { - furi_crash(NULL); + furi_crash(); } } diff --git a/applications/services/gui/view_dispatcher.c b/applications/services/gui/view_dispatcher.c index 0119abc20..87b07a87c 100644 --- a/applications/services/gui/view_dispatcher.c +++ b/applications/services/gui/view_dispatcher.c @@ -207,7 +207,7 @@ void view_dispatcher_attach_to_gui( } else if(type == ViewDispatcherTypeFullscreen) { gui_add_view_port(gui, view_dispatcher->view_port, GuiLayerFullscreen); } else { - furi_check(NULL); + furi_crash(); } view_dispatcher->gui = gui; } diff --git a/applications/services/input/input.c b/applications/services/input/input.c index 9ea1e6b5b..211d3ca16 100644 --- a/applications/services/input/input.c +++ b/applications/services/input/input.c @@ -6,20 +6,6 @@ static Input* input = NULL; -inline static void input_timer_start(FuriTimer* timer_id, uint32_t ticks) { - TimerHandle_t hTimer = (TimerHandle_t)timer_id; - furi_check(xTimerChangePeriod(hTimer, ticks, portMAX_DELAY) == pdPASS); -} - -inline static void input_timer_stop(FuriTimer* timer_id) { - TimerHandle_t hTimer = (TimerHandle_t)timer_id; - furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS); - // xTimerStop is not actually stopping timer, - // Instead it places stop event into timer queue - // This code ensures that timer is stopped - while(xTimerIsTimerActive(hTimer) == pdTRUE) furi_delay_tick(1); -} - void input_press_timer_callback(void* arg) { InputPinState* input_pin = arg; InputEvent event; @@ -140,10 +126,12 @@ int32_t input_srv(void* p) { input->counter++; input->pin_states[i].counter = input->counter; event.sequence_counter = input->pin_states[i].counter; - input_timer_start(input->pin_states[i].press_timer, INPUT_PRESS_TICKS); + furi_timer_start(input->pin_states[i].press_timer, INPUT_PRESS_TICKS); } else { event.sequence_counter = input->pin_states[i].counter; - input_timer_stop(input->pin_states[i].press_timer); + furi_timer_stop(input->pin_states[i].press_timer); + while(furi_timer_is_running(input->pin_states[i].press_timer)) + furi_delay_tick(1); if(input->pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) { event.type = InputTypeShort; furi_pubsub_publish(input->event_pubsub, &event); diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index c3a316c50..d09d070ef 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -308,7 +308,7 @@ static FlipperInternalApplication const* loader_find_application_by_name_in_list const FlipperInternalApplication* list, const uint32_t n_apps) { for(size_t i = 0; i < n_apps; i++) { - if(strcmp(name, list[i].name) == 0) { + if((strcmp(name, list[i].name) == 0) || (strcmp(name, list[i].appid) == 0)) { return &list[i]; } } diff --git a/applications/services/loader/loader.h b/applications/services/loader/loader.h index 0073df3de..f5f71b0d0 100644 --- a/applications/services/loader/loader.h +++ b/applications/services/loader/loader.h @@ -29,7 +29,7 @@ typedef struct { /** * @brief Start application * @param[in] instance loader instance - * @param[in] name application name + * @param[in] name application name or id * @param[in] args application arguments * @param[out] error_message detailed error message, can be NULL * @return LoaderStatus @@ -40,7 +40,7 @@ LoaderStatus /** * @brief Start application with GUI error message * @param[in] instance loader instance - * @param[in] name application name + * @param[in] name application name or id * @param[in] args application arguments * @return LoaderStatus */ diff --git a/applications/services/rpc/rpc.c b/applications/services/rpc/rpc.c index 791b14478..2c0950025 100644 --- a/applications/services/rpc/rpc.c +++ b/applications/services/rpc/rpc.c @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -164,7 +163,7 @@ void rpc_session_set_terminated_callback( * odd: client sends close request and sends command after. */ size_t - rpc_session_feed(RpcSession* session, uint8_t* encoded_bytes, size_t size, TickType_t timeout) { + rpc_session_feed(RpcSession* session, uint8_t* encoded_bytes, size_t size, uint32_t timeout) { furi_assert(session); furi_assert(encoded_bytes); @@ -483,12 +482,15 @@ void rpc_send_and_release(RpcSession* session, PB_Main* message) { } void rpc_send_and_release_empty(RpcSession* session, uint32_t command_id, PB_CommandStatus status) { + furi_assert(session); + PB_Main message = { .command_id = command_id, .command_status = status, .has_next = false, .which_content = PB_Main_empty_tag, }; + rpc_send_and_release(session, &message); pb_release(&PB_Main_msg, &message); } diff --git a/applications/services/rpc/rpc.h b/applications/services/rpc/rpc.h index d11fdc162..863bca355 100644 --- a/applications/services/rpc/rpc.h +++ b/applications/services/rpc/rpc.h @@ -124,7 +124,7 @@ void rpc_session_set_terminated_callback( * * @return actually consumed bytes */ -size_t rpc_session_feed(RpcSession* session, uint8_t* buffer, size_t size, TickType_t timeout); +size_t rpc_session_feed(RpcSession* session, uint8_t* buffer, size_t size, uint32_t timeout); /** Get available size of RPC buffer * diff --git a/applications/services/rpc/rpc_app.c b/applications/services/rpc/rpc_app.c index bf44ed2de..9af652dae 100644 --- a/applications/services/rpc/rpc_app.c +++ b/applications/services/rpc/rpc_app.c @@ -10,49 +10,85 @@ struct RpcAppSystem { RpcSession* session; - RpcAppSystemCallback app_callback; - void* app_context; + RpcAppSystemCallback callback; + void* callback_context; - RpcAppSystemDataExchangeCallback data_exchange_callback; - void* data_exchange_context; + uint32_t error_code; + char* error_text; - PB_Main* state_msg; - PB_Main* error_msg; - - uint32_t last_id; - char* last_data; + uint32_t last_command_id; + RpcAppSystemEventType last_event_type; }; #define RPC_SYSTEM_APP_TEMP_ARGS_SIZE 16 +static void rpc_system_app_send_state_response( + RpcAppSystem* rpc_app, + PB_App_AppState state, + const char* name) { + PB_Main* response = malloc(sizeof(PB_Main)); + + response->which_content = PB_Main_app_state_response_tag; + response->content.app_state_response.state = state; + + FURI_LOG_D(TAG, "%s", name); + rpc_send(rpc_app->session, response); + + free(response); +} + +static void rpc_system_app_send_error_response( + RpcAppSystem* rpc_app, + uint32_t command_id, + PB_CommandStatus status, + const char* name) { + // Not describing all possible errors as only APP_NOT_RUNNING is used + const char* status_str = status == PB_CommandStatus_ERROR_APP_NOT_RUNNING ? "APP_NOT_RUNNING" : + "UNKNOWN"; + FURI_LOG_E(TAG, "%s: %s, id %lu, status: %d", name, status_str, command_id, status); + rpc_send_and_release_empty(rpc_app->session, command_id, status); +} + +static void rpc_system_app_set_last_command( + RpcAppSystem* rpc_app, + uint32_t command_id, + const RpcAppSystemEvent* event) { + furi_assert(rpc_app->last_command_id == 0); + furi_assert(rpc_app->last_event_type == RpcAppEventTypeInvalid); + + rpc_app->last_command_id = command_id; + rpc_app->last_event_type = event->type; +} + static void rpc_system_app_start_process(const PB_Main* request, void* context) { furi_assert(request); - furi_assert(context); - furi_assert(request->which_content == PB_Main_app_start_request_tag); - RpcAppSystem* rpc_app = context; - RpcSession* session = rpc_app->session; - rpc_system_app_error_reset(rpc_app); - furi_assert(session); - char args_temp[RPC_SYSTEM_APP_TEMP_ARGS_SIZE]; - furi_assert(!rpc_app->last_id); - furi_assert(!rpc_app->last_data); + RpcAppSystem* rpc_app = context; + furi_assert(rpc_app); + furi_assert(rpc_app->last_command_id == 0); + furi_assert(rpc_app->last_event_type == RpcAppEventTypeInvalid); FURI_LOG_D(TAG, "StartProcess: id %lu", request->command_id); - PB_CommandStatus result; - Loader* loader = furi_record_open(RECORD_LOADER); const char* app_name = request->content.app_start_request.name; + + PB_CommandStatus result; + if(app_name) { + rpc_system_app_error_reset(rpc_app); + + char app_args_temp[RPC_SYSTEM_APP_TEMP_ARGS_SIZE]; const char* app_args = request->content.app_start_request.args; + if(app_args && strcmp(app_args, "RPC") == 0) { // If app is being started in RPC mode - pass RPC context via args string - snprintf(args_temp, RPC_SYSTEM_APP_TEMP_ARGS_SIZE, "RPC %08lX", (uint32_t)rpc_app); - app_args = args_temp; + snprintf(app_args_temp, RPC_SYSTEM_APP_TEMP_ARGS_SIZE, "RPC %08lX", (uint32_t)rpc_app); + app_args = app_args_temp; } - LoaderStatus status = loader_start(loader, app_name, app_args, NULL); + + const LoaderStatus status = loader_start(loader, app_name, app_args, NULL); if(status == LoaderStatusErrorAppStarted) { result = PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED; } else if(status == LoaderStatusErrorInternal) { @@ -62,7 +98,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) } else if(status == LoaderStatusOk) { result = PB_CommandStatus_OK; } else { - furi_crash(NULL); + furi_crash(); } } else { result = PB_CommandStatus_ERROR_INVALID_PARAMETERS; @@ -71,266 +107,271 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) furi_record_close(RECORD_LOADER); FURI_LOG_D(TAG, "StartProcess: response id %lu, result %d", request->command_id, result); - rpc_send_and_release_empty(session, request->command_id, result); + rpc_send_and_release_empty(rpc_app->session, request->command_id, result); } static void rpc_system_app_lock_status_process(const PB_Main* request, void* context) { furi_assert(request); - furi_assert(context); - furi_assert(request->which_content == PB_Main_app_lock_status_request_tag); + RpcAppSystem* rpc_app = context; + furi_assert(rpc_app); + rpc_system_app_error_reset(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); FURI_LOG_D(TAG, "LockStatus"); + PB_Main* response = malloc(sizeof(PB_Main)); + + response->command_id = request->command_id; + response->which_content = PB_Main_app_lock_status_response_tag; + Loader* loader = furi_record_open(RECORD_LOADER); - - PB_Main response = { - .has_next = false, - .command_status = PB_CommandStatus_OK, - .command_id = request->command_id, - .which_content = PB_Main_app_lock_status_response_tag, - }; - - response.content.app_lock_status_response.locked = loader_is_locked(loader); - + response->content.app_lock_status_response.locked = loader_is_locked(loader); furi_record_close(RECORD_LOADER); FURI_LOG_D(TAG, "LockStatus: response"); - rpc_send_and_release(session, &response); - pb_release(&PB_Main_msg, &response); + rpc_send_and_release(rpc_app->session, response); + + free(response); } static void rpc_system_app_exit_request(const PB_Main* request, void* context) { furi_assert(request); - furi_assert(context); - furi_assert(request->which_content == PB_Main_app_exit_request_tag); + RpcAppSystem* rpc_app = context; - rpc_system_app_error_reset(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); + furi_assert(rpc_app); - PB_CommandStatus status; - - if(rpc_app->app_callback) { + if(rpc_app->callback) { FURI_LOG_D(TAG, "ExitRequest: id %lu", request->command_id); - furi_assert(!rpc_app->last_id); - furi_assert(!rpc_app->last_data); - rpc_app->last_id = request->command_id; - rpc_app->app_callback(RpcAppEventAppExit, rpc_app->app_context); + + const RpcAppSystemEvent event = { + .type = RpcAppEventTypeAppExit, + .data = + { + .type = RpcAppSystemEventDataTypeNone, + {0}, + }, + }; + + rpc_system_app_error_reset(rpc_app); + rpc_system_app_set_last_command(rpc_app, request->command_id, &event); + + rpc_app->callback(&event, rpc_app->callback_context); + } else { - status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; - FURI_LOG_E( - TAG, "ExitRequest: APP_NOT_RUNNING, id %lu, status: %d", request->command_id, status); - rpc_send_and_release_empty(session, request->command_id, status); + rpc_system_app_send_error_response( + rpc_app, request->command_id, PB_CommandStatus_ERROR_APP_NOT_RUNNING, "ExitRequest"); } } static void rpc_system_app_load_file(const PB_Main* request, void* context) { furi_assert(request); - furi_assert(context); - furi_assert(request->which_content == PB_Main_app_load_file_request_tag); - RpcAppSystem* rpc_app = context; - rpc_system_app_error_reset(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); - PB_CommandStatus status; - if(rpc_app->app_callback) { + RpcAppSystem* rpc_app = context; + furi_assert(rpc_app); + + if(rpc_app->callback) { FURI_LOG_D(TAG, "LoadFile: id %lu", request->command_id); - furi_assert(!rpc_app->last_id); - furi_assert(!rpc_app->last_data); - rpc_app->last_id = request->command_id; - rpc_app->last_data = strdup(request->content.app_load_file_request.path); - rpc_app->app_callback(RpcAppEventLoadFile, rpc_app->app_context); + + const RpcAppSystemEvent event = { + .type = RpcAppEventTypeLoadFile, + .data = + { + .type = RpcAppSystemEventDataTypeString, + .string = request->content.app_load_file_request.path, + }, + }; + + rpc_system_app_error_reset(rpc_app); + rpc_system_app_set_last_command(rpc_app, request->command_id, &event); + + rpc_app->callback(&event, rpc_app->callback_context); + } else { - status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; - FURI_LOG_E( - TAG, "LoadFile: APP_NOT_RUNNING, id %lu, status: %d", request->command_id, status); - rpc_send_and_release_empty(session, request->command_id, status); + rpc_system_app_send_error_response( + rpc_app, request->command_id, PB_CommandStatus_ERROR_APP_NOT_RUNNING, "LoadFile"); } } static void rpc_system_app_button_press(const PB_Main* request, void* context) { furi_assert(request); - furi_assert(context); - furi_assert(request->which_content == PB_Main_app_button_press_request_tag); - RpcAppSystem* rpc_app = context; - rpc_system_app_error_reset(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); - PB_CommandStatus status; - if(rpc_app->app_callback) { + RpcAppSystem* rpc_app = context; + furi_assert(rpc_app); + + if(rpc_app->callback) { FURI_LOG_D(TAG, "ButtonPress"); - furi_assert(!rpc_app->last_id); - furi_assert(!rpc_app->last_data); - rpc_app->last_id = request->command_id; - rpc_app->last_data = strdup(request->content.app_button_press_request.args); - rpc_app->app_callback(RpcAppEventButtonPress, rpc_app->app_context); + + RpcAppSystemEvent event; + event.type = RpcAppEventTypeButtonPress; + + if(strlen(request->content.app_button_press_request.args) != 0) { + event.data.type = RpcAppSystemEventDataTypeString; + event.data.string = request->content.app_button_press_request.args; + } else { + event.data.type = RpcAppSystemEventDataTypeInt32; + event.data.i32 = request->content.app_button_press_request.index; + } + + rpc_system_app_error_reset(rpc_app); + rpc_system_app_set_last_command(rpc_app, request->command_id, &event); + + rpc_app->callback(&event, rpc_app->callback_context); + } else { - status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; - FURI_LOG_E( - TAG, "ButtonPress: APP_NOT_RUNNING, id %lu, status: %d", request->command_id, status); - rpc_send_and_release_empty(session, request->command_id, status); + rpc_system_app_send_error_response( + rpc_app, request->command_id, PB_CommandStatus_ERROR_APP_NOT_RUNNING, "ButtonPress"); } } static void rpc_system_app_button_release(const PB_Main* request, void* context) { furi_assert(request); furi_assert(request->which_content == PB_Main_app_button_release_request_tag); - furi_assert(context); RpcAppSystem* rpc_app = context; - rpc_system_app_error_reset(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); + furi_assert(rpc_app); - PB_CommandStatus status; - if(rpc_app->app_callback) { + if(rpc_app->callback) { FURI_LOG_D(TAG, "ButtonRelease"); - furi_assert(!rpc_app->last_id); - furi_assert(!rpc_app->last_data); - rpc_app->last_id = request->command_id; - rpc_app->app_callback(RpcAppEventButtonRelease, rpc_app->app_context); + + const RpcAppSystemEvent event = { + .type = RpcAppEventTypeButtonRelease, + .data = + { + .type = RpcAppSystemEventDataTypeNone, + {0}, + }, + }; + + rpc_system_app_error_reset(rpc_app); + rpc_system_app_set_last_command(rpc_app, request->command_id, &event); + + rpc_app->callback(&event, rpc_app->callback_context); + } else { - status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; - FURI_LOG_E( - TAG, "ButtonRelease: APP_NOT_RUNNING, id %lu, status: %d", request->command_id, status); - rpc_send_and_release_empty(session, request->command_id, status); + rpc_system_app_send_error_response( + rpc_app, request->command_id, PB_CommandStatus_ERROR_APP_NOT_RUNNING, "ButtonRelease"); } } static void rpc_system_app_get_error_process(const PB_Main* request, void* context) { furi_assert(request); furi_assert(request->which_content == PB_Main_app_get_error_request_tag); - furi_assert(context); RpcAppSystem* rpc_app = context; - RpcSession* session = rpc_app->session; - furi_assert(session); + furi_assert(rpc_app); - rpc_app->error_msg->command_id = request->command_id; + PB_Main* response = malloc(sizeof(PB_Main)); + + response->command_id = request->command_id; + response->which_content = PB_Main_app_get_error_response_tag; + response->content.app_get_error_response.code = rpc_app->error_code; + response->content.app_get_error_response.text = rpc_app->error_text; FURI_LOG_D(TAG, "GetError"); - rpc_send(session, rpc_app->error_msg); + rpc_send(rpc_app->session, response); + + free(response); } static void rpc_system_app_data_exchange_process(const PB_Main* request, void* context) { furi_assert(request); furi_assert(request->which_content == PB_Main_app_data_exchange_request_tag); - furi_assert(context); RpcAppSystem* rpc_app = context; - rpc_system_app_error_reset(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); + furi_assert(rpc_app); - PB_CommandStatus command_status; - pb_bytes_array_t* data = request->content.app_data_exchange_request.data; + if(rpc_app->callback) { + FURI_LOG_D(TAG, "DataExchange"); - if(rpc_app->data_exchange_callback) { - uint8_t* data_bytes = NULL; - size_t data_size = 0; - if(data) { - data_bytes = data->bytes; - data_size = data->size; - } - rpc_app->data_exchange_callback(data_bytes, data_size, rpc_app->data_exchange_context); - command_status = PB_CommandStatus_OK; + const pb_bytes_array_t* data = request->content.app_data_exchange_request.data; + + const RpcAppSystemEvent event = { + .type = RpcAppEventTypeDataExchange, + .data = + { + .type = RpcAppSystemEventDataTypeBytes, + .bytes = + { + .ptr = data ? data->bytes : NULL, + .size = data ? data->size : 0, + }, + }, + }; + + rpc_system_app_error_reset(rpc_app); + rpc_system_app_set_last_command(rpc_app, request->command_id, &event); + + rpc_app->callback(&event, rpc_app->callback_context); } else { - command_status = PB_CommandStatus_ERROR_APP_CMD_ERROR; + rpc_system_app_send_error_response( + rpc_app, request->command_id, PB_CommandStatus_ERROR_APP_NOT_RUNNING, "DataExchange"); } - - FURI_LOG_D(TAG, "DataExchange"); - rpc_send_and_release_empty(session, request->command_id, command_status); } void rpc_system_app_send_started(RpcAppSystem* rpc_app) { furi_assert(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); - - rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_STARTED; - - FURI_LOG_D(TAG, "SendStarted"); - rpc_send(session, rpc_app->state_msg); + rpc_system_app_send_state_response(rpc_app, PB_App_AppState_APP_STARTED, "SendStarted"); } void rpc_system_app_send_exited(RpcAppSystem* rpc_app) { furi_assert(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); - - rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_CLOSED; - - FURI_LOG_D(TAG, "SendExit"); - rpc_send(session, rpc_app->state_msg); + rpc_system_app_send_state_response(rpc_app, PB_App_AppState_APP_CLOSED, "SendExit"); } -const char* rpc_system_app_get_data(RpcAppSystem* rpc_app) { +void rpc_system_app_confirm(RpcAppSystem* rpc_app, bool result) { furi_assert(rpc_app); - furi_assert(rpc_app->last_data); - return rpc_app->last_data; -} + furi_assert(rpc_app->last_command_id != 0); + /* Ensure that only commands of these types can be confirmed */ + furi_assert( + rpc_app->last_event_type == RpcAppEventTypeAppExit || + rpc_app->last_event_type == RpcAppEventTypeLoadFile || + rpc_app->last_event_type == RpcAppEventTypeButtonPress || + rpc_app->last_event_type == RpcAppEventTypeButtonRelease || + rpc_app->last_event_type == RpcAppEventTypeDataExchange); -void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result) { - furi_assert(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); - furi_assert(rpc_app->last_id); + const uint32_t last_command_id = rpc_app->last_command_id; + const RpcAppSystemEventType last_event_type = rpc_app->last_event_type; - PB_CommandStatus status = result ? PB_CommandStatus_OK : PB_CommandStatus_ERROR_APP_CMD_ERROR; + rpc_app->last_command_id = 0; + rpc_app->last_event_type = RpcAppEventTypeInvalid; - uint32_t last_id = 0; - switch(event) { - case RpcAppEventAppExit: - case RpcAppEventLoadFile: - case RpcAppEventButtonPress: - case RpcAppEventButtonRelease: - last_id = rpc_app->last_id; - rpc_app->last_id = 0; - if(rpc_app->last_data) { - free(rpc_app->last_data); - rpc_app->last_data = NULL; - } - FURI_LOG_D(TAG, "AppConfirm: event %d last_id %lu status %d", event, last_id, status); - rpc_send_and_release_empty(session, last_id, status); - break; - default: - furi_crash("RPC App state programming Error"); - break; - } + const PB_CommandStatus status = result ? PB_CommandStatus_OK : + PB_CommandStatus_ERROR_APP_CMD_ERROR; + FURI_LOG_D( + TAG, + "AppConfirm: event %d last_id %lu status %d", + last_event_type, + last_command_id, + status); + + rpc_send_and_release_empty(rpc_app->session, last_command_id, status); } void rpc_system_app_set_callback(RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* ctx) { furi_assert(rpc_app); - rpc_app->app_callback = callback; - rpc_app->app_context = ctx; + rpc_app->callback = callback; + rpc_app->callback_context = ctx; } void rpc_system_app_set_error_code(RpcAppSystem* rpc_app, uint32_t error_code) { furi_assert(rpc_app); - PB_App_GetErrorResponse* content = &rpc_app->error_msg->content.app_get_error_response; - content->code = error_code; + rpc_app->error_code = error_code; } void rpc_system_app_set_error_text(RpcAppSystem* rpc_app, const char* error_text) { furi_assert(rpc_app); - PB_App_GetErrorResponse* content = &rpc_app->error_msg->content.app_get_error_response; - if(content->text) { - free(content->text); + if(rpc_app->error_text) { + free(rpc_app->error_text); } - content->text = error_text ? strdup(error_text) : NULL; + rpc_app->error_text = error_text ? strdup(error_text) : NULL; } void rpc_system_app_error_reset(RpcAppSystem* rpc_app) { @@ -340,29 +381,13 @@ void rpc_system_app_error_reset(RpcAppSystem* rpc_app) { rpc_system_app_set_error_text(rpc_app, NULL); } -void rpc_system_app_set_data_exchange_callback( - RpcAppSystem* rpc_app, - RpcAppSystemDataExchangeCallback callback, - void* ctx) { - furi_assert(rpc_app); - - rpc_app->data_exchange_callback = callback; - rpc_app->data_exchange_context = ctx; -} - void rpc_system_app_exchange_data(RpcAppSystem* rpc_app, const uint8_t* data, size_t data_size) { furi_assert(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); - PB_Main message = { - .command_id = 0, - .command_status = PB_CommandStatus_OK, - .has_next = false, - .which_content = PB_Main_app_data_exchange_request_tag, - }; + PB_Main* request = malloc(sizeof(PB_Main)); - PB_App_DataExchangeRequest* content = &message.content.app_data_exchange_request; + request->which_content = PB_Main_app_data_exchange_request_tag; + PB_App_DataExchangeRequest* content = &request->content.app_data_exchange_request; if(data && data_size) { content->data = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data_size)); @@ -372,7 +397,9 @@ void rpc_system_app_exchange_data(RpcAppSystem* rpc_app, const uint8_t* data, si content->data = NULL; } - rpc_send_and_release(session, &message); + rpc_send_and_release(rpc_app->session, request); + + free(request); } void* rpc_system_app_alloc(RpcSession* session) { @@ -381,18 +408,6 @@ void* rpc_system_app_alloc(RpcSession* session) { RpcAppSystem* rpc_app = malloc(sizeof(RpcAppSystem)); rpc_app->session = session; - // App exit message - rpc_app->state_msg = malloc(sizeof(PB_Main)); - rpc_app->state_msg->which_content = PB_Main_app_state_response_tag; - rpc_app->state_msg->command_status = PB_CommandStatus_OK; - - // App error message - rpc_app->error_msg = malloc(sizeof(PB_Main)); - rpc_app->error_msg->which_content = PB_Main_app_get_error_response_tag; - rpc_app->error_msg->command_status = PB_CommandStatus_OK; - rpc_app->error_msg->content.app_get_error_response.code = 0; - rpc_app->error_msg->content.app_get_error_response.text = NULL; - RpcHandler rpc_handler = { .message_handler = NULL, .decode_submessage = NULL, @@ -429,24 +444,24 @@ void* rpc_system_app_alloc(RpcSession* session) { void rpc_system_app_free(void* context) { RpcAppSystem* rpc_app = context; furi_assert(rpc_app); - RpcSession* session = rpc_app->session; - furi_assert(session); + furi_assert(rpc_app->session); - if(rpc_app->app_callback) { - rpc_app->app_callback(RpcAppEventSessionClose, rpc_app->app_context); + if(rpc_app->callback) { + const RpcAppSystemEvent event = { + .type = RpcAppEventTypeSessionClose, + .data = + { + .type = RpcAppSystemEventDataTypeNone, + {0}, + }, + }; + + rpc_app->callback(&event, rpc_app->callback_context); } - while(rpc_app->app_callback) { + while(rpc_app->callback) { furi_delay_tick(1); } - furi_assert(!rpc_app->data_exchange_callback); - - if(rpc_app->last_data) free(rpc_app->last_data); - - pb_release(&PB_Main_msg, rpc_app->error_msg); - - free(rpc_app->error_msg); - free(rpc_app->state_msg); free(rpc_app); } diff --git a/applications/services/rpc/rpc_app.h b/applications/services/rpc/rpc_app.h index d5c6fee96..4ee5a24d3 100644 --- a/applications/services/rpc/rpc_app.h +++ b/applications/services/rpc/rpc_app.h @@ -1,45 +1,213 @@ +/** + * @file rpc_app.h + * @brief Application RPC subsystem interface. + * + * The application RPC subsystem provides facilities for interacting with applications, + * such as starting/stopping, passing parameters, sending commands and exchanging arbitrary data. + * + * All commands are handled asynchronously via a user-settable callback. + * + * For a complete description of message types handled in this subsystem, + * see https://github.com/flipperdevices/flipperzero-protobuf/blob/dev/application.proto + */ #pragma once + #include "rpc.h" #ifdef __cplusplus extern "C" { #endif +/** + * @brief Enumeration of possible event data types. + */ typedef enum { - RpcAppEventSessionClose, - RpcAppEventAppExit, - RpcAppEventLoadFile, - RpcAppEventButtonPress, - RpcAppEventButtonRelease, + RpcAppSystemEventDataTypeNone, /**< No data is provided by the event. */ + RpcAppSystemEventDataTypeString, /**< Event data contains a zero-terminated string. */ + RpcAppSystemEventDataTypeInt32, /**< Event data contains a signed 32-bit integer. */ + RpcAppSystemEventDataTypeBytes, /**< Event data contains zero or more bytes. */ +} RpcAppSystemEventDataType; + +/** + * @brief Event data structure, containing the type and associated data. + * + * All below fields except for type are valid only if the respective type is set. + */ +typedef struct { + RpcAppSystemEventDataType + type; /**< Type of the data. The meaning of other fields depends on this one. */ + union { + const char* string; /**< Pointer to a zero-terminated character string. */ + int32_t i32; /**< Signed 32-bit integer value. */ + struct { + const uint8_t* ptr; /**< Pointer to the byte array data. */ + size_t size; /**< Size of the byte array, in bytes. */ + } bytes; /**< Byte array of arbitrary length. */ + }; +} RpcAppSystemEventData; + +/** + * @brief Enumeration of possible event types. + */ +typedef enum { + /** + * @brief Denotes an invalid state. + * + * An event of this type shall never be passed into the callback. + */ + RpcAppEventTypeInvalid, + /** + * @brief The client side has closed the session. + * + * After receiving this event, the RPC context is no more valid. + */ + RpcAppEventTypeSessionClose, + /** + * @brief The client has requested the application to exit. + * + * The application must exit after receiving this command. + */ + RpcAppEventTypeAppExit, + /** + * @brief The client has requested the application to load a file. + * + * This command's meaning is application-specific, i.e. the application might or + * might not require additional commands after loading a file to do anything useful. + */ + RpcAppEventTypeLoadFile, + /** + * @brief The client has informed the application that a button has been pressed. + * + * This command's meaning is application-specific, e.g. to select a part of the + * previously loaded file or to invoke a particular function within the application. + */ + RpcAppEventTypeButtonPress, + /** + * @brief The client has informed the application that a button has been released. + * + * This command's meaning is application-specific, e.g. to cease + * all activities to be conducted while a button is being pressed. + */ + RpcAppEventTypeButtonRelease, + /** + * @brief The client has sent a byte array of arbitrary size. + * + * This command's purpose is bi-directional exchange of arbitrary raw data. + * Useful for implementing higher-level protocols while using the RPC as a transport layer. + */ + RpcAppEventTypeDataExchange, +} RpcAppSystemEventType; + +/** + * @brief RPC application subsystem event structure. + */ +typedef struct { + RpcAppSystemEventType type; /**< Type of the event. */ + RpcAppSystemEventData data; /**< Data associated with the event. */ } RpcAppSystemEvent; -typedef void (*RpcAppSystemCallback)(RpcAppSystemEvent event, void* context); -typedef void ( - *RpcAppSystemDataExchangeCallback)(const uint8_t* data, size_t data_size, void* context); +/** + * @brief Callback function type. + * + * A function of this type must be passed to rpc_system_app_set_callback() by the user code. + * + * @warning The event pointer is valid ONLY inside the callback function. + * + * @param[in] event pointer to the event object. Valid only inside the callback function. + * @param[in,out] context pointer to the user-defined context object. + */ +typedef void (*RpcAppSystemCallback)(const RpcAppSystemEvent* event, void* context); +/** + * @brief RPC application subsystem opaque type declaration. + */ typedef struct RpcAppSystem RpcAppSystem; -void rpc_system_app_set_callback(RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* ctx); +/** + * @brief Set the callback function for use by an RpcAppSystem instance. + * + * @param[in,out] rpc_app pointer to the instance to be configured. + * @param[in] callback pointer to the function to be called upon message reception. + * @param[in,out] context pointer to the user-defined context object. Will be passed to the callback. + */ +void rpc_system_app_set_callback( + RpcAppSystem* rpc_app, + RpcAppSystemCallback callback, + void* context); +/** + * @brief Send a notification that an RpcAppSystem instance has been started and is ready. + * + * Call this function once right after acquiring an RPC context and setting the callback. + * + * @param[in,out] rpc_app pointer to the instance to be used. + */ void rpc_system_app_send_started(RpcAppSystem* rpc_app); +/** + * @brief Send a notification that the application using an RpcAppSystem instance is about to exit. + * + * Call this function when the application is about to exit (usually in the *_free() function). + * + * @param[in,out] rpc_app pointer to the instance to be used. + */ void rpc_system_app_send_exited(RpcAppSystem* rpc_app); -const char* rpc_system_app_get_data(RpcAppSystem* rpc_app); - -void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result); +/** + * @brief Send a confirmation that the application using an RpcAppSystem instance has handled the event. + * + * An explicit confirmation is required for the following event types: + * - RpcAppEventTypeAppExit + * - RpcAppEventTypeLoadFile + * - RpcAppEventTypeButtonPress + * - RpcAppEventTypeButtonRelease + * - RpcAppEventTypeDataExchange + * + * Not confirming these events will result in a client-side timeout. + * + * @param[in,out] rpc_app pointer to the instance to be used. + * @param[in] result whether the command was successfully handled or not (true for success). + */ +void rpc_system_app_confirm(RpcAppSystem* rpc_app, bool result); +/** + * @brief Set the error code stored in an RpcAppSystem instance. + * + * The error code can be retrieved by the client at any time by using the GetError request. + * The error code value has no meaning within the subsystem, i.e. it is only passed through to the client. + * + * @param[in,out] rpc_app pointer to the instance to be modified. + * @param[in] error_code arbitrary error code to be set. + */ void rpc_system_app_set_error_code(RpcAppSystem* rpc_app, uint32_t error_code); +/** + * @brief Set the error text stored in an RpcAppSystem instance. + * + * The error text can be retrieved by the client at any time by using the GetError request. + * The text has no meaning within the subsystem, i.e. it is only passed through to the client. + * + * @param[in,out] rpc_app pointer to the instance to be modified. + * @param[in] error_text Pointer to a zero-terminated string containing the error text. + */ void rpc_system_app_set_error_text(RpcAppSystem* rpc_app, const char* error_text); +/** + * @brief Reset the error code and text stored in an RpcAppSystem instance. + * + * Resets the error code to 0 and error text to "" (empty string). + * + * @param[in,out] rpc_app pointer to the instance to be reset. + */ void rpc_system_app_error_reset(RpcAppSystem* rpc_app); -void rpc_system_app_set_data_exchange_callback( - RpcAppSystem* rpc_app, - RpcAppSystemDataExchangeCallback callback, - void* ctx); - +/** + * @brief Send a byte array of arbitrary data to the client using an RpcAppSystem instance. + * + * @param[in,out] rpc_app pointer to the instance to be used. + * @param[in] data pointer to the data buffer to be sent. + * @param[in] data_size size of the data buffer, in bytes. + */ void rpc_system_app_exchange_data(RpcAppSystem* rpc_app, const uint8_t* data, size_t data_size); #ifdef __cplusplus diff --git a/applications/services/rpc/rpc_cli.c b/applications/services/rpc/rpc_cli.c index f1c139b5f..4612752a8 100644 --- a/applications/services/rpc/rpc_cli.c +++ b/applications/services/rpc/rpc_cli.c @@ -2,7 +2,6 @@ #include #include #include -#include #define TAG "RpcCli" diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c index e69a189e0..7379e4f27 100644 --- a/applications/services/storage/storage_cli.c +++ b/applications/services/storage/storage_cli.c @@ -335,11 +335,9 @@ static void storage_cli_write_chunk(Cli* cli, FuriString* path, FuriString* args if(buffer_size) { uint8_t* buffer = malloc(buffer_size); - for(uint32_t i = 0; i < buffer_size; i++) { - buffer[i] = cli_getc(cli); - } + size_t read_bytes = cli_read(cli, buffer, buffer_size); - uint16_t written_size = storage_file_write(file, buffer, buffer_size); + uint16_t written_size = storage_file_write(file, buffer, read_bytes); if(written_size != buffer_size) { storage_cli_print_error(storage_file_get_error(file)); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c index 26b58d9ac..2264a2899 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c @@ -67,7 +67,7 @@ bool desktop_settings_scene_pin_auth_on_event(void* context, SceneManagerEvent e } else if(state == SCENE_STATE_PIN_AUTH_DISABLE) { scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinDisable); } else { - furi_assert(0); + furi_crash(); } consumed = true; break; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c index dbb69c1b9..32418cfca 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c @@ -39,7 +39,7 @@ void desktop_settings_scene_pin_error_on_enter(void* context) { } else if(state == SCENE_STATE_PIN_ERROR_WRONG) { desktop_view_pin_input_set_label_primary(app->pin_input_view, 35, 8, "Wrong PIN!"); } else { - furi_assert(0); + furi_crash(); } desktop_view_pin_input_set_label_secondary(app->pin_input_view, 0, 8, NULL); desktop_view_pin_input_set_label_button(app->pin_input_view, "Retry"); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c index ec128246f..31eec3871 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c @@ -32,7 +32,7 @@ bool desktop_settings_scene_pin_setup_howto_on_event(void* context, SceneManager consumed = true; break; default: - furi_crash(NULL); + furi_crash(); } } return consumed; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c index 44b8e1bf7..0ebf85c64 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c @@ -52,7 +52,7 @@ bool desktop_settings_scene_pin_setup_howto2_on_event(void* context, SceneManage break; } default: - furi_crash(NULL); + furi_crash(); } } return consumed; diff --git a/applications/system/hid_app/hid.c b/applications/system/hid_app/hid.c index e8c26aa34..4ab10c907 100644 --- a/applications/system/hid_app/hid.c +++ b/applications/system/hid_app/hid.c @@ -279,7 +279,7 @@ void hid_hal_keyboard_press(Hid* instance, uint16_t event) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_kb_press(event); } else { - furi_crash(NULL); + furi_crash(); } } @@ -290,7 +290,7 @@ void hid_hal_keyboard_release(Hid* instance, uint16_t event) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_kb_release(event); } else { - furi_crash(NULL); + furi_crash(); } } @@ -301,7 +301,7 @@ void hid_hal_keyboard_release_all(Hid* instance) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_kb_release_all(); } else { - furi_crash(NULL); + furi_crash(); } } @@ -312,7 +312,7 @@ void hid_hal_consumer_key_press(Hid* instance, uint16_t event) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_consumer_key_press(event); } else { - furi_crash(NULL); + furi_crash(); } } @@ -323,7 +323,7 @@ void hid_hal_consumer_key_release(Hid* instance, uint16_t event) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_consumer_key_release(event); } else { - furi_crash(NULL); + furi_crash(); } } @@ -334,7 +334,7 @@ void hid_hal_consumer_key_release_all(Hid* instance) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_kb_release_all(); } else { - furi_crash(NULL); + furi_crash(); } } @@ -345,7 +345,7 @@ void hid_hal_mouse_move(Hid* instance, int8_t dx, int8_t dy) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_mouse_move(dx, dy); } else { - furi_crash(NULL); + furi_crash(); } } @@ -356,7 +356,7 @@ void hid_hal_mouse_scroll(Hid* instance, int8_t delta) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_mouse_scroll(delta); } else { - furi_crash(NULL); + furi_crash(); } } @@ -367,7 +367,7 @@ void hid_hal_mouse_press(Hid* instance, uint16_t event) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_mouse_press(event); } else { - furi_crash(NULL); + furi_crash(); } } @@ -378,7 +378,7 @@ void hid_hal_mouse_release(Hid* instance, uint16_t event) { } else if(instance->transport == HidTransportUsb) { furi_hal_hid_mouse_release(event); } else { - furi_crash(NULL); + furi_crash(); } } @@ -390,7 +390,7 @@ void hid_hal_mouse_release_all(Hid* instance) { furi_hal_hid_mouse_release(HID_MOUSE_BTN_LEFT); furi_hal_hid_mouse_release(HID_MOUSE_BTN_RIGHT); } else { - furi_crash(NULL); + furi_crash(); } } diff --git a/applications/system/updater/updater.c b/applications/system/updater/updater.c index e749f3ce6..4c7fd29e9 100644 --- a/applications/system/updater/updater.c +++ b/applications/system/updater/updater.c @@ -5,7 +5,6 @@ #include #include #include -#include #include static bool updater_custom_event_callback(void* context, uint32_t event) { diff --git a/assets/.gitignore b/assets/.gitignore index 88095e97b..ca338d633 100644 --- a/assets/.gitignore +++ b/assets/.gitignore @@ -1,6 +1 @@ /core2_firmware -/resources/Manifest -/resources/apps/* -/resources/asset_packs/* -/resources/dolphin/* -/resources/apps_data/**/*.fal diff --git a/assets/ReadMe.md b/assets/ReadMe.md index 5c5c0f3b6..67777fa86 100644 --- a/assets/ReadMe.md +++ b/assets/ReadMe.md @@ -32,11 +32,8 @@ Good starting point: https://docs.unrealengine.com/4.27/en-US/ProductionPipeline Don't include assets that you are not using, compiler is not going to strip unused assets. # Structure -- `compiled` - Output folder made for compiled assets, after building project, in `build` directory. - `dolphin` - Dolphin game assets sources. Goes to `compiled` and `resources` folders in `build` directory. - `packs` - Hot-swappable asset packs used system wide, both animations and icons. Compiled to `.bm` and `.bmx`, then put at `SD/asset_packs` - `icons` - Icons sources. Goes to `compiled` folder in `build` directory. - `protobuf` - Protobuf sources. Goes to `compiled` folder in `build` directory. -- `resources` - Assets that is going to be provisioned to SD card. - `slideshow` - One-time slideshows for desktop -- `unit_tests` - Some pre-defined signals for testing purposes. diff --git a/assets/SConscript b/assets/SConscript index 848b730f4..a420dbb2c 100644 --- a/assets/SConscript +++ b/assets/SConscript @@ -1,27 +1,27 @@ -from fbt.version import get_git_commit_unix_timestamp - Import("env") assetsenv = env.Clone( tools=["fbt_assets"], FW_LIB_NAME="assets", - GIT_UNIX_TIMESTAMP=get_git_commit_unix_timestamp(), + ASSETS_WORK_DIR=env.Dir("compiled"), + ASSETS_SRC_DIR=env.Dir("#/assets"), ) assetsenv.ApplyLibFlags() +# Keep firmware flash icons in build dir for api symbols for asset packs icons_path = ( assetsenv.Dir("#/build/icons") if assetsenv["IS_BASE_FIRMWARE"] - else assetsenv.Dir("compiled") + else assetsenv["ASSETS_WORK_DIR"] ) -icons = assetsenv.CompileIcons(icons_path, assetsenv.Dir("#/assets/icons")) +icons = assetsenv.CompileIcons(icons_path, assetsenv["ASSETS_SRC_DIR"].Dir("icons")) assetsenv.Alias("icons", icons) # Protobuf .proto -> .c + .h proto_src = assetsenv.Glob("protobuf/*.proto", source=True) proto_options = assetsenv.Glob("protobuf/*.options", source=True) -proto = assetsenv.ProtoBuilder(assetsenv.Dir("compiled"), proto_src) +proto = assetsenv.ProtoBuilder(assetsenv["ASSETS_WORK_DIR"], proto_src) assetsenv.Depends(proto, proto_options) # Precious(proto) assetsenv.Alias("proto", proto) @@ -30,8 +30,8 @@ assetsenv.Alias("proto", proto) # Internal animations dolphin_internal = assetsenv.DolphinSymBuilder( - assetsenv.Dir("compiled"), - assetsenv.Dir("#/assets/dolphin"), + assetsenv["ASSETS_WORK_DIR"], + assetsenv["ASSETS_SRC_DIR"].Dir("dolphin"), DOLPHIN_RES_TYPE="internal", ) assetsenv.Alias("dolphin_internal", dolphin_internal) @@ -40,8 +40,8 @@ assetsenv.Alias("dolphin_internal", dolphin_internal) # Blocking animations dolphin_blocking = assetsenv.DolphinSymBuilder( - assetsenv.Dir("compiled"), - assetsenv.Dir("#/assets/dolphin"), + assetsenv["ASSETS_WORK_DIR"], + assetsenv["ASSETS_SRC_DIR"].Dir("dolphin"), DOLPHIN_RES_TYPE="blocking", ) assetsenv.Alias("dolphin_blocking", dolphin_blocking) @@ -49,8 +49,8 @@ assetsenv.Alias("dolphin_blocking", dolphin_blocking) # Protobuf version meta proto_ver = assetsenv.ProtoVerBuilder( - "compiled/protobuf_version.h", - "#/assets/protobuf/Changelog", + "${ASSETS_WORK_DIR}/protobuf_version.h", + assetsenv["ASSETS_SRC_DIR"].File("protobuf/Changelog"), ) assetsenv.Depends(proto_ver, proto) assetsenv.Alias("proto_ver", proto_ver) @@ -64,41 +64,19 @@ assetsenv.Install("${LIB_DIST_DIR}", assetslib) # Resources for SD card -env.SetDefault(FW_RESOURCES=None) if assetsenv["IS_BASE_FIRMWARE"]: + dolphin_external_out_dir = assetsenv["ASSETS_WORK_DIR"].Dir("dolphin") # External dolphin animations dolphin_external = assetsenv.DolphinExtBuilder( - assetsenv.Dir("#/assets/resources/dolphin"), - assetsenv.Dir("#/assets/dolphin"), + dolphin_external_out_dir, + assetsenv["ASSETS_SRC_DIR"].Dir("dolphin"), DOLPHIN_RES_TYPE="external", ) if assetsenv["FORCE"]: assetsenv.AlwaysBuild(dolphin_external) assetsenv.Alias("dolphin_ext", dolphin_external) - assetsenv.Clean(dolphin_external, assetsenv.Dir("#/assets/resources/dolphin")) + assetsenv.Clean(dolphin_external, dolphin_external_out_dir) - # Resources manifest - resources = assetsenv.Command( - "#/assets/resources/Manifest", - assetsenv.GlobRecursive( - "*", - assetsenv.Dir("resources").srcnode(), - exclude=["Manifest"], - ), - action=Action( - '${PYTHON3} "${ASSETS_COMPILER}" manifest "${TARGET.dir.posix}" --timestamp=${GIT_UNIX_TIMESTAMP}', - "${RESMANIFESTCOMSTR}", - ), - ) - assetsenv.Precious(resources) - assetsenv.AlwaysBuild(resources) - assetsenv.Clean( - resources, - assetsenv.Dir("#/assets/resources/apps"), - ) - - # Exporting resources node to external environment - env.Replace(FW_RESOURCES=resources) - assetsenv.Alias("resources", resources) + env.Replace(DOLPHIN_EXTERNAL_OUT_DIR=dolphin_external_out_dir) Return("assetslib") diff --git a/assets/protobuf b/assets/protobuf index 327163d58..23ad19a75 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit 327163d5867c7aa3051334c93ced718d15bfe4da +Subproject commit 23ad19a756649ed9f6677b598e5361c5cce6847b diff --git a/firmware.scons b/firmware.scons index 82f775d71..eca6afc4c 100644 --- a/firmware.scons +++ b/firmware.scons @@ -1,15 +1,10 @@ -from SCons.Errors import UserError -from SCons.Node import FS - import itertools -from fbt_extra.util import ( - should_gen_cdb_and_link_dir, - link_elf_dir_as_latest, -) - from fbt.sdk.cache import LazySdkVersionLoader - +from fbt.version import get_git_commit_unix_timestamp +from fbt_extra.util import link_elf_dir_as_latest, should_gen_cdb_and_link_dir +from SCons.Errors import UserError +from SCons.Node import FS Import("ENV", "fw_build_meta") @@ -22,12 +17,15 @@ env = ENV.Clone( "pvsstudio", "fbt_hwtarget", "fbt_envhooks", + "fbt_resources", ], COMPILATIONDB_USE_ABSPATH=False, BUILD_DIR=fw_build_meta["build_dir"], IS_BASE_FIRMWARE=fw_build_meta["type"] == "firmware", FW_FLAVOR=fw_build_meta["flavor"], LIB_DIST_DIR=fw_build_meta["build_dir"].Dir("lib"), + RESOURCES_ROOT=fw_build_meta["build_dir"].Dir("resources"), + TARGETS_ROOT=Dir("#/targets"), LINT_SOURCES=[ Dir("applications"), ], @@ -37,7 +35,7 @@ env = ENV.Clone( CPPPATH=[ "#/furi", *(f"#/{app_dir[0]}" for app_dir in ENV["APPDIRS"] if app_dir[1]), - "#/firmware/targets/furi_hal_include", + "#/targets/furi_hal_include", ], # Specific flags for building libraries - always do optimized builds FW_LIB_OPTS={ @@ -104,7 +102,7 @@ lib_targets = env.BuildModules( [ "lib", "assets", - "firmware", + "targets", "furi", ], ) @@ -144,12 +142,22 @@ fwenv.PrepareApplicationsBuild() # Build external apps + configure SDK if env["IS_BASE_FIRMWARE"]: fwenv.SetDefault(FBT_FAP_DEBUG_ELF_ROOT=fwenv["BUILD_DIR"].Dir(".extapps")) - fwenv["FW_EXTAPPS"] = SConscript( + fw_extapps = fwenv["FW_EXTAPPS"] = SConscript( "site_scons/extapps.scons", exports={"ENV": fwenv}, ) - fw_artifacts.append(fwenv["FW_EXTAPPS"].sdk_tree) + fw_artifacts.append(fw_extapps.sdk_tree) + # Resources & manifest for SD card + manifest = fwenv.ManifestBuilder( + "${RESOURCES_ROOT}/Manifest", + GIT_UNIX_TIMESTAMP=get_git_commit_unix_timestamp(), + _EXTRA_DIST=[fwenv["DOLPHIN_EXTERNAL_OUT_DIR"]], + ) + fwenv.Replace(FW_RESOURCES_MANIFEST=manifest) + fwenv.Alias("resources", manifest) + + # API getter fwenv.Append(FBT_API_VERSION=LazySdkVersionLoader(fwenv.subst("$SDK_DEFINITION"))) fwenv.PhonyTarget( "get_apiversion", @@ -189,7 +197,7 @@ sources = [apps_c] # Gather sources only from app folders in current configuration sources.extend( itertools.chain.from_iterable( - fwenv.GlobRecursive(source_type, appdir.relpath, exclude=["lib"]) + fwenv.GatherSources([source_type, "!lib"], appdir.relpath) for appdir, source_type in fwenv["APPBUILD"].get_builtin_app_folders() ) ) diff --git a/furi/core/base.h b/furi/core/base.h index 29e874192..642ff2b6c 100644 --- a/furi/core/base.h +++ b/furi/core/base.h @@ -2,6 +2,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/furi/core/check.c b/furi/core/check.c index a24384e7c..ff56517af 100644 --- a/furi/core/check.c +++ b/furi/core/check.c @@ -55,8 +55,6 @@ PLACE_IN_SECTION("MB_MEM2") uint32_t __furi_check_registers[13] = {0}; : "memory"); extern size_t xPortGetTotalHeapSize(void); -extern size_t xPortGetFreeHeapSize(void); -extern size_t xPortGetMinimumEverFreeHeapSize(void); static void __furi_put_uint32_as_text(uint32_t data) { char tmp_str[] = "-2147483648"; @@ -128,7 +126,7 @@ static void __furi_print_name(bool isr) { } } -FURI_NORETURN void __furi_crash() { +FURI_NORETURN void __furi_crash_implementation() { __disable_irq(); GET_MESSAGE_AND_STORE_REGISTERS(); @@ -181,7 +179,7 @@ FURI_NORETURN void __furi_crash() { __builtin_unreachable(); } -FURI_NORETURN void __furi_halt() { +FURI_NORETURN void __furi_halt_implementation() { __disable_irq(); GET_MESSAGE_AND_STORE_REGISTERS(); diff --git a/furi/core/check.h b/furi/core/check.h index 8af418962..94c4e2b38 100644 --- a/furi/core/check.h +++ b/furi/core/check.h @@ -35,39 +35,51 @@ extern "C" { #endif /** Crash system */ -FURI_NORETURN void __furi_crash(); +FURI_NORETURN void __furi_crash_implementation(); /** Halt system */ -FURI_NORETURN void __furi_halt(); +FURI_NORETURN void __furi_halt_implementation(); /** Crash system with message. Show message after reboot. */ -#define furi_crash(message) \ +#define __furi_crash(message) \ do { \ register const void* r12 asm("r12") = (void*)message; \ asm volatile("sukima%=:" : : "r"(r12)); \ - __furi_crash(); \ + __furi_crash_implementation(); \ } while(0) +/** Crash system + * + * @param optional message (const char*) + */ +#define furi_crash(...) M_APPLY(__furi_crash, M_IF_EMPTY(__VA_ARGS__)((NULL), (__VA_ARGS__))) + /** Halt system with message. */ -#define furi_halt(message) \ +#define __furi_halt(message) \ do { \ register const void* r12 asm("r12") = (void*)message; \ asm volatile("sukima%=:" : : "r"(r12)); \ - __furi_halt(); \ + __furi_halt_implementation(); \ } while(0) +/** Halt system + * + * @param optional message (const char*) + */ +#define furi_halt(...) M_APPLY(__furi_halt, M_IF_EMPTY(__VA_ARGS__)((NULL), (__VA_ARGS__))) + /** Check condition and crash if check failed */ #define __furi_check(__e, __m) \ do { \ if(!(__e)) { \ - furi_crash(__m); \ + __furi_crash(__m); \ } \ } while(0) /** Check condition and crash if failed * * @param condition to check - * @param optional message + * @param optional message (const char*) */ #define furi_check(...) \ M_APPLY(__furi_check, M_DEFAULT_ARGS(2, (__FURI_CHECK_MESSAGE_FLAG), __VA_ARGS__)) @@ -77,7 +89,7 @@ FURI_NORETURN void __furi_halt(); #define __furi_assert(__e, __m) \ do { \ if(!(__e)) { \ - furi_crash(__m); \ + __furi_crash(__m); \ } \ } while(0) #else @@ -93,7 +105,7 @@ FURI_NORETURN void __furi_halt(); * @warning only will do check if firmware compiled in debug mode * * @param condition to check - * @param optional message + * @param optional message (const char*) */ #define furi_assert(...) \ M_APPLY(__furi_assert, M_DEFAULT_ARGS(2, (__FURI_ASSERT_MESSAGE_FLAG), __VA_ARGS__)) diff --git a/furi/core/common_defines.h b/furi/core/common_defines.h index 5bd218d35..2b30c3b06 100644 --- a/furi/core/common_defines.h +++ b/furi/core/common_defines.h @@ -2,8 +2,6 @@ #include "core_defines.h" #include -#include -#include #ifdef __cplusplus extern "C" { diff --git a/furi/core/critical.c b/furi/core/critical.c index 57fe2403b..3bef2be38 100644 --- a/furi/core/critical.c +++ b/furi/core/critical.c @@ -1,5 +1,8 @@ #include "common_defines.h" +#include +#include + __FuriCriticalInfo __furi_critical_enter(void) { __FuriCriticalInfo info; diff --git a/furi/core/event_flag.c b/furi/core/event_flag.c index 9406a581f..96b959187 100644 --- a/furi/core/event_flag.c +++ b/furi/core/event_flag.c @@ -2,6 +2,7 @@ #include "common_defines.h" #include "check.h" +#include #include #define FURI_EVENT_FLAG_MAX_BITS_EVENT_GROUPS 24U diff --git a/furi/core/kernel.c b/furi/core/kernel.c index 7928ad11c..89a50a9b5 100644 --- a/furi/core/kernel.c +++ b/furi/core/kernel.c @@ -5,6 +5,9 @@ #include +#include +#include + #include CMSIS_device_header bool furi_kernel_is_irq_or_masked() { @@ -31,6 +34,10 @@ bool furi_kernel_is_irq_or_masked() { return (irq); } +bool furi_kernel_is_running() { + return xTaskGetSchedulerState() != taskSCHEDULER_RUNNING; +} + int32_t furi_kernel_lock() { furi_assert(!furi_kernel_is_irq_or_masked()); diff --git a/furi/core/kernel.h b/furi/core/kernel.h index 371f76c1f..c962402ef 100644 --- a/furi/core/kernel.h +++ b/furi/core/kernel.h @@ -27,6 +27,12 @@ extern "C" { */ bool furi_kernel_is_irq_or_masked(); +/** Check if kernel is running + * + * @return true if running, false otherwise + */ +bool furi_kernel_is_running(); + /** Lock kernel, pause process scheduling * * @warning This should never be called in interrupt request context. diff --git a/furi/core/memmgr_heap.c b/furi/core/memmgr_heap.c index fc8672dee..5133ccef6 100644 --- a/furi/core/memmgr_heap.c +++ b/furi/core/memmgr_heap.c @@ -47,8 +47,8 @@ all the API functions to use the MPU wrappers. That should only be done when task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#include "FreeRTOS.h" -#include "task.h" +#include +#include #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE diff --git a/furi/core/message_queue.c b/furi/core/message_queue.c index ddf56f006..e20fa420a 100644 --- a/furi/core/message_queue.c +++ b/furi/core/message_queue.c @@ -1,8 +1,9 @@ #include "kernel.h" #include "message_queue.h" +#include "check.h" + #include #include -#include "check.h" FuriMessageQueue* furi_message_queue_alloc(uint32_t msg_count, uint32_t msg_size) { furi_assert((furi_kernel_is_irq_or_masked() == 0U) && (msg_count > 0U) && (msg_size > 0U)); diff --git a/furi/core/mutex.c b/furi/core/mutex.c index 9fb964a1e..8794e10dc 100644 --- a/furi/core/mutex.c +++ b/furi/core/mutex.c @@ -2,6 +2,7 @@ #include "check.h" #include "common_defines.h" +#include #include FuriMutex* furi_mutex_alloc(FuriMutexType type) { diff --git a/furi/core/semaphore.c b/furi/core/semaphore.c index 8c99bfc54..1f1a07780 100644 --- a/furi/core/semaphore.c +++ b/furi/core/semaphore.c @@ -2,6 +2,7 @@ #include "check.h" #include "common_defines.h" +#include #include FuriSemaphore* furi_semaphore_alloc(uint32_t max_count, uint32_t initial_count) { diff --git a/furi/core/stream_buffer.c b/furi/core/stream_buffer.c index bf483948b..a13d256b1 100644 --- a/furi/core/stream_buffer.c +++ b/furi/core/stream_buffer.c @@ -2,6 +2,7 @@ #include "check.h" #include "stream_buffer.h" #include "common_defines.h" + #include #include diff --git a/furi/core/thread.c b/furi/core/thread.c index 4139f2ebc..930caf8ad 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -9,12 +9,14 @@ #include "mutex.h" #include "string.h" -#include #include #include "log.h" #include #include +#include +#include + #define TAG "FuriThread" #define THREAD_NOTIFY_INDEX 1 // Index 0 is used for stream buffers diff --git a/furi/core/thread.h b/furi/core/thread.h index 692f2a100..44d66fb21 100644 --- a/furi/core/thread.h +++ b/furi/core/thread.h @@ -8,6 +8,9 @@ #include "base.h" #include "common_defines.h" +#include +#include + #ifdef __cplusplus extern "C" { #endif @@ -28,7 +31,8 @@ typedef enum { FuriThreadPriorityNormal = 16, /**< Normal */ FuriThreadPriorityHigh = 17, /**< High */ FuriThreadPriorityHighest = 18, /**< Highest */ - FuriThreadPriorityIsr = (configMAX_PRIORITIES - 1), /**< Deferred ISR (highest possible) */ + FuriThreadPriorityIsr = + (FURI_CONFIG_THREAD_MAX_PRIORITIES - 1), /**< Deferred ISR (highest possible) */ } FuriThreadPriority; /** FuriThread anonymous structure */ diff --git a/furi/core/timer.c b/furi/core/timer.c index d1fdc4456..945ffffa5 100644 --- a/furi/core/timer.c +++ b/furi/core/timer.c @@ -63,7 +63,7 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co callb = (TimerCallback_t*)((uint32_t)callb | 1U); // TimerCallback function is always provided as a callback and is used to call application // specified function with its context both stored in structure callb. - hTimer = xTimerCreate(name, 1, reload, callb, TimerCallback); + hTimer = xTimerCreate(name, portMAX_DELAY, reload, callb, TimerCallback); furi_check(hTimer); /* Return timer ID */ @@ -95,6 +95,7 @@ void furi_timer_free(FuriTimer* instance) { FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) { furi_assert(!furi_kernel_is_irq_or_masked()); furi_assert(instance); + furi_assert(ticks < portMAX_DELAY); TimerHandle_t hTimer = (TimerHandle_t)instance; FuriStatus stat; @@ -109,6 +110,25 @@ FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) { return (stat); } +FuriStatus furi_timer_restart(FuriTimer* instance, uint32_t ticks) { + furi_assert(!furi_kernel_is_irq_or_masked()); + furi_assert(instance); + furi_assert(ticks < portMAX_DELAY); + + TimerHandle_t hTimer = (TimerHandle_t)instance; + FuriStatus stat; + + if(xTimerChangePeriod(hTimer, ticks, portMAX_DELAY) == pdPASS && + xTimerReset(hTimer, portMAX_DELAY) == pdPASS) { + stat = FuriStatusOk; + } else { + stat = FuriStatusErrorResource; + } + + /* Return execution status */ + return (stat); +} + FuriStatus furi_timer_stop(FuriTimer* instance) { furi_assert(!furi_kernel_is_irq_or_masked()); furi_assert(instance); @@ -137,6 +157,15 @@ uint32_t furi_timer_is_running(FuriTimer* instance) { return (uint32_t)xTimerIsTimerActive(hTimer); } +uint32_t furi_timer_get_expire_time(FuriTimer* instance) { + furi_assert(!furi_kernel_is_irq_or_masked()); + furi_assert(instance); + + TimerHandle_t hTimer = (TimerHandle_t)instance; + + return (uint32_t)xTimerGetExpiryTime(hTimer); +} + void furi_timer_pending_callback(FuriTimerPendigCallback callback, void* context, uint32_t arg) { BaseType_t ret = pdFAIL; if(furi_kernel_is_irq_or_masked()) { @@ -146,3 +175,18 @@ void furi_timer_pending_callback(FuriTimerPendigCallback callback, void* context } furi_check(ret == pdPASS); } + +void furi_timer_set_thread_priority(FuriTimerThreadPriority priority) { + furi_assert(!furi_kernel_is_irq_or_masked()); + + TaskHandle_t task_handle = xTimerGetTimerDaemonTaskHandle(); + furi_check(task_handle); // Don't call this method before timer task start + + if(priority == FuriTimerThreadPriorityNormal) { + vTaskPrioritySet(task_handle, configTIMER_TASK_PRIORITY); + } else if(priority == FuriTimerThreadPriorityElevated) { + vTaskPrioritySet(task_handle, configMAX_PRIORITIES - 1); + } else { + furi_crash(); + } +} diff --git a/furi/core/timer.h b/furi/core/timer.h index 6c9c6fd2a..be136544e 100644 --- a/furi/core/timer.h +++ b/furi/core/timer.h @@ -34,12 +34,21 @@ void furi_timer_free(FuriTimer* instance); /** Start timer * * @param instance The pointer to FuriTimer instance - * @param[in] ticks The ticks + * @param[in] ticks The interval in ticks * * @return The furi status. */ FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks); +/** Restart timer with previous timeout value + * + * @param instance The pointer to FuriTimer instance + * @param[in] ticks The interval in ticks + * + * @return The furi status. + */ +FuriStatus furi_timer_restart(FuriTimer* instance, uint32_t ticks); + /** Stop timer * * @param instance The pointer to FuriTimer instance @@ -56,10 +65,29 @@ FuriStatus furi_timer_stop(FuriTimer* instance); */ uint32_t furi_timer_is_running(FuriTimer* instance); +/** Get timer expire time + * + * @param instance The Timer instance + * + * @return expire tick + */ +uint32_t furi_timer_get_expire_time(FuriTimer* instance); + typedef void (*FuriTimerPendigCallback)(void* context, uint32_t arg); void furi_timer_pending_callback(FuriTimerPendigCallback callback, void* context, uint32_t arg); +typedef enum { + FuriTimerThreadPriorityNormal, /**< Lower then other threads */ + FuriTimerThreadPriorityElevated, /**< Same as other threads */ +} FuriTimerThreadPriority; + +/** Set Timer thread priority + * + * @param[in] priority The priority + */ +void furi_timer_set_thread_priority(FuriTimerThreadPriority priority); + /** Get currently executing timer name * * @return The pointer to the timer name, or NULL diff --git a/furi/flipper.c b/furi/flipper.c index e5e7540a9..1ebaccdf1 100644 --- a/furi/flipper.c +++ b/furi/flipper.c @@ -17,6 +17,8 @@ #include #include +#include + #define TAG "Flipper" static void flipper_print_version(const char* target, const Version* version) { diff --git a/furi/furi.c b/furi/furi.c index cc0e3f4f1..6247e259f 100644 --- a/furi/furi.c +++ b/furi/furi.c @@ -1,6 +1,8 @@ #include "furi.h" #include -#include "queue.h" + +#include +#include void furi_init() { furi_assert(!furi_kernel_is_irq_or_masked()); diff --git a/furi/furi.h b/furi/furi.h index b1299c9a9..422509055 100644 --- a/furi/furi.h +++ b/furi/furi.h @@ -21,9 +21,6 @@ #include -// FreeRTOS timer, REMOVE AFTER REFACTORING -#include - // Workaround for math.h leaking through HAL in older versions #include diff --git a/lib/flipper_application/plugins/plugin_manager.c b/lib/flipper_application/plugins/plugin_manager.c index d2517fb0e..d8c16e0ec 100644 --- a/lib/flipper_application/plugins/plugin_manager.c +++ b/lib/flipper_application/plugins/plugin_manager.c @@ -68,7 +68,8 @@ PluginManagerError plugin_manager_load_single(PluginManager* manager, const char FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(lib); if(load_status != FlipperApplicationLoadStatusSuccess) { - FURI_LOG_E(TAG, "Failed to load module_demo_plugin1.fal"); + FURI_LOG_E(TAG, "Failed to load %s", path); + error = PluginManagerErrorLoaderError; break; } diff --git a/lib/ibutton/ibutton_protocols.c b/lib/ibutton/ibutton_protocols.c index 75aa225ef..df7412670 100644 --- a/lib/ibutton/ibutton_protocols.c +++ b/lib/ibutton/ibutton_protocols.c @@ -48,7 +48,7 @@ static void ibutton_protocols_get_group_by_id( local_id -= ibutton_protocol_groups[i]->protocol_count; } } - furi_crash(NULL); + furi_crash(); } iButtonProtocols* ibutton_protocols_alloc() { diff --git a/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c b/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c index 87f815142..47d8c3c64 100644 --- a/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c +++ b/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c @@ -48,7 +48,7 @@ void infrared_encoder_nec_reset(void* encoder_ptr, const InfraredMessage* messag *data2 = (message->command & 0xFFC0) >> 6; encoder->bits_to_encode = 42; } else { - furi_assert(0); + furi_crash(); } } diff --git a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c index 6adf2235c..39c2eb166 100644 --- a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c +++ b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c @@ -23,7 +23,7 @@ void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* messa *data |= (message->address & 0x1FFF) << 7; encoder->bits_to_encode = 20; } else { - furi_assert(0); + furi_crash(); } } diff --git a/lib/infrared/worker/infrared_transmit.c b/lib/infrared/worker/infrared_transmit.c index 113fb6324..8f99c0066 100644 --- a/lib/infrared/worker/infrared_transmit.c +++ b/lib/infrared/worker/infrared_transmit.c @@ -88,7 +88,7 @@ FuriHalInfraredTxGetDataState state = FuriHalInfraredTxGetDataStateDone; } } else { - furi_crash(NULL); + furi_crash(); } return state; diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 46effd420..38392fc06 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -165,7 +165,7 @@ static int32_t infrared_worker_rx_thread(void* thread_context) { InfraredWorker* instance = thread_context; uint32_t events = 0; LevelDuration level_duration; - TickType_t last_blink_time = 0; + uint32_t last_blink_time = 0; while(1) { events = furi_thread_flags_wait(INFRARED_WORKER_ALL_RX_EVENTS, 0, FuriWaitForever); @@ -173,8 +173,8 @@ static int32_t infrared_worker_rx_thread(void* thread_context) { if(events & INFRARED_WORKER_RX_RECEIVED) { if(!instance->rx.overrun && instance->blink_enable && - ((xTaskGetTickCount() - last_blink_time) > 80)) { - last_blink_time = xTaskGetTickCount(); + ((furi_get_tick() - last_blink_time) > 80)) { + last_blink_time = furi_get_tick(); notification_message(instance->notification, &sequence_blink_blue_10); } if(instance->signal.timings_cnt == 0) @@ -367,10 +367,11 @@ static FuriHalInfraredTxGetDataState *duration = timing.duration; state = timing.state; } else { - furi_assert(0); + // Why bother if we crash anyway?.. *level = 0; *duration = 100; state = FuriHalInfraredTxGetDataStateDone; + furi_crash(); } uint32_t flags_set = furi_thread_flags_set( @@ -414,7 +415,7 @@ static bool infrared_get_new_signal(InfraredWorker* instance) { } else if(response == InfraredWorkerGetSignalResponseStop) { new_signal_obtained = false; } else { - furi_assert(0); + furi_crash(); } return new_signal_obtained; @@ -443,9 +444,8 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) { } if(status == InfraredStatusError) { - furi_assert(0); new_data_available = false; - break; + furi_crash(); } else if(status == InfraredStatusOk) { timing.state = FuriHalInfraredTxGetDataStateOk; } else if(status == InfraredStatusDone) { @@ -456,7 +456,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) { timing.state = FuriHalInfraredTxGetDataStateLastDone; } } else { - furi_assert(0); + furi_crash(); } uint32_t written_size = furi_stream_buffer_send(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0); @@ -548,7 +548,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { break; default: - furi_assert(0); + furi_crash(); break; } } diff --git a/lib/lfrfid/lfrfid_worker.c b/lib/lfrfid/lfrfid_worker.c index cbc7b02e3..ffaa8ee92 100644 --- a/lib/lfrfid/lfrfid_worker.c +++ b/lib/lfrfid/lfrfid_worker.c @@ -1,7 +1,7 @@ +#include "lfrfid_worker_i.h" + #include #include -#include -#include "lfrfid_worker_i.h" typedef enum { LFRFIDEventStopThread = (1 << 0), diff --git a/lib/nfc/helpers/nfc_data_generator.c b/lib/nfc/helpers/nfc_data_generator.c index 278305162..011f9f6db 100644 --- a/lib/nfc/helpers/nfc_data_generator.c +++ b/lib/nfc/helpers/nfc_data_generator.c @@ -28,6 +28,7 @@ static const uint8_t default_config_ntag_i2c[] = {0x01, 0x00, 0xF8, 0x48, 0x08, static void nfc_generate_mf_ul_uid(uint8_t* uid) { uid[0] = NXP_MANUFACTURER_ID; furi_hal_random_fill_buf(&uid[1], 6); + uid[3] |= 0x01; // To avoid forbidden 0x88 value // I'm not sure how this is generated, but the upper nybble always seems to be 8 uid[6] &= 0x0F; uid[6] |= 0x80; @@ -322,6 +323,7 @@ static void nfc_generate_ntag_i2c_plus_2k(NfcDevice* nfc_device) { 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); + uid[3] |= 0x01; // To avoid forbidden 0x88 value } static void diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.h b/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.h index 1113d381c..ce878cb40 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.h +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.h @@ -43,8 +43,6 @@ struct Iso14443_4aPoller { void* context; }; -Iso14443_4aError iso14443_4a_process_error(Iso14443_3aError error); - const Iso14443_4aData* iso14443_4a_poller_get_data(Iso14443_4aPoller* instance); Iso14443_4aError iso14443_4a_poller_halt(Iso14443_4aPoller* instance); diff --git a/lib/nfc/protocols/iso14443_4b/iso14443_4b_poller_i.h b/lib/nfc/protocols/iso14443_4b/iso14443_4b_poller_i.h index 4df00adcf..bd55c6188 100644 --- a/lib/nfc/protocols/iso14443_4b/iso14443_4b_poller_i.h +++ b/lib/nfc/protocols/iso14443_4b/iso14443_4b_poller_i.h @@ -40,8 +40,6 @@ struct Iso14443_4bPoller { void* context; }; -Iso14443_4bError iso14443_4b_process_error(Iso14443_3bError error); - const Iso14443_4bData* iso14443_4b_poller_get_data(Iso14443_4bPoller* instance); Iso14443_4bError iso14443_4b_poller_halt(Iso14443_4bPoller* instance); diff --git a/lib/print/wrappers.h b/lib/print/wrappers.h index b6f0f004b..7c0d1f92e 100644 --- a/lib/print/wrappers.h +++ b/lib/print/wrappers.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -6,7 +8,6 @@ extern "C" { #endif -void _putchar(char character); int __wrap_printf(const char* format, ...); int __wrap_vsnprintf(char* str, size_t size, const char* format, va_list args); int __wrap_puts(const char* str); diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index 96a87f665..ccdd3b0cf 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -13,6 +13,7 @@ env.Append( File("subghz_file_encoder_worker.h"), File("transmitter.h"), File("protocols/raw.h"), + File("protocols/public_api.h"), File("blocks/const.h"), File("blocks/decoder.h"), File("blocks/encoder.h"), diff --git a/lib/subghz/protocols/bin_raw.h b/lib/subghz/protocols/bin_raw.h index 82775e575..26cc6ec3a 100644 --- a/lib/subghz/protocols/bin_raw.h +++ b/lib/subghz/protocols/bin_raw.h @@ -1,6 +1,7 @@ #pragma once #include "base.h" +#include "public_api.h" #define SUBGHZ_PROTOCOL_BIN_RAW_NAME "BinRAW" @@ -80,10 +81,6 @@ void subghz_protocol_decoder_bin_raw_feed(void* context, bool level, uint32_t du */ uint8_t subghz_protocol_decoder_bin_raw_get_hash_data(void* context); -void subghz_protocol_decoder_bin_raw_data_input_rssi( - SubGhzProtocolDecoderBinRAW* instance, - float rssi); - /** * Serialize data SubGhzProtocolDecoderBinRAW. * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance diff --git a/lib/subghz/protocols/keeloq.h b/lib/subghz/protocols/keeloq.h index a757e82d5..4abd14413 100644 --- a/lib/subghz/protocols/keeloq.h +++ b/lib/subghz/protocols/keeloq.h @@ -1,6 +1,7 @@ #pragma once #include "base.h" +#include "public_api.h" #define SUBGHZ_PROTOCOL_KEELOQ_NAME "KeeLoq" @@ -24,48 +25,6 @@ void* subghz_protocol_encoder_keeloq_alloc(SubGhzEnvironment* environment); */ void subghz_protocol_encoder_keeloq_free(void* context); -/** - * Key generation from simple data. - * @param context Pointer to a SubGhzProtocolEncoderKeeloq instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param serial Serial number, 28 bit - * @param btn Button number, 4 bit - * @param cnt Counter value, 16 bit - * @param manufacture_name Name of manufacturer's key - * @param preset Modulation, SubGhzRadioPreset - * @return true On success - */ -bool subghz_protocol_keeloq_create_data( - void* context, - FlipperFormat* flipper_format, - uint32_t serial, - uint8_t btn, - uint16_t cnt, - const char* manufacture_name, - SubGhzRadioPreset* preset); - -/** - * Key generation for BFT. - * @param context Pointer to a SubGhzProtocolEncoderKeeloq instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param serial Serial number, 28 bit - * @param btn Button number, 4 bit - * @param cnt Counter value, 16 bit - * @param seed Seed value, 32 bit - * @param manufacture_name Name of manufacturer's key - * @param preset Modulation, SubGhzRadioPreset - * @return true On success - */ -bool subghz_protocol_keeloq_bft_create_data( - void* context, - FlipperFormat* flipper_format, - uint32_t serial, - uint8_t btn, - uint16_t cnt, - uint32_t seed, - const char* manufacture_name, - SubGhzRadioPreset* preset); - /** * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderKeeloq instance diff --git a/lib/subghz/protocols/public_api.h b/lib/subghz/protocols/public_api.h new file mode 100644 index 000000000..57adc11ed --- /dev/null +++ b/lib/subghz/protocols/public_api.h @@ -0,0 +1,85 @@ +#pragma once + +#include "../types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Key generation from simple data. + * @param context Pointer to a SubGhzProtocolEncoderSecPlus_v2 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param serial Serial number, 32 bit + * @param btn Button number, 8 bit + * @param cnt Container value, 28 bit + * @param manufacture_name Name of manufacturer's key + * @param preset Modulation, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_secplus_v2_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint32_t cnt, + SubGhzRadioPreset* preset); + +/** + * Key generation from simple data. + * @param context Pointer to a SubGhzProtocolEncoderKeeloq instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param serial Serial number, 28 bit + * @param btn Button number, 4 bit + * @param cnt Container value, 16 bit + * @param manufacture_name Name of manufacturer's key + * @param preset Modulation, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_keeloq_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + const char* manufacture_name, + SubGhzRadioPreset* preset); + +/** + * Key generation for BFT. + * @param context Pointer to a SubGhzProtocolEncoderKeeloq instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param serial Serial number, 28 bit + * @param btn Button number, 4 bit + * @param cnt Counter value, 16 bit + * @param seed Seed value, 32 bit + * @param manufacture_name Name of manufacturer's key + * @param preset Modulation, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_keeloq_bft_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + uint32_t seed, + const char* manufacture_name, + SubGhzRadioPreset* preset); + +typedef struct SubGhzProtocolDecoderBinRAW SubGhzProtocolDecoderBinRAW; + +void subghz_protocol_decoder_bin_raw_data_input_rssi( + SubGhzProtocolDecoderBinRAW* instance, + float rssi); + +/** + * Validation of fixed parts SubGhzProtocolDecoderSecPlus_v1. + * @param fixed fixed parts + * @return true On success + */ +bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed); + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/protocols/secplus_v1.h b/lib/subghz/protocols/secplus_v1.h index 3490f2ca5..e01f8bcda 100644 --- a/lib/subghz/protocols/secplus_v1.h +++ b/lib/subghz/protocols/secplus_v1.h @@ -1,5 +1,7 @@ #pragma once + #include "base.h" +#include "public_api.h" #define SUBGHZ_PROTOCOL_SECPLUS_V1_NAME "Security+ 1.0" @@ -100,13 +102,6 @@ SubGhzProtocolStatus subghz_protocol_decoder_secplus_v1_serialize( SubGhzProtocolStatus subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format); -/** - * Validation of fixed parts SubGhzProtocolDecoderSecPlus_v1. - * @param fixed fixed parts - * @return true On success - */ -bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed); - /** * Getting a textual representation of the received data. * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance diff --git a/lib/subghz/protocols/secplus_v2.h b/lib/subghz/protocols/secplus_v2.h index 0eea732af..9eb912a27 100644 --- a/lib/subghz/protocols/secplus_v2.h +++ b/lib/subghz/protocols/secplus_v2.h @@ -1,5 +1,7 @@ #pragma once + #include "base.h" +#include "public_api.h" #define SUBGHZ_PROTOCOL_SECPLUS_V2_NAME "Security+ 2.0" @@ -45,25 +47,6 @@ void subghz_protocol_encoder_secplus_v2_stop(void* context); */ LevelDuration subghz_protocol_encoder_secplus_v2_yield(void* context); -/** - * Key generation from simple data. - * @param context Pointer to a SubGhzProtocolEncoderSecPlus_v2 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param serial Serial number, 32 bit - * @param btn Button number, 8 bit - * @param cnt Container value, 28 bit - * @param manufacture_name Name of manufacturer's key - * @param preset Modulation, SubGhzRadioPreset - * @return true On success - */ -bool subghz_protocol_secplus_v2_create_data( - void* context, - FlipperFormat* flipper_format, - uint32_t serial, - uint8_t btn, - uint32_t cnt, - SubGhzRadioPreset* preset); - /** * Allocate SubGhzProtocolDecoderSecPlus_v2. * @param environment Pointer to a SubGhzEnvironment instance diff --git a/lib/subghz/subghz_protocol_registry.h b/lib/subghz/subghz_protocol_registry.h index e5cf75cda..b53ca6cf2 100644 --- a/lib/subghz/subghz_protocol_registry.h +++ b/lib/subghz/subghz_protocol_registry.h @@ -10,39 +10,6 @@ extern const SubGhzProtocolRegistry subghz_protocol_registry; typedef struct SubGhzProtocolDecoderBinRAW SubGhzProtocolDecoderBinRAW; -bool subghz_protocol_secplus_v2_create_data( - void* context, - FlipperFormat* flipper_format, - uint32_t serial, - uint8_t btn, - uint32_t cnt, - SubGhzRadioPreset* preset); - -bool subghz_protocol_keeloq_create_data( - void* context, - FlipperFormat* flipper_format, - uint32_t serial, - uint8_t btn, - uint16_t cnt, - const char* manufacture_name, - SubGhzRadioPreset* preset); - -bool subghz_protocol_keeloq_bft_create_data( - void* context, - FlipperFormat* flipper_format, - uint32_t serial, - uint8_t btn, - uint16_t cnt, - uint32_t seed, - const char* manufacture_name, - SubGhzRadioPreset* preset); - -void subghz_protocol_decoder_bin_raw_data_input_rssi( - SubGhzProtocolDecoderBinRAW* instance, - float rssi); - -bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed); - bool subghz_protocol_faac_slh_create_data( void* context, FlipperFormat* flipper_format, diff --git a/lib/toolbox/buffer_stream.c b/lib/toolbox/buffer_stream.c index 37b2514ef..e8cb334d5 100644 --- a/lib/toolbox/buffer_stream.c +++ b/lib/toolbox/buffer_stream.c @@ -112,7 +112,7 @@ bool buffer_stream_send_from_isr(BufferStream* buffer_stream, const uint8_t* dat return result; } -Buffer* buffer_stream_receive(BufferStream* buffer_stream, TickType_t timeout) { +Buffer* buffer_stream_receive(BufferStream* buffer_stream, uint32_t timeout) { Buffer* buffer; size_t size = furi_stream_buffer_receive(buffer_stream->stream, &buffer, sizeof(Buffer*), timeout); diff --git a/lib/toolbox/buffer_stream.h b/lib/toolbox/buffer_stream.h index 9db547753..5c3dc0a34 100644 --- a/lib/toolbox/buffer_stream.h +++ b/lib/toolbox/buffer_stream.h @@ -69,7 +69,7 @@ bool buffer_stream_send_from_isr(BufferStream* buffer_stream, const uint8_t* dat * @param timeout * @return Buffer* */ -Buffer* buffer_stream_receive(BufferStream* buffer_stream, TickType_t timeout); +Buffer* buffer_stream_receive(BufferStream* buffer_stream, uint32_t timeout); /** * @brief Get stream overrun count diff --git a/scripts/ReadMe.md b/scripts/ReadMe.md index a9feba11b..359ce472a 100644 --- a/scripts/ReadMe.md +++ b/scripts/ReadMe.md @@ -52,10 +52,10 @@ ob.py set # Assets delivery -Run in the root folder of the repo: +Build the firmware and run in the root folder of the repo: ```bash -python scripts/storage.py -p send assets/resources /ext +python scripts/storage.py -p send build/latest/resources /ext ``` diff --git a/scripts/assets.py b/scripts/assets.py index 64d4d46ca..4b55b65e1 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import os +import shutil import pathlib import asset_packer @@ -255,6 +256,7 @@ extern const size_t ICON_PATHS_COUNT; if not os.path.isdir(directory_path): self.logger.error(f'"{directory_path}" is not a directory') exit(255) + manifest_file = os.path.join(directory_path, "Manifest") old_manifest = Manifest() if os.path.exists(manifest_file): @@ -269,13 +271,15 @@ extern const size_t ICON_PATHS_COUNT; self.logger.info("Comparing new manifest with existing") only_in_old, changed, only_in_new = Manifest.compare(old_manifest, new_manifest) for record in only_in_old: - self.logger.info(f"Only in old: {record}") + self.logger.debug(f"Only in old: {record}") for record in changed: self.logger.info(f"Changed: {record}") for record in only_in_new: - self.logger.info(f"Only in new: {record}") + self.logger.debug(f"Only in new: {record}") if any((only_in_old, changed, only_in_new)): - self.logger.warning("Manifests are different, updating") + self.logger.info( + f"Manifest updated ({len(only_in_new)} new, {len(only_in_old)} removed, {len(changed)} changed)" + ) new_manifest.save(manifest_file) else: self.logger.info("Manifest is up-to-date!") diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 11828d32e..7654ed94e 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -64,6 +64,7 @@ class FlipperApplication: order: int = 0 sdk_headers: List[str] = field(default_factory=list) targets: List[str] = field(default_factory=lambda: ["all"]) + resources: Optional[str] = None # .fap-specific sources: List[str] = field(default_factory=lambda: ["*.c*"]) @@ -239,12 +240,12 @@ class AppBuildset: FlipperAppType.SETTINGS, FlipperAppType.STARTUP, ) - EXTERNAL_APP_TYPES = ( - FlipperAppType.EXTERNAL, - FlipperAppType.MENUEXTERNAL, - FlipperAppType.PLUGIN, - FlipperAppType.DEBUG, - ) + EXTERNAL_APP_TYPES_MAP = { + FlipperAppType.EXTERNAL: True, + FlipperAppType.PLUGIN: True, + FlipperAppType.DEBUG: True, + FlipperAppType.MENUEXTERNAL: False, + } @staticmethod def print_writer(message): @@ -272,11 +273,15 @@ class AppBuildset: self._check_unsatisfied() # unneeded? self._check_target_match() self._group_plugins() - self.apps = sorted( + self._apps = sorted( list(map(self.appmgr.get, self.appnames)), key=lambda app: app.appid, ) + @property + def apps(self): + return list(self._apps) + def _is_missing_dep(self, dep_name: str): return dep_name not in self.appnames @@ -314,8 +319,8 @@ class AppBuildset: def _process_ext_apps(self): extapps = [ app - for apptype in self.EXTERNAL_APP_TYPES - for app in self.get_apps_of_type(apptype, True) + for (apptype, global_lookup) in self.EXTERNAL_APP_TYPES_MAP.items() + for app in self.get_apps_of_type(apptype, global_lookup) ] extapps.extend(map(self.appmgr.get, self._extra_ext_appnames)) @@ -386,13 +391,13 @@ class AppBuildset: def get_apps_cdefs(self): cdefs = set() - for app in self.apps: + for app in self._apps: cdefs.update(app.cdefines) return sorted(list(cdefs)) def get_sdk_headers(self): sdk_headers = [] - for app in self.apps: + for app in self._apps: sdk_headers.extend( [ src._appdir.File(header) @@ -403,17 +408,21 @@ class AppBuildset: return sdk_headers def get_apps_of_type(self, apptype: FlipperAppType, all_known: bool = False): + """Looks up apps of given type in current app set. If all_known is true, + ignores app set and checks all loaded apps' manifests.""" return sorted( filter( lambda app: app.apptype == apptype, - self.appmgr.known_apps.values() if all_known else self.apps, + self.appmgr.known_apps.values() + if all_known + else map(self.appmgr.get, self.appnames), ), key=lambda app: app.order, ) def get_builtin_apps(self): return list( - filter(lambda app: app.apptype in self.BUILTIN_APP_TYPES, self.apps) + filter(lambda app: app.apptype in self.BUILTIN_APP_TYPES, self._apps) ) def get_builtin_app_folders(self): diff --git a/scripts/fbt_tools/fbt_apps.py b/scripts/fbt_tools/fbt_apps.py index 9a0718055..edce194f0 100644 --- a/scripts/fbt_tools/fbt_apps.py +++ b/scripts/fbt_tools/fbt_apps.py @@ -21,8 +21,13 @@ def LoadAppManifest(env, entry): APP_MANIFEST_NAME = "application.fam" manifest_glob = entry.glob(APP_MANIFEST_NAME) if len(manifest_glob) == 0: + try: + disk_node = next(filter(lambda d: d.exists(), entry.get_all_rdirs())) + except Exception: + disk_node = entry + raise FlipperManifestException( - f"Folder {entry}: manifest {APP_MANIFEST_NAME} is missing" + f"App folder '{disk_node.abspath}': missing manifest ({APP_MANIFEST_NAME})" ) app_manifest_file_path = manifest_glob[0].rfile().abspath diff --git a/scripts/fbt_tools/fbt_assets.py b/scripts/fbt_tools/fbt_assets.py index eb6e62191..2b14d3bd2 100644 --- a/scripts/fbt_tools/fbt_assets.py +++ b/scripts/fbt_tools/fbt_assets.py @@ -5,9 +5,10 @@ from ansi.color import fg from SCons.Action import Action from SCons.Builder import Builder from SCons.Errors import StopError +from SCons.Node.FS import File -def icons_emitter(target, source, env): +def _icons_emitter(target, source, env): icons_src = env.GlobRecursive("*.png", env["ICON_SRC_DIR"]) icons_src += env.GlobRecursive("**/frame_rate", env["ICON_SRC_DIR"]) @@ -18,7 +19,7 @@ def icons_emitter(target, source, env): return target, icons_src -def proto_emitter(target, source, env): +def _proto_emitter(target, source, env): target = [] for src in source: basename = os.path.splitext(src.name)[0] @@ -27,25 +28,26 @@ def proto_emitter(target, source, env): return target, source -def dolphin_emitter(target, source, env): +def _dolphin_emitter(target, source, env): res_root_dir = source[0].Dir(env["DOLPHIN_RES_TYPE"]) - source = [res_root_dir] + source = list() source.extend(env.GlobRecursive("*.*", res_root_dir.srcnode())) target_base_dir = target[0] env.Replace(_DOLPHIN_OUT_DIR=target[0]) + env.Replace(_DOLPHIN_SRC_DIR=res_root_dir) if env["DOLPHIN_RES_TYPE"] == "external": target = [target_base_dir.File("manifest.txt")] ## A detailed list of files to be generated - ## works better if we just leave target the folder - # target = [] + # Not used ATM, becasuse it inflates the internal dependency graph too much + # Preserve original paths, do .png -> .bm conversion # target.extend( # map( # lambda node: target_base_dir.File( # res_root_dir.rel_path(node).replace(".png", ".bm") # ), - # filter(lambda node: isinstance(node, SCons.Node.FS.File), source), + # filter(lambda node: isinstance(node, File), source), # ) # ) else: @@ -55,7 +57,7 @@ def dolphin_emitter(target, source, env): target_base_dir.File(asset_basename + ".h"), ] - # Debug output + ## Debug output # print( # f"Dolphin res type: {env['DOLPHIN_RES_TYPE']},\ntarget files:", # list(f.path for f in target), @@ -65,7 +67,7 @@ def dolphin_emitter(target, source, env): return target, source -def _invoke_git(args, source_dir): +def __invoke_git(args, source_dir): cmd = ["git"] cmd.extend(args) return ( @@ -75,25 +77,38 @@ def _invoke_git(args, source_dir): ) -def proto_ver_generator(target, source, env): +def _proto_ver_generator(target, source, env): target_file = target[0] src_dir = source[0].dir.abspath - try: - _invoke_git( - ["fetch", "--tags"], - source_dir=src_dir, - ) - except (subprocess.CalledProcessError, EnvironmentError): - # Not great, not terrible - print(fg.boldred("Git: fetch failed")) - try: - git_describe = _invoke_git( - ["describe", "--tags", "--abbrev=0"], - source_dir=src_dir, - ) - except (subprocess.CalledProcessError, EnvironmentError): - raise StopError("Git: describe failed") + def fetch(unshallow=False): + git_args = ["fetch", "--tags"] + if unshallow: + git_args.append("--unshallow") + + try: + __invoke_git(git_args, source_dir=src_dir) + except (subprocess.CalledProcessError, EnvironmentError): + # Not great, not terrible + print(fg.boldred("Git: fetch failed")) + + def describe(): + try: + return __invoke_git( + ["describe", "--tags", "--abbrev=0"], + source_dir=src_dir, + ) + except (subprocess.CalledProcessError, EnvironmentError): + return None + + fetch() + git_describe = describe() + if not git_describe: + fetch(unshallow=True) + git_describe = describe() + + if not git_describe: + raise StopError("Failed to process git tags for protobuf versioning") git_major, git_minor = git_describe.split(".") version_file_data = ( @@ -131,7 +146,6 @@ def generate(env): ICONSCOMSTR="\tICONS\t${TARGET}", PROTOCOMSTR="\tPROTO\t${SOURCE}", DOLPHINCOMSTR="\tDOLPHIN\t${DOLPHIN_RES_TYPE}", - RESMANIFESTCOMSTR="\tMANIFEST\t${TARGET}", PBVERCOMSTR="\tPBVER\t${TARGET}", ) @@ -139,37 +153,74 @@ def generate(env): BUILDERS={ "IconBuilder": Builder( action=Action( - '${PYTHON3} ${ASSETS_COMPILER} icons ${ICON_SRC_DIR} ${TARGET.dir} --filename "${ICON_FILE_NAME}"', + [ + [ + "${PYTHON3}", + "${ASSETS_COMPILER}", + "icons", + "${ICON_SRC_DIR}", + "${TARGET.dir}", + "--filename", + "${ICON_FILE_NAME}", + ], + ], "${ICONSCOMSTR}", ), - emitter=icons_emitter, + emitter=_icons_emitter, ), "ProtoBuilder": Builder( action=Action( - "${PYTHON3} ${NANOPB_COMPILER} -q -I${SOURCE.dir.posix} -D${TARGET.dir.posix} ${SOURCES.posix}", + [ + [ + "${PYTHON3}", + "${NANOPB_COMPILER}", + "-q", + "-I${SOURCE.dir.posix}", + "-D${TARGET.dir.posix}", + "${SOURCES.posix}", + ], + ], "${PROTOCOMSTR}", ), - emitter=proto_emitter, + emitter=_proto_emitter, suffix=".pb.c", src_suffix=".proto", ), "DolphinSymBuilder": Builder( action=Action( - "${PYTHON3} ${ASSETS_COMPILER} dolphin -s dolphin_${DOLPHIN_RES_TYPE} ${SOURCE} ${_DOLPHIN_OUT_DIR}", + [ + [ + "${PYTHON3}", + "${ASSETS_COMPILER}", + "dolphin", + "-s", + "dolphin_${DOLPHIN_RES_TYPE}", + "${_DOLPHIN_SRC_DIR}", + "${_DOLPHIN_OUT_DIR}", + ], + ], "${DOLPHINCOMSTR}", ), - emitter=dolphin_emitter, + emitter=_dolphin_emitter, ), "DolphinExtBuilder": Builder( action=Action( - "${PYTHON3} ${ASSETS_COMPILER} dolphin ${SOURCE} ${_DOLPHIN_OUT_DIR}", + [ + [ + "${PYTHON3}", + "${ASSETS_COMPILER}", + "dolphin", + "${_DOLPHIN_SRC_DIR}", + "${_DOLPHIN_OUT_DIR}", + ], + ], "${DOLPHINCOMSTR}", ), - emitter=dolphin_emitter, + emitter=_dolphin_emitter, ), "ProtoVerBuilder": Builder( action=Action( - proto_ver_generator, + _proto_ver_generator, "${PBVERCOMSTR}", ), ), diff --git a/scripts/fbt_tools/fbt_dist.py b/scripts/fbt_tools/fbt_dist.py index 3645008c5..160f5fa03 100644 --- a/scripts/fbt_tools/fbt_dist.py +++ b/scripts/fbt_tools/fbt_dist.py @@ -96,7 +96,21 @@ def DistCommand(env, name, source, **kw): command = env.Command( target, source, - '@${PYTHON3} "${DIST_SCRIPT}" copy -p ${DIST_PROJECTS} -s "${DIST_SUFFIX}" ${DIST_EXTRA}', + action=Action( + [ + [ + "${PYTHON3}", + "${DIST_SCRIPT}", + "copy", + "-p", + "${DIST_PROJECTS}", + "-s", + "${DIST_SUFFIX}", + "${DIST_EXTRA}", + ] + ], + "${DISTCOMSTR}", + ), **kw, ) env.Pseudo(target) @@ -106,7 +120,10 @@ def DistCommand(env, name, source, **kw): def generate(env): if not env["VERBOSE"]: - env.SetDefault(COPROCOMSTR="\tCOPRO\t${TARGET}") + env.SetDefault( + COPROCOMSTR="\tCOPRO\t${TARGET}", + DISTCOMSTR="\tDIST\t${TARGET}", + ) env.AddMethod(AddFwProject) env.AddMethod(DistCommand) env.AddMethod(AddFwFlashTarget) diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index 963429f24..b88fa7929 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -1,7 +1,5 @@ import itertools -import os import pathlib -import shutil from dataclasses import dataclass, field from typing import Dict, List, Optional @@ -149,16 +147,10 @@ class AppBuilder: CPPPATH=[self.app_work_dir, self.app._appdir], ) - app_sources = list( - itertools.chain.from_iterable( - self.app_env.GlobRecursive( - source_type, - self.app_work_dir, - exclude="lib", - ) - for source_type in self.app.sources - ) + app_sources = self.app_env.GatherSources( + [self.app.sources, "!lib"], self.app_work_dir ) + if not app_sources: raise UserError(f"No source files found for {self.app.appid}") @@ -290,7 +282,7 @@ def prepare_app_metadata(target, source, env): ) -def validate_app_imports(target, source, env): +def _validate_app_imports(target, source, env): sdk_cache = SdkCache(env["SDK_DEFINITION"].path, load_version_only=False) app_syms = set() with open(target[0].path, "rt") as f: @@ -342,35 +334,7 @@ def GetExtAppByIdOrPath(env, app_dir): return app_artifacts -def resources_fap_dist_emitter(target, source, env): - # Initially we have a single target - target dir - # Here we inject pairs of (target, source) for each file - resources_root = target[0] - - target = [] - for app_artifacts in env["EXT_APPS"].values(): - for _, dist_path in filter( - lambda dist_entry: dist_entry[0], app_artifacts.dist_entries - ): - source.append(app_artifacts.compact) - target.append(resources_root.File(dist_path)) - - assert len(target) == len(source) - return (target, source) - - -def resources_fap_dist_action(target, source, env): - # FIXME: find a proper way to remove stale files - target_dir = env.Dir("${RESOURCES_ROOT}/apps") - shutil.rmtree(target_dir.path, ignore_errors=True) - - # Iterate over pairs generated in emitter - for src, target in zip(source, target): - os.makedirs(os.path.dirname(target.path), exist_ok=True) - shutil.copy(src.path, target.path) - - -def embed_app_metadata_emitter(target, source, env): +def _embed_app_metadata_emitter(target, source, env): app = env["APP"] # Hack: change extension for fap libs @@ -407,33 +371,52 @@ def generate_embed_app_metadata_actions(source, target, env, for_signature): Action(prepare_app_metadata, "$APPMETA_COMSTR"), ] - objcopy_str = ( - "${OBJCOPY} " - "--remove-section .ARM.attributes " - "--add-section ${_FAP_META_SECTION}=${APP._section_fapmeta} " - ) + objcopy_args = [ + "${OBJCOPY}", + "--remove-section", + ".ARM.attributes", + "--add-section", + "${_FAP_META_SECTION}=${APP._section_fapmeta}", + "--set-section-flags", + "${_FAP_META_SECTION}=contents,noload,readonly,data", + ] if app._section_fapfileassets: actions.append(Action(prepare_app_file_assets, "$APPFILE_COMSTR")) - objcopy_str += ( - "--add-section ${_FAP_FILEASSETS_SECTION}=${APP._section_fapfileassets} " + objcopy_args.extend( + ( + "--add-section", + "${_FAP_FILEASSETS_SECTION}=${APP._section_fapfileassets}", + "--set-section-flags", + "${_FAP_FILEASSETS_SECTION}=contents,noload,readonly,data", + ) ) - objcopy_str += ( - "--set-section-flags ${_FAP_META_SECTION}=contents,noload,readonly,data " - "--strip-debug --strip-unneeded " - "--add-gnu-debuglink=${SOURCE} " - "${SOURCES} ${TARGET}" + objcopy_args.extend( + ( + "--strip-debug", + "--strip-unneeded", + "--add-gnu-debuglink=${SOURCE}", + "${SOURCES}", + "${TARGET}", + ) ) actions.extend( ( Action( - objcopy_str, + [objcopy_args], "$APPMETAEMBED_COMSTR", ), Action( - "${PYTHON3} ${FBT_SCRIPT_DIR}/fastfap.py ${TARGET} ${OBJCOPY}", + [ + [ + "${PYTHON3}", + "${FBT_SCRIPT_DIR}/fastfap.py", + "${TARGET}", + "${OBJCOPY}", + ] + ], "$FASTFAP_COMSTR", ), ) @@ -511,7 +494,6 @@ def generate(env, **kw): ) if not env["VERBOSE"]: env.SetDefault( - FAPDISTCOMSTR="\tFAPDIST\t${TARGET}", APPMETA_COMSTR="\tAPPMETA\t${TARGET}", APPFILE_COMSTR="\tAPPFILE\t${TARGET}", APPMETAEMBED_COMSTR="\tFAP\t${TARGET}", @@ -534,18 +516,11 @@ def generate(env, **kw): env.Append( BUILDERS={ - "FapDist": Builder( - action=Action( - resources_fap_dist_action, - "$FAPDISTCOMSTR", - ), - emitter=resources_fap_dist_emitter, - ), "EmbedAppMetadata": Builder( generator=generate_embed_app_metadata_actions, suffix=".fap", src_suffix=".elf", - emitter=embed_app_metadata_emitter, + emitter=_embed_app_metadata_emitter, ), "ValidateAppImports": Builder( action=[ @@ -554,7 +529,7 @@ def generate(env, **kw): None, # "$APPDUMP_COMSTR", ), Action( - validate_app_imports, + _validate_app_imports, "$APPCHECK_COMSTR", ), ], diff --git a/scripts/fbt_tools/fbt_hwtarget.py b/scripts/fbt_tools/fbt_hwtarget.py index e7f857b1e..8e55b7d96 100644 --- a/scripts/fbt_tools/fbt_hwtarget.py +++ b/scripts/fbt_tools/fbt_hwtarget.py @@ -2,9 +2,9 @@ import json class HardwareTargetLoader: - def __init__(self, env, target_scons_dir, target_id): + def __init__(self, env, root_target_scons_dir, target_id): self.env = env - self.target_scons_dir = target_scons_dir + self.all_targets_root_dir = root_target_scons_dir self.target_dir = self._getTargetDir(target_id) # self.target_id = target_id self.layered_target_dirs = [] @@ -23,7 +23,7 @@ class HardwareTargetLoader: self._processTargetDefinitions(target_id) def _getTargetDir(self, target_id): - return self.target_scons_dir.Dir(f"f{target_id}") + return self.all_targets_root_dir.Dir(f"f{target_id}") def _loadDescription(self, target_id): target_json_file = self._getTargetDir(target_id).File("target.json") @@ -34,14 +34,14 @@ class HardwareTargetLoader: return vals def _processTargetDefinitions(self, target_id): - self.layered_target_dirs.append(f"targets/f{target_id}") + target_dir = self._getTargetDir(target_id) + self.layered_target_dirs.append(target_dir) config = self._loadDescription(target_id) for path_list in ("include_paths", "sdk_header_paths"): getattr(self, path_list).extend( - f"#/firmware/targets/f{target_id}/{p}" - for p in config.get(path_list, []) + target_dir.Dir(p) for p in config.get(path_list, []) ) self.excluded_sources.extend(config.get("excluded_sources", [])) @@ -50,7 +50,7 @@ class HardwareTargetLoader: file_attrs = ( # (name, use_src_node) - ("startup_script", False), + ("startup_script", True), ("linker_script_flash", True), ("linker_script_ram", True), ("linker_script_app", True), @@ -59,9 +59,10 @@ class HardwareTargetLoader: for attr_name, use_src_node in file_attrs: if (val := config.get(attr_name)) and not getattr(self, attr_name): - node = self.env.File(f"firmware/targets/f{target_id}/{val}") + node = target_dir.File(val) if use_src_node: node = node.srcnode() + # print(f"Got node {node}, {node.path} for {attr_name}") setattr(self, attr_name, node) for attr_name in ("linker_dependencies",): @@ -84,8 +85,8 @@ class HardwareTargetLoader: ) seen_filenames.update(f.name for f in accepted_sources) sources.extend(accepted_sources) - # print(f"Found {len(sources)} sources: {list(f.name for f in sources)}") - return sources + # print(f"Found {len(sources)} sources: {list(f.path for f in sources)}") + return list(f.get_path(self.all_targets_root_dir) for f in sources) def gatherSdkHeaders(self): sdk_headers = [] @@ -101,7 +102,7 @@ class HardwareTargetLoader: def ConfigureForTarget(env, target_id): - target_loader = HardwareTargetLoader(env, env.Dir("#/firmware/targets"), target_id) + target_loader = HardwareTargetLoader(env, env["TARGETS_ROOT"], target_id) env.Replace( TARGET_CFG=target_loader, SDK_DEFINITION=target_loader.sdk_symbols, diff --git a/scripts/fbt_tools/fbt_resources.py b/scripts/fbt_tools/fbt_resources.py new file mode 100644 index 000000000..4c3146ba4 --- /dev/null +++ b/scripts/fbt_tools/fbt_resources.py @@ -0,0 +1,117 @@ +import os +import shutil + +from SCons.Action import Action +from SCons.Builder import Builder +from SCons.Errors import StopError +from SCons.Node.FS import Dir, File + + +def __generate_resources_dist_entries(env): + src_target_entries = [] + + resources_root = env.Dir(env["RESOURCES_ROOT"]) + + for app_artifacts in env["FW_EXTAPPS"].application_map.values(): + for _, dist_path in filter( + lambda dist_entry: dist_entry[0], app_artifacts.dist_entries + ): + src_target_entries.append( + ( + app_artifacts.compact, + resources_root.File(dist_path), + ) + ) + + # Deploy apps' resources too + for app in env["APPBUILD"].apps: + if not app.resources: + continue + apps_resource_dir = app._appdir.Dir(app.resources) + for res_file in env.GlobRecursive("*", apps_resource_dir): + if not isinstance(res_file, File): + continue + src_target_entries.append( + ( + res_file, + resources_root.File( + res_file.get_path(apps_resource_dir), + ), + ) + ) + + # Deploy other stuff from _EXTRA_DIST + for extra_dist in env["_EXTRA_DIST"]: + if isinstance(extra_dist, Dir): + src_target_entries.append( + ( + extra_dist, + resources_root.Dir(extra_dist.name), + ) + ) + else: + raise StopError(f"Unsupported extra dist type: {type(extra_dist)}") + + return src_target_entries + + +def _resources_dist_emitter(target, source, env): + src_target_entries = __generate_resources_dist_entries(env) + source = list(map(lambda entry: entry[0], src_target_entries)) + return (target, source) + + +def _resources_dist_action(target, source, env): + dist_entries = __generate_resources_dist_entries(env) + assert len(dist_entries) == len(source) + shutil.rmtree(env.Dir(env["RESOURCES_ROOT"]).abspath, ignore_errors=True) + for src, target in dist_entries: + if isinstance(src, File): + os.makedirs(os.path.dirname(target.path), exist_ok=True) + shutil.copy(src.path, target.path) + elif isinstance(src, Dir): + shutil.copytree(src.path, target.path) + else: + raise StopError(f"Unsupported dist entry type: {type(src)}") + + +def generate(env, **kw): + env.SetDefault( + ASSETS_COMPILER="${FBT_SCRIPT_DIR}/assets.py", + ) + + if not env["VERBOSE"]: + env.SetDefault( + RESOURCEDISTCOMSTR="\tRESDIST\t${RESOURCES_ROOT}", + RESMANIFESTCOMSTR="\tMANIFST\t${TARGET}", + ) + + env.Append( + BUILDERS={ + "ManifestBuilder": Builder( + action=[ + Action( + _resources_dist_action, + "${RESOURCEDISTCOMSTR}", + ), + Action( + [ + [ + "${PYTHON3}", + "${ASSETS_COMPILER}", + "manifest", + "${TARGET.dir.posix}", + "--timestamp=${GIT_UNIX_TIMESTAMP}", + ] + ], + "${RESMANIFESTCOMSTR}", + ), + ], + emitter=_resources_dist_emitter, + ), + } + ) + + +def exists(env): + return True diff --git a/scripts/fbt_tools/fbt_sdk.py b/scripts/fbt_tools/fbt_sdk.py index 2f7d62388..6350f14b8 100644 --- a/scripts/fbt_tools/fbt_sdk.py +++ b/scripts/fbt_tools/fbt_sdk.py @@ -37,13 +37,13 @@ def ProcessSdkDepends(env, filename): return depends -def api_amalgam_emitter(target, source, env): +def _api_amalgam_emitter(target, source, env): target.append(env.ChangeFileExtension(target[0], ".d")) target.append(env.ChangeFileExtension(target[0], ".i.c")) return target, source -def api_amalgam_gen_origin_header(target, source, env): +def _api_amalgam_gen_origin_header(target, source, env): mega_file = env.subst("${TARGET}.c", target=target[0]) with open(mega_file, "wt") as sdk_c: sdk_c.write( @@ -183,12 +183,12 @@ class SdkTreeBuilder: self._generate_sdk_meta() -def deploy_sdk_header_tree_action(target, source, env): +def _deploy_sdk_header_tree_action(target, source, env): sdk_tree = SdkTreeBuilder(env, target, source) return sdk_tree.deploy_action() -def deploy_sdk_header_tree_emitter(target, source, env): +def _deploy_sdk_header_tree_emitter(target, source, env): sdk_tree = SdkTreeBuilder(env, target, source) return sdk_tree.emitter(target, source, env) @@ -227,7 +227,7 @@ def _check_sdk_is_up2date(sdk_cache: SdkCache): ) -def validate_api_cache(source, target, env): +def _validate_api_cache(source, target, env): # print(f"Generating SDK for {source[0]} to {target[0]}") current_sdk = SdkCollector() current_sdk.process_source_file_for_sdk(source[0].path) @@ -240,7 +240,7 @@ def validate_api_cache(source, target, env): _check_sdk_is_up2date(sdk_cache) -def generate_api_table(source, target, env): +def _generate_api_table(source, target, env): sdk_cache = SdkCache(source[0].path) _check_sdk_is_up2date(sdk_cache) @@ -278,10 +278,10 @@ def generate(env, **kw): env.Append( BUILDERS={ "ApiAmalgamator": Builder( - emitter=api_amalgam_emitter, + emitter=_api_amalgam_emitter, action=[ Action( - api_amalgam_gen_origin_header, + _api_amalgam_gen_origin_header, "$SDK_AMALGAMATE_HEADER_COMSTR", ), Action( @@ -293,15 +293,15 @@ def generate(env, **kw): ), "SDKHeaderTreeExtractor": Builder( action=Action( - deploy_sdk_header_tree_action, + _deploy_sdk_header_tree_action, "$SDKTREE_COMSTR", ), - emitter=deploy_sdk_header_tree_emitter, + emitter=_deploy_sdk_header_tree_emitter, src_suffix=".d", ), "ApiTableValidator": Builder( action=Action( - validate_api_cache, + _validate_api_cache, "$SDKSYM_UPDATER_COMSTR", ), suffix=".csv", @@ -309,7 +309,7 @@ def generate(env, **kw): ), "ApiSymbolTable": Builder( action=Action( - generate_api_table, + _generate_api_table, "$APITABLE_GENERATOR_COMSTR", ), suffix=".h", diff --git a/scripts/fbt_tools/fbt_version.py b/scripts/fbt_tools/fbt_version.py index 1bd86f1f1..1f755d4a4 100644 --- a/scripts/fbt_tools/fbt_version.py +++ b/scripts/fbt_tools/fbt_version.py @@ -2,7 +2,7 @@ from SCons.Action import Action from SCons.Builder import Builder -def version_emitter(target, source, env): +def _version_emitter(target, source, env): target_dir = target[0] target = [ target_dir.File("version.inc.h"), @@ -24,7 +24,7 @@ def generate(env): '-o ${TARGET.dir.posix} --dir "${ROOT_DIR}" --suffix "${DIST_SUFFIX}"', "${VERSIONCOMSTR}", ), - emitter=version_emitter, + emitter=_version_emitter, ), } ) diff --git a/scripts/fbt_tools/pvsstudio.py b/scripts/fbt_tools/pvsstudio.py index 211f46aee..f43db126e 100644 --- a/scripts/fbt_tools/pvsstudio.py +++ b/scripts/fbt_tools/pvsstudio.py @@ -17,7 +17,7 @@ def _set_browser_action(target, source, env): __no_browser = True -def emit_pvsreport(target, source, env): +def _emit_pvsreport(target, source, env): target_dir = env["REPORT_DIR"] if env["PLATFORM"] == "win32": # Report generator on Windows emits to a subfolder of given output folder @@ -96,7 +96,7 @@ def generate(env): ], "${PVSCONVCOMSTR}", ), - emitter=emit_pvsreport, + emitter=_emit_pvsreport, src_suffix=".log", ), } diff --git a/scripts/fbt_tools/sconsrecursiveglob.py b/scripts/fbt_tools/sconsrecursiveglob.py index e7eb8fb72..de64c76b7 100644 --- a/scripts/fbt_tools/sconsrecursiveglob.py +++ b/scripts/fbt_tools/sconsrecursiveglob.py @@ -1,7 +1,9 @@ +import itertools + import SCons from fbt.util import GLOB_FILE_EXCLUSION -from SCons.Script import Flatten from SCons.Node.FS import has_glob_magic +from SCons.Script import Flatten def GlobRecursive(env, pattern, node=".", exclude=[]): @@ -23,12 +25,35 @@ def GlobRecursive(env, pattern, node=".", exclude=[]): # Otherwise, just assume that file at path exists else: results.append(node.File(pattern)) + ## Debug # print(f"Glob result for {pattern} from {node}: {results}") return results +def GatherSources(env, sources_list, node="."): + sources_list = list(set(Flatten(sources_list))) + include_sources = list(filter(lambda x: not x.startswith("!"), sources_list)) + exclude_sources = list(x[1:] for x in sources_list if x.startswith("!")) + gathered_sources = list( + itertools.chain.from_iterable( + env.GlobRecursive( + source_type, + node, + exclude=exclude_sources, + ) + for source_type in include_sources + ) + ) + ## Debug + # print( + # f"Gathered sources for {sources_list} from {node}: {list(f.path for f in gathered_sources)}" + # ) + return gathered_sources + + def generate(env): env.AddMethod(GlobRecursive) + env.AddMethod(GatherSources) def exists(env): diff --git a/scripts/flipper/assets/dolphin.py b/scripts/flipper/assets/dolphin.py index e9089a1b9..cf98c8253 100644 --- a/scripts/flipper/assets/dolphin.py +++ b/scripts/flipper/assets/dolphin.py @@ -55,7 +55,7 @@ class DolphinBubbleAnimation: if not os.path.isfile(meta_filename): raise Exception(f"Animation meta file doesn't exist: { meta_filename }") - self.logger.info(f"Loading meta from {meta_filename}") + self.logger.debug(f"Loading meta from {meta_filename}") file = FlipperFormatFile() file.load(meta_filename) diff --git a/scripts/meta.py b/scripts/meta.py deleted file mode 100755 index f47ef65fb..000000000 --- a/scripts/meta.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python3 - -import json - -from flipper.app import App - - -class Main(App): - def init(self): - self.subparsers = self.parser.add_subparsers(help="sub-command help") - - # generate - self.parser_generate = self.subparsers.add_parser( - "generate", help="Generate JSON meta file" - ) - self.parser_generate.add_argument("-p", dest="project", required=True) - self.parser_generate.add_argument( - "-DBUILD_DATE", dest="build_date", required=True - ) - self.parser_generate.add_argument("-DGIT_COMMIT", dest="commit", required=True) - self.parser_generate.add_argument("-DGIT_BRANCH", dest="branch", required=True) - self.parser_generate.add_argument( - "-DTARGET", dest="target", type=int, required=True - ) - self.parser_generate.set_defaults(func=self.generate) - - # merge - self.parser_merge = self.subparsers.add_parser( - "merge", help="Merge JSON meta files" - ) - self.parser_merge.add_argument( - "-i", dest="input", action="append", nargs="+", required=True - ) - self.parser_merge.set_defaults(func=self.merge) - - def generate(self): - meta = {} - for k, v in vars(self.args).items(): - if k in ["project", "func", "debug"]: - continue - if isinstance(v, str): - v = v.strip('"') - meta[self.args.project + "_" + k] = v - - print(json.dumps(meta, indent=4)) - return 0 - - def merge(self): - full = {} - for path in self.args.input[0]: - with open(path, mode="r") as file: - dict = json.loads(file.read()) - full.update(dict) - - print(json.dumps(full, indent=4)) - return 0 - - -if __name__ == "__main__": - Main()() diff --git a/scripts/ufbt/project_template/app_template/.github/workflows/build.yml b/scripts/ufbt/project_template/app_template/.github/workflows/build.yml index c11ffc180..143847c4a 100644 --- a/scripts/ufbt/project_template/app_template/.github/workflows/build.yml +++ b/scripts/ufbt/project_template/app_template/.github/workflows/build.yml @@ -27,9 +27,9 @@ jobs: name: 'ufbt: Build for ${{ matrix.name }}' steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build with ufbt - uses: flipperdevices/flipperzero-ufbt-action@v0.1.1 + uses: flipperdevices/flipperzero-ufbt-action@v0.1 id: build-app with: sdk-channel: ${{ matrix.sdk-channel }} diff --git a/scripts/version.py b/scripts/version.py index 68670061b..032969af6 100755 --- a/scripts/version.py +++ b/scripts/version.py @@ -47,7 +47,7 @@ class GitVersion: ) else: commit_date = datetime.strptime( - self._exec_git("log -1 --format=%cd").strip(), + self._exec_git("log -1 --format=%cd --date=default").strip(), "%a %b %d %H:%M:%S %Y %z", ) diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index f9227ed37..769b3eb15 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -14,7 +14,6 @@ appenv = ENV["APPENV"] = ENV.Clone( "fbt_assets", "fbt_sdk", ], - RESOURCES_ROOT=ENV.Dir("#/assets/resources"), ) appenv.Replace( @@ -56,7 +55,6 @@ appenv.AppendUnique( @dataclass class FlipperExtAppBuildArtifacts: application_map: dict = field(default_factory=dict) - resources_dist: NodeList = field(default_factory=NodeList) sdk_tree: NodeList = field(default_factory=NodeList) @@ -78,8 +76,6 @@ Alias( list(app_artifact.validator for app_artifact in extapps.application_map.values()), ) -extapps.resources_dist = appenv.FapDist(appenv["RESOURCES_ROOT"], []) - if appsrc := appenv.subst("$APPSRC"): launch_target = appenv.AddAppLaunchTarget(appsrc, "launch") diff --git a/firmware/ReadMe.md b/targets/ReadMe.md similarity index 100% rename from firmware/ReadMe.md rename to targets/ReadMe.md diff --git a/firmware/SConscript b/targets/SConscript similarity index 100% rename from firmware/SConscript rename to targets/SConscript diff --git a/firmware/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv similarity index 94% rename from firmware/targets/f18/api_symbols.csv rename to targets/f18/api_symbols.csv index 4789d316d..0eadd799d 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,40.1,, +Version,+,44.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -36,51 +36,6 @@ Header,+,applications/services/notification/notification_messages.h,, Header,+,applications/services/power/power_service/power.h,, Header,+,applications/services/rpc/rpc_app.h,, Header,+,applications/services/storage/storage.h,, -Header,+,firmware/targets/f18/furi_hal/furi_hal_resources.h,, -Header,+,firmware/targets/f18/furi_hal/furi_hal_spi_config.h,, -Header,+,firmware/targets/f18/furi_hal/furi_hal_target_hw.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_bus.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_clock.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_console.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_dma.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_flash.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_gpio.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_config.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_types.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_idle_timer.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_interrupt.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_os.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_pwm.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_types.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_uart.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h,, -Header,+,firmware/targets/f7/platform_specific/intrinsic_export.h,, -Header,+,firmware/targets/f7/platform_specific/math_wrapper.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_bt.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_bt_hid.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_bt_serial.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_cortex.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_crypto.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_debug.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_i2c.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_info.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_light.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_memory.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_mpu.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_power.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_random.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_region.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_rtc.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_sd.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_speaker.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_spi.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_usb.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_usb_ccid.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, Header,+,lib/digital_signal/digital_sequence.h,, Header,+,lib/digital_signal/digital_signal.h,, Header,+,lib/drivers/cc1101_regs.h,, @@ -194,6 +149,51 @@ Header,+,lib/toolbox/stream/string_stream.h,, Header,+,lib/toolbox/tar/tar_archive.h,, Header,+,lib/toolbox/value_index.h,, Header,+,lib/toolbox/version.h,, +Header,+,targets/f18/furi_hal/furi_hal_resources.h,, +Header,+,targets/f18/furi_hal/furi_hal_spi_config.h,, +Header,+,targets/f18/furi_hal/furi_hal_target_hw.h,, +Header,+,targets/f7/furi_hal/furi_hal_bus.h,, +Header,+,targets/f7/furi_hal/furi_hal_clock.h,, +Header,+,targets/f7/furi_hal/furi_hal_console.h,, +Header,+,targets/f7/furi_hal/furi_hal_dma.h,, +Header,+,targets/f7/furi_hal/furi_hal_flash.h,, +Header,+,targets/f7/furi_hal/furi_hal_gpio.h,, +Header,+,targets/f7/furi_hal/furi_hal_i2c_config.h,, +Header,+,targets/f7/furi_hal/furi_hal_i2c_types.h,, +Header,+,targets/f7/furi_hal/furi_hal_idle_timer.h,, +Header,+,targets/f7/furi_hal/furi_hal_interrupt.h,, +Header,+,targets/f7/furi_hal/furi_hal_os.h,, +Header,+,targets/f7/furi_hal/furi_hal_pwm.h,, +Header,+,targets/f7/furi_hal/furi_hal_spi_types.h,, +Header,+,targets/f7/furi_hal/furi_hal_uart.h,, +Header,+,targets/f7/furi_hal/furi_hal_usb_cdc.h,, +Header,+,targets/f7/platform_specific/intrinsic_export.h,, +Header,+,targets/f7/platform_specific/math_wrapper.h,, +Header,+,targets/furi_hal_include/furi_hal.h,, +Header,+,targets/furi_hal_include/furi_hal_bt.h,, +Header,+,targets/furi_hal_include/furi_hal_bt_hid.h,, +Header,+,targets/furi_hal_include/furi_hal_bt_serial.h,, +Header,+,targets/furi_hal_include/furi_hal_cortex.h,, +Header,+,targets/furi_hal_include/furi_hal_crypto.h,, +Header,+,targets/furi_hal_include/furi_hal_debug.h,, +Header,+,targets/furi_hal_include/furi_hal_i2c.h,, +Header,+,targets/furi_hal_include/furi_hal_info.h,, +Header,+,targets/furi_hal_include/furi_hal_light.h,, +Header,+,targets/furi_hal_include/furi_hal_memory.h,, +Header,+,targets/furi_hal_include/furi_hal_mpu.h,, +Header,+,targets/furi_hal_include/furi_hal_power.h,, +Header,+,targets/furi_hal_include/furi_hal_random.h,, +Header,+,targets/furi_hal_include/furi_hal_region.h,, +Header,+,targets/furi_hal_include/furi_hal_rtc.h,, +Header,+,targets/furi_hal_include/furi_hal_sd.h,, +Header,+,targets/furi_hal_include/furi_hal_speaker.h,, +Header,+,targets/furi_hal_include/furi_hal_spi.h,, +Header,+,targets/furi_hal_include/furi_hal_usb.h,, +Header,+,targets/furi_hal_include/furi_hal_usb_ccid.h,, +Header,+,targets/furi_hal_include/furi_hal_usb_hid.h,, +Header,+,targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, +Header,+,targets/furi_hal_include/furi_hal_version.h,, +Header,+,targets/furi_hal_include/furi_hal_vibro.h,, Function,-,LL_ADC_CommonDeInit,ErrorStatus,ADC_Common_TypeDef* Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, const LL_ADC_CommonInitTypeDef*" Function,-,LL_ADC_CommonStructInit,void,LL_ADC_CommonInitTypeDef* @@ -302,10 +302,10 @@ Function,-,__eprintf,void,"const char*, const char*, unsigned int, const char*" Function,+,__errno,int*, Function,-,__fpclassifyd,int,double Function,-,__fpclassifyf,int,float -Function,+,__furi_crash,void, +Function,+,__furi_crash_implementation,void, Function,+,__furi_critical_enter,__FuriCriticalInfo, Function,+,__furi_critical_exit,void,__FuriCriticalInfo -Function,+,__furi_halt,void, +Function,+,__furi_halt_implementation,void, Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*" Function,-,__getline,ssize_t,"char**, size_t*, FILE*" Function,-,__isinfd,int,double @@ -417,7 +417,6 @@ Function,-,_perror_r,void,"_reent*, const char*" Function,-,_printf_r,int,"_reent*, const char*, ..." Function,-,_putc_r,int,"_reent*, int, FILE*" Function,-,_putc_unlocked_r,int,"_reent*, int, FILE*" -Function,-,_putchar,void,char Function,-,_putchar_r,int,"_reent*, int" Function,-,_putchar_unlocked_r,int,"_reent*, int" Function,-,_putenv_r,int,"_reent*, char*" @@ -751,8 +750,6 @@ Function,-,dprintf,int,"int, const char*, ..." Function,-,drand48,double, Function,-,drem,double,"double, double" Function,-,dremf,float,"float, float" -Function,-,eTaskConfirmSleepModeStatus,eSleepModeStatus, -Function,-,eTaskGetState,eTaskState,TaskHandle_t Function,+,elements_bold_rounded_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,elements_bubble,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,elements_bubble_str,void,"Canvas*, uint8_t, uint8_t, const char*, Align, Align" @@ -1342,6 +1339,7 @@ Function,+,furi_hal_vibro_on,void,_Bool Function,-,furi_init,void, Function,+,furi_kernel_get_tick_frequency,uint32_t, Function,+,furi_kernel_is_irq_or_masked,_Bool, +Function,+,furi_kernel_is_running,_Bool, Function,+,furi_kernel_lock,int32_t, Function,+,furi_kernel_restore_lock,int32_t,int32_t Function,+,furi_kernel_unlock,int32_t, @@ -1452,7 +1450,6 @@ Function,+,furi_string_utf8_push,void,"FuriString*, FuriStringUnicodeValue" Function,+,furi_string_vprintf,int,"FuriString*, const char[], va_list" Function,+,furi_thread_alloc,FuriThread*, Function,+,furi_thread_alloc_ex,FuriThread*,"const char*, uint32_t, FuriThreadCallback, void*" -Function,+,furi_thread_catch,void, Function,-,furi_thread_disable_heap_trace,void,FuriThread* Function,+,furi_thread_enable_heap_trace,void,FuriThread* Function,+,furi_thread_enumerate,uint32_t,"FuriThreadId*, uint32_t" @@ -1493,8 +1490,11 @@ Function,+,furi_thread_suspend,void,FuriThreadId Function,+,furi_thread_yield,void, Function,+,furi_timer_alloc,FuriTimer*,"FuriTimerCallback, FuriTimerType, void*" Function,+,furi_timer_free,void,FuriTimer* +Function,+,furi_timer_get_expire_time,uint32_t,FuriTimer* Function,+,furi_timer_is_running,uint32_t,FuriTimer* Function,+,furi_timer_pending_callback,void,"FuriTimerPendigCallback, void*, uint32_t" +Function,+,furi_timer_restart,FuriStatus,"FuriTimer*, uint32_t" +Function,+,furi_timer_set_thread_priority,void,FuriTimerThreadPriority Function,+,furi_timer_start,FuriStatus,"FuriTimer*, uint32_t" Function,+,furi_timer_stop,FuriStatus,FuriTimer* Function,-,fwrite,size_t,"const void*, size_t, size_t, FILE*" @@ -1838,8 +1838,6 @@ Function,+,pb_read,_Bool,"pb_istream_t*, pb_byte_t*, size_t" Function,+,pb_release,void,"const pb_msgdesc_t*, void*" Function,+,pb_skip_field,_Bool,"pb_istream_t*, pb_wire_type_t" Function,+,pb_write,_Bool,"pb_ostream_t*, const pb_byte_t*, size_t" -Function,-,pcTaskGetName,char*,TaskHandle_t -Function,-,pcTimerGetName,const char*,TimerHandle_t Function,-,pclose,int,FILE* Function,-,perror,void,const char* Function,+,plugin_manager_alloc,PluginManager*,"const char*, uint32_t, const ElfApiInterface*" @@ -1914,12 +1912,6 @@ Function,-,putchar_unlocked,int,int Function,-,putenv,int,char* Function,-,puts,int,const char* Function,-,putw,int,"int, FILE*" -Function,-,pvPortCalloc,void*,"size_t, size_t" -Function,-,pvPortMalloc,void*,size_t -Function,-,pvTaskGetThreadLocalStoragePointer,void*,"TaskHandle_t, BaseType_t" -Function,-,pvTaskIncrementMutexHeldCount,TaskHandle_t, -Function,-,pvTimerGetTimerID,void*,const TimerHandle_t -Function,-,pxPortInitialiseStack,StackType_t*,"StackType_t*, TaskFunction_t, void*" Function,-,qsort,void,"void*, size_t, size_t, __compar_fn_t" Function,-,qsort_r,void,"void*, size_t, size_t, int (*)(const void*, const void*, void*), void*" Function,-,quick_exit,void,int @@ -1949,7 +1941,7 @@ Function,-,round,double,double Function,+,roundf,float,float Function,-,roundl,long double,long double Function,+,rpc_session_close,void,RpcSession* -Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, TickType_t" +Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, uint32_t" Function,+,rpc_session_get_available_size,size_t,RpcSession* Function,+,rpc_session_get_owner,RpcOwner,RpcSession* Function,+,rpc_session_open,RpcSession*,"Rpc*, RpcOwner" @@ -1958,14 +1950,12 @@ Function,+,rpc_session_set_close_callback,void,"RpcSession*, RpcSessionClosedCal Function,+,rpc_session_set_context,void,"RpcSession*, void*" Function,+,rpc_session_set_send_bytes_callback,void,"RpcSession*, RpcSendBytesCallback" Function,+,rpc_session_set_terminated_callback,void,"RpcSession*, RpcSessionTerminatedCallback" -Function,+,rpc_system_app_confirm,void,"RpcAppSystem*, RpcAppSystemEvent, _Bool" +Function,+,rpc_system_app_confirm,void,"RpcAppSystem*, _Bool" Function,+,rpc_system_app_error_reset,void,RpcAppSystem* Function,+,rpc_system_app_exchange_data,void,"RpcAppSystem*, const uint8_t*, size_t" -Function,+,rpc_system_app_get_data,const char*,RpcAppSystem* Function,+,rpc_system_app_send_exited,void,RpcAppSystem* Function,+,rpc_system_app_send_started,void,RpcAppSystem* Function,+,rpc_system_app_set_callback,void,"RpcAppSystem*, RpcAppSystemCallback, void*" -Function,+,rpc_system_app_set_data_exchange_callback,void,"RpcAppSystem*, RpcAppSystemDataExchangeCallback, void*" Function,+,rpc_system_app_set_error_code,void,"RpcAppSystem*, uint32_t" Function,+,rpc_system_app_set_error_text,void,"RpcAppSystem*, const char*" Function,-,rpmatch,int,const char* @@ -2281,67 +2271,10 @@ Function,-,uECC_sign_deterministic,int,"const uint8_t*, const uint8_t*, unsigned Function,-,uECC_valid_public_key,int,"const uint8_t*, uECC_Curve" Function,-,uECC_verify,int,"const uint8_t*, const uint8_t*, unsigned, const uint8_t*, uECC_Curve" Function,+,uint8_to_hex_chars,void,"const uint8_t*, uint8_t*, int" -Function,-,ulTaskGenericNotifyTake,uint32_t,"UBaseType_t, BaseType_t, TickType_t" -Function,-,ulTaskGenericNotifyValueClear,uint32_t,"TaskHandle_t, UBaseType_t, uint32_t" -Function,-,ulTaskGetIdleRunTimeCounter,uint32_t, -Function,-,ulTaskGetIdleRunTimePercent,uint32_t, Function,-,ungetc,int,"int, FILE*" Function,-,unsetenv,int,const char* Function,-,usbd_poll,void,usbd_device* Function,-,utoa,char*,"unsigned, char*, int" -Function,-,uxListRemove,UBaseType_t,ListItem_t* -Function,-,uxTaskGetNumberOfTasks,UBaseType_t, -Function,-,uxTaskGetStackHighWaterMark,UBaseType_t,TaskHandle_t -Function,-,uxTaskGetStackHighWaterMark2,uint16_t,TaskHandle_t -Function,-,uxTaskGetSystemState,UBaseType_t,"TaskStatus_t*, const UBaseType_t, uint32_t*" -Function,-,uxTaskGetTaskNumber,UBaseType_t,TaskHandle_t -Function,-,uxTaskPriorityGet,UBaseType_t,const TaskHandle_t -Function,-,uxTaskPriorityGetFromISR,UBaseType_t,const TaskHandle_t -Function,-,uxTaskResetEventItemValue,TickType_t, -Function,-,uxTimerGetReloadMode,UBaseType_t,TimerHandle_t -Function,-,uxTimerGetTimerNumber,UBaseType_t,TimerHandle_t -Function,-,vApplicationGetIdleTaskMemory,void,"StaticTask_t**, StackType_t**, uint32_t*" -Function,-,vApplicationGetTimerTaskMemory,void,"StaticTask_t**, StackType_t**, uint32_t*" -Function,-,vListInitialise,void,List_t* -Function,-,vListInitialiseItem,void,ListItem_t* -Function,-,vListInsert,void,"List_t*, ListItem_t*" -Function,-,vListInsertEnd,void,"List_t*, ListItem_t*" -Function,-,vPortDefineHeapRegions,void,const HeapRegion_t* -Function,-,vPortEndScheduler,void, -Function,+,vPortEnterCritical,void, -Function,+,vPortExitCritical,void, -Function,-,vPortFree,void,void* -Function,-,vPortGetHeapStats,void,HeapStats_t* -Function,-,vPortInitialiseBlocks,void, -Function,-,vPortSuppressTicksAndSleep,void,TickType_t -Function,-,vTaskAllocateMPURegions,void,"TaskHandle_t, const MemoryRegion_t*" -Function,-,vTaskDelay,void,const TickType_t -Function,-,vTaskDelete,void,TaskHandle_t -Function,-,vTaskEndScheduler,void, -Function,-,vTaskGenericNotifyGiveFromISR,void,"TaskHandle_t, UBaseType_t, BaseType_t*" -Function,-,vTaskGetInfo,void,"TaskHandle_t, TaskStatus_t*, BaseType_t, eTaskState" -Function,-,vTaskGetRunTimeStats,void,char* -Function,-,vTaskInternalSetTimeOutState,void,TimeOut_t* -Function,-,vTaskList,void,char* -Function,-,vTaskMissedYield,void, -Function,-,vTaskPlaceOnEventList,void,"List_t*, const TickType_t" -Function,-,vTaskPlaceOnEventListRestricted,void,"List_t*, TickType_t, const BaseType_t" -Function,-,vTaskPlaceOnUnorderedEventList,void,"List_t*, const TickType_t, const TickType_t" -Function,-,vTaskPriorityDisinheritAfterTimeout,void,"const TaskHandle_t, UBaseType_t" -Function,+,vTaskPrioritySet,void,"TaskHandle_t, UBaseType_t" -Function,-,vTaskRemoveFromUnorderedEventList,void,"ListItem_t*, const TickType_t" -Function,-,vTaskResume,void,TaskHandle_t -Function,-,vTaskSetTaskNumber,void,"TaskHandle_t, const UBaseType_t" -Function,-,vTaskSetThreadLocalStoragePointer,void,"TaskHandle_t, BaseType_t, void*" -Function,-,vTaskSetTimeOutState,void,TimeOut_t* -Function,-,vTaskStartScheduler,void, -Function,-,vTaskStepTick,void,TickType_t -Function,-,vTaskSuspend,void,TaskHandle_t -Function,-,vTaskSuspendAll,void, -Function,-,vTaskSwitchContext,void, -Function,-,vTimerSetReloadMode,void,"TimerHandle_t, const BaseType_t" -Function,-,vTimerSetTimerID,void,"TimerHandle_t, void*" -Function,-,vTimerSetTimerNumber,void,"TimerHandle_t, UBaseType_t" Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*" Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*" Function,+,validator_is_file_free,void,ValidatorIsFile* @@ -2456,43 +2389,6 @@ Function,+,widget_alloc,Widget*, Function,+,widget_free,void,Widget* Function,+,widget_get_view,View*,Widget* Function,+,widget_reset,void,Widget* -Function,-,xPortGetFreeHeapSize,size_t, -Function,-,xPortGetMinimumEverFreeHeapSize,size_t, -Function,-,xPortStartScheduler,BaseType_t, -Function,-,xTaskAbortDelay,BaseType_t,TaskHandle_t -Function,-,xTaskCallApplicationTaskHook,BaseType_t,"TaskHandle_t, void*" -Function,-,xTaskCatchUpTicks,BaseType_t,TickType_t -Function,-,xTaskCheckForTimeOut,BaseType_t,"TimeOut_t*, TickType_t*" -Function,-,xTaskCreate,BaseType_t,"TaskFunction_t, const char*, const uint16_t, void*, UBaseType_t, TaskHandle_t*" -Function,-,xTaskCreateStatic,TaskHandle_t,"TaskFunction_t, const char*, const uint32_t, void*, UBaseType_t, StackType_t*, StaticTask_t*" -Function,-,xTaskDelayUntil,BaseType_t,"TickType_t*, const TickType_t" -Function,-,xTaskGenericNotify,BaseType_t,"TaskHandle_t, UBaseType_t, uint32_t, eNotifyAction, uint32_t*" -Function,-,xTaskGenericNotifyFromISR,BaseType_t,"TaskHandle_t, UBaseType_t, uint32_t, eNotifyAction, uint32_t*, BaseType_t*" -Function,-,xTaskGenericNotifyStateClear,BaseType_t,"TaskHandle_t, UBaseType_t" -Function,-,xTaskGenericNotifyWait,BaseType_t,"UBaseType_t, uint32_t, uint32_t, uint32_t*, TickType_t" -Function,-,xTaskGetCurrentTaskHandle,TaskHandle_t, -Function,+,xTaskGetHandle,TaskHandle_t,const char* -Function,-,xTaskGetIdleTaskHandle,TaskHandle_t, -Function,+,xTaskGetSchedulerState,BaseType_t, -Function,+,xTaskGetTickCount,TickType_t, -Function,-,xTaskGetTickCountFromISR,TickType_t, -Function,-,xTaskIncrementTick,BaseType_t, -Function,-,xTaskPriorityDisinherit,BaseType_t,const TaskHandle_t -Function,-,xTaskPriorityInherit,BaseType_t,const TaskHandle_t -Function,-,xTaskRemoveFromEventList,BaseType_t,const List_t* -Function,-,xTaskResumeAll,BaseType_t, -Function,-,xTaskResumeFromISR,BaseType_t,TaskHandle_t -Function,-,xTimerCreate,TimerHandle_t,"const char*, const TickType_t, const BaseType_t, void*, TimerCallbackFunction_t" -Function,-,xTimerCreateStatic,TimerHandle_t,"const char*, const TickType_t, const BaseType_t, void*, TimerCallbackFunction_t, StaticTimer_t*" -Function,-,xTimerCreateTimerTask,BaseType_t, -Function,-,xTimerGenericCommand,BaseType_t,"TimerHandle_t, const BaseType_t, const TickType_t, BaseType_t*, const TickType_t" -Function,-,xTimerGetExpiryTime,TickType_t,TimerHandle_t -Function,-,xTimerGetPeriod,TickType_t,TimerHandle_t -Function,-,xTimerGetReloadMode,BaseType_t,TimerHandle_t -Function,-,xTimerGetTimerDaemonTaskHandle,TaskHandle_t, -Function,-,xTimerIsTimerActive,BaseType_t,TimerHandle_t -Function,-,xTimerPendFunctionCall,BaseType_t,"PendedFunction_t, void*, uint32_t, TickType_t" -Function,-,xTimerPendFunctionCallFromISR,BaseType_t,"PendedFunction_t, void*, uint32_t, BaseType_t*" Function,-,y0,double,double Function,-,y0f,float,float Function,-,y1,double,double diff --git a/firmware/targets/f18/furi_hal/furi_hal.c b/targets/f18/furi_hal/furi_hal.c similarity index 100% rename from firmware/targets/f18/furi_hal/furi_hal.c rename to targets/f18/furi_hal/furi_hal.c diff --git a/firmware/targets/f18/furi_hal/furi_hal_power_config.c b/targets/f18/furi_hal/furi_hal_power_config.c similarity index 100% rename from firmware/targets/f18/furi_hal/furi_hal_power_config.c rename to targets/f18/furi_hal/furi_hal_power_config.c diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.c b/targets/f18/furi_hal/furi_hal_resources.c similarity index 100% rename from firmware/targets/f18/furi_hal/furi_hal_resources.c rename to targets/f18/furi_hal/furi_hal_resources.c diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.h b/targets/f18/furi_hal/furi_hal_resources.h similarity index 100% rename from firmware/targets/f18/furi_hal/furi_hal_resources.h rename to targets/f18/furi_hal/furi_hal_resources.h diff --git a/firmware/targets/f18/furi_hal/furi_hal_spi_config.c b/targets/f18/furi_hal/furi_hal_spi_config.c similarity index 100% rename from firmware/targets/f18/furi_hal/furi_hal_spi_config.c rename to targets/f18/furi_hal/furi_hal_spi_config.c diff --git a/firmware/targets/f18/furi_hal/furi_hal_spi_config.h b/targets/f18/furi_hal/furi_hal_spi_config.h similarity index 100% rename from firmware/targets/f18/furi_hal/furi_hal_spi_config.h rename to targets/f18/furi_hal/furi_hal_spi_config.h diff --git a/firmware/targets/f18/furi_hal/furi_hal_target_hw.h b/targets/f18/furi_hal/furi_hal_target_hw.h similarity index 100% rename from firmware/targets/f18/furi_hal/furi_hal_target_hw.h rename to targets/f18/furi_hal/furi_hal_target_hw.h diff --git a/firmware/targets/f18/furi_hal/furi_hal_version_device.c b/targets/f18/furi_hal/furi_hal_version_device.c similarity index 100% rename from firmware/targets/f18/furi_hal/furi_hal_version_device.c rename to targets/f18/furi_hal/furi_hal_version_device.c diff --git a/firmware/targets/f18/target.json b/targets/f18/target.json similarity index 100% rename from firmware/targets/f18/target.json rename to targets/f18/target.json diff --git a/firmware/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv similarity index 95% rename from firmware/targets/f7/api_symbols.csv rename to targets/f7/api_symbols.csv index 445bae51a..882f24369 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,40.1,, +Version,+,44.0,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/main/archive/helpers/archive_helpers_ext.h,, Header,+,applications/services/applications.h,, @@ -41,56 +41,6 @@ Header,+,applications/services/power/power_service/power.h,, Header,+,applications/services/rpc/rpc_app.h,, Header,+,applications/services/storage/storage.h,, Header,+,build/icons/assets_icons.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_bus.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_clock.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_console.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_dma.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_flash.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_gpio.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_config.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_types.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_ibutton.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_idle_timer.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_interrupt.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_os.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_pwm.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_resources.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_rfid.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_config.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_types.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_subghz.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_target_hw.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_uart.h,, -Header,+,firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h,, -Header,+,firmware/targets/f7/platform_specific/intrinsic_export.h,, -Header,+,firmware/targets/f7/platform_specific/math_wrapper.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_bt.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_bt_hid.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_bt_serial.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_cortex.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_crypto.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_debug.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_i2c.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_info.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_infrared.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_light.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_memory.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_mpu.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_nfc.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_power.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_random.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_region.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_rtc.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_sd.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_speaker.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_spi.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_usb.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_usb_ccid.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, -Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, Header,+,lib/digital_signal/digital_sequence.h,, Header,+,lib/digital_signal/digital_signal.h,, Header,+,lib/drivers/cc1101_regs.h,, @@ -235,6 +185,7 @@ Header,+,lib/subghz/blocks/math.h,, Header,+,lib/subghz/devices/cc1101_configs.h,, Header,+,lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h,, Header,+,lib/subghz/environment.h,, +Header,+,lib/subghz/protocols/public_api.h,, Header,+,lib/subghz/protocols/raw.h,, Header,+,lib/subghz/receiver.h,, Header,+,lib/subghz/registry.h,, @@ -270,6 +221,56 @@ Header,+,lib/toolbox/tar/tar_archive.h,, Header,+,lib/toolbox/value_index.h,, Header,+,lib/toolbox/version.h,, Header,+,lib/xtreme/xtreme.h,, +Header,+,targets/f7/furi_hal/furi_hal_bus.h,, +Header,+,targets/f7/furi_hal/furi_hal_clock.h,, +Header,+,targets/f7/furi_hal/furi_hal_console.h,, +Header,+,targets/f7/furi_hal/furi_hal_dma.h,, +Header,+,targets/f7/furi_hal/furi_hal_flash.h,, +Header,+,targets/f7/furi_hal/furi_hal_gpio.h,, +Header,+,targets/f7/furi_hal/furi_hal_i2c_config.h,, +Header,+,targets/f7/furi_hal/furi_hal_i2c_types.h,, +Header,+,targets/f7/furi_hal/furi_hal_ibutton.h,, +Header,+,targets/f7/furi_hal/furi_hal_idle_timer.h,, +Header,+,targets/f7/furi_hal/furi_hal_interrupt.h,, +Header,+,targets/f7/furi_hal/furi_hal_os.h,, +Header,+,targets/f7/furi_hal/furi_hal_pwm.h,, +Header,+,targets/f7/furi_hal/furi_hal_resources.h,, +Header,+,targets/f7/furi_hal/furi_hal_rfid.h,, +Header,+,targets/f7/furi_hal/furi_hal_spi_config.h,, +Header,+,targets/f7/furi_hal/furi_hal_spi_types.h,, +Header,+,targets/f7/furi_hal/furi_hal_subghz.h,, +Header,+,targets/f7/furi_hal/furi_hal_target_hw.h,, +Header,+,targets/f7/furi_hal/furi_hal_uart.h,, +Header,+,targets/f7/furi_hal/furi_hal_usb_cdc.h,, +Header,+,targets/f7/platform_specific/intrinsic_export.h,, +Header,+,targets/f7/platform_specific/math_wrapper.h,, +Header,+,targets/furi_hal_include/furi_hal.h,, +Header,+,targets/furi_hal_include/furi_hal_bt.h,, +Header,+,targets/furi_hal_include/furi_hal_bt_hid.h,, +Header,+,targets/furi_hal_include/furi_hal_bt_serial.h,, +Header,+,targets/furi_hal_include/furi_hal_cortex.h,, +Header,+,targets/furi_hal_include/furi_hal_crypto.h,, +Header,+,targets/furi_hal_include/furi_hal_debug.h,, +Header,+,targets/furi_hal_include/furi_hal_i2c.h,, +Header,+,targets/furi_hal_include/furi_hal_info.h,, +Header,+,targets/furi_hal_include/furi_hal_infrared.h,, +Header,+,targets/furi_hal_include/furi_hal_light.h,, +Header,+,targets/furi_hal_include/furi_hal_memory.h,, +Header,+,targets/furi_hal_include/furi_hal_mpu.h,, +Header,+,targets/furi_hal_include/furi_hal_nfc.h,, +Header,+,targets/furi_hal_include/furi_hal_power.h,, +Header,+,targets/furi_hal_include/furi_hal_random.h,, +Header,+,targets/furi_hal_include/furi_hal_region.h,, +Header,+,targets/furi_hal_include/furi_hal_rtc.h,, +Header,+,targets/furi_hal_include/furi_hal_sd.h,, +Header,+,targets/furi_hal_include/furi_hal_speaker.h,, +Header,+,targets/furi_hal_include/furi_hal_spi.h,, +Header,+,targets/furi_hal_include/furi_hal_usb.h,, +Header,+,targets/furi_hal_include/furi_hal_usb_ccid.h,, +Header,+,targets/furi_hal_include/furi_hal_usb_hid.h,, +Header,+,targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, +Header,+,targets/furi_hal_include/furi_hal_version.h,, +Header,+,targets/furi_hal_include/furi_hal_vibro.h,, Function,-,LL_ADC_CommonDeInit,ErrorStatus,ADC_Common_TypeDef* Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, const LL_ADC_CommonInitTypeDef*" Function,-,LL_ADC_CommonStructInit,void,LL_ADC_CommonInitTypeDef* @@ -386,10 +387,10 @@ Function,-,__eprintf,void,"const char*, const char*, unsigned int, const char*" Function,+,__errno,int*, Function,-,__fpclassifyd,int,double Function,-,__fpclassifyf,int,float -Function,+,__furi_crash,void, +Function,+,__furi_crash_implementation,void, Function,+,__furi_critical_enter,__FuriCriticalInfo, Function,+,__furi_critical_exit,void,__FuriCriticalInfo -Function,+,__furi_halt,void, +Function,+,__furi_halt_implementation,void, Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*" Function,-,__getline,ssize_t,"char**, size_t*, FILE*" Function,-,__isinfd,int,double @@ -501,7 +502,6 @@ Function,-,_perror_r,void,"_reent*, const char*" Function,-,_printf_r,int,"_reent*, const char*, ..." Function,-,_putc_r,int,"_reent*, int, FILE*" Function,-,_putc_unlocked_r,int,"_reent*, int, FILE*" -Function,-,_putchar,void,char Function,-,_putchar_r,int,"_reent*, int" Function,-,_putchar_unlocked_r,int,"_reent*, int" Function,-,_putenv_r,int,"_reent*, char*" @@ -883,8 +883,6 @@ Function,-,dprintf,int,"int, const char*, ..." Function,-,drand48,double, Function,-,drem,double,"double, double" Function,-,dremf,float,"float, float" -Function,-,eTaskConfirmSleepModeStatus,eSleepModeStatus, -Function,-,eTaskGetState,eTaskState,TaskHandle_t Function,+,elements_bold_rounded_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,elements_bubble,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,elements_bubble_str,void,"Canvas*, uint8_t, uint8_t, const char*, Align, Align" @@ -1614,6 +1612,7 @@ Function,+,furi_hal_vibro_on,void,_Bool Function,-,furi_init,void, Function,+,furi_kernel_get_tick_frequency,uint32_t, Function,+,furi_kernel_is_irq_or_masked,_Bool, +Function,+,furi_kernel_is_running,_Bool, Function,+,furi_kernel_lock,int32_t, Function,+,furi_kernel_restore_lock,int32_t,int32_t Function,+,furi_kernel_unlock,int32_t, @@ -1724,7 +1723,6 @@ Function,+,furi_string_utf8_push,void,"FuriString*, FuriStringUnicodeValue" Function,+,furi_string_vprintf,int,"FuriString*, const char[], va_list" Function,+,furi_thread_alloc,FuriThread*, Function,+,furi_thread_alloc_ex,FuriThread*,"const char*, uint32_t, FuriThreadCallback, void*" -Function,+,furi_thread_catch,void, Function,-,furi_thread_disable_heap_trace,void,FuriThread* Function,+,furi_thread_enable_heap_trace,void,FuriThread* Function,+,furi_thread_enumerate,uint32_t,"FuriThreadId*, uint32_t" @@ -1766,8 +1764,11 @@ Function,+,furi_thread_yield,void, Function,+,furi_timer_alloc,FuriTimer*,"FuriTimerCallback, FuriTimerType, void*" Function,+,furi_timer_free,void,FuriTimer* Function,-,furi_timer_get_current_name,const char*, +Function,+,furi_timer_get_expire_time,uint32_t,FuriTimer* Function,+,furi_timer_is_running,uint32_t,FuriTimer* Function,+,furi_timer_pending_callback,void,"FuriTimerPendigCallback, void*, uint32_t" +Function,+,furi_timer_restart,FuriStatus,"FuriTimer*, uint32_t" +Function,+,furi_timer_set_thread_priority,void,FuriTimerThreadPriority Function,+,furi_timer_start,FuriStatus,"FuriTimer*, uint32_t" Function,+,furi_timer_stop,FuriStatus,FuriTimer* Function,-,fwrite,size_t,"const void*, size_t, size_t, FILE*" @@ -2467,8 +2468,6 @@ Function,+,pb_read,_Bool,"pb_istream_t*, pb_byte_t*, size_t" Function,+,pb_release,void,"const pb_msgdesc_t*, void*" Function,+,pb_skip_field,_Bool,"pb_istream_t*, pb_wire_type_t" Function,+,pb_write,_Bool,"pb_ostream_t*, const pb_byte_t*, size_t" -Function,-,pcTaskGetName,char*,TaskHandle_t -Function,-,pcTimerGetName,const char*,TimerHandle_t Function,-,pclose,int,FILE* Function,-,perror,void,const char* Function,+,plugin_manager_alloc,PluginManager*,"const char*, uint32_t, const ElfApiInterface*" @@ -2547,11 +2546,6 @@ Function,-,putchar_unlocked,int,int Function,-,putenv,int,char* Function,-,puts,int,const char* Function,-,putw,int,"int, FILE*" -Function,-,pvPortMalloc,void*,size_t -Function,-,pvTaskGetThreadLocalStoragePointer,void*,"TaskHandle_t, BaseType_t" -Function,-,pvTaskIncrementMutexHeldCount,TaskHandle_t, -Function,-,pvTimerGetTimerID,void*,const TimerHandle_t -Function,-,pxPortInitialiseStack,StackType_t*,"StackType_t*, TaskFunction_t, void*" Function,-,qsort,void,"void*, size_t, size_t, __compar_fn_t" Function,-,qsort_r,void,"void*, size_t, size_t, int (*)(const void*, const void*, void*), void*" Function,-,quick_exit,void,int @@ -2597,7 +2591,7 @@ Function,-,round,double,double Function,+,roundf,float,float Function,-,roundl,long double,long double Function,+,rpc_session_close,void,RpcSession* -Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, TickType_t" +Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, uint32_t" Function,+,rpc_session_get_available_size,size_t,RpcSession* Function,+,rpc_session_get_owner,RpcOwner,RpcSession* Function,+,rpc_session_open,RpcSession*,"Rpc*, RpcOwner" @@ -2606,14 +2600,12 @@ Function,+,rpc_session_set_close_callback,void,"RpcSession*, RpcSessionClosedCal Function,+,rpc_session_set_context,void,"RpcSession*, void*" Function,+,rpc_session_set_send_bytes_callback,void,"RpcSession*, RpcSendBytesCallback" Function,+,rpc_session_set_terminated_callback,void,"RpcSession*, RpcSessionTerminatedCallback" -Function,+,rpc_system_app_confirm,void,"RpcAppSystem*, RpcAppSystemEvent, _Bool" +Function,+,rpc_system_app_confirm,void,"RpcAppSystem*, _Bool" Function,+,rpc_system_app_error_reset,void,RpcAppSystem* Function,+,rpc_system_app_exchange_data,void,"RpcAppSystem*, const uint8_t*, size_t" -Function,+,rpc_system_app_get_data,const char*,RpcAppSystem* Function,+,rpc_system_app_send_exited,void,RpcAppSystem* Function,+,rpc_system_app_send_started,void,RpcAppSystem* Function,+,rpc_system_app_set_callback,void,"RpcAppSystem*, RpcAppSystemCallback, void*" -Function,+,rpc_system_app_set_data_exchange_callback,void,"RpcAppSystem*, RpcAppSystemDataExchangeCallback, void*" Function,+,rpc_system_app_set_error_code,void,"RpcAppSystem*, uint32_t" Function,+,rpc_system_app_set_error_text,void,"RpcAppSystem*, const char*" Function,-,rpmatch,int,const char* @@ -3150,67 +3142,10 @@ Function,-,uECC_sign_deterministic,int,"const uint8_t*, const uint8_t*, unsigned Function,-,uECC_valid_public_key,int,"const uint8_t*, uECC_Curve" Function,-,uECC_verify,int,"const uint8_t*, const uint8_t*, unsigned, const uint8_t*, uECC_Curve" Function,+,uint8_to_hex_chars,void,"const uint8_t*, uint8_t*, int" -Function,-,ulTaskGenericNotifyTake,uint32_t,"UBaseType_t, BaseType_t, TickType_t" -Function,-,ulTaskGenericNotifyValueClear,uint32_t,"TaskHandle_t, UBaseType_t, uint32_t" -Function,-,ulTaskGetIdleRunTimeCounter,uint32_t, -Function,-,ulTaskGetIdleRunTimePercent,uint32_t, Function,-,ungetc,int,"int, FILE*" Function,-,unsetenv,int,const char* Function,-,usbd_poll,void,usbd_device* Function,-,utoa,char*,"unsigned, char*, int" -Function,-,uxListRemove,UBaseType_t,ListItem_t* -Function,-,uxTaskGetNumberOfTasks,UBaseType_t, -Function,-,uxTaskGetStackHighWaterMark,UBaseType_t,TaskHandle_t -Function,-,uxTaskGetStackHighWaterMark2,uint16_t,TaskHandle_t -Function,-,uxTaskGetSystemState,UBaseType_t,"TaskStatus_t*, const UBaseType_t, uint32_t*" -Function,-,uxTaskGetTaskNumber,UBaseType_t,TaskHandle_t -Function,-,uxTaskPriorityGet,UBaseType_t,const TaskHandle_t -Function,-,uxTaskPriorityGetFromISR,UBaseType_t,const TaskHandle_t -Function,-,uxTaskResetEventItemValue,TickType_t, -Function,-,uxTimerGetReloadMode,UBaseType_t,TimerHandle_t -Function,-,uxTimerGetTimerNumber,UBaseType_t,TimerHandle_t -Function,-,vApplicationGetIdleTaskMemory,void,"StaticTask_t**, StackType_t**, uint32_t*" -Function,-,vApplicationGetTimerTaskMemory,void,"StaticTask_t**, StackType_t**, uint32_t*" -Function,-,vListInitialise,void,List_t* -Function,-,vListInitialiseItem,void,ListItem_t* -Function,-,vListInsert,void,"List_t*, ListItem_t*" -Function,-,vListInsertEnd,void,"List_t*, ListItem_t*" -Function,-,vPortDefineHeapRegions,void,const HeapRegion_t* -Function,-,vPortEndScheduler,void, -Function,+,vPortEnterCritical,void, -Function,+,vPortExitCritical,void, -Function,-,vPortFree,void,void* -Function,-,vPortGetHeapStats,void,HeapStats_t* -Function,-,vPortInitialiseBlocks,void, -Function,-,vPortSuppressTicksAndSleep,void,TickType_t -Function,-,vTaskAllocateMPURegions,void,"TaskHandle_t, const MemoryRegion_t*" -Function,-,vTaskDelay,void,const TickType_t -Function,-,vTaskDelete,void,TaskHandle_t -Function,-,vTaskEndScheduler,void, -Function,-,vTaskGenericNotifyGiveFromISR,void,"TaskHandle_t, UBaseType_t, BaseType_t*" -Function,-,vTaskGetInfo,void,"TaskHandle_t, TaskStatus_t*, BaseType_t, eTaskState" -Function,-,vTaskGetRunTimeStats,void,char* -Function,-,vTaskInternalSetTimeOutState,void,TimeOut_t* -Function,-,vTaskList,void,char* -Function,-,vTaskMissedYield,void, -Function,-,vTaskPlaceOnEventList,void,"List_t*, const TickType_t" -Function,-,vTaskPlaceOnEventListRestricted,void,"List_t*, TickType_t, const BaseType_t" -Function,-,vTaskPlaceOnUnorderedEventList,void,"List_t*, const TickType_t, const TickType_t" -Function,-,vTaskPriorityDisinheritAfterTimeout,void,"const TaskHandle_t, UBaseType_t" -Function,+,vTaskPrioritySet,void,"TaskHandle_t, UBaseType_t" -Function,-,vTaskRemoveFromUnorderedEventList,void,"ListItem_t*, const TickType_t" -Function,-,vTaskResume,void,TaskHandle_t -Function,-,vTaskSetTaskNumber,void,"TaskHandle_t, const UBaseType_t" -Function,-,vTaskSetThreadLocalStoragePointer,void,"TaskHandle_t, BaseType_t, void*" -Function,-,vTaskSetTimeOutState,void,TimeOut_t* -Function,-,vTaskStartScheduler,void, -Function,-,vTaskStepTick,void,const TickType_t -Function,-,vTaskSuspend,void,TaskHandle_t -Function,-,vTaskSuspendAll,void, -Function,-,vTaskSwitchContext,void, -Function,-,vTimerSetReloadMode,void,"TimerHandle_t, const UBaseType_t" -Function,-,vTimerSetTimerID,void,"TimerHandle_t, void*" -Function,-,vTimerSetTimerNumber,void,"TimerHandle_t, UBaseType_t" Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*" Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*" Function,+,validator_is_file_free,void,ValidatorIsFile* @@ -3330,42 +3265,6 @@ Function,+,widget_alloc,Widget*, Function,+,widget_free,void,Widget* Function,+,widget_get_view,View*,Widget* Function,+,widget_reset,void,Widget* -Function,-,xPortGetFreeHeapSize,size_t, -Function,-,xPortGetMinimumEverFreeHeapSize,size_t, -Function,-,xPortStartScheduler,BaseType_t, -Function,-,xTaskAbortDelay,BaseType_t,TaskHandle_t -Function,-,xTaskCallApplicationTaskHook,BaseType_t,"TaskHandle_t, void*" -Function,-,xTaskCatchUpTicks,BaseType_t,TickType_t -Function,-,xTaskCheckForTimeOut,BaseType_t,"TimeOut_t*, TickType_t*" -Function,-,xTaskCreate,BaseType_t,"TaskFunction_t, const char*, const uint16_t, void*, UBaseType_t, TaskHandle_t*" -Function,-,xTaskCreateStatic,TaskHandle_t,"TaskFunction_t, const char*, const uint32_t, void*, UBaseType_t, StackType_t*, StaticTask_t*" -Function,-,xTaskDelayUntil,BaseType_t,"TickType_t*, const TickType_t" -Function,-,xTaskGenericNotify,BaseType_t,"TaskHandle_t, UBaseType_t, uint32_t, eNotifyAction, uint32_t*" -Function,-,xTaskGenericNotifyFromISR,BaseType_t,"TaskHandle_t, UBaseType_t, uint32_t, eNotifyAction, uint32_t*, BaseType_t*" -Function,-,xTaskGenericNotifyStateClear,BaseType_t,"TaskHandle_t, UBaseType_t" -Function,-,xTaskGenericNotifyWait,BaseType_t,"UBaseType_t, uint32_t, uint32_t, uint32_t*, TickType_t" -Function,-,xTaskGetCurrentTaskHandle,TaskHandle_t, -Function,+,xTaskGetHandle,TaskHandle_t,const char* -Function,-,xTaskGetIdleTaskHandle,TaskHandle_t, -Function,+,xTaskGetSchedulerState,BaseType_t, -Function,+,xTaskGetTickCount,TickType_t, -Function,-,xTaskGetTickCountFromISR,TickType_t, -Function,-,xTaskIncrementTick,BaseType_t, -Function,-,xTaskPriorityDisinherit,BaseType_t,const TaskHandle_t -Function,-,xTaskPriorityInherit,BaseType_t,const TaskHandle_t -Function,-,xTaskRemoveFromEventList,BaseType_t,const List_t* -Function,-,xTaskResumeAll,BaseType_t, -Function,-,xTaskResumeFromISR,BaseType_t,TaskHandle_t -Function,-,xTimerCreate,TimerHandle_t,"const char*, const TickType_t, const UBaseType_t, void*, TimerCallbackFunction_t" -Function,-,xTimerCreateStatic,TimerHandle_t,"const char*, const TickType_t, const UBaseType_t, void*, TimerCallbackFunction_t, StaticTimer_t*" -Function,-,xTimerCreateTimerTask,BaseType_t, -Function,-,xTimerGenericCommand,BaseType_t,"TimerHandle_t, const BaseType_t, const TickType_t, BaseType_t*, const TickType_t" -Function,-,xTimerGetExpiryTime,TickType_t,TimerHandle_t -Function,-,xTimerGetPeriod,TickType_t,TimerHandle_t -Function,-,xTimerGetTimerDaemonTaskHandle,TaskHandle_t, -Function,-,xTimerIsTimerActive,BaseType_t,TimerHandle_t -Function,-,xTimerPendFunctionCall,BaseType_t,"PendedFunction_t, void*, uint32_t, TickType_t" -Function,-,xTimerPendFunctionCallFromISR,BaseType_t,"PendedFunction_t, void*, uint32_t, BaseType_t*" Function,-,y0,double,double Function,-,y0f,float,float Function,-,y1,double,double diff --git a/firmware/targets/f7/application_ext.ld b/targets/f7/application_ext.ld similarity index 100% rename from firmware/targets/f7/application_ext.ld rename to targets/f7/application_ext.ld diff --git a/firmware/targets/f7/ble_glue/app_common.h b/targets/f7/ble_glue/app_common.h similarity index 100% rename from firmware/targets/f7/ble_glue/app_common.h rename to targets/f7/ble_glue/app_common.h diff --git a/firmware/targets/f7/ble_glue/app_conf.h b/targets/f7/ble_glue/app_conf.h similarity index 100% rename from firmware/targets/f7/ble_glue/app_conf.h rename to targets/f7/ble_glue/app_conf.h diff --git a/firmware/targets/f7/ble_glue/app_debug.c b/targets/f7/ble_glue/app_debug.c similarity index 100% rename from firmware/targets/f7/ble_glue/app_debug.c rename to targets/f7/ble_glue/app_debug.c diff --git a/firmware/targets/f7/ble_glue/app_debug.h b/targets/f7/ble_glue/app_debug.h similarity index 100% rename from firmware/targets/f7/ble_glue/app_debug.h rename to targets/f7/ble_glue/app_debug.h diff --git a/firmware/targets/f7/ble_glue/ble_app.c b/targets/f7/ble_glue/ble_app.c similarity index 100% rename from firmware/targets/f7/ble_glue/ble_app.c rename to targets/f7/ble_glue/ble_app.c diff --git a/firmware/targets/f7/ble_glue/ble_app.h b/targets/f7/ble_glue/ble_app.h similarity index 100% rename from firmware/targets/f7/ble_glue/ble_app.h rename to targets/f7/ble_glue/ble_app.h diff --git a/firmware/targets/f7/ble_glue/ble_conf.h b/targets/f7/ble_glue/ble_conf.h similarity index 100% rename from firmware/targets/f7/ble_glue/ble_conf.h rename to targets/f7/ble_glue/ble_conf.h diff --git a/firmware/targets/f7/ble_glue/ble_const.h b/targets/f7/ble_glue/ble_const.h similarity index 100% rename from firmware/targets/f7/ble_glue/ble_const.h rename to targets/f7/ble_glue/ble_const.h diff --git a/firmware/targets/f7/ble_glue/ble_dbg_conf.h b/targets/f7/ble_glue/ble_dbg_conf.h similarity index 100% rename from firmware/targets/f7/ble_glue/ble_dbg_conf.h rename to targets/f7/ble_glue/ble_dbg_conf.h diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/targets/f7/ble_glue/ble_glue.c similarity index 100% rename from firmware/targets/f7/ble_glue/ble_glue.c rename to targets/f7/ble_glue/ble_glue.c diff --git a/firmware/targets/f7/ble_glue/ble_glue.h b/targets/f7/ble_glue/ble_glue.h similarity index 100% rename from firmware/targets/f7/ble_glue/ble_glue.h rename to targets/f7/ble_glue/ble_glue.h diff --git a/firmware/targets/f7/ble_glue/compiler.h b/targets/f7/ble_glue/compiler.h similarity index 100% rename from firmware/targets/f7/ble_glue/compiler.h rename to targets/f7/ble_glue/compiler.h diff --git a/firmware/targets/f7/ble_glue/gap.c b/targets/f7/ble_glue/gap.c similarity index 99% rename from firmware/targets/f7/ble_glue/gap.c rename to targets/f7/ble_glue/gap.c index 27ab1ee40..d3dfe7b73 100644 --- a/firmware/targets/f7/ble_glue/gap.c +++ b/targets/f7/ble_glue/gap.c @@ -586,8 +586,6 @@ void gap_thread_stop() { // Free resources furi_mutex_free(gap->state_mutex); furi_message_queue_free(gap->command_queue); - furi_timer_stop(gap->advertise_timer); - while(xTimerIsTimerActive(gap->advertise_timer) == pdTRUE) furi_delay_tick(1); furi_timer_free(gap->advertise_timer); free(gap); gap = NULL; diff --git a/firmware/targets/f7/ble_glue/gap.h b/targets/f7/ble_glue/gap.h similarity index 100% rename from firmware/targets/f7/ble_glue/gap.h rename to targets/f7/ble_glue/gap.h diff --git a/firmware/targets/f7/ble_glue/hsem_map.h b/targets/f7/ble_glue/hsem_map.h similarity index 100% rename from firmware/targets/f7/ble_glue/hsem_map.h rename to targets/f7/ble_glue/hsem_map.h diff --git a/firmware/targets/f7/ble_glue/hw_ipcc.c b/targets/f7/ble_glue/hw_ipcc.c similarity index 100% rename from firmware/targets/f7/ble_glue/hw_ipcc.c rename to targets/f7/ble_glue/hw_ipcc.c diff --git a/firmware/targets/f7/ble_glue/osal.h b/targets/f7/ble_glue/osal.h similarity index 100% rename from firmware/targets/f7/ble_glue/osal.h rename to targets/f7/ble_glue/osal.h diff --git a/firmware/targets/f7/ble_glue/services/battery_service.c b/targets/f7/ble_glue/services/battery_service.c similarity index 100% rename from firmware/targets/f7/ble_glue/services/battery_service.c rename to targets/f7/ble_glue/services/battery_service.c diff --git a/firmware/targets/f7/ble_glue/services/battery_service.h b/targets/f7/ble_glue/services/battery_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/services/battery_service.h rename to targets/f7/ble_glue/services/battery_service.h diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.c b/targets/f7/ble_glue/services/dev_info_service.c similarity index 100% rename from firmware/targets/f7/ble_glue/services/dev_info_service.c rename to targets/f7/ble_glue/services/dev_info_service.c diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.h b/targets/f7/ble_glue/services/dev_info_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/services/dev_info_service.h rename to targets/f7/ble_glue/services/dev_info_service.h diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service_uuid.inc b/targets/f7/ble_glue/services/dev_info_service_uuid.inc similarity index 100% rename from firmware/targets/f7/ble_glue/services/dev_info_service_uuid.inc rename to targets/f7/ble_glue/services/dev_info_service_uuid.inc diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/targets/f7/ble_glue/services/gatt_char.c similarity index 100% rename from firmware/targets/f7/ble_glue/services/gatt_char.c rename to targets/f7/ble_glue/services/gatt_char.c diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.h b/targets/f7/ble_glue/services/gatt_char.h similarity index 100% rename from firmware/targets/f7/ble_glue/services/gatt_char.h rename to targets/f7/ble_glue/services/gatt_char.h diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/targets/f7/ble_glue/services/hid_service.c similarity index 100% rename from firmware/targets/f7/ble_glue/services/hid_service.c rename to targets/f7/ble_glue/services/hid_service.c diff --git a/firmware/targets/f7/ble_glue/services/hid_service.h b/targets/f7/ble_glue/services/hid_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/services/hid_service.h rename to targets/f7/ble_glue/services/hid_service.h diff --git a/firmware/targets/f7/ble_glue/services/serial_service.c b/targets/f7/ble_glue/services/serial_service.c similarity index 100% rename from firmware/targets/f7/ble_glue/services/serial_service.c rename to targets/f7/ble_glue/services/serial_service.c diff --git a/firmware/targets/f7/ble_glue/services/serial_service.h b/targets/f7/ble_glue/services/serial_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/services/serial_service.h rename to targets/f7/ble_glue/services/serial_service.h diff --git a/firmware/targets/f7/ble_glue/services/serial_service_uuid.inc b/targets/f7/ble_glue/services/serial_service_uuid.inc similarity index 100% rename from firmware/targets/f7/ble_glue/services/serial_service_uuid.inc rename to targets/f7/ble_glue/services/serial_service_uuid.inc diff --git a/firmware/targets/f7/ble_glue/tl_dbg_conf.h b/targets/f7/ble_glue/tl_dbg_conf.h similarity index 100% rename from firmware/targets/f7/ble_glue/tl_dbg_conf.h rename to targets/f7/ble_glue/tl_dbg_conf.h diff --git a/firmware/targets/f7/fatfs/fatfs.c b/targets/f7/fatfs/fatfs.c similarity index 100% rename from firmware/targets/f7/fatfs/fatfs.c rename to targets/f7/fatfs/fatfs.c diff --git a/firmware/targets/f7/fatfs/fatfs.h b/targets/f7/fatfs/fatfs.h similarity index 100% rename from firmware/targets/f7/fatfs/fatfs.h rename to targets/f7/fatfs/fatfs.h diff --git a/firmware/targets/f7/fatfs/ffconf.h b/targets/f7/fatfs/ffconf.h similarity index 100% rename from firmware/targets/f7/fatfs/ffconf.h rename to targets/f7/fatfs/ffconf.h diff --git a/firmware/targets/f7/fatfs/sector_cache.c b/targets/f7/fatfs/sector_cache.c similarity index 100% rename from firmware/targets/f7/fatfs/sector_cache.c rename to targets/f7/fatfs/sector_cache.c diff --git a/firmware/targets/f7/fatfs/sector_cache.h b/targets/f7/fatfs/sector_cache.h similarity index 100% rename from firmware/targets/f7/fatfs/sector_cache.h rename to targets/f7/fatfs/sector_cache.h diff --git a/firmware/targets/f7/fatfs/user_diskio.c b/targets/f7/fatfs/user_diskio.c similarity index 100% rename from firmware/targets/f7/fatfs/user_diskio.c rename to targets/f7/fatfs/user_diskio.c diff --git a/firmware/targets/f7/fatfs/user_diskio.h b/targets/f7/fatfs/user_diskio.h similarity index 100% rename from firmware/targets/f7/fatfs/user_diskio.h rename to targets/f7/fatfs/user_diskio.h diff --git a/firmware/targets/f7/furi_hal/furi_hal.c b/targets/f7/furi_hal/furi_hal.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal.c rename to targets/f7/furi_hal/furi_hal.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/targets/f7/furi_hal/furi_hal_bt.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_bt.c rename to targets/f7/furi_hal/furi_hal_bt.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c b/targets/f7/furi_hal/furi_hal_bt_hid.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_bt_hid.c rename to targets/f7/furi_hal/furi_hal_bt_hid.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c b/targets/f7/furi_hal/furi_hal_bt_serial.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_bt_serial.c rename to targets/f7/furi_hal/furi_hal_bt_serial.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_bus.c b/targets/f7/furi_hal/furi_hal_bus.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_bus.c rename to targets/f7/furi_hal/furi_hal_bus.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_bus.h b/targets/f7/furi_hal/furi_hal_bus.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_bus.h rename to targets/f7/furi_hal/furi_hal_bus.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.c b/targets/f7/furi_hal/furi_hal_clock.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_clock.c rename to targets/f7/furi_hal/furi_hal_clock.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.h b/targets/f7/furi_hal/furi_hal_clock.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_clock.h rename to targets/f7/furi_hal/furi_hal_clock.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_console.c b/targets/f7/furi_hal/furi_hal_console.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_console.c rename to targets/f7/furi_hal/furi_hal_console.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_console.h b/targets/f7/furi_hal/furi_hal_console.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_console.h rename to targets/f7/furi_hal/furi_hal_console.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_cortex.c b/targets/f7/furi_hal/furi_hal_cortex.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_cortex.c rename to targets/f7/furi_hal/furi_hal_cortex.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_crypto.c b/targets/f7/furi_hal/furi_hal_crypto.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_crypto.c rename to targets/f7/furi_hal/furi_hal_crypto.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_debug.c b/targets/f7/furi_hal/furi_hal_debug.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_debug.c rename to targets/f7/furi_hal/furi_hal_debug.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_dma.c b/targets/f7/furi_hal/furi_hal_dma.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_dma.c rename to targets/f7/furi_hal/furi_hal_dma.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_dma.h b/targets/f7/furi_hal/furi_hal_dma.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_dma.h rename to targets/f7/furi_hal/furi_hal_dma.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.c b/targets/f7/furi_hal/furi_hal_flash.c similarity index 99% rename from firmware/targets/f7/furi_hal/furi_hal_flash.c rename to targets/f7/furi_hal/furi_hal_flash.c index bc65b29eb..284d48bf5 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_flash.c +++ b/targets/f7/furi_hal/furi_hal_flash.c @@ -11,6 +11,9 @@ #include +#include +#include + #define TAG "FuriHalFlash" #define FURI_HAL_CRITICAL_MSG "Critical flash operation fail" diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.h b/targets/f7/furi_hal/furi_hal_flash.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_flash.h rename to targets/f7/furi_hal/furi_hal_flash.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_gpio.c b/targets/f7/furi_hal/furi_hal_gpio.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_gpio.c rename to targets/f7/furi_hal/furi_hal_gpio.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_gpio.h b/targets/f7/furi_hal/furi_hal_gpio.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_gpio.h rename to targets/f7/furi_hal/furi_hal_gpio.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_i2c.c b/targets/f7/furi_hal/furi_hal_i2c.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_i2c.c rename to targets/f7/furi_hal/furi_hal_i2c.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_i2c_config.c b/targets/f7/furi_hal/furi_hal_i2c_config.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_i2c_config.c rename to targets/f7/furi_hal/furi_hal_i2c_config.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_i2c_config.h b/targets/f7/furi_hal/furi_hal_i2c_config.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_i2c_config.h rename to targets/f7/furi_hal/furi_hal_i2c_config.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_i2c_types.h b/targets/f7/furi_hal/furi_hal_i2c_types.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_i2c_types.h rename to targets/f7/furi_hal/furi_hal_i2c_types.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_ibutton.c b/targets/f7/furi_hal/furi_hal_ibutton.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_ibutton.c rename to targets/f7/furi_hal/furi_hal_ibutton.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_ibutton.h b/targets/f7/furi_hal/furi_hal_ibutton.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_ibutton.h rename to targets/f7/furi_hal/furi_hal_ibutton.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_idle_timer.h b/targets/f7/furi_hal/furi_hal_idle_timer.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_idle_timer.h rename to targets/f7/furi_hal/furi_hal_idle_timer.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_info.c b/targets/f7/furi_hal/furi_hal_info.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_info.c rename to targets/f7/furi_hal/furi_hal_info.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_infrared.c b/targets/f7/furi_hal/furi_hal_infrared.c similarity index 99% rename from firmware/targets/f7/furi_hal/furi_hal_infrared.c rename to targets/f7/furi_hal/furi_hal_infrared.c index e76582dac..9c0d84c55 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_infrared.c +++ b/targets/f7/furi_hal/furi_hal_infrared.c @@ -128,7 +128,7 @@ static void furi_hal_infrared_tim_rx_isr() { if(infrared_tim_rx.capture_callback) infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 1, duration); } else { - furi_assert(0); + furi_crash(); } } @@ -144,7 +144,7 @@ static void furi_hal_infrared_tim_rx_isr() { if(infrared_tim_rx.capture_callback) infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 0, duration); } else { - furi_assert(0); + furi_crash(); } } } @@ -257,7 +257,7 @@ static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void) { } else if(buffer_adr == (uint32_t)infrared_tim_tx.buffer[1].data) { buf_num = 1; } else { - furi_assert(0); + furi_crash(); } return buf_num; } @@ -266,7 +266,7 @@ static void furi_hal_infrared_tx_dma_polarity_isr() { #if INFRARED_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1 if(LL_DMA_IsActiveFlag_TE1(INFRARED_DMA)) { LL_DMA_ClearFlag_TE1(INFRARED_DMA); - furi_crash(NULL); + furi_crash(); } if(LL_DMA_IsActiveFlag_TC1(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH1_DEF)) { LL_DMA_ClearFlag_TC1(INFRARED_DMA); @@ -288,7 +288,7 @@ static void furi_hal_infrared_tx_dma_isr() { #if INFRARED_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2 if(LL_DMA_IsActiveFlag_TE2(INFRARED_DMA)) { LL_DMA_ClearFlag_TE2(INFRARED_DMA); - furi_crash(NULL); + furi_crash(); } if(LL_DMA_IsActiveFlag_HT2(INFRARED_DMA) && LL_DMA_IsEnabledIT_HT(INFRARED_DMA_CH2_DEF)) { LL_DMA_ClearFlag_HT2(INFRARED_DMA); @@ -306,7 +306,7 @@ static void furi_hal_infrared_tx_dma_isr() { } else if(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) { /* fallthrough */ } else { - furi_crash(NULL); + furi_crash(); } } if(LL_DMA_IsActiveFlag_TC2(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH2_DEF)) { @@ -605,7 +605,7 @@ static void furi_hal_infrared_async_tx_free_resources(void) { void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) { if((duty_cycle > 1) || (duty_cycle <= 0) || (freq > INFRARED_MAX_FREQUENCY) || (freq < INFRARED_MIN_FREQUENCY) || (infrared_tim_tx.data_callback == NULL)) { - furi_crash(NULL); + furi_crash(); } furi_assert(furi_hal_infrared_state == InfraredStateIdle); diff --git a/firmware/targets/f7/furi_hal/furi_hal_interrupt.c b/targets/f7/furi_hal/furi_hal_interrupt.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_interrupt.c rename to targets/f7/furi_hal/furi_hal_interrupt.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_interrupt.h b/targets/f7/furi_hal/furi_hal_interrupt.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_interrupt.h rename to targets/f7/furi_hal/furi_hal_interrupt.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_light.c b/targets/f7/furi_hal/furi_hal_light.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_light.c rename to targets/f7/furi_hal/furi_hal_light.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_memory.c b/targets/f7/furi_hal/furi_hal_memory.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_memory.c rename to targets/f7/furi_hal/furi_hal_memory.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_mpu.c b/targets/f7/furi_hal/furi_hal_mpu.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_mpu.c rename to targets/f7/furi_hal/furi_hal_mpu.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/targets/f7/furi_hal/furi_hal_nfc.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc.c rename to targets/f7/furi_hal/furi_hal_nfc.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc_event.c b/targets/f7/furi_hal/furi_hal_nfc_event.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc_event.c rename to targets/f7/furi_hal/furi_hal_nfc_event.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc_felica.c b/targets/f7/furi_hal/furi_hal_nfc_felica.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc_felica.c rename to targets/f7/furi_hal/furi_hal_nfc_felica.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc_i.h b/targets/f7/furi_hal/furi_hal_nfc_i.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc_i.h rename to targets/f7/furi_hal/furi_hal_nfc_i.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc_irq.c b/targets/f7/furi_hal/furi_hal_nfc_irq.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc_irq.c rename to targets/f7/furi_hal/furi_hal_nfc_irq.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc_iso14443a.c b/targets/f7/furi_hal/furi_hal_nfc_iso14443a.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc_iso14443a.c rename to targets/f7/furi_hal/furi_hal_nfc_iso14443a.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc_iso14443b.c b/targets/f7/furi_hal/furi_hal_nfc_iso14443b.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc_iso14443b.c rename to targets/f7/furi_hal/furi_hal_nfc_iso14443b.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc_iso15693.c b/targets/f7/furi_hal/furi_hal_nfc_iso15693.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc_iso15693.c rename to targets/f7/furi_hal/furi_hal_nfc_iso15693.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc_tech_i.h b/targets/f7/furi_hal/furi_hal_nfc_tech_i.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc_tech_i.h rename to targets/f7/furi_hal/furi_hal_nfc_tech_i.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc_timer.c b/targets/f7/furi_hal/furi_hal_nfc_timer.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_nfc_timer.c rename to targets/f7/furi_hal/furi_hal_nfc_timer.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_os.c b/targets/f7/furi_hal/furi_hal_os.c similarity index 99% rename from firmware/targets/f7/furi_hal/furi_hal_os.c rename to targets/f7/furi_hal/furi_hal_os.c index 046cf79dc..ea835b95f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_os.c +++ b/targets/f7/furi_hal/furi_hal_os.c @@ -10,6 +10,9 @@ #include +#include +#include + #define TAG "FuriHalOs" #define FURI_HAL_IDLE_TIMER_CLK_HZ 32768 diff --git a/firmware/targets/f7/furi_hal/furi_hal_os.h b/targets/f7/furi_hal/furi_hal_os.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_os.h rename to targets/f7/furi_hal/furi_hal_os.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/targets/f7/furi_hal/furi_hal_power.c similarity index 99% rename from firmware/targets/f7/furi_hal/furi_hal_power.c rename to targets/f7/furi_hal/furi_hal_power.c index 0eb93e664..119dee81f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/targets/f7/furi_hal/furi_hal_power.c @@ -459,10 +459,10 @@ void furi_hal_power_disable_external_3_3v() { } void furi_hal_power_suppress_charge_enter() { - vTaskSuspendAll(); + FURI_CRITICAL_ENTER(); bool disable_charging = furi_hal_power.suppress_charge == 0; furi_hal_power.suppress_charge++; - xTaskResumeAll(); + FURI_CRITICAL_EXIT(); if(disable_charging) { furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); @@ -472,10 +472,10 @@ void furi_hal_power_suppress_charge_enter() { } void furi_hal_power_suppress_charge_exit() { - vTaskSuspendAll(); + FURI_CRITICAL_ENTER(); furi_hal_power.suppress_charge--; bool enable_charging = furi_hal_power.suppress_charge == 0; - xTaskResumeAll(); + FURI_CRITICAL_EXIT(); if(enable_charging) { furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); diff --git a/firmware/targets/f7/furi_hal/furi_hal_power_config.c b/targets/f7/furi_hal/furi_hal_power_config.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_power_config.c rename to targets/f7/furi_hal/furi_hal_power_config.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_pwm.c b/targets/f7/furi_hal/furi_hal_pwm.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_pwm.c rename to targets/f7/furi_hal/furi_hal_pwm.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_pwm.h b/targets/f7/furi_hal/furi_hal_pwm.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_pwm.h rename to targets/f7/furi_hal/furi_hal_pwm.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_random.c b/targets/f7/furi_hal/furi_hal_random.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_random.c rename to targets/f7/furi_hal/furi_hal_random.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_region.c b/targets/f7/furi_hal/furi_hal_region.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_region.c rename to targets/f7/furi_hal/furi_hal_region.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.c b/targets/f7/furi_hal/furi_hal_resources.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_resources.c rename to targets/f7/furi_hal/furi_hal_resources.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.h b/targets/f7/furi_hal/furi_hal_resources.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_resources.h rename to targets/f7/furi_hal/furi_hal_resources.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_rfid.c b/targets/f7/furi_hal/furi_hal_rfid.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_rfid.c rename to targets/f7/furi_hal/furi_hal_rfid.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_rfid.h b/targets/f7/furi_hal/furi_hal_rfid.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_rfid.h rename to targets/f7/furi_hal/furi_hal_rfid.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_rtc.c b/targets/f7/furi_hal/furi_hal_rtc.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_rtc.c rename to targets/f7/furi_hal/furi_hal_rtc.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_sd.c b/targets/f7/furi_hal/furi_hal_sd.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_sd.c rename to targets/f7/furi_hal/furi_hal_sd.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_speaker.c b/targets/f7/furi_hal/furi_hal_speaker.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_speaker.c rename to targets/f7/furi_hal/furi_hal_speaker.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi.c b/targets/f7/furi_hal/furi_hal_spi.c similarity index 99% rename from firmware/targets/f7/furi_hal/furi_hal_spi.c rename to targets/f7/furi_hal/furi_hal_spi.c index a8884105a..98ca71af3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi.c +++ b/targets/f7/furi_hal/furi_hal_spi.c @@ -200,7 +200,7 @@ bool furi_hal_spi_bus_trx_dma( furi_assert(size > 0); // If scheduler is not running, use blocking mode - if(xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) { + if(furi_kernel_is_running()) { return furi_hal_spi_bus_trx(handle, tx_buffer, rx_buffer, size, timeout_ms); } @@ -221,7 +221,7 @@ bool furi_hal_spi_bus_trx_dma( dma_rx_req = LL_DMAMUX_REQ_SPI2_RX; dma_tx_req = LL_DMAMUX_REQ_SPI2_TX; } else { - furi_crash(NULL); + furi_crash(); } if(rx_buffer == NULL) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi_config.c b/targets/f7/furi_hal/furi_hal_spi_config.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_spi_config.c rename to targets/f7/furi_hal/furi_hal_spi_config.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi_config.h b/targets/f7/furi_hal/furi_hal_spi_config.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_spi_config.h rename to targets/f7/furi_hal/furi_hal_spi_config.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi_types.h b/targets/f7/furi_hal/furi_hal_spi_types.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_spi_types.h rename to targets/f7/furi_hal/furi_hal_spi_types.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/targets/f7/furi_hal/furi_hal_subghz.c similarity index 99% rename from firmware/targets/f7/furi_hal/furi_hal_subghz.c rename to targets/f7/furi_hal/furi_hal_subghz.c index c5326e3fd..899ead2d3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/targets/f7/furi_hal/furi_hal_subghz.c @@ -658,7 +658,7 @@ static void furi_hal_subghz_async_tx_timer_isr() { furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullDown, GpioSpeedLow); LL_TIM_DisableCounter(TIM2); } else { - furi_crash(NULL); + furi_crash(); } } } diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.h b/targets/f7/furi_hal/furi_hal_subghz.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_subghz.h rename to targets/f7/furi_hal/furi_hal_subghz.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz_i.h b/targets/f7/furi_hal/furi_hal_subghz_i.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_subghz_i.h rename to targets/f7/furi_hal/furi_hal_subghz_i.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_target_hw.h b/targets/f7/furi_hal/furi_hal_target_hw.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_target_hw.h rename to targets/f7/furi_hal/furi_hal_target_hw.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_uart.c b/targets/f7/furi_hal/furi_hal_uart.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_uart.c rename to targets/f7/furi_hal/furi_hal_uart.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_uart.h b/targets/f7/furi_hal/furi_hal_uart.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_uart.h rename to targets/f7/furi_hal/furi_hal_uart.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb.c b/targets/f7/furi_hal/furi_hal_usb.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_usb.c rename to targets/f7/furi_hal/furi_hal_usb.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_ccid.c b/targets/f7/furi_hal/furi_hal_usb_ccid.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_usb_ccid.c rename to targets/f7/furi_hal/furi_hal_usb_ccid.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c b/targets/f7/furi_hal/furi_hal_usb_cdc.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c rename to targets/f7/furi_hal/furi_hal_usb_cdc.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h b/targets/f7/furi_hal/furi_hal_usb_cdc.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h rename to targets/f7/furi_hal/furi_hal_usb_cdc.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c b/targets/f7/furi_hal/furi_hal_usb_hid.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_usb_hid.c rename to targets/f7/furi_hal/furi_hal_usb_hid.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_i.h b/targets/f7/furi_hal/furi_hal_usb_i.h similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_usb_i.h rename to targets/f7/furi_hal/furi_hal_usb_i.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c b/targets/f7/furi_hal/furi_hal_usb_u2f.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c rename to targets/f7/furi_hal/furi_hal_usb_u2f.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_version.c b/targets/f7/furi_hal/furi_hal_version.c similarity index 99% rename from firmware/targets/f7/furi_hal/furi_hal_version.c rename to targets/f7/furi_hal/furi_hal_version.c index ce8700fc8..2e3c3fa4c 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_version.c +++ b/targets/f7/furi_hal/furi_hal_version.c @@ -207,7 +207,7 @@ void furi_hal_version_init() { furi_hal_version_load_otp_v2(); break; default: - furi_crash(NULL); + furi_crash(); } furi_hal_rtc_set_register(FuriHalRtcRegisterVersion, (uint32_t)version_get()); diff --git a/firmware/targets/f7/furi_hal/furi_hal_version_device.c b/targets/f7/furi_hal/furi_hal_version_device.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_version_device.c rename to targets/f7/furi_hal/furi_hal_version_device.c diff --git a/firmware/targets/f7/furi_hal/furi_hal_vibro.c b/targets/f7/furi_hal/furi_hal_vibro.c similarity index 100% rename from firmware/targets/f7/furi_hal/furi_hal_vibro.c rename to targets/f7/furi_hal/furi_hal_vibro.c diff --git a/firmware/targets/f7/inc/FreeRTOSConfig.h b/targets/f7/inc/FreeRTOSConfig.h similarity index 99% rename from firmware/targets/f7/inc/FreeRTOSConfig.h rename to targets/f7/inc/FreeRTOSConfig.h index 024d43a6d..3bc57f8f3 100644 --- a/firmware/targets/f7/inc/FreeRTOSConfig.h +++ b/targets/f7/inc/FreeRTOSConfig.h @@ -3,13 +3,14 @@ #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) #include #pragma GCC diagnostic ignored "-Wredundant-decls" -extern uint32_t SystemCoreClock; #endif #ifndef CMSIS_device_header #define CMSIS_device_header "stm32wbxx.h" #endif /* CMSIS_device_header */ +#include CMSIS_device_header + #define configENABLE_FPU 1 #define configENABLE_MPU 0 diff --git a/firmware/targets/f7/inc/alt_boot.h b/targets/f7/inc/alt_boot.h similarity index 100% rename from firmware/targets/f7/inc/alt_boot.h rename to targets/f7/inc/alt_boot.h diff --git a/targets/f7/inc/furi_config.h b/targets/f7/inc/furi_config.h new file mode 100644 index 000000000..c935611ab --- /dev/null +++ b/targets/f7/inc/furi_config.h @@ -0,0 +1,3 @@ +#pragma once + +#define FURI_CONFIG_THREAD_MAX_PRIORITIES (32) \ No newline at end of file diff --git a/firmware/targets/f7/inc/stm32.h b/targets/f7/inc/stm32.h similarity index 100% rename from firmware/targets/f7/inc/stm32.h rename to targets/f7/inc/stm32.h diff --git a/firmware/targets/f7/inc/stm32_assert.h b/targets/f7/inc/stm32_assert.h similarity index 100% rename from firmware/targets/f7/inc/stm32_assert.h rename to targets/f7/inc/stm32_assert.h diff --git a/firmware/targets/f7/platform_specific/intrinsic_export.h b/targets/f7/platform_specific/intrinsic_export.h similarity index 100% rename from firmware/targets/f7/platform_specific/intrinsic_export.h rename to targets/f7/platform_specific/intrinsic_export.h diff --git a/firmware/targets/f7/platform_specific/math_wrapper.h b/targets/f7/platform_specific/math_wrapper.h similarity index 100% rename from firmware/targets/f7/platform_specific/math_wrapper.h rename to targets/f7/platform_specific/math_wrapper.h diff --git a/firmware/targets/f7/src/dfu.c b/targets/f7/src/dfu.c similarity index 100% rename from firmware/targets/f7/src/dfu.c rename to targets/f7/src/dfu.c diff --git a/firmware/targets/f7/src/main.c b/targets/f7/src/main.c similarity index 99% rename from firmware/targets/f7/src/main.c rename to targets/f7/src/main.c index 8e9fcf512..2a1ba64d1 100644 --- a/firmware/targets/f7/src/main.c +++ b/targets/f7/src/main.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #define TAG "Main" diff --git a/firmware/targets/f7/src/recovery.c b/targets/f7/src/recovery.c similarity index 100% rename from firmware/targets/f7/src/recovery.c rename to targets/f7/src/recovery.c diff --git a/firmware/targets/f7/src/system_stm32wbxx.c b/targets/f7/src/system_stm32wbxx.c similarity index 100% rename from firmware/targets/f7/src/system_stm32wbxx.c rename to targets/f7/src/system_stm32wbxx.c diff --git a/firmware/targets/f7/src/update.c b/targets/f7/src/update.c similarity index 100% rename from firmware/targets/f7/src/update.c rename to targets/f7/src/update.c diff --git a/firmware/targets/f7/startup_stm32wb55xx_cm4.s b/targets/f7/startup_stm32wb55xx_cm4.s similarity index 100% rename from firmware/targets/f7/startup_stm32wb55xx_cm4.s rename to targets/f7/startup_stm32wb55xx_cm4.s diff --git a/firmware/targets/f7/stm32wb55xx_flash.ld b/targets/f7/stm32wb55xx_flash.ld similarity index 100% rename from firmware/targets/f7/stm32wb55xx_flash.ld rename to targets/f7/stm32wb55xx_flash.ld diff --git a/firmware/targets/f7/stm32wb55xx_ram_fw.ld b/targets/f7/stm32wb55xx_ram_fw.ld similarity index 100% rename from firmware/targets/f7/stm32wb55xx_ram_fw.ld rename to targets/f7/stm32wb55xx_ram_fw.ld diff --git a/firmware/targets/f7/target.json b/targets/f7/target.json similarity index 100% rename from firmware/targets/f7/target.json rename to targets/f7/target.json diff --git a/firmware/targets/furi_hal_include/furi_hal.h b/targets/furi_hal_include/furi_hal.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal.h rename to targets/furi_hal_include/furi_hal.h diff --git a/firmware/targets/furi_hal_include/furi_hal_bt.h b/targets/furi_hal_include/furi_hal_bt.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_bt.h rename to targets/furi_hal_include/furi_hal_bt.h diff --git a/firmware/targets/furi_hal_include/furi_hal_bt_hid.h b/targets/furi_hal_include/furi_hal_bt_hid.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_bt_hid.h rename to targets/furi_hal_include/furi_hal_bt_hid.h diff --git a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h b/targets/furi_hal_include/furi_hal_bt_serial.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_bt_serial.h rename to targets/furi_hal_include/furi_hal_bt_serial.h diff --git a/firmware/targets/furi_hal_include/furi_hal_cortex.h b/targets/furi_hal_include/furi_hal_cortex.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_cortex.h rename to targets/furi_hal_include/furi_hal_cortex.h diff --git a/firmware/targets/furi_hal_include/furi_hal_crypto.h b/targets/furi_hal_include/furi_hal_crypto.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_crypto.h rename to targets/furi_hal_include/furi_hal_crypto.h diff --git a/firmware/targets/furi_hal_include/furi_hal_debug.h b/targets/furi_hal_include/furi_hal_debug.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_debug.h rename to targets/furi_hal_include/furi_hal_debug.h diff --git a/firmware/targets/furi_hal_include/furi_hal_i2c.h b/targets/furi_hal_include/furi_hal_i2c.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_i2c.h rename to targets/furi_hal_include/furi_hal_i2c.h diff --git a/firmware/targets/furi_hal_include/furi_hal_info.h b/targets/furi_hal_include/furi_hal_info.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_info.h rename to targets/furi_hal_include/furi_hal_info.h diff --git a/firmware/targets/furi_hal_include/furi_hal_infrared.h b/targets/furi_hal_include/furi_hal_infrared.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_infrared.h rename to targets/furi_hal_include/furi_hal_infrared.h diff --git a/firmware/targets/furi_hal_include/furi_hal_light.h b/targets/furi_hal_include/furi_hal_light.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_light.h rename to targets/furi_hal_include/furi_hal_light.h diff --git a/firmware/targets/furi_hal_include/furi_hal_memory.h b/targets/furi_hal_include/furi_hal_memory.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_memory.h rename to targets/furi_hal_include/furi_hal_memory.h diff --git a/firmware/targets/furi_hal_include/furi_hal_mpu.h b/targets/furi_hal_include/furi_hal_mpu.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_mpu.h rename to targets/furi_hal_include/furi_hal_mpu.h diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/targets/furi_hal_include/furi_hal_nfc.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_nfc.h rename to targets/furi_hal_include/furi_hal_nfc.h diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/targets/furi_hal_include/furi_hal_power.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_power.h rename to targets/furi_hal_include/furi_hal_power.h diff --git a/firmware/targets/furi_hal_include/furi_hal_random.h b/targets/furi_hal_include/furi_hal_random.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_random.h rename to targets/furi_hal_include/furi_hal_random.h diff --git a/firmware/targets/furi_hal_include/furi_hal_region.h b/targets/furi_hal_include/furi_hal_region.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_region.h rename to targets/furi_hal_include/furi_hal_region.h diff --git a/firmware/targets/furi_hal_include/furi_hal_rtc.h b/targets/furi_hal_include/furi_hal_rtc.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_rtc.h rename to targets/furi_hal_include/furi_hal_rtc.h diff --git a/firmware/targets/furi_hal_include/furi_hal_sd.h b/targets/furi_hal_include/furi_hal_sd.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_sd.h rename to targets/furi_hal_include/furi_hal_sd.h diff --git a/firmware/targets/furi_hal_include/furi_hal_speaker.h b/targets/furi_hal_include/furi_hal_speaker.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_speaker.h rename to targets/furi_hal_include/furi_hal_speaker.h diff --git a/firmware/targets/furi_hal_include/furi_hal_spi.h b/targets/furi_hal_include/furi_hal_spi.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_spi.h rename to targets/furi_hal_include/furi_hal_spi.h diff --git a/firmware/targets/furi_hal_include/furi_hal_usb.h b/targets/furi_hal_include/furi_hal_usb.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_usb.h rename to targets/furi_hal_include/furi_hal_usb.h diff --git a/firmware/targets/furi_hal_include/furi_hal_usb_ccid.h b/targets/furi_hal_include/furi_hal_usb_ccid.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_usb_ccid.h rename to targets/furi_hal_include/furi_hal_usb_ccid.h diff --git a/firmware/targets/furi_hal_include/furi_hal_usb_hid.h b/targets/furi_hal_include/furi_hal_usb_hid.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_usb_hid.h rename to targets/furi_hal_include/furi_hal_usb_hid.h diff --git a/firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h b/targets/furi_hal_include/furi_hal_usb_hid_u2f.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h rename to targets/furi_hal_include/furi_hal_usb_hid_u2f.h diff --git a/firmware/targets/furi_hal_include/furi_hal_version.h b/targets/furi_hal_include/furi_hal_version.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_version.h rename to targets/furi_hal_include/furi_hal_version.h diff --git a/firmware/targets/furi_hal_include/furi_hal_vibro.h b/targets/furi_hal_include/furi_hal_vibro.h similarity index 100% rename from firmware/targets/furi_hal_include/furi_hal_vibro.h rename to targets/furi_hal_include/furi_hal_vibro.h