feat(nfc): probe ISO-DEP activation
This commit is contained in:
@@ -44,6 +44,10 @@ static volatile int g_nfc_irq_trigger = 0;
|
||||
#endif
|
||||
|
||||
#if (NFC_WORK_MODE == NFC_WORK_MODE_CARD_EMULATION)
|
||||
#define NFC_CARD_FRAME_MAX 64
|
||||
#define NFC_CARD_SESSION_POLLS 200
|
||||
#define NFC_CARD_SESSION_POLL_MS 1
|
||||
|
||||
static void nfc_card_emulation_log_status(const char *reason)
|
||||
{
|
||||
printf("NFC card emulation %s: cmd=%02X irq=%02X err=%02X status1=%02X status2=%02X fifo=%02X\r\n",
|
||||
@@ -56,6 +60,52 @@ static void nfc_card_emulation_log_status(const char *reason)
|
||||
DP1312EA_ReadRawRC(FIFOLevelReg));
|
||||
}
|
||||
|
||||
static u8 nfc_card_emulation_read_frame(u8 *frame, u8 capacity)
|
||||
{
|
||||
u8 fifo_len = DP1312EA_ReadRawRC(FIFOLevelReg) & 0x7F;
|
||||
u8 read_len = fifo_len;
|
||||
|
||||
if (read_len > capacity) {
|
||||
read_len = capacity;
|
||||
}
|
||||
|
||||
if (read_len > 0) {
|
||||
DP1312EA_ReadFIFO(frame, read_len);
|
||||
}
|
||||
|
||||
while (read_len < fifo_len) {
|
||||
(void)DP1312EA_ReadRawRC(FIFODataReg);
|
||||
read_len++;
|
||||
}
|
||||
|
||||
return fifo_len > capacity ? capacity : fifo_len;
|
||||
}
|
||||
|
||||
static void nfc_card_emulation_log_frame(const char *prefix,
|
||||
const u8 *frame,
|
||||
u8 length)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
printf("NFC %s (%u):", prefix, length);
|
||||
for (i = 0; i < length; i++) {
|
||||
printf(" %02X", frame[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
|
||||
static void nfc_card_emulation_send_frame(const u8 *frame, u8 length)
|
||||
{
|
||||
DP1312EA_WriteRawRC(ComIrqReg, 0x7F);
|
||||
DP1312EA_SetBitMask(FIFOLevelReg, 0x80);
|
||||
DP1312EA_WriteFIFO((u8 *)frame, length);
|
||||
|
||||
/* AutoColl leaves Transceive active and waiting for StartSend. */
|
||||
DP1312EA_SetBitMask(TxModeReg, 0x80);
|
||||
DP1312EA_SetBitMask(RxModeReg, 0x80);
|
||||
DP1312EA_WriteRawRC(BitFramingReg, 0x80);
|
||||
}
|
||||
|
||||
static void nfc_card_emulation_start(void)
|
||||
{
|
||||
DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE);
|
||||
@@ -65,11 +115,19 @@ static void nfc_card_emulation_start(void)
|
||||
|
||||
DP1312EA_Simulate_Card();
|
||||
nfc_card_emulation_log_status("started");
|
||||
printf("NFC phase-1 target: ATQA=44 00, UID=08 AA BB CC, SAK=00\r\n");
|
||||
printf("NFC phase-2 probe: ATQA=44 00, UID=08 AA BB CC, SAK=00\r\n");
|
||||
}
|
||||
|
||||
static void nfc_card_emulation_task(void)
|
||||
{
|
||||
static const u8 ats[] = {
|
||||
0x03, /* TL: three ATS bytes */
|
||||
0x24, /* TB(1) present, FSCI=4 (48-byte frame size) */
|
||||
0x80 /* FWI=8 (~77 ms frame waiting time), SFGI=0 */
|
||||
};
|
||||
u8 frame[NFC_CARD_FRAME_MAX];
|
||||
u8 frame_len;
|
||||
u16 poll_count;
|
||||
u8 last_command = 0xFF;
|
||||
u8 command;
|
||||
|
||||
@@ -83,18 +141,50 @@ static void nfc_card_emulation_task(void)
|
||||
last_command = command;
|
||||
}
|
||||
|
||||
if (command != DP1312EA_AUTOCOLL) {
|
||||
/*
|
||||
* AutoColl normally exits after selection or on an RF/error event.
|
||||
* Phase 1 has no ISO14443-4 handler yet, so allow the phone time to
|
||||
* finish its probe, then arm AutoColl again for the next tap.
|
||||
*/
|
||||
ql_rtos_task_sleep_ms(500);
|
||||
if (command == DP1312EA_TRANSCEIVE) {
|
||||
frame_len = nfc_card_emulation_read_frame(frame, sizeof(frame));
|
||||
nfc_card_emulation_log_frame("activation RX", frame, frame_len);
|
||||
|
||||
if (frame_len == 2 && frame[0] == 0xE0) {
|
||||
nfc_card_emulation_send_frame(ats, sizeof(ats));
|
||||
nfc_card_emulation_log_frame("ATS TX", ats, sizeof(ats));
|
||||
|
||||
for (poll_count = 0;
|
||||
poll_count < NFC_CARD_SESSION_POLLS;
|
||||
poll_count++) {
|
||||
u8 irq = DP1312EA_ReadRawRC(ComIrqReg);
|
||||
u8 error = DP1312EA_ReadRawRC(ErrorReg);
|
||||
|
||||
if (error != 0) {
|
||||
nfc_card_emulation_log_status("ISO-DEP error");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((irq & 0x20) != 0 &&
|
||||
(DP1312EA_ReadRawRC(FIFOLevelReg) & 0x7F) != 0) {
|
||||
frame_len = nfc_card_emulation_read_frame(
|
||||
frame, sizeof(frame));
|
||||
nfc_card_emulation_log_frame(
|
||||
"first ISO-DEP RX", frame, frame_len);
|
||||
break;
|
||||
}
|
||||
|
||||
ql_rtos_task_sleep_ms(NFC_CARD_SESSION_POLL_MS);
|
||||
}
|
||||
} else {
|
||||
printf("NFC activation frame is not RATS\r\n");
|
||||
}
|
||||
|
||||
nfc_card_emulation_log_status("session complete");
|
||||
nfc_card_emulation_start();
|
||||
last_command = DP1312EA_AUTOCOLL;
|
||||
} else if (command != DP1312EA_AUTOCOLL) {
|
||||
nfc_card_emulation_log_status("unexpected command");
|
||||
nfc_card_emulation_start();
|
||||
last_command = DP1312EA_AUTOCOLL;
|
||||
}
|
||||
|
||||
ql_rtos_task_sleep_ms(20);
|
||||
ql_rtos_task_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -121,7 +211,7 @@ static void nfc_irq_wake(void *args)
|
||||
void ql_nfc_task_thread(void *arvg)
|
||||
{
|
||||
#if (NFC_WORK_MODE == NFC_WORK_MODE_CARD_EMULATION)
|
||||
printf("NFC work mode: CARD_EMULATION (phase 1)\r\n");
|
||||
printf("NFC work mode: CARD_EMULATION (phase 2 probe)\r\n");
|
||||
nfc_card_emulation_task();
|
||||
#else
|
||||
s8 read_status;
|
||||
|
||||
Reference in New Issue
Block a user