FL-53: new NFC worker, A/B/F/V poll and display. (#283)

* GUI: view. Flooper-blooper fix compilation error.
* GUI: view and viewdispatcher bones
* GUI: view implementation, view models, view dispatcher
* GUI: view navigation, model refinement. Power: use view, view dispatcher.

* HAL Flash: proper page write. Dolphin: views. Power: views

* Dolphin: transition idle scree to Views
* Dolphin: input events on stats view. Format sources.

* HAL: flash erase. Dolphin: permanent state storage.

* Dolphin: first start welcome. HAL: flash operation status, errata 2.2.9 crutch.

* NFC: rewrite worker
* NFC: add support for B,F,V.
* NFC: replace rfal irq hanlder with realtime thread, more details about cards.

* Bootloader: LSE and RTS shenanigans, LED control, morse code for LSE failure error.

* F4: stop in Error_Handler

* BLE: handle working FUS, but empty radio stack.

* HAL: alive FUS is now sufficient for flash controller access

* Dolphin: update model after state load

* NFC: detect navigation

* RFAL: use osPriorityISR for isr thread

* NFC: emulation

* Bootloader: rollback incorrectly merged rename

* Dolphin: rollback incorrectly merged changes

* RFAL: remove volatile from thread attr

* RFAL: do not call platform ErrorHandler, error codes is enough

* NFC: improved error handling

* Format sources

* NFC: reset detect view model on start

* Format sources

* update codeowners

* NFC: hide last info if no card detected
This commit is contained in:
あく 2021-01-11 15:42:25 +03:00 committed by GitHub
parent 34dbb2ea86
commit 6928122650
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 838 additions and 419 deletions

1
.github/CODEOWNERS vendored
View File

@ -59,6 +59,7 @@ applications/menu/** @skotopes
# NFC
applications/nfc/** @skotopes
lib/ST25RFAL002/** @skotopes
# SD Card

View File

@ -92,11 +92,6 @@ Dolphin* dolphin_alloc() {
view_set_context(dolphin->idle_view_stats, dolphin);
view_allocate_model(
dolphin->idle_view_stats, ViewModelTypeLockFree, sizeof(DolphinViewIdleStatsModel));
with_view_model(
dolphin->idle_view_stats, (DolphinViewIdleStatsModel * model) {
model->icounter = dolphin_state_get_icounter(dolphin->state);
model->butthurt = dolphin_state_get_butthurt(dolphin->state);
});
view_set_draw_callback(dolphin->idle_view_stats, dolphin_view_idle_stats_draw);
view_set_input_callback(dolphin->idle_view_stats, dolphin_view_idle_stats_input);
view_set_previous_callback(dolphin->idle_view_stats, dolphin_view_idle_back);
@ -137,6 +132,11 @@ void dolphin_task() {
} else {
view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewFirstStart);
}
with_view_model(
dolphin->idle_view_stats, (DolphinViewIdleStatsModel * model) {
model->icounter = dolphin_state_get_icounter(dolphin->state);
model->butthurt = dolphin_state_get_butthurt(dolphin->state);
});
if(!furi_create("dolphin", dolphin)) {
printf("[dolphin_task] cannot create the dolphin record\n");

View File

@ -1,57 +0,0 @@
#include "dispatcher.h"
#include <flipper.h>
#include <flipper_v2.h>
struct Dispatcher {
void* message;
size_t message_size;
osMessageQueueId_t mqueue;
osMutexId_t lock_mutex;
};
Dispatcher* dispatcher_alloc(size_t queue_size, size_t message_size) {
Dispatcher* dispatcher = furi_alloc(sizeof(Dispatcher));
dispatcher->message = furi_alloc(message_size);
dispatcher->message_size = message_size;
dispatcher->mqueue = osMessageQueueNew(queue_size, message_size, NULL);
furi_check(dispatcher->mqueue);
dispatcher->lock_mutex = osMutexNew(NULL);
furi_check(dispatcher->lock_mutex);
dispatcher_lock(dispatcher);
return dispatcher;
}
void dispatcher_free(Dispatcher* dispatcher) {
furi_assert(dispatcher);
free(dispatcher);
}
void dispatcher_send(Dispatcher* dispatcher, Message* message) {
furi_assert(dispatcher);
furi_assert(message);
furi_check(osMessageQueuePut(dispatcher->mqueue, message, 0, osWaitForever) == osOK);
}
// TODO: bad side-effect
void dispatcher_recieve(Dispatcher* dispatcher, Message* message) {
furi_assert(dispatcher);
furi_assert(message);
dispatcher_unlock(dispatcher);
furi_check(osMessageQueueGet(dispatcher->mqueue, message, NULL, osWaitForever) == osOK);
dispatcher_lock(dispatcher);
}
void dispatcher_lock(Dispatcher* dispatcher) {
furi_assert(dispatcher);
furi_check(osMutexAcquire(dispatcher->lock_mutex, osWaitForever) == osOK);
}
void dispatcher_unlock(Dispatcher* dispatcher) {
furi_assert(dispatcher);
furi_check(osMutexRelease(dispatcher->lock_mutex) == osOK);
}

View File

@ -1,28 +0,0 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
enum MessageTypeBase {
MessageTypeExit = 0x00,
MessageTypeMemoryLow = 0x01,
MessageTypeBatteryLow = 0x02,
};
typedef struct {
enum MessageTypeBase type;
} Message;
typedef struct Dispatcher Dispatcher;
Dispatcher* dispatcher_alloc(size_t queue_size, size_t message_size);
void dispatcher_free(Dispatcher* dispatcher);
void dispatcher_send(Dispatcher* dispatcher, Message* message);
void dispatcher_recieve(Dispatcher* dispatcher, Message* message);
void dispatcher_lock(Dispatcher* dispatcher);
void dispatcher_unlock(Dispatcher* dispatcher);

View File

@ -1,174 +1,109 @@
#include "nfc.h"
#include "nfc_i.h"
#include "nfc_worker.h"
void nfc_draw_callback(Canvas* canvas, void* context) {
furi_assert(canvas);
furi_assert(context);
Nfc* nfc = context;
dispatcher_lock(nfc->dispatcher);
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
if(nfc->screen == 0) {
char status[128 / 8];
if(nfc->ret == ERR_WRONG_STATE)
canvas_draw_str(canvas, 2, 16, "NFC Wrong State");
else if(nfc->ret == ERR_PARAM)
canvas_draw_str(canvas, 2, 16, "NFC Wrong Param");
else if(nfc->ret == ERR_IO)
canvas_draw_str(canvas, 2, 16, "NFC IO Error");
else if(nfc->ret == ERR_NONE)
canvas_draw_str(canvas, 2, 16, "NFC Device Found");
else if(nfc->ret == ERR_TIMEOUT)
canvas_draw_str(canvas, 2, 16, "NFC Timeout");
else
canvas_draw_str(canvas, 2, 16, "NFC error");
canvas_set_font(canvas, FontSecondary);
snprintf(status, sizeof(status), "Found: %d", nfc->devCnt);
if(nfc->devCnt > 0) {
canvas_draw_str(canvas, 2, 32, status);
canvas_draw_str(canvas, 2, 42, nfc->current);
snprintf(
status,
sizeof(status),
"ATQA:%d SAK:%d",
nfc->first_atqa.anticollisionInfo,
nfc->first_sak.sak);
canvas_draw_str(canvas, 2, 52, status);
}
} else {
canvas_draw_str(canvas, 2, 16, "Not implemented");
}
dispatcher_unlock(nfc->dispatcher);
}
void nfc_input_callback(InputEvent* event, void* context) {
furi_assert(event);
uint32_t nfc_view_exit(void* context) {
furi_assert(context);
Nfc* nfc = context;
if(!event->state || event->input != InputBack) return;
widget_enabled_set(nfc->widget, false);
}
void nfc_test_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
dispatcher_lock(nfc->dispatcher);
nfc->screen = 0;
widget_enabled_set(nfc->widget, true);
// TODO only for workaround
if(nfc->ret != ERR_NONE) {
nfc->ret = rfalNfcInitialize();
rfalLowPowerModeStart();
}
if(nfc->ret == ERR_NONE && !nfc->worker) {
// TODO change to fuirac_start
nfc->worker = osThreadNew(nfc_worker_task, nfc, &nfc->worker_attr);
}
dispatcher_unlock(nfc->dispatcher);
}
void nfc_field_on_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
// TODO only for workaround
if(nfc->ret != ERR_NONE) {
nfc->ret = rfalNfcInitialize();
rfalLowPowerModeStart();
}
st25r3916OscOn();
st25r3916TxRxOn();
}
void nfc_field_off_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
// TODO only for workaround
if(nfc->ret != ERR_NONE) {
nfc->ret = rfalNfcInitialize();
rfalLowPowerModeStart();
}
st25r3916TxRxOff();
}
void nfc_read_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
nfc->screen = 1;
widget_enabled_set(nfc->widget, true);
}
void nfc_write_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
nfc->screen = 1;
widget_enabled_set(nfc->widget, true);
}
void nfc_bridge_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
nfc->screen = 1;
widget_enabled_set(nfc->widget, true);
NfcMessage message;
message.type = NfcMessageTypeStop;
furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
return VIEW_NONE;
}
Nfc* nfc_alloc() {
Nfc* nfc = furi_alloc(sizeof(Nfc));
nfc->dispatcher = dispatcher_alloc(32, sizeof(NfcMessage));
nfc->message_queue = osMessageQueueNew(8, sizeof(NfcMessage), NULL);
nfc->worker = nfc_worker_alloc(nfc->message_queue);
nfc->icon = assets_icons_get(A_NFC_14);
nfc->widget = widget_alloc();
widget_draw_callback_set(nfc->widget, nfc_draw_callback, nfc);
widget_input_callback_set(nfc->widget, nfc_input_callback, nfc);
nfc->menu_vm = furi_open("menu");
furi_check(nfc->menu_vm);
nfc->menu = menu_item_alloc_menu("NFC", nfc->icon);
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Test", NULL, nfc_test_callback, nfc));
nfc->menu, menu_item_alloc_function("Detect", NULL, nfc_menu_detect_callback, nfc));
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Field On", NULL, nfc_field_on_callback, nfc));
nfc->menu, menu_item_alloc_function("Emulate", NULL, nfc_menu_emulate_callback, nfc));
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Field Off", NULL, nfc_field_off_callback, nfc));
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Read", NULL, nfc_read_callback, nfc));
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Write", NULL, nfc_write_callback, nfc));
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Brdige", NULL, nfc_bridge_callback, nfc));
nfc->menu, menu_item_alloc_function("Field", NULL, nfc_menu_field_callback, nfc));
nfc->view_detect = view_alloc();
view_set_context(nfc->view_detect, nfc);
view_set_draw_callback(nfc->view_detect, nfc_view_read_draw);
view_set_previous_callback(nfc->view_detect, nfc_view_exit);
view_allocate_model(nfc->view_detect, ViewModelTypeLocking, sizeof(NfcViewReadModel));
nfc->view_emulate = view_alloc();
view_set_context(nfc->view_emulate, nfc);
view_set_draw_callback(nfc->view_emulate, nfc_view_emulate_draw);
view_set_previous_callback(nfc->view_emulate, nfc_view_exit);
nfc->view_field = view_alloc();
view_set_context(nfc->view_field, nfc);
view_set_draw_callback(nfc->view_field, nfc_view_field_draw);
view_set_previous_callback(nfc->view_field, nfc_view_exit);
nfc->view_error = view_alloc();
view_set_context(nfc->view_error, nfc);
view_set_draw_callback(nfc->view_error, nfc_view_error_draw);
view_set_previous_callback(nfc->view_error, nfc_view_exit);
view_allocate_model(nfc->view_error, ViewModelTypeLockFree, sizeof(NfcViewErrorModel));
nfc->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewRead, nfc->view_detect);
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewEmulate, nfc->view_emulate);
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewField, nfc->view_field);
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewError, nfc->view_error);
nfc->worker_attr.name = "nfc_worker";
// nfc->worker_attr.attr_bits = osThreadJoinable;
nfc->worker_attr.stack_size = 4096;
return nfc;
}
void nfc_menu_detect_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
NfcMessage message;
message.type = NfcMessageTypeDetect;
furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
}
void nfc_menu_emulate_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
NfcMessage message;
message.type = NfcMessageTypeEmulate;
furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
}
void nfc_menu_field_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
NfcMessage message;
message.type = NfcMessageTypeField;
furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
}
void nfc_menu_field_off_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
NfcMessage message;
message.type = NfcMessageTypeField;
furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
}
void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) {
NfcWorkerState state = nfc_worker_get_state(nfc->worker);
if(state == NfcWorkerStateBroken) {
with_view_model(
nfc->view_error,
(NfcViewErrorModel * model) { model->error = nfc_worker_get_error(nfc->worker); });
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewError);
} else if(state == NfcWorkerStateReady) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, view_id);
nfc_worker_start(nfc->worker, worker_state);
}
}
void nfc_task(void* p) {
Nfc* nfc = nfc_alloc();
Gui* gui = furi_open("gui");
widget_enabled_set(nfc->widget, false);
gui_add_widget(gui, nfc->widget, GuiLayerFullscreen);
view_dispatcher_attach_to_gui(nfc->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
with_value_mutex(
nfc->menu_vm, (Menu * menu) { menu_item_add(menu, nfc->menu); });
@ -178,17 +113,30 @@ void nfc_task(void* p) {
furiac_exit(NULL);
}
// TODO only for workaround
nfc->ret = ERR_WRONG_STATE;
furiac_ready();
NfcMessage message;
while(1) {
dispatcher_recieve(nfc->dispatcher, (Message*)&message);
if(message.base.type == MessageTypeExit) {
break;
furi_check(osMessageQueueGet(nfc->message_queue, &message, NULL, osWaitForever) == osOK);
if(message.type == NfcMessageTypeDetect) {
with_view_model(
nfc->view_detect, (NfcViewReadModel * model) { model->found = false; });
nfc_start(nfc, NfcViewRead, NfcWorkerStatePoll);
} else if(message.type == NfcMessageTypeEmulate) {
nfc_start(nfc, NfcViewEmulate, NfcWorkerStateEmulate);
} else if(message.type == NfcMessageTypeField) {
nfc_start(nfc, NfcViewField, NfcWorkerStateField);
} else if(message.type == NfcMessageTypeStop) {
nfc_worker_stop(nfc->worker);
} else if(message.type == NfcMessageTypeDeviceFound) {
with_view_model(
nfc->view_detect, (NfcViewReadModel * model) {
model->found = true;
model->device = message.device;
});
} else if(message.type == NfcMessageTypeDeviceNotFound) {
with_view_model(
nfc->view_detect, (NfcViewReadModel * model) { model->found = false; });
}
}
}

View File

@ -1,49 +1,44 @@
#pragma once
#include "nfc.h"
#include "nfc_types.h"
#include "nfc_views.h"
#include "nfc_worker.h"
#include <flipper_v2.h>
#include <rfal_analogConfig.h>
#include <rfal_rf.h>
#include <rfal_nfc.h>
#include <rfal_nfca.h>
#include <st25r3916.h>
#include <st25r3916_irq.h>
#include <gui/gui.h>
#include <gui/widget.h>
#include <gui/canvas.h>
#include <gui/view.h>
#include <gui/view_dispatcher.h>
#include <assets_icons.h>
#include <menu/menu.h>
#include <menu/menu_item.h>
#include "dispatcher.h"
typedef enum {
MessageTypeBase,
} NfcMessageType;
typedef struct {
Message base;
void* data;
} NfcMessage;
struct Nfc {
Dispatcher* dispatcher;
Icon* icon;
Widget* widget;
osMessageQueueId_t message_queue;
NfcWorker* worker;
ValueMutex* menu_vm;
MenuItem* menu;
rfalNfcDiscoverParam* disParams;
Icon* icon;
osThreadAttr_t worker_attr;
osThreadId_t worker;
uint8_t screen;
uint8_t ret;
uint8_t devCnt;
rfalNfcaSensRes first_atqa;
rfalNfcaSelRes first_sak;
char* current;
View* view_detect;
View* view_emulate;
View* view_field;
View* view_error;
ViewDispatcher* view_dispatcher;
};
Nfc* nfc_alloc();
void nfc_menu_detect_callback(void* context);
void nfc_menu_emulate_callback(void* context);
void nfc_menu_field_callback(void* context);
void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state);
void nfc_task(void* p);

View File

@ -0,0 +1,68 @@
#pragma once
#include <rfal_nfc.h>
#include <st_errno.h>
static inline const char* nfc_get_nfca_type(rfalNfcaListenDeviceType type) {
if(type == RFAL_NFCA_T1T) {
return "T1T";
} else if(type == RFAL_NFCA_T2T) {
return "T2T";
} else if(type == RFAL_NFCA_T4T) {
return "T4T";
} else if(type == RFAL_NFCA_NFCDEP) {
return "NFCDEP";
} else if(type == RFAL_NFCA_T4T_NFCDEP) {
return "T4T_NFCDEP";
} else {
return "Unknown";
}
}
typedef enum {
NfcDeviceTypeNfca,
NfcDeviceTypeNfcb,
NfcDeviceTypeNfcf,
NfcDeviceTypeNfcv,
NfcDeviceTypeNfcMifare
} NfcDeviceType;
typedef struct {
NfcDeviceType type;
union {
rfalNfcaListenDevice nfca;
rfalNfcbListenDevice nfcb;
rfalNfcfListenDevice nfcf;
rfalNfcvListenDevice nfcv;
};
} NfcDevice;
typedef enum {
// Init states
NfcWorkerStateNone,
NfcWorkerStateBroken,
NfcWorkerStateReady,
// Main worker states
NfcWorkerStatePoll,
NfcWorkerStateEmulate,
NfcWorkerStateField,
// Transition
NfcWorkerStateStop,
} NfcWorkerState;
typedef enum {
NfcMessageTypeDetect,
NfcMessageTypeEmulate,
NfcMessageTypeField,
NfcMessageTypeStop,
// From Worker
NfcMessageTypeDeviceFound,
NfcMessageTypeDeviceNotFound,
} NfcMessageType;
typedef struct {
NfcMessageType type;
union {
NfcDevice device;
};
} NfcMessage;

View File

@ -0,0 +1,147 @@
#include "nfc_views.h"
void nfc_view_read_draw(Canvas* canvas, void* model) {
NfcViewReadModel* m = model;
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
if(m->found) {
if(m->device.type == NfcDeviceTypeNfca) {
nfc_view_read_nfca_draw(canvas, m);
} else if(m->device.type == NfcDeviceTypeNfcb) {
nfc_view_read_nfcb_draw(canvas, m);
} else if(m->device.type == NfcDeviceTypeNfcv) {
nfc_view_read_nfcv_draw(canvas, m);
} else if(m->device.type == NfcDeviceTypeNfcf) {
nfc_view_read_nfcf_draw(canvas, m);
}
} else {
canvas_draw_str(canvas, 0, 12, "Searching");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 22, "Place card to the back");
}
}
void nfc_view_read_nfca_draw(Canvas* canvas, NfcViewReadModel* model) {
char buffer[32];
canvas_draw_str(canvas, 0, 12, "Found NFC-A");
canvas_set_font(canvas, FontSecondary);
snprintf(buffer, sizeof(buffer), "Type: %s", nfc_get_nfca_type(model->device.nfca.type));
canvas_draw_str(canvas, 2, 22, buffer);
snprintf(buffer, sizeof(buffer), "UID length: %d", model->device.nfca.nfcId1Len);
canvas_draw_str(canvas, 2, 32, buffer);
canvas_draw_str(canvas, 2, 42, "UID:");
for(uint8_t i = 0; i < model->device.nfca.nfcId1Len; i++) {
snprintf(buffer + (i * 2), sizeof(buffer) - (i * 2), "%02X", model->device.nfca.nfcId1[i]);
}
buffer[model->device.nfca.nfcId1Len * 2] = 0;
canvas_draw_str(canvas, 18, 42, buffer);
snprintf(
buffer,
sizeof(buffer),
"SAK: %02X ATQA: %02X/%02X",
model->device.nfca.selRes.sak,
model->device.nfca.sensRes.anticollisionInfo,
model->device.nfca.sensRes.platformInfo);
canvas_draw_str(canvas, 2, 52, buffer);
}
void nfc_view_read_nfcb_draw(Canvas* canvas, NfcViewReadModel* model) {
char buffer[32];
canvas_draw_str(canvas, 0, 12, "Found NFC-B");
canvas_set_font(canvas, FontSecondary);
snprintf(buffer, sizeof(buffer), "UID length: %d", RFAL_NFCB_NFCID0_LEN);
canvas_draw_str(canvas, 2, 32, buffer);
canvas_draw_str(canvas, 2, 42, "UID:");
for(uint8_t i = 0; i < RFAL_NFCB_NFCID0_LEN; i++) {
snprintf(
buffer + (i * 2),
sizeof(buffer) - (i * 2),
"%02X",
model->device.nfcb.sensbRes.nfcid0[i]);
}
buffer[RFAL_NFCB_NFCID0_LEN * 2] = 0;
canvas_draw_str(canvas, 18, 42, buffer);
}
void nfc_view_read_nfcf_draw(Canvas* canvas, NfcViewReadModel* model) {
char buffer[32];
canvas_draw_str(canvas, 0, 12, "Found NFC-F");
canvas_set_font(canvas, FontSecondary);
snprintf(buffer, sizeof(buffer), "UID length: %d", RFAL_NFCF_NFCID2_LEN);
canvas_draw_str(canvas, 2, 32, buffer);
canvas_draw_str(canvas, 2, 42, "UID:");
for(uint8_t i = 0; i < RFAL_NFCF_NFCID2_LEN; i++) {
snprintf(
buffer + (i * 2),
sizeof(buffer) - (i * 2),
"%02X",
model->device.nfcf.sensfRes.NFCID2[i]);
}
buffer[RFAL_NFCF_NFCID2_LEN * 2] = 0;
canvas_draw_str(canvas, 18, 42, buffer);
}
void nfc_view_read_nfcv_draw(Canvas* canvas, NfcViewReadModel* model) {
char buffer[32];
canvas_draw_str(canvas, 0, 12, "Found NFC-V");
canvas_set_font(canvas, FontSecondary);
snprintf(buffer, sizeof(buffer), "UID length: %d", RFAL_NFCV_UID_LEN);
canvas_draw_str(canvas, 2, 32, buffer);
canvas_draw_str(canvas, 2, 42, "UID:");
for(uint8_t i = 0; i < RFAL_NFCV_UID_LEN; i++) {
snprintf(
buffer + (i * 2), sizeof(buffer) - (i * 2), "%02X", model->device.nfcv.InvRes.UID[i]);
}
buffer[RFAL_NFCV_UID_LEN * 2] = 0;
canvas_draw_str(canvas, 18, 42, buffer);
}
void nfc_view_emulate_draw(Canvas* canvas, void* model) {
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 0, 12, "Emulating NFC-A");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 22, "Type: T2T");
canvas_draw_str(canvas, 2, 32, "UID length: 7");
canvas_draw_str(canvas, 2, 42, "UID: 00010203040506");
canvas_draw_str(canvas, 2, 52, "SAK: 00 ATQA: 44/00");
}
void nfc_view_field_draw(Canvas* canvas, void* model) {
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 0, 12, "Field ON");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 22, "TX/RX is disabled");
}
void nfc_view_error_draw(Canvas* canvas, void* model) {
NfcViewErrorModel* m = model;
char buffer[32];
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
snprintf(buffer, sizeof(buffer), "Error: %d", m->error);
canvas_draw_str(canvas, 0, 12, buffer);
canvas_set_font(canvas, FontSecondary);
if(m->error == ERR_WRONG_STATE) {
canvas_draw_str(canvas, 2, 22, "Wrong State");
} else if(m->error == ERR_PARAM) {
canvas_draw_str(canvas, 2, 22, "Wrong Param");
} else if(m->error == ERR_HW_MISMATCH) {
canvas_draw_str(canvas, 2, 22, "HW mismatch");
} else if(m->error == ERR_IO) {
canvas_draw_str(canvas, 2, 22, "IO Error");
} else {
canvas_draw_str(canvas, 2, 22, "Details in st_errno.h");
}
}

View File

@ -0,0 +1,36 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <gui/canvas.h>
#include <flipper_v2.h>
#include "nfc_types.h"
typedef enum {
NfcViewRead,
NfcViewEmulate,
NfcViewField,
NfcViewError,
} NfcView;
typedef struct {
bool found;
NfcDevice device;
} NfcViewReadModel;
void nfc_view_read_draw(Canvas* canvas, void* model);
void nfc_view_read_nfca_draw(Canvas* canvas, NfcViewReadModel* model);
void nfc_view_read_nfcb_draw(Canvas* canvas, NfcViewReadModel* model);
void nfc_view_read_nfcf_draw(Canvas* canvas, NfcViewReadModel* model);
void nfc_view_read_nfcv_draw(Canvas* canvas, NfcViewReadModel* model);
void nfc_view_emulate_draw(Canvas* canvas, void* model);
void nfc_view_field_draw(Canvas* canvas, void* model);
typedef struct {
ReturnCode error;
} NfcViewErrorModel;
void nfc_view_error_draw(Canvas* canvas, void* model);

View File

@ -1,108 +1,320 @@
#include "nfc_worker.h"
#include "nfc.h"
#include "nfc_i.h"
#include "nfc_worker_i.h"
#define EXAMPLE_NFCA_DEVICES 5
// TODO replace with pubsub
static bool isr_enabled = false;
void nfc_isr() {
if(isr_enabled) {
st25r3916Isr();
NfcWorker* nfc_worker_alloc(osMessageQueueId_t message_queue) {
NfcWorker* nfc_worker = furi_alloc(sizeof(NfcWorker));
nfc_worker->message_queue = message_queue;
// Worker thread attributes
nfc_worker->thread_attr.name = "nfc_worker";
nfc_worker->thread_attr.stack_size = 2048;
// Initialize rfal
rfalAnalogConfigInitialize();
nfc_worker->error = rfalNfcInitialize();
if(nfc_worker->error == ERR_NONE) {
rfalLowPowerModeStart();
nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
} else {
nfc_worker_change_state(nfc_worker, NfcWorkerStateBroken);
}
return nfc_worker;
}
NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker) {
return nfc_worker->state;
}
ReturnCode nfc_worker_get_error(NfcWorker* nfc_worker) {
return nfc_worker->error;
}
void nfc_worker_free(NfcWorker* nfc_worker) {
furi_assert(nfc_worker);
}
void nfc_worker_start(NfcWorker* nfc_worker, NfcWorkerState state) {
furi_assert(nfc_worker);
furi_assert(nfc_worker->state == NfcWorkerStateReady);
nfc_worker_change_state(nfc_worker, state);
nfc_worker->thread = osThreadNew(nfc_worker_task, nfc_worker, &nfc_worker->thread_attr);
}
void nfc_worker_stop(NfcWorker* nfc_worker) {
furi_assert(nfc_worker);
if(nfc_worker->state == NfcWorkerStateBroken) {
return;
}
nfc_worker_change_state(nfc_worker, NfcWorkerStateStop);
}
void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) {
nfc_worker->state = state;
}
void nfc_worker_task(void* context) {
Nfc* nfc = context;
ReturnCode err;
rfalNfcaSensRes sensRes;
rfalNfcaSelRes selRes;
rfalNfcaListenDevice nfcaDevList[EXAMPLE_NFCA_DEVICES];
uint8_t devCnt;
uint8_t devIt;
NfcWorker* nfc_worker = context;
rfalLowPowerModeStop();
if(nfc_worker->state == NfcWorkerStatePoll) {
nfc_worker_poll(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateEmulate) {
nfc_worker_emulate(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateField) {
nfc_worker_field(nfc_worker);
}
rfalLowPowerModeStart();
isr_enabled = true;
nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
while(widget_is_enabled(nfc->widget)) {
osThreadExit();
}
void nfc_worker_poll(NfcWorker* nfc_worker) {
while(nfc_worker->state == NfcWorkerStatePoll) {
bool is_found = false;
is_found |= nfc_worker_nfca_poll(nfc_worker);
is_found |= nfc_worker_nfcb_poll(nfc_worker);
is_found |= nfc_worker_nfcf_poll(nfc_worker);
is_found |= nfc_worker_nfcv_poll(nfc_worker);
rfalFieldOff();
platformDelay(500);
nfc->current = "Not detected";
nfc->devCnt = 0;
rfalNfcaPollerInitialize();
rfalFieldOnAndStartGT();
nfc->ret = err = rfalNfcaPollerTechnologyDetection(RFAL_COMPLIANCE_MODE_NFC, &sensRes);
if(err == ERR_NONE) {
err = rfalNfcaPollerFullCollisionResolution(
RFAL_COMPLIANCE_MODE_NFC, EXAMPLE_NFCA_DEVICES, nfcaDevList, &devCnt);
nfc->devCnt = devCnt;
if((err == ERR_NONE) && (devCnt > 0)) {
platformLog("NFC-A device(s) found %d\r\n", devCnt);
devIt = 0;
if(nfcaDevList[devIt].isSleep) {
err = rfalNfcaPollerCheckPresence(
RFAL_14443A_SHORTFRAME_CMD_WUPA, &sensRes); /* Wake up all cards */
if(err != ERR_NONE) {
continue;
}
err = rfalNfcaPollerSelect(
nfcaDevList[devIt].nfcId1,
nfcaDevList[devIt].nfcId1Len,
&selRes); /* Select specific device */
if(err != ERR_NONE) {
continue;
}
}
nfc->first_atqa = nfcaDevList[devIt].sensRes;
nfc->first_sak = nfcaDevList[devIt].selRes;
switch(nfcaDevList[devIt].type) {
case RFAL_NFCA_T1T:
/* No further activation needed for a T1T (RID already performed)*/
platformLog(
"NFC-A T1T device found \r\n"); /* NFC-A T1T device found, NFCID/UID is contained in: t1tRidRes.uid */
nfc->current = "NFC-A T1T";
/* Following communications shall be performed using:
* - Non blocking: rfalStartTransceive() + rfalGetTransceiveState()
* - Blocking: rfalTransceiveBlockingTx() + rfalTransceiveBlockingRx() or rfalTransceiveBlockingTxRx() */
break;
case RFAL_NFCA_T2T:
/* No specific activation needed for a T2T */
platformLog(
"NFC-A T2T device found \r\n"); /* NFC-A T2T device found, NFCID/UID is contained in: nfcaDev.nfcid */
nfc->current = "NFC-A T2T";
/* Following communications shall be performed using:
* - Non blocking: rfalStartTransceive() + rfalGetTransceiveState()
* - Blocking: rfalTransceiveBlockingTx() + rfalTransceiveBlockingRx() or rfalTransceiveBlockingTxRx() */
break;
case RFAL_NFCA_T4T:
platformLog(
"NFC-A T4T (ISO-DEP) device found \r\n"); /* NFC-A T4T device found, NFCID/UID is contained in: nfcaDev.nfcid */
nfc->current = "NFC-A T4T";
/* Activation should continue using rfalIsoDepPollAHandleActivation(), see exampleRfalPoller.c */
break;
case RFAL_NFCA_T4T_NFCDEP: /* Device supports T4T and NFC-DEP */
case RFAL_NFCA_NFCDEP: /* Device supports NFC-DEP */
platformLog(
"NFC-A P2P (NFC-DEP) device found \r\n"); /* NFC-A P2P device found, NFCID/UID is contained in: nfcaDev.nfcid */
nfc->current = "NFC-A P2P";
/* Activation should continue using rfalNfcDepInitiatorHandleActivation(), see exampleRfalPoller.c */
break;
}
rfalNfcaPollerSleep(); /* Put device to sleep / HLTA (useless as the field will be turned off anyhow) */
}
if(!is_found) {
NfcMessage message;
message.type = NfcMessageTypeDeviceNotFound;
furi_check(
osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK);
}
widget_update(nfc->widget);
platformDelay(333);
}
}
bool nfc_worker_nfca_poll(NfcWorker* nfc_worker) {
ReturnCode ret;
rfalNfcaSensRes sense_res;
rfalNfcaPollerInitialize();
rfalFieldOnAndStartGT();
ret = rfalNfcaPollerTechnologyDetection(RFAL_COMPLIANCE_MODE_NFC, &sense_res);
if(ret != ERR_NONE) {
return false;
}
isr_enabled = false;
rfalFieldOff();
rfalLowPowerModeStart();
nfc->ret = ERR_NONE;
nfc->worker = NULL;
osThreadExit();
}
uint8_t dev_cnt;
rfalNfcaListenDevice device;
ret = rfalNfcaPollerFullCollisionResolution(RFAL_COMPLIANCE_MODE_NFC, 1, &device, &dev_cnt);
if(ret != ERR_NONE) {
return false;
}
if(dev_cnt) {
rfalNfcaPollerSleep();
NfcMessage message;
message.type = NfcMessageTypeDeviceFound;
message.device.type = NfcDeviceTypeNfca;
message.device.nfca = device;
furi_check(
osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK);
return true;
}
return false;
}
bool nfc_worker_nfcb_poll(NfcWorker* nfc_worker) {
ReturnCode ret;
rfalNfcbPollerInitialize();
rfalFieldOnAndStartGT();
rfalNfcbSensbRes sensb_res;
uint8_t sensb_res_len;
ret = rfalNfcbPollerTechnologyDetection(RFAL_COMPLIANCE_MODE_NFC, &sensb_res, &sensb_res_len);
if(ret != ERR_NONE) {
return false;
}
uint8_t dev_cnt;
rfalNfcbListenDevice device;
ret = rfalNfcbPollerCollisionResolution(RFAL_COMPLIANCE_MODE_NFC, 1, &device, &dev_cnt);
if(ret != ERR_NONE) {
return false;
}
if(dev_cnt) {
rfalNfcbPollerSleep(device.sensbRes.nfcid0);
NfcMessage message;
message.type = NfcMessageTypeDeviceFound;
message.device.type = NfcDeviceTypeNfcb;
message.device.nfcb = device;
furi_check(
osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK);
return true;
}
return false;
}
bool nfc_worker_nfcf_poll(NfcWorker* nfc_worker) {
ReturnCode ret;
rfalNfcfPollerInitialize(RFAL_BR_212);
rfalFieldOnAndStartGT();
ret = rfalNfcfPollerCheckPresence();
if(ret != ERR_NONE) {
return false;
}
uint8_t dev_cnt;
rfalNfcfListenDevice device;
ret = rfalNfcfPollerCollisionResolution(RFAL_COMPLIANCE_MODE_NFC, 1, &device, &dev_cnt);
if(ret != ERR_NONE) {
return false;
}
if(dev_cnt) {
NfcMessage message;
message.type = NfcMessageTypeDeviceFound;
message.device.type = NfcDeviceTypeNfcf;
message.device.nfcf = device;
furi_check(
osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK);
return true;
}
return false;
}
bool nfc_worker_nfcv_poll(NfcWorker* nfc_worker) {
ReturnCode ret;
rfalNfcvInventoryRes invRes;
rfalNfcvPollerInitialize();
rfalFieldOnAndStartGT();
ret = rfalNfcvPollerCheckPresence(&invRes);
if(ret != ERR_NONE) {
return false;
}
uint8_t dev_cnt;
rfalNfcvListenDevice device;
ret = rfalNfcvPollerCollisionResolution(RFAL_COMPLIANCE_MODE_NFC, 1, &device, &dev_cnt);
if(ret != ERR_NONE) {
return false;
}
if(dev_cnt) {
rfalNfcvPollerSleep(RFAL_NFCV_REQ_FLAG_DEFAULT, device.InvRes.UID);
NfcMessage message;
message.type = NfcMessageTypeDeviceFound;
message.device.type = NfcDeviceTypeNfcv;
message.device.nfcv = device;
furi_check(
osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK);
return true;
}
return false;
}
void nfc_worker_state_callback(rfalNfcState st) {
(void)st;
}
ReturnCode nfc_worker_trx(
uint8_t* txBuf,
uint16_t txBufSize,
uint8_t** rxData,
uint16_t** rcvLen,
uint32_t fwt) {
ReturnCode err;
err = rfalNfcDataExchangeStart(txBuf, txBufSize, rxData, rcvLen, fwt);
if(err == ERR_NONE) {
do {
rfalNfcWorker();
err = rfalNfcDataExchangeGetStatus();
} while(err == ERR_BUSY);
}
return err;
}
void nfc_worker_exchange(NfcWorker* nfc_worker, rfalNfcDevice* nfc_device) {
ReturnCode err;
uint8_t* rxData;
uint16_t* rcvLen;
uint8_t txBuf[100];
uint16_t txLen;
do {
rfalNfcWorker();
switch(rfalNfcGetState()) {
case RFAL_NFC_STATE_ACTIVATED:
err = nfc_worker_trx(NULL, 0, &rxData, &rcvLen, 0);
break;
case RFAL_NFC_STATE_DATAEXCHANGE:
case RFAL_NFC_STATE_DATAEXCHANGE_DONE:
// Not supported
txBuf[0] = ((char)0x68);
txBuf[1] = ((char)0x00);
txLen = 2;
err = nfc_worker_trx(txBuf, txLen, &rxData, &rcvLen, RFAL_FWT_NONE);
break;
case RFAL_NFC_STATE_START_DISCOVERY:
return;
case RFAL_NFC_STATE_LISTEN_SLEEP:
default:
break;
}
} while((err == ERR_NONE) || (err == ERR_SLEEP_REQ));
}
void nfc_worker_emulate(NfcWorker* nfc_worker) {
rfalNfcDiscoverParam params;
params.compMode = RFAL_COMPLIANCE_MODE_NFC;
params.techs2Find = RFAL_NFC_LISTEN_TECH_A;
params.totalDuration = 1000U;
params.devLimit = 1;
params.wakeupEnabled = false;
params.wakeupConfigDefault = true;
params.nfcfBR = RFAL_BR_212;
params.ap2pBR = RFAL_BR_424;
params.maxBR = RFAL_BR_KEEP;
params.GBLen = RFAL_NFCDEP_GB_MAX_LEN;
params.notifyCb = nfc_worker_state_callback;
params.lmConfigPA.nfcidLen = RFAL_LM_NFCID_LEN_07;
params.lmConfigPA.nfcid[0] = 0x00;
params.lmConfigPA.nfcid[1] = 0x01;
params.lmConfigPA.nfcid[2] = 0x02;
params.lmConfigPA.nfcid[3] = 0x03;
params.lmConfigPA.nfcid[4] = 0x04;
params.lmConfigPA.nfcid[5] = 0x05;
params.lmConfigPA.nfcid[6] = 0x06;
params.lmConfigPA.SENS_RES[0] = 0x44;
params.lmConfigPA.SENS_RES[1] = 0x00;
params.lmConfigPA.SEL_RES = 0x00;
ReturnCode ret;
ret = rfalNfcDiscover(&params);
if(ret != ERR_NONE) {
asm("bkpt 1");
return;
}
rfalNfcDevice* nfc_device;
while(nfc_worker->state == NfcWorkerStateEmulate) {
rfalNfcWorker();
if(rfalNfcIsDevActivated(rfalNfcGetState())) {
rfalNfcGetActiveDevice(&nfc_device);
nfc_worker_exchange(nfc_worker, nfc_device);
}
osDelay(10);
}
rfalNfcDeactivate(false);
}
void nfc_worker_field(NfcWorker* nfc_worker) {
st25r3916TxRxOn();
while(nfc_worker->state == NfcWorkerStateField) {
osDelay(50);
}
st25r3916TxRxOff();
}

View File

@ -1,3 +1,15 @@
#pragma once
void nfc_worker_task(void* context);
typedef struct NfcWorker NfcWorker;
NfcWorker* nfc_worker_alloc(osMessageQueueId_t message_queue);
NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker);
ReturnCode nfc_worker_get_error(NfcWorker* nfc_worker);
void nfc_worker_free(NfcWorker* nfc_worker);
void nfc_worker_start(NfcWorker* nfc_worker, NfcWorkerState state);
void nfc_worker_stop(NfcWorker* nfc_worker);

View File

@ -0,0 +1,41 @@
#pragma once
#include "nfc_types.h"
#include "nfc_worker.h"
#include <flipper_v2.h>
#include <cmsis_os2.h>
#include <stdbool.h>
#include <rfal_analogConfig.h>
#include <rfal_rf.h>
#include <rfal_nfc.h>
#include <rfal_nfca.h>
#include <rfal_nfcb.h>
#include <rfal_nfcf.h>
#include <rfal_nfcv.h>
#include <st25r3916.h>
#include <st25r3916_irq.h>
struct NfcWorker {
osMessageQueueId_t message_queue;
osThreadAttr_t thread_attr;
osThreadId_t thread;
NfcWorkerState state;
ReturnCode error;
};
void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state);
void nfc_worker_task(void* context);
void nfc_worker_poll(NfcWorker* nfc_worker);
bool nfc_worker_nfca_poll(NfcWorker* nfc_worker);
bool nfc_worker_nfcb_poll(NfcWorker* nfc_worker);
bool nfc_worker_nfcf_poll(NfcWorker* nfc_worker);
bool nfc_worker_nfcv_poll(NfcWorker* nfc_worker);
void nfc_worker_emulate(NfcWorker* nfc_worker);
void nfc_worker_field(NfcWorker* nfc_worker);

View File

@ -16,8 +16,10 @@ void api_hal_bt_dump_state(string_t buffer);
/* Get BT/BLE system component state */
bool api_hal_bt_is_alive();
/* Lock shared access to flash controller */
void api_hal_bt_lock_flash();
/* Lock shared access to flash controller
* @return true if lock was successful, false if not
*/
bool api_hal_bt_lock_flash();
/* Unlock shared access to flash controller */
void api_hal_bt_unlock_flash();

View File

@ -223,13 +223,6 @@ void SystemClock_Config(void)
Error_Handler();
}
/* USER CODE BEGIN Smps */
if (!LL_RCC_LSE_IsReady()) {
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
NVIC_SystemReset();
}
/* USER CODE END Smps */
/** Enables the Clock Security System
*/
@ -272,7 +265,7 @@ void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
asm("bkpt 1");
/* USER CODE END Error_Handler_Debug */
}

View File

@ -39,34 +39,40 @@ bool api_hal_bt_is_alive() {
}
bool api_hal_bt_wait_transition() {
if (APPE_Status() == BleGlueStatusUninitialized) {
return false;
}
while (APPE_Status() != BleGlueStatusStarted) {
osDelay(1);
uint8_t counter = 0;
while (APPE_Status() == BleGlueStatusStartup) {
osDelay(10);
counter++;
if (counter > 1000) {
return false;
}
}
return true;
}
void api_hal_bt_lock_flash() {
bool api_hal_bt_lock_flash() {
if (!api_hal_bt_wait_transition()) {
return false;
}
if (APPE_Status() == BleGlueStatusUninitialized) {
HAL_FLASH_Unlock();
return;
} else {
while (HAL_HSEM_FastTake(CFG_HW_FLASH_SEMID) != HAL_OK) {
osDelay(1);
}
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);
HAL_FLASH_Unlock();
while(LL_FLASH_IsOperationSuspended()) {};
}
while (HAL_HSEM_FastTake(CFG_HW_FLASH_SEMID) != HAL_OK) {
osDelay(1);
}
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);
HAL_FLASH_Unlock();
while(LL_FLASH_IsOperationSuspended()) {};
return true;
}
void api_hal_bt_unlock_flash() {
if (!api_hal_bt_wait_transition()) {
if (APPE_Status() == BleGlueStatusUninitialized) {
HAL_FLASH_Lock();
return;
} else {
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF);
HAL_FLASH_Lock();
HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_CPU1_COREID);
}
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF);
HAL_FLASH_Lock();
HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_CPU1_COREID);
}

View File

@ -3,7 +3,9 @@
#include <stm32wbxx.h>
bool api_hal_flash_erase(uint8_t page, uint8_t count) {
api_hal_bt_lock_flash();
if (!api_hal_bt_lock_flash()) {
return false;
}
FLASH_EraseInitTypeDef erase;
erase.TypeErase = FLASH_TYPEERASE_PAGES;
erase.Page = page;
@ -15,14 +17,18 @@ bool api_hal_flash_erase(uint8_t page, uint8_t count) {
}
bool api_hal_flash_write_dword(size_t address, uint64_t data) {
api_hal_bt_lock_flash();
if (!api_hal_bt_lock_flash()) {
return false;
}
HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data);
api_hal_bt_unlock_flash();
return status == HAL_OK;
}
bool api_hal_flash_write_row(size_t address, size_t source_address) {
api_hal_bt_lock_flash();
if (!api_hal_bt_lock_flash()) {
return false;
}
HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, address, source_address);
api_hal_bt_unlock_flash();
return status == HAL_OK;

View File

@ -129,7 +129,7 @@ static void AdvUpdateProcess(void *argument);
static void Adv_Update( void );
void APP_BLE_Init() {
bool APP_BLE_Init() {
SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = {
{{0,0,0}}, /**< Header unused */
{0, /** pBleBufferAddress not used */
@ -158,7 +158,7 @@ void APP_BLE_Init() {
HciUserEvtProcessId = osThreadNew(HciUserEvtProcess, NULL, &HciUserEvtProcess_attr);
// Starts the BLE Stack on CPU2
if (SHCI_C2_BLE_Init( &ble_init_cmd_packet ) != SHCI_Success) {
Error_Handler();
return false;
}
// Initialization of HCI & GATT & GAP layer
Ble_Hci_Gap_Gatt_Init();
@ -191,6 +191,7 @@ void APP_BLE_Init() {
AdvIntervalMax = CFG_FAST_CONN_ADV_INTERVAL_MAX;
Adv_Request(APP_BLE_FAST_ADV);
return true;
}
SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt )

View File

@ -4,6 +4,7 @@
extern "C" {
#endif
#include <stdbool.h>
#include "hci_tl.h"
typedef enum {
@ -16,7 +17,7 @@ typedef enum {
APP_BLE_CONNECTED_CLIENT
} APP_BLE_ConnStatus_t;
void APP_BLE_Init();
bool APP_BLE_Init();
APP_BLE_ConnStatus_t APP_BLE_Get_Server_Connection_Status();

View File

@ -136,8 +136,12 @@ static void APPE_SysUserEvtRx( void * pPayload ) {
UNUSED(pPayload);
/* Traces channel initialization */
// APPD_EnableCPU2( );
ble_glue_status = BleGlueStatusStarted;
APP_BLE_Init( );
if (APP_BLE_Init()) {
ble_glue_status = BleGlueStatusStarted;
} else {
ble_glue_status = BleGlueStatusBroken;
}
}
/*************************************************************

View File

@ -7,6 +7,7 @@ extern "C" {
typedef enum {
BleGlueStatusUninitialized,
BleGlueStatusStartup,
BleGlueStatusBroken,
BleGlueStatusStarted
} BleGlueStatus;

View File

@ -1,7 +1,34 @@
#include "platform.h"
#include <assert.h>
#include <main.h>
#include <spi.h>
#include <api-hal-spi.h>
static osThreadAttr_t platform_irq_thread_attr;
static volatile osThreadId_t platform_irq_thread_id = NULL;
static volatile PlatformIrqCallback platform_irq_callback = NULL;
void nfc_isr() {
if(platform_irq_callback && platformGpioIsHigh( ST25R_INT_PORT, ST25R_INT_PIN )) {
osThreadFlagsSet(platform_irq_thread_id, 0x1);
}
}
void platformIrqWorker() {
while(1) {
uint32_t flags = osThreadFlagsWait(0x1, osFlagsWaitAny, osWaitForever);
if (flags & 0x1) {
platform_irq_callback();
}
}
}
void platformSetIrqCallback(PlatformIrqCallback callback) {
platform_irq_callback = callback;
platform_irq_thread_attr.name = "rfal_irq_worker";
platform_irq_thread_attr.stack_size = 512;
platform_irq_thread_attr.priority = osPriorityISR;
platform_irq_thread_id = osThreadNew(platformIrqWorker, NULL, &platform_irq_thread_attr);
}
HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len) {
HAL_StatusTypeDef ret;
@ -14,18 +41,17 @@ HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t
}
if(ret != HAL_OK) {
exit(250);
asm("bkpt 1");
exit(255);
}
return ret;
}
void platformProtectST25RComm()
{
void platformProtectST25RComm() {
api_hal_spi_lock(&SPI_R);
NFC_SPI_Reconfigure();
}
void platformUnprotectST25RComm()
{
void platformUnprotectST25RComm() {
api_hal_spi_unlock(&SPI_R);
}

View File

@ -11,6 +11,9 @@
#include "spi.h"
#include "main.h"
typedef void (*PlatformIrqCallback)();
void platformSetIrqCallback(PlatformIrqCallback cb);
HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len);
void platformProtectST25RComm();
void platformUnprotectST25RComm();
@ -21,8 +24,8 @@ void platformUnprotectST25RComm();
#define ST25R_INT_PIN NFC_IRQ_Pin
#define ST25R_INT_PORT NFC_IRQ_GPIO_Port
#define PLATFORM_LED_RX_PIN LED_GREEN_Pin
#define PLATFORM_LED_RX_PORT LED_GREEN_GPIO_Port
#define PLATFORM_LED_RX_PIN LED_RED_Pin
#define PLATFORM_LED_RX_PORT LED_RED_GPIO_Port
#define PLATFORM_LED_FIELD_PIN LED_BLUE_Pin
#define PLATFORM_LED_FIELD_PORT LED_BLUE_GPIO_Port
@ -52,6 +55,7 @@ void platformUnprotectST25RComm();
#define RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN 512U /*!< ISO-DEP APDU max length. */
#define RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN 512U /*!< NFC-DEP PDU max length. */
#define platformIrqST25RSetCallback( cb ) platformSetIrqCallback(cb)
#define platformProtectST25RIrqStatus() platformProtectST25RComm() /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */
#define platformUnprotectST25RIrqStatus() platformUnprotectST25RComm() /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */
@ -72,7 +76,7 @@ void platformUnprotectST25RComm();
#define platformGetSysTick() osKernelGetTickCount() /*!< Get System Tick (1 tick = 1 ms) */
#define platformAssert( exp ) assert_param( exp ) /*!< Asserts whether the given expression is true*/
#define platformErrorHandle() Error_Handler() /*!< Global error handle\trap */
// #define platformErrorHandle() Error_Handler() /*!< Global error handle\trap */
#define platformSpiSelect() platformGpioClear( ST25R_SS_PORT, ST25R_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Select */
#define platformSpiDeselect() platformGpioSet( ST25R_SS_PORT, ST25R_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Deselect */