Merge branch 'dev' into release-candidate
This commit is contained in:
commit
dad1b0622b
4
Makefile
4
Makefile
@ -49,14 +49,14 @@ firmware_clean:
|
||||
|
||||
.PHONY: bootloader_flash
|
||||
bootloader_flash:
|
||||
ifeq ($(FORCE), '1')
|
||||
ifeq ($(FORCE), 1)
|
||||
rm $(PROJECT_ROOT)/bootloader/.obj/f*/flash || true
|
||||
endif
|
||||
$(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) flash
|
||||
|
||||
.PHONY: firmware_flash
|
||||
firmware_flash:
|
||||
ifeq ($(FORCE), '1')
|
||||
ifeq ($(FORCE), 1)
|
||||
rm $(PROJECT_ROOT)/firmware/.obj/f*/flash || true
|
||||
endif
|
||||
$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) flash
|
||||
|
||||
@ -65,55 +65,55 @@ extern int32_t power_settings_app(void* p);
|
||||
const FlipperApplication FLIPPER_SERVICES[] = {
|
||||
/* Services */
|
||||
#ifdef SRV_RPC
|
||||
{.app = rpc_srv, .name = "RPC", .stack_size = 1024 * 4, .icon = NULL},
|
||||
{.app = rpc_srv, .name = "RpcSrv", .stack_size = 1024 * 4, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_BT
|
||||
{.app = bt_srv, .name = "BT", .stack_size = 1024, .icon = NULL},
|
||||
{.app = bt_srv, .name = "BtSrv", .stack_size = 1024, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_CLI
|
||||
{.app = cli_srv, .name = "Cli", .stack_size = 4096, .icon = NULL},
|
||||
{.app = cli_srv, .name = "CliSrv", .stack_size = 4096, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_DIALOGS
|
||||
{.app = dialogs_srv, .name = "Dialogs", .stack_size = 1024, .icon = NULL},
|
||||
{.app = dialogs_srv, .name = "DialogsSrv", .stack_size = 1024, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_DOLPHIN
|
||||
{.app = dolphin_srv, .name = "Dolphin", .stack_size = 1024, .icon = NULL},
|
||||
{.app = dolphin_srv, .name = "DolphinSrv", .stack_size = 1024, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_DESKTOP
|
||||
{.app = desktop_srv, .name = "Desktop", .stack_size = 1024, .icon = NULL},
|
||||
{.app = desktop_srv, .name = "DesktopSrv", .stack_size = 2048, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_GUI
|
||||
{.app = gui_srv, .name = "Gui", .stack_size = 8192, .icon = NULL},
|
||||
{.app = gui_srv, .name = "GuiSrv", .stack_size = 2048, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_INPUT
|
||||
{.app = input_srv, .name = "Input", .stack_size = 1024, .icon = NULL},
|
||||
{.app = input_srv, .name = "InputSrv", .stack_size = 1024, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_LOADER
|
||||
{.app = loader_srv, .name = "Loader", .stack_size = 1024, .icon = NULL},
|
||||
{.app = loader_srv, .name = "LoaderSrv", .stack_size = 1024, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_NOTIFICATION
|
||||
{.app = notification_srv, .name = "Notification", .stack_size = 1024, .icon = NULL},
|
||||
{.app = notification_srv, .name = "NotificationSrv", .stack_size = 1536, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_POWER
|
||||
{.app = power_srv, .name = "Power", .stack_size = 1024, .icon = NULL},
|
||||
{.app = power_srv, .name = "PowerSrv", .stack_size = 1024, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_POWER_OBSERVER
|
||||
{.app = power_observer_srv, .name = "PowerObserver", .stack_size = 1024, .icon = NULL},
|
||||
{.app = power_observer_srv, .name = "PowerAuditSrv", .stack_size = 1024, .icon = NULL},
|
||||
#endif
|
||||
|
||||
#ifdef SRV_STORAGE
|
||||
{.app = storage_srv, .name = "Storage", .stack_size = 4096, .icon = NULL},
|
||||
{.app = storage_srv, .name = "StorageSrv", .stack_size = 3072, .icon = NULL},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -231,6 +231,10 @@ endif
|
||||
SRV_RPC ?= 0
|
||||
ifeq ($(SRV_RPC), 1)
|
||||
CFLAGS += -DSRV_RPC
|
||||
ifeq ($(SRV_RPC_DEBUG), 1)
|
||||
CFLAGS += -DSRV_RPC_DEBUG
|
||||
endif
|
||||
SRV_CLI = 1
|
||||
endif
|
||||
|
||||
SRV_LOADER ?= 0
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#include "archive_files.h"
|
||||
#include "archive_browser.h"
|
||||
|
||||
#define TAG "Archive"
|
||||
|
||||
bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name) {
|
||||
furi_assert(file_info);
|
||||
furi_assert(tab_ext);
|
||||
@ -147,11 +149,11 @@ void archive_file_append(const char* path, const char* format, ...) {
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
|
||||
if(!file_worker_open(file_worker, path, FSAM_WRITE, FSOM_OPEN_APPEND)) {
|
||||
FURI_LOG_E("Archive", "Append open error");
|
||||
FURI_LOG_E(TAG, "Append open error");
|
||||
}
|
||||
|
||||
if(!file_worker_write(file_worker, string_get_cstr(string), string_size(string))) {
|
||||
FURI_LOG_E("Archive", "Append write error");
|
||||
FURI_LOG_E(TAG, "Append write error");
|
||||
}
|
||||
|
||||
file_worker_close(file_worker);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include "battery_service.h"
|
||||
#include "bt_keys_storage.h"
|
||||
|
||||
#define BT_SERVICE_TAG "BT"
|
||||
#define TAG "BtSrv"
|
||||
|
||||
static void bt_draw_statusbar_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(context);
|
||||
@ -81,14 +81,15 @@ Bt* bt_alloc() {
|
||||
}
|
||||
|
||||
// Called from GAP thread from Serial service
|
||||
static void bt_on_data_received_callback(uint8_t* data, uint16_t size, void* context) {
|
||||
static uint16_t bt_on_data_received_callback(uint8_t* data, uint16_t size, void* context) {
|
||||
furi_assert(context);
|
||||
Bt* bt = context;
|
||||
|
||||
size_t bytes_processed = rpc_session_feed(bt->rpc_session, data, size, 1000);
|
||||
if(bytes_processed != size) {
|
||||
FURI_LOG_E(BT_SERVICE_TAG, "Only %d of %d bytes processed by RPC", bytes_processed, size);
|
||||
FURI_LOG_E(TAG, "Only %d of %d bytes processed by RPC", bytes_processed, size);
|
||||
}
|
||||
return rpc_session_get_available_size(bt->rpc_session);
|
||||
}
|
||||
|
||||
// Called from GAP thread from Serial service
|
||||
@ -118,6 +119,11 @@ static void bt_rpc_send_bytes_callback(void* context, uint8_t* bytes, size_t byt
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_rpc_buffer_is_empty_callback(void* context) {
|
||||
furi_assert(context);
|
||||
furi_hal_bt_notify_buffer_is_empty();
|
||||
}
|
||||
|
||||
// Called from GAP thread
|
||||
static void bt_on_gap_event_callback(BleEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
@ -129,12 +135,13 @@ static void bt_on_gap_event_callback(BleEvent event, void* context) {
|
||||
BtMessage message = {.type = BtMessageTypeUpdateStatusbar};
|
||||
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
|
||||
// Open RPC session
|
||||
FURI_LOG_I(BT_SERVICE_TAG, "Open RPC connection");
|
||||
FURI_LOG_I(TAG, "Open RPC connection");
|
||||
bt->rpc_session = rpc_session_open(bt->rpc);
|
||||
rpc_session_set_send_bytes_callback(bt->rpc_session, bt_rpc_send_bytes_callback);
|
||||
rpc_session_set_buffer_is_empty_callback(bt->rpc_session, bt_rpc_buffer_is_empty_callback);
|
||||
rpc_session_set_context(bt->rpc_session, bt);
|
||||
furi_hal_bt_set_data_event_callbacks(
|
||||
bt_on_data_received_callback, bt_on_data_sent_callback, bt);
|
||||
RPC_BUFFER_SIZE, bt_on_data_received_callback, bt_on_data_sent_callback, bt);
|
||||
// Update battery level
|
||||
PowerInfo info;
|
||||
power_get_info(bt->power, &info);
|
||||
@ -142,7 +149,7 @@ static void bt_on_gap_event_callback(BleEvent event, void* context) {
|
||||
message.data.battery_level = info.charge;
|
||||
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
|
||||
} else if(event.type == BleEventTypeDisconnected) {
|
||||
FURI_LOG_I(BT_SERVICE_TAG, "Close RPC connection");
|
||||
FURI_LOG_I(TAG, "Close RPC connection");
|
||||
if(bt->rpc_session) {
|
||||
rpc_session_close(bt->rpc_session);
|
||||
bt->rpc_session = NULL;
|
||||
@ -165,7 +172,7 @@ static void bt_on_gap_event_callback(BleEvent event, void* context) {
|
||||
static void bt_on_key_storage_change_callback(uint8_t* addr, uint16_t size, void* context) {
|
||||
furi_assert(context);
|
||||
Bt* bt = context;
|
||||
FURI_LOG_I(BT_SERVICE_TAG, "Changed addr start: %08lX, size changed: %d", addr, size);
|
||||
FURI_LOG_I(TAG, "Changed addr start: %08lX, size changed: %d", addr, size);
|
||||
BtMessage message = {.type = BtMessageTypeKeysStorageUpdated};
|
||||
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
|
||||
}
|
||||
@ -188,20 +195,20 @@ int32_t bt_srv() {
|
||||
|
||||
// Read keys
|
||||
if(!bt_load_key_storage(bt)) {
|
||||
FURI_LOG_W(BT_SERVICE_TAG, "Failed to load saved bonding keys");
|
||||
FURI_LOG_W(TAG, "Failed to load saved bonding keys");
|
||||
}
|
||||
// Start 2nd core
|
||||
if(!furi_hal_bt_start_core2()) {
|
||||
FURI_LOG_E(BT_SERVICE_TAG, "Core2 startup failed");
|
||||
FURI_LOG_E(TAG, "Core2 startup failed");
|
||||
} else {
|
||||
view_port_enabled_set(bt->statusbar_view_port, true);
|
||||
if(furi_hal_bt_init_app(bt_on_gap_event_callback, bt)) {
|
||||
FURI_LOG_I(BT_SERVICE_TAG, "BLE stack started");
|
||||
FURI_LOG_I(TAG, "BLE stack started");
|
||||
if(bt->bt_settings.enabled) {
|
||||
furi_hal_bt_start_advertising();
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(BT_SERVICE_TAG, "BT App start failed");
|
||||
FURI_LOG_E(TAG, "BT App start failed");
|
||||
}
|
||||
}
|
||||
furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include <furi.h>
|
||||
#include <file-worker.h>
|
||||
|
||||
#define BT_SETTINGS_TAG "bt settings"
|
||||
#define TAG "BtSettings"
|
||||
#define BT_SETTINGS_PATH "/int/bt.settings"
|
||||
|
||||
bool bt_settings_load(BtSettings* bt_settings) {
|
||||
@ -10,7 +10,7 @@ bool bt_settings_load(BtSettings* bt_settings) {
|
||||
bool file_loaded = false;
|
||||
BtSettings settings = {};
|
||||
|
||||
FURI_LOG_I(BT_SETTINGS_TAG, "Loading settings from \"%s\"", BT_SETTINGS_PATH);
|
||||
FURI_LOG_I(TAG, "Loading settings from \"%s\"", BT_SETTINGS_PATH);
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
if(file_worker_open(file_worker, BT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
if(file_worker_read(file_worker, &settings, sizeof(settings))) {
|
||||
@ -20,16 +20,16 @@ bool bt_settings_load(BtSettings* bt_settings) {
|
||||
file_worker_free(file_worker);
|
||||
|
||||
if(file_loaded) {
|
||||
FURI_LOG_I(BT_SETTINGS_TAG, "Settings load success");
|
||||
FURI_LOG_I(TAG, "Settings load success");
|
||||
if(settings.version != BT_SETTINGS_VERSION) {
|
||||
FURI_LOG_E(BT_SETTINGS_TAG, "Settings version mismatch");
|
||||
FURI_LOG_E(TAG, "Settings version mismatch");
|
||||
} else {
|
||||
osKernelLock();
|
||||
*bt_settings = settings;
|
||||
osKernelUnlock();
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(BT_SETTINGS_TAG, "Settings load failed");
|
||||
FURI_LOG_E(TAG, "Settings load failed");
|
||||
}
|
||||
return file_loaded;
|
||||
}
|
||||
@ -41,7 +41,7 @@ bool bt_settings_save(BtSettings* bt_settings) {
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
if(file_worker_open(file_worker, BT_SETTINGS_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) {
|
||||
if(file_worker_write(file_worker, bt_settings, sizeof(BtSettings))) {
|
||||
FURI_LOG_I(BT_SETTINGS_TAG, "Settings saved to \"%s\"", BT_SETTINGS_PATH);
|
||||
FURI_LOG_I(TAG, "Settings saved to \"%s\"", BT_SETTINGS_PATH);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
#include <furi-hal-usb-hid.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
#define TAG "BadUsb"
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
|
||||
typedef enum {
|
||||
EventTypeInput,
|
||||
EventTypeWorkerState,
|
||||
@ -191,7 +194,7 @@ static bool ducky_parse_line(string_t line, BadUsbParams* app) {
|
||||
|
||||
static void badusb_worker(void* context) {
|
||||
BadUsbParams* app = context;
|
||||
FURI_LOG_I("BadUSB worker", "Init");
|
||||
FURI_LOG_I(WORKER_TAG, "Init");
|
||||
File* script_file = storage_file_alloc(furi_record_open("storage"));
|
||||
BadUsbEvent evt;
|
||||
string_t line;
|
||||
@ -203,7 +206,7 @@ static void badusb_worker(void* context) {
|
||||
uint32_t flags =
|
||||
osThreadFlagsWait(WorkerCmdStart | WorkerCmdStop, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & WorkerCmdStart) {
|
||||
FURI_LOG_I("BadUSB worker", "Start");
|
||||
FURI_LOG_I(WORKER_TAG, "Start");
|
||||
do {
|
||||
ret = storage_file_read(script_file, buffer, 16);
|
||||
for(uint16_t i = 0; i < ret; i++) {
|
||||
@ -211,7 +214,7 @@ static void badusb_worker(void* context) {
|
||||
line_cnt++;
|
||||
if(ducky_parse_line(line, app) == false) {
|
||||
ret = 0;
|
||||
FURI_LOG_E("BadUSB worker", "Unknown command at line %lu", line_cnt);
|
||||
FURI_LOG_E(WORKER_TAG, "Unknown command at line %lu", line_cnt);
|
||||
evt.type = EventTypeWorkerState;
|
||||
evt.worker.state = WorkerStateScriptError;
|
||||
evt.worker.line = line_cnt;
|
||||
@ -231,7 +234,7 @@ static void badusb_worker(void* context) {
|
||||
} while(ret > 0);
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E("BadUSB worker", "Script file open error");
|
||||
FURI_LOG_E(WORKER_TAG, "Script file open error");
|
||||
evt.type = EventTypeWorkerState;
|
||||
evt.worker.state = WorkerStateNoFile;
|
||||
osMessageQueuePut(app->event_queue, &evt, 0, osWaitForever);
|
||||
@ -243,7 +246,7 @@ static void badusb_worker(void* context) {
|
||||
storage_file_close(script_file);
|
||||
storage_file_free(script_file);
|
||||
|
||||
FURI_LOG_I("BadUSB worker", "End");
|
||||
FURI_LOG_I(WORKER_TAG, "End");
|
||||
evt.type = EventTypeWorkerState;
|
||||
evt.worker.state = WorkerStateDone;
|
||||
osMessageQueuePut(app->event_queue, &evt, 0, osWaitForever);
|
||||
@ -324,7 +327,7 @@ int32_t bad_usb_app(void* p) {
|
||||
}
|
||||
}
|
||||
} else if(event.type == EventTypeWorkerState) {
|
||||
FURI_LOG_I("BadUSB app", "ev: %d", event.worker.state);
|
||||
FURI_LOG_I(TAG, "ev: %d", event.worker.state);
|
||||
if(event.worker.state == WorkerStateDone) {
|
||||
worker_running = false;
|
||||
if(app_state == AppStateExit)
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
|
||||
#include "view_display_test.h"
|
||||
|
||||
#define TAG "DisplayTest"
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
@ -77,7 +79,7 @@ static uint32_t display_test_exit_callback(void* context) {
|
||||
|
||||
static void display_test_reload_config(DisplayTest* instance) {
|
||||
FURI_LOG_I(
|
||||
"DisplayTest",
|
||||
TAG,
|
||||
"contrast: %d, regulation_ratio: %d, bias: %d",
|
||||
instance->config_contrast,
|
||||
instance->config_regulation_ratio,
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#define TAG "KeypadTest"
|
||||
|
||||
typedef struct {
|
||||
bool press[5];
|
||||
uint16_t up;
|
||||
@ -80,7 +82,7 @@ int32_t keypad_test_app(void* p) {
|
||||
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(KeypadTestState))) {
|
||||
FURI_LOG_E("KeypadTest", "cannot create mutex");
|
||||
FURI_LOG_E(TAG, "cannot create mutex");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -101,7 +103,7 @@ int32_t keypad_test_app(void* p) {
|
||||
if(event_status == osOK) {
|
||||
if(event.type == EventTypeInput) {
|
||||
FURI_LOG_I(
|
||||
"KeypadTest",
|
||||
TAG,
|
||||
"key: %s type: %s",
|
||||
input_get_key_name(event.input.key),
|
||||
input_get_type_name(event.input.type));
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include "desktop_animation.h"
|
||||
|
||||
#define TAG "DesktopAnimation"
|
||||
|
||||
static const Icon* idle_scenes[] = {&A_Wink_128x64, &A_WatchingTV_128x64};
|
||||
|
||||
const Icon* desktop_get_icon() {
|
||||
@ -12,10 +14,10 @@ const Icon* desktop_get_icon() {
|
||||
DolphinStats stats = dolphin_stats(dolphin);
|
||||
float timediff = fabs(difftime(stats.timestamp, dolphin_state_timestamp()));
|
||||
|
||||
FURI_LOG_I("desktop-animation", "background change");
|
||||
FURI_LOG_I("desktop-animation", "icounter: %d", stats.icounter);
|
||||
FURI_LOG_I("desktop-animation", "butthurt: %d", stats.butthurt);
|
||||
FURI_LOG_I("desktop-animation", "time since deeed: %.0f", timediff);
|
||||
FURI_LOG_I(TAG, "background change");
|
||||
FURI_LOG_I(TAG, "icounter: %d", stats.icounter);
|
||||
FURI_LOG_I(TAG, "butthurt: %d", stats.butthurt);
|
||||
FURI_LOG_I(TAG, "time since deeed: %.0f", timediff);
|
||||
#endif
|
||||
|
||||
if((random() % 100) > 50) { // temp rnd selection
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#include "view-holder.h"
|
||||
#include <gui/view_i.h>
|
||||
|
||||
#define TAG "ViewHolder"
|
||||
|
||||
struct ViewHolder {
|
||||
View* view;
|
||||
ViewPort* view_port;
|
||||
@ -125,7 +127,7 @@ static void view_holder_input_callback(InputEvent* event, void* context) {
|
||||
view_holder->ongoing_input &= ~key_bit;
|
||||
} else if(!(view_holder->ongoing_input & key_bit)) {
|
||||
FURI_LOG_W(
|
||||
"ViewHolder",
|
||||
TAG,
|
||||
"non-complementary input, discarding key: %s, type: %s",
|
||||
input_get_key_name(event->key),
|
||||
input_get_type_name(event->type));
|
||||
|
||||
@ -82,7 +82,7 @@ static void dolphin_check_butthurt(DolphinState* state) {
|
||||
float diff_time = difftime(dolphin_state_get_timestamp(state), dolphin_state_timestamp());
|
||||
|
||||
if((fabs(diff_time)) > DOLPHIN_TIMEGATE) {
|
||||
FURI_LOG_I("dolphin-state", "Increasing butthurt");
|
||||
FURI_LOG_I("DolphinState", "Increasing butthurt");
|
||||
dolphin_state_butthurted(state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#include <math.h>
|
||||
#include <toolbox/saved_struct.h>
|
||||
|
||||
#define DOLPHIN_STATE_TAG "DolphinState"
|
||||
#define TAG "DolphinState"
|
||||
#define DOLPHIN_STATE_PATH "/int/dolphin.state"
|
||||
#define DOLPHIN_STATE_HEADER_MAGIC 0xD0
|
||||
#define DOLPHIN_STATE_HEADER_VERSION 0x01
|
||||
@ -48,10 +48,10 @@ bool dolphin_state_save(DolphinState* dolphin_state) {
|
||||
DOLPHIN_STATE_HEADER_VERSION);
|
||||
|
||||
if(result) {
|
||||
FURI_LOG_I(DOLPHIN_STATE_TAG, "State saved");
|
||||
FURI_LOG_I(TAG, "State saved");
|
||||
dolphin_state->dirty = false;
|
||||
} else {
|
||||
FURI_LOG_E(DOLPHIN_STATE_TAG, "Failed to save state");
|
||||
FURI_LOG_E(TAG, "Failed to save state");
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -66,7 +66,7 @@ bool dolphin_state_load(DolphinState* dolphin_state) {
|
||||
DOLPHIN_STATE_HEADER_VERSION);
|
||||
|
||||
if(!loaded) {
|
||||
FURI_LOG_W(DOLPHIN_STATE_TAG, "Reset dolphin-state");
|
||||
FURI_LOG_W(TAG, "Reset dolphin-state");
|
||||
memset(dolphin_state, 0, sizeof(*dolphin_state));
|
||||
dolphin_state->dirty = true;
|
||||
}
|
||||
|
||||
@ -8,11 +8,12 @@
|
||||
#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)
|
||||
|
||||
typedef enum {
|
||||
WorkerEvtStop = (1 << 0),
|
||||
WorkerEvtRxDone = (1 << 1),
|
||||
WorkerEvtReserved = (1 << 0), // Reserved for StreamBuffer internal event
|
||||
WorkerEvtStop = (1 << 1),
|
||||
WorkerEvtRxDone = (1 << 2),
|
||||
|
||||
WorkerEvtTxStop = (1 << 2),
|
||||
WorkerEvtCdcRx = (1 << 3),
|
||||
WorkerEvtTxStop = (1 << 3),
|
||||
WorkerEvtCdcRx = (1 << 4),
|
||||
} WorkerEvtFlags;
|
||||
|
||||
#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
|
||||
@ -75,7 +76,7 @@ static int32_t usb_uart_worker(void* context) {
|
||||
usb_uart->usb_mutex = osMutexNew(NULL);
|
||||
|
||||
usb_uart->tx_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(usb_uart->tx_thread, "usb_uart_tx");
|
||||
furi_thread_set_name(usb_uart->tx_thread, "UsbUartTxWorker");
|
||||
furi_thread_set_stack_size(usb_uart->tx_thread, 512);
|
||||
furi_thread_set_context(usb_uart->tx_thread, NULL);
|
||||
furi_thread_set_callback(usb_uart->tx_thread, usb_uart_tx_thread);
|
||||
@ -191,7 +192,7 @@ void usb_uart_enable(UsbUartConfig* cfg) {
|
||||
usb_uart = furi_alloc(sizeof(UsbUartParams));
|
||||
|
||||
usb_uart->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(usb_uart->thread, "usb_uart");
|
||||
furi_thread_set_name(usb_uart->thread, "UsbUartWorker");
|
||||
furi_thread_set_stack_size(usb_uart->thread, 1024);
|
||||
furi_thread_set_context(usb_uart->thread, cfg);
|
||||
furi_thread_set_callback(usb_uart->thread, usb_uart_worker);
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include "gui_i.h"
|
||||
|
||||
#define TAG "GuiSrv"
|
||||
|
||||
ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) {
|
||||
// Iterating backward
|
||||
ViewPortArray_it_t it;
|
||||
@ -190,7 +192,7 @@ void gui_input(Gui* gui, InputEvent* input_event) {
|
||||
gui->ongoing_input |= key_bit;
|
||||
} else if(!(gui->ongoing_input & key_bit)) {
|
||||
FURI_LOG_D(
|
||||
"Gui",
|
||||
TAG,
|
||||
"non-complementary input, discarding key: %s type: %s, sequence: %p",
|
||||
input_get_key_name(input_event->key),
|
||||
input_get_type_name(input_event->type),
|
||||
@ -212,7 +214,7 @@ void gui_input(Gui* gui, InputEvent* input_event) {
|
||||
view_port_input(view_port, input_event);
|
||||
} else if(gui->ongoing_input_view_port && input_event->type == InputTypeRelease) {
|
||||
FURI_LOG_D(
|
||||
"Gui",
|
||||
TAG,
|
||||
"ViewPort changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port",
|
||||
gui->ongoing_input_view_port,
|
||||
view_port,
|
||||
@ -222,7 +224,7 @@ void gui_input(Gui* gui, InputEvent* input_event) {
|
||||
view_port_input(gui->ongoing_input_view_port, input_event);
|
||||
} else {
|
||||
FURI_LOG_D(
|
||||
"Gui",
|
||||
TAG,
|
||||
"ViewPort changed while key press %p -> %p. Discarding key: %s, type: %s, sequence: %p",
|
||||
gui->ongoing_input_view_port,
|
||||
view_port,
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include "view_dispatcher_i.h"
|
||||
|
||||
#define TAG "ViewDispatcher"
|
||||
|
||||
ViewDispatcher* view_dispatcher_alloc() {
|
||||
ViewDispatcher* view_dispatcher = furi_alloc(sizeof(ViewDispatcher));
|
||||
|
||||
@ -237,7 +239,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
|
||||
view_dispatcher->ongoing_input &= ~key_bit;
|
||||
} else if(!(view_dispatcher->ongoing_input & key_bit)) {
|
||||
FURI_LOG_D(
|
||||
"ViewDispatcher",
|
||||
TAG,
|
||||
"non-complementary input, discarding key: %s, type: %s, sequence: %p",
|
||||
input_get_key_name(event->key),
|
||||
input_get_type_name(event->type),
|
||||
@ -276,7 +278,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
|
||||
}
|
||||
} else if(view_dispatcher->ongoing_input_view && event->type == InputTypeRelease) {
|
||||
FURI_LOG_D(
|
||||
"ViewDispatcher",
|
||||
TAG,
|
||||
"View changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port",
|
||||
view_dispatcher->ongoing_input_view,
|
||||
view_dispatcher->current_view,
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#include <furi-hal-irda.h>
|
||||
#include <file-worker-cpp.h>
|
||||
|
||||
#define TAG "IrdaFileParser"
|
||||
|
||||
bool IrdaAppFileParser::open_irda_file_read(const char* name) {
|
||||
std::string full_filename;
|
||||
if(name[0] != '/')
|
||||
@ -154,11 +156,7 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
|
||||
if(!irda_is_protocol_valid((IrdaProtocol)protocol)) {
|
||||
size_t end_of_str = MIN(str.find_last_not_of(" \t\r\n") + 1, (size_t)30);
|
||||
FURI_LOG_E(
|
||||
"IrdaFileParser",
|
||||
"Unknown protocol(\'%.*s...\'): \'%s\'",
|
||||
end_of_str,
|
||||
str.c_str(),
|
||||
protocol_name);
|
||||
TAG, "Unknown protocol(\'%.*s...\'): \'%s\'", end_of_str, str.c_str(), protocol_name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -167,7 +165,7 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
|
||||
if(address != (address & address_mask)) {
|
||||
size_t end_of_str = MIN(str.find_last_not_of(" \t\r\n") + 1, (size_t)30);
|
||||
FURI_LOG_E(
|
||||
"IrdaFileParser",
|
||||
TAG,
|
||||
"Signal(\'%.*s...\'): address is too long (mask for this protocol is 0x%08X): 0x%X",
|
||||
end_of_str,
|
||||
str.c_str(),
|
||||
@ -181,7 +179,7 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
|
||||
if(command != (command & command_mask)) {
|
||||
size_t end_of_str = MIN(str.find_last_not_of(" \t\r\n") + 1, (size_t)30);
|
||||
FURI_LOG_E(
|
||||
"IrdaFileParser",
|
||||
TAG,
|
||||
"Signal(\'%.*s...\'): command is too long (mask for this protocol is 0x%08X): 0x%X",
|
||||
end_of_str,
|
||||
str.c_str(),
|
||||
@ -256,7 +254,7 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
|
||||
if((frequency < IRDA_MIN_FREQUENCY) || (frequency > IRDA_MAX_FREQUENCY)) {
|
||||
size_t end_of_str = MIN(string.find_last_not_of(" \t\r\n") + 1, (size_t)30);
|
||||
FURI_LOG_E(
|
||||
"IrdaFileParser",
|
||||
TAG,
|
||||
"RAW signal(\'%.*s...\'): frequency is out of bounds (%ld-%ld): %ld",
|
||||
end_of_str,
|
||||
string.c_str(),
|
||||
@ -269,7 +267,7 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
|
||||
if((duty_cycle == 0) || (duty_cycle > 100)) {
|
||||
size_t end_of_str = MIN(string.find_last_not_of(" \t\r\n") + 1, (size_t)30);
|
||||
FURI_LOG_E(
|
||||
"IrdaFileParser",
|
||||
TAG,
|
||||
"RAW signal(\'%.*s...\'): duty cycle is out of bounds (0-100): %ld",
|
||||
end_of_str,
|
||||
string.c_str(),
|
||||
@ -283,8 +281,7 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
|
||||
if(last_valid_ch != std::string_view::npos) {
|
||||
str.remove_suffix(str.size() - last_valid_ch - 1);
|
||||
} else {
|
||||
FURI_LOG_E(
|
||||
"IrdaFileParser", "RAW signal(\'%.*s\'): no timings", header_len, string.c_str());
|
||||
FURI_LOG_E(TAG, "RAW signal(\'%.*s\'): no timings", header_len, string.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -303,7 +300,7 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
|
||||
parsed = std::sscanf(str.data(), "%9s", buf);
|
||||
if(parsed != 1) {
|
||||
FURI_LOG_E(
|
||||
"IrdaFileParser",
|
||||
TAG,
|
||||
"RAW signal(\'%.*s...\'): failed on timing[%ld] \'%*s\'",
|
||||
header_len,
|
||||
string.c_str(),
|
||||
@ -318,7 +315,7 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
|
||||
int value = atoi(buf);
|
||||
if(value <= 0) {
|
||||
FURI_LOG_E(
|
||||
"IrdaFileParser",
|
||||
TAG,
|
||||
"RAW signal(\'%.*s...\'): failed on timing[%ld] \'%s\'",
|
||||
header_len,
|
||||
string.c_str(),
|
||||
@ -330,7 +327,7 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
|
||||
|
||||
if(raw_signal.timings_cnt >= max_raw_timings_in_signal) {
|
||||
FURI_LOG_E(
|
||||
"IrdaFileParser",
|
||||
TAG,
|
||||
"RAW signal(\'%.*s...\'): too much timings (max %ld)",
|
||||
header_len,
|
||||
string.c_str(),
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#include "loader/loader.h"
|
||||
#include "loader_i.h"
|
||||
|
||||
#define TAG "LoaderSrv"
|
||||
|
||||
#define LOADER_THREAD_FLAG_SHOW_MENU (1 << 0)
|
||||
#define LOADER_THREAD_FLAG_ALL (LOADER_THREAD_FLAG_SHOW_MENU)
|
||||
|
||||
@ -15,15 +17,13 @@ static void loader_menu_callback(void* _ctx, uint32_t index) {
|
||||
if(!loader_lock(loader_instance)) return;
|
||||
|
||||
if(furi_thread_get_state(loader_instance->thread) != FuriThreadStateStopped) {
|
||||
FURI_LOG_E(
|
||||
LOADER_LOG_TAG, "Can't start app. %s is running", loader_instance->current_app->name);
|
||||
FURI_LOG_E(TAG, "Can't start app. %s is running", loader_instance->current_app->name);
|
||||
return;
|
||||
}
|
||||
furi_hal_power_insomnia_enter();
|
||||
loader_instance->current_app = flipper_app;
|
||||
|
||||
FURI_LOG_I(
|
||||
LOADER_LOG_TAG, "Starting furi application: %s", loader_instance->current_app->name);
|
||||
FURI_LOG_I(TAG, "Starting furi application: %s", loader_instance->current_app->name);
|
||||
furi_thread_set_name(loader_instance->thread, flipper_app->name);
|
||||
furi_thread_set_stack_size(loader_instance->thread, flipper_app->stack_size);
|
||||
furi_thread_set_context(loader_instance->thread, NULL);
|
||||
@ -79,14 +79,14 @@ LoaderStatus loader_start(Loader* instance, const char* name, const char* args)
|
||||
}
|
||||
|
||||
if(!flipper_app) {
|
||||
FURI_LOG_E(LOADER_LOG_TAG, "Can't find application with name %s", name);
|
||||
FURI_LOG_E(TAG, "Can't find application with name %s", name);
|
||||
return LoaderStatusErrorUnknownApp;
|
||||
}
|
||||
|
||||
bool locked = loader_lock(instance);
|
||||
|
||||
if(!locked || (furi_thread_get_state(instance->thread) != FuriThreadStateStopped)) {
|
||||
FURI_LOG_E(LOADER_LOG_TAG, "Can't start app. %s is running", instance->current_app->name);
|
||||
FURI_LOG_E(TAG, "Can't start app. %s is running", instance->current_app->name);
|
||||
/* no need to call loader_unlock() - it is called as soon as application stops */
|
||||
return LoaderStatusErrorAppStarted;
|
||||
}
|
||||
@ -97,10 +97,10 @@ LoaderStatus loader_start(Loader* instance, const char* name, const char* args)
|
||||
string_set_str(instance->args, args);
|
||||
string_strim(instance->args);
|
||||
thread_args = (void*)string_get_cstr(instance->args);
|
||||
FURI_LOG_I(LOADER_LOG_TAG, "Start %s app with args: %s", name, args);
|
||||
FURI_LOG_I(TAG, "Start %s app with args: %s", name, args);
|
||||
} else {
|
||||
string_clean(instance->args);
|
||||
FURI_LOG_I(LOADER_LOG_TAG, "Start %s app with no args", name);
|
||||
FURI_LOG_I(TAG, "Start %s app with no args", name);
|
||||
}
|
||||
|
||||
furi_thread_set_name(instance->thread, flipper_app->name);
|
||||
@ -155,7 +155,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con
|
||||
delay(20);
|
||||
int heap_diff = instance->free_heap_size - memmgr_get_free_heap();
|
||||
FURI_LOG_I(
|
||||
LOADER_LOG_TAG,
|
||||
TAG,
|
||||
"Application thread stopped. Heap allocation balance: %d. Thread allocation balance: %d.",
|
||||
heap_diff,
|
||||
furi_thread_get_heap_size(instance->thread));
|
||||
@ -266,7 +266,7 @@ static void loader_add_cli_command(FlipperApplication* app) {
|
||||
}
|
||||
|
||||
static void loader_build_menu() {
|
||||
FURI_LOG_I(LOADER_LOG_TAG, "Building main menu");
|
||||
FURI_LOG_I(TAG, "Building main menu");
|
||||
size_t i;
|
||||
for(i = 0; i < FLIPPER_APPS_COUNT; i++) {
|
||||
loader_add_cli_command((FlipperApplication*)&FLIPPER_APPS[i]);
|
||||
@ -300,7 +300,7 @@ static void loader_build_menu() {
|
||||
loader_submenu_callback,
|
||||
(void*)LoaderMenuViewSettings);
|
||||
|
||||
FURI_LOG_I(LOADER_LOG_TAG, "Building plugins menu");
|
||||
FURI_LOG_I(TAG, "Building plugins menu");
|
||||
for(i = 0; i < FLIPPER_PLUGINS_COUNT; i++) {
|
||||
loader_add_cli_command((FlipperApplication*)&FLIPPER_PLUGINS[i]);
|
||||
submenu_add_item(
|
||||
@ -311,7 +311,7 @@ static void loader_build_menu() {
|
||||
(void*)&FLIPPER_PLUGINS[i]);
|
||||
}
|
||||
|
||||
FURI_LOG_I(LOADER_LOG_TAG, "Building debug menu");
|
||||
FURI_LOG_I(TAG, "Building debug menu");
|
||||
for(i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) {
|
||||
loader_add_cli_command((FlipperApplication*)&FLIPPER_DEBUG_APPS[i]);
|
||||
submenu_add_item(
|
||||
@ -322,7 +322,7 @@ static void loader_build_menu() {
|
||||
(void*)&FLIPPER_DEBUG_APPS[i]);
|
||||
}
|
||||
|
||||
FURI_LOG_I(LOADER_LOG_TAG, "Building settings menu");
|
||||
FURI_LOG_I(TAG, "Building settings menu");
|
||||
for(i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) {
|
||||
submenu_add_item(
|
||||
loader_instance->settings_menu,
|
||||
@ -339,7 +339,7 @@ void loader_show_menu() {
|
||||
}
|
||||
|
||||
int32_t loader_srv(void* p) {
|
||||
FURI_LOG_I(LOADER_LOG_TAG, "Starting");
|
||||
FURI_LOG_I(TAG, "Starting");
|
||||
|
||||
loader_instance = loader_alloc();
|
||||
|
||||
@ -350,7 +350,7 @@ int32_t loader_srv(void* p) {
|
||||
FLIPPER_ON_SYSTEM_START[i]();
|
||||
}
|
||||
|
||||
FURI_LOG_I(LOADER_LOG_TAG, "Started");
|
||||
FURI_LOG_I(TAG, "Started");
|
||||
|
||||
furi_record_create("loader", loader_instance);
|
||||
|
||||
|
||||
@ -12,8 +12,6 @@
|
||||
#include <applications.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
#define LOADER_LOG_TAG "loader"
|
||||
|
||||
struct Loader {
|
||||
osThreadId_t loader_thread;
|
||||
FuriThread* thread;
|
||||
|
||||
@ -1,49 +1,80 @@
|
||||
#include "nfc_emv_parser.h"
|
||||
#include <lib/flipper_file/flipper_file.h>
|
||||
|
||||
#include <file-worker.h>
|
||||
static const char* nfc_resources_header = "Flipper EMV resources";
|
||||
static const uint32_t nfc_resources_file_version = 1;
|
||||
|
||||
static bool
|
||||
nfc_emv_parser_get_value(const char* file_path, string_t key, char delimiter, string_t value) {
|
||||
bool found = false;
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
static bool nfc_emv_parser_search_data(
|
||||
Storage* storage,
|
||||
const char* file_name,
|
||||
string_t key,
|
||||
string_t data) {
|
||||
bool parsed = false;
|
||||
FlipperFile* file = flipper_file_alloc(storage);
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
if(file_worker_open(file_worker, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
if(file_worker_get_value_from_key(file_worker, key, delimiter, value)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
do {
|
||||
// Open file
|
||||
if(!flipper_file_open_existing(file, file_name)) break;
|
||||
// Read file header and version
|
||||
uint32_t version = 0;
|
||||
if(!flipper_file_read_header(file, temp_str, &version)) break;
|
||||
if(string_cmp_str(temp_str, nfc_resources_header) ||
|
||||
(version != nfc_resources_file_version))
|
||||
break;
|
||||
if(!flipper_file_read_string(file, string_get_cstr(key), data)) break;
|
||||
parsed = true;
|
||||
} while(false);
|
||||
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
return found;
|
||||
string_clear(temp_str);
|
||||
flipper_file_free(file);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name) {
|
||||
bool result = false;
|
||||
bool nfc_emv_parser_get_aid_name(
|
||||
Storage* storage,
|
||||
uint8_t* aid,
|
||||
uint8_t aid_len,
|
||||
string_t aid_name) {
|
||||
furi_assert(storage);
|
||||
bool parsed = false;
|
||||
string_t key;
|
||||
string_init(key);
|
||||
for(uint8_t i = 0; i < aid_len; i++) {
|
||||
string_cat_printf(key, "%02X", aid[i]);
|
||||
}
|
||||
result = nfc_emv_parser_get_value("/ext/nfc/emv/aid.nfc", key, ' ', aid_name);
|
||||
if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/aid.nfc", key, aid_name)) {
|
||||
parsed = true;
|
||||
}
|
||||
string_clear(key);
|
||||
return result;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name) {
|
||||
bool result = false;
|
||||
bool nfc_emv_parser_get_country_name(
|
||||
Storage* storage,
|
||||
uint16_t country_code,
|
||||
string_t country_name) {
|
||||
bool parsed = false;
|
||||
string_t key;
|
||||
string_init_printf(key, "%04X", country_code);
|
||||
result = nfc_emv_parser_get_value("/ext/nfc/emv/country_code.nfc", key, ' ', country_name);
|
||||
if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/country_code.nfc", key, country_name)) {
|
||||
parsed = true;
|
||||
}
|
||||
string_clear(key);
|
||||
return result;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name) {
|
||||
bool result = false;
|
||||
bool nfc_emv_parser_get_currency_name(
|
||||
Storage* storage,
|
||||
uint16_t currency_code,
|
||||
string_t currency_name) {
|
||||
bool parsed = false;
|
||||
string_t key;
|
||||
string_init_printf(key, "%04X", currency_code);
|
||||
result = nfc_emv_parser_get_value("/ext/nfc/emv/currency_code.nfc", key, ' ', currency_name);
|
||||
if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/currency_code.nfc", key, currency_name)) {
|
||||
parsed = true;
|
||||
}
|
||||
string_clear(key);
|
||||
return result;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
@ -3,25 +3,39 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <m-string.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
/** Get EMV application name by number
|
||||
* @param storage Storage instance
|
||||
* @param aid - AID number array
|
||||
* @param aid_len - AID length
|
||||
* @param aid_name - string to keep AID name
|
||||
* @return - true if AID found, false otherwies
|
||||
*/
|
||||
bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name);
|
||||
bool nfc_emv_parser_get_aid_name(
|
||||
Storage* storage,
|
||||
uint8_t* aid,
|
||||
uint8_t aid_len,
|
||||
string_t aid_name);
|
||||
|
||||
/** Get country name by country code
|
||||
* @param storage Storage instance
|
||||
* @param country_code - ISO 3166 country code
|
||||
* @param country_name - string to keep country name
|
||||
* @return - true if country found, false otherwies
|
||||
*/
|
||||
bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name);
|
||||
bool nfc_emv_parser_get_country_name(
|
||||
Storage* storage,
|
||||
uint16_t country_code,
|
||||
string_t country_name);
|
||||
|
||||
/** Get currency name by currency code
|
||||
* @param storage Storage instance
|
||||
* @param currency_code - ISO 3166 currency code
|
||||
* @param currency_name - string to keep currency name
|
||||
* @return - true if currency found, false otherwies
|
||||
*/
|
||||
bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name);
|
||||
bool nfc_emv_parser_get_currency_name(
|
||||
Storage* storage,
|
||||
uint16_t currency_code,
|
||||
string_t currency_name);
|
||||
|
||||
@ -31,6 +31,9 @@ Nfc* nfc_alloc() {
|
||||
view_dispatcher_set_navigation_event_callback(nfc->view_dispatcher, nfc_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(nfc->view_dispatcher, nfc_tick_event_callback, 100);
|
||||
|
||||
// Nfc device
|
||||
nfc->dev = nfc_device_alloc();
|
||||
|
||||
// Open GUI record
|
||||
nfc->gui = furi_record_open("gui");
|
||||
view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen);
|
||||
@ -82,6 +85,9 @@ Nfc* nfc_alloc() {
|
||||
void nfc_free(Nfc* nfc) {
|
||||
furi_assert(nfc);
|
||||
|
||||
// Nfc device
|
||||
nfc_device_free(nfc->dev);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
submenu_free(nfc->submenu);
|
||||
@ -154,8 +160,12 @@ int32_t nfc_app(void* p) {
|
||||
char* args = p;
|
||||
|
||||
// Check argument and run corresponding scene
|
||||
if((*args != '\0') && nfc_device_load(&nfc->dev, p)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
if((*args != '\0') && nfc_device_load(nfc->dev, p)) {
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
}
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneStart);
|
||||
}
|
||||
|
||||
@ -1,45 +1,38 @@
|
||||
#include "nfc_device_i.h"
|
||||
#include "nfc_device.h"
|
||||
|
||||
#include <file-worker.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <lib/toolbox/hex.h>
|
||||
|
||||
#define NFC_DEVICE_MAX_DATA_LEN 14
|
||||
#include <lib/flipper_file/flipper_file.h>
|
||||
|
||||
static const char* nfc_app_folder = "/any/nfc";
|
||||
static const char* nfc_app_extension = ".nfc";
|
||||
static const char* nfc_app_shadow_extension = ".shd";
|
||||
static const char* nfc_file_header = "Flipper NFC device";
|
||||
static const uint32_t nfc_file_version = 2;
|
||||
|
||||
static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len, uint8_t delim_len) {
|
||||
string_strim(str);
|
||||
uint8_t nibble_high = 0;
|
||||
uint8_t nibble_low = 0;
|
||||
bool parsed = true;
|
||||
|
||||
for(uint16_t i = 0; i < len; i++) {
|
||||
if(hex_char_to_hex_nibble(string_get_char(str, 0), &nibble_high) &&
|
||||
hex_char_to_hex_nibble(string_get_char(str, 1), &nibble_low)) {
|
||||
buff[i] = (nibble_high << 4) | nibble_low;
|
||||
string_right(str, delim_len + 2);
|
||||
} else {
|
||||
parsed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return parsed;
|
||||
NfcDevice* nfc_device_alloc() {
|
||||
NfcDevice* nfc_dev = furi_alloc(sizeof(NfcDevice));
|
||||
nfc_dev->storage = furi_record_open("storage");
|
||||
nfc_dev->dialogs = furi_record_open("dialogs");
|
||||
return nfc_dev;
|
||||
}
|
||||
|
||||
uint16_t nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) {
|
||||
void nfc_device_free(NfcDevice* nfc_dev) {
|
||||
furi_assert(nfc_dev);
|
||||
furi_record_close("storage");
|
||||
furi_record_close("dialogs");
|
||||
free(nfc_dev);
|
||||
}
|
||||
|
||||
void nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) {
|
||||
if(dev->format == NfcDeviceSaveFormatUid) {
|
||||
string_set_str(format_string, "UID\n");
|
||||
string_set_str(format_string, "UID");
|
||||
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
string_set_str(format_string, "Bank card\n");
|
||||
string_set_str(format_string, "Bank card");
|
||||
} else if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
string_set_str(format_string, "Mifare Ultralight\n");
|
||||
string_set_str(format_string, "Mifare Ultralight");
|
||||
} else {
|
||||
string_set_str(format_string, "Unknown\n");
|
||||
string_set_str(format_string, "Unknown");
|
||||
}
|
||||
return string_size(format_string);
|
||||
}
|
||||
|
||||
bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) {
|
||||
@ -59,228 +52,166 @@ bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string) {
|
||||
NfcDeviceCommonData* uid_data = &dev->dev_data.nfc_data;
|
||||
string_printf(uid_string, "UID len: %02X UID: ", dev->dev_data.nfc_data.uid_len);
|
||||
for(uint8_t i = 0; i < uid_data->uid_len; i++) {
|
||||
string_cat_printf(uid_string, "%02X ", uid_data->uid[i]);
|
||||
}
|
||||
string_cat_printf(
|
||||
uid_string,
|
||||
"ATQA: %02X %02X SAK: %02X\n",
|
||||
uid_data->atqa[0],
|
||||
uid_data->atqa[1],
|
||||
uid_data->sak);
|
||||
return string_size(uid_string);
|
||||
}
|
||||
|
||||
bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string) {
|
||||
NfcDeviceCommonData* uid_data = &dev->dev_data.nfc_data;
|
||||
bool parsed = false;
|
||||
|
||||
do {
|
||||
// strlen("UID len: ") = 9
|
||||
string_right(uid_string, 9);
|
||||
if(!nfc_device_read_hex(uid_string, &uid_data->uid_len, 1, 1)) {
|
||||
break;
|
||||
}
|
||||
// strlen("UID: ") = 5
|
||||
string_right(uid_string, 5);
|
||||
if(!nfc_device_read_hex(uid_string, uid_data->uid, uid_data->uid_len, 1)) {
|
||||
break;
|
||||
}
|
||||
// strlen("ATQA: ") = 6
|
||||
string_right(uid_string, 6);
|
||||
if(!nfc_device_read_hex(uid_string, uid_data->atqa, 2, 1)) {
|
||||
break;
|
||||
}
|
||||
// strlen("SAK: ") = 5
|
||||
string_right(uid_string, 5);
|
||||
if(!nfc_device_read_hex(uid_string, &uid_data->sak, 1, 1)) {
|
||||
break;
|
||||
}
|
||||
parsed = true;
|
||||
} while(0);
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
uint16_t nfc_device_prepare_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string) {
|
||||
static bool nfc_device_save_mifare_ul_data(FlipperFile* file, NfcDevice* dev) {
|
||||
bool saved = false;
|
||||
MifareUlData* data = &dev->dev_data.mf_ul_data;
|
||||
string_printf(mifare_ul_string, "Signature:");
|
||||
for(uint8_t i = 0; i < sizeof(data->signature); i++) {
|
||||
string_cat_printf(mifare_ul_string, " %02X", data->signature[i]);
|
||||
}
|
||||
string_cat_printf(mifare_ul_string, "\nVersion:");
|
||||
uint8_t* version = (uint8_t*)&data->version;
|
||||
for(uint8_t i = 0; i < sizeof(data->version); i++) {
|
||||
string_cat_printf(mifare_ul_string, " %02X", version[i]);
|
||||
}
|
||||
for(uint8_t i = 0; i < 3; i++) {
|
||||
string_cat_printf(
|
||||
mifare_ul_string,
|
||||
"\nCounter %d: %lu Tearing flag %d: %02X",
|
||||
i,
|
||||
data->counter[i],
|
||||
i,
|
||||
data->tearing[i]);
|
||||
}
|
||||
string_cat_printf(mifare_ul_string, "\nData size: %d\n", data->data_size);
|
||||
for(uint16_t i = 0; i < data->data_size; i += 4) {
|
||||
string_cat_printf(
|
||||
mifare_ul_string,
|
||||
"%02X %02X %02X %02X\n",
|
||||
data->data[i],
|
||||
data->data[i + 1],
|
||||
data->data[i + 2],
|
||||
data->data[i + 3]);
|
||||
}
|
||||
return string_size(mifare_ul_string);
|
||||
}
|
||||
|
||||
bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string) {
|
||||
MifareUlData* data = &dev->dev_data.mf_ul_data;
|
||||
uint16_t tearing_tmp = 0;
|
||||
uint16_t cnt_num = 0;
|
||||
size_t ws = 0;
|
||||
int res = 0;
|
||||
bool parsed = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
// Save Mifare Ultralight specific data
|
||||
do {
|
||||
// strlen("Signature: ") = 11
|
||||
string_right(mifare_ul_string, 11);
|
||||
if(!nfc_device_read_hex(mifare_ul_string, data->signature, sizeof(data->signature), 1)) {
|
||||
if(!flipper_file_write_comment_cstr(file, "Mifare Ultralight specific data")) break;
|
||||
if(!flipper_file_write_hex(file, "Signature", data->signature, sizeof(data->signature)))
|
||||
break;
|
||||
}
|
||||
// strlen("Version: ") = 9
|
||||
string_right(mifare_ul_string, 9);
|
||||
if(!nfc_device_read_hex(
|
||||
mifare_ul_string, (uint8_t*)&data->version, sizeof(data->version), 1)) {
|
||||
if(!flipper_file_write_hex(
|
||||
file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version)))
|
||||
break;
|
||||
}
|
||||
string_strim(mifare_ul_string);
|
||||
// Read counters and tearing flags
|
||||
// Write conters and tearing flags data
|
||||
bool counters_saved = true;
|
||||
for(uint8_t i = 0; i < 3; i++) {
|
||||
res = sscanf(
|
||||
string_get_cstr(mifare_ul_string),
|
||||
"Counter %hX: %lu Tearing flag %hX: %02hX",
|
||||
&cnt_num,
|
||||
&data->counter[i],
|
||||
&cnt_num,
|
||||
&tearing_tmp);
|
||||
if(res != 4) {
|
||||
string_printf(temp_str, "Counter %d", i);
|
||||
if(!flipper_file_write_uint32(file, string_get_cstr(temp_str), &data->counter[i], 1)) {
|
||||
counters_saved = false;
|
||||
break;
|
||||
}
|
||||
string_printf(temp_str, "Tearing %d", i);
|
||||
if(!flipper_file_write_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) {
|
||||
counters_saved = false;
|
||||
break;
|
||||
}
|
||||
data->tearing[i] = tearing_tmp;
|
||||
ws = string_search_char(mifare_ul_string, '\n');
|
||||
string_right(mifare_ul_string, ws + 1);
|
||||
}
|
||||
// Read data size
|
||||
res = sscanf(string_get_cstr(mifare_ul_string), "Data size: %hu", &data->data_size);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
ws = string_search_char(mifare_ul_string, '\n');
|
||||
string_right(mifare_ul_string, ws + 1);
|
||||
// Read data
|
||||
if(!counters_saved) break;
|
||||
// Write pages data
|
||||
uint32_t pages_total = data->data_size / 4;
|
||||
if(!flipper_file_write_uint32(file, "Pages total", &pages_total, 1)) break;
|
||||
bool pages_saved = true;
|
||||
for(uint16_t i = 0; i < data->data_size; i += 4) {
|
||||
if(!nfc_device_read_hex(mifare_ul_string, &data->data[i], 4, 1)) {
|
||||
string_printf(temp_str, "Page %d", i / 4);
|
||||
if(!flipper_file_write_hex(file, string_get_cstr(temp_str), &data->data[i], 4)) {
|
||||
pages_saved = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
parsed = true;
|
||||
} while(0);
|
||||
if(!pages_saved) break;
|
||||
saved = true;
|
||||
} while(false);
|
||||
|
||||
string_clear(temp_str);
|
||||
return saved;
|
||||
}
|
||||
|
||||
bool nfc_device_load_mifare_ul_data(FlipperFile* file, NfcDevice* dev) {
|
||||
bool parsed = false;
|
||||
MifareUlData* data = &dev->dev_data.mf_ul_data;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
do {
|
||||
// Read signature
|
||||
if(!flipper_file_read_hex(file, "Signature", data->signature, sizeof(data->signature)))
|
||||
break;
|
||||
// Read Mifare version
|
||||
if(!flipper_file_read_hex(
|
||||
file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version)))
|
||||
break;
|
||||
// Read counters and tearing flags
|
||||
bool counters_parsed = true;
|
||||
for(uint8_t i = 0; i < 3; i++) {
|
||||
string_printf(temp_str, "Counter %d", i);
|
||||
if(!flipper_file_read_uint32(file, string_get_cstr(temp_str), &data->counter[i], 1)) {
|
||||
counters_parsed = false;
|
||||
break;
|
||||
}
|
||||
string_printf(temp_str, "Tearing %d", i);
|
||||
if(!flipper_file_read_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) {
|
||||
counters_parsed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!counters_parsed) break;
|
||||
// Read pages
|
||||
uint32_t pages = 0;
|
||||
if(!flipper_file_read_uint32(file, "Pages total", &pages, 1)) break;
|
||||
data->data_size = pages * 4;
|
||||
bool pages_parsed = true;
|
||||
for(uint16_t i = 0; i < pages; i++) {
|
||||
string_printf(temp_str, "Page %d", i);
|
||||
if(!flipper_file_read_hex(file, string_get_cstr(temp_str), &data->data[i * 4], 4)) {
|
||||
pages_parsed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!pages_parsed) break;
|
||||
parsed = true;
|
||||
} while(false);
|
||||
|
||||
string_clear(temp_str);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_string) {
|
||||
static bool nfc_device_save_bank_card_data(FlipperFile* file, NfcDevice* dev) {
|
||||
bool saved = false;
|
||||
NfcEmvData* data = &dev->dev_data.emv_data;
|
||||
string_printf(bank_card_string, "AID len: %d, AID:", data->aid_len);
|
||||
for(uint8_t i = 0; i < data->aid_len; i++) {
|
||||
string_cat_printf(bank_card_string, " %02X", data->aid[i]);
|
||||
}
|
||||
string_cat_printf(
|
||||
bank_card_string, "\nName: %s\nNumber len: %d\nNumber:", data->name, data->number_len);
|
||||
for(uint8_t i = 0; i < data->number_len; i++) {
|
||||
string_cat_printf(bank_card_string, " %02X", data->number[i]);
|
||||
}
|
||||
if(data->exp_mon) {
|
||||
string_cat_printf(
|
||||
bank_card_string, "\nExp date: %02X/%02X", data->exp_mon, data->exp_year);
|
||||
}
|
||||
if(data->country_code) {
|
||||
string_cat_printf(bank_card_string, "\nCountry code: %04X", data->country_code);
|
||||
}
|
||||
if(data->currency_code) {
|
||||
string_cat_printf(bank_card_string, "\nCurrency code: %04X", data->currency_code);
|
||||
}
|
||||
return string_size(bank_card_string);
|
||||
}
|
||||
|
||||
bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string) {
|
||||
NfcEmvData* data = &dev->dev_data.emv_data;
|
||||
bool parsed = false;
|
||||
int res = 0;
|
||||
uint8_t code[2] = {};
|
||||
memset(data, 0, sizeof(NfcEmvData));
|
||||
uint32_t data_temp = 0;
|
||||
|
||||
do {
|
||||
res = sscanf(string_get_cstr(bank_card_string), "AID len: %hu", &data->aid_len);
|
||||
if(res != 1) {
|
||||
break;
|
||||
// Write Bank card specific data
|
||||
if(!flipper_file_write_comment_cstr(file, "Bank card specific data")) break;
|
||||
if(!flipper_file_write_hex(file, "AID", data->aid, data->aid_len)) break;
|
||||
if(!flipper_file_write_string_cstr(file, "Name", data->name)) break;
|
||||
if(!flipper_file_write_hex(file, "Number", data->number, data->number_len)) break;
|
||||
if(data->exp_mon) {
|
||||
uint8_t exp_data[2] = {data->exp_mon, data->exp_year};
|
||||
if(!flipper_file_write_hex(file, "Exp data", exp_data, sizeof(exp_data))) break;
|
||||
}
|
||||
// strlen("AID len: ") = 9
|
||||
string_right(bank_card_string, 9);
|
||||
size_t ws = string_search_char(bank_card_string, ':');
|
||||
string_right(bank_card_string, ws + 1);
|
||||
if(!nfc_device_read_hex(bank_card_string, data->aid, data->aid_len, 1)) {
|
||||
break;
|
||||
if(data->country_code) {
|
||||
data_temp = data->country_code;
|
||||
if(!flipper_file_write_uint32(file, "Country code", &data_temp, 1)) break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(bank_card_string), "Name: %s\n", data->name);
|
||||
if(res != 1) {
|
||||
break;
|
||||
if(data->currency_code) {
|
||||
data_temp = data->currency_code;
|
||||
if(!flipper_file_write_uint32(file, "Currency code", &data_temp, 1)) break;
|
||||
}
|
||||
ws = string_search_char(bank_card_string, '\n');
|
||||
string_right(bank_card_string, ws + 1);
|
||||
res = sscanf(string_get_cstr(bank_card_string), "Number len: %hhu", &data->number_len);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
ws = string_search_char(bank_card_string, '\n');
|
||||
string_right(bank_card_string, ws + 1);
|
||||
// strlen("Number: ") = 8
|
||||
string_right(bank_card_string, 8);
|
||||
if(!nfc_device_read_hex(bank_card_string, data->number, data->number_len, 1)) {
|
||||
break;
|
||||
}
|
||||
parsed = true;
|
||||
// Check expiration date presence
|
||||
ws = string_search_str(bank_card_string, "Exp date: ");
|
||||
if(ws != STRING_FAILURE) {
|
||||
// strlen("Exp date: ") = 10
|
||||
string_right(bank_card_string, 10);
|
||||
nfc_device_read_hex(bank_card_string, &data->exp_mon, 1, 1);
|
||||
nfc_device_read_hex(bank_card_string, &data->exp_year, 1, 1);
|
||||
}
|
||||
// Check country code presence
|
||||
ws = string_search_str(bank_card_string, "Country code: ");
|
||||
if(ws != STRING_FAILURE) {
|
||||
// strlen("Country code: ") = 14
|
||||
string_right(bank_card_string, 14);
|
||||
nfc_device_read_hex(bank_card_string, code, 2, 0);
|
||||
data->country_code = code[0] << 8 | code[1];
|
||||
}
|
||||
// Check currency code presence
|
||||
ws = string_search_str(bank_card_string, "Currency code: ");
|
||||
if(ws != STRING_FAILURE) {
|
||||
// strlen("Currency code: ") = 15
|
||||
string_right(bank_card_string, 15);
|
||||
nfc_device_read_hex(bank_card_string, code, 2, 0);
|
||||
data->currency_code = code[0] << 8 | code[1];
|
||||
}
|
||||
} while(0);
|
||||
saved = true;
|
||||
} while(false);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
bool nfc_device_load_bank_card_data(FlipperFile* file, NfcDevice* dev) {
|
||||
bool parsed = false;
|
||||
NfcEmvData* data = &dev->dev_data.emv_data;
|
||||
memset(data, 0, sizeof(NfcEmvData));
|
||||
uint32_t data_cnt = 0;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
|
||||
do {
|
||||
// Load essential data
|
||||
if(!flipper_file_get_value_count(file, "AID", &data_cnt)) break;
|
||||
data->aid_len = data_cnt;
|
||||
if(!flipper_file_read_hex(file, "AID", data->aid, data->aid_len)) break;
|
||||
if(!flipper_file_read_string(file, "Name", temp_str)) break;
|
||||
strlcpy(data->name, string_get_cstr(temp_str), sizeof(data->name));
|
||||
if(!flipper_file_get_value_count(file, "Number", &data_cnt)) break;
|
||||
data->number_len = data_cnt;
|
||||
if(!flipper_file_read_hex(file, "Number", data->number, data->number_len)) break;
|
||||
parsed = true;
|
||||
// Load optional data
|
||||
uint8_t exp_data[2] = {};
|
||||
if(flipper_file_read_hex(file, "Exp data", exp_data, 2)) {
|
||||
data->exp_mon = exp_data[0];
|
||||
data->exp_year = exp_data[1];
|
||||
}
|
||||
if(flipper_file_read_uint32(file, "Country code", &data_cnt, 1)) {
|
||||
data->country_code = data_cnt;
|
||||
}
|
||||
if(flipper_file_read_uint32(file, "Currency code", &data_cnt, 1)) {
|
||||
data->currency_code = data_cnt;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
string_clear(temp_str);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
@ -297,58 +228,49 @@ static bool nfc_device_save_file(
|
||||
const char* extension) {
|
||||
furi_assert(dev);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
string_t dev_file_name;
|
||||
string_init(dev_file_name);
|
||||
bool saved = false;
|
||||
FlipperFile* file = flipper_file_alloc(dev->storage);
|
||||
NfcDeviceCommonData* data = &dev->dev_data.nfc_data;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
uint16_t string_len = 0;
|
||||
|
||||
do {
|
||||
// Create nfc directory if necessary
|
||||
if(!file_worker_mkdir(file_worker, nfc_app_folder)) {
|
||||
break;
|
||||
};
|
||||
if(!storage_simply_mkdir(dev->storage, nfc_app_folder)) break;
|
||||
// First remove nfc device file if it was saved
|
||||
string_printf(dev_file_name, "%s/%s%s", folder, dev_name, extension);
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) {
|
||||
break;
|
||||
};
|
||||
string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
|
||||
// Open file
|
||||
if(!file_worker_open(
|
||||
file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
||||
if(!flipper_file_open_always(file, string_get_cstr(temp_str))) break;
|
||||
// Write header
|
||||
if(!flipper_file_write_header_cstr(file, nfc_file_header, nfc_file_version)) break;
|
||||
// Write nfc device type
|
||||
if(!flipper_file_write_comment_cstr(
|
||||
file, "Nfc device type can be UID, Mifare Ultralight, Bank card"))
|
||||
break;
|
||||
}
|
||||
// Prepare and write format name on 1st line
|
||||
string_len = nfc_device_prepare_format_string(dev, temp_str);
|
||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
|
||||
nfc_device_prepare_format_string(dev, temp_str);
|
||||
if(!flipper_file_write_string(file, "Device type", temp_str)) break;
|
||||
// Write UID, ATQA, SAK
|
||||
if(!flipper_file_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats"))
|
||||
break;
|
||||
}
|
||||
// Prepare and write UID data on 2nd line
|
||||
string_len = nfc_device_prepare_uid_string(dev, temp_str);
|
||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
|
||||
break;
|
||||
}
|
||||
if(!flipper_file_write_hex(file, "UID", data->uid, data->uid_len)) break;
|
||||
if(!flipper_file_write_hex(file, "ATQA", data->atqa, 2)) break;
|
||||
if(!flipper_file_write_hex(file, "SAK", &data->sak, 1)) break;
|
||||
// Save more data if necessary
|
||||
if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
string_len = nfc_device_prepare_mifare_ul_string(dev, temp_str);
|
||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
|
||||
break;
|
||||
}
|
||||
if(!nfc_device_save_mifare_ul_data(file, dev)) break;
|
||||
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
string_len = nfc_device_prepare_bank_card_string(dev, temp_str);
|
||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) {
|
||||
break;
|
||||
}
|
||||
if(!nfc_device_save_bank_card_data(file, dev)) break;
|
||||
}
|
||||
saved = true;
|
||||
} while(0);
|
||||
|
||||
if(!saved) {
|
||||
dialog_message_show_storage_error(dev->dialogs, "Can not save\nkey file");
|
||||
}
|
||||
string_clear(temp_str);
|
||||
string_clear(dev_file_name);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
|
||||
return true;
|
||||
flipper_file_close(file);
|
||||
flipper_file_free(file);
|
||||
return saved;
|
||||
}
|
||||
|
||||
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
||||
@ -360,73 +282,64 @@ bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) {
|
||||
return nfc_device_save_file(dev, dev_name, nfc_app_folder, nfc_app_shadow_extension);
|
||||
}
|
||||
|
||||
static bool nfc_device_load_data(FileWorker* file_worker, string_t path, NfcDevice* dev) {
|
||||
string_t temp_string;
|
||||
string_init(temp_string);
|
||||
static bool nfc_device_load_data(NfcDevice* dev, string_t path) {
|
||||
bool parsed = false;
|
||||
FlipperFile* file = flipper_file_alloc(dev->storage);
|
||||
NfcDeviceCommonData* data = &dev->dev_data.nfc_data;
|
||||
uint32_t data_cnt = 0;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
bool depricated_version = false;
|
||||
|
||||
do {
|
||||
// Check existance of shadow file
|
||||
size_t ext_start = string_search_str(path, nfc_app_extension);
|
||||
string_set_n(temp_string, path, 0, ext_start);
|
||||
string_cat_printf(temp_string, "%s", nfc_app_shadow_extension);
|
||||
if(!file_worker_is_file_exist(
|
||||
file_worker, string_get_cstr(temp_string), &dev->shadow_file_exist)) {
|
||||
break;
|
||||
}
|
||||
string_set_n(temp_str, path, 0, ext_start);
|
||||
string_cat_printf(temp_str, "%s", nfc_app_shadow_extension);
|
||||
dev->shadow_file_exist =
|
||||
storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK;
|
||||
// Open shadow file if it exists. If not - open original
|
||||
if(dev->shadow_file_exist) {
|
||||
if(!file_worker_open(
|
||||
file_worker, string_get_cstr(temp_string), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
break;
|
||||
}
|
||||
if(!flipper_file_open_existing(file, string_get_cstr(temp_str))) break;
|
||||
} else {
|
||||
if(!file_worker_open(
|
||||
file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
break;
|
||||
}
|
||||
if(!flipper_file_open_existing(file, string_get_cstr(path))) break;
|
||||
}
|
||||
|
||||
// Read and parse format from 1st line
|
||||
if(!file_worker_read_until(file_worker, temp_string, '\n')) {
|
||||
break;
|
||||
}
|
||||
if(!nfc_device_parse_format_string(dev, temp_string)) {
|
||||
break;
|
||||
}
|
||||
// Read and parse UID data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_string, '\n')) {
|
||||
break;
|
||||
}
|
||||
if(!nfc_device_parse_uid_string(dev, temp_string)) {
|
||||
// Read and verify file header
|
||||
uint32_t version = 0;
|
||||
if(!flipper_file_read_header(file, temp_str, &version)) break;
|
||||
if(string_cmp_str(temp_str, nfc_file_header) || (version != nfc_file_version)) {
|
||||
depricated_version = true;
|
||||
break;
|
||||
}
|
||||
// Read Nfc device type
|
||||
if(!flipper_file_read_string(file, "Device type", temp_str)) break;
|
||||
if(!nfc_device_parse_format_string(dev, temp_str)) break;
|
||||
// Read and parse UID, ATQA and SAK
|
||||
if(!flipper_file_get_value_count(file, "UID", &data_cnt)) break;
|
||||
data->uid_len = data_cnt;
|
||||
if(!flipper_file_read_hex(file, "UID", data->uid, data->uid_len)) break;
|
||||
if(!flipper_file_read_hex(file, "ATQA", data->atqa, 2)) break;
|
||||
if(!flipper_file_read_hex(file, "SAK", &data->sak, 1)) break;
|
||||
// Parse other data
|
||||
if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
// Read until EOF
|
||||
if(!file_worker_read_until(file_worker, temp_string, 0x05)) {
|
||||
break;
|
||||
}
|
||||
if(!nfc_device_parse_mifare_ul_string(dev, temp_string)) {
|
||||
break;
|
||||
}
|
||||
if(!nfc_device_load_mifare_ul_data(file, dev)) break;
|
||||
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
// Read until EOF
|
||||
if(!file_worker_read_until(file_worker, temp_string, 0x05)) {
|
||||
break;
|
||||
}
|
||||
if(!nfc_device_parse_bank_card_string(dev, temp_string)) {
|
||||
break;
|
||||
}
|
||||
if(!nfc_device_load_bank_card_data(file, dev)) break;
|
||||
}
|
||||
parsed = true;
|
||||
} while(0);
|
||||
} while(false);
|
||||
|
||||
if(!parsed) {
|
||||
file_worker_show_error(file_worker, "Can not parse\nfile");
|
||||
if(depricated_version) {
|
||||
dialog_message_show_storage_error(dev->dialogs, "File format depricated");
|
||||
} else {
|
||||
dialog_message_show_storage_error(dev->dialogs, "Can not parse\nfile");
|
||||
}
|
||||
}
|
||||
|
||||
string_clear(temp_string);
|
||||
string_clear(temp_str);
|
||||
flipper_file_close(file);
|
||||
flipper_file_free(file);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
@ -434,19 +347,16 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
|
||||
furi_assert(dev);
|
||||
furi_assert(file_path);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
// Load device data
|
||||
string_t path;
|
||||
string_init_set_str(path, file_path);
|
||||
bool dev_load = nfc_device_load_data(file_worker, path, dev);
|
||||
bool dev_load = nfc_device_load_data(dev, path);
|
||||
if(dev_load) {
|
||||
// Set device name
|
||||
path_extract_filename_no_ext(file_path, path);
|
||||
nfc_device_set_name(dev, string_get_cstr(path));
|
||||
}
|
||||
string_clear(path);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
|
||||
return dev_load;
|
||||
}
|
||||
@ -454,10 +364,9 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
|
||||
bool nfc_file_select(NfcDevice* dev) {
|
||||
furi_assert(dev);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
// Input events and views are managed by file_select
|
||||
bool res = file_worker_file_select(
|
||||
file_worker,
|
||||
bool res = dialog_file_select_show(
|
||||
dev->dialogs,
|
||||
nfc_app_folder,
|
||||
nfc_app_extension,
|
||||
dev->file_name,
|
||||
@ -465,18 +374,14 @@ bool nfc_file_select(NfcDevice* dev) {
|
||||
dev->dev_name);
|
||||
if(res) {
|
||||
string_t dev_str;
|
||||
|
||||
// Get key file path
|
||||
string_init_printf(dev_str, "%s/%s%s", nfc_app_folder, dev->file_name, nfc_app_extension);
|
||||
|
||||
res = nfc_device_load_data(file_worker, dev_str, dev);
|
||||
res = nfc_device_load_data(dev, dev_str);
|
||||
if(res) {
|
||||
nfc_device_set_name(dev, dev->file_name);
|
||||
}
|
||||
string_clear(dev_str);
|
||||
}
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -491,61 +396,48 @@ void nfc_device_clear(NfcDevice* dev) {
|
||||
bool nfc_device_delete(NfcDevice* dev) {
|
||||
furi_assert(dev);
|
||||
|
||||
bool result = true;
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
bool deleted = false;
|
||||
string_t file_path;
|
||||
string_init(file_path);
|
||||
|
||||
do {
|
||||
// Delete original file
|
||||
string_init_printf(file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(file_path))) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break;
|
||||
// Delete shadow file if it exists
|
||||
if(dev->shadow_file_exist) {
|
||||
string_clean(file_path);
|
||||
string_printf(
|
||||
file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension);
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(file_path))) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break;
|
||||
}
|
||||
deleted = true;
|
||||
} while(0);
|
||||
|
||||
if(!deleted) {
|
||||
dialog_message_show_storage_error(dev->dialogs, "Can not remove file");
|
||||
}
|
||||
|
||||
string_clear(file_path);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
return result;
|
||||
return deleted;
|
||||
}
|
||||
|
||||
bool nfc_device_restore(NfcDevice* dev) {
|
||||
furi_assert(dev);
|
||||
furi_assert(dev->shadow_file_exist);
|
||||
|
||||
bool result = true;
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
bool restored = false;
|
||||
string_t path;
|
||||
|
||||
do {
|
||||
string_init_printf(
|
||||
path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension);
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(path))) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
if(!storage_simply_remove(dev->storage, string_get_cstr(path))) break;
|
||||
dev->shadow_file_exist = false;
|
||||
string_clean(path);
|
||||
string_printf(path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
|
||||
if(!nfc_device_load_data(file_worker, path, dev)) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
if(!nfc_device_load_data(dev, path)) break;
|
||||
restored = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(path);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
return result;
|
||||
return restored;
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <storage/storage.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
#include "mifare_ultralight.h"
|
||||
|
||||
@ -57,6 +59,8 @@ typedef struct {
|
||||
} NfcDeviceData;
|
||||
|
||||
typedef struct {
|
||||
Storage* storage;
|
||||
DialogsApp* dialogs;
|
||||
NfcDeviceData dev_data;
|
||||
char dev_name[NFC_DEV_NAME_MAX_LEN + 1];
|
||||
char file_name[NFC_FILE_NAME_MAX_LEN];
|
||||
@ -64,6 +68,10 @@ typedef struct {
|
||||
bool shadow_file_exist;
|
||||
} NfcDevice;
|
||||
|
||||
NfcDevice* nfc_device_alloc();
|
||||
|
||||
void nfc_device_free(NfcDevice* nfc_dev);
|
||||
|
||||
void nfc_device_set_name(NfcDevice* dev, const char* name);
|
||||
|
||||
bool nfc_device_save(NfcDevice* dev, const char* dev_name);
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "nfc_device.h"
|
||||
#include <m-string.h>
|
||||
|
||||
uint16_t nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string);
|
||||
bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string);
|
||||
|
||||
uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string);
|
||||
bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string);
|
||||
|
||||
uint16_t nfc_device_prepare_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string);
|
||||
bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string);
|
||||
|
||||
uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_string);
|
||||
bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string);
|
||||
@ -36,7 +36,7 @@ struct Nfc {
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
SceneManager* scene_manager;
|
||||
NfcDevice dev;
|
||||
NfcDevice* dev;
|
||||
NfcDeviceCommonData dev_edit_data;
|
||||
|
||||
char text_store[NFC_TEXT_STORE_SIZE + 1];
|
||||
|
||||
145
applications/nfc/nfc_worker.c
Executable file → Normal file
145
applications/nfc/nfc_worker.c
Executable file → Normal file
@ -3,14 +3,14 @@
|
||||
#include "nfc_protocols/emv_decoder.h"
|
||||
#include "nfc_protocols/mifare_ultralight.h"
|
||||
|
||||
#define NFC_WORKER_TAG "nfc worker"
|
||||
#define TAG "NfcWorker"
|
||||
|
||||
/***************************** NFC Worker API *******************************/
|
||||
|
||||
NfcWorker* nfc_worker_alloc() {
|
||||
NfcWorker* nfc_worker = furi_alloc(sizeof(NfcWorker));
|
||||
// Worker thread attributes
|
||||
nfc_worker->thread_attr.name = "nfc_worker";
|
||||
nfc_worker->thread_attr.name = "NfcWorker";
|
||||
nfc_worker->thread_attr.stack_size = 8192;
|
||||
nfc_worker->callback = NULL;
|
||||
nfc_worker->context = NULL;
|
||||
@ -144,7 +144,7 @@ void nfc_worker_emulate(NfcWorker* nfc_worker) {
|
||||
NfcDeviceCommonData* data = &nfc_worker->dev_data->nfc_data;
|
||||
while(nfc_worker->state == NfcWorkerStateEmulate) {
|
||||
if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Reader detected");
|
||||
FURI_LOG_I(TAG, "Reader detected");
|
||||
}
|
||||
osDelay(10);
|
||||
}
|
||||
@ -174,18 +174,17 @@ void nfc_worker_read_emv_app(NfcWorker* nfc_worker) {
|
||||
result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len);
|
||||
result->nfc_data.protocol = NfcDeviceProtocolEMV;
|
||||
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Send select PPSE command");
|
||||
FURI_LOG_I(TAG, "Send select PPSE command");
|
||||
tx_len = emv_prepare_select_ppse(tx_buff);
|
||||
err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err != ERR_NONE) {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Error during selection PPSE request: %d", err);
|
||||
FURI_LOG_E(TAG, "Error during selection PPSE request: %d", err);
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
FURI_LOG_I(
|
||||
NFC_WORKER_TAG, "Select PPSE response received. Start parsing response");
|
||||
FURI_LOG_I(TAG, "Select PPSE response received. Start parsing response");
|
||||
if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Select PPSE responce parced");
|
||||
FURI_LOG_I(TAG, "Select PPSE responce parced");
|
||||
// Notify caller and exit
|
||||
result->emv_data.aid_len = emv_app.aid_len;
|
||||
memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len);
|
||||
@ -194,18 +193,18 @@ void nfc_worker_read_emv_app(NfcWorker* nfc_worker) {
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Can't find pay application");
|
||||
FURI_LOG_E(TAG, "Can't find pay application");
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Can't find EMV card
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Card doesn't support EMV");
|
||||
FURI_LOG_W(TAG, "Card doesn't support EMV");
|
||||
furi_hal_nfc_deactivate();
|
||||
}
|
||||
} else {
|
||||
// Can't find EMV card
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Can't find any cards");
|
||||
FURI_LOG_W(TAG, "Can't find any cards");
|
||||
furi_hal_nfc_deactivate();
|
||||
}
|
||||
osDelay(20);
|
||||
@ -236,56 +235,53 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
|
||||
result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len);
|
||||
result->nfc_data.protocol = NfcDeviceProtocolEMV;
|
||||
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Send select PPSE command");
|
||||
FURI_LOG_I(TAG, "Send select PPSE command");
|
||||
tx_len = emv_prepare_select_ppse(tx_buff);
|
||||
err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err != ERR_NONE) {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Error during selection PPSE request: %d", err);
|
||||
FURI_LOG_E(TAG, "Error during selection PPSE request: %d", err);
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
FURI_LOG_I(
|
||||
NFC_WORKER_TAG, "Select PPSE response received. Start parsing response");
|
||||
FURI_LOG_I(TAG, "Select PPSE response received. Start parsing response");
|
||||
if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Select PPSE responce parced");
|
||||
FURI_LOG_I(TAG, "Select PPSE responce parced");
|
||||
result->emv_data.aid_len = emv_app.aid_len;
|
||||
memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len);
|
||||
} else {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Can't find pay application");
|
||||
FURI_LOG_E(TAG, "Can't find pay application");
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Starting application ...");
|
||||
FURI_LOG_I(TAG, "Starting application ...");
|
||||
tx_len = emv_prepare_select_app(tx_buff, &emv_app);
|
||||
err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err != ERR_NONE) {
|
||||
FURI_LOG_E(
|
||||
NFC_WORKER_TAG, "Error during application selection request: %d", err);
|
||||
FURI_LOG_E(TAG, "Error during application selection request: %d", err);
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
FURI_LOG_I(
|
||||
NFC_WORKER_TAG,
|
||||
"Select application response received. Start parsing response");
|
||||
FURI_LOG_I(TAG, "Select application response received. Start parsing response");
|
||||
if(emv_decode_select_app_response(rx_buff, *rx_len, &emv_app)) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Card name: %s", emv_app.name);
|
||||
FURI_LOG_I(TAG, "Card name: %s", emv_app.name);
|
||||
memcpy(result->emv_data.name, emv_app.name, sizeof(emv_app.name));
|
||||
} else if(emv_app.pdol.size > 0) {
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Can't find card name, but PDOL is present.");
|
||||
FURI_LOG_W(TAG, "Can't find card name, but PDOL is present.");
|
||||
} else {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Can't find card name or PDOL");
|
||||
FURI_LOG_E(TAG, "Can't find card name or PDOL");
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Starting Get Processing Options command ...");
|
||||
FURI_LOG_I(TAG, "Starting Get Processing Options command ...");
|
||||
tx_len = emv_prepare_get_proc_opt(tx_buff, &emv_app);
|
||||
err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err != ERR_NONE) {
|
||||
FURI_LOG_E(
|
||||
NFC_WORKER_TAG, "Error during Get Processing Options command: %d", err);
|
||||
FURI_LOG_E(TAG, "Error during Get Processing Options command: %d", err);
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
if(emv_decode_get_proc_opt(rx_buff, *rx_len, &emv_app)) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Card number parsed");
|
||||
FURI_LOG_I(TAG, "Card number parsed");
|
||||
result->emv_data.number_len = emv_app.card_number_len;
|
||||
memcpy(result->emv_data.number, emv_app.card_number, emv_app.card_number_len);
|
||||
// Notify caller and exit
|
||||
@ -309,7 +305,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
|
||||
tx_buff, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err != ERR_NONE) {
|
||||
FURI_LOG_E(
|
||||
NFC_WORKER_TAG,
|
||||
TAG,
|
||||
"Error reading application sfi %d, record %d",
|
||||
sfi,
|
||||
record);
|
||||
@ -321,7 +317,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
|
||||
}
|
||||
}
|
||||
if(pan_found) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Card PAN found");
|
||||
FURI_LOG_I(TAG, "Card PAN found");
|
||||
result->emv_data.number_len = emv_app.card_number_len;
|
||||
memcpy(
|
||||
result->emv_data.number,
|
||||
@ -343,18 +339,18 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Can't read card number");
|
||||
FURI_LOG_E(TAG, "Can't read card number");
|
||||
}
|
||||
furi_hal_nfc_deactivate();
|
||||
}
|
||||
} else {
|
||||
// Can't find EMV card
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Card doesn't support EMV");
|
||||
FURI_LOG_W(TAG, "Card doesn't support EMV");
|
||||
furi_hal_nfc_deactivate();
|
||||
}
|
||||
} else {
|
||||
// Can't find EMV card
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Can't find any cards");
|
||||
FURI_LOG_W(TAG, "Can't find any cards");
|
||||
furi_hal_nfc_deactivate();
|
||||
}
|
||||
osDelay(20);
|
||||
@ -416,63 +412,63 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) {
|
||||
|
||||
while(nfc_worker->state == NfcWorkerStateEmulateApdu) {
|
||||
if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 300)) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "POS terminal detected");
|
||||
FURI_LOG_I(TAG, "POS terminal detected");
|
||||
// Read data from POS terminal
|
||||
err = furi_hal_nfc_data_exchange(NULL, 0, &rx_buff, &rx_len, false);
|
||||
if(err == ERR_NONE) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Received Select PPSE");
|
||||
FURI_LOG_I(TAG, "Received Select PPSE");
|
||||
} else {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Error in 1st data exchange: select PPSE");
|
||||
FURI_LOG_E(TAG, "Error in 1st data exchange: select PPSE");
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Transive SELECT PPSE ANS");
|
||||
FURI_LOG_I(TAG, "Transive SELECT PPSE ANS");
|
||||
tx_len = emv_select_ppse_ans(tx_buff);
|
||||
err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err == ERR_NONE) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Received Select APP");
|
||||
FURI_LOG_I(TAG, "Received Select APP");
|
||||
} else {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Error in 2nd data exchange: select APP");
|
||||
FURI_LOG_E(TAG, "Error in 2nd data exchange: select APP");
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Transive SELECT APP ANS");
|
||||
FURI_LOG_I(TAG, "Transive SELECT APP ANS");
|
||||
tx_len = emv_select_app_ans(tx_buff);
|
||||
err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err == ERR_NONE) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Received PDOL");
|
||||
FURI_LOG_I(TAG, "Received PDOL");
|
||||
} else {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Error in 3rd data exchange: receive PDOL");
|
||||
FURI_LOG_E(TAG, "Error in 3rd data exchange: receive PDOL");
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Transive PDOL ANS");
|
||||
FURI_LOG_I(TAG, "Transive PDOL ANS");
|
||||
tx_len = emv_get_proc_opt_ans(tx_buff);
|
||||
err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err == ERR_NONE) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Transive PDOL ANS");
|
||||
FURI_LOG_I(TAG, "Transive PDOL ANS");
|
||||
} else {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Error in 4rd data exchange: Transive PDOL ANS");
|
||||
FURI_LOG_E(TAG, "Error in 4rd data exchange: Transive PDOL ANS");
|
||||
furi_hal_nfc_deactivate();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(*rx_len != sizeof(debug_rx) || memcmp(rx_buff, debug_rx, sizeof(debug_rx))) {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Failed long message test");
|
||||
FURI_LOG_E(TAG, "Failed long message test");
|
||||
} else {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Correct debug message received");
|
||||
FURI_LOG_I(TAG, "Correct debug message received");
|
||||
tx_len = sizeof(debug_tx);
|
||||
err = furi_hal_nfc_data_exchange(
|
||||
(uint8_t*)debug_tx, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err == ERR_NONE) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Transive Debug message");
|
||||
FURI_LOG_I(TAG, "Transive Debug message");
|
||||
}
|
||||
}
|
||||
furi_hal_nfc_deactivate();
|
||||
} else {
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Can't find reader");
|
||||
FURI_LOG_W(TAG, "Can't find reader");
|
||||
}
|
||||
osDelay(20);
|
||||
}
|
||||
@ -499,71 +495,69 @@ void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) {
|
||||
dev_list[0].dev.nfca.sensRes.platformInfo,
|
||||
dev_list[0].dev.nfca.selRes.sak)) {
|
||||
// Get Mifare Ultralight version
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Found Mifare Ultralight tag. Reading tag version");
|
||||
FURI_LOG_I(TAG, "Found Mifare Ultralight tag. Reading tag version");
|
||||
tx_len = mf_ul_prepare_get_version(tx_buff);
|
||||
err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
|
||||
if(err == ERR_NONE) {
|
||||
mf_ul_parse_get_version_response(rx_buff, &mf_ul_read);
|
||||
FURI_LOG_I(
|
||||
NFC_WORKER_TAG,
|
||||
TAG,
|
||||
"Mifare Ultralight Type: %d, Pages: %d",
|
||||
mf_ul_read.type,
|
||||
mf_ul_read.pages_to_read);
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Reading signature ...");
|
||||
FURI_LOG_I(TAG, "Reading signature ...");
|
||||
tx_len = mf_ul_prepare_read_signature(tx_buff);
|
||||
if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Failed reading signature");
|
||||
FURI_LOG_W(TAG, "Failed reading signature");
|
||||
memset(mf_ul_read.data.signature, 0, sizeof(mf_ul_read.data.signature));
|
||||
} else {
|
||||
mf_ul_parse_read_signature_response(rx_buff, &mf_ul_read);
|
||||
}
|
||||
} else if(err == ERR_TIMEOUT) {
|
||||
FURI_LOG_W(
|
||||
NFC_WORKER_TAG,
|
||||
TAG,
|
||||
"Card doesn't respond to GET VERSION command. Setting default read parameters");
|
||||
err = ERR_NONE;
|
||||
mf_ul_set_default_version(&mf_ul_read);
|
||||
// Reinit device
|
||||
furi_hal_nfc_deactivate();
|
||||
if(!furi_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Lost connection. Restarting search");
|
||||
FURI_LOG_E(TAG, "Lost connection. Restarting search");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(
|
||||
NFC_WORKER_TAG,
|
||||
"Error getting Mifare Ultralight version. Error code: %d",
|
||||
err);
|
||||
TAG, "Error getting Mifare Ultralight version. Error code: %d", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(mf_ul_read.support_fast_read) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Reading pages ...");
|
||||
FURI_LOG_I(TAG, "Reading pages ...");
|
||||
tx_len = mf_ul_prepare_fast_read(tx_buff, 0x00, mf_ul_read.pages_to_read - 1);
|
||||
if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Failed reading pages");
|
||||
FURI_LOG_E(TAG, "Failed reading pages");
|
||||
continue;
|
||||
} else {
|
||||
mf_ul_parse_fast_read_response(
|
||||
rx_buff, 0x00, mf_ul_read.pages_to_read - 1, &mf_ul_read);
|
||||
}
|
||||
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Reading 3 counters ...");
|
||||
FURI_LOG_I(TAG, "Reading 3 counters ...");
|
||||
for(uint8_t i = 0; i < 3; i++) {
|
||||
tx_len = mf_ul_prepare_read_cnt(tx_buff, i);
|
||||
if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Failed reading Counter %d", i);
|
||||
FURI_LOG_W(TAG, "Failed reading Counter %d", i);
|
||||
mf_ul_read.data.counter[i] = 0;
|
||||
} else {
|
||||
mf_ul_parse_read_cnt_response(rx_buff, i, &mf_ul_read);
|
||||
}
|
||||
}
|
||||
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Checking tearing flags ...");
|
||||
FURI_LOG_I(TAG, "Checking tearing flags ...");
|
||||
for(uint8_t i = 0; i < 3; i++) {
|
||||
tx_len = mf_ul_prepare_check_tearing(tx_buff, i);
|
||||
if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Error checking tearing flag %d", i);
|
||||
FURI_LOG_E(TAG, "Error checking tearing flag %d", i);
|
||||
mf_ul_read.data.tearing[i] = MF_UL_TEARING_FLAG_DEFAULT;
|
||||
} else {
|
||||
mf_ul_parse_check_tearing_response(rx_buff, i, &mf_ul_read);
|
||||
@ -572,11 +566,10 @@ void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) {
|
||||
} else {
|
||||
// READ card with READ command (4 pages at a time)
|
||||
for(uint8_t page = 0; page < mf_ul_read.pages_to_read; page += 4) {
|
||||
FURI_LOG_I(NFC_WORKER_TAG, "Reading pages %d - %d ...", page, page + 3);
|
||||
FURI_LOG_I(TAG, "Reading pages %d - %d ...", page, page + 3);
|
||||
tx_len = mf_ul_prepare_read(tx_buff, page);
|
||||
if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) {
|
||||
FURI_LOG_E(
|
||||
NFC_WORKER_TAG, "Read pages %d - %d failed", page, page + 3);
|
||||
FURI_LOG_E(TAG, "Read pages %d - %d failed", page, page + 3);
|
||||
continue;
|
||||
} else {
|
||||
mf_ul_parse_read_response(rx_buff, page, &mf_ul_read);
|
||||
@ -600,10 +593,10 @@ void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) {
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Tag does not support Mifare Ultralight");
|
||||
FURI_LOG_W(TAG, "Tag does not support Mifare Ultralight");
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Can't find any tags");
|
||||
FURI_LOG_W(TAG, "Can't find any tags");
|
||||
}
|
||||
osDelay(100);
|
||||
}
|
||||
@ -627,7 +620,7 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) {
|
||||
data->nfc_data.sak,
|
||||
true,
|
||||
200)) {
|
||||
FURI_LOG_D(NFC_WORKER_TAG, "Anticollision passed");
|
||||
FURI_LOG_D(TAG, "Anticollision passed");
|
||||
if(furi_hal_nfc_get_first_frame(&rx_buff, &rx_len)) {
|
||||
// Data exchange loop
|
||||
while(nfc_worker->state == NfcWorkerStateEmulateMifareUl) {
|
||||
@ -639,17 +632,17 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) {
|
||||
if(err == ERR_NONE) {
|
||||
continue;
|
||||
} else {
|
||||
FURI_LOG_E(NFC_WORKER_TAG, "Communication error: %d", err);
|
||||
FURI_LOG_E(TAG, "Communication error: %d", err);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Not valid command: %02X", rx_buff[0]);
|
||||
FURI_LOG_W(TAG, "Not valid command: %02X", rx_buff[0]);
|
||||
furi_hal_nfc_deactivate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Error in 1st data exchange");
|
||||
FURI_LOG_W(TAG, "Error in 1st data exchange");
|
||||
furi_hal_nfc_deactivate();
|
||||
}
|
||||
}
|
||||
@ -660,7 +653,7 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) {
|
||||
nfc_worker->callback(nfc_worker->context);
|
||||
}
|
||||
}
|
||||
FURI_LOG_W(NFC_WORKER_TAG, "Can't find reader");
|
||||
FURI_LOG_W(TAG, "Can't find reader");
|
||||
osThreadYield();
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ void nfc_scene_card_menu_on_enter(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
if(nfc->dev.dev_data.nfc_data.protocol > NfcDeviceProtocolUnknown) {
|
||||
if(nfc->dev->dev_data.nfc_data.protocol > NfcDeviceProtocolUnknown) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Run compatible app",
|
||||
@ -48,9 +48,9 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == SubmenuIndexRunApp) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexRunApp);
|
||||
if(nfc->dev.dev_data.nfc_data.protocol == NfcDeviceProtocolMifareUl) {
|
||||
if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolMifareUl) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl);
|
||||
} else if(nfc->dev.dev_data.nfc_data.protocol == NfcDeviceProtocolEMV) {
|
||||
} else if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolEMV) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp);
|
||||
}
|
||||
return true;
|
||||
@ -66,7 +66,7 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
return true;
|
||||
} else if(event.event == SubmenuIndexSave) {
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexSave);
|
||||
nfc->dev.format = NfcDeviceSaveFormatUid;
|
||||
nfc->dev->format = NfcDeviceSaveFormatUid;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -12,14 +12,14 @@ void nfc_scene_delete_on_enter(void* context) {
|
||||
|
||||
// Setup Custom Widget view
|
||||
char delete_str[64];
|
||||
snprintf(delete_str, sizeof(delete_str), "\e#Delete %s\e#", nfc->dev.dev_name);
|
||||
snprintf(delete_str, sizeof(delete_str), "\e#Delete %s\e#", nfc->dev->dev_name);
|
||||
widget_add_text_box_element(nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, delete_str);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc);
|
||||
char uid_str[32];
|
||||
NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data;
|
||||
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
|
||||
if(data->uid_len == 4) {
|
||||
snprintf(
|
||||
uid_str,
|
||||
@ -73,7 +73,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
return scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
if(nfc_device_delete(&nfc->dev)) {
|
||||
if(nfc_device_delete(nfc->dev)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
|
||||
#define NFC_SCENE_DEVICE_INFO_BACK_EVENT (0UL)
|
||||
|
||||
@ -36,13 +37,13 @@ void nfc_scene_device_info_on_enter(void* context) {
|
||||
|
||||
// Setup Custom Widget view
|
||||
widget_add_text_box_element(
|
||||
nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, nfc->dev.dev_name);
|
||||
nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, nfc->dev->dev_name);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc);
|
||||
widget_add_button_element(
|
||||
nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc);
|
||||
char uid_str[32];
|
||||
NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data;
|
||||
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
|
||||
if(data->uid_len == 4) {
|
||||
snprintf(
|
||||
uid_str,
|
||||
@ -87,14 +88,14 @@ void nfc_scene_device_info_on_enter(void* context) {
|
||||
widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, atqa_str);
|
||||
|
||||
// Setup Data View
|
||||
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Back");
|
||||
dialog_ex_set_text(dialog_ex, "No data", 64, 32, AlignCenter, AlignCenter);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback);
|
||||
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
||||
MifareUlData* mf_ul_data = (MifareUlData*)&nfc->dev.dev_data.mf_ul_data;
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
MifareUlData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data;
|
||||
TextBox* text_box = nfc->text_box;
|
||||
text_box_set_context(text_box, nfc);
|
||||
text_box_set_exit_callback(text_box, nfc_scene_device_info_text_box_callback);
|
||||
@ -107,8 +108,8 @@ void nfc_scene_device_info_on_enter(void* context) {
|
||||
nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]);
|
||||
}
|
||||
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
|
||||
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
|
||||
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||
BankCard* bank_card = nfc->bank_card;
|
||||
bank_card_set_name(bank_card, emv_data->name);
|
||||
bank_card_set_number(bank_card, emv_data->number, emv_data->number_len);
|
||||
@ -116,12 +117,29 @@ void nfc_scene_device_info_on_enter(void* context) {
|
||||
if(emv_data->exp_mon) {
|
||||
bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year);
|
||||
}
|
||||
string_t display_str;
|
||||
string_init(display_str);
|
||||
if(emv_data->country_code) {
|
||||
bank_card_set_country_name(bank_card, emv_data->country_code);
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if(nfc_emv_parser_get_country_name(
|
||||
nfc->dev->storage, emv_data->country_code, country_name)) {
|
||||
string_printf(display_str, "Reg:%s", string_get_cstr(country_name));
|
||||
bank_card_set_country_name(bank_card, string_get_cstr(display_str));
|
||||
}
|
||||
string_clear(country_name);
|
||||
}
|
||||
if(emv_data->currency_code) {
|
||||
bank_card_set_currency_name(bank_card, emv_data->currency_code);
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if(nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->country_code, currency_name)) {
|
||||
string_printf(display_str, "Cur:%s", string_get_cstr(currency_name));
|
||||
bank_card_set_currency_name(bank_card, string_get_cstr(display_str));
|
||||
}
|
||||
string_clear(currency_name);
|
||||
}
|
||||
string_clear(display_str);
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
@ -136,17 +154,17 @@ bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) {
|
||||
if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeLeft)) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeRight)) {
|
||||
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
consumed = true;
|
||||
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
|
||||
consumed = true;
|
||||
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard);
|
||||
@ -168,7 +186,7 @@ void nfc_scene_device_info_on_exit(void* context) {
|
||||
// Clear Custom Widget
|
||||
widget_clear(nfc->widget);
|
||||
|
||||
if(nfc->dev.format == NfcDeviceSaveFormatUid) {
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatUid) {
|
||||
// Clear Dialog
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
|
||||
@ -179,11 +197,11 @@ void nfc_scene_device_info_on_exit(void* context) {
|
||||
dialog_ex_set_center_button_text(dialog_ex, NULL);
|
||||
dialog_ex_set_result_callback(dialog_ex, NULL);
|
||||
dialog_ex_set_context(dialog_ex, NULL);
|
||||
} else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
// Clear TextBox
|
||||
text_box_clean(nfc->text_box);
|
||||
string_clean(nfc->text_box_store);
|
||||
} else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) {
|
||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||
// Clear Bank Card
|
||||
bank_card_clear(nfc->bank_card);
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ void nfc_scene_emulate_apdu_sequence_on_enter(void* context) {
|
||||
// Setup and start worker
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
nfc_worker_start(nfc->worker, NfcWorkerStateEmulateApdu, &nfc->dev.dev_data, NULL, nfc);
|
||||
nfc_worker_start(nfc->worker, NfcWorkerStateEmulateApdu, &nfc->dev->dev_data, NULL, nfc);
|
||||
}
|
||||
|
||||
bool nfc_scene_emulate_apdu_sequence_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
@ -14,8 +14,8 @@ void nfc_scene_emulate_mifare_ul_on_enter(void* context) {
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
if(strcmp(nfc->dev.dev_name, "")) {
|
||||
nfc_text_store_set(nfc, "%s", nfc->dev.dev_name);
|
||||
if(strcmp(nfc->dev->dev_name, "")) {
|
||||
nfc_text_store_set(nfc, "%s", nfc->dev->dev_name);
|
||||
}
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||
popup_set_header(popup, "Emulating\nMf Ultralight", 56, 31, AlignLeft, AlignTop);
|
||||
@ -25,7 +25,7 @@ void nfc_scene_emulate_mifare_ul_on_enter(void* context) {
|
||||
nfc_worker_start(
|
||||
nfc->worker,
|
||||
NfcWorkerStateEmulateMifareUl,
|
||||
&nfc->dev.dev_data,
|
||||
&nfc->dev->dev_data,
|
||||
nfc_emulate_mifare_ul_worker_callback,
|
||||
nfc);
|
||||
}
|
||||
@ -45,7 +45,7 @@ bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event
|
||||
NFC_MF_UL_DATA_CHANGED) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_NOT_CHANGED);
|
||||
nfc_device_save_shadow(&nfc->dev, nfc->dev.dev_name);
|
||||
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
|
||||
}
|
||||
consumed = false;
|
||||
}
|
||||
|
||||
@ -5,10 +5,10 @@ void nfc_scene_emulate_uid_on_enter(void* context) {
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data;
|
||||
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
|
||||
|
||||
if(strcmp(nfc->dev.dev_name, "")) {
|
||||
nfc_text_store_set(nfc, "%s", nfc->dev.dev_name);
|
||||
if(strcmp(nfc->dev->dev_name, "")) {
|
||||
nfc_text_store_set(nfc, "%s", nfc->dev->dev_name);
|
||||
} else if(data->uid_len == 4) {
|
||||
nfc_text_store_set(
|
||||
nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]);
|
||||
@ -32,7 +32,7 @@ void nfc_scene_emulate_uid_on_enter(void* context) {
|
||||
// Setup and start worker
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
nfc_worker_start(nfc->worker, NfcWorkerStateEmulate, &nfc->dev.dev_data, NULL, nfc);
|
||||
nfc_worker_start(nfc->worker, NfcWorkerStateEmulate, &nfc->dev->dev_data, NULL, nfc);
|
||||
}
|
||||
|
||||
bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
void nfc_scene_file_select_on_enter(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
// Process file_select return
|
||||
if(nfc_file_select(&nfc->dev)) {
|
||||
if(nfc_file_select(nfc->dev)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart);
|
||||
|
||||
@ -32,9 +32,9 @@ bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == SubmenuIndexSave) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave);
|
||||
nfc->dev.format = NfcDeviceSaveFormatMifareUl;
|
||||
nfc->dev->format = NfcDeviceSaveFormatMifareUl;
|
||||
// Clear device name
|
||||
nfc_device_set_name(&nfc->dev, "");
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
return true;
|
||||
} else if(event.event == SubmenuIndexEmulate) {
|
||||
|
||||
@ -18,7 +18,7 @@ void nfc_scene_read_card_on_enter(void* context) {
|
||||
// Start worker
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
nfc_worker_start(
|
||||
nfc->worker, NfcWorkerStateDetect, &nfc->dev.dev_data, nfc_read_card_worker_callback, nfc);
|
||||
nfc->worker, NfcWorkerStateDetect, &nfc->dev->dev_data, nfc_read_card_worker_callback, nfc);
|
||||
}
|
||||
|
||||
bool nfc_scene_read_card_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
@ -15,7 +15,7 @@ void nfc_scene_read_card_success_on_enter(void* context) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
|
||||
// Setup view
|
||||
NfcDeviceCommonData* data = (NfcDeviceCommonData*)&nfc->dev.dev_data.nfc_data;
|
||||
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
||||
@ -68,7 +68,7 @@ bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event
|
||||
return scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if(event.event == DialogExResultRight) {
|
||||
// Clear device name
|
||||
nfc_device_set_name(&nfc->dev, "");
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneCardMenu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ void nfc_scene_read_emv_app_on_enter(void* context) {
|
||||
nfc_worker_start(
|
||||
nfc->worker,
|
||||
NfcWorkerStateReadEMVApp,
|
||||
&nfc->dev.dev_data,
|
||||
&nfc->dev->dev_data,
|
||||
nfc_read_emv_app_worker_callback,
|
||||
nfc);
|
||||
}
|
||||
|
||||
@ -13,8 +13,8 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
// Setup view
|
||||
NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data;
|
||||
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
|
||||
NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "Run app");
|
||||
@ -23,7 +23,8 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) {
|
||||
// Display UID and AID
|
||||
string_t aid;
|
||||
string_init(aid);
|
||||
bool aid_found = nfc_emv_parser_get_aid_name(emv_data->aid, emv_data->aid_len, aid);
|
||||
bool aid_found =
|
||||
nfc_emv_parser_get_aid_name(nfc->dev->storage, emv_data->aid, emv_data->aid_len, aid);
|
||||
if(!aid_found) {
|
||||
for(uint8_t i = 0; i < emv_data->aid_len; i++) {
|
||||
string_cat_printf(aid, "%02X", emv_data->aid[i]);
|
||||
|
||||
@ -17,12 +17,12 @@ void nfc_scene_read_emv_data_on_enter(void* context) {
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
// Clear emv data
|
||||
memset(&nfc->dev.dev_data.emv_data, 0, sizeof(nfc->dev.dev_data.emv_data));
|
||||
memset(&nfc->dev->dev_data.emv_data, 0, sizeof(nfc->dev->dev_data.emv_data));
|
||||
// Start worker
|
||||
nfc_worker_start(
|
||||
nfc->worker,
|
||||
NfcWorkerStateReadEMV,
|
||||
&nfc->dev.dev_data,
|
||||
&nfc->dev->dev_data,
|
||||
nfc_read_emv_data_worker_callback,
|
||||
nfc);
|
||||
}
|
||||
|
||||
@ -13,8 +13,8 @@ void nfc_scene_read_emv_data_success_widget_callback(
|
||||
|
||||
void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
|
||||
NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data;
|
||||
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
|
||||
NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data;
|
||||
|
||||
// Setup Custom Widget view
|
||||
// Add frame
|
||||
@ -34,7 +34,7 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
nfc);
|
||||
// Add card name
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev.dev_data.emv_data.name);
|
||||
nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name);
|
||||
// Add cad number
|
||||
string_t pan_str;
|
||||
string_init(pan_str);
|
||||
@ -49,7 +49,7 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if((emv_data->country_code) &&
|
||||
nfc_emv_parser_get_country_name(emv_data->country_code, country_name)) {
|
||||
nfc_emv_parser_get_country_name(nfc->dev->storage, emv_data->country_code, country_name)) {
|
||||
string_t disp_country;
|
||||
string_init_printf(disp_country, "Reg:%s", country_name);
|
||||
widget_add_string_element(
|
||||
@ -61,7 +61,8 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if((emv_data->currency_code) &&
|
||||
nfc_emv_parser_get_currency_name(emv_data->currency_code, currency_name)) {
|
||||
nfc_emv_parser_get_currency_name(
|
||||
nfc->dev->storage, emv_data->currency_code, currency_name)) {
|
||||
string_t disp_currency;
|
||||
string_init_printf(disp_currency, "Cur:%s", currency_name);
|
||||
widget_add_string_element(
|
||||
@ -122,8 +123,8 @@ bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerEvent e
|
||||
nfc->scene_manager, NfcSceneReadEmvAppSuccess);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
// Clear device name
|
||||
nfc_device_set_name(&nfc->dev, "");
|
||||
nfc->dev.format = NfcDeviceSaveFormatBankCard;
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
nfc->dev->format = NfcDeviceSaveFormatBankCard;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ void nfc_scene_read_mifare_ul_on_enter(void* context) {
|
||||
nfc_worker_start(
|
||||
nfc->worker,
|
||||
NfcWorkerStateReadMifareUl,
|
||||
&nfc->dev.dev_data,
|
||||
&nfc->dev->dev_data,
|
||||
nfc_read_mifare_ul_worker_callback,
|
||||
nfc);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
|
||||
notification_message(nfc->notifications, &sequence_success);
|
||||
|
||||
// Setup dialog view
|
||||
NfcDeviceCommonData* data = (NfcDeviceCommonData*)&nfc->dev.dev_data.nfc_data;
|
||||
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
||||
@ -54,7 +54,7 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_mifare_ul_success_dialog_callback);
|
||||
|
||||
// Setup TextBox view
|
||||
MifareUlData* mf_ul_data = (MifareUlData*)&nfc->dev.dev_data.mf_ul_data;
|
||||
MifareUlData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data;
|
||||
TextBox* text_box = nfc->text_box;
|
||||
text_box_set_context(text_box, nfc);
|
||||
text_box_set_exit_callback(text_box, nfc_scene_read_mifare_ul_success_text_box_callback);
|
||||
|
||||
@ -15,11 +15,11 @@ void nfc_scene_save_name_on_enter(void* context) {
|
||||
// Setup view
|
||||
TextInput* text_input = nfc->text_input;
|
||||
bool dev_name_empty = false;
|
||||
if(!strcmp(nfc->dev.dev_name, "")) {
|
||||
if(!strcmp(nfc->dev->dev_name, "")) {
|
||||
set_random_name(nfc->text_store, sizeof(nfc->text_store));
|
||||
dev_name_empty = true;
|
||||
} else {
|
||||
nfc_text_store_set(nfc, nfc->dev.dev_name);
|
||||
nfc_text_store_set(nfc, nfc->dev->dev_name);
|
||||
}
|
||||
text_input_set_header_text(text_input, "Name the card");
|
||||
text_input_set_result_callback(
|
||||
@ -37,14 +37,14 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) {
|
||||
if(strcmp(nfc->dev.dev_name, "")) {
|
||||
nfc_device_delete(&nfc->dev);
|
||||
if(strcmp(nfc->dev->dev_name, "")) {
|
||||
nfc_device_delete(nfc->dev);
|
||||
}
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) {
|
||||
nfc->dev.dev_data.nfc_data = nfc->dev_edit_data;
|
||||
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
|
||||
}
|
||||
strlcpy(nfc->dev.dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
|
||||
if(nfc_device_save(&nfc->dev, nfc->text_store)) {
|
||||
strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
|
||||
if(nfc_device_save(nfc->dev, nfc->text_store)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@ -18,7 +18,7 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
|
||||
if(nfc->dev.format != NfcDeviceSaveFormatBankCard) {
|
||||
if(nfc->dev->format != NfcDeviceSaveFormatBankCard) {
|
||||
submenu_add_item(
|
||||
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
}
|
||||
@ -30,7 +30,7 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
|
||||
if(nfc->dev.shadow_file_exist) {
|
||||
if(nfc->dev->shadow_file_exist) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Restore original",
|
||||
@ -49,7 +49,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, event.event);
|
||||
if(event.event == SubmenuIndexEmulate) {
|
||||
if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
@ -65,7 +65,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexRestoreOriginal) {
|
||||
if(!nfc_device_restore(&nfc->dev)) {
|
||||
if(!nfc_device_restore(nfc->dev)) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneStart);
|
||||
} else {
|
||||
|
||||
@ -19,7 +19,7 @@ void nfc_scene_set_atqa_on_enter(void* context) {
|
||||
nfc_scene_set_atqa_byte_input_callback,
|
||||
NULL,
|
||||
nfc,
|
||||
nfc->dev.dev_data.nfc_data.atqa,
|
||||
nfc->dev->dev_data.nfc_data.atqa,
|
||||
2);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ void nfc_scene_set_sak_on_enter(void* context) {
|
||||
nfc_scene_set_sak_byte_input_callback,
|
||||
NULL,
|
||||
nfc,
|
||||
&nfc->dev.dev_data.nfc_data.sak,
|
||||
&nfc->dev->dev_data.nfc_data.sak,
|
||||
1);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ void nfc_scene_set_type_on_enter(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
Submenu* submenu = nfc->submenu;
|
||||
// Clear device name
|
||||
nfc_device_set_name(&nfc->dev, "");
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
submenu_add_item(
|
||||
submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
@ -28,13 +28,13 @@ bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexNFCA7) {
|
||||
nfc->dev.dev_data.nfc_data.uid_len = 7;
|
||||
nfc->dev.format = NfcDeviceSaveFormatUid;
|
||||
nfc->dev->dev_data.nfc_data.uid_len = 7;
|
||||
nfc->dev->format = NfcDeviceSaveFormatUid;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
|
||||
return true;
|
||||
} else if(event.event == SubmenuIndexNFCA4) {
|
||||
nfc->dev.dev_data.nfc_data.uid_len = 4;
|
||||
nfc->dev.format = NfcDeviceSaveFormatUid;
|
||||
nfc->dev->dev_data.nfc_data.uid_len = 4;
|
||||
nfc->dev->format = NfcDeviceSaveFormatUid;
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ void nfc_scene_set_uid_on_enter(void* context) {
|
||||
// Setup view
|
||||
ByteInput* byte_input = nfc->byte_input;
|
||||
byte_input_set_header_text(byte_input, "Enter uid in hex");
|
||||
nfc->dev_edit_data = nfc->dev.dev_data.nfc_data;
|
||||
nfc->dev_edit_data = nfc->dev->dev_data.nfc_data;
|
||||
byte_input_set_result_callback(
|
||||
byte_input,
|
||||
nfc_scene_set_uid_byte_input_callback,
|
||||
|
||||
@ -34,7 +34,7 @@ void nfc_scene_start_on_enter(void* context) {
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneStart));
|
||||
|
||||
nfc_device_clear(&nfc->dev);
|
||||
nfc_device_clear(nfc->dev);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
|
||||
@ -67,42 +67,14 @@ void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) {
|
||||
bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str);
|
||||
}
|
||||
|
||||
void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code) {
|
||||
void bank_card_set_country_name(BankCard* bank_card, const char* country_name) {
|
||||
furi_assert(bank_card);
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if(nfc_emv_parser_get_country_name(country_code, country_name)) {
|
||||
string_t disp_country;
|
||||
string_init_printf(disp_country, "Reg:%s", country_name);
|
||||
widget_add_string_element(
|
||||
bank_card->widget,
|
||||
120,
|
||||
18,
|
||||
AlignRight,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(disp_country));
|
||||
string_clear(disp_country);
|
||||
}
|
||||
string_clear(country_name);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 120, 18, AlignRight, AlignTop, FontSecondary, country_name);
|
||||
}
|
||||
|
||||
void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code) {
|
||||
void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name) {
|
||||
furi_assert(bank_card);
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if(nfc_emv_parser_get_currency_name(currency_code, currency_name)) {
|
||||
string_t disp_currency;
|
||||
string_init_printf(disp_currency, "Cur:%s", currency_name);
|
||||
widget_add_string_element(
|
||||
bank_card->widget,
|
||||
31,
|
||||
18,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(disp_currency));
|
||||
string_clear(disp_currency);
|
||||
}
|
||||
string_clear(currency_name);
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 31, 18, AlignLeft, AlignTop, FontSecondary, currency_name);
|
||||
}
|
||||
|
||||
@ -21,6 +21,6 @@ void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len);
|
||||
|
||||
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year);
|
||||
|
||||
void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code);
|
||||
void bank_card_set_country_name(BankCard* bank_card, const char* country_name);
|
||||
|
||||
void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code);
|
||||
void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name);
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
#include "notification-messages.h"
|
||||
#include "notification-app.h"
|
||||
|
||||
#define TAG "NotificationSrv"
|
||||
|
||||
static const uint8_t minimal_delay = 100;
|
||||
static const uint8_t led_off_values[NOTIFICATION_LED_COUNT] = {0x00, 0x00, 0x00};
|
||||
|
||||
@ -314,7 +316,7 @@ static bool notification_load_settings(NotificationApp* app) {
|
||||
File* file = storage_file_alloc(furi_record_open("storage"));
|
||||
const size_t settings_size = sizeof(NotificationSettings);
|
||||
|
||||
FURI_LOG_I("notification", "loading settings from \"%s\"", NOTIFICATION_SETTINGS_PATH);
|
||||
FURI_LOG_I(TAG, "loading settings from \"%s\"", NOTIFICATION_SETTINGS_PATH);
|
||||
bool fs_result =
|
||||
storage_file_open(file, NOTIFICATION_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
|
||||
@ -327,21 +329,18 @@ static bool notification_load_settings(NotificationApp* app) {
|
||||
}
|
||||
|
||||
if(fs_result) {
|
||||
FURI_LOG_I("notification", "load success");
|
||||
FURI_LOG_I(TAG, "load success");
|
||||
|
||||
if(settings.version != NOTIFICATION_SETTINGS_VERSION) {
|
||||
FURI_LOG_E(
|
||||
"notification",
|
||||
"version(%d != %d) mismatch",
|
||||
settings.version,
|
||||
NOTIFICATION_SETTINGS_VERSION);
|
||||
TAG, "version(%d != %d) mismatch", settings.version, NOTIFICATION_SETTINGS_VERSION);
|
||||
} else {
|
||||
osKernelLock();
|
||||
memcpy(&app->settings, &settings, settings_size);
|
||||
osKernelUnlock();
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E("notification", "load failed, %s", storage_file_get_error_desc(file));
|
||||
FURI_LOG_E(TAG, "load failed, %s", storage_file_get_error_desc(file));
|
||||
}
|
||||
|
||||
storage_file_close(file);
|
||||
@ -356,7 +355,7 @@ static bool notification_save_settings(NotificationApp* app) {
|
||||
File* file = storage_file_alloc(furi_record_open("storage"));
|
||||
const size_t settings_size = sizeof(NotificationSettings);
|
||||
|
||||
FURI_LOG_I("notification", "saving settings to \"%s\"", NOTIFICATION_SETTINGS_PATH);
|
||||
FURI_LOG_I(TAG, "saving settings to \"%s\"", NOTIFICATION_SETTINGS_PATH);
|
||||
|
||||
osKernelLock();
|
||||
memcpy(&settings, &app->settings, settings_size);
|
||||
@ -374,9 +373,9 @@ static bool notification_save_settings(NotificationApp* app) {
|
||||
}
|
||||
|
||||
if(fs_result) {
|
||||
FURI_LOG_I("notification", "save success");
|
||||
FURI_LOG_I(TAG, "save success");
|
||||
} else {
|
||||
FURI_LOG_E("notification", "save failed, %s", storage_file_get_error_desc(file));
|
||||
FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
|
||||
}
|
||||
|
||||
storage_file_close(file);
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include <cmsis_os2.h>
|
||||
#include <portmacro.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <cli/cli.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@ -16,14 +17,12 @@
|
||||
#include <m-string.h>
|
||||
#include <m-dict.h>
|
||||
|
||||
#define RPC_TAG "RPC"
|
||||
#define TAG "RpcSrv"
|
||||
|
||||
#define RPC_EVENT_NEW_DATA (1 << 0)
|
||||
#define RPC_EVENT_DISCONNECT (1 << 1)
|
||||
#define RPC_EVENTS_ALL (RPC_EVENT_DISCONNECT | RPC_EVENT_NEW_DATA)
|
||||
|
||||
#define DEBUG_PRINT 0
|
||||
|
||||
DICT_DEF2(RpcHandlerDict, pb_size_t, M_DEFAULT_OPLIST, RpcHandler, M_POD_OPLIST)
|
||||
|
||||
typedef struct {
|
||||
@ -53,6 +52,7 @@ static RpcSystemCallbacks rpc_systems[] = {
|
||||
|
||||
struct RpcSession {
|
||||
RpcSendBytesCallback send_bytes_callback;
|
||||
RpcBufferIsEmptyCallback buffer_is_empty_callback;
|
||||
RpcSessionClosedCallback closed_callback;
|
||||
void* context;
|
||||
osMutexId_t callbacks_mutex;
|
||||
@ -263,6 +263,7 @@ void rpc_print_message(const PB_Main* message) {
|
||||
size_t msg_file_count = message->content.storage_list_response.file_count;
|
||||
string_cat_printf(str, "\tlist_response {\r\n");
|
||||
rpc_sprintf_msg_file(str, "\t\t", msg_file, msg_file_count);
|
||||
break;
|
||||
}
|
||||
case PB_Main_gui_start_screen_stream_request_tag:
|
||||
string_cat_printf(str, "\tstart_screen_stream {\r\n");
|
||||
@ -270,8 +271,8 @@ void rpc_print_message(const PB_Main* message) {
|
||||
case PB_Main_gui_stop_screen_stream_request_tag:
|
||||
string_cat_printf(str, "\tstop_screen_stream {\r\n");
|
||||
break;
|
||||
case PB_Main_gui_screen_stream_frame_tag:
|
||||
string_cat_printf(str, "\tscreen_stream_frame {\r\n");
|
||||
case PB_Main_gui_screen_frame_tag:
|
||||
string_cat_printf(str, "\tscreen_frame {\r\n");
|
||||
break;
|
||||
case PB_Main_gui_send_input_event_request_tag:
|
||||
string_cat_printf(str, "\tsend_input_event {\r\n");
|
||||
@ -280,6 +281,12 @@ void rpc_print_message(const PB_Main* message) {
|
||||
string_cat_printf(
|
||||
str, "\t\type: %d\r\n", message->content.gui_send_input_event_request.type);
|
||||
break;
|
||||
case PB_Main_gui_start_virtual_display_request_tag:
|
||||
string_cat_printf(str, "\tstart_virtual_display {\r\n");
|
||||
break;
|
||||
case PB_Main_gui_stop_virtual_display_request_tag:
|
||||
string_cat_printf(str, "\tstop_virtual_display {\r\n");
|
||||
break;
|
||||
}
|
||||
string_cat_printf(str, "\t}\r\n}\r\n");
|
||||
printf("%s", string_get_cstr(str));
|
||||
@ -292,7 +299,7 @@ static Rpc* rpc_alloc(void) {
|
||||
rpc->busy_mutex = osMutexNew(NULL);
|
||||
rpc->busy = false;
|
||||
rpc->events = osEventFlagsNew(NULL);
|
||||
rpc->stream = xStreamBufferCreate(256, 1);
|
||||
rpc->stream = xStreamBufferCreate(RPC_BUFFER_SIZE, 1);
|
||||
|
||||
rpc->decoded_message = furi_alloc(sizeof(PB_Main));
|
||||
rpc->decoded_message->cb_content.funcs.decode = content_callback;
|
||||
@ -334,7 +341,7 @@ RpcSession* rpc_session_open(Rpc* rpc) {
|
||||
};
|
||||
rpc_add_handler(rpc, PB_Main_stop_session_tag, &rpc_handler);
|
||||
|
||||
FURI_LOG_D(RPC_TAG, "Session started\r\n");
|
||||
FURI_LOG_D(TAG, "Session started\r\n");
|
||||
}
|
||||
|
||||
return result ? &rpc->session : NULL; /* support 1 open session for now */
|
||||
@ -365,6 +372,7 @@ static void rpc_free_session(RpcSession* session) {
|
||||
session->context = NULL;
|
||||
session->closed_callback = NULL;
|
||||
session->send_bytes_callback = NULL;
|
||||
session->buffer_is_empty_callback = NULL;
|
||||
}
|
||||
|
||||
void rpc_session_set_context(RpcSession* session, void* context) {
|
||||
@ -397,6 +405,18 @@ void rpc_session_set_send_bytes_callback(RpcSession* session, RpcSendBytesCallba
|
||||
osMutexRelease(session->callbacks_mutex);
|
||||
}
|
||||
|
||||
void rpc_session_set_buffer_is_empty_callback(
|
||||
RpcSession* session,
|
||||
RpcBufferIsEmptyCallback callback) {
|
||||
furi_assert(session);
|
||||
furi_assert(callback);
|
||||
furi_assert(session->rpc->busy);
|
||||
|
||||
osMutexAcquire(session->callbacks_mutex, osWaitForever);
|
||||
session->buffer_is_empty_callback = callback;
|
||||
osMutexRelease(session->callbacks_mutex);
|
||||
}
|
||||
|
||||
/* Doesn't forbid using rpc_feed_bytes() after session close - it's safe.
|
||||
* Because any bytes received in buffer will be flushed before next session.
|
||||
* If bytes get into stream buffer before it's get epmtified and this
|
||||
@ -415,6 +435,12 @@ size_t
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
size_t rpc_session_get_available_size(RpcSession* session) {
|
||||
furi_assert(session);
|
||||
Rpc* rpc = session->rpc;
|
||||
return xStreamBufferSpacesAvailable(rpc->stream);
|
||||
}
|
||||
|
||||
bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
||||
Rpc* rpc = istream->state;
|
||||
uint32_t flags = 0;
|
||||
@ -425,6 +451,11 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
||||
while(1) {
|
||||
bytes_received +=
|
||||
xStreamBufferReceive(rpc->stream, buf + bytes_received, count - bytes_received, 0);
|
||||
if(xStreamBufferIsEmpty(rpc->stream)) {
|
||||
if(rpc->session.buffer_is_empty_callback) {
|
||||
rpc->session.buffer_is_empty_callback(rpc->session.context);
|
||||
}
|
||||
}
|
||||
if(count == bytes_received) {
|
||||
break;
|
||||
} else {
|
||||
@ -443,7 +474,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_PRINT
|
||||
#if SRV_RPC_DEBUG
|
||||
rpc_print_data("INPUT", buf, bytes_received);
|
||||
#endif
|
||||
|
||||
@ -456,8 +487,8 @@ void rpc_send_and_release(Rpc* rpc, PB_Main* message) {
|
||||
RpcSession* session = &rpc->session;
|
||||
pb_ostream_t ostream = PB_OSTREAM_SIZING;
|
||||
|
||||
#if DEBUG_PRINT
|
||||
FURI_LOG_I(RPC_TAG, "OUTPUT:");
|
||||
#if SRV_RPC_DEBUG
|
||||
FURI_LOG_I(TAG, "OUTPUT:");
|
||||
rpc_print_message(message);
|
||||
#endif
|
||||
|
||||
@ -469,7 +500,7 @@ void rpc_send_and_release(Rpc* rpc, PB_Main* message) {
|
||||
|
||||
pb_encode_ex(&ostream, &PB_Main_msg, message, PB_ENCODE_DELIMITED);
|
||||
|
||||
#if DEBUG_PRINT
|
||||
#if SRV_RPC_DEBUG
|
||||
rpc_print_data("OUTPUT", buffer, ostream.bytes_written);
|
||||
#endif
|
||||
|
||||
@ -510,12 +541,12 @@ int32_t rpc_srv(void* p) {
|
||||
.callback = rpc_pb_stream_read,
|
||||
.state = rpc,
|
||||
.errmsg = NULL,
|
||||
.bytes_left = 1024, /* max incoming message size */
|
||||
.bytes_left = RPC_MAX_MESSAGE_SIZE, /* max incoming message size */
|
||||
};
|
||||
|
||||
if(pb_decode_ex(&istream, &PB_Main_msg, rpc->decoded_message, PB_DECODE_DELIMITED)) {
|
||||
#if DEBUG_PRINT
|
||||
FURI_LOG_I(RPC_TAG, "INPUT:");
|
||||
#if SRV_RPC_DEBUG
|
||||
FURI_LOG_I(TAG, "INPUT:");
|
||||
rpc_print_message(rpc->decoded_message);
|
||||
#endif
|
||||
RpcHandler* handler =
|
||||
@ -524,20 +555,19 @@ int32_t rpc_srv(void* p) {
|
||||
if(handler && handler->message_handler) {
|
||||
handler->message_handler(rpc->decoded_message, handler->context);
|
||||
} else if(!handler && !rpc->session.terminate) {
|
||||
FURI_LOG_E(
|
||||
RPC_TAG, "Unhandled message, tag: %d", rpc->decoded_message->which_content);
|
||||
FURI_LOG_E(TAG, "Unhandled message, tag: %d", rpc->decoded_message->which_content);
|
||||
}
|
||||
} else {
|
||||
xStreamBufferReset(rpc->stream);
|
||||
if(!rpc->session.terminate) {
|
||||
FURI_LOG_E(RPC_TAG, "Decode failed, error: \'%.128s\'", PB_GET_ERROR(&istream));
|
||||
FURI_LOG_E(TAG, "Decode failed, error: \'%.128s\'", PB_GET_ERROR(&istream));
|
||||
}
|
||||
}
|
||||
|
||||
pb_release(&PB_Main_msg, rpc->decoded_message);
|
||||
|
||||
if(rpc->session.terminate) {
|
||||
FURI_LOG_D(RPC_TAG, "Session terminated");
|
||||
FURI_LOG_D(TAG, "Session terminated");
|
||||
osEventFlagsClear(rpc->events, RPC_EVENTS_ALL);
|
||||
rpc_free_session(&rpc->session);
|
||||
rpc->busy = false;
|
||||
|
||||
22
applications/rpc/rpc.h
Normal file → Executable file
22
applications/rpc/rpc.h
Normal file → Executable file
@ -4,6 +4,9 @@
|
||||
#include <stdbool.h>
|
||||
#include "cmsis_os.h"
|
||||
|
||||
#define RPC_BUFFER_SIZE (1024)
|
||||
#define RPC_MAX_MESSAGE_SIZE (1536)
|
||||
|
||||
/** Rpc interface. Used for opening session only. */
|
||||
typedef struct Rpc Rpc;
|
||||
/** Rpc session interface */
|
||||
@ -11,6 +14,8 @@ typedef struct RpcSession RpcSession;
|
||||
|
||||
/** Callback to send to client any data (e.g. response to command) */
|
||||
typedef void (*RpcSendBytesCallback)(void* context, uint8_t* bytes, size_t bytes_len);
|
||||
/** Callback to notify client that buffer is empty */
|
||||
typedef void (*RpcBufferIsEmptyCallback)(void* context);
|
||||
/** Callback to notify transport layer that close_session command
|
||||
* is received. Any other actions lays on transport layer.
|
||||
* No destruction or session close preformed. */
|
||||
@ -59,6 +64,15 @@ void rpc_session_set_context(RpcSession* session, void* context);
|
||||
*/
|
||||
void rpc_session_set_send_bytes_callback(RpcSession* session, RpcSendBytesCallback callback);
|
||||
|
||||
/** Set callback to notify that buffer is empty
|
||||
*
|
||||
* @param session pointer to RpcSession descriptor
|
||||
* @param callback callback to notify client that buffer is empty (can be NULL)
|
||||
*/
|
||||
void rpc_session_set_buffer_is_empty_callback(
|
||||
RpcSession* session,
|
||||
RpcBufferIsEmptyCallback callback);
|
||||
|
||||
/** Set callback to be called when RPC command to close session is received
|
||||
* WARN: It's forbidden to call RPC API within RpcSessionClosedCallback
|
||||
*
|
||||
@ -77,3 +91,11 @@ void rpc_session_set_close_callback(RpcSession* session, RpcSessionClosedCallbac
|
||||
* @return actually consumed bytes
|
||||
*/
|
||||
size_t rpc_session_feed(RpcSession* session, uint8_t* buffer, size_t size, TickType_t timeout);
|
||||
|
||||
/** Get available size of RPC buffer
|
||||
*
|
||||
* @param session pointer to RpcSession descriptor
|
||||
*
|
||||
* @return bytes available in buffer
|
||||
*/
|
||||
size_t rpc_session_get_available_size(RpcSession* session);
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
#include <cli/cli.h>
|
||||
#include <furi.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <furi-hal-vcp.h>
|
||||
#include <furi-hal.h>
|
||||
|
||||
typedef struct {
|
||||
Cli* cli;
|
||||
bool session_close_request;
|
||||
} CliRpc;
|
||||
|
||||
#define CLI_READ_BUFFER_SIZE 100
|
||||
#define CLI_READ_BUFFER_SIZE 64
|
||||
|
||||
static void rpc_send_bytes_callback(void* context, uint8_t* bytes, size_t bytes_len) {
|
||||
furi_assert(context);
|
||||
@ -50,7 +50,8 @@ void rpc_cli_command_start_session(Cli* cli, string_t args, void* context) {
|
||||
}
|
||||
|
||||
if(size_received) {
|
||||
rpc_session_feed(rpc_session, buffer, size_received, 3000);
|
||||
furi_assert(
|
||||
rpc_session_feed(rpc_session, buffer, size_received, 3000) == size_received);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,12 +3,17 @@
|
||||
#include "gui.pb.h"
|
||||
#include <gui/gui_i.h>
|
||||
|
||||
#define TAG "RpcGui"
|
||||
|
||||
typedef struct {
|
||||
Rpc* rpc;
|
||||
Gui* gui;
|
||||
ViewPort* virtual_display_view_port;
|
||||
uint8_t* virtual_display_buffer;
|
||||
bool virtual_display_not_empty;
|
||||
} RpcGuiSystem;
|
||||
|
||||
void rpc_system_gui_screen_frame_callback(uint8_t* data, size_t size, void* context) {
|
||||
void rpc_system_gui_screen_stream_frame_callback(uint8_t* data, size_t size, void* context) {
|
||||
furi_assert(data);
|
||||
furi_assert(size == 1024);
|
||||
furi_assert(context);
|
||||
@ -17,11 +22,11 @@ void rpc_system_gui_screen_frame_callback(uint8_t* data, size_t size, void* cont
|
||||
|
||||
PB_Main* frame = furi_alloc(sizeof(PB_Main));
|
||||
|
||||
frame->which_content = PB_Main_gui_screen_stream_frame_tag;
|
||||
frame->which_content = PB_Main_gui_screen_frame_tag;
|
||||
frame->command_status = PB_CommandStatus_OK;
|
||||
frame->content.gui_screen_stream_frame.data = furi_alloc(PB_BYTES_ARRAY_T_ALLOCSIZE(size));
|
||||
uint8_t* buffer = frame->content.gui_screen_stream_frame.data->bytes;
|
||||
uint16_t* frame_size_msg = &frame->content.gui_screen_stream_frame.data->size;
|
||||
frame->content.gui_screen_frame.data = furi_alloc(PB_BYTES_ARRAY_T_ALLOCSIZE(size));
|
||||
uint8_t* buffer = frame->content.gui_screen_frame.data->bytes;
|
||||
uint16_t* frame_size_msg = &frame->content.gui_screen_frame.data->size;
|
||||
*frame_size_msg = size;
|
||||
memcpy(buffer, data, size);
|
||||
|
||||
@ -37,7 +42,8 @@ void rpc_system_gui_start_screen_stream_process(const PB_Main* request, void* co
|
||||
|
||||
rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
|
||||
|
||||
gui_set_framebuffer_callback(rpc_gui->gui, rpc_system_gui_screen_frame_callback, context);
|
||||
gui_set_framebuffer_callback(
|
||||
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
||||
}
|
||||
|
||||
void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, void* context) {
|
||||
@ -45,9 +51,9 @@ void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, void* con
|
||||
furi_assert(context);
|
||||
RpcGuiSystem* rpc_gui = context;
|
||||
|
||||
rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
|
||||
|
||||
gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL);
|
||||
|
||||
rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
|
||||
}
|
||||
|
||||
void rpc_system_gui_send_input_event_request_process(const PB_Main* request, void* context) {
|
||||
@ -120,6 +126,88 @@ void rpc_system_gui_send_input_event_request_process(const PB_Main* request, voi
|
||||
rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
|
||||
}
|
||||
|
||||
static void rpc_system_gui_virtual_display_render_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(context);
|
||||
RpcGuiSystem* rpc_gui = context;
|
||||
|
||||
if(!rpc_gui->virtual_display_not_empty) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 64, 20, AlignCenter, AlignCenter, "Virtual Display");
|
||||
canvas_draw_str_aligned(canvas, 64, 36, AlignCenter, AlignCenter, "Waiting for frames...");
|
||||
return;
|
||||
}
|
||||
|
||||
canvas_draw_xbm(canvas, 0, 0, canvas->width, canvas->height, rpc_gui->virtual_display_buffer);
|
||||
}
|
||||
|
||||
void rpc_system_gui_start_virtual_display_process(const PB_Main* request, void* context) {
|
||||
furi_assert(request);
|
||||
furi_assert(context);
|
||||
RpcGuiSystem* rpc_gui = context;
|
||||
|
||||
if(rpc_gui->virtual_display_view_port) {
|
||||
rpc_send_and_release_empty(
|
||||
rpc_gui->rpc,
|
||||
request->command_id,
|
||||
PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_ALREADY_STARTED);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: consider refactoring
|
||||
// Using display framebuffer size as an XBM buffer size is like comparing apples and oranges
|
||||
// Glad they both are 1024 for now
|
||||
size_t buffer_size = canvas_get_buffer_size(rpc_gui->gui->canvas);
|
||||
rpc_gui->virtual_display_buffer = furi_alloc(buffer_size);
|
||||
rpc_gui->virtual_display_view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(
|
||||
rpc_gui->virtual_display_view_port,
|
||||
rpc_system_gui_virtual_display_render_callback,
|
||||
rpc_gui);
|
||||
gui_add_view_port(rpc_gui->gui, rpc_gui->virtual_display_view_port, GuiLayerFullscreen);
|
||||
|
||||
rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
|
||||
}
|
||||
|
||||
void rpc_system_gui_stop_virtual_display_process(const PB_Main* request, void* context) {
|
||||
furi_assert(request);
|
||||
furi_assert(context);
|
||||
RpcGuiSystem* rpc_gui = context;
|
||||
|
||||
if(!rpc_gui->virtual_display_view_port) {
|
||||
rpc_send_and_release_empty(
|
||||
rpc_gui->rpc, request->command_id, PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED);
|
||||
return;
|
||||
}
|
||||
|
||||
gui_remove_view_port(rpc_gui->gui, rpc_gui->virtual_display_view_port);
|
||||
view_port_free(rpc_gui->virtual_display_view_port);
|
||||
free(rpc_gui->virtual_display_buffer);
|
||||
rpc_gui->virtual_display_view_port = NULL;
|
||||
rpc_gui->virtual_display_not_empty = false;
|
||||
|
||||
rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
|
||||
}
|
||||
|
||||
void rpc_system_gui_virtual_display_frame_process(const PB_Main* request, void* context) {
|
||||
furi_assert(request);
|
||||
furi_assert(context);
|
||||
RpcGuiSystem* rpc_gui = context;
|
||||
|
||||
if(!rpc_gui->virtual_display_view_port) {
|
||||
FURI_LOG_W(TAG, "Virtual display is not started, ignoring incoming frame packet");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t buffer_size = canvas_get_buffer_size(rpc_gui->gui->canvas);
|
||||
memcpy(
|
||||
rpc_gui->virtual_display_buffer,
|
||||
request->content.gui_screen_frame.data->bytes,
|
||||
buffer_size);
|
||||
rpc_gui->virtual_display_not_empty = true;
|
||||
view_port_update(rpc_gui->virtual_display_view_port);
|
||||
}
|
||||
|
||||
void* rpc_system_gui_alloc(Rpc* rpc) {
|
||||
furi_assert(rpc);
|
||||
|
||||
@ -142,6 +230,15 @@ void* rpc_system_gui_alloc(Rpc* rpc) {
|
||||
rpc_handler.message_handler = rpc_system_gui_send_input_event_request_process;
|
||||
rpc_add_handler(rpc, PB_Main_gui_send_input_event_request_tag, &rpc_handler);
|
||||
|
||||
rpc_handler.message_handler = rpc_system_gui_start_virtual_display_process;
|
||||
rpc_add_handler(rpc, PB_Main_gui_start_virtual_display_request_tag, &rpc_handler);
|
||||
|
||||
rpc_handler.message_handler = rpc_system_gui_stop_virtual_display_process;
|
||||
rpc_add_handler(rpc, PB_Main_gui_stop_virtual_display_request_tag, &rpc_handler);
|
||||
|
||||
rpc_handler.message_handler = rpc_system_gui_virtual_display_frame_process;
|
||||
rpc_add_handler(rpc, PB_Main_gui_screen_frame_tag, &rpc_handler);
|
||||
|
||||
return rpc_gui;
|
||||
}
|
||||
|
||||
@ -149,6 +246,15 @@ void rpc_system_gui_free(void* ctx) {
|
||||
furi_assert(ctx);
|
||||
RpcGuiSystem* rpc_gui = ctx;
|
||||
furi_assert(rpc_gui->gui);
|
||||
|
||||
if(rpc_gui->virtual_display_view_port) {
|
||||
gui_remove_view_port(rpc_gui->gui, rpc_gui->virtual_display_view_port);
|
||||
view_port_free(rpc_gui->virtual_display_view_port);
|
||||
free(rpc_gui->virtual_display_buffer);
|
||||
rpc_gui->virtual_display_view_port = NULL;
|
||||
rpc_gui->virtual_display_not_empty = false;
|
||||
}
|
||||
|
||||
gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL);
|
||||
furi_record_close("gui");
|
||||
free(rpc_gui);
|
||||
|
||||
@ -463,3 +463,28 @@ bool storage_simply_mkdir(Storage* storage, const char* path) {
|
||||
result = storage_common_mkdir(storage, path);
|
||||
return result == FSE_OK || result == FSE_EXIST;
|
||||
}
|
||||
|
||||
void storage_get_next_filename(
|
||||
Storage* storage,
|
||||
const char* dirname,
|
||||
const char* filename,
|
||||
const char* fileextension,
|
||||
string_t nextfilename) {
|
||||
string_t temp_str;
|
||||
uint16_t num = 0;
|
||||
|
||||
string_init_printf(temp_str, "%s/%s%s", dirname, filename, fileextension);
|
||||
|
||||
while(storage_common_stat(storage, string_get_cstr(temp_str), NULL) == FSE_OK) {
|
||||
num++;
|
||||
string_printf(temp_str, "%s/%s%d%s", dirname, filename, num, fileextension);
|
||||
}
|
||||
|
||||
if(num) {
|
||||
string_printf(nextfilename, "%s%d", filename, num);
|
||||
} else {
|
||||
string_printf(nextfilename, "%s", filename);
|
||||
}
|
||||
|
||||
string_clear(temp_str);
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include <furi-hal.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
#define TAG "storage-test"
|
||||
#define TAG "StorageTest"
|
||||
#define BYTES_COUNT 16
|
||||
#define TEST_STRING "TestDataStringProvidedByDiceRoll"
|
||||
#define SEEK_OFFSET_FROM_START 10
|
||||
|
||||
@ -262,6 +262,22 @@ bool storage_simply_remove_recursive(Storage* storage, const char* path);
|
||||
*/
|
||||
bool storage_simply_mkdir(Storage* storage, const char* path);
|
||||
|
||||
/**
|
||||
* @brief Get next free filename.
|
||||
*
|
||||
* @param storage
|
||||
* @param dirname
|
||||
* @param filename
|
||||
* @param fileextension
|
||||
* @param nextfilename return name
|
||||
*/
|
||||
void storage_get_next_filename(
|
||||
Storage* storage,
|
||||
const char* dirname,
|
||||
const char* filename,
|
||||
const char* fileextension,
|
||||
string_t nextfilename);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -10,7 +10,7 @@ typedef DIR SDDir;
|
||||
typedef FILINFO SDFileInfo;
|
||||
typedef FRESULT SDError;
|
||||
|
||||
#define TAG "storage-ext"
|
||||
#define TAG "StorageExt"
|
||||
#define STORAGE_PATH "/ext"
|
||||
/********************* Definitions ********************/
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include <lfs.h>
|
||||
#include <furi-hal.h>
|
||||
|
||||
#define TAG "storage-int"
|
||||
#define TAG "StorageInt"
|
||||
#define STORAGE_PATH "/int"
|
||||
|
||||
typedef struct {
|
||||
@ -121,7 +121,7 @@ static int storage_int_device_erase(const struct lfs_config* c, lfs_block_t bloc
|
||||
|
||||
FURI_LOG_D(TAG, "Device erase: page %d, translated page: %x", block, page);
|
||||
|
||||
if(furi_hal_flash_erase(page, 1)) {
|
||||
if(furi_hal_flash_erase(page)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
|
||||
@ -145,7 +145,7 @@ SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc() {
|
||||
SubGhzFrequencyAnalyzerWorker* instance = furi_alloc(sizeof(SubGhzFrequencyAnalyzerWorker));
|
||||
|
||||
instance->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(instance->thread, "subghz_frequency_analyzer_worker");
|
||||
furi_thread_set_name(instance->thread, "SubghzFAWorker");
|
||||
furi_thread_set_stack_size(instance->thread, 2048);
|
||||
furi_thread_set_context(instance->thread, instance);
|
||||
furi_thread_set_callback(instance->thread, subghz_frequency_analyzer_worker_thread);
|
||||
|
||||
@ -11,33 +11,33 @@ void subghz_scene_delete_callback(GuiButtonType result, InputType type, void* co
|
||||
|
||||
void subghz_scene_delete_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
char buffer_str[16];
|
||||
snprintf(
|
||||
buffer_str,
|
||||
sizeof(buffer_str),
|
||||
"%03ld.%02ld",
|
||||
subghz->txrx->frequency / 1000000 % 1000,
|
||||
subghz->txrx->frequency / 10000 % 100);
|
||||
widget_add_string_element(
|
||||
subghz->widget, 78, 0, AlignLeft, AlignTop, FontSecondary, buffer_str);
|
||||
if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
|
||||
snprintf(buffer_str, sizeof(buffer_str), "AM");
|
||||
} else if(
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) {
|
||||
snprintf(buffer_str, sizeof(buffer_str), "FM");
|
||||
} else {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
widget_add_string_element(
|
||||
subghz->widget, 113, 0, AlignLeft, AlignTop, FontSecondary, buffer_str);
|
||||
string_t frequency_str;
|
||||
string_t modulation_str;
|
||||
string_t text;
|
||||
|
||||
string_init(frequency_str);
|
||||
string_init(modulation_str);
|
||||
string_init(text);
|
||||
|
||||
subghz_get_frequency_modulation(subghz, frequency_str, modulation_str);
|
||||
widget_add_string_element(
|
||||
subghz->widget, 78, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(frequency_str));
|
||||
|
||||
widget_add_string_element(
|
||||
subghz->widget,
|
||||
113,
|
||||
0,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(modulation_str));
|
||||
|
||||
subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, text);
|
||||
widget_add_string_multiline_element(
|
||||
subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(text));
|
||||
|
||||
string_clear(frequency_str);
|
||||
string_clear(modulation_str);
|
||||
string_clear(text);
|
||||
|
||||
widget_add_button_element(
|
||||
@ -50,7 +50,7 @@ bool subghz_scene_delete_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubghzCustomEventSceneDelete) {
|
||||
memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name));
|
||||
memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name) + 1);
|
||||
if(subghz_delete_file(subghz)) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess);
|
||||
} else {
|
||||
|
||||
@ -6,27 +6,19 @@
|
||||
static void subghz_scene_read_raw_update_statusbar(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
char frequency_str[20];
|
||||
char preset_str[10];
|
||||
|
||||
snprintf(
|
||||
frequency_str,
|
||||
sizeof(frequency_str),
|
||||
"%03ld.%02ld",
|
||||
subghz->txrx->frequency / 1000000 % 1000,
|
||||
subghz->txrx->frequency / 10000 % 100);
|
||||
if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
|
||||
snprintf(preset_str, sizeof(preset_str), "AM");
|
||||
} else if(
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) {
|
||||
snprintf(preset_str, sizeof(preset_str), "FM");
|
||||
} else {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
string_t frequency_str;
|
||||
string_t modulation_str;
|
||||
|
||||
subghz_read_raw_add_data_statusbar(subghz->subghz_read_raw, frequency_str, preset_str);
|
||||
string_init(frequency_str);
|
||||
string_init(modulation_str);
|
||||
|
||||
subghz_get_frequency_modulation(subghz, frequency_str, modulation_str);
|
||||
subghz_read_raw_add_data_statusbar(
|
||||
subghz->subghz_read_raw, string_get_cstr(frequency_str), string_get_cstr(modulation_str));
|
||||
|
||||
string_clear(frequency_str);
|
||||
string_clear(modulation_str);
|
||||
}
|
||||
|
||||
void subghz_scene_read_raw_callback(SubghzCustomEvent event, void* context) {
|
||||
@ -70,7 +62,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
|
||||
subghz_protocol_raw_save_to_file_stop(
|
||||
(SubGhzProtocolRAW*)subghz->txrx->protocol_result);
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
|
||||
if(subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) {
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateExit;
|
||||
@ -95,7 +87,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
};
|
||||
subghz_protocol_raw_save_to_file_stop(
|
||||
(SubGhzProtocolRAW*)subghz->txrx->protocol_result);
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey;
|
||||
|
||||
@ -106,17 +98,18 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
if(subghz->txrx->rx_key_state != SubGhzRxKeyStateIDLE) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
|
||||
} else {
|
||||
subghz_get_preset_name(subghz, subghz->error_str);
|
||||
if(subghz_protocol_raw_save_to_file_init(
|
||||
(SubGhzProtocolRAW*)subghz->txrx->protocol_result,
|
||||
"Raw_temp",
|
||||
subghz->txrx->frequency,
|
||||
subghz->txrx->preset)) {
|
||||
string_get_cstr(subghz->error_str))) {
|
||||
if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) ||
|
||||
(subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
|
||||
subghz_begin(subghz, subghz->txrx->preset);
|
||||
subghz_rx(subghz, subghz->txrx->frequency);
|
||||
}
|
||||
subghz->state_notifications = NOTIFICATION_RX_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateRX;
|
||||
} else {
|
||||
string_set(subghz->error_str, "No SD card");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
@ -127,14 +120,14 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
break;
|
||||
case SubghzCustomEventViewReadRAWMore:
|
||||
if(strcmp(
|
||||
subghz_protocol_get_last_file_name(
|
||||
subghz_protocol_raw_get_last_file_name(
|
||||
(SubGhzProtocolRAW*)subghz->txrx->protocol_result),
|
||||
"")) {
|
||||
strlcpy(
|
||||
subghz->file_name,
|
||||
subghz_protocol_get_last_file_name(
|
||||
subghz_protocol_raw_get_last_file_name(
|
||||
(SubGhzProtocolRAW*)subghz->txrx->protocol_result),
|
||||
strlen(subghz_protocol_get_last_file_name(
|
||||
strlen(subghz_protocol_raw_get_last_file_name(
|
||||
(SubGhzProtocolRAW*)subghz->txrx->protocol_result)) +
|
||||
1);
|
||||
//set the path to read the file
|
||||
@ -145,7 +138,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
SUBGHZ_APP_PATH_FOLDER,
|
||||
subghz->file_name,
|
||||
SUBGHZ_APP_EXTENSION);
|
||||
subghz_protocol_set_last_file_name(
|
||||
subghz_protocol_raw_set_last_file_name(
|
||||
(SubGhzProtocolRAW*)subghz->txrx->protocol_result, string_get_cstr(temp_str));
|
||||
string_clear(temp_str);
|
||||
|
||||
@ -159,7 +152,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
switch(subghz->state_notifications) {
|
||||
case NOTIFICATION_RX_STATE:
|
||||
case SubGhzNotificationStateRX:
|
||||
notification_message(subghz->notifications, &sequence_blink_blue_10);
|
||||
subghz_read_raw_update_sample_write(
|
||||
subghz->subghz_read_raw,
|
||||
@ -182,7 +175,7 @@ void subghz_scene_read_raw_on_exit(void* context) {
|
||||
subghz_rx_end(subghz);
|
||||
subghz_sleep(subghz);
|
||||
};
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
|
||||
//Сallback restoration
|
||||
subghz_worker_set_pair_callback(
|
||||
|
||||
@ -3,33 +3,29 @@
|
||||
|
||||
static void subghz_scene_receiver_update_statusbar(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
char frequency_str[20];
|
||||
char preset_str[10];
|
||||
string_t history_stat_str;
|
||||
string_init(history_stat_str);
|
||||
if(!subghz_history_get_text_space_left(subghz->txrx->history, history_stat_str)) {
|
||||
snprintf(
|
||||
frequency_str,
|
||||
sizeof(frequency_str),
|
||||
"%03ld.%02ld",
|
||||
subghz->txrx->frequency / 1000000 % 1000,
|
||||
subghz->txrx->frequency / 10000 % 100);
|
||||
if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
|
||||
snprintf(preset_str, sizeof(preset_str), "AM");
|
||||
} else if(
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) {
|
||||
snprintf(preset_str, sizeof(preset_str), "FM");
|
||||
} else {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
string_t frequency_str;
|
||||
string_t modulation_str;
|
||||
|
||||
string_init(frequency_str);
|
||||
string_init(modulation_str);
|
||||
|
||||
subghz_get_frequency_modulation(subghz, frequency_str, modulation_str);
|
||||
|
||||
subghz_receiver_add_data_statusbar(
|
||||
subghz->subghz_receiver, frequency_str, preset_str, string_get_cstr(history_stat_str));
|
||||
subghz->subghz_receiver,
|
||||
string_get_cstr(frequency_str),
|
||||
string_get_cstr(modulation_str),
|
||||
string_get_cstr(history_stat_str));
|
||||
|
||||
string_clear(frequency_str);
|
||||
string_clear(modulation_str);
|
||||
} else {
|
||||
subghz_receiver_add_data_statusbar(
|
||||
subghz->subghz_receiver, string_get_cstr(history_stat_str), "", "");
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
}
|
||||
string_clear(history_stat_str);
|
||||
}
|
||||
@ -83,7 +79,7 @@ void subghz_scene_receiver_on_enter(void* context) {
|
||||
subghz_receiver_set_callback(subghz->subghz_receiver, subghz_scene_receiver_callback, subghz);
|
||||
subghz_parser_enable_dump(subghz->txrx->parser, subghz_scene_add_to_history_callback, subghz);
|
||||
|
||||
subghz->state_notifications = NOTIFICATION_RX_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateRX;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz);
|
||||
};
|
||||
@ -104,7 +100,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
switch(event.event) {
|
||||
case SubghzCustomEventViewReceverBack:
|
||||
// Stop CC1101 Rx
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz);
|
||||
subghz_sleep(subghz);
|
||||
@ -125,7 +121,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
return true;
|
||||
break;
|
||||
case SubghzCustomEventViewReceverConfig:
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
|
||||
return true;
|
||||
@ -140,7 +136,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
switch(subghz->state_notifications) {
|
||||
case NOTIFICATION_RX_STATE:
|
||||
case SubGhzNotificationStateRX:
|
||||
notification_message(subghz->notifications, &sequence_blink_blue_10);
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -40,35 +40,42 @@ void subghz_scene_receiver_info_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
if(subghz_scene_receiver_info_update_parser(subghz)) {
|
||||
char buffer_str[16];
|
||||
snprintf(
|
||||
buffer_str,
|
||||
sizeof(buffer_str),
|
||||
"%03ld.%02ld",
|
||||
subghz->txrx->frequency / 1000000 % 1000,
|
||||
subghz->txrx->frequency / 10000 % 100);
|
||||
widget_add_string_element(
|
||||
subghz->widget, 78, 0, AlignLeft, AlignTop, FontSecondary, buffer_str);
|
||||
if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
|
||||
snprintf(buffer_str, sizeof(buffer_str), "AM");
|
||||
} else if(
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) {
|
||||
snprintf(buffer_str, sizeof(buffer_str), "FM");
|
||||
} else {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
widget_add_string_element(
|
||||
subghz->widget, 113, 0, AlignLeft, AlignTop, FontSecondary, buffer_str);
|
||||
string_t frequency_str;
|
||||
string_t modulation_str;
|
||||
string_t text;
|
||||
|
||||
string_init(frequency_str);
|
||||
string_init(modulation_str);
|
||||
string_init(text);
|
||||
|
||||
subghz_get_frequency_modulation(subghz, frequency_str, modulation_str);
|
||||
widget_add_string_element(
|
||||
subghz->widget,
|
||||
78,
|
||||
0,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(frequency_str));
|
||||
|
||||
widget_add_string_element(
|
||||
subghz->widget,
|
||||
113,
|
||||
0,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(modulation_str));
|
||||
|
||||
subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, text);
|
||||
widget_add_string_multiline_element(
|
||||
subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(text));
|
||||
|
||||
string_clear(frequency_str);
|
||||
string_clear(modulation_str);
|
||||
string_clear(text);
|
||||
|
||||
if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_string &&
|
||||
if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_file &&
|
||||
strcmp(subghz->txrx->protocol_result->name, "KeeLoq")) {
|
||||
widget_add_button_element(
|
||||
subghz->widget,
|
||||
@ -112,13 +119,13 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
if(!subghz_tx_start(subghz)) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx);
|
||||
} else {
|
||||
subghz->state_notifications = NOTIFICATION_TX_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateTX;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubghzCustomEventSceneReceiverInfoTxStop) {
|
||||
//CC1101 Stop Tx -> Start RX
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
}
|
||||
@ -129,11 +136,11 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
if(subghz->txrx->hopper_state == SubGhzHopperStatePause) {
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
|
||||
}
|
||||
subghz->state_notifications = NOTIFICATION_RX_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateRX;
|
||||
return true;
|
||||
} else if(event.event == SubghzCustomEventSceneReceiverInfoSave) {
|
||||
//CC1101 Stop RX -> Save
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) {
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
||||
}
|
||||
@ -144,7 +151,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
if(!subghz_scene_receiver_info_update_parser(subghz)) {
|
||||
return false;
|
||||
}
|
||||
if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_string &&
|
||||
if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_file &&
|
||||
strcmp(subghz->txrx->protocol_result->name, "KeeLoq")) {
|
||||
subghz_file_name_clear(subghz);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
|
||||
@ -156,10 +163,10 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
subghz_hopper_update(subghz);
|
||||
}
|
||||
switch(subghz->state_notifications) {
|
||||
case NOTIFICATION_TX_STATE:
|
||||
case SubGhzNotificationStateTX:
|
||||
notification_message(subghz->notifications, &sequence_blink_red_10);
|
||||
break;
|
||||
case NOTIFICATION_RX_STATE:
|
||||
case SubGhzNotificationStateRX:
|
||||
notification_message(subghz->notifications, &sequence_blink_blue_10);
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -19,7 +19,7 @@ void subghz_scene_save_name_on_enter(void* context) {
|
||||
set_random_name(subghz->file_name, sizeof(subghz->file_name));
|
||||
dev_name_empty = true;
|
||||
} else {
|
||||
memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name));
|
||||
memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name) + 1);
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAWMenu) ==
|
||||
SubghzCustomEventManagerSet) {
|
||||
subghz_get_next_name_file(subghz);
|
||||
|
||||
@ -16,8 +16,8 @@ void subghz_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
|
||||
void subghz_scene_start_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
if(subghz->state_notifications == NOTIFICATION_STARTING_STATE) {
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
if(subghz->state_notifications == SubGhzNotificationStateStarting) {
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
}
|
||||
submenu_add_item(
|
||||
subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz);
|
||||
|
||||
@ -13,9 +13,12 @@ bool subghz_scene_transmitter_update_data_show(void* context) {
|
||||
|
||||
if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->get_upload_protocol) {
|
||||
string_t key_str;
|
||||
string_t frequency_str;
|
||||
string_t modulation_str;
|
||||
|
||||
string_init(key_str);
|
||||
char frequency_str[10];
|
||||
char preset_str[6];
|
||||
string_init(frequency_str);
|
||||
string_init(modulation_str);
|
||||
uint8_t show_button = 0;
|
||||
subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, key_str);
|
||||
|
||||
@ -27,29 +30,17 @@ bool subghz_scene_transmitter_update_data_show(void* context) {
|
||||
} else {
|
||||
show_button = 1;
|
||||
}
|
||||
snprintf(
|
||||
frequency_str,
|
||||
sizeof(frequency_str),
|
||||
"%03ld.%02ld",
|
||||
subghz->txrx->frequency / 1000000 % 1000,
|
||||
subghz->txrx->frequency / 10000 % 100);
|
||||
if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
|
||||
snprintf(preset_str, sizeof(preset_str), "AM");
|
||||
} else if(
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) {
|
||||
snprintf(preset_str, sizeof(preset_str), "FM");
|
||||
} else {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
|
||||
subghz_get_frequency_modulation(subghz, frequency_str, modulation_str);
|
||||
subghz_transmitter_add_data_to_show(
|
||||
subghz->subghz_transmitter,
|
||||
string_get_cstr(key_str),
|
||||
frequency_str,
|
||||
preset_str,
|
||||
string_get_cstr(frequency_str),
|
||||
string_get_cstr(modulation_str),
|
||||
show_button);
|
||||
|
||||
string_clear(frequency_str);
|
||||
string_clear(modulation_str);
|
||||
string_clear(key_str);
|
||||
|
||||
return true;
|
||||
@ -67,7 +58,7 @@ void subghz_scene_transmitter_on_enter(void* context) {
|
||||
subghz_transmitter_set_callback(
|
||||
subghz->subghz_transmitter, subghz_scene_transmitter_callback, subghz);
|
||||
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTransmitter);
|
||||
}
|
||||
|
||||
@ -75,7 +66,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubghzCustomEventViewTransmitterSendStart) {
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz);
|
||||
}
|
||||
@ -84,20 +75,20 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
|
||||
if(!subghz_tx_start(subghz)) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx);
|
||||
} else {
|
||||
subghz->state_notifications = NOTIFICATION_TX_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateTX;
|
||||
subghz_scene_transmitter_update_data_show(subghz);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubghzCustomEventViewTransmitterSendStop) {
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
subghz_sleep(subghz);
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubghzCustomEventViewTransmitterBack) {
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
return true;
|
||||
@ -106,7 +97,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subghz->state_notifications == NOTIFICATION_TX_STATE) {
|
||||
if(subghz->state_notifications == SubGhzNotificationStateTX) {
|
||||
notification_message(subghz->notifications, &sequence_blink_red_10);
|
||||
}
|
||||
return true;
|
||||
@ -117,5 +108,5 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
|
||||
void subghz_scene_transmitter_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include "subghz_i.h"
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
const char* const subghz_frequencies_text[] = {
|
||||
"300.00",
|
||||
@ -119,6 +120,9 @@ SubGhz* subghz_alloc() {
|
||||
view_dispatcher_add_view(
|
||||
subghz->view_dispatcher, SubGhzViewWidget, widget_get_view(subghz->widget));
|
||||
|
||||
//Dialog
|
||||
subghz->dialogs = furi_record_open("dialogs");
|
||||
|
||||
// Transmitter
|
||||
subghz->subghz_transmitter = subghz_transmitter_alloc();
|
||||
view_dispatcher_add_view(
|
||||
@ -224,6 +228,9 @@ void subghz_free(SubGhz* subghz) {
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewWidget);
|
||||
widget_free(subghz->widget);
|
||||
|
||||
//Dialog
|
||||
furi_record_close("dialogs");
|
||||
|
||||
// Transmitter
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTransmitter);
|
||||
subghz_transmitter_free(subghz->subghz_transmitter);
|
||||
@ -280,6 +287,14 @@ int32_t subghz_app(void* p) {
|
||||
|
||||
// Check argument and run corresponding scene
|
||||
if(p && subghz_key_load(subghz, p)) {
|
||||
string_t filename;
|
||||
string_init(filename);
|
||||
|
||||
path_extract_filename_no_ext(p, filename);
|
||||
strlcpy(
|
||||
subghz->file_name, string_get_cstr(filename), strlen(string_get_cstr(filename)) + 1);
|
||||
string_clear(filename);
|
||||
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTransmitter);
|
||||
} else {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStart);
|
||||
|
||||
@ -6,10 +6,74 @@
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <notification/notification-messages.h>
|
||||
#include "file-worker.h"
|
||||
#include <lib/flipper_file/flipper_file.h>
|
||||
#include "../notification/notification.h"
|
||||
#include "views/subghz_receiver.h"
|
||||
|
||||
bool subghz_set_pteset(SubGhz* subghz, const char* preset) {
|
||||
if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) {
|
||||
subghz->txrx->preset = FuriHalSubGhzPresetOok270Async;
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) {
|
||||
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) {
|
||||
subghz->txrx->preset = FuriHalSubGhzPreset2FSKDev238Async;
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) {
|
||||
subghz->txrx->preset = FuriHalSubGhzPreset2FSKDev476Async;
|
||||
} else {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unknown preset");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool subghz_get_preset_name(SubGhz* subghz, string_t preset) {
|
||||
const char* preset_name;
|
||||
switch(subghz->txrx->preset) {
|
||||
case FuriHalSubGhzPresetOok270Async:
|
||||
preset_name = "FuriHalSubGhzPresetOok270Async";
|
||||
break;
|
||||
case FuriHalSubGhzPresetOok650Async:
|
||||
preset_name = "FuriHalSubGhzPresetOok650Async";
|
||||
break;
|
||||
case FuriHalSubGhzPreset2FSKDev238Async:
|
||||
preset_name = "FuriHalSubGhzPreset2FSKDev238Async";
|
||||
break;
|
||||
case FuriHalSubGhzPreset2FSKDev476Async:
|
||||
preset_name = "FuriHalSubGhzPreset2FSKDev476Async";
|
||||
break;
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unknown preset");
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
string_set(preset, preset_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_t modulation) {
|
||||
furi_assert(subghz);
|
||||
if(frequency != NULL) {
|
||||
string_printf(
|
||||
frequency,
|
||||
"%03ld.%02ld",
|
||||
subghz->txrx->frequency / 1000000 % 1000,
|
||||
subghz->txrx->frequency / 10000 % 100);
|
||||
}
|
||||
|
||||
if(modulation != NULL) {
|
||||
if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
|
||||
string_set(modulation, "AM");
|
||||
} else if(
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) {
|
||||
string_set(modulation, "FM");
|
||||
} else {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset) {
|
||||
furi_assert(subghz);
|
||||
furi_hal_subghz_reset();
|
||||
@ -79,17 +143,6 @@ void subghz_sleep(SubGhz* subghz) {
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
|
||||
}
|
||||
|
||||
static void subghz_frequency_preset_to_str(SubGhz* subghz, string_t output) {
|
||||
furi_assert(subghz);
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Frequency: %d\n"
|
||||
"Preset: %d\n",
|
||||
(int)subghz->txrx->frequency,
|
||||
(int)subghz->txrx->preset);
|
||||
}
|
||||
|
||||
bool subghz_tx_start(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
|
||||
@ -144,66 +197,78 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(file_path);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
Storage* storage = furi_record_open("storage");
|
||||
FlipperFile* flipper_file = flipper_file_alloc(storage);
|
||||
|
||||
// Load device data
|
||||
bool loaded = false;
|
||||
string_t path;
|
||||
string_init_set_str(path, file_path);
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
uint32_t version;
|
||||
|
||||
do {
|
||||
if(!file_worker_open(file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
if(!flipper_file_open_existing(flipper_file, string_get_cstr(path))) {
|
||||
FURI_LOG_E(
|
||||
SUBGHZ_PARSER_TAG, "Unable to open file for read: %s", string_get_cstr(path));
|
||||
break;
|
||||
}
|
||||
if(!flipper_file_read_header(flipper_file, temp_str, &version)) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing or incorrect header");
|
||||
break;
|
||||
}
|
||||
|
||||
// Read and parse frequency from 1st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
if(((!strcmp(string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
|
||||
(!strcmp(string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
|
||||
version == SUBGHZ_KEY_FILE_VERSION) {
|
||||
} else {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Type or version mismatch");
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
subghz->txrx->frequency = (uint32_t)data;
|
||||
|
||||
// Read and parse preset from 2st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
if(!flipper_file_read_uint32(
|
||||
flipper_file, "Frequency", (uint32_t*)&subghz->txrx->frequency, 1)) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing Frequency");
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
subghz->txrx->preset = (FuriHalSubGhzPreset)data;
|
||||
|
||||
// Read and parse name protocol from 2st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
if(!flipper_file_read_string(flipper_file, "Preset", temp_str)) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing Preset");
|
||||
break;
|
||||
}
|
||||
// strlen("Protocol: ") = 10
|
||||
string_right(temp_str, 10);
|
||||
if(!subghz_set_pteset(subghz, string_get_cstr(temp_str))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_file_read_string(flipper_file, "Protocol", temp_str)) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_parser_get_by_name(subghz->txrx->parser, string_get_cstr(temp_str));
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "This type of protocol was not found");
|
||||
break;
|
||||
}
|
||||
if(!subghz->txrx->protocol_result->to_load_protocol_from_file(
|
||||
file_worker, subghz->txrx->protocol_result, string_get_cstr(path))) {
|
||||
flipper_file, subghz->txrx->protocol_result, string_get_cstr(path))) {
|
||||
break;
|
||||
}
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
if(!loaded) {
|
||||
file_worker_show_error(file_worker, "Cannot parse\nfile");
|
||||
dialog_message_show_storage_error(subghz->dialogs, "Cannot parse\nfile");
|
||||
}
|
||||
string_clear(temp_str);
|
||||
string_clear(path);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
|
||||
flipper_file_close(flipper_file);
|
||||
flipper_file_free(flipper_file);
|
||||
|
||||
furi_record_close("storage");
|
||||
|
||||
return loaded;
|
||||
}
|
||||
@ -211,23 +276,22 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
bool subghz_get_next_name_file(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
Storage* storage = furi_record_open("storage");
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
bool res = false;
|
||||
|
||||
if(strcmp(subghz->file_name, "")) {
|
||||
//get the name of the next free file
|
||||
file_worker_get_next_filename(
|
||||
file_worker, SUBGHZ_RAW_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION, temp_str);
|
||||
storage_get_next_filename(
|
||||
storage, SUBGHZ_RAW_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION, temp_str);
|
||||
|
||||
memcpy(subghz->file_name, string_get_cstr(temp_str), strlen(string_get_cstr(temp_str)));
|
||||
res = true;
|
||||
}
|
||||
|
||||
string_clear(temp_str);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
furi_record_close("storage");
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -236,7 +300,8 @@ bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(subghz->txrx->protocol_result);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
Storage* storage = furi_record_open("storage");
|
||||
FlipperFile* flipper_file = flipper_file_alloc(storage);
|
||||
string_t dev_file_name;
|
||||
string_init(dev_file_name);
|
||||
string_t temp_str;
|
||||
@ -244,43 +309,71 @@ bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name) {
|
||||
bool saved = false;
|
||||
|
||||
do {
|
||||
// Checking that this type of people can be saved
|
||||
if(subghz->txrx->protocol_result->to_save_file == NULL) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "No saving of this type of keys");
|
||||
break;
|
||||
}
|
||||
// Create subghz folder directory if necessary
|
||||
if(!file_worker_mkdir(file_worker, SUBGHZ_APP_FOLDER)) {
|
||||
if(!storage_simply_mkdir(storage, SUBGHZ_APP_FOLDER)) {
|
||||
dialog_message_show_storage_error(subghz->dialogs, "Cannot create\nfolder");
|
||||
break;
|
||||
}
|
||||
// Create saved directory if necessary
|
||||
if(!file_worker_mkdir(file_worker, SUBGHZ_APP_PATH_FOLDER)) {
|
||||
if(!storage_simply_mkdir(storage, SUBGHZ_APP_FOLDER)) {
|
||||
dialog_message_show_storage_error(subghz->dialogs, "Cannot create\nfolder");
|
||||
break;
|
||||
}
|
||||
|
||||
// First remove subghz device file if it was saved
|
||||
string_printf(
|
||||
dev_file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, dev_name, SUBGHZ_APP_EXTENSION);
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) {
|
||||
|
||||
if(!storage_simply_remove(storage, string_get_cstr(dev_file_name))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Open file
|
||||
if(!file_worker_open(
|
||||
file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
||||
if(!flipper_file_open_always(flipper_file, string_get_cstr(dev_file_name))) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to open file for write: %s", dev_file_name);
|
||||
break;
|
||||
}
|
||||
//Get string frequency preset protocol
|
||||
subghz_frequency_preset_to_str(subghz, temp_str);
|
||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) {
|
||||
|
||||
if(!flipper_file_write_header_cstr(
|
||||
flipper_file, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add header");
|
||||
break;
|
||||
}
|
||||
//Get string save
|
||||
subghz->txrx->protocol_result->to_save_string(subghz->txrx->protocol_result, temp_str);
|
||||
// Prepare and write data to file
|
||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) {
|
||||
|
||||
if(!flipper_file_write_uint32(
|
||||
flipper_file, "Frequency", (uint32_t*)&subghz->txrx->frequency, 1)) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add Frequency");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!subghz_get_preset_name(subghz, temp_str)) {
|
||||
break;
|
||||
}
|
||||
if(!flipper_file_write_string_cstr(flipper_file, "Preset", string_get_cstr(temp_str))) {
|
||||
FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add Preset");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!subghz->txrx->protocol_result->to_save_file(
|
||||
subghz->txrx->protocol_result, flipper_file)) {
|
||||
break;
|
||||
}
|
||||
|
||||
saved = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
string_clear(dev_file_name);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
|
||||
flipper_file_close(flipper_file);
|
||||
flipper_file_free(flipper_file);
|
||||
|
||||
furi_record_close("storage");
|
||||
|
||||
return saved;
|
||||
}
|
||||
@ -288,17 +381,12 @@ bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name) {
|
||||
bool subghz_load_protocol_from_file(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
string_t protocol_file_name;
|
||||
string_init(protocol_file_name);
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int sscanf_res = 0;
|
||||
int data = 0;
|
||||
string_t file_name;
|
||||
string_init(file_name);
|
||||
|
||||
// Input events and views are managed by file_select
|
||||
bool res = file_worker_file_select(
|
||||
file_worker,
|
||||
bool res = dialog_file_select_show(
|
||||
subghz->dialogs,
|
||||
SUBGHZ_APP_PATH_FOLDER,
|
||||
SUBGHZ_APP_EXTENSION,
|
||||
subghz->file_name,
|
||||
@ -306,87 +394,24 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) {
|
||||
NULL);
|
||||
|
||||
if(res) {
|
||||
// Get key file path
|
||||
string_printf(
|
||||
protocol_file_name,
|
||||
"%s/%s%s",
|
||||
SUBGHZ_APP_PATH_FOLDER,
|
||||
subghz->file_name,
|
||||
SUBGHZ_APP_EXTENSION);
|
||||
} else {
|
||||
string_clear(temp_str);
|
||||
string_clear(protocol_file_name);
|
||||
file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION);
|
||||
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
return res;
|
||||
}
|
||||
res = false;
|
||||
do {
|
||||
if(!file_worker_open(
|
||||
file_worker, string_get_cstr(protocol_file_name), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
return res;
|
||||
}
|
||||
// Read and parse frequency from 1st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
sscanf_res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data);
|
||||
if(sscanf_res != 1) {
|
||||
break;
|
||||
}
|
||||
subghz->txrx->frequency = (uint32_t)data;
|
||||
|
||||
// Read and parse preset from 2st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
sscanf_res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data);
|
||||
if(sscanf_res != 1) {
|
||||
break;
|
||||
}
|
||||
subghz->txrx->preset = (FuriHalSubGhzPreset)data;
|
||||
|
||||
// Read and parse name protocol from 3st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
// strlen("Protocol: ") = 10
|
||||
string_right(temp_str, 10);
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_parser_get_by_name(subghz->txrx->parser, string_get_cstr(temp_str));
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(subghz->txrx->protocol_result->to_load_protocol_from_file == NULL ||
|
||||
!subghz->txrx->protocol_result->to_load_protocol_from_file(
|
||||
file_worker, subghz->txrx->protocol_result, string_get_cstr(protocol_file_name))) {
|
||||
break;
|
||||
}
|
||||
res = true;
|
||||
} while(0);
|
||||
|
||||
if(!res) {
|
||||
file_worker_show_error(file_worker, "Cannot parse\nfile");
|
||||
res = subghz_key_load(subghz, string_get_cstr(file_name));
|
||||
}
|
||||
|
||||
string_clear(temp_str);
|
||||
string_clear(protocol_file_name);
|
||||
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
string_clear(file_name);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool subghz_rename_file(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
bool ret = false;
|
||||
bool ret = true;
|
||||
string_t old_path;
|
||||
string_t new_path;
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
Storage* storage = furi_record_open("storage");
|
||||
|
||||
string_init_printf(
|
||||
old_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name_tmp, SUBGHZ_APP_EXTENSION);
|
||||
@ -394,39 +419,33 @@ bool subghz_rename_file(SubGhz* subghz) {
|
||||
string_init_printf(
|
||||
new_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION);
|
||||
|
||||
ret = file_worker_rename(file_worker, string_get_cstr(old_path), string_get_cstr(new_path));
|
||||
FS_Error fs_result =
|
||||
storage_common_rename(storage, string_get_cstr(old_path), string_get_cstr(new_path));
|
||||
|
||||
if(fs_result != FSE_OK && fs_result != FSE_EXIST) {
|
||||
dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
string_clear(old_path);
|
||||
string_clear(new_path);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
furi_record_close("storage");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool subghz_delete_file(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
|
||||
bool result = true;
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
Storage* storage = furi_record_open("storage");
|
||||
string_t file_path;
|
||||
string_init_printf(
|
||||
file_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name_tmp, SUBGHZ_APP_EXTENSION);
|
||||
bool result = storage_simply_remove(storage, string_get_cstr(file_path));
|
||||
furi_record_close("storage");
|
||||
|
||||
do {
|
||||
// Get key file path
|
||||
string_init_printf(
|
||||
file_path,
|
||||
"%s/%s%s",
|
||||
SUBGHZ_APP_PATH_FOLDER,
|
||||
subghz->file_name_tmp,
|
||||
SUBGHZ_APP_EXTENSION);
|
||||
// Delete original file
|
||||
if(!file_worker_remove(file_worker, string_get_cstr(file_path))) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
} while(0);
|
||||
subghz_file_name_clear(subghz);
|
||||
|
||||
string_clear(file_path);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
#include <gui/gui.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <notification/notification-messages.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
@ -33,11 +34,6 @@
|
||||
|
||||
#define SUBGHZ_TEXT_STORE_SIZE 40
|
||||
|
||||
#define NOTIFICATION_STARTING_STATE 0u
|
||||
#define NOTIFICATION_IDLE_STATE 1u
|
||||
#define NOTIFICATION_TX_STATE 2u
|
||||
#define NOTIFICATION_RX_STATE 3u
|
||||
|
||||
extern const char* const subghz_frequencies_text[];
|
||||
extern const uint32_t subghz_frequencies[];
|
||||
extern const uint32_t subghz_hopper_frequencies[];
|
||||
@ -45,6 +41,14 @@ extern const uint32_t subghz_frequencies_count;
|
||||
extern const uint32_t subghz_hopper_frequencies_count;
|
||||
extern const uint32_t subghz_frequencies_433_92;
|
||||
|
||||
/** SubGhzNotification state */
|
||||
typedef enum {
|
||||
SubGhzNotificationStateStarting,
|
||||
SubGhzNotificationStateIDLE,
|
||||
SubGhzNotificationStateTX,
|
||||
SubGhzNotificationStateRX,
|
||||
} SubGhzNotificationState;
|
||||
|
||||
/** SubGhzTxRx state */
|
||||
typedef enum {
|
||||
SubGhzTxRxStateIDLE,
|
||||
@ -101,9 +105,10 @@ struct SubGhz {
|
||||
Popup* popup;
|
||||
TextInput* text_input;
|
||||
Widget* widget;
|
||||
DialogsApp* dialogs;
|
||||
char file_name[SUBGHZ_TEXT_STORE_SIZE + 1];
|
||||
char file_name_tmp[SUBGHZ_TEXT_STORE_SIZE + 1];
|
||||
uint8_t state_notifications;
|
||||
SubGhzNotificationState state_notifications;
|
||||
|
||||
SubghzReceiver* subghz_receiver;
|
||||
SubghzTransmitter* subghz_transmitter;
|
||||
@ -133,6 +138,9 @@ typedef enum {
|
||||
SubGhzViewTestPacket,
|
||||
} SubGhzView;
|
||||
|
||||
bool subghz_set_pteset(SubGhz* subghz, const char* preset);
|
||||
bool subghz_get_preset_name(SubGhz* subghz, string_t preset);
|
||||
void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_t modulation);
|
||||
void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset);
|
||||
uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency);
|
||||
void subghz_rx_end(SubGhz* subghz);
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
#include <notification/notification-messages.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_princeton.h>
|
||||
|
||||
#define TAG "SubGhzTestStatic"
|
||||
|
||||
typedef enum {
|
||||
SubghzTestStaticStatusIDLE,
|
||||
SubghzTestStaticStatusTX,
|
||||
@ -99,7 +101,7 @@ bool subghz_test_static_input(InputEvent* event, void* context) {
|
||||
} else {
|
||||
notification_message_block(notification, &sequence_set_red_255);
|
||||
|
||||
FURI_LOG_I("SubghzTestStatic", "TX Start");
|
||||
FURI_LOG_I(TAG, "TX Start");
|
||||
|
||||
subghz_encoder_princeton_set(
|
||||
instance->encoder, subghz_test_static_keys[model->button], 10000);
|
||||
@ -110,7 +112,7 @@ bool subghz_test_static_input(InputEvent* event, void* context) {
|
||||
}
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
if(instance->satus_tx == SubghzTestStaticStatusTX) {
|
||||
FURI_LOG_I("SubghzTestStatic", "TX Stop");
|
||||
FURI_LOG_I(TAG, "TX Stop");
|
||||
subghz_encoder_princeton_print_log(instance->encoder);
|
||||
furi_hal_subghz_stop_async_tx();
|
||||
notification_message(notification, &sequence_reset_red);
|
||||
|
||||
@ -29,7 +29,7 @@ static RpcSession* session = NULL;
|
||||
static StreamBufferHandle_t output_stream = NULL;
|
||||
static uint32_t command_id = 0;
|
||||
|
||||
#define TEST_RPC_TAG "TEST_RPC"
|
||||
#define TAG "UnitTestsRpc"
|
||||
#define MAX_RECEIVE_OUTPUT_TIMEOUT 3000
|
||||
#define MAX_NAME_LENGTH 255
|
||||
#define MAX_DATA_SIZE 512 // have to be exact as in rpc_storage.c
|
||||
@ -1334,7 +1334,7 @@ int run_minunit_test_rpc() {
|
||||
Storage* storage = furi_record_open("storage");
|
||||
furi_record_close("storage");
|
||||
if(storage_sd_status(storage) != FSE_OK) {
|
||||
FURI_LOG_E("UNIT_TESTS", "SD card not mounted - skip storage tests");
|
||||
FURI_LOG_E(TAG, "SD card not mounted - skip storage tests");
|
||||
} else {
|
||||
MU_RUN_SUITE(test_rpc_storage);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#include <cli/cli.h>
|
||||
#include <loader/loader.h>
|
||||
|
||||
#define TESTS_TAG "UNIT_TESTS"
|
||||
#define TAG "UnitTests"
|
||||
|
||||
int run_minunit();
|
||||
int run_minunit_test_irda_decoder_encoder();
|
||||
@ -42,7 +42,7 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) {
|
||||
|
||||
// TODO: lock device while test running
|
||||
if(loader_is_locked(loader)) {
|
||||
FURI_LOG_E(TESTS_TAG, "RPC: stop all applications to run tests");
|
||||
FURI_LOG_E(TAG, "RPC: stop all applications to run tests");
|
||||
notification_message(notification, &sequence_blink_magenta_100);
|
||||
} else {
|
||||
notification_message_block(notification, &sequence_set_only_blue_255);
|
||||
@ -56,21 +56,21 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) {
|
||||
test_result |= run_minunit_test_flipper_file();
|
||||
cycle_counter = (DWT->CYCCNT - cycle_counter);
|
||||
|
||||
FURI_LOG_I(TESTS_TAG, "Consumed: %0.2fs", (float)cycle_counter / (SystemCoreClock));
|
||||
FURI_LOG_I(TAG, "Consumed: %0.2fs", (float)cycle_counter / (SystemCoreClock));
|
||||
|
||||
if(test_result == 0) {
|
||||
delay(200); /* wait for tested services and apps to deallocate */
|
||||
uint32_t heap_after = memmgr_get_free_heap();
|
||||
notification_message(notification, &sequence_success);
|
||||
if(heap_after != heap_before) {
|
||||
FURI_LOG_E(TESTS_TAG, "Leaked: %d", heap_before - heap_after);
|
||||
FURI_LOG_E(TAG, "Leaked: %d", heap_before - heap_after);
|
||||
} else {
|
||||
FURI_LOG_I(TESTS_TAG, "No leaks");
|
||||
FURI_LOG_I(TAG, "No leaks");
|
||||
}
|
||||
FURI_LOG_I(TESTS_TAG, "PASSED");
|
||||
FURI_LOG_I(TAG, "PASSED");
|
||||
} else {
|
||||
notification_message(notification, &sequence_error);
|
||||
FURI_LOG_E(TESTS_TAG, "FAILED");
|
||||
FURI_LOG_E(TAG, "FAILED");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,10 @@ typedef enum _PB_CommandStatus {
|
||||
PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY = 18, /* *< Directory, you're going to remove is not empty */
|
||||
/* *< Application Errors */
|
||||
PB_CommandStatus_ERROR_APP_CANT_START = 16, /* *< Can't start app - internal error */
|
||||
PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED = 17 /* *< Another app is running */
|
||||
PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED = 17, /* *< Another app is running */
|
||||
/* *< Virtual Display Errors */
|
||||
PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_ALREADY_STARTED = 19, /* *< Virtual Display session can't be started twice */
|
||||
PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED = 20 /* *< Virtual Display session can't be stopped when it's not started */
|
||||
} PB_CommandStatus;
|
||||
|
||||
/* Struct definitions */
|
||||
@ -76,18 +79,20 @@ typedef struct _PB_Main {
|
||||
PB_StopSession stop_session;
|
||||
PB_Gui_StartScreenStreamRequest gui_start_screen_stream_request;
|
||||
PB_Gui_StopScreenStreamRequest gui_stop_screen_stream_request;
|
||||
PB_Gui_ScreenStreamFrame gui_screen_stream_frame;
|
||||
PB_Gui_ScreenFrame gui_screen_frame;
|
||||
PB_Gui_SendInputEventRequest gui_send_input_event_request;
|
||||
PB_Storage_StatRequest storage_stat_request;
|
||||
PB_Storage_StatResponse storage_stat_response;
|
||||
PB_Gui_StartVirtualDisplayRequest gui_start_virtual_display_request;
|
||||
PB_Gui_StopVirtualDisplayRequest gui_stop_virtual_display_request;
|
||||
} content;
|
||||
} PB_Main;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _PB_CommandStatus_MIN PB_CommandStatus_OK
|
||||
#define _PB_CommandStatus_MAX PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY
|
||||
#define _PB_CommandStatus_ARRAYSIZE ((PB_CommandStatus)(PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY+1))
|
||||
#define _PB_CommandStatus_MAX PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED
|
||||
#define _PB_CommandStatus_ARRAYSIZE ((PB_CommandStatus)(PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -124,10 +129,12 @@ extern "C" {
|
||||
#define PB_Main_stop_session_tag 19
|
||||
#define PB_Main_gui_start_screen_stream_request_tag 20
|
||||
#define PB_Main_gui_stop_screen_stream_request_tag 21
|
||||
#define PB_Main_gui_screen_stream_frame_tag 22
|
||||
#define PB_Main_gui_screen_frame_tag 22
|
||||
#define PB_Main_gui_send_input_event_request_tag 23
|
||||
#define PB_Main_storage_stat_request_tag 24
|
||||
#define PB_Main_storage_stat_response_tag 25
|
||||
#define PB_Main_gui_start_virtual_display_request_tag 26
|
||||
#define PB_Main_gui_stop_virtual_display_request_tag 27
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define PB_Empty_FIELDLIST(X, a) \
|
||||
@ -162,10 +169,12 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,app_lock_status_response,content.app
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,stop_session,content.stop_session), 19) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_start_screen_stream_request,content.gui_start_screen_stream_request), 20) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_stop_screen_stream_request,content.gui_stop_screen_stream_request), 21) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_screen_stream_frame,content.gui_screen_stream_frame), 22) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_screen_frame,content.gui_screen_frame), 22) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_send_input_event_request,content.gui_send_input_event_request), 23) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_request,content.storage_stat_request), 24) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_response,content.storage_stat_response), 25)
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_response,content.storage_stat_response), 25) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_start_virtual_display_request,content.gui_start_virtual_display_request), 26) \
|
||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_stop_virtual_display_request,content.gui_stop_virtual_display_request), 27)
|
||||
#define PB_Main_CALLBACK NULL
|
||||
#define PB_Main_DEFAULT NULL
|
||||
#define PB_Main_content_empty_MSGTYPE PB_Empty
|
||||
@ -186,10 +195,12 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_response,content.storag
|
||||
#define PB_Main_content_stop_session_MSGTYPE PB_StopSession
|
||||
#define PB_Main_content_gui_start_screen_stream_request_MSGTYPE PB_Gui_StartScreenStreamRequest
|
||||
#define PB_Main_content_gui_stop_screen_stream_request_MSGTYPE PB_Gui_StopScreenStreamRequest
|
||||
#define PB_Main_content_gui_screen_stream_frame_MSGTYPE PB_Gui_ScreenStreamFrame
|
||||
#define PB_Main_content_gui_screen_frame_MSGTYPE PB_Gui_ScreenFrame
|
||||
#define PB_Main_content_gui_send_input_event_request_MSGTYPE PB_Gui_SendInputEventRequest
|
||||
#define PB_Main_content_storage_stat_request_MSGTYPE PB_Storage_StatRequest
|
||||
#define PB_Main_content_storage_stat_response_MSGTYPE PB_Storage_StatResponse
|
||||
#define PB_Main_content_gui_start_virtual_display_request_MSGTYPE PB_Gui_StartVirtualDisplayRequest
|
||||
#define PB_Main_content_gui_stop_virtual_display_request_MSGTYPE PB_Gui_StopVirtualDisplayRequest
|
||||
|
||||
extern const pb_msgdesc_t PB_Empty_msg;
|
||||
extern const pb_msgdesc_t PB_StopSession_msg;
|
||||
@ -203,9 +214,9 @@ extern const pb_msgdesc_t PB_Main_msg;
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define PB_Empty_size 0
|
||||
#define PB_StopSession_size 0
|
||||
#if defined(PB_Storage_ListRequest_size) && defined(PB_Storage_ListResponse_size) && defined(PB_Storage_ReadRequest_size) && defined(PB_Storage_ReadResponse_size) && defined(PB_Storage_WriteRequest_size) && defined(PB_Storage_DeleteRequest_size) && defined(PB_Storage_MkdirRequest_size) && defined(PB_Storage_Md5sumRequest_size) && defined(PB_App_StartRequest_size) && defined(PB_Gui_ScreenStreamFrame_size) && defined(PB_Storage_StatRequest_size) && defined(PB_Storage_StatResponse_size)
|
||||
#if defined(PB_Storage_ListRequest_size) && defined(PB_Storage_ListResponse_size) && defined(PB_Storage_ReadRequest_size) && defined(PB_Storage_ReadResponse_size) && defined(PB_Storage_WriteRequest_size) && defined(PB_Storage_DeleteRequest_size) && defined(PB_Storage_MkdirRequest_size) && defined(PB_Storage_Md5sumRequest_size) && defined(PB_App_StartRequest_size) && defined(PB_Gui_ScreenFrame_size) && defined(PB_Storage_StatRequest_size) && defined(PB_Storage_StatResponse_size)
|
||||
#define PB_Main_size (10 + sizeof(union PB_Main_content_size_union))
|
||||
union PB_Main_content_size_union {char f7[(6 + PB_Storage_ListRequest_size)]; char f8[(6 + PB_Storage_ListResponse_size)]; char f9[(6 + PB_Storage_ReadRequest_size)]; char f10[(6 + PB_Storage_ReadResponse_size)]; char f11[(6 + PB_Storage_WriteRequest_size)]; char f12[(6 + PB_Storage_DeleteRequest_size)]; char f13[(6 + PB_Storage_MkdirRequest_size)]; char f14[(6 + PB_Storage_Md5sumRequest_size)]; char f16[(7 + PB_App_StartRequest_size)]; char f22[(7 + PB_Gui_ScreenStreamFrame_size)]; char f24[(7 + PB_Storage_StatRequest_size)]; char f25[(7 + PB_Storage_StatResponse_size)]; char f0[36];};
|
||||
union PB_Main_content_size_union {char f7[(6 + PB_Storage_ListRequest_size)]; char f8[(6 + PB_Storage_ListResponse_size)]; char f9[(6 + PB_Storage_ReadRequest_size)]; char f10[(6 + PB_Storage_ReadResponse_size)]; char f11[(6 + PB_Storage_WriteRequest_size)]; char f12[(6 + PB_Storage_DeleteRequest_size)]; char f13[(6 + PB_Storage_MkdirRequest_size)]; char f14[(6 + PB_Storage_Md5sumRequest_size)]; char f16[(7 + PB_App_StartRequest_size)]; char f22[(7 + PB_Gui_ScreenFrame_size)]; char f24[(7 + PB_Storage_StatRequest_size)]; char f25[(7 + PB_Storage_StatResponse_size)]; char f0[36];};
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -6,18 +6,24 @@
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(PB_Gui_ScreenFrame, PB_Gui_ScreenFrame, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PB_Gui_StartScreenStreamRequest, PB_Gui_StartScreenStreamRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PB_Gui_StopScreenStreamRequest, PB_Gui_StopScreenStreamRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PB_Gui_ScreenStreamFrame, PB_Gui_ScreenStreamFrame, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PB_Gui_SendInputEventRequest, PB_Gui_SendInputEventRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PB_Gui_StartVirtualDisplayRequest, PB_Gui_StartVirtualDisplayRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PB_Gui_StopVirtualDisplayRequest, PB_Gui_StopVirtualDisplayRequest, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -28,18 +28,26 @@ typedef enum _PB_Gui_InputType {
|
||||
} PB_Gui_InputType;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _PB_Gui_ScreenStreamFrame {
|
||||
typedef struct _PB_Gui_ScreenFrame {
|
||||
pb_bytes_array_t *data;
|
||||
} PB_Gui_ScreenStreamFrame;
|
||||
} PB_Gui_ScreenFrame;
|
||||
|
||||
typedef struct _PB_Gui_StartScreenStreamRequest {
|
||||
char dummy_field;
|
||||
} PB_Gui_StartScreenStreamRequest;
|
||||
|
||||
typedef struct _PB_Gui_StartVirtualDisplayRequest {
|
||||
char dummy_field;
|
||||
} PB_Gui_StartVirtualDisplayRequest;
|
||||
|
||||
typedef struct _PB_Gui_StopScreenStreamRequest {
|
||||
char dummy_field;
|
||||
} PB_Gui_StopScreenStreamRequest;
|
||||
|
||||
typedef struct _PB_Gui_StopVirtualDisplayRequest {
|
||||
char dummy_field;
|
||||
} PB_Gui_StopVirtualDisplayRequest;
|
||||
|
||||
typedef struct _PB_Gui_SendInputEventRequest {
|
||||
PB_Gui_InputKey key;
|
||||
PB_Gui_InputType type;
|
||||
@ -61,21 +69,30 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define PB_Gui_ScreenFrame_init_default {NULL}
|
||||
#define PB_Gui_StartScreenStreamRequest_init_default {0}
|
||||
#define PB_Gui_StopScreenStreamRequest_init_default {0}
|
||||
#define PB_Gui_ScreenStreamFrame_init_default {NULL}
|
||||
#define PB_Gui_SendInputEventRequest_init_default {_PB_Gui_InputKey_MIN, _PB_Gui_InputType_MIN}
|
||||
#define PB_Gui_StartVirtualDisplayRequest_init_default {0}
|
||||
#define PB_Gui_StopVirtualDisplayRequest_init_default {0}
|
||||
#define PB_Gui_ScreenFrame_init_zero {NULL}
|
||||
#define PB_Gui_StartScreenStreamRequest_init_zero {0}
|
||||
#define PB_Gui_StopScreenStreamRequest_init_zero {0}
|
||||
#define PB_Gui_ScreenStreamFrame_init_zero {NULL}
|
||||
#define PB_Gui_SendInputEventRequest_init_zero {_PB_Gui_InputKey_MIN, _PB_Gui_InputType_MIN}
|
||||
#define PB_Gui_StartVirtualDisplayRequest_init_zero {0}
|
||||
#define PB_Gui_StopVirtualDisplayRequest_init_zero {0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define PB_Gui_ScreenStreamFrame_data_tag 1
|
||||
#define PB_Gui_ScreenFrame_data_tag 1
|
||||
#define PB_Gui_SendInputEventRequest_key_tag 1
|
||||
#define PB_Gui_SendInputEventRequest_type_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define PB_Gui_ScreenFrame_FIELDLIST(X, a) \
|
||||
X(a, POINTER, SINGULAR, BYTES, data, 1)
|
||||
#define PB_Gui_ScreenFrame_CALLBACK NULL
|
||||
#define PB_Gui_ScreenFrame_DEFAULT NULL
|
||||
|
||||
#define PB_Gui_StartScreenStreamRequest_FIELDLIST(X, a) \
|
||||
|
||||
#define PB_Gui_StartScreenStreamRequest_CALLBACK NULL
|
||||
@ -86,33 +103,44 @@ extern "C" {
|
||||
#define PB_Gui_StopScreenStreamRequest_CALLBACK NULL
|
||||
#define PB_Gui_StopScreenStreamRequest_DEFAULT NULL
|
||||
|
||||
#define PB_Gui_ScreenStreamFrame_FIELDLIST(X, a) \
|
||||
X(a, POINTER, SINGULAR, BYTES, data, 1)
|
||||
#define PB_Gui_ScreenStreamFrame_CALLBACK NULL
|
||||
#define PB_Gui_ScreenStreamFrame_DEFAULT NULL
|
||||
|
||||
#define PB_Gui_SendInputEventRequest_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, key, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, type, 2)
|
||||
#define PB_Gui_SendInputEventRequest_CALLBACK NULL
|
||||
#define PB_Gui_SendInputEventRequest_DEFAULT NULL
|
||||
|
||||
#define PB_Gui_StartVirtualDisplayRequest_FIELDLIST(X, a) \
|
||||
|
||||
#define PB_Gui_StartVirtualDisplayRequest_CALLBACK NULL
|
||||
#define PB_Gui_StartVirtualDisplayRequest_DEFAULT NULL
|
||||
|
||||
#define PB_Gui_StopVirtualDisplayRequest_FIELDLIST(X, a) \
|
||||
|
||||
#define PB_Gui_StopVirtualDisplayRequest_CALLBACK NULL
|
||||
#define PB_Gui_StopVirtualDisplayRequest_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t PB_Gui_ScreenFrame_msg;
|
||||
extern const pb_msgdesc_t PB_Gui_StartScreenStreamRequest_msg;
|
||||
extern const pb_msgdesc_t PB_Gui_StopScreenStreamRequest_msg;
|
||||
extern const pb_msgdesc_t PB_Gui_ScreenStreamFrame_msg;
|
||||
extern const pb_msgdesc_t PB_Gui_SendInputEventRequest_msg;
|
||||
extern const pb_msgdesc_t PB_Gui_StartVirtualDisplayRequest_msg;
|
||||
extern const pb_msgdesc_t PB_Gui_StopVirtualDisplayRequest_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define PB_Gui_ScreenFrame_fields &PB_Gui_ScreenFrame_msg
|
||||
#define PB_Gui_StartScreenStreamRequest_fields &PB_Gui_StartScreenStreamRequest_msg
|
||||
#define PB_Gui_StopScreenStreamRequest_fields &PB_Gui_StopScreenStreamRequest_msg
|
||||
#define PB_Gui_ScreenStreamFrame_fields &PB_Gui_ScreenStreamFrame_msg
|
||||
#define PB_Gui_SendInputEventRequest_fields &PB_Gui_SendInputEventRequest_msg
|
||||
#define PB_Gui_StartVirtualDisplayRequest_fields &PB_Gui_StartVirtualDisplayRequest_msg
|
||||
#define PB_Gui_StopVirtualDisplayRequest_fields &PB_Gui_StopVirtualDisplayRequest_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* PB_Gui_ScreenStreamFrame_size depends on runtime parameters */
|
||||
/* PB_Gui_ScreenFrame_size depends on runtime parameters */
|
||||
#define PB_Gui_SendInputEventRequest_size 4
|
||||
#define PB_Gui_StartScreenStreamRequest_size 0
|
||||
#define PB_Gui_StartVirtualDisplayRequest_size 0
|
||||
#define PB_Gui_StopScreenStreamRequest_size 0
|
||||
#define PB_Gui_StopVirtualDisplayRequest_size 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 0e6d374ab1a12f95a3cd04444376a261e7252db4
|
||||
Subproject commit 6be7def6087c4d277386381ff2792fa622933668
|
||||
@ -1,148 +1,151 @@
|
||||
A00000000305076010 VISA ELO Credit
|
||||
A0000000031010 VISA Debit/Credit (Classic)
|
||||
A000000003101001 VISA Credit
|
||||
A000000003101002 VISA Debit
|
||||
A0000000032010 VISA Electron
|
||||
A0000000032020 VISA
|
||||
A0000000033010 VISA Interlink
|
||||
A0000000034010 VISA Specific
|
||||
A0000000035010 VISA Specific
|
||||
A0000000036010 Domestic Visa Cash
|
||||
A0000000036020 International Visa Cash
|
||||
A0000000038002 VISA Auth EMV-CAP (DPA)
|
||||
A0000000038010 VISA Plus
|
||||
A0000000039010 VISA Loyalty
|
||||
A000000003999910 VISA Proprietary ATM
|
||||
A00000000401 MasterCard PayPass
|
||||
A0000000041010 MasterCard Global
|
||||
A00000000410101213 MasterCard Credit
|
||||
A00000000410101215 MasterCard Credit
|
||||
A0000000042010 MasterCard Specific
|
||||
A0000000043010 MasterCard Specific
|
||||
A0000000043060 Maestro (Debit)
|
||||
A000000004306001 Maestro (Debit)
|
||||
A0000000044010 MasterCard Specific
|
||||
A0000000045010 MasterCard Specific
|
||||
A0000000046000 Cirrus
|
||||
A0000000048002 SecureCode EMV-CAP
|
||||
A0000000049999 MasterCard PayPass
|
||||
A0000000050001 Maestro UK
|
||||
A0000000050002 Solo
|
||||
A00000002401 Self Service
|
||||
A000000025 American Express
|
||||
A0000000250000 American Express
|
||||
A00000002501 American Express
|
||||
A000000025010402 American Express
|
||||
A000000025010701 ExpressPay
|
||||
A000000025010801 American Express
|
||||
A0000000291010 Link / American Express
|
||||
A0000000421010 Cartes Bancaire EMV Card
|
||||
A0000000426010 Apple Pay
|
||||
A00000006510 JCB
|
||||
A0000000651010 JCB J Smart Credit
|
||||
A00000006900 Moneo
|
||||
A000000077010000021000000000003B Visa AEPN
|
||||
A000000098 Debit Card
|
||||
A0000000980848 Debit Card
|
||||
A0000001211010 Dankort VISA GEM Vision
|
||||
A0000001410001 PagoBANCOMAT
|
||||
A0000001523010 Discover, Pulse D Pas
|
||||
A0000001524010 Discover
|
||||
A0000001544442 Banricompras Debito
|
||||
A000000172950001 BAROC Taiwan
|
||||
A0000002281010 SPAN (M/Chip)
|
||||
A0000002282010 SPAN (VIS)
|
||||
A0000002771010 INTERAC
|
||||
A00000031510100528 Currence PuC
|
||||
A0000003156020 Chipknip
|
||||
A0000003591010028001 Girocard EAPS
|
||||
A0000003710001 InterSwitch Verve Card
|
||||
A0000004540010 Etranzact Genesis Card
|
||||
A0000004540011 Etranzact Genesis Card 2
|
||||
A0000004766C GOOGLE_PAYMENT
|
||||
A0000005241010 RuPay
|
||||
A0000006723010 TROY chip credit card
|
||||
A0000006723020 TROY chip debit card
|
||||
A0000007705850 XTRAPOWER
|
||||
B012345678 Maestro TEST
|
||||
D27600002545500100 Girocard
|
||||
D5780000021010 Bankaxept
|
||||
F0000000030001 BRADESCO
|
||||
A000000003000000 (VISA) Card Manager
|
||||
A000000003534441 Schlumberger SD
|
||||
A0000000035350 Security Domain
|
||||
A000000003535041 Security Domain
|
||||
A0000000040000 MasterCard Card Manager
|
||||
A000000018434D Gemplus card manager
|
||||
A000000018434D00 Gemplus Security Domain
|
||||
A0000000960200 Proton WISD
|
||||
A0000001510000 Global Platform SD
|
||||
A00000015153504341534400 CASD_AID
|
||||
A000000476A010 GSD_MANAGER_AID
|
||||
A000000476A110 GSD_MANAGER_AID
|
||||
315041592E5359532E4444463031 Visa PSE
|
||||
325041592E5359532E4444463031 Visa PPSE
|
||||
A0000000042203 MasterCard Specific
|
||||
A0000000045555 APDULogger
|
||||
A0000000090001FF44FF1289 Orange
|
||||
A0000000101030 Maestro-CH
|
||||
A00000001800 Gemplus
|
||||
A0000000181001 gemplus util packages
|
||||
A000000025010104 American Express
|
||||
A00000002949034010100001 HSBC
|
||||
A00000002949282010100000 Barclay
|
||||
A00000005945430100 Girocard Electronic Cash
|
||||
A0000000980840 Visa Common Debit
|
||||
A0000001570010 AMEX
|
||||
A0000001570020 MasterCard
|
||||
A0000001570021 Maestro
|
||||
A0000001570022 Maestro
|
||||
A0000001570023 CASH
|
||||
A0000001570030 VISA
|
||||
A0000001570031 VISA
|
||||
A0000001570040 JCB
|
||||
A0000001570050 Postcard
|
||||
A0000001570051 Postcard
|
||||
A0000001570100 MCard
|
||||
A0000001570104 MyOne
|
||||
A000000157010C WIRCard
|
||||
A000000157010D Power Card
|
||||
A0000001574443 DINERS CLUB
|
||||
A0000001574444 Supercard Plus
|
||||
A00000022820101010 SPAN
|
||||
A000000308000010000100 ID-ONE PIV BIO
|
||||
A0000003241010 Discover Zip
|
||||
A000000333010101 UnionPay Debit
|
||||
A000000333010102 UnionPay Credit
|
||||
A000000333010103 UnionPay Quasi Credit
|
||||
A000000333010106 UnionPay Electronic Cash
|
||||
A000000333010108 U.S. UnionPay Common Debit
|
||||
A000000337102000 Classic
|
||||
A000000337101001 Prepaye Online
|
||||
A000000337102001 Prepaye Possibile Offiline
|
||||
A000000337601001 Porte Monnaie Electronique
|
||||
A0000006581010 MIR Credit
|
||||
A0000006581011 MIR Credit
|
||||
A0000006582010 MIR Debit
|
||||
D040000001000002 Paylife Quick IEP
|
||||
D040000002000002 RFU
|
||||
D040000003000002 POS
|
||||
D040000004000002 ATM
|
||||
D04000000B000002 Retail
|
||||
D04000000C000002 Bank_Data
|
||||
D04000000D000002 Shopping
|
||||
D040000013000001 DF_UNI_Kepler1
|
||||
D040000013000001 DF_Schüler1
|
||||
D040000013000002 DF_UNI_Kepler2
|
||||
D040000013000002 DF_Schüler2
|
||||
D040000014000001 DF_Mensa
|
||||
D040000015000001 DF_UNI_Ausweis
|
||||
D040000015000001 DF_Ausweis
|
||||
D0400000190001 EMV ATM Maestro
|
||||
D0400000190002 EMV POS Maestro
|
||||
D0400000190003 EMV ATM MasterCard
|
||||
D0400000190004 EMV POS MasterCard
|
||||
D276000025 Girocard
|
||||
D27600002547410100 Girocard ATM
|
||||
D7560000010101 Reka Card
|
||||
D7560000300101 M Budget
|
||||
Filetype: Flipper EMV resources
|
||||
Version: 1
|
||||
# EMV Application ID code: Application ID name
|
||||
A00000000305076010: VISA ELO Credit
|
||||
A0000000031010: VISA Debit/Credit (Classic)
|
||||
A000000003101001: VISA Credit
|
||||
A000000003101002: VISA Debit
|
||||
A0000000032010: VISA Electron
|
||||
A0000000032020: VISA
|
||||
A0000000033010: VISA Interlink
|
||||
A0000000034010: VISA Specific
|
||||
A0000000035010: VISA Specific
|
||||
A0000000036010: Domestic Visa Cash
|
||||
A0000000036020: International Visa Cash
|
||||
A0000000038002: VISA Auth EMV-CAP (DPA)
|
||||
A0000000038010: VISA Plus
|
||||
A0000000039010: VISA Loyalty
|
||||
A000000003999910: VISA Proprietary ATM
|
||||
A00000000401: MasterCard PayPass
|
||||
A0000000041010: MasterCard Global
|
||||
A00000000410101213: MasterCard Credit
|
||||
A00000000410101215: MasterCard Credit
|
||||
A0000000042010: MasterCard Specific
|
||||
A0000000043010: MasterCard Specific
|
||||
A0000000043060: Maestro (Debit)
|
||||
A000000004306001: Maestro (Debit)
|
||||
A0000000044010: MasterCard Specific
|
||||
A0000000045010: MasterCard Specific
|
||||
A0000000046000: Cirrus
|
||||
A0000000048002: SecureCode EMV-CAP
|
||||
A0000000049999: MasterCard PayPass
|
||||
A0000000050001: Maestro UK
|
||||
A0000000050002: Solo
|
||||
A00000002401: Self Service
|
||||
A000000025: American Express
|
||||
A0000000250000: American Express
|
||||
A00000002501: American Express
|
||||
A000000025010402: American Express
|
||||
A000000025010701: ExpressPay
|
||||
A000000025010801: American Express
|
||||
A0000000291010: Link / American Express
|
||||
A0000000421010: Cartes Bancaire EMV Card
|
||||
A0000000426010: Apple Pay
|
||||
A00000006510: JCB
|
||||
A0000000651010: JCB J Smart Credit
|
||||
A00000006900: Moneo
|
||||
A000000077010000021000000000003B: Visa AEPN
|
||||
A000000098: Debit Card
|
||||
A0000000980848: Debit Card
|
||||
A0000001211010: Dankort VISA GEM Vision
|
||||
A0000001410001: PagoBANCOMAT
|
||||
A0000001523010: Discover, Pulse D Pas
|
||||
A0000001524010: Discover
|
||||
A0000001544442: Banricompras Debito
|
||||
A000000172950001: BAROC Taiwan
|
||||
A0000002281010: SPAN (M/Chip)
|
||||
A0000002282010: SPAN (VIS)
|
||||
A0000002771010: INTERAC
|
||||
A00000031510100528: Currence PuC
|
||||
A0000003156020: Chipknip
|
||||
A0000003591010028001: Girocard EAPS
|
||||
A0000003710001: InterSwitch Verve Card
|
||||
A0000004540010: Etranzact Genesis Card
|
||||
A0000004540011: Etranzact Genesis Card 2
|
||||
A0000004766C: GOOGLE_PAYMENT
|
||||
A0000005241010: RuPay
|
||||
A0000006723010: TROY chip credit card
|
||||
A0000006723020: TROY chip debit card
|
||||
A0000007705850: XTRAPOWER
|
||||
B012345678: Maestro TEST
|
||||
D27600002545500100: Girocard
|
||||
D5780000021010: Bankaxept
|
||||
F0000000030001: BRADESCO
|
||||
A000000003000000: (VISA) Card Manager
|
||||
A000000003534441: Schlumberger SD
|
||||
A0000000035350: Security Domain
|
||||
A000000003535041: Security Domain
|
||||
A0000000040000: MasterCard Card Manager
|
||||
A000000018434D: Gemplus card manager
|
||||
A000000018434D00: Gemplus Security Domain
|
||||
A0000000960200: Proton WISD
|
||||
A0000001510000: Global Platform SD
|
||||
A00000015153504341534400: CASD_AID
|
||||
A000000476A010: GSD_MANAGER_AID
|
||||
A000000476A110: GSD_MANAGER_AID
|
||||
315041592E5359532E4444463031: Visa PSE
|
||||
325041592E5359532E4444463031: Visa PPSE
|
||||
A0000000042203: MasterCard Specific
|
||||
A0000000045555: APDULogger
|
||||
A0000000090001FF44FF1289: Orange
|
||||
A0000000101030: Maestro-CH
|
||||
A00000001800: Gemplus
|
||||
A0000000181001: gemplus util packages
|
||||
A000000025010104: American Express
|
||||
A00000002949034010100001: HSBC
|
||||
A00000002949282010100000: Barclay
|
||||
A00000005945430100: Girocard Electronic Cash
|
||||
A0000000980840: Visa Common Debit
|
||||
A0000001570010: AMEX
|
||||
A0000001570020: MasterCard
|
||||
A0000001570021: Maestro
|
||||
A0000001570022: Maestro
|
||||
A0000001570023: CASH
|
||||
A0000001570030: VISA
|
||||
A0000001570031: VISA
|
||||
A0000001570040: JCB
|
||||
A0000001570050: Postcard
|
||||
A0000001570051: Postcard
|
||||
A0000001570100: MCard
|
||||
A0000001570104: MyOne
|
||||
A000000157010C: WIRCard
|
||||
A000000157010D: Power Card
|
||||
A0000001574443: DINERS CLUB
|
||||
A0000001574444: Supercard Plus
|
||||
A00000022820101010: SPAN
|
||||
A000000308000010000100: ID-ONE PIV BIO
|
||||
A0000003241010: Discover Zip
|
||||
A000000333010101: UnionPay Debit
|
||||
A000000333010102: UnionPay Credit
|
||||
A000000333010103: UnionPay Quasi Credit
|
||||
A000000333010106: UnionPay Electronic Cash
|
||||
A000000333010108: U.S. UnionPay Common Debit
|
||||
A000000337102000: Classic
|
||||
A000000337101001: Prepaye Online
|
||||
A000000337102001: Prepaye Possibile Offiline
|
||||
A000000337601001: Porte Monnaie Electronique
|
||||
A0000006581010: MIR Credit
|
||||
A0000006581011: MIR Credit
|
||||
A0000006582010: MIR Debit
|
||||
D040000001000002: Paylife Quick IEP
|
||||
D040000002000002: RFU
|
||||
D040000003000002: POS
|
||||
D040000004000002: ATM
|
||||
D04000000B000002: Retail
|
||||
D04000000C000002: Bank_Data
|
||||
D04000000D000002: Shopping
|
||||
D040000013000001: DF_UNI_Kepler1
|
||||
D040000013000001: DF_Schüler1
|
||||
D040000013000002: DF_UNI_Kepler2
|
||||
D040000013000002: DF_Schüler2
|
||||
D040000014000001: DF_Mensa
|
||||
D040000015000001: DF_UNI_Ausweis
|
||||
D040000015000001: DF_Ausweis
|
||||
D0400000190001: EMV ATM Maestro
|
||||
D0400000190002: EMV POS Maestro
|
||||
D0400000190003: EMV ATM MasterCard
|
||||
D0400000190004: EMV POS MasterCard
|
||||
D276000025: Girocard
|
||||
D27600002547410100: Girocard ATM
|
||||
D7560000010101: Reka Card
|
||||
D7560000300101: M Budget
|
||||
@ -1,249 +1,252 @@
|
||||
0004 AFG
|
||||
0008 ALB
|
||||
0010 ATA
|
||||
0012 DZA
|
||||
0016 ASM
|
||||
0020 AND
|
||||
0024 AGO
|
||||
0028 ATG
|
||||
0031 AZE
|
||||
0032 ARG
|
||||
0036 AUS
|
||||
0040 AUT
|
||||
0044 BHS
|
||||
0048 BHR
|
||||
0050 BGD
|
||||
0051 ARM
|
||||
0052 BRB
|
||||
0056 BEL
|
||||
0060 BMU
|
||||
0064 BTN
|
||||
0068 BOL
|
||||
0070 BIH
|
||||
0072 BWA
|
||||
0074 BVT
|
||||
0076 BRA
|
||||
0084 BLZ
|
||||
0086 IOT
|
||||
0090 SLB
|
||||
0092 VGB
|
||||
0096 BRN
|
||||
0100 BGR
|
||||
0104 MMR
|
||||
0108 BDI
|
||||
0112 BLR
|
||||
0116 KHM
|
||||
0120 CMR
|
||||
0124 CAN
|
||||
0132 CPV
|
||||
0136 CYM
|
||||
0140 CAF
|
||||
0144 LKA
|
||||
0148 TCD
|
||||
0152 CHL
|
||||
0156 CHN
|
||||
0158 TWN
|
||||
0162 CXR
|
||||
0166 CCK
|
||||
0170 COL
|
||||
0174 COM
|
||||
0175 MYT
|
||||
0178 COG
|
||||
0180 COD
|
||||
0184 COK
|
||||
0188 CRI
|
||||
0191 HRV
|
||||
0192 CUB
|
||||
0196 CYP
|
||||
0203 CZE
|
||||
0204 BEN
|
||||
0208 DNK
|
||||
0212 DMA
|
||||
0214 DOM
|
||||
0218 ECU
|
||||
0222 SLV
|
||||
0226 GNQ
|
||||
0231 ETH
|
||||
0232 ERI
|
||||
0233 EST
|
||||
0234 FRO
|
||||
0238 FLK
|
||||
0239 SGS
|
||||
0242 FJI
|
||||
0246 FIN
|
||||
0248 ALA
|
||||
0250 FRA
|
||||
0254 GUF
|
||||
0258 PYF
|
||||
0260 ATF
|
||||
0262 DJI
|
||||
0266 GAB
|
||||
0268 GEO
|
||||
0270 GMB
|
||||
0275 PSE
|
||||
0276 DEU
|
||||
0288 GHA
|
||||
0292 GIB
|
||||
0296 KIR
|
||||
0300 GRC
|
||||
0304 GRL
|
||||
0308 GRD
|
||||
0312 GLP
|
||||
0316 GUM
|
||||
0320 GTM
|
||||
0324 GIN
|
||||
0328 GUY
|
||||
0332 HTI
|
||||
0334 HMD
|
||||
0336 VAT
|
||||
0340 HND
|
||||
0344 HKG
|
||||
0348 HUN
|
||||
0352 ISL
|
||||
0356 IND
|
||||
0360 IDN
|
||||
0364 IRN
|
||||
0368 IRQ
|
||||
0372 IRL
|
||||
0376 ISR
|
||||
0380 ITA
|
||||
0384 CIV
|
||||
0388 JAM
|
||||
0392 JPN
|
||||
0398 KAZ
|
||||
0400 JOR
|
||||
0404 KEN
|
||||
0408 PRK
|
||||
0410 KOR
|
||||
0414 KWT
|
||||
0417 KGZ
|
||||
0418 LAO
|
||||
0422 LBN
|
||||
0426 LSO
|
||||
0428 LVA
|
||||
0430 LBR
|
||||
0434 LBY
|
||||
0438 LIE
|
||||
0440 LTU
|
||||
0442 LUX
|
||||
0446 MAC
|
||||
0450 MDG
|
||||
0454 MWI
|
||||
0458 MYS
|
||||
0462 MDV
|
||||
0466 MLI
|
||||
0470 MLT
|
||||
0474 MTQ
|
||||
0478 MRT
|
||||
0480 MUS
|
||||
0484 MEX
|
||||
0492 MCO
|
||||
0496 MNG
|
||||
0498 MDA
|
||||
0499 MNE
|
||||
0500 MSR
|
||||
0504 MAR
|
||||
0508 MOZ
|
||||
0512 OMN
|
||||
0516 NAM
|
||||
0520 NRU
|
||||
0524 NPL
|
||||
0528 NLD
|
||||
0531 CUW
|
||||
0533 ABW
|
||||
0534 SXM
|
||||
0535 BES
|
||||
0540 NCL
|
||||
0548 VUT
|
||||
0554 NZL
|
||||
0558 NIC
|
||||
0562 NER
|
||||
0566 NGA
|
||||
0570 NIU
|
||||
0574 NFK
|
||||
0578 NOR
|
||||
0580 MNP
|
||||
0581 UMI
|
||||
0583 FSM
|
||||
0584 MHL
|
||||
0585 PLW
|
||||
0586 PAK
|
||||
0591 PAN
|
||||
0598 PNG
|
||||
0600 PRY
|
||||
0604 PER
|
||||
0608 PHL
|
||||
0612 PCN
|
||||
0616 POL
|
||||
0620 PRT
|
||||
0624 GNB
|
||||
0626 TLS
|
||||
0630 PRI
|
||||
0634 QAT
|
||||
0638 REU
|
||||
0642 ROU
|
||||
0643 RUS
|
||||
0646 RWA
|
||||
0652 BLM
|
||||
0654 SHN
|
||||
0659 KNA
|
||||
0660 AIA
|
||||
0662 LCA
|
||||
0663 MAF
|
||||
0666 SPM
|
||||
0670 VCT
|
||||
0674 SMR
|
||||
0678 STP
|
||||
0682 SAU
|
||||
0686 SEN
|
||||
0688 SRB
|
||||
0690 SYC
|
||||
0694 SLE
|
||||
0702 SGP
|
||||
0703 SVK
|
||||
0704 VNM
|
||||
0705 SVN
|
||||
0706 SOM
|
||||
0710 ZAF
|
||||
0716 ZWE
|
||||
0724 ESP
|
||||
0728 SSD
|
||||
0729 SDN
|
||||
0732 ESH
|
||||
0740 SUR
|
||||
0744 SJM
|
||||
0748 SWZ
|
||||
0752 SWE
|
||||
0756 CHE
|
||||
0760 SYR
|
||||
0762 TJK
|
||||
0764 THA
|
||||
0768 TGO
|
||||
0772 TKL
|
||||
0776 TON
|
||||
0780 TTO
|
||||
0784 ARE
|
||||
0788 TUN
|
||||
0792 TUR
|
||||
0795 TKM
|
||||
0796 TCA
|
||||
0798 TUV
|
||||
0800 UGA
|
||||
0804 UKR
|
||||
0807 MKD
|
||||
0818 EGY
|
||||
0826 GBR
|
||||
0831 GGY
|
||||
0832 JEY
|
||||
0833 IMN
|
||||
0834 TZA
|
||||
0840 USA
|
||||
0850 VIR
|
||||
0854 BFA
|
||||
0858 URY
|
||||
0860 UZB
|
||||
0862 VEN
|
||||
0876 WLF
|
||||
0882 WSM
|
||||
0887 YEM
|
||||
0894 ZMB
|
||||
Filetype: Flipper EMV resources
|
||||
Version: 1
|
||||
# EMV country code: country name
|
||||
0004: AFG
|
||||
0008: ALB
|
||||
0010: ATA
|
||||
0012: DZA
|
||||
0016: ASM
|
||||
0020: AND
|
||||
0024: AGO
|
||||
0028: ATG
|
||||
0031: AZE
|
||||
0032: ARG
|
||||
0036: AUS
|
||||
0040: AUT
|
||||
0044: BHS
|
||||
0048: BHR
|
||||
0050: BGD
|
||||
0051: ARM
|
||||
0052: BRB
|
||||
0056: BEL
|
||||
0060: BMU
|
||||
0064: BTN
|
||||
0068: BOL
|
||||
0070: BIH
|
||||
0072: BWA
|
||||
0074: BVT
|
||||
0076: BRA
|
||||
0084: BLZ
|
||||
0086: IOT
|
||||
0090: SLB
|
||||
0092: VGB
|
||||
0096: BRN
|
||||
0100: BGR
|
||||
0104: MMR
|
||||
0108: BDI
|
||||
0112: BLR
|
||||
0116: KHM
|
||||
0120: CMR
|
||||
0124: CAN
|
||||
0132: CPV
|
||||
0136: CYM
|
||||
0140: CAF
|
||||
0144: LKA
|
||||
0148: TCD
|
||||
0152: CHL
|
||||
0156: CHN
|
||||
0158: TWN
|
||||
0162: CXR
|
||||
0166: CCK
|
||||
0170: COL
|
||||
0174: COM
|
||||
0175: MYT
|
||||
0178: COG
|
||||
0180: COD
|
||||
0184: COK
|
||||
0188: CRI
|
||||
0191: HRV
|
||||
0192: CUB
|
||||
0196: CYP
|
||||
0203: CZE
|
||||
0204: BEN
|
||||
0208: DNK
|
||||
0212: DMA
|
||||
0214: DOM
|
||||
0218: ECU
|
||||
0222: SLV
|
||||
0226: GNQ
|
||||
0231: ETH
|
||||
0232: ERI
|
||||
0233: EST
|
||||
0234: FRO
|
||||
0238: FLK
|
||||
0239: SGS
|
||||
0242: FJI
|
||||
0246: FIN
|
||||
0248: ALA
|
||||
0250: FRA
|
||||
0254: GUF
|
||||
0258: PYF
|
||||
0260: ATF
|
||||
0262: DJI
|
||||
0266: GAB
|
||||
0268: GEO
|
||||
0270: GMB
|
||||
0275: PSE
|
||||
0276: DEU
|
||||
0288: GHA
|
||||
0292: GIB
|
||||
0296: KIR
|
||||
0300: GRC
|
||||
0304: GRL
|
||||
0308: GRD
|
||||
0312: GLP
|
||||
0316: GUM
|
||||
0320: GTM
|
||||
0324: GIN
|
||||
0328: GUY
|
||||
0332: HTI
|
||||
0334: HMD
|
||||
0336: VAT
|
||||
0340: HND
|
||||
0344: HKG
|
||||
0348: HUN
|
||||
0352: ISL
|
||||
0356: IND
|
||||
0360: IDN
|
||||
0364: IRN
|
||||
0368: IRQ
|
||||
0372: IRL
|
||||
0376: ISR
|
||||
0380: ITA
|
||||
0384: CIV
|
||||
0388: JAM
|
||||
0392: JPN
|
||||
0398: KAZ
|
||||
0400: JOR
|
||||
0404: KEN
|
||||
0408: PRK
|
||||
0410: KOR
|
||||
0414: KWT
|
||||
0417: KGZ
|
||||
0418: LAO
|
||||
0422: LBN
|
||||
0426: LSO
|
||||
0428: LVA
|
||||
0430: LBR
|
||||
0434: LBY
|
||||
0438: LIE
|
||||
0440: LTU
|
||||
0442: LUX
|
||||
0446: MAC
|
||||
0450: MDG
|
||||
0454: MWI
|
||||
0458: MYS
|
||||
0462: MDV
|
||||
0466: MLI
|
||||
0470: MLT
|
||||
0474: MTQ
|
||||
0478: MRT
|
||||
0480: MUS
|
||||
0484: MEX
|
||||
0492: MCO
|
||||
0496: MNG
|
||||
0498: MDA
|
||||
0499: MNE
|
||||
0500: MSR
|
||||
0504: MAR
|
||||
0508: MOZ
|
||||
0512: OMN
|
||||
0516: NAM
|
||||
0520: NRU
|
||||
0524: NPL
|
||||
0528: NLD
|
||||
0531: CUW
|
||||
0533: ABW
|
||||
0534: SXM
|
||||
0535: BES
|
||||
0540: NCL
|
||||
0548: VUT
|
||||
0554: NZL
|
||||
0558: NIC
|
||||
0562: NER
|
||||
0566: NGA
|
||||
0570: NIU
|
||||
0574: NFK
|
||||
0578: NOR
|
||||
0580: MNP
|
||||
0581: UMI
|
||||
0583: FSM
|
||||
0584: MHL
|
||||
0585: PLW
|
||||
0586: PAK
|
||||
0591: PAN
|
||||
0598: PNG
|
||||
0600: PRY
|
||||
0604: PER
|
||||
0608: PHL
|
||||
0612: PCN
|
||||
0616: POL
|
||||
0620: PRT
|
||||
0624: GNB
|
||||
0626: TLS
|
||||
0630: PRI
|
||||
0634: QAT
|
||||
0638: REU
|
||||
0642: ROU
|
||||
0643: RUS
|
||||
0646: RWA
|
||||
0652: BLM
|
||||
0654: SHN
|
||||
0659: KNA
|
||||
0660: AIA
|
||||
0662: LCA
|
||||
0663: MAF
|
||||
0666: SPM
|
||||
0670: VCT
|
||||
0674: SMR
|
||||
0678: STP
|
||||
0682: SAU
|
||||
0686: SEN
|
||||
0688: SRB
|
||||
0690: SYC
|
||||
0694: SLE
|
||||
0702: SGP
|
||||
0703: SVK
|
||||
0704: VNM
|
||||
0705: SVN
|
||||
0706: SOM
|
||||
0710: ZAF
|
||||
0716: ZWE
|
||||
0724: ESP
|
||||
0728: SSD
|
||||
0729: SDN
|
||||
0732: ESH
|
||||
0740: SUR
|
||||
0744: SJM
|
||||
0748: SWZ
|
||||
0752: SWE
|
||||
0756: CHE
|
||||
0760: SYR
|
||||
0762: TJK
|
||||
0764: THA
|
||||
0768: TGO
|
||||
0772: TKL
|
||||
0776: TON
|
||||
0780: TTO
|
||||
0784: ARE
|
||||
0788: TUN
|
||||
0792: TUR
|
||||
0795: TKM
|
||||
0796: TCA
|
||||
0798: TUV
|
||||
0800: UGA
|
||||
0804: UKR
|
||||
0807: MKD
|
||||
0818: EGY
|
||||
0826: GBR
|
||||
0831: GGY
|
||||
0832: JEY
|
||||
0833: IMN
|
||||
0834: TZA
|
||||
0840: USA
|
||||
0850: VIR
|
||||
0854: BFA
|
||||
0858: URY
|
||||
0860: UZB
|
||||
0862: VEN
|
||||
0876: WLF
|
||||
0882: WSM
|
||||
0887: YEM
|
||||
0894: ZMB
|
||||
@ -1,168 +1,171 @@
|
||||
0997 USN
|
||||
0994 XSU
|
||||
0990 CLF
|
||||
0986 BRL
|
||||
0985 PLN
|
||||
0984 BOV
|
||||
0981 GEL
|
||||
0980 UAH
|
||||
0979 MXV
|
||||
0978 EUR
|
||||
0977 BAM
|
||||
0976 CDF
|
||||
0975 BGN
|
||||
0973 AOA
|
||||
0972 TJS
|
||||
0971 AFN
|
||||
0970 COU
|
||||
0969 MGA
|
||||
0968 SRD
|
||||
0967 ZMW
|
||||
0965 XUA
|
||||
0960 XDR
|
||||
0953 XPF
|
||||
0952 XOF
|
||||
0951 XCD
|
||||
0950 XAF
|
||||
0949 TRY
|
||||
0948 CHW
|
||||
0947 CHE
|
||||
0946 RON
|
||||
0944 AZN
|
||||
0943 MZN
|
||||
0941 RSD
|
||||
0940 UYI
|
||||
0938 SDG
|
||||
0937 VEF
|
||||
0936 GHS
|
||||
0934 TMT
|
||||
0933 BYN
|
||||
0932 ZWL
|
||||
0931 CUC
|
||||
0930 STN
|
||||
0929 MRU
|
||||
0901 TWD
|
||||
0886 YER
|
||||
0882 WST
|
||||
0860 UZS
|
||||
0858 UYU
|
||||
0840 USD
|
||||
0834 TZS
|
||||
0826 GBP
|
||||
0818 EGP
|
||||
0807 MKD
|
||||
0800 UGX
|
||||
0788 TND
|
||||
0784 AED
|
||||
0780 TTD
|
||||
0776 TOP
|
||||
0764 THB
|
||||
0760 SYP
|
||||
0756 CHF
|
||||
0752 SEK
|
||||
0748 SZL
|
||||
0728 SSP
|
||||
0710 ZAR
|
||||
0706 SOS
|
||||
0704 VND
|
||||
0702 SGD
|
||||
0694 SLL
|
||||
0690 SCR
|
||||
0682 SAR
|
||||
0654 SHP
|
||||
0646 RWF
|
||||
0643 RUB
|
||||
0634 QAR
|
||||
0608 PHP
|
||||
0604 PEN
|
||||
0600 PYG
|
||||
0598 PGK
|
||||
0590 PAB
|
||||
0586 PKR
|
||||
0578 NOK
|
||||
0566 NGN
|
||||
0558 NIO
|
||||
0554 NZD
|
||||
0548 VUV
|
||||
0533 AWG
|
||||
0532 ANG
|
||||
0524 NPR
|
||||
0516 NAD
|
||||
0512 OMR
|
||||
0504 MAD
|
||||
0498 MDL
|
||||
0496 MNT
|
||||
0484 MXN
|
||||
0480 MUR
|
||||
0462 MVR
|
||||
0458 MYR
|
||||
0454 MWK
|
||||
0446 MOP
|
||||
0434 LYD
|
||||
0430 LRD
|
||||
0426 LSL
|
||||
0422 LBP
|
||||
0418 LAK
|
||||
0417 KGS
|
||||
0414 KWD
|
||||
0410 KRW
|
||||
0408 KPW
|
||||
0404 KES
|
||||
0400 JOD
|
||||
0398 KZT
|
||||
0392 JPY
|
||||
0388 JMD
|
||||
0376 ILS
|
||||
0368 IQD
|
||||
0364 IRR
|
||||
0360 IDR
|
||||
0356 INR
|
||||
0352 ISK
|
||||
0348 HUF
|
||||
0344 HKD
|
||||
0340 HNL
|
||||
0332 HTG
|
||||
0328 GYD
|
||||
0324 GNF
|
||||
0320 GTQ
|
||||
0292 GIP
|
||||
0270 GMD
|
||||
0262 DJF
|
||||
0242 FJD
|
||||
0238 FKP
|
||||
0232 ERN
|
||||
0230 ETB
|
||||
0222 SVC
|
||||
0214 DOP
|
||||
0208 DKK
|
||||
0203 CZK
|
||||
0192 CUP
|
||||
0191 HRK
|
||||
0188 CRC
|
||||
0174 KMF
|
||||
0170 COP
|
||||
0156 CNY
|
||||
0152 CLP
|
||||
0144 LKR
|
||||
0136 KYD
|
||||
0132 CVE
|
||||
0124 CAD
|
||||
0116 KHR
|
||||
0108 BIF
|
||||
0104 MMK
|
||||
0096 BND
|
||||
0090 SBD
|
||||
0084 BZD
|
||||
0072 BWP
|
||||
0068 BOB
|
||||
0064 BTN
|
||||
0060 BMD
|
||||
0052 BBD
|
||||
0051 AMD
|
||||
0050 BDT
|
||||
0048 BHD
|
||||
0044 BSD
|
||||
0036 AUD
|
||||
0032 ARS
|
||||
0012 DZD
|
||||
0008 ALL
|
||||
Filetype: Flipper EMV resources
|
||||
Version: 1
|
||||
# EMV currency code: currency name
|
||||
0997: USN
|
||||
0994: XSU
|
||||
0990: CLF
|
||||
0986: BRL
|
||||
0985: PLN
|
||||
0984: BOV
|
||||
0981: GEL
|
||||
0980: UAH
|
||||
0979: MXV
|
||||
0978: EUR
|
||||
0977: BAM
|
||||
0976: CDF
|
||||
0975: BGN
|
||||
0973: AOA
|
||||
0972: TJS
|
||||
0971: AFN
|
||||
0970: COU
|
||||
0969: MGA
|
||||
0968: SRD
|
||||
0967: ZMW
|
||||
0965: XUA
|
||||
0960: XDR
|
||||
0953: XPF
|
||||
0952: XOF
|
||||
0951: XCD
|
||||
0950: XAF
|
||||
0949: TRY
|
||||
0948: CHW
|
||||
0947: CHE
|
||||
0946: RON
|
||||
0944: AZN
|
||||
0943: MZN
|
||||
0941: RSD
|
||||
0940: UYI
|
||||
0938: SDG
|
||||
0937: VEF
|
||||
0936: GHS
|
||||
0934: TMT
|
||||
0933: BYN
|
||||
0932: ZWL
|
||||
0931: CUC
|
||||
0930: STN
|
||||
0929: MRU
|
||||
0901: TWD
|
||||
0886: YER
|
||||
0882: WST
|
||||
0860: UZS
|
||||
0858: UYU
|
||||
0840: USD
|
||||
0834: TZS
|
||||
0826: GBP
|
||||
0818: EGP
|
||||
0807: MKD
|
||||
0800: UGX
|
||||
0788: TND
|
||||
0784: AED
|
||||
0780: TTD
|
||||
0776: TOP
|
||||
0764: THB
|
||||
0760: SYP
|
||||
0756: CHF
|
||||
0752: SEK
|
||||
0748: SZL
|
||||
0728: SSP
|
||||
0710: ZAR
|
||||
0706: SOS
|
||||
0704: VND
|
||||
0702: SGD
|
||||
0694: SLL
|
||||
0690: SCR
|
||||
0682: SAR
|
||||
0654: SHP
|
||||
0646: RWF
|
||||
0643: RUB
|
||||
0634: QAR
|
||||
0608: PHP
|
||||
0604: PEN
|
||||
0600: PYG
|
||||
0598: PGK
|
||||
0590: PAB
|
||||
0586: PKR
|
||||
0578: NOK
|
||||
0566: NGN
|
||||
0558: NIO
|
||||
0554: NZD
|
||||
0548: VUV
|
||||
0533: AWG
|
||||
0532: ANG
|
||||
0524: NPR
|
||||
0516: NAD
|
||||
0512: OMR
|
||||
0504: MAD
|
||||
0498: MDL
|
||||
0496: MNT
|
||||
0484: MXN
|
||||
0480: MUR
|
||||
0462: MVR
|
||||
0458: MYR
|
||||
0454: MWK
|
||||
0446: MOP
|
||||
0434: LYD
|
||||
0430: LRD
|
||||
0426: LSL
|
||||
0422: LBP
|
||||
0418: LAK
|
||||
0417: KGS
|
||||
0414: KWD
|
||||
0410: KRW
|
||||
0408: KPW
|
||||
0404: KES
|
||||
0400: JOD
|
||||
0398: KZT
|
||||
0392: JPY
|
||||
0388: JMD
|
||||
0376: ILS
|
||||
0368: IQD
|
||||
0364: IRR
|
||||
0360: IDR
|
||||
0356: INR
|
||||
0352: ISK
|
||||
0348: HUF
|
||||
0344: HKD
|
||||
0340: HNL
|
||||
0332: HTG
|
||||
0328: GYD
|
||||
0324: GNF
|
||||
0320: GTQ
|
||||
0292: GIP
|
||||
0270: GMD
|
||||
0262: DJF
|
||||
0242: FJD
|
||||
0238: FKP
|
||||
0232: ERN
|
||||
0230: ETB
|
||||
0222: SVC
|
||||
0214: DOP
|
||||
0208: DKK
|
||||
0203: CZK
|
||||
0192: CUP
|
||||
0191: HRK
|
||||
0188: CRC
|
||||
0174: KMF
|
||||
0170: COP
|
||||
0156: CNY
|
||||
0152: CLP
|
||||
0144: LKR
|
||||
0136: KYD
|
||||
0132: CVE
|
||||
0124: CAD
|
||||
0116: KHR
|
||||
0108: BIF
|
||||
0104: MMK
|
||||
0096: BND
|
||||
0090: SBD
|
||||
0084: BZD
|
||||
0072: BWP
|
||||
0068: BOB
|
||||
0064: BTN
|
||||
0060: BMD
|
||||
0052: BBD
|
||||
0051: AMD
|
||||
0050: BDT
|
||||
0048: BHD
|
||||
0044: BSD
|
||||
0036: AUD
|
||||
0032: ARS
|
||||
0012: DZD
|
||||
0008: ALL
|
||||
@ -3,10 +3,12 @@
|
||||
#include <furi.h>
|
||||
#include <furi-hal-version.h>
|
||||
|
||||
#define TAG "Flipper"
|
||||
|
||||
static void flipper_print_version(const char* target, const Version* version) {
|
||||
if(version) {
|
||||
FURI_LOG_I(
|
||||
"FLIPPER",
|
||||
TAG,
|
||||
"\r\n\t%s version:\t%s\r\n"
|
||||
"\tBuild date:\t\t%s\r\n"
|
||||
"\tGit Commit:\t\t%s (%s)\r\n"
|
||||
@ -18,7 +20,7 @@ static void flipper_print_version(const char* target, const Version* version) {
|
||||
version_get_gitbranchnum(version),
|
||||
version_get_gitbranch(version));
|
||||
} else {
|
||||
FURI_LOG_I("FLIPPER", "No build info for %s", target);
|
||||
FURI_LOG_I(TAG, "No build info for %s", target);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,10 +33,10 @@ void flipper_init() {
|
||||
version = (const Version*)furi_hal_version_get_firmware_version();
|
||||
flipper_print_version("Firmware", version);
|
||||
|
||||
FURI_LOG_I("FLIPPER", "starting services");
|
||||
FURI_LOG_I(TAG, "starting services");
|
||||
|
||||
for(size_t i = 0; i < FLIPPER_SERVICES_COUNT; i++) {
|
||||
FURI_LOG_I("FLIPPER", "starting service %s", FLIPPER_SERVICES[i].name);
|
||||
FURI_LOG_I(TAG, "starting service %s", FLIPPER_SERVICES[i].name);
|
||||
|
||||
FuriThread* thread = furi_thread_alloc();
|
||||
|
||||
@ -45,5 +47,5 @@ void flipper_init() {
|
||||
furi_thread_start(thread);
|
||||
}
|
||||
|
||||
FURI_LOG_I("FLIPPER", "services startup complete");
|
||||
FURI_LOG_I(TAG, "services startup complete");
|
||||
}
|
||||
|
||||
6
core/furi/common_defines.h
Normal file → Executable file
6
core/furi/common_defines.h
Normal file → Executable file
@ -64,4 +64,10 @@
|
||||
|
||||
#ifndef TOSTRING
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#endif
|
||||
|
||||
#ifndef REVERSE_BYTES_U32
|
||||
#define REVERSE_BYTES_U32(x) \
|
||||
((((x)&0x000000FF) << 24) | (((x)&0x0000FF00) << 8) | (((x)&0x00FF0000) >> 8) | \
|
||||
(((x)&0xFF000000) >> 24))
|
||||
#endif
|
||||
@ -57,7 +57,7 @@
|
||||
#endif /* CMSIS_device_header */
|
||||
|
||||
#define configENABLE_FPU 1
|
||||
#define configENABLE_MPU 1
|
||||
#define configENABLE_MPU 0
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configSUPPORT_STATIC_ALLOCATION 0
|
||||
@ -101,6 +101,9 @@
|
||||
#define configTIMER_TASK_PRIORITY ( 2 )
|
||||
#define configTIMER_QUEUE_LENGTH 32
|
||||
#define configTIMER_TASK_STACK_DEPTH 256
|
||||
#define configTIMER_SERVICE_TASK_NAME "TimersSrv"
|
||||
|
||||
#define configIDLE_TASK_NAME "(-_-)"
|
||||
|
||||
/* Set the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
|
||||
40
firmware/targets/f6/Inc/stm32_assert.h
Normal file
40
firmware/targets/f6/Inc/stm32_assert.h
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32_assert.h
|
||||
* @brief STM32 assert file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32_ASSERT_H
|
||||
#define __STM32_ASSERT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#define assert_param(expr) ((expr) ? (void)0U : assert_failed())
|
||||
void assert_failed();
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32_ASSERT_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@ -184,7 +184,7 @@
|
||||
* @brief Uncomment the line below to expanse the "assert_param" macro in the
|
||||
* HAL drivers code
|
||||
*/
|
||||
/* #define USE_FULL_ASSERT 1U */
|
||||
#define USE_FULL_ASSERT 1U
|
||||
|
||||
/* ################## SPI peripheral configuration ########################## */
|
||||
|
||||
@ -329,17 +329,8 @@
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief The assert_param macro is used for function's parameters check.
|
||||
* @param expr If expr is false, it calls assert_failed function
|
||||
* which reports the name of the source file and the source
|
||||
* line number of the call that failed.
|
||||
* If expr is true, it returns no value.
|
||||
* @retval None
|
||||
*/
|
||||
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void assert_failed(uint8_t* file, uint32_t line);
|
||||
#define assert_param(expr) ((expr) ? (void)0U : assert_failed())
|
||||
void assert_failed();
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
#include "main.h"
|
||||
|
||||
#include "fatfs/fatfs.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
#include <flipper.h>
|
||||
|
||||
#define TAG "Main"
|
||||
|
||||
int main(void) {
|
||||
// Initialize FURI layer
|
||||
furi_init();
|
||||
@ -16,13 +16,9 @@ int main(void) {
|
||||
// Flipper FURI HAL
|
||||
furi_hal_init();
|
||||
|
||||
// 3rd party
|
||||
MX_FATFS_Init();
|
||||
FURI_LOG_I("HAL", "FATFS OK");
|
||||
|
||||
// CMSIS initialization
|
||||
osKernelInitialize();
|
||||
FURI_LOG_I("HAL", "KERNEL OK");
|
||||
FURI_LOG_I(TAG, "KERNEL OK");
|
||||
|
||||
// Init flipper
|
||||
flipper_init();
|
||||
@ -47,9 +43,6 @@ void Error_Handler(void) {
|
||||
* @retval None
|
||||
*/
|
||||
void assert_failed(uint8_t *file, uint32_t line) {
|
||||
/* USER CODE BEGIN 6 */
|
||||
/* User can add his own implementation to report the file name and line number,
|
||||
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||||
/* USER CODE END 6 */
|
||||
furi_crash("HAL assert failed");
|
||||
}
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define BATTERY_SERVICE_TAG "battery service"
|
||||
#define TAG "BtBatterySvc"
|
||||
|
||||
typedef struct {
|
||||
uint16_t svc_handle;
|
||||
@ -23,7 +23,7 @@ void battery_svc_start() {
|
||||
// Add Battery service
|
||||
status = aci_gatt_add_service(UUID_TYPE_16, (Service_UUID_t*)&service_uuid, PRIMARY_SERVICE, 4, &battery_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to add Battery service: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add Battery service: %d", status);
|
||||
}
|
||||
// Add Battery level characteristic
|
||||
status = aci_gatt_add_char(battery_svc->svc_handle,
|
||||
@ -37,7 +37,7 @@ void battery_svc_start() {
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&battery_svc->char_level_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to add Battery level characteristic: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,12 +47,12 @@ void battery_svc_stop() {
|
||||
// Delete Battery level characteristic
|
||||
status = aci_gatt_del_char(battery_svc->svc_handle, battery_svc->char_level_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to delete Battery level characteristic: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status);
|
||||
}
|
||||
// Delete Battery service
|
||||
status = aci_gatt_del_service(battery_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to delete Battery service: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete Battery service: %d", status);
|
||||
}
|
||||
free(battery_svc);
|
||||
battery_svc = NULL;
|
||||
@ -65,14 +65,14 @@ bool battery_svc_update_level(uint8_t battery_charge) {
|
||||
return false;
|
||||
}
|
||||
// Update battery level characteristic
|
||||
FURI_LOG_I(BATTERY_SERVICE_TAG, "Updating battery level characteristic");
|
||||
FURI_LOG_I(TAG, "Updating battery level characteristic");
|
||||
tBleStatus result = aci_gatt_update_char_value(battery_svc->svc_handle,
|
||||
battery_svc->char_level_handle,
|
||||
0,
|
||||
1,
|
||||
&battery_charge);
|
||||
if(result) {
|
||||
FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed updating RX characteristic: %d", result);
|
||||
FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result);
|
||||
}
|
||||
return result != BLE_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#include <furi-hal.h>
|
||||
|
||||
#define BLE_APP_TAG "ble app"
|
||||
#define TAG "Bt"
|
||||
|
||||
PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t ble_app_cmd_buffer;
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint32_t ble_app_nvm[BLE_NVM_SRAM_SIZE];
|
||||
@ -33,7 +33,7 @@ bool ble_app_init() {
|
||||
ble_app->hci_mtx = osMutexNew(NULL);
|
||||
ble_app->hci_sem = osSemaphoreNew(1, 0, NULL);
|
||||
// HCI transport layer thread to handle user asynch events
|
||||
ble_app->hci_thread_attr.name = "ble hci";
|
||||
ble_app->hci_thread_attr.name = "BleHciWorker";
|
||||
ble_app->hci_thread_attr.stack_size = 1024;
|
||||
ble_app->hci_thread_id = osThreadNew(ble_app_hci_thread, NULL, &ble_app->hci_thread_attr);
|
||||
|
||||
@ -53,7 +53,7 @@ bool ble_app_init() {
|
||||
};
|
||||
status = SHCI_C2_Config(&config_param);
|
||||
if(status) {
|
||||
FURI_LOG_E(BLE_APP_TAG, "Failed to configure 2nd core: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to configure 2nd core: %d", status);
|
||||
}
|
||||
|
||||
// Start ble stack on 2nd core
|
||||
@ -82,7 +82,7 @@ bool ble_app_init() {
|
||||
};
|
||||
status = SHCI_C2_BLE_Init(&ble_init_cmd_packet);
|
||||
if(status) {
|
||||
FURI_LOG_E(BLE_APP_TAG, "Failed to start ble stack: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to start ble stack: %d", status);
|
||||
}
|
||||
return status == SHCI_Success;
|
||||
}
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
#include "app_debug.h"
|
||||
#include <furi-hal.h>
|
||||
|
||||
#define TAG "Core2"
|
||||
|
||||
#define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH*4U*DIVC(( sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE ), 4U))
|
||||
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_event_pool[POOL_SIZE];
|
||||
@ -17,6 +19,16 @@ PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ble_glue_system_cmd_b
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_system_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U];
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
|
||||
|
||||
typedef enum {
|
||||
// Stage 1: core2 startup and FUS
|
||||
BleGlueStatusStartup,
|
||||
BleGlueStatusBroken,
|
||||
BleGlueStatusFusStarted,
|
||||
// Stage 2: radio stack
|
||||
BleGlueStatusRadioStackStarted,
|
||||
BleGlueStatusRadioStackMissing
|
||||
} BleGlueStatus;
|
||||
|
||||
typedef struct {
|
||||
osMutexId_t shci_mtx;
|
||||
osSemaphoreId_t shci_sem;
|
||||
@ -33,13 +45,6 @@ static void ble_glue_user_event_thread(void *argument);
|
||||
static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status);
|
||||
static void ble_glue_sys_user_event_callback(void* pPayload);
|
||||
|
||||
BleGlueStatus ble_glue_get_status() {
|
||||
if(!ble_glue) {
|
||||
return BleGlueStatusUninitialized;
|
||||
}
|
||||
return ble_glue->status;
|
||||
}
|
||||
|
||||
void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context) {
|
||||
furi_assert(ble_glue);
|
||||
furi_assert(callback);
|
||||
@ -50,7 +55,7 @@ void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback
|
||||
void ble_glue_init() {
|
||||
ble_glue = furi_alloc(sizeof(BleGlue));
|
||||
ble_glue->status = BleGlueStatusStartup;
|
||||
ble_glue->shci_user_event_thread_attr.name = "ble_shci_evt";
|
||||
ble_glue->shci_user_event_thread_attr.name = "BleShciWorker";
|
||||
ble_glue->shci_user_event_thread_attr.stack_size = 1024;
|
||||
|
||||
// Configure the system Power Mode
|
||||
@ -94,6 +99,68 @@ void ble_glue_init() {
|
||||
*/
|
||||
}
|
||||
|
||||
static bool ble_glue_wait_status(BleGlueStatus status) {
|
||||
bool ret = false;
|
||||
size_t countdown = 1000;
|
||||
while (countdown > 0) {
|
||||
if (ble_glue->status == status) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
countdown--;
|
||||
osDelay(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ble_glue_start() {
|
||||
furi_assert(ble_glue);
|
||||
|
||||
if (!ble_glue_wait_status(BleGlueStatusFusStarted)) {
|
||||
// shutdown core2 power
|
||||
FURI_LOG_E(TAG, "Core2 catastrophic failure, cutting its power");
|
||||
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
||||
ble_glue->status = BleGlueStatusBroken;
|
||||
furi_hal_power_insomnia_exit();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
furi_hal_power_insomnia_enter();
|
||||
if(ble_app_init()) {
|
||||
FURI_LOG_I(TAG, "Radio stack started");
|
||||
ble_glue->status = BleGlueStatusRadioStackStarted;
|
||||
ret = true;
|
||||
if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) {
|
||||
FURI_LOG_I(TAG, "Flash activity control switched to SEM7");
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to switch flash activity control to SEM7");
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Radio stack startup failed");
|
||||
ble_glue->status = BleGlueStatusRadioStackMissing;
|
||||
}
|
||||
furi_hal_power_insomnia_exit();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ble_glue_is_alive() {
|
||||
if(!ble_glue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ble_glue->status >= BleGlueStatusFusStarted;
|
||||
}
|
||||
|
||||
bool ble_glue_is_radio_stack_ready() {
|
||||
if(!ble_glue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ble_glue->status == BleGlueStatusRadioStackStarted;
|
||||
}
|
||||
|
||||
static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) {
|
||||
switch (status) {
|
||||
case SHCI_TL_CmdBusy:
|
||||
@ -124,21 +191,11 @@ static void ble_glue_sys_user_event_callback( void * pPayload ) {
|
||||
TL_AsynchEvt_t *p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
||||
|
||||
if(p_sys_event->subevtcode == SHCI_SUB_EVT_CODE_READY) {
|
||||
if(ble_app_init()) {
|
||||
FURI_LOG_I("Core2", "BLE stack started");
|
||||
ble_glue->status = BleGlueStatusStarted;
|
||||
if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) {
|
||||
FURI_LOG_I("Core2", "Flash activity control switched to SEM7");
|
||||
} else {
|
||||
FURI_LOG_E("Core2", "Failed to switch flash activity control to SEM7");
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E("Core2", "BLE stack startup failed");
|
||||
ble_glue->status = BleGlueStatusBleStackMissing;
|
||||
}
|
||||
FURI_LOG_I(TAG, "Fus started");
|
||||
ble_glue->status = BleGlueStatusFusStarted;
|
||||
furi_hal_power_insomnia_exit();
|
||||
} else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) {
|
||||
FURI_LOG_E("Core2", "Error during initialization");
|
||||
FURI_LOG_E(TAG, "Error during initialization");
|
||||
furi_hal_power_insomnia_exit();
|
||||
} else if(p_sys_event->subevtcode == SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE) {
|
||||
SHCI_C2_BleNvmRamUpdate_Evt_t* p_sys_ble_nvm_ram_update_event = (SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -8,17 +9,33 @@ extern "C" {
|
||||
|
||||
typedef void(*BleGlueKeyStorageChangedCallback)(uint8_t* change_addr_start, uint16_t size, void* context);
|
||||
|
||||
typedef enum {
|
||||
BleGlueStatusUninitialized,
|
||||
BleGlueStatusStartup,
|
||||
BleGlueStatusBleStackMissing,
|
||||
BleGlueStatusStarted
|
||||
} BleGlueStatus;
|
||||
|
||||
/** Initialize start core2 and initialize transport */
|
||||
void ble_glue_init();
|
||||
|
||||
BleGlueStatus ble_glue_get_status();
|
||||
/** Start Core2 Radio stack
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool ble_glue_start();
|
||||
|
||||
/** Is core2 alive and at least FUS is running
|
||||
*
|
||||
* @return true if core2 is alive
|
||||
*/
|
||||
bool ble_glue_is_alive();
|
||||
|
||||
/** Is core2 radio stack present and ready
|
||||
*
|
||||
* @return true if present and ready
|
||||
*/
|
||||
bool ble_glue_is_radio_stack_ready();
|
||||
|
||||
/** Set callback for NVM in RAM changes
|
||||
*
|
||||
* @param[in] callback The callback to call on NVM change
|
||||
* @param context The context for callback
|
||||
*/
|
||||
void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define DEV_INFO_SVC_TAG "dev info service"
|
||||
#define TAG "BtDevInfoSvc"
|
||||
|
||||
typedef struct {
|
||||
uint16_t service_handle;
|
||||
@ -29,7 +29,7 @@ void dev_info_svc_start() {
|
||||
uint16_t uuid = DEVICE_INFORMATION_SERVICE_UUID;
|
||||
status = aci_gatt_add_service(UUID_TYPE_16, (Service_UUID_t*)&uuid, PRIMARY_SERVICE, 9, &dev_info_svc->service_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add Device Information Service: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add Device Information Service: %d", status);
|
||||
}
|
||||
|
||||
// Add characteristics
|
||||
@ -45,7 +45,7 @@ void dev_info_svc_start() {
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&dev_info_svc->man_name_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add manufacturer name char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add manufacturer name char: %d", status);
|
||||
}
|
||||
uuid = SERIAL_NUMBER_UUID;
|
||||
status = aci_gatt_add_char(dev_info_svc->service_handle,
|
||||
@ -59,7 +59,7 @@ void dev_info_svc_start() {
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&dev_info_svc->serial_num_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add serial number char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add serial number char: %d", status);
|
||||
}
|
||||
uuid = FIRMWARE_REVISION_UUID;
|
||||
status = aci_gatt_add_char(dev_info_svc->service_handle,
|
||||
@ -73,7 +73,7 @@ void dev_info_svc_start() {
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&dev_info_svc->firmware_rev_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add firmware revision char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add firmware revision char: %d", status);
|
||||
}
|
||||
uuid = SOFTWARE_REVISION_UUID;
|
||||
status = aci_gatt_add_char(dev_info_svc->service_handle,
|
||||
@ -87,7 +87,7 @@ void dev_info_svc_start() {
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&dev_info_svc->software_rev_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add software revision char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add software revision char: %d", status);
|
||||
}
|
||||
|
||||
// Update characteristics
|
||||
@ -97,7 +97,7 @@ void dev_info_svc_start() {
|
||||
strlen(dev_info_man_name),
|
||||
(uint8_t*)dev_info_man_name);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update manufacturer name char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to update manufacturer name char: %d", status);
|
||||
}
|
||||
status = aci_gatt_update_char_value(dev_info_svc->service_handle,
|
||||
dev_info_svc->serial_num_char_handle,
|
||||
@ -105,7 +105,7 @@ void dev_info_svc_start() {
|
||||
strlen(dev_info_serial_num),
|
||||
(uint8_t*)dev_info_serial_num);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update serial number char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to update serial number char: %d", status);
|
||||
}
|
||||
status = aci_gatt_update_char_value(dev_info_svc->service_handle,
|
||||
dev_info_svc->firmware_rev_char_handle,
|
||||
@ -113,7 +113,7 @@ void dev_info_svc_start() {
|
||||
strlen(dev_info_firmware_rev_num),
|
||||
(uint8_t*)dev_info_firmware_rev_num);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update firmware revision char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to update firmware revision char: %d", status);
|
||||
}
|
||||
status = aci_gatt_update_char_value(dev_info_svc->service_handle,
|
||||
dev_info_svc->software_rev_char_handle,
|
||||
@ -121,7 +121,7 @@ void dev_info_svc_start() {
|
||||
strlen(dev_info_software_rev_num),
|
||||
(uint8_t*)dev_info_software_rev_num);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update software revision char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to update software revision char: %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,24 +131,24 @@ void dev_info_svc_stop() {
|
||||
// Delete service characteristics
|
||||
status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->man_name_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete manufacturer name char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete manufacturer name char: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->serial_num_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete serial number char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete serial number char: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete firmware revision char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete firmware revision char: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete software revision char: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete software revision char: %d", status);
|
||||
}
|
||||
// Delete service
|
||||
status = aci_gatt_del_service(dev_info_svc->service_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete device info service: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete device info service: %d", status);
|
||||
}
|
||||
free(dev_info_svc);
|
||||
dev_info_svc = NULL;
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
#include <furi-hal.h>
|
||||
|
||||
#define GAP_TAG "BLE"
|
||||
#define TAG "BtGap"
|
||||
|
||||
#define FAST_ADV_TIMEOUT 30000
|
||||
#define INITIAL_ADV_TIMEOUT 60000
|
||||
@ -80,7 +80,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt )
|
||||
if (disconnection_complete_event->Connection_Handle == gap->gap_svc.connection_handle) {
|
||||
gap->gap_svc.connection_handle = 0;
|
||||
gap->state = GapStateIdle;
|
||||
FURI_LOG_I(GAP_TAG, "Disconnect from client. Reason: %d", disconnection_complete_event->Reason);
|
||||
FURI_LOG_I(TAG, "Disconnect from client. Reason: %d", disconnection_complete_event->Reason);
|
||||
}
|
||||
if(gap->enable_adv) {
|
||||
// Restart advertising
|
||||
@ -96,28 +96,28 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt )
|
||||
meta_evt = (evt_le_meta_event*) event_pckt->data;
|
||||
switch (meta_evt->subevent) {
|
||||
case EVT_LE_CONN_UPDATE_COMPLETE:
|
||||
FURI_LOG_D(GAP_TAG, "Connection update event");
|
||||
FURI_LOG_D(TAG, "Connection update event");
|
||||
break;
|
||||
|
||||
case EVT_LE_PHY_UPDATE_COMPLETE:
|
||||
evt_le_phy_update_complete = (hci_le_phy_update_complete_event_rp0*)meta_evt->data;
|
||||
if(evt_le_phy_update_complete->Status) {
|
||||
FURI_LOG_E(GAP_TAG, "Update PHY failed, status %d", evt_le_phy_update_complete->Status);
|
||||
FURI_LOG_E(TAG, "Update PHY failed, status %d", evt_le_phy_update_complete->Status);
|
||||
} else {
|
||||
FURI_LOG_I(GAP_TAG, "Update PHY succeed");
|
||||
FURI_LOG_I(TAG, "Update PHY succeed");
|
||||
}
|
||||
ret = hci_le_read_phy(gap->gap_svc.connection_handle,&tx_phy,&rx_phy);
|
||||
if(ret) {
|
||||
FURI_LOG_E(GAP_TAG, "Read PHY failed, status: %d", ret);
|
||||
FURI_LOG_E(TAG, "Read PHY failed, status: %d", ret);
|
||||
} else {
|
||||
FURI_LOG_I(GAP_TAG, "PHY Params TX = %d, RX = %d ", tx_phy, rx_phy);
|
||||
FURI_LOG_I(TAG, "PHY Params TX = %d, RX = %d ", tx_phy, rx_phy);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVT_LE_CONN_COMPLETE:
|
||||
furi_hal_power_insomnia_enter();
|
||||
hci_le_connection_complete_event_rp0* connection_complete_event = (hci_le_connection_complete_event_rp0 *) meta_evt->data;
|
||||
FURI_LOG_I(GAP_TAG, "Connection complete for connection handle 0x%x", connection_complete_event->Connection_Handle);
|
||||
FURI_LOG_I(TAG, "Connection complete for connection handle 0x%x", connection_complete_event->Connection_Handle);
|
||||
|
||||
// Stop advertising as connection completed
|
||||
osTimerStop(gap->advertise_timer);
|
||||
@ -141,7 +141,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt )
|
||||
aci_gap_pairing_complete_event_rp0 *pairing_complete;
|
||||
|
||||
case EVT_BLUE_GAP_LIMITED_DISCOVERABLE:
|
||||
FURI_LOG_I(GAP_TAG, "Limited discoverable event");
|
||||
FURI_LOG_I(TAG, "Limited discoverable event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_PASS_KEY_REQUEST:
|
||||
@ -149,39 +149,39 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt )
|
||||
// Generate random PIN code
|
||||
uint32_t pin = rand() % 999999;
|
||||
aci_gap_pass_key_resp(gap->gap_svc.connection_handle, pin);
|
||||
FURI_LOG_I(GAP_TAG, "Pass key request event. Pin: %d", pin);
|
||||
FURI_LOG_I(TAG, "Pass key request event. Pin: %d", pin);
|
||||
BleEvent event = {.type = BleEventTypePinCodeShow, .data.pin_code = pin};
|
||||
gap->on_event_cb(event, gap->context);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_AUTHORIZATION_REQUEST:
|
||||
FURI_LOG_I(GAP_TAG, "Authorization request event");
|
||||
FURI_LOG_I(TAG, "Authorization request event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED:
|
||||
FURI_LOG_I(GAP_TAG, "Slave security initiated");
|
||||
FURI_LOG_I(TAG, "Slave security initiated");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_BOND_LOST:
|
||||
FURI_LOG_I(GAP_TAG, "Bond lost event. Start rebonding");
|
||||
FURI_LOG_I(TAG, "Bond lost event. Start rebonding");
|
||||
aci_gap_allow_rebond(gap->gap_svc.connection_handle);
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_DEVICE_FOUND:
|
||||
FURI_LOG_I(GAP_TAG, "Device found event");
|
||||
FURI_LOG_I(TAG, "Device found event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_ADDR_NOT_RESOLVED:
|
||||
FURI_LOG_I(GAP_TAG, "Address not resolved event");
|
||||
FURI_LOG_I(TAG, "Address not resolved event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_KEYPRESS_NOTIFICATION:
|
||||
FURI_LOG_I(GAP_TAG, "Key press notification event");
|
||||
FURI_LOG_I(TAG, "Key press notification event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE:
|
||||
FURI_LOG_I(GAP_TAG, "Hex_value = %lx",
|
||||
FURI_LOG_I(TAG, "Hex_value = %lx",
|
||||
((aci_gap_numeric_comparison_value_event_rp0 *)(blue_evt->data))->Numeric_Value);
|
||||
aci_gap_numeric_comparison_value_confirm_yesno(gap->gap_svc.connection_handle, 1);
|
||||
break;
|
||||
@ -189,17 +189,17 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt )
|
||||
case EVT_BLUE_GAP_PAIRING_CMPLT:
|
||||
pairing_complete = (aci_gap_pairing_complete_event_rp0*)blue_evt->data;
|
||||
if (pairing_complete->Status) {
|
||||
FURI_LOG_E(GAP_TAG, "Pairing failed with status: %d. Terminating connection", pairing_complete->Status);
|
||||
FURI_LOG_E(TAG, "Pairing failed with status: %d. Terminating connection", pairing_complete->Status);
|
||||
aci_gap_terminate(gap->gap_svc.connection_handle, 5);
|
||||
} else {
|
||||
FURI_LOG_I(GAP_TAG, "Pairing complete");
|
||||
FURI_LOG_I(TAG, "Pairing complete");
|
||||
BleEvent event = {.type = BleEventTypeConnected};
|
||||
gap->on_event_cb(event, gap->context);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_PROCEDURE_COMPLETE:
|
||||
FURI_LOG_I(GAP_TAG, "Procedure complete event");
|
||||
FURI_LOG_I(TAG, "Procedure complete event");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -286,11 +286,11 @@ static void gap_init_svc(Gap* gap) {
|
||||
// Set GAP characteristics
|
||||
status = aci_gatt_update_char_value(gap->gap_svc.gap_svc_handle, gap->gap_svc.dev_name_char_handle, 0, strlen(name), (uint8_t *) name);
|
||||
if (status) {
|
||||
FURI_LOG_E(GAP_TAG, "Failed updating name characteristic: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed updating name characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_update_char_value(gap->gap_svc.gap_svc_handle, gap->gap_svc.appearance_char_handle, 0, 2, gap_appearence_char_uuid);
|
||||
if(status) {
|
||||
FURI_LOG_E(GAP_TAG, "Failed updating appearence characteristic: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed updating appearence characteristic: %d", status);
|
||||
}
|
||||
// Set default PHY
|
||||
hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED);
|
||||
@ -322,7 +322,7 @@ static void gap_advertise_start(GapState new_state)
|
||||
// Stop advertising
|
||||
status = aci_gap_set_non_discoverable();
|
||||
if (status) {
|
||||
FURI_LOG_E(GAP_TAG, "Stop Advertising Failed, result: %d", status);
|
||||
FURI_LOG_E(TAG, "Stop Advertising Failed, result: %d", status);
|
||||
}
|
||||
}
|
||||
// Configure advertising
|
||||
@ -331,7 +331,7 @@ static void gap_advertise_start(GapState new_state)
|
||||
strlen(name), (uint8_t*)name,
|
||||
gap->gap_svc.adv_svc_uuid_len, gap->gap_svc.adv_svc_uuid, 0, 0);
|
||||
if(status) {
|
||||
FURI_LOG_E(GAP_TAG, "Set discoverable err: %d", status);
|
||||
FURI_LOG_E(TAG, "Set discoverable err: %d", status);
|
||||
}
|
||||
gap->state = new_state;
|
||||
BleEvent event = {.type = BleEventTypeStartAdvertising};
|
||||
@ -355,14 +355,14 @@ static void gap_advertise_stop() {
|
||||
}
|
||||
|
||||
void gap_start_advertising() {
|
||||
FURI_LOG_I(GAP_TAG, "Start advertising");
|
||||
FURI_LOG_I(TAG, "Start advertising");
|
||||
gap->enable_adv = true;
|
||||
GapCommand command = GapCommandAdvFast;
|
||||
furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK);
|
||||
}
|
||||
|
||||
void gap_stop_advertising() {
|
||||
FURI_LOG_I(GAP_TAG, "Stop advertising");
|
||||
FURI_LOG_I(TAG, "Stop advertising");
|
||||
gap->enable_adv = false;
|
||||
GapCommand command = GapCommandAdvStop;
|
||||
furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK);
|
||||
@ -374,7 +374,7 @@ static void gap_advetise_timer_callback(void* context) {
|
||||
}
|
||||
|
||||
bool gap_init(BleEventCallback on_event_cb, void* context) {
|
||||
if (ble_glue_get_status() != BleGlueStatusStarted) {
|
||||
if (!ble_glue_is_radio_stack_ready()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -393,7 +393,7 @@ bool gap_init(BleEventCallback on_event_cb, void* context) {
|
||||
gap->enable_adv = true;
|
||||
|
||||
// Thread configuration
|
||||
gap->thread_attr.name = "BLE advertising";
|
||||
gap->thread_attr.name = "BleGapWorker";
|
||||
gap->thread_attr.stack_size = 1024;
|
||||
gap->thread_id = osThreadNew(gap_app, NULL, &gap->thread_attr);
|
||||
|
||||
|
||||
@ -4,22 +4,27 @@
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define SERIAL_SERVICE_TAG "serial service"
|
||||
#define TAG "BtSerialSvc"
|
||||
|
||||
typedef struct {
|
||||
uint16_t svc_handle;
|
||||
uint16_t rx_char_handle;
|
||||
uint16_t tx_char_handle;
|
||||
uint16_t flow_ctrl_char_handle;
|
||||
osMutexId_t buff_size_mtx;
|
||||
uint32_t buff_size;
|
||||
uint16_t bytes_ready_to_receive;
|
||||
SerialSvcDataReceivedCallback on_received_cb;
|
||||
SerialSvcDataSentCallback on_sent_cb;
|
||||
void* context;
|
||||
} SerialSvc;
|
||||
|
||||
static SerialSvc* serial_svc;
|
||||
static SerialSvc* serial_svc = NULL;
|
||||
|
||||
static const uint8_t service_uuid[] = {0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f};
|
||||
static const uint8_t char_rx_uuid[] = {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||
static const uint8_t char_tx_uuid[] = {0x00, 0x00, 0xfe, 0x61, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||
static const uint8_t char_rx_uuid[] = {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||
static const uint8_t flow_ctrl_uuid[] = {0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||
|
||||
static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void *event) {
|
||||
SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck;
|
||||
@ -32,16 +37,26 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void *event) {
|
||||
if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 2) {
|
||||
// Descriptor handle
|
||||
ret = SVCCTL_EvtAckFlowEnable;
|
||||
FURI_LOG_D(SERIAL_SERVICE_TAG, "RX descriptor event");
|
||||
FURI_LOG_D(TAG, "RX descriptor event");
|
||||
} else if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 1) {
|
||||
FURI_LOG_D(SERIAL_SERVICE_TAG, "Received %d bytes", attribute_modified->Attr_Data_Length);
|
||||
FURI_LOG_D(TAG, "Received %d bytes", attribute_modified->Attr_Data_Length);
|
||||
if(serial_svc->on_received_cb) {
|
||||
serial_svc->on_received_cb(attribute_modified->Attr_Data, attribute_modified->Attr_Data_Length, serial_svc->context);
|
||||
furi_check(osMutexAcquire(serial_svc->buff_size_mtx, osWaitForever) == osOK);
|
||||
if(attribute_modified->Attr_Data_Length > serial_svc->bytes_ready_to_receive) {
|
||||
FURI_LOG_W(
|
||||
TAG, "Received %d, while was ready to receive %d bytes. Can lead to buffer overflow!",
|
||||
attribute_modified->Attr_Data_Length, serial_svc->bytes_ready_to_receive);
|
||||
}
|
||||
serial_svc->bytes_ready_to_receive -= MIN(serial_svc->bytes_ready_to_receive, attribute_modified->Attr_Data_Length);
|
||||
uint32_t buff_free_size =
|
||||
serial_svc->on_received_cb(attribute_modified->Attr_Data, attribute_modified->Attr_Data_Length, serial_svc->context);
|
||||
FURI_LOG_D(TAG, "Available buff size: %d", buff_free_size);
|
||||
furi_check(osMutexRelease(serial_svc->buff_size_mtx) == osOK);
|
||||
}
|
||||
ret = SVCCTL_EvtAckFlowEnable;
|
||||
}
|
||||
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
|
||||
FURI_LOG_D(SERIAL_SERVICE_TAG, "Ack received", blecore_evt->ecode);
|
||||
FURI_LOG_D(TAG, "Ack received", blecore_evt->ecode);
|
||||
if(serial_svc->on_sent_cb) {
|
||||
serial_svc->on_sent_cb(serial_svc->context);
|
||||
}
|
||||
@ -58,9 +73,9 @@ void serial_svc_start() {
|
||||
SVCCTL_RegisterSvcHandler(serial_svc_event_handler);
|
||||
|
||||
// Add service
|
||||
status = aci_gatt_add_service(UUID_TYPE_128, (Service_UUID_t *)service_uuid, PRIMARY_SERVICE, 6, &serial_svc->svc_handle);
|
||||
status = aci_gatt_add_service(UUID_TYPE_128, (Service_UUID_t *)service_uuid, PRIMARY_SERVICE, 10, &serial_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add Serial service: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add Serial service: %d", status);
|
||||
}
|
||||
|
||||
// Add RX characteristics
|
||||
@ -73,12 +88,12 @@ void serial_svc_start() {
|
||||
CHAR_VALUE_LEN_VARIABLE,
|
||||
&serial_svc->rx_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add RX characteristic: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add RX characteristic: %d", status);
|
||||
}
|
||||
|
||||
// Add TX characteristic
|
||||
status = aci_gatt_add_char(serial_svc->svc_handle, UUID_TYPE_128, (const Char_UUID_t*)char_tx_uuid,
|
||||
SERIAL_SVC_DATA_LEN_MAX,
|
||||
SERIAL_SVC_DATA_LEN_MAX,
|
||||
CHAR_PROP_READ | CHAR_PROP_INDICATE,
|
||||
ATTR_PERMISSION_AUTHEN_READ,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
@ -86,14 +101,47 @@ void serial_svc_start() {
|
||||
CHAR_VALUE_LEN_VARIABLE,
|
||||
&serial_svc->tx_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add TX characteristic: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to add TX characteristic: %d", status);
|
||||
}
|
||||
// Add Flow Control characteristic
|
||||
status = aci_gatt_add_char(serial_svc->svc_handle, UUID_TYPE_128, (const Char_UUID_t*)flow_ctrl_uuid,
|
||||
sizeof(uint32_t),
|
||||
CHAR_PROP_READ | CHAR_PROP_NOTIFY,
|
||||
ATTR_PERMISSION_AUTHEN_READ,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&serial_svc->flow_ctrl_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status);
|
||||
}
|
||||
// Allocate buffer size mutex
|
||||
serial_svc->buff_size_mtx = osMutexNew(NULL);
|
||||
}
|
||||
|
||||
void serial_svc_set_callbacks(SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) {
|
||||
void serial_svc_set_callbacks(uint16_t buff_size, SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) {
|
||||
furi_assert(serial_svc);
|
||||
serial_svc->on_received_cb = on_received_cb;
|
||||
serial_svc->on_sent_cb = on_sent_cb;
|
||||
serial_svc->context = context;
|
||||
serial_svc->buff_size = buff_size;
|
||||
serial_svc->bytes_ready_to_receive = buff_size;
|
||||
uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size);
|
||||
aci_gatt_update_char_value(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle, 0, sizeof(uint32_t), (uint8_t*)&buff_size_reversed);
|
||||
}
|
||||
|
||||
void serial_svc_notify_buffer_is_empty() {
|
||||
furi_assert(serial_svc);
|
||||
furi_assert(serial_svc->buff_size_mtx);
|
||||
|
||||
furi_check(osMutexAcquire(serial_svc->buff_size_mtx, osWaitForever) == osOK);
|
||||
if(serial_svc->bytes_ready_to_receive == 0) {
|
||||
FURI_LOG_D(TAG, "Buffer is empty. Notifying client");
|
||||
serial_svc->bytes_ready_to_receive = serial_svc->buff_size;
|
||||
uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size);
|
||||
aci_gatt_update_char_value(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle, 0, sizeof(uint32_t), (uint8_t*)&buff_size_reversed);
|
||||
}
|
||||
furi_check(osMutexRelease(serial_svc->buff_size_mtx) == osOK);
|
||||
}
|
||||
|
||||
void serial_svc_stop() {
|
||||
@ -102,17 +150,23 @@ void serial_svc_stop() {
|
||||
// Delete characteristics
|
||||
status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->tx_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to delete TX characteristic: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete TX characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rx_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to delete RX characteristic: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete RX characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status);
|
||||
}
|
||||
// Delete service
|
||||
status = aci_gatt_del_service(serial_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to delete Serial service: %d", status);
|
||||
FURI_LOG_E(TAG, "Failed to delete Serial service: %d", status);
|
||||
}
|
||||
// Delete buffer size mutex
|
||||
osMutexDelete(serial_svc->buff_size_mtx);
|
||||
free(serial_svc);
|
||||
serial_svc = NULL;
|
||||
}
|
||||
@ -122,14 +176,13 @@ bool serial_svc_update_tx(uint8_t* data, uint8_t data_len) {
|
||||
if(data_len > SERIAL_SVC_DATA_LEN_MAX) {
|
||||
return false;
|
||||
}
|
||||
FURI_LOG_D(SERIAL_SERVICE_TAG, "Updating char %d len", data_len);
|
||||
tBleStatus result = aci_gatt_update_char_value(serial_svc->svc_handle,
|
||||
serial_svc->tx_char_handle,
|
||||
0,
|
||||
data_len,
|
||||
data);
|
||||
if(result) {
|
||||
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed updating TX characteristic: %d", result);
|
||||
FURI_LOG_E(TAG, "Failed updating TX characteristic: %d", result);
|
||||
}
|
||||
return result != BLE_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -9,12 +9,14 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void(*SerialSvcDataReceivedCallback)(uint8_t* buff, uint16_t size, void* context);
|
||||
typedef uint16_t(*SerialSvcDataReceivedCallback)(uint8_t* buff, uint16_t size, void* context);
|
||||
typedef void(*SerialSvcDataSentCallback)(void* context);
|
||||
|
||||
void serial_svc_start();
|
||||
|
||||
void serial_svc_set_callbacks(SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context);
|
||||
void serial_svc_set_callbacks(uint16_t buff_size, SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context);
|
||||
|
||||
void serial_svc_notify_buffer_is_empty();
|
||||
|
||||
void serial_svc_stop();
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user