Merge branch 'fz-dev' into dev

This commit is contained in:
MX 2022-11-04 14:34:34 +03:00
commit 0ab400a27e
No known key found for this signature in database
GPG key ID: 6C4C311DFD4B4AB5
100 changed files with 1881 additions and 20 deletions

View file

@ -170,9 +170,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
} else if(event.event == SubGhzCustomEventSceneReceiverInfoSave) { } else if(event.event == SubGhzCustomEventSceneReceiverInfoSave) {
//CC1101 Stop RX -> Save //CC1101 Stop RX -> Save
subghz->state_notifications = SubGhzNotificationStateIDLE; subghz->state_notifications = SubGhzNotificationStateIDLE;
if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { subghz->txrx->hopper_state = SubGhzHopperStateOFF;
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
}
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
subghz_rx_end(subghz); subghz_rx_end(subghz);
subghz_sleep(subghz); subghz_sleep(subghz);

View file

@ -42,9 +42,8 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
bool result = false; bool result = false;
if((subghz->txrx->txrx_state == SubGhzTxRxStateSleep) && if((subghz->txrx->txrx_state == SubGhzTxRxStateSleep) &&
(state == SubGhzRpcStateLoaded)) { (state == SubGhzRpcStateLoaded)) {
subghz_blink_start(subghz);
result = subghz_tx_start(subghz, subghz->txrx->fff_data); result = subghz_tx_start(subghz, subghz->txrx->fff_data);
result = true; if(result) subghz_blink_start(subghz);
} }
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result); rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result);
} else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) { } else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) {

View file

@ -72,8 +72,8 @@ void dap_scene_config_on_enter(void* context) {
variable_item_set_current_value_index(item, config->uart_swap); variable_item_set_current_value_index(item, config->uart_swap);
variable_item_set_current_value_text(item, uart_swap[config->uart_swap]); variable_item_set_current_value_text(item, uart_swap[config->uart_swap]);
item = variable_item_list_add(var_item_list, "Help and Pinout", 0, NULL, NULL); variable_item_list_add(var_item_list, "Help and Pinout", 0, NULL, NULL);
item = variable_item_list_add(var_item_list, "About", 0, NULL, NULL); variable_item_list_add(var_item_list, "About", 0, NULL, NULL);
variable_item_list_set_selected_item( variable_item_list_set_selected_item(
var_item_list, scene_manager_get_scene_state(app->scene_manager, DapSceneConfig)); var_item_list, scene_manager_get_scene_state(app->scene_manager, DapSceneConfig));

View file

@ -0,0 +1,20 @@
App(
appid="nfc_magic",
name="Nfc Magic",
apptype=FlipperAppType.EXTERNAL,
entry_point="nfc_magic_app",
requires=[
"storage",
"gui",
],
stack_size=4 * 1024,
order=30,
fap_icon="../../../assets/icons/Archive/125_10px.png",
fap_category="Tools",
fap_private_libs=[
Lib(
name="magic",
),
],
fap_icon_assets="assets",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -0,0 +1,214 @@
#include "magic.h"
#include <furi_hal_nfc.h>
#define TAG "Magic"
#define MAGIC_CMD_WUPA (0x40)
#define MAGIC_CMD_WIPE (0x41)
#define MAGIC_CMD_READ (0x43)
#define MAGIC_CMD_WRITE (0x43)
#define MAGIC_MIFARE_READ_CMD (0x30)
#define MAGIC_MIFARE_WRITE_CMD (0xA0)
#define MAGIC_ACK (0x0A)
#define MAGIC_BUFFER_SIZE (32)
bool magic_wupa() {
bool magic_activated = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
// Setup nfc poller
furi_hal_nfc_exit_sleep();
furi_hal_nfc_ll_txrx_on();
furi_hal_nfc_ll_poll();
ret = furi_hal_nfc_ll_set_mode(
FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106);
if(ret != FuriHalNfcReturnOk) break;
furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER);
furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER);
furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc);
furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA);
// Start communication
tx_data[0] = MAGIC_CMD_WUPA;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
7,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
magic_activated = true;
} while(false);
if(!magic_activated) {
furi_hal_nfc_ll_txrx_off();
furi_hal_nfc_start_sleep();
}
return magic_activated;
}
bool magic_data_access_cmd() {
bool write_cmd_success = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
tx_data[0] = MAGIC_CMD_WRITE;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
write_cmd_success = true;
} while(false);
if(!write_cmd_success) {
furi_hal_nfc_ll_txrx_off();
furi_hal_nfc_start_sleep();
}
return write_cmd_success;
}
bool magic_read_block(uint8_t block_num, MfClassicBlock* data) {
furi_assert(data);
bool read_success = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
tx_data[0] = MAGIC_MIFARE_READ_CMD;
tx_data[1] = block_num;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
2 * 8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnOk) break;
if(rx_len != 16 * 8) break;
memcpy(data->value, rx_data, sizeof(data->value));
read_success = true;
} while(false);
if(!read_success) {
furi_hal_nfc_ll_txrx_off();
furi_hal_nfc_start_sleep();
}
return read_success;
}
bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) {
furi_assert(data);
bool write_success = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
tx_data[0] = MAGIC_MIFARE_WRITE_CMD;
tx_data[1] = block_num;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
2 * 8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
memcpy(tx_data, data->value, sizeof(data->value));
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
16 * 8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
write_success = true;
} while(false);
if(!write_success) {
furi_hal_nfc_ll_txrx_off();
furi_hal_nfc_start_sleep();
}
return write_success;
}
bool magic_wipe() {
bool wipe_success = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
tx_data[0] = MAGIC_CMD_WIPE;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(2000));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
wipe_success = true;
} while(false);
return wipe_success;
}
void magic_deactivate() {
furi_hal_nfc_ll_txrx_off();
furi_hal_nfc_start_sleep();
}

View file

@ -0,0 +1,15 @@
#pragma once
#include <lib/nfc/protocols/mifare_classic.h>
bool magic_wupa();
bool magic_read_block(uint8_t block_num, MfClassicBlock* data);
bool magic_data_access_cmd();
bool magic_write_blk(uint8_t block_num, MfClassicBlock* data);
bool magic_wipe();
void magic_deactivate();

View file

@ -0,0 +1,169 @@
#include "nfc_magic_i.h"
bool nfc_magic_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);
NfcMagic* nfc_magic = context;
return scene_manager_handle_custom_event(nfc_magic->scene_manager, event);
}
bool nfc_magic_back_event_callback(void* context) {
furi_assert(context);
NfcMagic* nfc_magic = context;
return scene_manager_handle_back_event(nfc_magic->scene_manager);
}
void nfc_magic_tick_event_callback(void* context) {
furi_assert(context);
NfcMagic* nfc_magic = context;
scene_manager_handle_tick_event(nfc_magic->scene_manager);
}
void nfc_magic_show_loading_popup(void* context, bool show) {
NfcMagic* nfc_magic = context;
TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
if(show) {
// Raise timer priority so that animations can play
vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1);
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewLoading);
} else {
// Restore default timer priority
vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY);
}
}
NfcMagic* nfc_magic_alloc() {
NfcMagic* nfc_magic = malloc(sizeof(NfcMagic));
nfc_magic->worker = nfc_magic_worker_alloc();
nfc_magic->view_dispatcher = view_dispatcher_alloc();
nfc_magic->scene_manager = scene_manager_alloc(&nfc_magic_scene_handlers, nfc_magic);
view_dispatcher_enable_queue(nfc_magic->view_dispatcher);
view_dispatcher_set_event_callback_context(nfc_magic->view_dispatcher, nfc_magic);
view_dispatcher_set_custom_event_callback(
nfc_magic->view_dispatcher, nfc_magic_custom_event_callback);
view_dispatcher_set_navigation_event_callback(
nfc_magic->view_dispatcher, nfc_magic_back_event_callback);
view_dispatcher_set_tick_event_callback(
nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100);
// Nfc device
nfc_magic->nfc_dev = nfc_device_alloc();
// Open GUI record
nfc_magic->gui = furi_record_open(RECORD_GUI);
view_dispatcher_attach_to_gui(
nfc_magic->view_dispatcher, nfc_magic->gui, ViewDispatcherTypeFullscreen);
// Open Notification record
nfc_magic->notifications = furi_record_open(RECORD_NOTIFICATION);
// Submenu
nfc_magic->submenu = submenu_alloc();
view_dispatcher_add_view(
nfc_magic->view_dispatcher, NfcMagicViewMenu, submenu_get_view(nfc_magic->submenu));
// Popup
nfc_magic->popup = popup_alloc();
view_dispatcher_add_view(
nfc_magic->view_dispatcher, NfcMagicViewPopup, popup_get_view(nfc_magic->popup));
// Loading
nfc_magic->loading = loading_alloc();
view_dispatcher_add_view(
nfc_magic->view_dispatcher, NfcMagicViewLoading, loading_get_view(nfc_magic->loading));
// Text Input
nfc_magic->text_input = text_input_alloc();
view_dispatcher_add_view(
nfc_magic->view_dispatcher,
NfcMagicViewTextInput,
text_input_get_view(nfc_magic->text_input));
// Custom Widget
nfc_magic->widget = widget_alloc();
view_dispatcher_add_view(
nfc_magic->view_dispatcher, NfcMagicViewWidget, widget_get_view(nfc_magic->widget));
return nfc_magic;
}
void nfc_magic_free(NfcMagic* nfc_magic) {
furi_assert(nfc_magic);
// Nfc device
nfc_device_free(nfc_magic->nfc_dev);
// Submenu
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
submenu_free(nfc_magic->submenu);
// Popup
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
popup_free(nfc_magic->popup);
// Loading
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading);
loading_free(nfc_magic->loading);
// TextInput
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput);
text_input_free(nfc_magic->text_input);
// Custom Widget
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
widget_free(nfc_magic->widget);
// Worker
nfc_magic_worker_stop(nfc_magic->worker);
nfc_magic_worker_free(nfc_magic->worker);
// View Dispatcher
view_dispatcher_free(nfc_magic->view_dispatcher);
// Scene Manager
scene_manager_free(nfc_magic->scene_manager);
// GUI
furi_record_close(RECORD_GUI);
nfc_magic->gui = NULL;
// Notifications
furi_record_close(RECORD_NOTIFICATION);
nfc_magic->notifications = NULL;
free(nfc_magic);
}
static const NotificationSequence nfc_magic_sequence_blink_start_blue = {
&message_blink_start_10,
&message_blink_set_color_blue,
&message_do_not_reset,
NULL,
};
static const NotificationSequence nfc_magic_sequence_blink_stop = {
&message_blink_stop,
NULL,
};
void nfc_magic_blink_start(NfcMagic* nfc_magic) {
notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_start_blue);
}
void nfc_magic_blink_stop(NfcMagic* nfc_magic) {
notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_stop);
}
int32_t nfc_magic_app(void* p) {
UNUSED(p);
NfcMagic* nfc_magic = nfc_magic_alloc();
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneStart);
view_dispatcher_run(nfc_magic->view_dispatcher);
nfc_magic_free(nfc_magic);
return 0;
}

View file

@ -0,0 +1,3 @@
#pragma once
typedef struct NfcMagic NfcMagic;

View file

@ -0,0 +1,77 @@
#pragma once
#include "nfc_magic.h"
#include "nfc_magic_worker.h"
#include "lib/magic/magic.h"
#include <furi.h>
#include <gui/gui.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <notification/notification_messages.h>
#include <gui/modules/submenu.h>
#include <gui/modules/popup.h>
#include <gui/modules/loading.h>
#include <gui/modules/text_input.h>
#include <gui/modules/widget.h>
#include <input/input.h>
#include "scenes/nfc_magic_scene.h"
#include <storage/storage.h>
#include <lib/toolbox/path.h>
#include <lib/nfc/nfc_device.h>
#include "nfc_magic_icons.h"
enum NfcMagicCustomEvent {
// Reserve first 100 events for button types and indexes, starting from 0
NfcMagicCustomEventReserved = 100,
NfcMagicCustomEventViewExit,
NfcMagicCustomEventWorkerExit,
NfcMagicCustomEventByteInputDone,
NfcMagicCustomEventTextInputDone,
};
struct NfcMagic {
NfcMagicWorker* worker;
ViewDispatcher* view_dispatcher;
Gui* gui;
NotificationApp* notifications;
SceneManager* scene_manager;
// NfcMagicDevice* dev;
NfcDevice* nfc_dev;
FuriString* text_box_store;
// Common Views
Submenu* submenu;
Popup* popup;
Loading* loading;
TextInput* text_input;
Widget* widget;
};
typedef enum {
NfcMagicViewMenu,
NfcMagicViewPopup,
NfcMagicViewLoading,
NfcMagicViewTextInput,
NfcMagicViewWidget,
} NfcMagicView;
NfcMagic* nfc_magic_alloc();
void nfc_magic_text_store_set(NfcMagic* nfc_magic, const char* text, ...);
void nfc_magic_text_store_clear(NfcMagic* nfc_magic);
void nfc_magic_blink_start(NfcMagic* nfc_magic);
void nfc_magic_blink_stop(NfcMagic* nfc_magic);
void nfc_magic_show_loading_popup(void* context, bool show);

View file

@ -0,0 +1,174 @@
#include "nfc_magic_worker_i.h"
#include "lib/magic/magic.h"
#define TAG "NfcMagicWorker"
static void
nfc_magic_worker_change_state(NfcMagicWorker* nfc_magic_worker, NfcMagicWorkerState state) {
furi_assert(nfc_magic_worker);
nfc_magic_worker->state = state;
}
NfcMagicWorker* nfc_magic_worker_alloc() {
NfcMagicWorker* nfc_magic_worker = malloc(sizeof(NfcMagicWorker));
// Worker thread attributes
nfc_magic_worker->thread = furi_thread_alloc();
furi_thread_set_name(nfc_magic_worker->thread, "NfcMagicWorker");
furi_thread_set_stack_size(nfc_magic_worker->thread, 8192);
furi_thread_set_callback(nfc_magic_worker->thread, nfc_magic_worker_task);
furi_thread_set_context(nfc_magic_worker->thread, nfc_magic_worker);
nfc_magic_worker->callback = NULL;
nfc_magic_worker->context = NULL;
nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady);
return nfc_magic_worker;
}
void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker) {
furi_assert(nfc_magic_worker);
furi_thread_free(nfc_magic_worker->thread);
free(nfc_magic_worker);
}
void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) {
furi_assert(nfc_magic_worker);
nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateStop);
furi_thread_join(nfc_magic_worker->thread);
}
void nfc_magic_worker_start(
NfcMagicWorker* nfc_magic_worker,
NfcMagicWorkerState state,
NfcDeviceData* dev_data,
NfcMagicWorkerCallback callback,
void* context) {
furi_assert(nfc_magic_worker);
furi_assert(dev_data);
nfc_magic_worker->callback = callback;
nfc_magic_worker->context = context;
nfc_magic_worker->dev_data = dev_data;
nfc_magic_worker_change_state(nfc_magic_worker, state);
furi_thread_start(nfc_magic_worker->thread);
}
int32_t nfc_magic_worker_task(void* context) {
NfcMagicWorker* nfc_magic_worker = context;
if(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
nfc_magic_worker_check(nfc_magic_worker);
} else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
nfc_magic_worker_write(nfc_magic_worker);
} else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
nfc_magic_worker_wipe(nfc_magic_worker);
}
nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady);
return 0;
}
void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
bool card_found_notified = false;
FuriHalNfcDevData nfc_data = {};
MfClassicData* src_data = &nfc_magic_worker->dev_data->mf_classic_data;
while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
if(furi_hal_nfc_detect(&nfc_data, 200)) {
if(!card_found_notified) {
nfc_magic_worker->callback(
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
card_found_notified = true;
}
furi_hal_nfc_sleep();
if(!magic_wupa()) {
FURI_LOG_E(TAG, "Not Magic card");
nfc_magic_worker->callback(
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
break;
}
if(!magic_data_access_cmd()) {
FURI_LOG_E(TAG, "Not Magic card");
nfc_magic_worker->callback(
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
break;
}
for(size_t i = 0; i < 64; i++) {
FURI_LOG_D(TAG, "Writing block %d", i);
if(!magic_write_blk(i, &src_data->block[i])) {
FURI_LOG_E(TAG, "Failed to write %d block", i);
nfc_magic_worker->callback(NfcMagicWorkerEventFail, nfc_magic_worker->context);
break;
}
}
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
break;
} else {
if(card_found_notified) {
nfc_magic_worker->callback(
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
card_found_notified = false;
}
}
furi_delay_ms(300);
}
magic_deactivate();
}
void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
bool card_found_notified = false;
while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
if(magic_wupa()) {
if(!card_found_notified) {
nfc_magic_worker->callback(
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
card_found_notified = true;
}
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
break;
} else {
if(card_found_notified) {
nfc_magic_worker->callback(
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
card_found_notified = false;
}
}
furi_delay_ms(300);
}
magic_deactivate();
}
void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
MfClassicBlock block;
memset(&block, 0, sizeof(MfClassicBlock));
block.value[0] = 0x01;
block.value[1] = 0x02;
block.value[2] = 0x03;
block.value[3] = 0x04;
block.value[4] = 0x04;
block.value[5] = 0x08;
block.value[6] = 0x04;
while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
magic_deactivate();
furi_delay_ms(300);
if(!magic_wupa()) continue;
if(!magic_wipe()) continue;
if(!magic_data_access_cmd()) continue;
if(!magic_write_blk(0, &block)) continue;
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
magic_deactivate();
break;
}
magic_deactivate();
}

View file

@ -0,0 +1,38 @@
#pragma once
#include <lib/nfc/nfc_device.h>
typedef struct NfcMagicWorker NfcMagicWorker;
typedef enum {
NfcMagicWorkerStateReady,
NfcMagicWorkerStateCheck,
NfcMagicWorkerStateWrite,
NfcMagicWorkerStateWipe,
NfcMagicWorkerStateStop,
} NfcMagicWorkerState;
typedef enum {
NfcMagicWorkerEventSuccess,
NfcMagicWorkerEventFail,
NfcMagicWorkerEventCardDetected,
NfcMagicWorkerEventNoCardDetected,
NfcMagicWorkerEventWrongCard,
} NfcMagicWorkerEvent;
typedef bool (*NfcMagicWorkerCallback)(NfcMagicWorkerEvent event, void* context);
NfcMagicWorker* nfc_magic_worker_alloc();
void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker);
void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker);
void nfc_magic_worker_start(
NfcMagicWorker* nfc_magic_worker,
NfcMagicWorkerState state,
NfcDeviceData* dev_data,
NfcMagicWorkerCallback callback,
void* context);

View file

@ -0,0 +1,24 @@
#pragma once
#include <furi.h>
#include "nfc_magic_worker.h"
struct NfcMagicWorker {
FuriThread* thread;
NfcDeviceData* dev_data;
NfcMagicWorkerCallback callback;
void* context;
NfcMagicWorkerState state;
};
int32_t nfc_magic_worker_task(void* context);
void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker);
void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker);
void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker);

View file

@ -0,0 +1,30 @@
#include "nfc_magic_scene.h"
// Generate scene on_enter handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
void (*const nfc_magic_on_enter_handlers[])(void*) = {
#include "nfc_magic_scene_config.h"
};
#undef ADD_SCENE
// Generate scene on_event handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
bool (*const nfc_magic_on_event_handlers[])(void* context, SceneManagerEvent event) = {
#include "nfc_magic_scene_config.h"
};
#undef ADD_SCENE
// Generate scene on_exit handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
void (*const nfc_magic_on_exit_handlers[])(void* context) = {
#include "nfc_magic_scene_config.h"
};
#undef ADD_SCENE
// Initialize scene handlers configuration structure
const SceneManagerHandlers nfc_magic_scene_handlers = {
.on_enter_handlers = nfc_magic_on_enter_handlers,
.on_event_handlers = nfc_magic_on_event_handlers,
.on_exit_handlers = nfc_magic_on_exit_handlers,
.scene_num = NfcMagicSceneNum,
};

View file

@ -0,0 +1,29 @@
#pragma once
#include <gui/scene_manager.h>
// Generate scene id and total number
#define ADD_SCENE(prefix, name, id) NfcMagicScene##id,
typedef enum {
#include "nfc_magic_scene_config.h"
NfcMagicSceneNum,
} NfcMagicScene;
#undef ADD_SCENE
extern const SceneManagerHandlers nfc_magic_scene_handlers;
// Generate scene on_enter handlers declaration
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
#include "nfc_magic_scene_config.h"
#undef ADD_SCENE
// Generate scene on_event handlers declaration
#define ADD_SCENE(prefix, name, id) \
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
#include "nfc_magic_scene_config.h"
#undef ADD_SCENE
// Generate scene on_exit handlers declaration
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
#include "nfc_magic_scene_config.h"
#undef ADD_SCENE

View file

@ -0,0 +1,87 @@
#include "../nfc_magic_i.h"
enum {
NfcMagicSceneCheckStateCardSearch,
NfcMagicSceneCheckStateCardFound,
};
bool nfc_magic_check_worker_callback(NfcMagicWorkerEvent event, void* context) {
furi_assert(context);
NfcMagic* nfc_magic = context;
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event);
return true;
}
static void nfc_magic_scene_check_setup_view(NfcMagic* nfc_magic) {
Popup* popup = nfc_magic->popup;
popup_reset(popup);
uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneCheck);
if(state == NfcMagicSceneCheckStateCardSearch) {
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
popup_set_text(
nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter);
} else {
popup_set_icon(popup, 12, 23, &I_Loading_24);
popup_set_header(popup, "Checking\nDon't move...", 52, 32, AlignLeft, AlignCenter);
}
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
}
void nfc_magic_scene_check_on_enter(void* context) {
NfcMagic* nfc_magic = context;
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch);
nfc_magic_scene_check_setup_view(nfc_magic);
// Setup and start worker
nfc_magic_worker_start(
nfc_magic->worker,
NfcMagicWorkerStateCheck,
&nfc_magic->nfc_dev->dev_data,
nfc_magic_check_worker_callback,
nfc_magic);
nfc_magic_blink_start(nfc_magic);
}
bool nfc_magic_scene_check_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcMagicWorkerEventSuccess) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneMagicInfo);
consumed = true;
} else if(event.event == NfcMagicWorkerEventWrongCard) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic);
consumed = true;
} else if(event.event == NfcMagicWorkerEventCardDetected) {
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardFound);
nfc_magic_scene_check_setup_view(nfc_magic);
consumed = true;
} else if(event.event == NfcMagicWorkerEventNoCardDetected) {
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch);
nfc_magic_scene_check_setup_view(nfc_magic);
consumed = true;
}
}
return consumed;
}
void nfc_magic_scene_check_on_exit(void* context) {
NfcMagic* nfc_magic = context;
nfc_magic_worker_stop(nfc_magic->worker);
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch);
// Clear view
popup_reset(nfc_magic->popup);
nfc_magic_blink_stop(nfc_magic);
}

View file

@ -0,0 +1,12 @@
ADD_SCENE(nfc_magic, start, Start)
ADD_SCENE(nfc_magic, file_select, FileSelect)
ADD_SCENE(nfc_magic, write_confirm, WriteConfirm)
ADD_SCENE(nfc_magic, wrong_card, WrongCard)
ADD_SCENE(nfc_magic, write, Write)
ADD_SCENE(nfc_magic, write_fail, WriteFail)
ADD_SCENE(nfc_magic, success, Success)
ADD_SCENE(nfc_magic, check, Check)
ADD_SCENE(nfc_magic, not_magic, NotMagic)
ADD_SCENE(nfc_magic, magic_info, MagicInfo)
ADD_SCENE(nfc_magic, wipe, Wipe)
ADD_SCENE(nfc_magic, wipe_fail, WipeFail)

View file

@ -0,0 +1,34 @@
#include "../nfc_magic_i.h"
static bool nfc_magic_scene_file_select_is_file_suitable(NfcDevice* nfc_dev) {
return (nfc_dev->format == NfcDeviceSaveFormatMifareClassic) &&
(nfc_dev->dev_data.mf_classic_data.type == MfClassicType1k) &&
(nfc_dev->dev_data.nfc_data.uid_len == 4);
}
void nfc_magic_scene_file_select_on_enter(void* context) {
NfcMagic* nfc_magic = context;
// Process file_select return
nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic);
if(nfc_file_select(nfc_magic->nfc_dev)) {
if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm);
} else {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard);
}
} else {
scene_manager_previous_scene(nfc_magic->scene_manager);
}
}
bool nfc_magic_scene_file_select_on_event(void* context, SceneManagerEvent event) {
UNUSED(context);
UNUSED(event);
return false;
}
void nfc_magic_scene_file_select_on_exit(void* context) {
NfcMagic* nfc_magic = context;
nfc_device_set_loading_callback(nfc_magic->nfc_dev, NULL, nfc_magic);
}

View file

@ -0,0 +1,45 @@
#include "../nfc_magic_i.h"
void nfc_magic_scene_magic_info_widget_callback(
GuiButtonType result,
InputType type,
void* context) {
NfcMagic* nfc_magic = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
}
}
void nfc_magic_scene_magic_info_on_enter(void* context) {
NfcMagic* nfc_magic = context;
Widget* widget = nfc_magic->widget;
notification_message(nfc_magic->notifications, &sequence_success);
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
widget_add_string_element(
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected");
widget_add_button_element(
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, nfc_magic);
// Setup and start worker
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
}
bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
}
}
return consumed;
}
void nfc_magic_scene_magic_info_on_exit(void* context) {
NfcMagic* nfc_magic = context;
widget_reset(nfc_magic->widget);
}

View file

@ -0,0 +1,44 @@
#include "../nfc_magic_i.h"
void nfc_magic_scene_not_magic_widget_callback(GuiButtonType result, InputType type, void* context) {
NfcMagic* nfc_magic = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
}
}
void nfc_magic_scene_not_magic_on_enter(void* context) {
NfcMagic* nfc_magic = context;
Widget* widget = nfc_magic->widget;
notification_message(nfc_magic->notifications, &sequence_error);
// widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
widget_add_string_element(
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card");
widget_add_string_multiline_element(
widget, 4, 17, AlignLeft, AlignTop, FontSecondary, "Not a magic\ncard");
widget_add_button_element(
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_not_magic_widget_callback, nfc_magic);
// Setup and start worker
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
}
bool nfc_magic_scene_not_magic_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
}
}
return consumed;
}
void nfc_magic_scene_not_magic_on_exit(void* context) {
NfcMagic* nfc_magic = context;
widget_reset(nfc_magic->widget);
}

View file

@ -0,0 +1,61 @@
#include "../nfc_magic_i.h"
enum SubmenuIndex {
SubmenuIndexCheck,
SubmenuIndexWriteGen1A,
SubmenuIndexWipe,
};
void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) {
NfcMagic* nfc_magic = context;
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index);
}
void nfc_magic_scene_start_on_enter(void* context) {
NfcMagic* nfc_magic = context;
Submenu* submenu = nfc_magic->submenu;
submenu_add_item(
submenu,
"Check Magic Tag",
SubmenuIndexCheck,
nfc_magic_scene_start_submenu_callback,
nfc_magic);
submenu_add_item(
submenu,
"Write Gen1A",
SubmenuIndexWriteGen1A,
nfc_magic_scene_start_submenu_callback,
nfc_magic);
submenu_add_item(
submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_start_submenu_callback, nfc_magic);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart));
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
}
bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexCheck) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck);
consumed = true;
} else if(event.event == SubmenuIndexWriteGen1A) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect);
consumed = true;
} else if(event.event == SubmenuIndexWipe) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe);
consumed = true;
}
scene_manager_set_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart, event.event);
}
return consumed;
}
void nfc_magic_scene_start_on_exit(void* context) {
NfcMagic* nfc_magic = context;
submenu_reset(nfc_magic->submenu);
}

View file

@ -0,0 +1,42 @@
#include "../nfc_magic_i.h"
void nfc_magic_scene_success_popup_callback(void* context) {
NfcMagic* nfc_magic = context;
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, NfcMagicCustomEventViewExit);
}
void nfc_magic_scene_success_on_enter(void* context) {
NfcMagic* nfc_magic = context;
notification_message(nfc_magic->notifications, &sequence_success);
Popup* popup = nfc_magic->popup;
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
popup_set_header(popup, "Success!", 10, 20, AlignLeft, AlignBottom);
popup_set_timeout(popup, 1500);
popup_set_context(popup, nfc_magic);
popup_set_callback(popup, nfc_magic_scene_success_popup_callback);
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
}
bool nfc_magic_scene_success_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcMagicCustomEventViewExit) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc_magic->scene_manager, NfcMagicSceneStart);
}
}
return consumed;
}
void nfc_magic_scene_success_on_exit(void* context) {
NfcMagic* nfc_magic = context;
// Clear view
popup_reset(nfc_magic->popup);
}

View file

@ -0,0 +1,90 @@
#include "../nfc_magic_i.h"
enum {
NfcMagicSceneWipeStateCardSearch,
NfcMagicSceneWipeStateCardFound,
};
bool nfc_magic_wipe_worker_callback(NfcMagicWorkerEvent event, void* context) {
furi_assert(context);
NfcMagic* nfc_magic = context;
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event);
return true;
}
static void nfc_magic_scene_wipe_setup_view(NfcMagic* nfc_magic) {
Popup* popup = nfc_magic->popup;
popup_reset(popup);
uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneWipe);
if(state == NfcMagicSceneWipeStateCardSearch) {
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
popup_set_text(
nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter);
} else {
popup_set_icon(popup, 12, 23, &I_Loading_24);
popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter);
}
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
}
void nfc_magic_scene_wipe_on_enter(void* context) {
NfcMagic* nfc_magic = context;
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch);
nfc_magic_scene_wipe_setup_view(nfc_magic);
// Setup and start worker
nfc_magic_worker_start(
nfc_magic->worker,
NfcMagicWorkerStateWipe,
&nfc_magic->nfc_dev->dev_data,
nfc_magic_wipe_worker_callback,
nfc_magic);
nfc_magic_blink_start(nfc_magic);
}
bool nfc_magic_scene_wipe_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcMagicWorkerEventSuccess) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess);
consumed = true;
} else if(event.event == NfcMagicWorkerEventFail) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipeFail);
consumed = true;
} else if(event.event == NfcMagicWorkerEventWrongCard) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic);
consumed = true;
} else if(event.event == NfcMagicWorkerEventCardDetected) {
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardFound);
nfc_magic_scene_wipe_setup_view(nfc_magic);
consumed = true;
} else if(event.event == NfcMagicWorkerEventNoCardDetected) {
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch);
nfc_magic_scene_wipe_setup_view(nfc_magic);
consumed = true;
}
}
return consumed;
}
void nfc_magic_scene_wipe_on_exit(void* context) {
NfcMagic* nfc_magic = context;
nfc_magic_worker_stop(nfc_magic->worker);
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch);
// Clear view
popup_reset(nfc_magic->popup);
nfc_magic_blink_stop(nfc_magic);
}

View file

@ -0,0 +1,41 @@
#include "../nfc_magic_i.h"
void nfc_magic_scene_wipe_fail_widget_callback(GuiButtonType result, InputType type, void* context) {
NfcMagic* nfc_magic = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
}
}
void nfc_magic_scene_wipe_fail_on_enter(void* context) {
NfcMagic* nfc_magic = context;
Widget* widget = nfc_magic->widget;
notification_message(nfc_magic->notifications, &sequence_error);
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
widget_add_string_element(widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Wipe failed");
widget_add_button_element(
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wipe_fail_widget_callback, nfc_magic);
// Setup and start worker
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
}
bool nfc_magic_scene_wipe_fail_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
}
}
return consumed;
}
void nfc_magic_scene_wipe_fail_on_exit(void* context) {
NfcMagic* nfc_magic = context;
widget_reset(nfc_magic->widget);
}

View file

@ -0,0 +1,90 @@
#include "../nfc_magic_i.h"
enum {
NfcMagicSceneWriteStateCardSearch,
NfcMagicSceneWriteStateCardFound,
};
bool nfc_magic_write_worker_callback(NfcMagicWorkerEvent event, void* context) {
furi_assert(context);
NfcMagic* nfc_magic = context;
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event);
return true;
}
static void nfc_magic_scene_write_setup_view(NfcMagic* nfc_magic) {
Popup* popup = nfc_magic->popup;
popup_reset(popup);
uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneWrite);
if(state == NfcMagicSceneWriteStateCardSearch) {
popup_set_text(
nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter);
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
} else {
popup_set_icon(popup, 12, 23, &I_Loading_24);
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
}
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
}
void nfc_magic_scene_write_on_enter(void* context) {
NfcMagic* nfc_magic = context;
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch);
nfc_magic_scene_write_setup_view(nfc_magic);
// Setup and start worker
nfc_magic_worker_start(
nfc_magic->worker,
NfcMagicWorkerStateWrite,
&nfc_magic->nfc_dev->dev_data,
nfc_magic_write_worker_callback,
nfc_magic);
nfc_magic_blink_start(nfc_magic);
}
bool nfc_magic_scene_write_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcMagicWorkerEventSuccess) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess);
consumed = true;
} else if(event.event == NfcMagicWorkerEventFail) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteFail);
consumed = true;
} else if(event.event == NfcMagicWorkerEventWrongCard) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic);
consumed = true;
} else if(event.event == NfcMagicWorkerEventCardDetected) {
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardFound);
nfc_magic_scene_write_setup_view(nfc_magic);
consumed = true;
} else if(event.event == NfcMagicWorkerEventNoCardDetected) {
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch);
nfc_magic_scene_write_setup_view(nfc_magic);
consumed = true;
}
}
return consumed;
}
void nfc_magic_scene_write_on_exit(void* context) {
NfcMagic* nfc_magic = context;
nfc_magic_worker_stop(nfc_magic->worker);
scene_manager_set_scene_state(
nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch);
// Clear view
popup_reset(nfc_magic->popup);
nfc_magic_blink_stop(nfc_magic);
}

View file

@ -0,0 +1,64 @@
#include "../nfc_magic_i.h"
void nfc_magic_scene_write_confirm_widget_callback(
GuiButtonType result,
InputType type,
void* context) {
NfcMagic* nfc_magic = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
}
}
void nfc_magic_scene_write_confirm_on_enter(void* context) {
NfcMagic* nfc_magic = context;
Widget* widget = nfc_magic->widget;
widget_add_string_element(widget, 3, 0, AlignLeft, AlignTop, FontPrimary, "Risky operation");
widget_add_text_box_element(
widget,
0,
13,
128,
54,
AlignLeft,
AlignTop,
"Writing to this card will change manufacturer block. On some cards it may not be rewritten",
false);
widget_add_button_element(
widget,
GuiButtonTypeCenter,
"Continue",
nfc_magic_scene_write_confirm_widget_callback,
nfc_magic);
widget_add_button_element(
widget,
GuiButtonTypeLeft,
"Back",
nfc_magic_scene_write_confirm_widget_callback,
nfc_magic);
// Setup and start worker
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
}
bool nfc_magic_scene_write_confirm_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
} else if(event.event == GuiButtonTypeCenter) {
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrite);
consumed = true;
}
}
return consumed;
}
void nfc_magic_scene_write_confirm_on_exit(void* context) {
NfcMagic* nfc_magic = context;
widget_reset(nfc_magic->widget);
}

View file

@ -0,0 +1,58 @@
#include "../nfc_magic_i.h"
void nfc_magic_scene_write_fail_widget_callback(
GuiButtonType result,
InputType type,
void* context) {
NfcMagic* nfc_magic = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
}
}
void nfc_magic_scene_write_fail_on_enter(void* context) {
NfcMagic* nfc_magic = context;
Widget* widget = nfc_magic->widget;
notification_message(nfc_magic->notifications, &sequence_error);
widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48);
widget_add_string_element(
widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Writing gone wrong!");
widget_add_string_multiline_element(
widget,
7,
17,
AlignLeft,
AlignTop,
FontSecondary,
"Not all sectors\nwere written\ncorrectly.");
widget_add_button_element(
widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_write_fail_widget_callback, nfc_magic);
// Setup and start worker
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
}
bool nfc_magic_scene_write_fail_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc_magic->scene_manager, NfcMagicSceneStart);
}
} else if(event.type == SceneManagerEventTypeBack) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc_magic->scene_manager, NfcMagicSceneStart);
}
return consumed;
}
void nfc_magic_scene_write_fail_on_exit(void* context) {
NfcMagic* nfc_magic = context;
widget_reset(nfc_magic->widget);
}

View file

@ -0,0 +1,53 @@
#include "../nfc_magic_i.h"
void nfc_magic_scene_wrong_card_widget_callback(
GuiButtonType result,
InputType type,
void* context) {
NfcMagic* nfc_magic = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
}
}
void nfc_magic_scene_wrong_card_on_enter(void* context) {
NfcMagic* nfc_magic = context;
Widget* widget = nfc_magic->widget;
notification_message(nfc_magic->notifications, &sequence_error);
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
widget_add_string_element(
widget, 1, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card");
widget_add_string_multiline_element(
widget,
1,
17,
AlignLeft,
AlignTop,
FontSecondary,
"Writing is supported\nonly for 4 bytes UID\nMifare CLassic 1k");
widget_add_button_element(
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic);
// Setup and start worker
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
}
bool nfc_magic_scene_wrong_card_on_event(void* context, SceneManagerEvent event) {
NfcMagic* nfc_magic = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
}
}
return consumed;
}
void nfc_magic_scene_wrong_card_on_exit(void* context) {
NfcMagic* nfc_magic = context;
widget_reset(nfc_magic->widget);
}

View file

@ -40,7 +40,7 @@ static bool pin_name_to_int(FuriString* pin_name, size_t* result) {
bool debug = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); bool debug = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug);
for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) { for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) {
if(!furi_string_cmp(pin_name, cli_command_gpio_pins[i].name)) { if(!furi_string_cmp(pin_name, cli_command_gpio_pins[i].name)) {
if(!cli_command_gpio_pins[i].debug || (cli_command_gpio_pins[i].debug && debug)) { if(!cli_command_gpio_pins[i].debug || debug) {
*result = i; *result = i;
found = true; found = true;
break; break;
@ -55,7 +55,7 @@ static void gpio_print_pins(void) {
printf("Wrong pin name. Available pins: "); printf("Wrong pin name. Available pins: ");
bool debug = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); bool debug = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug);
for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) { for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) {
if(!cli_command_gpio_pins[i].debug || (cli_command_gpio_pins[i].debug && debug)) { if(!cli_command_gpio_pins[i].debug || debug) {
printf("%s ", cli_command_gpio_pins[i].name); printf("%s ", cli_command_gpio_pins[i].name);
} }
} }

View file

@ -160,7 +160,7 @@ static bool desktop_view_locked_input(InputEvent* event, void* context) {
view_commit_model(locked_view->view, is_changed); view_commit_model(locked_view->view, is_changed);
if(view_state == DesktopViewLockedStateUnlocked) { if(view_state == DesktopViewLockedStateUnlocked) {
return view_state != DesktopViewLockedStateUnlocked; return false;
} else if(view_state == DesktopViewLockedStateLocked && pin_locked) { } else if(view_state == DesktopViewLockedStateLocked && pin_locked) {
locked_view->callback(DesktopLockedEventShowPinInput, locked_view->context); locked_view->callback(DesktopLockedEventShowPinInput, locked_view->context);
} else if( } else if(

View file

@ -304,8 +304,7 @@ void view_dispatcher_handle_custom_event(ViewDispatcher* view_dispatcher, uint32
} }
// If custom event is not consumed in View, call callback // If custom event is not consumed in View, call callback
if(!is_consumed && view_dispatcher->custom_event_callback) { if(!is_consumed && view_dispatcher->custom_event_callback) {
is_consumed = view_dispatcher->custom_event_callback(view_dispatcher->event_context, event);
view_dispatcher->custom_event_callback(view_dispatcher->event_context, event);
} }
} }

View file

@ -22,7 +22,7 @@ static const uint8_t reset_blink_mask = 1 << 6;
void notification_vibro_on(); void notification_vibro_on();
void notification_vibro_off(); void notification_vibro_off();
void notification_sound_on(float pwm, float freq); void notification_sound_on(float freq, float volume);
void notification_sound_off(); void notification_sound_off();
uint8_t notification_settings_get_display_brightness(NotificationApp* app, uint8_t value); uint8_t notification_settings_get_display_brightness(NotificationApp* app, uint8_t value);

View file

@ -138,6 +138,41 @@ static void rpc_system_storage_info_process(const PB_Main* request, void* contex
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
} }
static void rpc_system_storage_timestamp_process(const PB_Main* request, void* context) {
furi_assert(request);
furi_assert(context);
furi_assert(request->which_content == PB_Main_storage_timestamp_request_tag);
FURI_LOG_D(TAG, "Timestamp");
RpcStorageSystem* rpc_storage = context;
RpcSession* session = rpc_storage->session;
furi_assert(session);
rpc_system_storage_reset_state(rpc_storage, session, true);
PB_Main* response = malloc(sizeof(PB_Main));
response->command_id = request->command_id;
Storage* fs_api = furi_record_open(RECORD_STORAGE);
const char* path = request->content.storage_timestamp_request.path;
uint32_t timestamp = 0;
FS_Error error = storage_common_timestamp(fs_api, path, &timestamp);
response->command_status = rpc_system_storage_get_error(error);
response->which_content = PB_Main_empty_tag;
if(error == FSE_OK) {
response->which_content = PB_Main_storage_timestamp_response_tag;
response->content.storage_timestamp_response.timestamp = timestamp;
}
rpc_send_and_release(session, response);
free(response);
furi_record_close(RECORD_STORAGE);
}
static void rpc_system_storage_stat_process(const PB_Main* request, void* context) { static void rpc_system_storage_stat_process(const PB_Main* request, void* context) {
furi_assert(request); furi_assert(request);
furi_assert(context); furi_assert(context);
@ -672,6 +707,9 @@ void* rpc_system_storage_alloc(RpcSession* session) {
rpc_handler.message_handler = rpc_system_storage_info_process; rpc_handler.message_handler = rpc_system_storage_info_process;
rpc_add_handler(session, PB_Main_storage_info_request_tag, &rpc_handler); rpc_add_handler(session, PB_Main_storage_info_request_tag, &rpc_handler);
rpc_handler.message_handler = rpc_system_storage_timestamp_process;
rpc_add_handler(session, PB_Main_storage_timestamp_request_tag, &rpc_handler);
rpc_handler.message_handler = rpc_system_storage_stat_process; rpc_handler.message_handler = rpc_system_storage_stat_process;
rpc_add_handler(session, PB_Main_storage_stat_request_tag, &rpc_handler); rpc_add_handler(session, PB_Main_storage_stat_request_tag, &rpc_handler);

View file

@ -39,6 +39,7 @@ Storage* storage_app_alloc() {
for(uint8_t i = 0; i < STORAGE_COUNT; i++) { for(uint8_t i = 0; i < STORAGE_COUNT; i++) {
storage_data_init(&app->storage[i]); storage_data_init(&app->storage[i]);
storage_data_timestamp(&app->storage[i]);
} }
#ifndef FURI_RAM_EXEC #ifndef FURI_RAM_EXEC

View file

@ -177,6 +177,16 @@ bool storage_dir_rewind(File* file);
/******************* Common Functions *******************/ /******************* Common Functions *******************/
/** Retrieves unix timestamp of last access
*
* @param storage The storage instance
* @param path path to file/directory
* @param timestamp the timestamp pointer
*
* @return FS_Error operation result
*/
FS_Error storage_common_timestamp(Storage* storage, const char* path, uint32_t* timestamp);
/** Retrieves information about a file/directory /** Retrieves information about a file/directory
* @param app pointer to the api * @param app pointer to the api
* @param path path to file/directory * @param path path to file/directory

View file

@ -32,6 +32,7 @@ static void storage_cli_print_usage() {
printf("\tmkdir\t - creates a new directory\r\n"); printf("\tmkdir\t - creates a new directory\r\n");
printf("\tmd5\t - md5 hash of the file\r\n"); printf("\tmd5\t - md5 hash of the file\r\n");
printf("\tstat\t - info about file or dir\r\n"); printf("\tstat\t - info about file or dir\r\n");
printf("\ttimestamp\t - last modification timestamp\r\n");
}; };
static void storage_cli_print_error(FS_Error error) { static void storage_cli_print_error(FS_Error error) {
@ -386,6 +387,22 @@ static void storage_cli_stat(Cli* cli, FuriString* path) {
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
} }
static void storage_cli_timestamp(Cli* cli, FuriString* path) {
UNUSED(cli);
Storage* api = furi_record_open(RECORD_STORAGE);
uint32_t timestamp = 0;
FS_Error error = storage_common_timestamp(api, furi_string_get_cstr(path), &timestamp);
if(error != FSE_OK) {
printf("Invalid arguments\r\n");
} else {
printf("Timestamp %lu\r\n", timestamp);
}
furi_record_close(RECORD_STORAGE);
}
static void storage_cli_copy(Cli* cli, FuriString* old_path, FuriString* args) { static void storage_cli_copy(Cli* cli, FuriString* old_path, FuriString* args) {
UNUSED(cli); UNUSED(cli);
Storage* api = furi_record_open(RECORD_STORAGE); Storage* api = furi_record_open(RECORD_STORAGE);
@ -578,6 +595,11 @@ void storage_cli(Cli* cli, FuriString* args, void* context) {
break; break;
} }
if(furi_string_cmp_str(cmd, "timestamp") == 0) {
storage_cli_timestamp(cli, path);
break;
}
storage_cli_print_usage(); storage_cli_print_usage();
} while(false); } while(false);

View file

@ -354,6 +354,16 @@ bool storage_dir_rewind(File* file) {
/****************** COMMON ******************/ /****************** COMMON ******************/
FS_Error storage_common_timestamp(Storage* storage, const char* path, uint32_t* timestamp) {
S_API_PROLOGUE;
SAData data = {.ctimestamp = {.path = path, .timestamp = timestamp}};
S_API_MESSAGE(StorageCommandCommonTimestamp);
S_API_EPILOGUE;
return S_RETURN_ERROR;
}
FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* fileinfo) { FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* fileinfo) {
S_API_PROLOGUE; S_API_PROLOGUE;

View file

@ -82,6 +82,14 @@ const char* storage_data_status_text(StorageData* storage) {
return result; return result;
} }
void storage_data_timestamp(StorageData* storage) {
storage->timestamp = furi_hal_rtc_get_timestamp();
}
uint32_t storage_data_get_timestamp(StorageData* storage) {
return storage->timestamp;
}
/****************** storage glue ******************/ /****************** storage glue ******************/
bool storage_has_file(const File* file, StorageData* storage_data) { bool storage_has_file(const File* file, StorageData* storage_data) {

View file

@ -42,6 +42,8 @@ bool storage_data_lock(StorageData* storage);
bool storage_data_unlock(StorageData* storage); bool storage_data_unlock(StorageData* storage);
StorageStatus storage_data_status(StorageData* storage); StorageStatus storage_data_status(StorageData* storage);
const char* storage_data_status_text(StorageData* storage); const char* storage_data_status_text(StorageData* storage);
void storage_data_timestamp(StorageData* storage);
uint32_t storage_data_get_timestamp(StorageData* storage);
LIST_DEF( LIST_DEF(
StorageFileList, StorageFileList,
@ -58,6 +60,7 @@ struct StorageData {
FuriMutex* mutex; FuriMutex* mutex;
StorageStatus status; StorageStatus status;
StorageFileList_t files; StorageFileList_t files;
uint32_t timestamp;
}; };
bool storage_has_file(const File* file, StorageData* storage_data); bool storage_has_file(const File* file, StorageData* storage_data);

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <furi.h> #include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h> #include <gui/gui.h>
#include "storage_glue.h" #include "storage_glue.h"
#include "storage_sd_api.h" #include "storage_sd_api.h"

View file

@ -42,6 +42,11 @@ typedef struct {
uint16_t name_length; uint16_t name_length;
} SADataDRead; } SADataDRead;
typedef struct {
const char* path;
uint32_t* timestamp;
} SADataCTimestamp;
typedef struct { typedef struct {
const char* path; const char* path;
FileInfo* fileinfo; FileInfo* fileinfo;
@ -78,6 +83,7 @@ typedef union {
SADataDOpen dopen; SADataDOpen dopen;
SADataDRead dread; SADataDRead dread;
SADataCTimestamp ctimestamp;
SADataCStat cstat; SADataCStat cstat;
SADataCFSInfo cfsinfo; SADataCFSInfo cfsinfo;
@ -112,6 +118,7 @@ typedef enum {
StorageCommandDirClose, StorageCommandDirClose,
StorageCommandDirRead, StorageCommandDirRead,
StorageCommandDirRewind, StorageCommandDirRewind,
StorageCommandCommonTimestamp,
StorageCommandCommonStat, StorageCommandCommonStat,
StorageCommandCommonRemove, StorageCommandCommonRemove,
StorageCommandCommonMkDir, StorageCommandCommonMkDir,

View file

@ -114,6 +114,9 @@ bool storage_process_file_open(
if(storage_path_already_open(real_path, storage->files)) { if(storage_path_already_open(real_path, storage->files)) {
file->error_id = FSE_ALREADY_OPEN; file->error_id = FSE_ALREADY_OPEN;
} else { } else {
if(access_mode & FSAM_WRITE) {
storage_data_timestamp(storage);
}
storage_push_storage_file(file, real_path, type, storage); storage_push_storage_file(file, real_path, type, storage);
FS_CALL(storage, file.open(storage, file, remove_vfs(path), access_mode, open_mode)); FS_CALL(storage, file.open(storage, file, remove_vfs(path), access_mode, open_mode));
} }
@ -166,6 +169,7 @@ static uint16_t storage_process_file_write(
if(storage == NULL) { if(storage == NULL) {
file->error_id = FSE_INVALID_PARAMETER; file->error_id = FSE_INVALID_PARAMETER;
} else { } else {
storage_data_timestamp(storage);
FS_CALL(storage, file.write(storage, file, buff, bytes_to_write)); FS_CALL(storage, file.write(storage, file, buff, bytes_to_write));
} }
@ -209,6 +213,7 @@ static bool storage_process_file_truncate(Storage* app, File* file) {
if(storage == NULL) { if(storage == NULL) {
file->error_id = FSE_INVALID_PARAMETER; file->error_id = FSE_INVALID_PARAMETER;
} else { } else {
storage_data_timestamp(storage);
FS_CALL(storage, file.truncate(storage, file)); FS_CALL(storage, file.truncate(storage, file));
} }
@ -222,6 +227,7 @@ static bool storage_process_file_sync(Storage* app, File* file) {
if(storage == NULL) { if(storage == NULL) {
file->error_id = FSE_INVALID_PARAMETER; file->error_id = FSE_INVALID_PARAMETER;
} else { } else {
storage_data_timestamp(storage);
FS_CALL(storage, file.sync(storage, file)); FS_CALL(storage, file.sync(storage, file));
} }
@ -332,6 +338,21 @@ bool storage_process_dir_rewind(Storage* app, File* file) {
/******************* Common FS Functions *******************/ /******************* Common FS Functions *******************/
static FS_Error
storage_process_common_timestamp(Storage* app, const char* path, uint32_t* timestamp) {
FS_Error ret = FSE_OK;
StorageType type = storage_get_type_by_path(app, path);
if(storage_type_is_not_valid(type)) {
ret = FSE_INVALID_NAME;
} else {
StorageData* storage = storage_get_storage_by_type(app, type);
*timestamp = storage_data_get_timestamp(storage);
}
return ret;
}
static FS_Error storage_process_common_stat(Storage* app, const char* path, FileInfo* fileinfo) { static FS_Error storage_process_common_stat(Storage* app, const char* path, FileInfo* fileinfo) {
FS_Error ret = FSE_OK; FS_Error ret = FSE_OK;
StorageType type = storage_get_type_by_path(app, path); StorageType type = storage_get_type_by_path(app, path);
@ -366,6 +387,7 @@ static FS_Error storage_process_common_remove(Storage* app, const char* path) {
break; break;
} }
storage_data_timestamp(storage);
FS_CALL(storage, common.remove(storage, remove_vfs(path))); FS_CALL(storage, common.remove(storage, remove_vfs(path)));
} while(false); } while(false);
@ -382,6 +404,7 @@ static FS_Error storage_process_common_mkdir(Storage* app, const char* path) {
ret = FSE_INVALID_NAME; ret = FSE_INVALID_NAME;
} else { } else {
StorageData* storage = storage_get_storage_by_type(app, type); StorageData* storage = storage_get_storage_by_type(app, type);
storage_data_timestamp(storage);
FS_CALL(storage, common.mkdir(storage, remove_vfs(path))); FS_CALL(storage, common.mkdir(storage, remove_vfs(path)));
} }
@ -417,6 +440,7 @@ static FS_Error storage_process_sd_format(Storage* app) {
ret = FSE_NOT_READY; ret = FSE_NOT_READY;
} else { } else {
ret = sd_format_card(&app->storage[ST_EXT]); ret = sd_format_card(&app->storage[ST_EXT]);
storage_data_timestamp(&app->storage[ST_EXT]);
} }
return ret; return ret;
@ -429,6 +453,7 @@ static FS_Error storage_process_sd_unmount(Storage* app) {
ret = FSE_NOT_READY; ret = FSE_NOT_READY;
} else { } else {
sd_unmount_card(&app->storage[ST_EXT]); sd_unmount_card(&app->storage[ST_EXT]);
storage_data_timestamp(&app->storage[ST_EXT]);
} }
return ret; return ret;
@ -541,6 +566,10 @@ void storage_process_message_internal(Storage* app, StorageMessage* message) {
message->return_data->bool_value = message->return_data->bool_value =
storage_process_dir_rewind(app, message->data->file.file); storage_process_dir_rewind(app, message->data->file.file);
break; break;
case StorageCommandCommonTimestamp:
message->return_data->error_value = storage_process_common_timestamp(
app, message->data->ctimestamp.path, message->data->ctimestamp.timestamp);
break;
case StorageCommandCommonStat: case StorageCommandCommonStat:
message->return_data->error_value = storage_process_common_stat( message->return_data->error_value = storage_process_common_stat(
app, message->data->cstat.path, message->data->cstat.fileinfo); app, message->data->cstat.path, message->data->cstat.fileinfo);

View file

@ -90,6 +90,7 @@ static bool sd_mount_card(StorageData* storage, bool notify) {
} }
} }
storage_data_timestamp(storage);
storage_data_unlock(storage); storage_data_unlock(storage);
return result; return result;

View file

@ -3,6 +3,9 @@
#include <gui/elements.h> #include <gui/elements.h>
#include <assets_icons.h> #include <assets_icons.h>
#define LOW_CHARGE_THRESHOLD 10
#define HIGH_DRAIN_CURRENT_THRESHOLD 100
struct BatteryInfo { struct BatteryInfo {
View* view; View* view;
}; };
@ -28,9 +31,9 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28); canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28);
if(charge_current > 0) { if(charge_current > 0) {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14); canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14);
} else if(drain_current > 100) { } else if(drain_current > HIGH_DRAIN_CURRENT_THRESHOLD) {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14); canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14);
} else if(data->charge < 10) { } else if(data->charge < LOW_CHARGE_THRESHOLD) {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14); canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14);
} else { } else {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNormal_29x14); canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNormal_29x14);
@ -51,11 +54,19 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
(uint32_t)(data->vbus_voltage * 10) % 10, (uint32_t)(data->vbus_voltage * 10) % 10,
charge_current); charge_current);
} else if(drain_current > 0) { } else if(drain_current > 0) {
snprintf(emote, sizeof(emote), "%s", drain_current > 100 ? "Oh no!" : "Om-nom-nom!"); snprintf(
emote,
sizeof(emote),
"%s",
drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!");
snprintf(header, sizeof(header), "%s", "Consumption is"); snprintf(header, sizeof(header), "%s", "Consumption is");
snprintf( snprintf(
value, sizeof(value), "%ld %s", drain_current, drain_current > 100 ? "mA!" : "mA"); value,
} else if(charge_current != 0 || drain_current != 0) { sizeof(value),
"%ld %s",
drain_current,
drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA");
} else if(drain_current != 0) {
snprintf(header, 20, "..."); snprintf(header, 20, "...");
} else { } else {
snprintf(header, sizeof(header), "Charged!"); snprintf(header, sizeof(header), "Charged!");

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -0,0 +1,14 @@
Filetype: Flipper Animation
Version: 1
Width: 128
Height: 64
Passive frames: 23
Active frames: 18
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
Active cycles: 1
Frame rate: 2
Duration: 3600
Active cooldown: 7
Bubble slots: 0

View file

@ -85,12 +85,19 @@ Min level: 1
Max level: 3 Max level: 3
Weight: 3 Weight: 3
Name: L1_Mods_128x64
Min butthurt: 0
Max butthurt: 9
Min level: 1
Max level: 3
Weight: 5
Name: L1_Painting_128x64 Name: L1_Painting_128x64
Min butthurt: 0 Min butthurt: 0
Max butthurt: 7 Max butthurt: 7
Min level: 1 Min level: 1
Max level: 3 Max level: 3
Weight: 6 Weight: 4
Name: L3_Hijack_radio_128x64 Name: L3_Hijack_radio_128x64
Min butthurt: 0 Min butthurt: 0

@ -1 +1 @@
Subproject commit 6727eaf287db077dcd28719cd764f5804712223e Subproject commit e5af96e08fea8351898f7b8c6d1e34ce5fd6cdef

View file

@ -152,6 +152,7 @@ Header,+,lib/libusb_stm32/inc/usbd_core.h,,
Header,+,lib/mbedtls/include/mbedtls/des.h,, Header,+,lib/mbedtls/include/mbedtls/des.h,,
Header,+,lib/mbedtls/include/mbedtls/sha1.h,, Header,+,lib/mbedtls/include/mbedtls/sha1.h,,
Header,+,lib/micro-ecc/uECC.h,, Header,+,lib/micro-ecc/uECC.h,,
Header,+,lib/nfc/nfc_device.h,,
Header,+,lib/one_wire/ibutton/ibutton_worker.h,, Header,+,lib/one_wire/ibutton/ibutton_worker.h,,
Header,+,lib/one_wire/maxim_crc.h,, Header,+,lib/one_wire/maxim_crc.h,,
Header,+,lib/one_wire/one_wire_device.h,, Header,+,lib/one_wire/one_wire_device.h,,
@ -688,6 +689,14 @@ Function,-,coshl,long double,long double
Function,-,cosl,long double,long double Function,-,cosl,long double,long double
Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t" Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t"
Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*" Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*"
Function,-,crypto1_bit,uint8_t,"Crypto1*, uint8_t, int"
Function,-,crypto1_byte,uint8_t,"Crypto1*, uint8_t, int"
Function,-,crypto1_decrypt,void,"Crypto1*, uint8_t*, uint16_t, uint8_t*"
Function,-,crypto1_encrypt,void,"Crypto1*, uint8_t*, uint8_t*, uint16_t, uint8_t*, uint8_t*"
Function,-,crypto1_filter,uint32_t,uint32_t
Function,-,crypto1_init,void,"Crypto1*, uint64_t"
Function,-,crypto1_reset,void,Crypto1*
Function,-,crypto1_word,uint32_t,"Crypto1*, uint32_t, int"
Function,-,ctermid,char*,char* Function,-,ctermid,char*,char*
Function,-,ctime,char*,const time_t* Function,-,ctime,char*,const time_t*
Function,-,ctime_r,char*,"const time_t*, char*" Function,-,ctime_r,char*,"const time_t*, char*"
@ -770,6 +779,8 @@ Function,+,elements_text_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t,
Function,+,empty_screen_alloc,EmptyScreen*, Function,+,empty_screen_alloc,EmptyScreen*,
Function,+,empty_screen_free,void,EmptyScreen* Function,+,empty_screen_free,void,EmptyScreen*
Function,+,empty_screen_get_view,View*,EmptyScreen* Function,+,empty_screen_get_view,View*,EmptyScreen*
Function,-,emv_card_emulation,_Bool,FuriHalNfcTxRxContext*
Function,-,emv_read_bank_card,_Bool,"FuriHalNfcTxRxContext*, EmvApplication*"
Function,-,erand48,double,unsigned short[3] Function,-,erand48,double,unsigned short[3]
Function,-,erf,double,double Function,-,erf,double,double
Function,-,erfc,double,double Function,-,erfc,double,double
@ -1181,6 +1192,7 @@ Function,+,furi_hal_nfc_ll_set_fdt_poll,void,uint32_t
Function,+,furi_hal_nfc_ll_set_guard_time,void,uint32_t Function,+,furi_hal_nfc_ll_set_guard_time,void,uint32_t
Function,+,furi_hal_nfc_ll_set_mode,FuriHalNfcReturn,"FuriHalNfcMode, FuriHalNfcBitrate, FuriHalNfcBitrate" Function,+,furi_hal_nfc_ll_set_mode,FuriHalNfcReturn,"FuriHalNfcMode, FuriHalNfcBitrate, FuriHalNfcBitrate"
Function,+,furi_hal_nfc_ll_txrx,FuriHalNfcReturn,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" Function,+,furi_hal_nfc_ll_txrx,FuriHalNfcReturn,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t"
Function,+,furi_hal_nfc_ll_txrx_bits,FuriHalNfcReturn,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t"
Function,+,furi_hal_nfc_ll_txrx_off,void, Function,+,furi_hal_nfc_ll_txrx_off,void,
Function,+,furi_hal_nfc_ll_txrx_on,void, Function,+,furi_hal_nfc_ll_txrx_on,void,
Function,+,furi_hal_nfc_sleep,void, Function,+,furi_hal_nfc_sleep,void,
@ -1266,6 +1278,7 @@ Function,+,furi_hal_rtc_get_fault_data,uint32_t,
Function,+,furi_hal_rtc_get_log_level,uint8_t, Function,+,furi_hal_rtc_get_log_level,uint8_t,
Function,+,furi_hal_rtc_get_pin_fails,uint32_t, Function,+,furi_hal_rtc_get_pin_fails,uint32_t,
Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister
Function,+,furi_hal_rtc_get_timestamp,uint32_t,
Function,-,furi_hal_rtc_init,void, Function,-,furi_hal_rtc_init,void,
Function,-,furi_hal_rtc_init_early,void, Function,-,furi_hal_rtc_init_early,void,
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
@ -1825,6 +1838,100 @@ Function,+,menu_free,void,Menu*
Function,+,menu_get_view,View*,Menu* Function,+,menu_get_view,View*,Menu*
Function,+,menu_reset,void,Menu* Function,+,menu_reset,void,Menu*
Function,+,menu_set_selected_item,void,"Menu*, uint32_t" Function,+,menu_set_selected_item,void,"Menu*, uint32_t"
Function,-,mf_classic_auth_attempt,_Bool,"FuriHalNfcTxRxContext*, MfClassicAuthContext*, uint64_t"
Function,-,mf_classic_auth_init_context,void,"MfClassicAuthContext*, uint8_t"
Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey"
Function,-,mf_classic_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
Function,-,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*"
Function,-,mf_classic_dict_add_key_str,_Bool,"MfClassicDict*, FuriString*"
Function,-,mf_classic_dict_alloc,MfClassicDict*,MfClassicDictType
Function,-,mf_classic_dict_check_presence,_Bool,MfClassicDictType
Function,-,mf_classic_dict_delete_index,_Bool,"MfClassicDict*, uint32_t"
Function,-,mf_classic_dict_find_index,_Bool,"MfClassicDict*, uint8_t*, uint32_t*"
Function,-,mf_classic_dict_find_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t*"
Function,-,mf_classic_dict_free,void,MfClassicDict*
Function,-,mf_classic_dict_get_key_at_index,_Bool,"MfClassicDict*, uint64_t*, uint32_t"
Function,-,mf_classic_dict_get_key_at_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t"
Function,-,mf_classic_dict_get_next_key,_Bool,"MfClassicDict*, uint64_t*"
Function,-,mf_classic_dict_get_next_key_str,_Bool,"MfClassicDict*, FuriString*"
Function,-,mf_classic_dict_get_total_keys,uint32_t,MfClassicDict*
Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*"
Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*"
Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict*
Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*"
Function,-,mf_classic_get_classic_type,MfClassicType,"int8_t, uint8_t, uint8_t"
Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*"
Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t
Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t
Function,-,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t"
Function,-,mf_classic_get_total_sectors_num,uint8_t,MfClassicType
Function,-,mf_classic_get_type_str,const char*,MfClassicType
Function,-,mf_classic_is_allowed_access_data_block,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction"
Function,-,mf_classic_is_allowed_access_sector_trailer,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction"
Function,-,mf_classic_is_block_read,_Bool,"MfClassicData*, uint8_t"
Function,-,mf_classic_is_card_read,_Bool,MfClassicData*
Function,-,mf_classic_is_key_found,_Bool,"MfClassicData*, uint8_t, MfClassicKey"
Function,-,mf_classic_is_sector_data_read,_Bool,"MfClassicData*, uint8_t"
Function,-,mf_classic_is_sector_read,_Bool,"MfClassicData*, uint8_t"
Function,-,mf_classic_is_sector_trailer,_Bool,uint8_t
Function,-,mf_classic_read_card,uint8_t,"FuriHalNfcTxRxContext*, MfClassicReader*, MfClassicData*"
Function,-,mf_classic_read_sector,void,"FuriHalNfcTxRxContext*, MfClassicData*, uint8_t"
Function,-,mf_classic_reader_add_sector,void,"MfClassicReader*, uint8_t, uint64_t, uint64_t"
Function,-,mf_classic_set_block_read,void,"MfClassicData*, uint8_t, MfClassicBlock*"
Function,-,mf_classic_set_key_found,void,"MfClassicData*, uint8_t, MfClassicKey, uint64_t"
Function,-,mf_classic_set_key_not_found,void,"MfClassicData*, uint8_t, MfClassicKey"
Function,-,mf_classic_set_sector_data_not_read,void,MfClassicData*
Function,-,mf_classic_update_card,uint8_t,"FuriHalNfcTxRxContext*, MfClassicData*"
Function,-,mf_classic_write_block,_Bool,"FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t"
Function,-,mf_classic_write_sector,_Bool,"FuriHalNfcTxRxContext*, MfClassicData*, MfClassicData*, uint8_t"
Function,-,mf_df_cat_application,void,"MifareDesfireApplication*, FuriString*"
Function,-,mf_df_cat_application_info,void,"MifareDesfireApplication*, FuriString*"
Function,-,mf_df_cat_card_info,void,"MifareDesfireData*, FuriString*"
Function,-,mf_df_cat_data,void,"MifareDesfireData*, FuriString*"
Function,-,mf_df_cat_file,void,"MifareDesfireFile*, FuriString*"
Function,-,mf_df_cat_free_mem,void,"MifareDesfireFreeMemory*, FuriString*"
Function,-,mf_df_cat_key_settings,void,"MifareDesfireKeySettings*, FuriString*"
Function,-,mf_df_cat_version,void,"MifareDesfireVersion*, FuriString*"
Function,-,mf_df_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
Function,-,mf_df_clear,void,MifareDesfireData*
Function,-,mf_df_parse_get_application_ids_response,_Bool,"uint8_t*, uint16_t, MifareDesfireApplication**"
Function,-,mf_df_parse_get_file_ids_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile**"
Function,-,mf_df_parse_get_file_settings_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile*"
Function,-,mf_df_parse_get_free_memory_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFreeMemory*"
Function,-,mf_df_parse_get_key_settings_response,_Bool,"uint8_t*, uint16_t, MifareDesfireKeySettings*"
Function,-,mf_df_parse_get_key_version_response,_Bool,"uint8_t*, uint16_t, MifareDesfireKeyVersion*"
Function,-,mf_df_parse_get_version_response,_Bool,"uint8_t*, uint16_t, MifareDesfireVersion*"
Function,-,mf_df_parse_read_data_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile*"
Function,-,mf_df_parse_select_application_response,_Bool,"uint8_t*, uint16_t"
Function,-,mf_df_prepare_get_application_ids,uint16_t,uint8_t*
Function,-,mf_df_prepare_get_file_ids,uint16_t,uint8_t*
Function,-,mf_df_prepare_get_file_settings,uint16_t,"uint8_t*, uint8_t"
Function,-,mf_df_prepare_get_free_memory,uint16_t,uint8_t*
Function,-,mf_df_prepare_get_key_settings,uint16_t,uint8_t*
Function,-,mf_df_prepare_get_key_version,uint16_t,"uint8_t*, uint8_t"
Function,-,mf_df_prepare_get_value,uint16_t,"uint8_t*, uint8_t"
Function,-,mf_df_prepare_get_version,uint16_t,uint8_t*
Function,-,mf_df_prepare_read_data,uint16_t,"uint8_t*, uint8_t, uint32_t, uint32_t"
Function,-,mf_df_prepare_read_records,uint16_t,"uint8_t*, uint8_t, uint32_t, uint32_t"
Function,-,mf_df_prepare_select_application,uint16_t,"uint8_t*, uint8_t[3]"
Function,-,mf_df_read_card,_Bool,"FuriHalNfcTxRxContext*, MifareDesfireData*"
Function,-,mf_ul_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
Function,-,mf_ul_prepare_emulation,void,"MfUltralightEmulator*, MfUltralightData*"
Function,-,mf_ul_prepare_emulation_response,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*"
Function,-,mf_ul_pwdgen_amiibo,uint32_t,FuriHalNfcDevData*
Function,-,mf_ul_pwdgen_xiaomi,uint32_t,FuriHalNfcDevData*
Function,-,mf_ul_read_card,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*"
Function,-,mf_ul_reset,void,MfUltralightData*
Function,-,mf_ul_reset_emulation,void,"MfUltralightEmulator*, _Bool"
Function,-,mf_ultralight_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint32_t, uint16_t*"
Function,-,mf_ultralight_fast_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*"
Function,-,mf_ultralight_get_config_pages,MfUltralightConfigPages*,MfUltralightData*
Function,-,mf_ultralight_read_counters,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*"
Function,-,mf_ultralight_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*"
Function,-,mf_ultralight_read_pages_direct,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint8_t*"
Function,-,mf_ultralight_read_signature,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*"
Function,-,mf_ultralight_read_tearing_flags,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*"
Function,-,mf_ultralight_read_version,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*"
Function,-,mkdtemp,char*,char* Function,-,mkdtemp,char*,char*
Function,-,mkostemp,int,"char*, int" Function,-,mkostemp,int,"char*, int"
Function,-,mkostemps,int,"char*, int, int" Function,-,mkostemps,int,"char*, int, int"
@ -1848,6 +1955,19 @@ Function,-,nextafterl,long double,"long double, long double"
Function,-,nexttoward,double,"double, long double" Function,-,nexttoward,double,"double, long double"
Function,-,nexttowardf,float,"float, long double" Function,-,nexttowardf,float,"float, long double"
Function,-,nexttowardl,long double,"long double, long double" Function,-,nexttowardl,long double,"long double, long double"
Function,+,nfc_device_alloc,NfcDevice*,
Function,+,nfc_device_clear,void,NfcDevice*
Function,+,nfc_device_data_clear,void,NfcDeviceData*
Function,+,nfc_device_delete,_Bool,"NfcDevice*, _Bool"
Function,+,nfc_device_free,void,NfcDevice*
Function,+,nfc_device_load,_Bool,"NfcDevice*, const char*, _Bool"
Function,+,nfc_device_load_key_cache,_Bool,NfcDevice*
Function,+,nfc_device_restore,_Bool,"NfcDevice*, _Bool"
Function,+,nfc_device_save,_Bool,"NfcDevice*, const char*"
Function,+,nfc_device_save_shadow,_Bool,"NfcDevice*, const char*"
Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*"
Function,+,nfc_device_set_name,void,"NfcDevice*, const char*"
Function,+,nfc_file_select,_Bool,NfcDevice*
Function,-,nfca_append_crc16,void,"uint8_t*, uint16_t" Function,-,nfca_append_crc16,void,"uint8_t*, uint16_t"
Function,-,nfca_emulation_handler,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*" Function,-,nfca_emulation_handler,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*"
Function,-,nfca_get_crc16,uint16_t,"uint8_t*, uint16_t" Function,-,nfca_get_crc16,uint16_t,"uint8_t*, uint16_t"
@ -1962,6 +2082,7 @@ Function,+,power_reboot,void,PowerBootMode
Function,+,powf,float,"float, float" Function,+,powf,float,"float, float"
Function,-,powl,long double,"long double, long double" Function,-,powl,long double,"long double, long double"
Function,-,printf,int,"const char*, ..." Function,-,printf,int,"const char*, ..."
Function,-,prng_successor,uint32_t,"uint32_t, uint32_t"
Function,+,protocol_dict_alloc,ProtocolDict*,"const ProtocolBase**, size_t" Function,+,protocol_dict_alloc,ProtocolDict*,"const ProtocolBase**, size_t"
Function,-,protocol_dict_decoders_feed,ProtocolId,"ProtocolDict*, _Bool, uint32_t" Function,-,protocol_dict_decoders_feed,ProtocolId,"ProtocolDict*, _Bool, uint32_t"
Function,-,protocol_dict_decoders_feed_by_feature,ProtocolId,"ProtocolDict*, uint32_t, _Bool, uint32_t" Function,-,protocol_dict_decoders_feed_by_feature,ProtocolId,"ProtocolDict*, uint32_t, _Bool, uint32_t"
@ -2178,6 +2299,7 @@ Function,-,rfalT1TPollerRall,ReturnCode,"const uint8_t*, uint8_t*, uint16_t, uin
Function,-,rfalT1TPollerRid,ReturnCode,rfalT1TRidRes* Function,-,rfalT1TPollerRid,ReturnCode,rfalT1TRidRes*
Function,-,rfalT1TPollerWrite,ReturnCode,"const uint8_t*, uint8_t, uint8_t" Function,-,rfalT1TPollerWrite,ReturnCode,"const uint8_t*, uint8_t, uint8_t"
Function,-,rfalTransceiveBitsBlockingTx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" Function,-,rfalTransceiveBitsBlockingTx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t"
Function,-,rfalTransceiveBitsBlockingTxRx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t"
Function,-,rfalTransceiveBlockingRx,ReturnCode, Function,-,rfalTransceiveBlockingRx,ReturnCode,
Function,-,rfalTransceiveBlockingTx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" Function,-,rfalTransceiveBlockingTx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t"
Function,-,rfalTransceiveBlockingTxRx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" Function,-,rfalTransceiveBlockingTxRx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t"
@ -2287,6 +2409,7 @@ Function,+,storage_common_mkdir,FS_Error,"Storage*, const char*"
Function,+,storage_common_remove,FS_Error,"Storage*, const char*" Function,+,storage_common_remove,FS_Error,"Storage*, const char*"
Function,+,storage_common_rename,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_rename,FS_Error,"Storage*, const char*, const char*"
Function,+,storage_common_stat,FS_Error,"Storage*, const char*, FileInfo*" Function,+,storage_common_stat,FS_Error,"Storage*, const char*, FileInfo*"
Function,+,storage_common_timestamp,FS_Error,"Storage*, const char*, uint32_t*"
Function,+,storage_dir_close,_Bool,File* Function,+,storage_dir_close,_Bool,File*
Function,+,storage_dir_open,_Bool,"File*, const char*" Function,+,storage_dir_open,_Bool,"File*, const char*"
Function,+,storage_dir_read,_Bool,"File*, FileInfo*, char*, uint16_t" Function,+,storage_dir_read,_Bool,"File*, FileInfo*, char*, uint16_t"

1 entry status name type params
152 Header + lib/mbedtls/include/mbedtls/des.h
153 Header + lib/mbedtls/include/mbedtls/sha1.h
154 Header + lib/micro-ecc/uECC.h
155 Header + lib/nfc/nfc_device.h
156 Header + lib/one_wire/ibutton/ibutton_worker.h
157 Header + lib/one_wire/maxim_crc.h
158 Header + lib/one_wire/one_wire_device.h
689 Function - cosl long double long double
690 Function + crc32_calc_buffer uint32_t uint32_t, const void*, size_t
691 Function + crc32_calc_file uint32_t File*, const FileCrcProgressCb, void*
692 Function - crypto1_bit uint8_t Crypto1*, uint8_t, int
693 Function - crypto1_byte uint8_t Crypto1*, uint8_t, int
694 Function - crypto1_decrypt void Crypto1*, uint8_t*, uint16_t, uint8_t*
695 Function - crypto1_encrypt void Crypto1*, uint8_t*, uint8_t*, uint16_t, uint8_t*, uint8_t*
696 Function - crypto1_filter uint32_t uint32_t
697 Function - crypto1_init void Crypto1*, uint64_t
698 Function - crypto1_reset void Crypto1*
699 Function - crypto1_word uint32_t Crypto1*, uint32_t, int
700 Function - ctermid char* char*
701 Function - ctime char* const time_t*
702 Function - ctime_r char* const time_t*, char*
779 Function + empty_screen_alloc EmptyScreen*
780 Function + empty_screen_free void EmptyScreen*
781 Function + empty_screen_get_view View* EmptyScreen*
782 Function - emv_card_emulation _Bool FuriHalNfcTxRxContext*
783 Function - emv_read_bank_card _Bool FuriHalNfcTxRxContext*, EmvApplication*
784 Function - erand48 double unsigned short[3]
785 Function - erf double double
786 Function - erfc double double
1192 Function + furi_hal_nfc_ll_set_guard_time void uint32_t
1193 Function + furi_hal_nfc_ll_set_mode FuriHalNfcReturn FuriHalNfcMode, FuriHalNfcBitrate, FuriHalNfcBitrate
1194 Function + furi_hal_nfc_ll_txrx FuriHalNfcReturn uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t
1195 Function + furi_hal_nfc_ll_txrx_bits FuriHalNfcReturn uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t
1196 Function + furi_hal_nfc_ll_txrx_off void
1197 Function + furi_hal_nfc_ll_txrx_on void
1198 Function + furi_hal_nfc_sleep void
1278 Function + furi_hal_rtc_get_log_level uint8_t
1279 Function + furi_hal_rtc_get_pin_fails uint32_t
1280 Function + furi_hal_rtc_get_register uint32_t FuriHalRtcRegister
1281 Function + furi_hal_rtc_get_timestamp uint32_t
1282 Function - furi_hal_rtc_init void
1283 Function - furi_hal_rtc_init_early void
1284 Function + furi_hal_rtc_is_flag_set _Bool FuriHalRtcFlag
1838 Function + menu_get_view View* Menu*
1839 Function + menu_reset void Menu*
1840 Function + menu_set_selected_item void Menu*, uint32_t
1841 Function - mf_classic_auth_attempt _Bool FuriHalNfcTxRxContext*, MfClassicAuthContext*, uint64_t
1842 Function - mf_classic_auth_init_context void MfClassicAuthContext*, uint8_t
1843 Function - mf_classic_authenticate _Bool FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey
1844 Function - mf_classic_check_card_type _Bool uint8_t, uint8_t, uint8_t
1845 Function - mf_classic_dict_add_key _Bool MfClassicDict*, uint8_t*
1846 Function - mf_classic_dict_add_key_str _Bool MfClassicDict*, FuriString*
1847 Function - mf_classic_dict_alloc MfClassicDict* MfClassicDictType
1848 Function - mf_classic_dict_check_presence _Bool MfClassicDictType
1849 Function - mf_classic_dict_delete_index _Bool MfClassicDict*, uint32_t
1850 Function - mf_classic_dict_find_index _Bool MfClassicDict*, uint8_t*, uint32_t*
1851 Function - mf_classic_dict_find_index_str _Bool MfClassicDict*, FuriString*, uint32_t*
1852 Function - mf_classic_dict_free void MfClassicDict*
1853 Function - mf_classic_dict_get_key_at_index _Bool MfClassicDict*, uint64_t*, uint32_t
1854 Function - mf_classic_dict_get_key_at_index_str _Bool MfClassicDict*, FuriString*, uint32_t
1855 Function - mf_classic_dict_get_next_key _Bool MfClassicDict*, uint64_t*
1856 Function - mf_classic_dict_get_next_key_str _Bool MfClassicDict*, FuriString*
1857 Function - mf_classic_dict_get_total_keys uint32_t MfClassicDict*
1858 Function - mf_classic_dict_is_key_present _Bool MfClassicDict*, uint8_t*
1859 Function - mf_classic_dict_is_key_present_str _Bool MfClassicDict*, FuriString*
1860 Function - mf_classic_dict_rewind _Bool MfClassicDict*
1861 Function - mf_classic_emulator _Bool MfClassicEmulator*, FuriHalNfcTxRxContext*
1862 Function - mf_classic_get_classic_type MfClassicType int8_t, uint8_t, uint8_t
1863 Function - mf_classic_get_read_sectors_and_keys void MfClassicData*, uint8_t*, uint8_t*
1864 Function - mf_classic_get_sector_by_block uint8_t uint8_t
1865 Function - mf_classic_get_sector_trailer_block_num_by_sector uint8_t uint8_t
1866 Function - mf_classic_get_sector_trailer_by_sector MfClassicSectorTrailer* MfClassicData*, uint8_t
1867 Function - mf_classic_get_total_sectors_num uint8_t MfClassicType
1868 Function - mf_classic_get_type_str const char* MfClassicType
1869 Function - mf_classic_is_allowed_access_data_block _Bool MfClassicData*, uint8_t, MfClassicKey, MfClassicAction
1870 Function - mf_classic_is_allowed_access_sector_trailer _Bool MfClassicData*, uint8_t, MfClassicKey, MfClassicAction
1871 Function - mf_classic_is_block_read _Bool MfClassicData*, uint8_t
1872 Function - mf_classic_is_card_read _Bool MfClassicData*
1873 Function - mf_classic_is_key_found _Bool MfClassicData*, uint8_t, MfClassicKey
1874 Function - mf_classic_is_sector_data_read _Bool MfClassicData*, uint8_t
1875 Function - mf_classic_is_sector_read _Bool MfClassicData*, uint8_t
1876 Function - mf_classic_is_sector_trailer _Bool uint8_t
1877 Function - mf_classic_read_card uint8_t FuriHalNfcTxRxContext*, MfClassicReader*, MfClassicData*
1878 Function - mf_classic_read_sector void FuriHalNfcTxRxContext*, MfClassicData*, uint8_t
1879 Function - mf_classic_reader_add_sector void MfClassicReader*, uint8_t, uint64_t, uint64_t
1880 Function - mf_classic_set_block_read void MfClassicData*, uint8_t, MfClassicBlock*
1881 Function - mf_classic_set_key_found void MfClassicData*, uint8_t, MfClassicKey, uint64_t
1882 Function - mf_classic_set_key_not_found void MfClassicData*, uint8_t, MfClassicKey
1883 Function - mf_classic_set_sector_data_not_read void MfClassicData*
1884 Function - mf_classic_update_card uint8_t FuriHalNfcTxRxContext*, MfClassicData*
1885 Function - mf_classic_write_block _Bool FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t
1886 Function - mf_classic_write_sector _Bool FuriHalNfcTxRxContext*, MfClassicData*, MfClassicData*, uint8_t
1887 Function - mf_df_cat_application void MifareDesfireApplication*, FuriString*
1888 Function - mf_df_cat_application_info void MifareDesfireApplication*, FuriString*
1889 Function - mf_df_cat_card_info void MifareDesfireData*, FuriString*
1890 Function - mf_df_cat_data void MifareDesfireData*, FuriString*
1891 Function - mf_df_cat_file void MifareDesfireFile*, FuriString*
1892 Function - mf_df_cat_free_mem void MifareDesfireFreeMemory*, FuriString*
1893 Function - mf_df_cat_key_settings void MifareDesfireKeySettings*, FuriString*
1894 Function - mf_df_cat_version void MifareDesfireVersion*, FuriString*
1895 Function - mf_df_check_card_type _Bool uint8_t, uint8_t, uint8_t
1896 Function - mf_df_clear void MifareDesfireData*
1897 Function - mf_df_parse_get_application_ids_response _Bool uint8_t*, uint16_t, MifareDesfireApplication**
1898 Function - mf_df_parse_get_file_ids_response _Bool uint8_t*, uint16_t, MifareDesfireFile**
1899 Function - mf_df_parse_get_file_settings_response _Bool uint8_t*, uint16_t, MifareDesfireFile*
1900 Function - mf_df_parse_get_free_memory_response _Bool uint8_t*, uint16_t, MifareDesfireFreeMemory*
1901 Function - mf_df_parse_get_key_settings_response _Bool uint8_t*, uint16_t, MifareDesfireKeySettings*
1902 Function - mf_df_parse_get_key_version_response _Bool uint8_t*, uint16_t, MifareDesfireKeyVersion*
1903 Function - mf_df_parse_get_version_response _Bool uint8_t*, uint16_t, MifareDesfireVersion*
1904 Function - mf_df_parse_read_data_response _Bool uint8_t*, uint16_t, MifareDesfireFile*
1905 Function - mf_df_parse_select_application_response _Bool uint8_t*, uint16_t
1906 Function - mf_df_prepare_get_application_ids uint16_t uint8_t*
1907 Function - mf_df_prepare_get_file_ids uint16_t uint8_t*
1908 Function - mf_df_prepare_get_file_settings uint16_t uint8_t*, uint8_t
1909 Function - mf_df_prepare_get_free_memory uint16_t uint8_t*
1910 Function - mf_df_prepare_get_key_settings uint16_t uint8_t*
1911 Function - mf_df_prepare_get_key_version uint16_t uint8_t*, uint8_t
1912 Function - mf_df_prepare_get_value uint16_t uint8_t*, uint8_t
1913 Function - mf_df_prepare_get_version uint16_t uint8_t*
1914 Function - mf_df_prepare_read_data uint16_t uint8_t*, uint8_t, uint32_t, uint32_t
1915 Function - mf_df_prepare_read_records uint16_t uint8_t*, uint8_t, uint32_t, uint32_t
1916 Function - mf_df_prepare_select_application uint16_t uint8_t*, uint8_t[3]
1917 Function - mf_df_read_card _Bool FuriHalNfcTxRxContext*, MifareDesfireData*
1918 Function - mf_ul_check_card_type _Bool uint8_t, uint8_t, uint8_t
1919 Function - mf_ul_prepare_emulation void MfUltralightEmulator*, MfUltralightData*
1920 Function - mf_ul_prepare_emulation_response _Bool uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*
1921 Function - mf_ul_pwdgen_amiibo uint32_t FuriHalNfcDevData*
1922 Function - mf_ul_pwdgen_xiaomi uint32_t FuriHalNfcDevData*
1923 Function - mf_ul_read_card _Bool FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*
1924 Function - mf_ul_reset void MfUltralightData*
1925 Function - mf_ul_reset_emulation void MfUltralightEmulator*, _Bool
1926 Function - mf_ultralight_authenticate _Bool FuriHalNfcTxRxContext*, uint32_t, uint16_t*
1927 Function - mf_ultralight_fast_read_pages _Bool FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*
1928 Function - mf_ultralight_get_config_pages MfUltralightConfigPages* MfUltralightData*
1929 Function - mf_ultralight_read_counters _Bool FuriHalNfcTxRxContext*, MfUltralightData*
1930 Function - mf_ultralight_read_pages _Bool FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*
1931 Function - mf_ultralight_read_pages_direct _Bool FuriHalNfcTxRxContext*, uint8_t, uint8_t*
1932 Function - mf_ultralight_read_signature _Bool FuriHalNfcTxRxContext*, MfUltralightData*
1933 Function - mf_ultralight_read_tearing_flags _Bool FuriHalNfcTxRxContext*, MfUltralightData*
1934 Function - mf_ultralight_read_version _Bool FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*
1935 Function - mkdtemp char* char*
1936 Function - mkostemp int char*, int
1937 Function - mkostemps int char*, int, int
1955 Function - nexttoward double double, long double
1956 Function - nexttowardf float float, long double
1957 Function - nexttowardl long double long double, long double
1958 Function + nfc_device_alloc NfcDevice*
1959 Function + nfc_device_clear void NfcDevice*
1960 Function + nfc_device_data_clear void NfcDeviceData*
1961 Function + nfc_device_delete _Bool NfcDevice*, _Bool
1962 Function + nfc_device_free void NfcDevice*
1963 Function + nfc_device_load _Bool NfcDevice*, const char*, _Bool
1964 Function + nfc_device_load_key_cache _Bool NfcDevice*
1965 Function + nfc_device_restore _Bool NfcDevice*, _Bool
1966 Function + nfc_device_save _Bool NfcDevice*, const char*
1967 Function + nfc_device_save_shadow _Bool NfcDevice*, const char*
1968 Function + nfc_device_set_loading_callback void NfcDevice*, NfcLoadingCallback, void*
1969 Function + nfc_device_set_name void NfcDevice*, const char*
1970 Function + nfc_file_select _Bool NfcDevice*
1971 Function - nfca_append_crc16 void uint8_t*, uint16_t
1972 Function - nfca_emulation_handler _Bool uint8_t*, uint16_t, uint8_t*, uint16_t*
1973 Function - nfca_get_crc16 uint16_t uint8_t*, uint16_t
2082 Function + powf float float, float
2083 Function - powl long double long double, long double
2084 Function - printf int const char*, ...
2085 Function - prng_successor uint32_t uint32_t, uint32_t
2086 Function + protocol_dict_alloc ProtocolDict* const ProtocolBase**, size_t
2087 Function - protocol_dict_decoders_feed ProtocolId ProtocolDict*, _Bool, uint32_t
2088 Function - protocol_dict_decoders_feed_by_feature ProtocolId ProtocolDict*, uint32_t, _Bool, uint32_t
2299 Function - rfalT1TPollerRid ReturnCode rfalT1TRidRes*
2300 Function - rfalT1TPollerWrite ReturnCode const uint8_t*, uint8_t, uint8_t
2301 Function - rfalTransceiveBitsBlockingTx ReturnCode uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t
2302 Function - rfalTransceiveBitsBlockingTxRx ReturnCode uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t
2303 Function - rfalTransceiveBlockingRx ReturnCode
2304 Function - rfalTransceiveBlockingTx ReturnCode uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t
2305 Function - rfalTransceiveBlockingTxRx ReturnCode uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t
2409 Function + storage_common_remove FS_Error Storage*, const char*
2410 Function + storage_common_rename FS_Error Storage*, const char*, const char*
2411 Function + storage_common_stat FS_Error Storage*, const char*, FileInfo*
2412 Function + storage_common_timestamp FS_Error Storage*, const char*, uint32_t*
2413 Function + storage_dir_close _Bool File*
2414 Function + storage_dir_open _Bool File*, const char*
2415 Function + storage_dir_read _Bool File*, FileInfo*, char*, uint16_t

View file

@ -786,6 +786,17 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx(
return rfalTransceiveBlockingTxRx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt); return rfalTransceiveBlockingTxRx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt);
} }
FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits(
uint8_t* txBuf,
uint16_t txBufLen,
uint8_t* rxBuf,
uint16_t rxBufLen,
uint16_t* actLen,
uint32_t flags,
uint32_t fwt) {
return rfalTransceiveBitsBlockingTxRx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt);
}
void furi_hal_nfc_ll_poll() { void furi_hal_nfc_ll_poll() {
rfalWorker(); rfalWorker();
} }

View file

@ -318,6 +318,12 @@ uint32_t furi_hal_rtc_get_pin_fails() {
return furi_hal_rtc_get_register(FuriHalRtcRegisterPinFails); return furi_hal_rtc_get_register(FuriHalRtcRegisterPinFails);
} }
uint32_t furi_hal_rtc_get_timestamp() {
FuriHalRtcDateTime datetime = {0};
furi_hal_rtc_get_datetime(&datetime);
return furi_hal_rtc_datetime_to_timestamp(&datetime);
}
uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) { uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
uint32_t timestamp = 0; uint32_t timestamp = 0;
uint8_t years = 0; uint8_t years = 0;

View file

@ -398,6 +398,7 @@ void furi_hal_nfc_ll_txrx_on();
void furi_hal_nfc_ll_txrx_off(); void furi_hal_nfc_ll_txrx_off();
// TODO rework all pollers with furi_hal_nfc_ll_txrx_bits
FuriHalNfcReturn furi_hal_nfc_ll_txrx( FuriHalNfcReturn furi_hal_nfc_ll_txrx(
uint8_t* txBuf, uint8_t* txBuf,
uint16_t txBufLen, uint16_t txBufLen,
@ -407,6 +408,15 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx(
uint32_t flags, uint32_t flags,
uint32_t fwt); uint32_t fwt);
FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits(
uint8_t* txBuf,
uint16_t txBufLen,
uint8_t* rxBuf,
uint16_t rxBufLen,
uint16_t* actLen,
uint32_t flags,
uint32_t fwt);
void furi_hal_nfc_ll_poll(); void furi_hal_nfc_ll_poll();
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -93,6 +93,8 @@ void furi_hal_rtc_set_pin_fails(uint32_t value);
uint32_t furi_hal_rtc_get_pin_fails(); uint32_t furi_hal_rtc_get_pin_fails();
uint32_t furi_hal_rtc_get_timestamp();
uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime); uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -1496,6 +1496,15 @@ ReturnCode rfalTransceiveBlockingTxRx(
uint32_t flags, uint32_t flags,
uint32_t fwt); uint32_t fwt);
ReturnCode rfalTransceiveBitsBlockingTxRx(
uint8_t* txBuf,
uint16_t txBufLen,
uint8_t* rxBuf,
uint16_t rxBufLen,
uint16_t* actLen,
uint32_t flags,
uint32_t fwt);
ReturnCode rfalTransceiveBitsBlockingTx( ReturnCode rfalTransceiveBitsBlockingTx(
uint8_t* txBuf, uint8_t* txBuf,
uint16_t txBufLen, uint16_t txBufLen,

View file

@ -1607,6 +1607,23 @@ ReturnCode rfalTransceiveBlockingTxRx(
return ret; return ret;
} }
ReturnCode rfalTransceiveBitsBlockingTxRx(
uint8_t* txBuf,
uint16_t txBufLen,
uint8_t* rxBuf,
uint16_t rxBufLen,
uint16_t* actLen,
uint32_t flags,
uint32_t fwt) {
ReturnCode ret;
EXIT_ON_ERR(
ret, rfalTransceiveBitsBlockingTx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt));
ret = rfalTransceiveBlockingRx();
return ret;
}
/*******************************************************************************/ /*******************************************************************************/
static ReturnCode rfalRunTransceiveWorker(void) { static ReturnCode rfalRunTransceiveWorker(void) {
if(gRFAL.state == RFAL_STATE_TXRX) { if(gRFAL.state == RFAL_STATE_TXRX) {

View file

@ -4,6 +4,9 @@ env.Append(
CPPPATH=[ CPPPATH=[
"#/lib/nfc", "#/lib/nfc",
], ],
SDK_HEADERS=[
File("#/lib/nfc/nfc_device.h"),
],
) )
libenv = env.Clone(FW_LIB_NAME="nfc") libenv = env.Clone(FW_LIB_NAME="nfc")

View file

@ -12,6 +12,10 @@
#include <lib/nfc/protocols/mifare_classic.h> #include <lib/nfc/protocols/mifare_classic.h>
#include <lib/nfc/protocols/mifare_desfire.h> #include <lib/nfc/protocols/mifare_desfire.h>
#ifdef __cplusplus
extern "C" {
#endif
#define NFC_DEV_NAME_MAX_LEN 22 #define NFC_DEV_NAME_MAX_LEN 22
#define NFC_READER_DATA_MAX_SIZE 64 #define NFC_READER_DATA_MAX_SIZE 64
#define NFC_DICT_KEY_BATCH_SIZE 50 #define NFC_DICT_KEY_BATCH_SIZE 50
@ -101,3 +105,7 @@ bool nfc_device_delete(NfcDevice* dev, bool use_load_path);
bool nfc_device_restore(NfcDevice* dev, bool use_load_path); bool nfc_device_restore(NfcDevice* dev, bool use_load_path);
void nfc_device_set_loading_callback(NfcDevice* dev, NfcLoadingCallback callback, void* context); void nfc_device_set_loading_callback(NfcDevice* dev, NfcLoadingCallback callback, void* context);
#ifdef __cplusplus
}
#endif