diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index e5fe8908..719d3c37 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -1,156 +1,6 @@ #include "nfc.h" - -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#include "dispatcher.h" - -typedef enum { - MessageTypeBase, -} NfcMessageType; - -typedef struct { - Message base; - void* data; -} NfcMessage; - -struct Nfc { - Dispatcher* dispatcher; - Icon* icon; - Widget* widget; - ValueMutex* menu_vm; - MenuItem* menu; - rfalNfcDiscoverParam* disParams; - - osThreadAttr_t worker_attr; - osThreadId_t worker; - - uint8_t screen; - uint8_t ret; - uint8_t devCnt; - uint8_t ticker; - - char* current; -}; - -#define EXAMPLE_NFCA_DEVICES 5 - -// TODO replace with pubsub -static bool isr_enabled = false; - -void nfc_isr() { - if(isr_enabled) { - st25r3916Isr(); - } -} - -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; - - rfalLowPowerModeStop(); - - nfc->ticker = 0; - - isr_enabled = true; - - while(widget_is_enabled(nfc->widget)) { - rfalFieldOff(); - platformDelay(1000); - nfc->ticker += 1; - 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; - } - } - - 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) */ - } - } - widget_update(nfc->widget); - } - - isr_enabled = false; - rfalFieldOff(); - rfalLowPowerModeStart(); - nfc->ret = ERR_NONE; - nfc->worker = NULL; - osThreadExit(); -} +#include "nfc_i.h" +#include "nfc_worker.h" void nfc_draw_callback(CanvasApi* canvas, void* context) { furi_assert(canvas); @@ -178,10 +28,20 @@ void nfc_draw_callback(CanvasApi* canvas, void* context) { else canvas->draw_str(canvas, 2, 16, "NFC error"); - snprintf(status, sizeof(status), "Tck:%d Cnt:%d", nfc->ticker, nfc->devCnt); + 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); - canvas->draw_str(canvas, 2, 32, status); - canvas->draw_str(canvas, 2, 46, 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"); } @@ -194,7 +54,7 @@ void nfc_input_callback(InputEvent* event, void* context) { furi_assert(context); Nfc* nfc = context; - if(!event->state) return; + if(!event->state || event->input != InputBack) return; widget_enabled_set(nfc->widget, false); } @@ -216,6 +76,15 @@ void nfc_test_callback(void* context) { dispatcher_unlock(nfc->dispatcher); } +void nfc_field_on_callback(void* context) { + st25r3916OscOn(); + st25r3916TxRxOn(); +} + +void nfc_field_off_callback(void* context) { + st25r3916TxRxOff(); +} + void nfc_read_callback(void* context) { furi_assert(context); Nfc* nfc = context; @@ -253,6 +122,10 @@ Nfc* nfc_alloc() { 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)); + menu_item_subitem_add( + nfc->menu, menu_item_alloc_function("Field On", NULL, nfc_field_on_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( diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h new file mode 100644 index 00000000..455c4b31 --- /dev/null +++ b/applications/nfc/nfc_i.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "dispatcher.h" + +typedef enum { + MessageTypeBase, +} NfcMessageType; + +typedef struct { + Message base; + void* data; +} NfcMessage; + +struct Nfc { + Dispatcher* dispatcher; + Icon* icon; + Widget* widget; + ValueMutex* menu_vm; + MenuItem* menu; + rfalNfcDiscoverParam* disParams; + + osThreadAttr_t worker_attr; + osThreadId_t worker; + + uint8_t screen; + uint8_t ret; + uint8_t devCnt; + rfalNfcaSensRes first_atqa; + rfalNfcaSelRes first_sak; + + char* current; +}; diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c new file mode 100644 index 00000000..b6a37736 --- /dev/null +++ b/applications/nfc/nfc_worker.c @@ -0,0 +1,108 @@ +#include "nfc_worker.h" +#include "nfc.h" +#include "nfc_i.h" + +#define EXAMPLE_NFCA_DEVICES 5 + +// TODO replace with pubsub +static bool isr_enabled = false; + +void nfc_isr() { + if(isr_enabled) { + st25r3916Isr(); + } +} + +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; + + rfalLowPowerModeStop(); + + isr_enabled = true; + + while(widget_is_enabled(nfc->widget)) { + 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) */ + } + } + widget_update(nfc->widget); + } + + isr_enabled = false; + rfalFieldOff(); + rfalLowPowerModeStart(); + nfc->ret = ERR_NONE; + nfc->worker = NULL; + osThreadExit(); +} \ No newline at end of file diff --git a/applications/nfc/nfc_worker.h b/applications/nfc/nfc_worker.h new file mode 100644 index 00000000..a767606e --- /dev/null +++ b/applications/nfc/nfc_worker.h @@ -0,0 +1,3 @@ +#pragma once + +void nfc_worker_task(void* context); \ No newline at end of file diff --git a/lib/ST25RFAL002/platform.h b/lib/ST25RFAL002/platform.h index 6db86393..4be2ea66 100644 --- a/lib/ST25RFAL002/platform.h +++ b/lib/ST25RFAL002/platform.h @@ -21,6 +21,11 @@ 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_FIELD_PIN LED_BLUE_Pin +#define PLATFORM_LED_FIELD_PORT LED_BLUE_GPIO_Port + #define RFAL_FEATURE_LISTEN_MODE true /*!< Enable/Disable RFAL support for Listen Mode */ #define RFAL_FEATURE_WAKEUP_MODE true /*!< Enable/Disable RFAL support for the Wake-Up mode */ #define RFAL_FEATURE_LOWPOWER_MODE true /*!< Enable/Disable RFAL support for the Low Power mode */ @@ -51,6 +56,9 @@ void platformUnprotectST25RComm(); #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 */ +#define platformLedOff( port, pin ) platformGpioSet(port, pin) +#define platformLedOn( port, pin ) platformGpioClear(port, pin) + #define platformGpioSet( port, pin ) HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET) /*!< Turns the given GPIO High */ #define platformGpioClear( port, pin ) HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET) /*!< Turns the given GPIO Low */ #define platformGpioToogle( port, pin ) HAL_GPIO_TogglePin(port, pin) /*!< Toogles the given GPIO */