diff --git a/applications/ibutton/ibutton.c b/applications/ibutton/ibutton.c index 30accd469..5ccb1f6c8 100644 --- a/applications/ibutton/ibutton.c +++ b/applications/ibutton/ibutton.c @@ -5,7 +5,7 @@ #include "m-string.h" #include #include -#include "rpc/rpc_app.h" +#include #define TAG "iButtonApp" @@ -58,7 +58,7 @@ static void ibutton_make_app_folder(iButton* ibutton) { } } -static bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog) { +bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog) { FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); bool result = false; string_t data; @@ -99,33 +99,20 @@ static bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show return result; } -static bool ibutton_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context) { furi_assert(context); iButton* ibutton = context; - bool result = false; - if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL); - ibutton->rpc_ctx = NULL; - view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit); - result = true; + view_dispatcher_send_custom_event( + ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose); } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit); - result = true; } else if(event == RpcAppEventLoadFile) { - if(arg) { - string_set_str(ibutton->file_path, arg); - if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) { - ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key); - view_dispatcher_send_custom_event( - ibutton->view_dispatcher, iButtonCustomEventRpcLoad); - result = true; - } - } + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoad); + } else { + rpc_system_app_confirm(ibutton->rpc_ctx, event, false); } - - return result; } bool ibutton_custom_event_callback(void* context, uint32_t event) { diff --git a/applications/ibutton/ibutton_custom_event.h b/applications/ibutton/ibutton_custom_event.h index 25dfc31d9..1e2f0300d 100644 --- a/applications/ibutton/ibutton_custom_event.h +++ b/applications/ibutton/ibutton_custom_event.h @@ -12,4 +12,5 @@ enum iButtonCustomEvent { iButtonCustomEventRpcLoad, iButtonCustomEventRpcExit, + iButtonCustomEventRpcSessionClose, }; diff --git a/applications/ibutton/ibutton_i.h b/applications/ibutton/ibutton_i.h index de3065c32..9d4354d02 100644 --- a/applications/ibutton/ibutton_i.h +++ b/applications/ibutton/ibutton_i.h @@ -78,6 +78,7 @@ typedef enum { } iButtonNotificationMessage; bool ibutton_file_select(iButton* ibutton); +bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog); bool ibutton_save_key(iButton* ibutton, const char* key_name); bool ibutton_delete_key(iButton* ibutton); void ibutton_text_store_set(iButton* ibutton, const char* text, ...); diff --git a/applications/ibutton/scenes/ibutton_scene_rpc.c b/applications/ibutton/scenes/ibutton_scene_rpc.c index 14f7df638..a3f5eeee4 100644 --- a/applications/ibutton/scenes/ibutton_scene_rpc.c +++ b/applications/ibutton/scenes/ibutton_scene_rpc.c @@ -1,5 +1,6 @@ #include "../ibutton_i.h" #include +#include void ibutton_scene_rpc_on_enter(void* context) { iButton* ibutton = context; @@ -26,23 +27,40 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == iButtonCustomEventRpcLoad) { - string_t key_name; - string_init(key_name); - if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { - path_extract_filename(ibutton->file_path, key_name, true); + const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx); + bool result = false; + if(arg) { + string_set_str(ibutton->file_path, arg); + if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) { + ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key); + string_t key_name; + string_init(key_name); + if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + path_extract_filename(ibutton->file_path, key_name, true); + } + + if(!string_empty_p(key_name)) { + ibutton_text_store_set( + ibutton, "emulating\n%s", string_get_cstr(key_name)); + } else { + ibutton_text_store_set(ibutton, "emulating"); + } + popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop); + + ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); + + string_clear(key_name); + result = true; + } } - - if(!string_empty_p(key_name)) { - ibutton_text_store_set(ibutton, "emulating\n%s", string_get_cstr(key_name)); - } else { - ibutton_text_store_set(ibutton, "emulating"); - } - popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop); - - ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); - - string_clear(key_name); + rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result); } else if(event.event == iButtonCustomEventRpcExit) { + rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventAppExit, true); + ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop); + view_dispatcher_stop(ibutton->view_dispatcher); + } else if(event.event == iButtonCustomEventRpcSessionClose) { + rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL); + ibutton->rpc_ctx = NULL; ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop); view_dispatcher_stop(ibutton->view_dispatcher); } diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c index 4b7a46714..cbbd375d5 100644 --- a/applications/infrared/infrared.c +++ b/applications/infrared/infrared.c @@ -36,52 +36,29 @@ static void infrared_tick_event_callback(void* context) { scene_manager_handle_tick_event(infrared->scene_manager); } -static bool - infrared_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context) { furi_assert(context); Infrared* infrared = context; - - if(!infrared->rpc_ctx) { - return false; - } - - bool result = false; + furi_assert(infrared->rpc_ctx); if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL); - infrared->rpc_ctx = NULL; view_dispatcher_send_custom_event( - infrared->view_dispatcher, InfraredCustomEventTypeBackPressed); - result = true; + infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose); } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event( - infrared->view_dispatcher, InfraredCustomEventTypeBackPressed); - result = true; + infrared->view_dispatcher, InfraredCustomEventTypeRpcExit); } else if(event == RpcAppEventLoadFile) { - if(arg) { - string_set_str(infrared->file_path, arg); - result = infrared_remote_load(infrared->remote, infrared->file_path); - infrared_worker_tx_set_get_signal_callback( - infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); - infrared_worker_tx_set_signal_sent_callback( - infrared->worker, infrared_signal_sent_callback, infrared); - view_dispatcher_send_custom_event( - infrared->view_dispatcher, InfraredCustomEventTypeRpcLoaded); - } + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeRpcLoad); } else if(event == RpcAppEventButtonPress) { - if(arg) { - size_t button_index = 0; - if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) { - infrared_tx_start_button_index(infrared, button_index); - result = true; - } - } + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPress); } else if(event == RpcAppEventButtonRelease) { - infrared_tx_stop(infrared); - result = true; + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonRelease); + } else { + rpc_system_app_confirm(infrared->rpc_ctx, event, false); } - - return result; } static void infrared_find_vacant_remote_name(string_t name, const char* path) { diff --git a/applications/infrared/infrared_custom_event.h b/applications/infrared/infrared_custom_event.h index 29bd61f11..09440ddec 100644 --- a/applications/infrared/infrared_custom_event.h +++ b/applications/infrared/infrared_custom_event.h @@ -14,7 +14,12 @@ enum InfraredCustomEventType { InfraredCustomEventTypePopupClosed, InfraredCustomEventTypeButtonSelected, InfraredCustomEventTypeBackPressed, - InfraredCustomEventTypeRpcLoaded, + + InfraredCustomEventTypeRpcLoad, + InfraredCustomEventTypeRpcExit, + InfraredCustomEventTypeRpcButtonPress, + InfraredCustomEventTypeRpcButtonRelease, + InfraredCustomEventTypeRpcSessionClose, }; #pragma pack(push, 1) diff --git a/applications/infrared/scenes/infrared_scene_rpc.c b/applications/infrared/scenes/infrared_scene_rpc.c index e31e7fb61..1d970f6a8 100644 --- a/applications/infrared/scenes/infrared_scene_rpc.c +++ b/applications/infrared/scenes/infrared_scene_rpc.c @@ -28,12 +28,45 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { view_dispatcher_stop(infrared->view_dispatcher); } else if(event.event == InfraredCustomEventTypePopupClosed) { view_dispatcher_stop(infrared->view_dispatcher); - } else if(event.event == InfraredCustomEventTypeRpcLoaded) { + } else if(event.event == InfraredCustomEventTypeRpcLoad) { + bool result = false; + const char* arg = rpc_system_app_get_data(infrared->rpc_ctx); + if(arg) { + string_set_str(infrared->file_path, arg); + result = infrared_remote_load(infrared->remote, infrared->file_path); + infrared_worker_tx_set_get_signal_callback( + infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); + infrared_worker_tx_set_signal_sent_callback( + infrared->worker, infrared_signal_sent_callback, infrared); + } const char* remote_name = infrared_remote_get_name(infrared->remote); infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name); popup_set_text( infrared->popup, infrared->text_store[0], 82, 32, AlignCenter, AlignTop); + + rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventLoadFile, result); + } else if(event.event == InfraredCustomEventTypeRpcButtonPress) { + bool result = false; + const char* arg = rpc_system_app_get_data(infrared->rpc_ctx); + if(arg) { + size_t button_index = 0; + if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) { + infrared_tx_start_button_index(infrared, button_index); + result = true; + } + } + rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result); + } else if(event.event == InfraredCustomEventTypeRpcButtonRelease) { + infrared_tx_stop(infrared); + rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, true); + } else if(event.event == InfraredCustomEventTypeRpcExit) { + view_dispatcher_stop(infrared->view_dispatcher); + rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventAppExit, true); + } else if(event.event == InfraredCustomEventTypeRpcSessionClose) { + rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL); + infrared->rpc_ctx = NULL; + view_dispatcher_stop(infrared->view_dispatcher); } } return consumed; diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp index 329f052ba..29e99b74f 100644 --- a/applications/lfrfid/lfrfid_app.cpp +++ b/applications/lfrfid/lfrfid_app.cpp @@ -25,7 +25,7 @@ #include #include -#include "rpc/rpc_app.h" +#include const char* LfRfidApp::app_folder = ANY_PATH("lfrfid"); const char* LfRfidApp::app_extension = ".rfid"; @@ -48,38 +48,25 @@ LfRfidApp::~LfRfidApp() { } } -static bool rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) { furi_assert(context); LfRfidApp* app = static_cast(context); - bool result = false; - - if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL); - app->rpc_ctx = NULL; + if(rpc_event == RpcAppEventSessionClose) { + LfRfidApp::Event event; + event.type = LfRfidApp::EventType::RpcSessionClose; + app->view_controller.send_event(&event); + } else if(rpc_event == RpcAppEventAppExit) { LfRfidApp::Event event; event.type = LfRfidApp::EventType::Exit; app->view_controller.send_event(&event); - result = true; - } else if(event == RpcAppEventAppExit) { + } else if(rpc_event == RpcAppEventLoadFile) { LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Exit; + event.type = LfRfidApp::EventType::RpcLoadFile; app->view_controller.send_event(&event); - result = true; - } else if(event == RpcAppEventLoadFile) { - if(arg) { - string_set_str(app->file_path, arg); - if(app->load_key_data(app->file_path, &(app->worker.key), false)) { - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::EmulateStart; - app->view_controller.send_event(&event); - app->worker.start_emulate(); - result = true; - } - } + } else { + rpc_system_app_confirm(app->rpc_ctx, rpc_event, false); } - - return result; } void LfRfidApp::run(void* _args) { diff --git a/applications/lfrfid/lfrfid_app.h b/applications/lfrfid/lfrfid_app.h index 3372552fc..b0d4c5898 100644 --- a/applications/lfrfid/lfrfid_app.h +++ b/applications/lfrfid/lfrfid_app.h @@ -33,6 +33,8 @@ public: Retry, Exit, EmulateStart, + RpcLoadFile, + RpcSessionClose, }; enum class SceneType : uint8_t { diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp index bc070ce61..a32982afb 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp @@ -1,6 +1,7 @@ #include "lfrfid_app_scene_rpc.h" #include #include +#include static const NotificationSequence sequence_blink_start_magenta = { &message_blink_start_10, @@ -36,6 +37,16 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) { LfRfidApp::Event view_event; view_event.type = LfRfidApp::EventType::Back; app->view_controller.send_event(&view_event); + rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true); + } else if(event->type == LfRfidApp::EventType::RpcSessionClose) { + // Detach RPC + rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL); + app->rpc_ctx = NULL; + + consumed = true; + LfRfidApp::Event view_event; + view_event.type = LfRfidApp::EventType::Back; + app->view_controller.send_event(&view_event); } else if(event->type == LfRfidApp::EventType::EmulateStart) { auto popup = app->view_controller.get(); consumed = true; @@ -45,7 +56,22 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) { popup->set_text(app->text_store.text, 89, 43, AlignCenter, AlignTop); notification_message(app->notification, &sequence_blink_start_magenta); + } else if(event->type == LfRfidApp::EventType::RpcLoadFile) { + const char* arg = rpc_system_app_get_data(app->rpc_ctx); + bool result = false; + if(arg) { + string_set_str(app->file_path, arg); + if(app->load_key_data(app->file_path, &(app->worker.key), false)) { + LfRfidApp::Event event; + event.type = LfRfidApp::EventType::EmulateStart; + app->view_controller.send_event(&event); + app->worker.start_emulate(); + result = true; + } + } + rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result); } + return consumed; } diff --git a/applications/nfc/helpers/nfc_custom_event.h b/applications/nfc/helpers/nfc_custom_event.h index fbd54b277..4227a5b14 100644 --- a/applications/nfc/helpers/nfc_custom_event.h +++ b/applications/nfc/helpers/nfc_custom_event.h @@ -11,4 +11,5 @@ enum NfcCustomEvent { NfcCustomEventDictAttackDone, NfcCustomEventDictAttackSkip, NfcCustomEventRpcLoad, + NfcCustomEventRpcSessionClose, }; diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index b19f92f27..32e74e8f2 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -13,78 +13,21 @@ bool nfc_back_event_callback(void* context) { return scene_manager_handle_back_event(nfc->scene_manager); } -void nfc_rpc_exit_callback(Nfc* nfc) { - if(nfc->rpc_state == NfcRpcStateEmulating) { - // Stop worker - nfc_worker_stop(nfc->worker); - } else if(nfc->rpc_state == NfcRpcStateEmulated) { - // Stop worker - nfc_worker_stop(nfc->worker); - // Save data in shadow file - nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name); - } - if(nfc->rpc_ctx) { - rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); - rpc_system_app_send_exited(nfc->rpc_ctx); - nfc->rpc_ctx = NULL; - } -} - -static bool nfc_rpc_emulate_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - Nfc* nfc = context; - - nfc->rpc_state = NfcRpcStateEmulated; - return true; -} - -static bool nfc_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void nfc_rpc_command_callback(RpcAppSystemEvent event, void* context) { furi_assert(context); Nfc* nfc = context; - if(!nfc->rpc_ctx) { - return false; - } - - bool result = false; + furi_assert(nfc->rpc_ctx); if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); - nfc->rpc_ctx = NULL; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); - result = true; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcSessionClose); } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); - result = true; } else if(event == RpcAppEventLoadFile) { - if((arg) && (nfc->rpc_state == NfcRpcStateIdle)) { - if(nfc_device_load(nfc->dev, arg, false)) { - if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - nfc_worker_start( - nfc->worker, - NfcWorkerStateMfUltralightEmulate, - &nfc->dev->dev_data, - nfc_rpc_emulate_callback, - nfc); - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { - nfc_worker_start( - nfc->worker, - NfcWorkerStateMfClassicEmulate, - &nfc->dev->dev_data, - nfc_rpc_emulate_callback, - nfc); - } else { - nfc_worker_start( - nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc); - } - nfc->rpc_state = NfcRpcStateEmulating; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad); - result = true; - } - } + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad); + } else { + rpc_system_app_confirm(nfc->rpc_ctx, event, false); } - - return result; } Nfc* nfc_alloc() { @@ -163,6 +106,21 @@ Nfc* nfc_alloc() { void nfc_free(Nfc* nfc) { furi_assert(nfc); + if(nfc->rpc_state == NfcRpcStateEmulating) { + // Stop worker + nfc_worker_stop(nfc->worker); + } else if(nfc->rpc_state == NfcRpcStateEmulated) { + // Stop worker + nfc_worker_stop(nfc->worker); + // Save data in shadow file + nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name); + } + if(nfc->rpc_ctx) { + rpc_system_app_send_exited(nfc->rpc_ctx); + rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); + nfc->rpc_ctx = NULL; + } + // Nfc device nfc_device_free(nfc->dev); diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 84c0e7f0c..5a916e803 100755 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -102,5 +102,3 @@ void nfc_blink_start(Nfc* nfc); void nfc_blink_stop(Nfc* nfc); void nfc_show_loading_popup(void* context, bool show); - -void nfc_rpc_exit_callback(Nfc* nfc); diff --git a/applications/nfc/scenes/nfc_scene_rpc.c b/applications/nfc/scenes/nfc_scene_rpc.c index 582dff8e6..94beccc6b 100644 --- a/applications/nfc/scenes/nfc_scene_rpc.c +++ b/applications/nfc/scenes/nfc_scene_rpc.c @@ -14,6 +14,14 @@ void nfc_scene_rpc_on_enter(void* context) { notification_message(nfc->notifications, &sequence_display_backlight_on); } +static bool nfc_scene_rpc_emulate_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); + Nfc* nfc = context; + + nfc->rpc_state = NfcRpcStateEmulated; + return true; +} + bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; Popup* popup = nfc->popup; @@ -22,13 +30,47 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == NfcCustomEventViewExit) { + rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventAppExit, true); + view_dispatcher_stop(nfc->view_dispatcher); + nfc_blink_stop(nfc); + } else if(event.event == NfcCustomEventRpcSessionClose) { + rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); + nfc->rpc_ctx = NULL; view_dispatcher_stop(nfc->view_dispatcher); nfc_blink_stop(nfc); } else if(event.event == NfcCustomEventRpcLoad) { - nfc_blink_start(nfc); + bool result = false; + const char* arg = rpc_system_app_get_data(nfc->rpc_ctx); + if((arg) && (nfc->rpc_state == NfcRpcStateIdle)) { + if(nfc_device_load(nfc->dev, arg, false)) { + if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { + nfc_worker_start( + nfc->worker, + NfcWorkerStateMfUltralightEmulate, + &nfc->dev->dev_data, + nfc_scene_rpc_emulate_callback, + nfc); + } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { + nfc_worker_start( + nfc->worker, + NfcWorkerStateMfClassicEmulate, + &nfc->dev->dev_data, + nfc_scene_rpc_emulate_callback, + nfc); + } else { + nfc_worker_start( + nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc); + } + nfc->rpc_state = NfcRpcStateEmulating; + result = true; - nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name); - popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop); + nfc_blink_start(nfc); + nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name); + popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop); + } + } + + rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventLoadFile, result); } } return consumed; @@ -38,7 +80,6 @@ void nfc_scene_rpc_on_exit(void* context) { Nfc* nfc = context; Popup* popup = nfc->popup; - nfc_rpc_exit_callback(nfc); nfc_blink_stop(nfc); popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); diff --git a/applications/rpc/rpc_app.c b/applications/rpc/rpc_app.c index e349e61cf..555cec8cf 100644 --- a/applications/rpc/rpc_app.c +++ b/applications/rpc/rpc_app.c @@ -6,24 +6,18 @@ #include "rpc_app.h" #define TAG "RpcSystemApp" -#define APP_BUTTON_TIMEOUT 1000 struct RpcAppSystem { RpcSession* session; RpcAppSystemCallback app_callback; void* app_context; PB_Main* state_msg; - FuriTimer* timer; + + uint32_t last_id; + char* last_data; }; -static void rpc_system_app_timer_callback(void* context) { - furi_assert(context); - RpcAppSystem* rpc_app = context; - - if(rpc_app->app_callback) { - rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context); - } -} +#define RPC_SYSTEM_APP_TEMP_ARGS_SIZE 16 static void rpc_system_app_start_process(const PB_Main* request, void* context) { furi_assert(request); @@ -33,9 +27,12 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) RpcAppSystem* rpc_app = context; RpcSession* session = rpc_app->session; furi_assert(session); - char args_temp[16]; + char args_temp[RPC_SYSTEM_APP_TEMP_ARGS_SIZE]; - FURI_LOG_D(TAG, "Start"); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + + FURI_LOG_D(TAG, "StartProcess: id %d", request->command_id); PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START; @@ -43,9 +40,9 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) const char* app_name = request->content.app_start_request.name; if(app_name) { const char* app_args = request->content.app_start_request.args; - if(strcmp(app_args, "RPC") == 0) { + if(app_args && strcmp(app_args, "RPC") == 0) { // If app is being started in RPC mode - pass RPC context via args string - snprintf(args_temp, 16, "RPC %08lX", (uint32_t)rpc_app); + snprintf(args_temp, RPC_SYSTEM_APP_TEMP_ARGS_SIZE, "RPC %08lX", (uint32_t)rpc_app); app_args = args_temp; } LoaderStatus status = loader_start(loader, app_name, app_args); @@ -58,7 +55,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) } else if(status == LoaderStatusOk) { result = PB_CommandStatus_OK; } else { - furi_assert(0); + furi_crash("Programming Error"); } } else { result = PB_CommandStatus_ERROR_INVALID_PARAMETERS; @@ -66,6 +63,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) furi_record_close(RECORD_LOADER); + FURI_LOG_D(TAG, "StartProcess: response id %d, result %d", request->command_id, result); rpc_send_and_release_empty(session, request->command_id, result); } @@ -93,6 +91,7 @@ static void rpc_system_app_lock_status_process(const PB_Main* request, void* con furi_record_close(RECORD_LOADER); + FURI_LOG_D(TAG, "LockStatus: response"); rpc_send_and_release(session, &response); pb_release(&PB_Main_msg, &response); } @@ -109,17 +108,17 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - if(rpc_app->app_callback(RpcAppEventAppExit, NULL, rpc_app->app_context)) { - status = PB_CommandStatus_OK; - furi_timer_stop(rpc_app->timer); - } else { - status = PB_CommandStatus_ERROR_APP_CMD_ERROR; - } + FURI_LOG_D(TAG, "ExitRequest: id %d", request->command_id); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + rpc_app->last_id = request->command_id; + rpc_app->app_callback(RpcAppEventAppExit, rpc_app->app_context); } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; + FURI_LOG_E( + TAG, "ExitRequest: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + rpc_send_and_release_empty(session, request->command_id, status); } - - rpc_send_and_release_empty(session, request->command_id, status); } static void rpc_system_app_load_file(const PB_Main* request, void* context) { @@ -133,17 +132,18 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - const char* file_path = request->content.app_load_file_request.path; - if(rpc_app->app_callback(RpcAppEventLoadFile, file_path, rpc_app->app_context)) { - status = PB_CommandStatus_OK; - } else { - status = PB_CommandStatus_ERROR_APP_CMD_ERROR; - } + FURI_LOG_D(TAG, "LoadFile: id %d", request->command_id); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + rpc_app->last_id = request->command_id; + rpc_app->last_data = strdup(request->content.app_load_file_request.path); + rpc_app->app_callback(RpcAppEventLoadFile, rpc_app->app_context); } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; + FURI_LOG_E( + TAG, "LoadFile: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + rpc_send_and_release_empty(session, request->command_id, status); } - - rpc_send_and_release_empty(session, request->command_id, status); } static void rpc_system_app_button_press(const PB_Main* request, void* context) { @@ -157,18 +157,18 @@ static void rpc_system_app_button_press(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - const char* args = request->content.app_button_press_request.args; - if(rpc_app->app_callback(RpcAppEventButtonPress, args, rpc_app->app_context)) { - status = PB_CommandStatus_OK; - furi_timer_start(rpc_app->timer, APP_BUTTON_TIMEOUT); - } else { - status = PB_CommandStatus_ERROR_APP_CMD_ERROR; - } + FURI_LOG_D(TAG, "ButtonPress"); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + rpc_app->last_id = request->command_id; + rpc_app->last_data = strdup(request->content.app_button_press_request.args); + rpc_app->app_callback(RpcAppEventButtonPress, rpc_app->app_context); } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; + FURI_LOG_E( + TAG, "ButtonPress: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + rpc_send_and_release_empty(session, request->command_id, status); } - - rpc_send_and_release_empty(session, request->command_id, status); } static void rpc_system_app_button_release(const PB_Main* request, void* context) { @@ -182,17 +182,17 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context) PB_CommandStatus status; if(rpc_app->app_callback) { - if(rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context)) { - status = PB_CommandStatus_OK; - furi_timer_stop(rpc_app->timer); - } else { - status = PB_CommandStatus_ERROR_APP_CMD_ERROR; - } + FURI_LOG_D(TAG, "ButtonRelease"); + furi_assert(!rpc_app->last_id); + furi_assert(!rpc_app->last_data); + rpc_app->last_id = request->command_id; + rpc_app->app_callback(RpcAppEventButtonRelease, rpc_app->app_context); } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; + FURI_LOG_E( + TAG, "ButtonRelease: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status); + rpc_send_and_release_empty(session, request->command_id, status); } - - rpc_send_and_release_empty(session, request->command_id, status); } void rpc_system_app_send_started(RpcAppSystem* rpc_app) { @@ -201,6 +201,8 @@ void rpc_system_app_send_started(RpcAppSystem* rpc_app) { furi_assert(session); rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_STARTED; + + FURI_LOG_D(TAG, "SendStarted"); rpc_send(session, rpc_app->state_msg); } @@ -210,9 +212,46 @@ void rpc_system_app_send_exited(RpcAppSystem* rpc_app) { furi_assert(session); rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_CLOSED; + + FURI_LOG_D(TAG, "SendExit"); rpc_send(session, rpc_app->state_msg); } +const char* rpc_system_app_get_data(RpcAppSystem* rpc_app) { + furi_assert(rpc_app); + furi_assert(rpc_app->last_data); + return rpc_app->last_data; +} + +void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result) { + furi_assert(rpc_app); + RpcSession* session = rpc_app->session; + furi_assert(session); + furi_assert(rpc_app->last_id); + + PB_CommandStatus status = result ? PB_CommandStatus_OK : PB_CommandStatus_ERROR_APP_CMD_ERROR; + + uint32_t last_id = 0; + switch(event) { + case RpcAppEventAppExit: + case RpcAppEventLoadFile: + case RpcAppEventButtonPress: + case RpcAppEventButtonRelease: + last_id = rpc_app->last_id; + rpc_app->last_id = 0; + if(rpc_app->last_data) { + free(rpc_app->last_data); + rpc_app->last_data = NULL; + } + FURI_LOG_D(TAG, "AppConfirm: event %d last_id %d status %d", event, last_id, status); + rpc_send_and_release_empty(session, last_id, status); + break; + default: + furi_crash("RPC App state programming Error"); + break; + } +} + void rpc_system_app_set_callback(RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* ctx) { furi_assert(rpc_app); @@ -226,8 +265,6 @@ void* rpc_system_app_alloc(RpcSession* session) { RpcAppSystem* rpc_app = malloc(sizeof(RpcAppSystem)); rpc_app->session = session; - rpc_app->timer = furi_timer_alloc(rpc_system_app_timer_callback, FuriTimerTypeOnce, rpc_app); - // App exit message rpc_app->state_msg = malloc(sizeof(PB_Main)); rpc_app->state_msg->which_content = PB_Main_app_state_response_tag; @@ -265,12 +302,16 @@ void rpc_system_app_free(void* context) { RpcSession* session = rpc_app->session; furi_assert(session); - furi_timer_free(rpc_app->timer); - if(rpc_app->app_callback) { - rpc_app->app_callback(RpcAppEventSessionClose, NULL, rpc_app->app_context); + rpc_app->app_callback(RpcAppEventSessionClose, rpc_app->app_context); } + while(rpc_app->app_callback) { + furi_delay_tick(1); + } + + if(rpc_app->last_data) free(rpc_app->last_data); + free(rpc_app->state_msg); free(rpc_app); } diff --git a/applications/rpc/rpc_app.h b/applications/rpc/rpc_app.h index 4e00922ff..635c9f8c6 100644 --- a/applications/rpc/rpc_app.h +++ b/applications/rpc/rpc_app.h @@ -13,7 +13,7 @@ typedef enum { RpcAppEventButtonRelease, } RpcAppSystemEvent; -typedef bool (*RpcAppSystemCallback)(RpcAppSystemEvent event, const char* arg, void* context); +typedef void (*RpcAppSystemCallback)(RpcAppSystemEvent event, void* context); typedef struct RpcAppSystem RpcAppSystem; @@ -23,6 +23,10 @@ void rpc_system_app_send_started(RpcAppSystem* rpc_app); void rpc_system_app_send_exited(RpcAppSystem* rpc_app); +const char* rpc_system_app_get_data(RpcAppSystem* rpc_app); + +void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result); + #ifdef __cplusplus } #endif diff --git a/applications/subghz/helpers/subghz_custom_event.h b/applications/subghz/helpers/subghz_custom_event.h index 801a8ae9d..765c9e251 100644 --- a/applications/subghz/helpers/subghz_custom_event.h +++ b/applications/subghz/helpers/subghz_custom_event.h @@ -47,6 +47,9 @@ typedef enum { SubGhzCustomEventSceneStay, SubGhzCustomEventSceneRpcLoad, + SubGhzCustomEventSceneRpcButtonPress, + SubGhzCustomEventSceneRpcButtonRelease, + SubGhzCustomEventSceneRpcSessionClose, SubGhzCustomEventViewReceiverOK, SubGhzCustomEventViewReceiverConfig, diff --git a/applications/subghz/scenes/subghz_scene_rpc.c b/applications/subghz/scenes/subghz_scene_rpc.c index 844f5c167..c6f7df268 100644 --- a/applications/subghz/scenes/subghz_scene_rpc.c +++ b/applications/subghz/scenes/subghz_scene_rpc.c @@ -22,20 +22,60 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == SubGhzCustomEventSceneExit) { + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_tx_stop(subghz); + subghz_sleep(subghz); + } view_dispatcher_stop(subghz->view_dispatcher); + rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventAppExit, true); + } else if(event.event == SubGhzCustomEventSceneRpcSessionClose) { + rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL); + subghz->rpc_ctx = NULL; + subghz_blink_stop(subghz); + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_tx_stop(subghz); + subghz_sleep(subghz); + } + view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit); + } else if(event.event == SubGhzCustomEventSceneRpcButtonPress) { + bool result = false; + if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) { + subghz_blink_start(subghz); + result = subghz_tx_start(subghz, subghz->txrx->fff_data); + result = true; + } + rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result); + } else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) { + bool result = false; + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_blink_stop(subghz); + subghz_tx_stop(subghz); + subghz_sleep(subghz); + result = true; + } + rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonRelease, result); } else if(event.event == SubGhzCustomEventSceneRpcLoad) { - string_t file_name; - string_init(file_name); - path_extract_filename(subghz->file_path, file_name, true); + bool result = false; + const char* arg = rpc_system_app_get_data(subghz->rpc_ctx); + if(arg) { + if(subghz_key_load(subghz, arg, false)) { + string_set_str(subghz->file_path, arg); + result = true; + string_t file_name; + string_init(file_name); + path_extract_filename(subghz->file_path, file_name, true); - snprintf( - subghz->file_name_tmp, - SUBGHZ_MAX_LEN_NAME, - "loaded\n%s", - string_get_cstr(file_name)); - popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop); + snprintf( + subghz->file_name_tmp, + SUBGHZ_MAX_LEN_NAME, + "loaded\n%s", + string_get_cstr(file_name)); + popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop); - string_clear(file_name); + string_clear(file_name); + } + } + rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventLoadFile, result); } } return consumed; diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index a970e10c4..4631d7a30 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -35,57 +35,38 @@ void subghz_tick_event_callback(void* context) { scene_manager_handle_tick_event(subghz->scene_manager); } -static bool subghz_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { +static void subghz_rpc_command_callback(RpcAppSystemEvent event, void* context) { furi_assert(context); SubGhz* subghz = context; - if(!subghz->rpc_ctx) { - return false; - } - - bool result = false; + furi_assert(subghz->rpc_ctx); if(event == RpcAppEventSessionClose) { - rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL); - subghz->rpc_ctx = NULL; - notification_message(subghz->notifications, &sequence_blink_stop); - view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit); - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - subghz_sleep(subghz); - } - result = true; + view_dispatcher_send_custom_event( + subghz->view_dispatcher, SubGhzCustomEventSceneRpcSessionClose); } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit); - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - subghz_sleep(subghz); - } - result = true; } else if(event == RpcAppEventLoadFile) { - if(arg) { - if(subghz_key_load(subghz, arg, false)) { - string_set_str(subghz->file_path, arg); - view_dispatcher_send_custom_event( - subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad); - result = true; - } - } + view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad); } else if(event == RpcAppEventButtonPress) { - if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) { - notification_message(subghz->notifications, &sequence_blink_start_magenta); - result = subghz_tx_start(subghz, subghz->txrx->fff_data); - } + view_dispatcher_send_custom_event( + subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonPress); } else if(event == RpcAppEventButtonRelease) { - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - notification_message(subghz->notifications, &sequence_blink_stop); - subghz_tx_stop(subghz); - subghz_sleep(subghz); - result = true; - } + view_dispatcher_send_custom_event( + subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonRelease); + } else { + rpc_system_app_confirm(subghz->rpc_ctx, event, false); } +} - return result; +void subghz_blink_start(SubGhz* instance) { + furi_assert(instance); + notification_message(instance->notifications, &sequence_blink_start_magenta); +} + +void subghz_blink_stop(SubGhz* instance) { + furi_assert(instance); + notification_message(instance->notifications, &sequence_blink_stop); } SubGhz* subghz_alloc() { @@ -237,7 +218,7 @@ void subghz_free(SubGhz* subghz) { if(subghz->rpc_ctx) { rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL); rpc_system_app_send_exited(subghz->rpc_ctx); - notification_message(subghz->notifications, &sequence_blink_stop); + subghz_blink_stop(subghz); subghz->rpc_ctx = NULL; } diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index 01fbe57be..99a0f8a28 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -108,6 +108,10 @@ void subghz_begin(SubGhz* subghz, uint8_t* preset_data); uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency); void subghz_rx_end(SubGhz* subghz); void subghz_sleep(SubGhz* subghz); + +void subghz_blink_start(SubGhz* instance); +void subghz_blink_stop(SubGhz* instance); + bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format); void subghz_tx_stop(SubGhz* subghz); void subghz_dialog_message_show_only_rx(SubGhz* subghz);