feat(nfc): probe ISO-DEP activation

This commit is contained in:
chenjintao
2026-09-22 15:30:06 +08:00
parent d8b2114d0e
commit 913c5b9f71
+100 -10
View File
@@ -44,6 +44,10 @@ static volatile int g_nfc_irq_trigger = 0;
#endif #endif
#if (NFC_WORK_MODE == NFC_WORK_MODE_CARD_EMULATION) #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) 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", 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)); 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) static void nfc_card_emulation_start(void)
{ {
DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE); DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE);
@@ -65,11 +115,19 @@ static void nfc_card_emulation_start(void)
DP1312EA_Simulate_Card(); DP1312EA_Simulate_Card();
nfc_card_emulation_log_status("started"); 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 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 last_command = 0xFF;
u8 command; u8 command;
@@ -83,18 +141,50 @@ static void nfc_card_emulation_task(void)
last_command = command; last_command = command;
} }
if (command != DP1312EA_AUTOCOLL) { if (command == DP1312EA_TRANSCEIVE) {
/* frame_len = nfc_card_emulation_read_frame(frame, sizeof(frame));
* AutoColl normally exits after selection or on an RF/error event. nfc_card_emulation_log_frame("activation RX", frame, frame_len);
* 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. if (frame_len == 2 && frame[0] == 0xE0) {
*/ nfc_card_emulation_send_frame(ats, sizeof(ats));
ql_rtos_task_sleep_ms(500); 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(); nfc_card_emulation_start();
last_command = DP1312EA_AUTOCOLL; last_command = DP1312EA_AUTOCOLL;
} }
ql_rtos_task_sleep_ms(20); ql_rtos_task_sleep_ms(1);
} }
} }
#endif #endif
@@ -121,7 +211,7 @@ static void nfc_irq_wake(void *args)
void ql_nfc_task_thread(void *arvg) void ql_nfc_task_thread(void *arvg)
{ {
#if (NFC_WORK_MODE == NFC_WORK_MODE_CARD_EMULATION) #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(); nfc_card_emulation_task();
#else #else
s8 read_status; s8 read_status;