From fb73d3bd523990808975873fb16d84c4a295ed38 Mon Sep 17 00:00:00 2001 From: gornekich Date: Thu, 6 May 2021 22:51:20 +0300 Subject: [PATCH] [FL-1214] NFC application (#448) * platform: include only used api-hal files * api-hal-nfc: introduce nfc hal * nfc_worker: rework nfc worker * nfc: move nfc from services to applications, add startup hook * api-hal-nfc: init nfc worker in api_hal_detect * nfc: rework nfc application * nfc: fix app exit * api-hal-nfc: init nfc worker only once --- applications/app-loader/app-loader.c | 5 + applications/applications.c | 22 +- applications/applications.h | 8 + applications/applications.mk | 16 +- applications/nfc/nfc.c | 277 +++++++++--------- applications/nfc/nfc_i.h | 15 +- applications/nfc/nfc_types.h | 23 +- applications/nfc/nfc_views.c | 8 - applications/nfc/nfc_views.h | 4 +- applications/nfc/nfc_worker.c | 195 +++--------- applications/nfc/nfc_worker_i.h | 6 +- .../targets/api-hal-include/api-hal-nfc.h | 49 ++++ firmware/targets/api-hal-include/api-hal.h | 1 + firmware/targets/f5/api-hal/api-hal-nfc.c | 83 ++++++ lib/ST25RFAL002/platform.h | 4 +- lib/lib.mk | 2 +- 16 files changed, 386 insertions(+), 332 deletions(-) mode change 100644 => 100755 applications/nfc/nfc.c create mode 100644 firmware/targets/api-hal-include/api-hal-nfc.h create mode 100644 firmware/targets/f5/api-hal/api-hal-nfc.c diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c index 8e1f87cb1..6b9e4171b 100644 --- a/applications/app-loader/app-loader.c +++ b/applications/app-loader/app-loader.c @@ -154,6 +154,11 @@ int32_t app_loader(void* p) { menu_item_add(menu, menu_debug); }); + // Call on start hooks + for(size_t i = 0; i < FLIPPER_ON_SYSTEM_START_COUNT; i++) { + (*FLIPPER_ON_SYSTEM_START[i])(); + } + FURI_LOG_I("APPLOADER", "OK"); while(1) { diff --git a/applications/applications.c b/applications/applications.c index f5920aa23..1647ccf18 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -1,5 +1,6 @@ #include "applications.h" +// Services and apps decalartion int32_t flipper_test_app(void* p); int32_t application_blink(void* p); int32_t application_uart_write(void* p); @@ -34,6 +35,9 @@ int32_t scene_app(void* p); int32_t passport(void* p); int32_t app_accessor(void* p); +// On system start hooks declaration +void nfc_cli_init(); + const FlipperApplication FLIPPER_SERVICES[] = { #ifdef SRV_CLI {.app = cli_task, .name = "cli_task", .stack_size = 2048, .icon = A_Plugins_14}, @@ -89,10 +93,6 @@ const FlipperApplication FLIPPER_SERVICES[] = { {.app = irda, .name = "irda", .stack_size = 1024, .icon = A_Plugins_14}, #endif -#ifdef SRV_NFC - {.app = nfc_task, .name = "nfc_task", .stack_size = 1024, .icon = A_Plugins_14}, -#endif - #ifdef SRV_EXAMPLE_QRCODE {.app = u8g2_qrcode, .name = "u8g2_qrcode", .stack_size = 1024, .icon = A_Plugins_14}, #endif @@ -158,6 +158,10 @@ const FlipperApplication FLIPPER_APPS[] = { {.app = app_lfrfid, .name = "125 kHz RFID", .stack_size = 1024, .icon = A_125khz_14}, #endif +#ifdef APP_NFC + {.app = nfc_task, .name = "NFC", .stack_size = 1024, .icon = A_NFC_14}, +#endif + #ifdef APP_IRDA {.app = irda, .name = "Infrared", .stack_size = 1024, .icon = A_Infrared_14}, #endif @@ -173,6 +177,16 @@ const FlipperApplication FLIPPER_APPS[] = { const size_t FLIPPER_APPS_COUNT = sizeof(FLIPPER_APPS) / sizeof(FlipperApplication); +// On system start hooks +const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = { +#ifdef APP_NFC + nfc_cli_init, +#endif +}; + +const size_t FLIPPER_ON_SYSTEM_START_COUNT = + sizeof(FLIPPER_ON_SYSTEM_START_COUNT) / sizeof(FlipperOnStartHook); + // Plugin menu const FlipperApplication FLIPPER_PLUGINS[] = { diff --git a/applications/applications.h b/applications/applications.h index 6d6363764..2ee66d3cc 100644 --- a/applications/applications.h +++ b/applications/applications.h @@ -10,6 +10,8 @@ typedef struct { const IconName icon; } FlipperApplication; +typedef void (*FlipperOnStartHook)(void); + /* Services list * Spawned on startup */ @@ -22,6 +24,12 @@ extern const size_t FLIPPER_SERVICES_COUNT; extern const FlipperApplication FLIPPER_APPS[]; extern const size_t FLIPPER_APPS_COUNT; +/* On system start hooks + * Called by app-loader, after OS initialization complete + */ +extern const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[]; +extern const size_t FLIPPER_ON_SYSTEM_START_COUNT; + /* Plugins list * Spawned by app-loader */ diff --git a/applications/applications.mk b/applications/applications.mk index 594d9ca3a..028f6f5d1 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -13,7 +13,6 @@ APP_RELEASE ?= 1 ifeq ($(APP_RELEASE), 1) # Main services SRV_MENU = 1 -SRV_NFC = 1 SRV_POWER = 1 SRV_BT = 1 SRV_CLI = 1 @@ -24,6 +23,7 @@ SRV_DOLPHIN = 1 APP_IRDA = 1 APP_SUBGHZ = 1 APP_LF_RFID = 1 +APP_NFC = 1 APP_GPIO_DEMO = 1 APP_MUSIC_PLAYER = 1 APP_FLOOPPER_BLOOPPER = 1 @@ -42,12 +42,6 @@ APP_EXAMPLE_INPUT_DUMP = 1 APP_UNIT_TESTS = 1 endif -SRV_NFC ?= 0 -ifeq ($(SRV_NFC), 1) -SRV_MENU = 1 -CFLAGS += -DSRV_NFC -endif - SRV_DOLPHIN ?= 0 ifeq ($(SRV_DOLPHIN), 1) SRV_MENU = 1 @@ -155,6 +149,14 @@ SRV_INPUT = 1 SRV_GUI = 1 endif +APP_NFC ?= 0 +ifeq ($(APP_NFC), 1) +CFLAGS += -DAPP_NFC +SRV_MENU = 1 +SRV_INPUT = 1 +SRV_GUI = 1 +endif + SRV_IRDA ?= 0 ifeq ($(SRV_IRDA), 1) CFLAGS += -DSRV_IRDA diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c old mode 100644 new mode 100755 index 2bcecc207..1cbf88a6d --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -1,143 +1,176 @@ #include "nfc_i.h" +#include "api-hal-nfc.h" -uint32_t nfc_view_exit(void* context) { - furi_assert(context); - Nfc* nfc = context; +osMessageQueueId_t message_queue = NULL; + +uint32_t nfc_view_stop(void* context) { + furi_assert(message_queue); NfcMessage message; message.type = NfcMessageTypeStop; - furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK); + furi_check(osMessageQueuePut(message_queue, &message, 0, osWaitForever) == osOK); + return NfcViewMenu; +} + +uint32_t nfc_view_exit(void* context) { + furi_assert(message_queue); + NfcMessage message; + message.type = NfcMessageTypeExit; + furi_check(osMessageQueuePut(message_queue, &message, 0, osWaitForever) == osOK); return VIEW_NONE; } +void nfc_menu_callback(void* context, uint32_t index) { + furi_assert(message_queue); + NfcMessage message; + if(index == 0) { + message.type = NfcMessageTypeDetect; + } else if(index == 1) { + message.type = NfcMessageTypeEmulate; + } else if(index == 2) { + message.type = NfcMessageTypeField; + } + furi_check(osMessageQueuePut(message_queue, &message, 0, osWaitForever) == osOK); +} + Nfc* nfc_alloc() { Nfc* nfc = furi_alloc(sizeof(Nfc)); - nfc->message_queue = osMessageQueueNew(8, sizeof(NfcMessage), NULL); - nfc->cli_message_queue = osMessageQueueNew(1, sizeof(NfcMessage), NULL); - nfc->worker = nfc_worker_alloc(nfc->message_queue); + message_queue = osMessageQueueNew(8, sizeof(NfcMessage), NULL); - nfc->icon = assets_icons_get(A_NFC_14); - nfc->menu_vm = furi_record_open("menu"); + nfc->worker = nfc_worker_alloc(message_queue); - nfc->menu = menu_item_alloc_menu("NFC", nfc->icon); - menu_item_subitem_add( - nfc->menu, menu_item_alloc_function("Detect", NULL, nfc_menu_detect_callback, nfc)); - menu_item_subitem_add( - nfc->menu, menu_item_alloc_function("Emulate", NULL, nfc_menu_emulate_callback, nfc)); - menu_item_subitem_add( - nfc->menu, menu_item_alloc_function("Field", NULL, nfc_menu_field_callback, nfc)); + // Open GUI record + nfc->gui = furi_record_open("gui"); + // View Dispatcher + nfc->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen); + + // Menu + nfc->submenu = submenu_alloc(); + submenu_add_item(nfc->submenu, "Detect", 0, nfc_menu_callback, nfc); + submenu_add_item(nfc->submenu, "Emulate", 1, nfc_menu_callback, nfc); + submenu_add_item(nfc->submenu, "Field", 2, nfc_menu_callback, nfc); + View* submenu_view = submenu_get_view(nfc->submenu); + view_set_previous_callback(submenu_view, nfc_view_exit); + view_dispatcher_add_view(nfc->view_dispatcher, NfcViewMenu, submenu_view); + + // Detect 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_set_previous_callback(nfc->view_detect, nfc_view_stop); view_allocate_model(nfc->view_detect, ViewModelTypeLocking, sizeof(NfcViewReadModel)); + view_dispatcher_add_view(nfc->view_dispatcher, NfcViewRead, nfc->view_detect); + + // Emulate 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); + view_set_previous_callback(nfc->view_emulate, nfc_view_stop); + view_dispatcher_add_view(nfc->view_dispatcher, NfcViewEmulate, nfc->view_emulate); + + // Field 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_cli = view_alloc(); - view_set_context(nfc->view_cli, nfc); - view_set_draw_callback(nfc->view_cli, nfc_view_cli_draw); + view_set_previous_callback(nfc->view_field, nfc_view_stop); + view_dispatcher_add_view(nfc->view_dispatcher, NfcViewField, nfc->view_field); + + // Error 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_set_previous_callback(nfc->view_error, nfc_view_stop); 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, NfcViewCli, nfc->view_cli); view_dispatcher_add_view(nfc->view_dispatcher, NfcViewError, nfc->view_error); + // Switch to menu + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + 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_free(Nfc* nfc) { + // Free nfc worker + nfc_worker_free(nfc->worker); + // Free allocated queue + osMessageQueueDelete(message_queue); + message_queue = NULL; -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); -} + // Free allocated views + // Menu + view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewMenu); + submenu_free(nfc->submenu); -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); -} + // Detect + view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewRead); + view_free(nfc->view_detect); -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); + // Emulate + view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewEmulate); + view_free(nfc->view_emulate); + + // Field + view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewField); + view_free(nfc->view_field); + + // Error + view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewError); + view_free(nfc->view_error); + + // Free View Dispatcher + view_dispatcher_free(nfc->view_dispatcher); + + // Close all opened records + furi_record_close("gui"); + nfc->gui = NULL; + + // Free nfc object + free(nfc); } void nfc_cli_detect(string_t args, void* context) { furi_assert(context); - Nfc* nfc = context; - NfcWorkerState state = nfc_worker_get_state(nfc->worker); - if(state != NfcWorkerStateReady) { + Cli* cli = context; + + // Check if nfc worker is not busy + if(api_hal_nfc_is_busy()) { printf("Nfc is busy"); return; } - NfcMessage message; - message.type = NfcMessageTypeDetectCliCmd; - furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK); - // Wait until nfc task send response - furi_check(osMessageQueueGet(nfc->cli_message_queue, &message, NULL, osWaitForever) == osOK); - if(message.type == NfcMessageTypeDeviceFound) { - if(message.device.type == NfcDeviceTypeNfca) { - printf( - "Found NFC-A, type: %s, UID length: %d, UID:", - nfc_get_nfca_type(message.device.nfca.type), - message.device.nfca.nfcId1Len); - for(uint8_t i = 0; i < message.device.nfca.nfcId1Len; i++) { - printf("%02X", message.device.nfca.nfcId1[i]); - } - printf( - " SAK: %02X ATQA: %02X/%02X", - message.device.nfca.selRes.sak, - message.device.nfca.sensRes.anticollisionInfo, - message.device.nfca.sensRes.platformInfo); - } else if(message.device.type == NfcDeviceTypeNfcb) { - printf("Found NFC-B, UID length: %d, UID:", RFAL_NFCB_NFCID0_LEN); - for(uint8_t i = 0; i < RFAL_NFCB_NFCID0_LEN; i++) { - printf("%02X", message.device.nfcb.sensbRes.nfcid0[i]); - } - } else if(message.device.type == NfcDeviceTypeNfcv) { - printf("Found NFC-V, UID length: %d, UID:", RFAL_NFCV_UID_LEN); - for(uint8_t i = 0; i < RFAL_NFCV_UID_LEN; i++) { - printf("%02X", message.device.nfcv.InvRes.UID[i]); - } - } else if(message.device.type == NfcDeviceTypeNfcf) { - printf("Found NFC-F, UID length: %d, UID:", RFAL_NFCF_NFCID2_LEN); - for(uint8_t i = 0; i < RFAL_NFCF_NFCID2_LEN; i++) { - printf("%02X", message.device.nfcf.sensfRes.NFCID2[i]); + rfalNfcDevice* dev_list; + uint8_t dev_cnt = 0; + bool cmd_exit = false; + api_hal_nfc_init(); + printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n"); + while(!cmd_exit) { + cmd_exit |= cli_cmd_interrupt_received(cli); + cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 100); + if(dev_cnt > 0) { + printf("Found %d devices\r\n", dev_cnt); + for(uint8_t i = 0; i < dev_cnt; i++) { + printf("%d found: %s ", i, nfc_get_dev_type(dev_list[i].type)); + if(dev_list[i].type == RFAL_NFC_LISTEN_TYPE_NFCA) { + printf("type: %s, ", nfc_get_nfca_type(dev_list[i].dev.nfca.type)); + } + printf("UID length: %d, UID:", dev_list[i].nfcidLen); + for(uint8_t j = 0; j < dev_list[i].nfcidLen; j++) { + printf("%02X", dev_list[i].nfcid[j]); + } + printf("\r\n"); } } - } else { - printf("Device not found"); + osDelay(50); } } +void nfc_cli_init() { + Cli* cli = furi_record_open("cli"); + cli_add_command(cli, "nfc_detect", nfc_cli_detect, cli); + furi_record_close("cli"); +} + void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) { NfcWorkerState state = nfc_worker_get_state(nfc->worker); if(state == NfcWorkerStateBroken) { @@ -156,22 +189,9 @@ void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) { int32_t nfc_task(void* p) { Nfc* nfc = nfc_alloc(); - Gui* gui = furi_record_open("gui"); - view_dispatcher_attach_to_gui(nfc->view_dispatcher, gui, ViewDispatcherTypeFullscreen); - - nfc->cli = furi_record_open("cli"); - if(nfc->cli) { - cli_add_command(nfc->cli, "nfc_detect", nfc_cli_detect, nfc); - } - - with_value_mutex( - nfc->menu_vm, (Menu * menu) { menu_item_add(menu, nfc->menu); }); - - furi_record_create("nfc", nfc); - NfcMessage message; while(1) { - furi_check(osMessageQueueGet(nfc->message_queue, &message, NULL, osWaitForever) == osOK); + furi_check(osMessageQueueGet(message_queue, &message, NULL, osWaitForever) == osOK); if(message.type == NfcMessageTypeDetect) { with_view_model( nfc->view_detect, (NfcViewReadModel * model) { @@ -179,8 +199,6 @@ int32_t nfc_task(void* p) { return true; }); nfc_start(nfc, NfcViewRead, NfcWorkerStatePoll); - } else if(message.type == NfcMessageTypeDetectCliCmd) { - nfc_start(nfc, NfcViewCli, NfcWorkerStatePollOnce); } else if(message.type == NfcMessageTypeEmulate) { nfc_start(nfc, NfcViewEmulate, NfcWorkerStateEmulate); } else if(message.type == NfcMessageTypeField) { @@ -188,34 +206,21 @@ int32_t nfc_task(void* p) { } else if(message.type == NfcMessageTypeStop) { nfc_worker_stop(nfc->worker); } else if(message.type == NfcMessageTypeDeviceFound) { - NfcWorkerState state = nfc_worker_get_state(nfc->worker); - if(state == NfcWorkerStatePollOnce) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, VIEW_NONE); - furi_check( - osMessageQueuePut(nfc->cli_message_queue, &message, 0, osWaitForever) == osOK); - nfc_worker_stop(nfc->worker); - } else { - with_view_model( - nfc->view_detect, (NfcViewReadModel * model) { - model->found = true; - model->device = message.device; - return true; - }); - } + with_view_model( + nfc->view_detect, (NfcViewReadModel * model) { + model->found = true; + model->device = message.device; + return true; + }); } else if(message.type == NfcMessageTypeDeviceNotFound) { - NfcWorkerState state = nfc_worker_get_state(nfc->worker); - if(state == NfcWorkerStatePollOnce) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, VIEW_NONE); - furi_check( - osMessageQueuePut(nfc->cli_message_queue, &message, 0, osWaitForever) == osOK); - nfc_worker_stop(nfc->worker); - } else { - with_view_model( - nfc->view_detect, (NfcViewReadModel * model) { - model->found = false; - return true; - }); - } + with_view_model( + nfc->view_detect, (NfcViewReadModel * model) { + model->found = false; + return true; + }); + } else if(message.type == NfcMessageTypeExit) { + nfc_free(nfc); + break; } } diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 30be84424..e3d139db9 100644 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -15,17 +15,16 @@ #include #include +#include struct Nfc { osMessageQueueId_t message_queue; - osMessageQueueId_t cli_message_queue; NfcWorker* worker; - ValueMutex* menu_vm; - MenuItem* menu; - Icon* icon; - Cli* cli; + Gui* gui; + + Submenu* submenu; View* view_detect; View* view_emulate; @@ -37,12 +36,6 @@ struct Nfc { 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); int32_t nfc_task(void* p); \ No newline at end of file diff --git a/applications/nfc/nfc_types.h b/applications/nfc/nfc_types.h index befc1f50e..ab4b10fab 100644 --- a/applications/nfc/nfc_types.h +++ b/applications/nfc/nfc_types.h @@ -3,6 +3,26 @@ #include #include +static inline const char* nfc_get_dev_type(rfalNfcDevType type) { + if(type == RFAL_NFC_LISTEN_TYPE_NFCA) { + return "NFC-A"; + } else if(type == RFAL_NFC_LISTEN_TYPE_NFCB) { + return "NFC-B"; + } else if(type == RFAL_NFC_LISTEN_TYPE_NFCF) { + return "NFC-F"; + } else if(type == RFAL_NFC_LISTEN_TYPE_NFCB) { + return "NFC-B"; + } else if(type == RFAL_NFC_LISTEN_TYPE_NFCV) { + return "NFC-V"; + } else if(type == RFAL_NFC_LISTEN_TYPE_ST25TB) { + return "NFC-ST25TB"; + } else if(type == RFAL_NFC_LISTEN_TYPE_AP2P) { + return "NFC-AP2P"; + } else { + return "Unknown"; + } +} + static inline const char* nfc_get_nfca_type(rfalNfcaListenDeviceType type) { if(type == RFAL_NFCA_T1T) { return "T1T"; @@ -44,7 +64,6 @@ typedef enum { NfcWorkerStateReady, // Main worker states NfcWorkerStatePoll, - NfcWorkerStatePollOnce, NfcWorkerStateEmulate, NfcWorkerStateField, // Transition @@ -53,10 +72,10 @@ typedef enum { typedef enum { NfcMessageTypeDetect, - NfcMessageTypeDetectCliCmd, NfcMessageTypeEmulate, NfcMessageTypeField, NfcMessageTypeStop, + NfcMessageTypeExit, // From Worker NfcMessageTypeDeviceFound, NfcMessageTypeDeviceNotFound, diff --git a/applications/nfc/nfc_views.c b/applications/nfc/nfc_views.c index e7f8878fb..9832a3bf1 100644 --- a/applications/nfc/nfc_views.c +++ b/applications/nfc/nfc_views.c @@ -123,14 +123,6 @@ void nfc_view_field_draw(Canvas* canvas, void* model) { canvas_draw_str(canvas, 2, 22, "TX/RX is disabled"); } -void nfc_view_cli_draw(Canvas* canvas, void* model) { - canvas_clear(canvas); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 0, 12, "USB connected"); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 2, 22, "Cli command in process..."); -} - void nfc_view_error_draw(Canvas* canvas, void* model) { NfcViewErrorModel* m = model; char buffer[32]; diff --git a/applications/nfc/nfc_views.h b/applications/nfc/nfc_views.h index 0b891ccc3..f9d69f383 100644 --- a/applications/nfc/nfc_views.h +++ b/applications/nfc/nfc_views.h @@ -8,10 +8,10 @@ #include "nfc_types.h" typedef enum { + NfcViewMenu, NfcViewRead, NfcViewEmulate, NfcViewField, - NfcViewCli, NfcViewError, } NfcView; @@ -30,8 +30,6 @@ void nfc_view_emulate_draw(Canvas* canvas, void* model); void nfc_view_field_draw(Canvas* canvas, void* model); -void nfc_view_cli_draw(Canvas* canvas, void* model); - typedef struct { ReturnCode error; } NfcViewErrorModel; diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index 150d176e0..fa4e3f35b 100644 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -8,10 +8,9 @@ NfcWorker* nfc_worker_alloc(osMessageQueueId_t message_queue) { nfc_worker->thread_attr.name = "nfc_worker"; nfc_worker->thread_attr.stack_size = 2048; // Initialize rfal - rfalAnalogConfigInitialize(); - nfc_worker->error = rfalNfcInitialize(); + nfc_worker->error = api_hal_nfc_init(); if(nfc_worker->error == ERR_NONE) { - rfalLowPowerModeStart(); + api_hal_nfc_start_sleep(); nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); } else { nfc_worker_change_state(nfc_worker, NfcWorkerStateBroken); @@ -20,6 +19,11 @@ NfcWorker* nfc_worker_alloc(osMessageQueueId_t message_queue) { return nfc_worker; } +void nfc_worker_free(NfcWorker* nfc_worker) { + furi_assert(nfc_worker); + free(nfc_worker); +} + NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker) { return nfc_worker->state; } @@ -28,10 +32,6 @@ 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); @@ -57,170 +57,57 @@ void nfc_worker_task(void* context) { api_hal_power_insomnia_enter(); - rfalLowPowerModeStop(); if(nfc_worker->state == NfcWorkerStatePoll) { - nfc_worker_poll(nfc_worker, 0); - } else if(nfc_worker->state == NfcWorkerStatePollOnce) { - nfc_worker_poll(nfc_worker, 5); + 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(); nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); - api_hal_power_insomnia_exit(); osThreadExit(); } -void nfc_worker_poll(NfcWorker* nfc_worker, uint8_t cycles) { - while((nfc_worker->state == NfcWorkerStatePoll) || - ((nfc_worker->state == NfcWorkerStatePollOnce) && cycles)) { - 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(); - if(cycles > 0) cycles--; - if((!is_found) && (!cycles)) { - NfcMessage message; +void nfc_worker_poll(NfcWorker* nfc_worker) { + rfalNfcDevice* dev_list; + uint8_t dev_cnt; + // Update screen before start searching + NfcMessage message = {.type = NfcMessageTypeDeviceNotFound}; + furi_check(osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK); + + while(nfc_worker->state == NfcWorkerStatePoll) { + if(api_hal_nfc_detect(&dev_list, &dev_cnt, 100)) { + // Send message with first device found + message.type = NfcMessageTypeDeviceFound; + if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA) { + message.device.type = NfcDeviceTypeNfca; + message.device.nfca = dev_list[0].dev.nfca; + } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCB) { + message.device.type = NfcDeviceTypeNfcb; + message.device.nfcb = dev_list[0].dev.nfcb; + } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCF) { + message.device.type = NfcDeviceTypeNfcf; + message.device.nfcf = dev_list[0].dev.nfcf; + } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCV) { + message.device.type = NfcDeviceTypeNfcv; + message.device.nfcv = dev_list[0].dev.nfcv; + } else { + // TODO show information about all found devices + message.type = NfcMessageTypeDeviceNotFound; + } + furi_check( + osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK); + } else { message.type = NfcMessageTypeDeviceNotFound; furi_check( osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK); } - platformDelay(333); + osDelay(20); } } -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; - } - - 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; } @@ -320,9 +207,9 @@ void nfc_worker_emulate(NfcWorker* nfc_worker) { } void nfc_worker_field(NfcWorker* nfc_worker) { - st25r3916TxRxOn(); + api_hal_nfc_field_on(); while(nfc_worker->state == NfcWorkerStateField) { osDelay(50); } - st25r3916TxRxOff(); + api_hal_nfc_field_off(); } diff --git a/applications/nfc/nfc_worker_i.h b/applications/nfc/nfc_worker_i.h index 1a0b53e66..21f7da6fd 100644 --- a/applications/nfc/nfc_worker_i.h +++ b/applications/nfc/nfc_worker_i.h @@ -29,11 +29,7 @@ void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state); void nfc_worker_task(void* context); -void nfc_worker_poll(NfcWorker* nfc_worker, uint8_t cycles); -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_poll(NfcWorker* nfc_worker); void nfc_worker_emulate(NfcWorker* nfc_worker); diff --git a/firmware/targets/api-hal-include/api-hal-nfc.h b/firmware/targets/api-hal-include/api-hal-nfc.h new file mode 100644 index 000000000..8b7f49320 --- /dev/null +++ b/firmware/targets/api-hal-include/api-hal-nfc.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Init nfc + */ +ReturnCode api_hal_nfc_init(); + +/** + * Check if nfc worker is busy + */ +bool api_hal_nfc_is_busy(); + +/** + * NFC field on + */ +void api_hal_nfc_field_on(); + +/** + * NFC field off + */ +void api_hal_nfc_field_off(); + +/** + * NFC start sleep + */ +void api_hal_nfc_start_sleep(); + +/** + * NFC stop sleep + */ +void api_hal_nfc_exit_sleep(); + +/** + * NFC poll + */ +bool api_hal_nfc_detect(rfalNfcDevice** dev_list, uint8_t* dev_cnt, uint32_t cycles); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/api-hal-include/api-hal.h b/firmware/targets/api-hal-include/api-hal.h index a1af61471..7bb2ed820 100644 --- a/firmware/targets/api-hal-include/api-hal.h +++ b/firmware/targets/api-hal-include/api-hal.h @@ -25,6 +25,7 @@ template struct STOP_EXTERNING_ME {}; #include "api-hal-vibro.h" #include "api-hal-ibutton.h" #include "api-hal-rfid.h" +#include "api-hal-nfc.h" /** Init api-hal */ void api_hal_init(); diff --git a/firmware/targets/f5/api-hal/api-hal-nfc.c b/firmware/targets/f5/api-hal/api-hal-nfc.c new file mode 100644 index 000000000..73275b52e --- /dev/null +++ b/firmware/targets/f5/api-hal/api-hal-nfc.c @@ -0,0 +1,83 @@ +#include "api-hal-nfc.h" +#include + +static bool dev_is_found = false; + +ReturnCode api_hal_nfc_init() { + // Check if Nfc worker was started + if(rfalNfcGetState() > RFAL_NFC_STATE_NOTINIT) { + return ERR_NONE; + } + return rfalNfcInitialize(); +} + +bool api_hal_nfc_is_busy() { + return rfalNfcGetState() > RFAL_NFC_STATE_IDLE; +} + +void api_hal_nfc_field_on() { + st25r3916TxRxOn(); +} + +void api_hal_nfc_field_off() { + rfalFieldOff(); +} + +void api_hal_nfc_start_sleep() { + rfalLowPowerModeStart(); +} + +void api_hal_nfc_exit_sleep() { + rfalLowPowerModeStop(); +} + +static void api_hal_nfc_change_state_cb(rfalNfcState st) { + FURI_LOG_D("HAL NFC", "NFC worker state: %d", st); + if(st >= RFAL_NFC_STATE_POLL_SELECT) { + dev_is_found = true; + } +} + +bool api_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t cycles) { + furi_assert(dev_list); + furi_assert(dev_cnt); + + rfalLowPowerModeStop(); + if(rfalNfcGetState() == RFAL_NFC_STATE_NOTINIT) { + rfalNfcInitialize(); + } + rfalNfcDiscoverParam params; + params.compMode = RFAL_COMPLIANCE_MODE_EMV; + params.techs2Find = RFAL_NFC_POLL_TECH_A | RFAL_NFC_POLL_TECH_B | RFAL_NFC_POLL_TECH_F | + RFAL_NFC_POLL_TECH_V | RFAL_NFC_POLL_TECH_AP2P | RFAL_NFC_POLL_TECH_ST25TB; + params.totalDuration = 1000; + params.devLimit = 3; + 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 = api_hal_nfc_change_state_cb; + + dev_is_found = false; + rfalNfcDiscover(¶ms); + while(--cycles) { + rfalNfcWorker(); + FURI_LOG_D("HAL NFC", "Current state %d", rfalNfcGetState()); + if(dev_is_found) { + rfalNfcGetDevicesFound(dev_list, dev_cnt); + FURI_LOG_D("HAL NFC", "Found %d devices", dev_cnt); + break; + } + osDelay(5); + } + rfalNfcDeactivate(false); + rfalLowPowerModeStart(); + if(!cycles) { + FURI_LOG_D("HAL NFC", "Timeout"); + return false; + } + + return true; +} diff --git a/lib/ST25RFAL002/platform.h b/lib/ST25RFAL002/platform.h index 842c04d64..22a6436f8 100644 --- a/lib/ST25RFAL002/platform.h +++ b/lib/ST25RFAL002/platform.h @@ -10,7 +10,9 @@ #include "math.h" #include "spi.h" #include "main.h" -#include +#include +#include +#include typedef void (*PlatformIrqCallback)(); void platformSetIrqCallback(PlatformIrqCallback cb); diff --git a/lib/lib.mk b/lib/lib.mk index d2f7eab2c..1704f2bfb 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -36,7 +36,7 @@ C_SOURCES += $(FATFS_DIR)/ff_gen_drv.c C_SOURCES += $(FATFS_DIR)/diskio.c C_SOURCES += $(FATFS_DIR)/option/unicode.c -ifeq ($(SRV_NFC), 1) +ifeq ($(APP_NFC), 1) ST25RFAL002_DIR = $(LIB_DIR)/ST25RFAL002 CFLAGS += -I$(ST25RFAL002_DIR) CFLAGS += -I$(ST25RFAL002_DIR)/include