[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
This commit is contained in:
		| @@ -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) { | ||||
|   | ||||
| @@ -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[] = { | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|  */ | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										251
									
								
								applications/nfc/nfc.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										251
									
								
								applications/nfc/nfc.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -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]); | ||||
|     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( | ||||
|                 " 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]); | ||||
|                 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]); | ||||
|                 } | ||||
|         } 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]); | ||||
|                 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; | ||||
|                 }); | ||||
|             } | ||||
|         } 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; | ||||
|                 }); | ||||
|             } | ||||
|         } else if(message.type == NfcMessageTypeExit) { | ||||
|             nfc_free(nfc); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -15,17 +15,16 @@ | ||||
|  | ||||
| #include <menu/menu.h> | ||||
| #include <menu/menu_item.h> | ||||
| #include <gui/modules/submenu.h> | ||||
|  | ||||
| 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); | ||||
| @@ -3,6 +3,26 @@ | ||||
| #include <rfal_nfc.h> | ||||
| #include <st_errno.h> | ||||
|  | ||||
| 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, | ||||
|   | ||||
| @@ -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]; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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(); | ||||
| } | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
							
								
								
									
										49
									
								
								firmware/targets/api-hal-include/api-hal-nfc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								firmware/targets/api-hal-include/api-hal-nfc.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <rfal_nfc.h> | ||||
| #include <st_errno.h> | ||||
| #include <stdbool.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #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 | ||||
| @@ -25,6 +25,7 @@ template <unsigned int N> 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(); | ||||
|   | ||||
							
								
								
									
										83
									
								
								firmware/targets/f5/api-hal/api-hal-nfc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								firmware/targets/f5/api-hal/api-hal-nfc.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| #include "api-hal-nfc.h" | ||||
| #include <st25r3916.h> | ||||
|  | ||||
| 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; | ||||
| } | ||||
| @@ -10,7 +10,9 @@ | ||||
| #include "math.h" | ||||
| #include "spi.h" | ||||
| #include "main.h" | ||||
| #include <api-hal.h> | ||||
| #include <api-hal-gpio.h> | ||||
| #include <api-hal-light.h> | ||||
| #include <api-hal-spi.h> | ||||
|  | ||||
| typedef void (*PlatformIrqCallback)(); | ||||
| void platformSetIrqCallback(PlatformIrqCallback cb); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user