diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index a2e45eaf..2bcecc20 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -13,6 +13,7 @@ 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); nfc->icon = assets_icons_get(A_NFC_14); @@ -39,6 +40,9 @@ Nfc* nfc_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); nfc->view_error = view_alloc(); view_set_context(nfc->view_error, nfc); view_set_draw_callback(nfc->view_error, nfc_view_error_draw); @@ -48,6 +52,7 @@ Nfc* nfc_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); return nfc; @@ -85,6 +90,54 @@ void nfc_menu_field_off_callback(void* context) { furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK); } +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) { + 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]); + } + } + } else { + printf("Device not found"); + } +} + void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) { NfcWorkerState state = nfc_worker_get_state(nfc->worker); if(state == NfcWorkerStateBroken) { @@ -106,6 +159,11 @@ int32_t nfc_task(void* p) { 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); }); @@ -121,6 +179,8 @@ 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) { @@ -128,18 +188,34 @@ int32_t nfc_task(void* p) { } 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; - return true; - }); + 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) { - with_view_model( - nfc->view_detect, (NfcViewReadModel * model) { - model->found = false; - return true; - }); + 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; + }); + } } } diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 9b8f074e..30be8442 100644 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -11,22 +11,26 @@ #include #include #include +#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; View* view_detect; View* view_emulate; View* view_field; + View* view_cli; View* view_error; ViewDispatcher* view_dispatcher; }; diff --git a/applications/nfc/nfc_types.h b/applications/nfc/nfc_types.h index b49c92ec..befc1f50 100644 --- a/applications/nfc/nfc_types.h +++ b/applications/nfc/nfc_types.h @@ -44,6 +44,7 @@ typedef enum { NfcWorkerStateReady, // Main worker states NfcWorkerStatePoll, + NfcWorkerStatePollOnce, NfcWorkerStateEmulate, NfcWorkerStateField, // Transition @@ -52,6 +53,7 @@ typedef enum { typedef enum { NfcMessageTypeDetect, + NfcMessageTypeDetectCliCmd, NfcMessageTypeEmulate, NfcMessageTypeField, NfcMessageTypeStop, diff --git a/applications/nfc/nfc_views.c b/applications/nfc/nfc_views.c index 9832a3bf..e7f8878f 100644 --- a/applications/nfc/nfc_views.c +++ b/applications/nfc/nfc_views.c @@ -123,6 +123,14 @@ 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 70e3fb15..0b891ccc 100644 --- a/applications/nfc/nfc_views.h +++ b/applications/nfc/nfc_views.h @@ -11,6 +11,7 @@ typedef enum { NfcViewRead, NfcViewEmulate, NfcViewField, + NfcViewCli, NfcViewError, } NfcView; @@ -29,6 +30,8 @@ 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 88a3c5b3..657cf009 100644 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -59,7 +59,9 @@ void nfc_worker_task(void* context) { rfalLowPowerModeStop(); if(nfc_worker->state == NfcWorkerStatePoll) { - nfc_worker_poll(nfc_worker); + nfc_worker_poll(nfc_worker, 0); + } else if(nfc_worker->state == NfcWorkerStatePollOnce) { + nfc_worker_poll(nfc_worker, 5); } else if(nfc_worker->state == NfcWorkerStateEmulate) { nfc_worker_emulate(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateField) { @@ -73,15 +75,17 @@ void nfc_worker_task(void* context) { osThreadExit(); } -void nfc_worker_poll(NfcWorker* nfc_worker) { - while(nfc_worker->state == NfcWorkerStatePoll) { +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(!is_found) { + cycles--; + if((!is_found) && (!cycles)) { NfcMessage message; message.type = NfcMessageTypeDeviceNotFound; furi_check( diff --git a/applications/nfc/nfc_worker_i.h b/applications/nfc/nfc_worker_i.h index 75939879..1a0b53e6 100644 --- a/applications/nfc/nfc_worker_i.h +++ b/applications/nfc/nfc_worker_i.h @@ -29,7 +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); +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);