mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-12-23 05:14:16 +03:00
[FL-2705] App RPC Bug Fixes and redesign (#1491)
* Rpc: remove callback timer * Rpc: simplify rpc event callback * Rpc: migrate to new confirmation schema * Rpc: migrate to new confirmation schema part2: finalize ibutton and rfid * Rpc: migrate to new confirmation schema part3: finallize nfc and fix id in load * Rpc: hardened sequencing check * Rpc: migrate to new confirmation schema part4: finalize subghz * iButton: properly handle exit * Nfc: correct sequence for rpc exit send * Rpc: fix review issues and nfc exit message * Rpc: more logging and condition race fix in confirmation * Rpc: migrate to new confirmation schema part5: finalize infrared * Rpc: more logging
This commit is contained in:
parent
f9386b2649
commit
f9745b4141
@ -5,7 +5,7 @@
|
||||
#include "m-string.h"
|
||||
#include <toolbox/path.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include "rpc/rpc_app.h"
|
||||
#include <rpc/rpc_app.h>
|
||||
|
||||
#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) {
|
||||
|
@ -12,4 +12,5 @@ enum iButtonCustomEvent {
|
||||
|
||||
iButtonCustomEventRpcLoad,
|
||||
iButtonCustomEventRpcExit,
|
||||
iButtonCustomEventRpcSessionClose,
|
||||
};
|
||||
|
@ -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, ...);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "../ibutton_i.h"
|
||||
#include <toolbox/path.h>
|
||||
#include <rpc/rpc_app.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -14,7 +14,12 @@ enum InfraredCustomEventType {
|
||||
InfraredCustomEventTypePopupClosed,
|
||||
InfraredCustomEventTypeButtonSelected,
|
||||
InfraredCustomEventTypeBackPressed,
|
||||
InfraredCustomEventTypeRpcLoaded,
|
||||
|
||||
InfraredCustomEventTypeRpcLoad,
|
||||
InfraredCustomEventTypeRpcExit,
|
||||
InfraredCustomEventTypeRpcButtonPress,
|
||||
InfraredCustomEventTypeRpcButtonRelease,
|
||||
InfraredCustomEventTypeRpcSessionClose,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
@ -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;
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <toolbox/path.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
#include "rpc/rpc_app.h"
|
||||
#include <rpc/rpc_app.h>
|
||||
|
||||
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<LfRfidApp*>(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) {
|
||||
|
@ -33,6 +33,8 @@ public:
|
||||
Retry,
|
||||
Exit,
|
||||
EmulateStart,
|
||||
RpcLoadFile,
|
||||
RpcSessionClose,
|
||||
};
|
||||
|
||||
enum class SceneType : uint8_t {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "lfrfid_app_scene_rpc.h"
|
||||
#include <core/common_defines.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <rpc/rpc_app.h>
|
||||
|
||||
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<PopupVM>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -11,4 +11,5 @@ enum NfcCustomEvent {
|
||||
NfcCustomEventDictAttackDone,
|
||||
NfcCustomEventDictAttackSkip,
|
||||
NfcCustomEventRpcLoad,
|
||||
NfcCustomEventRpcSessionClose,
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -47,6 +47,9 @@ typedef enum {
|
||||
SubGhzCustomEventSceneStay,
|
||||
|
||||
SubGhzCustomEventSceneRpcLoad,
|
||||
SubGhzCustomEventSceneRpcButtonPress,
|
||||
SubGhzCustomEventSceneRpcButtonRelease,
|
||||
SubGhzCustomEventSceneRpcSessionClose,
|
||||
|
||||
SubGhzCustomEventViewReceiverOK,
|
||||
SubGhzCustomEventViewReceiverConfig,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user