Files
whowechina_aic_pico/firmware/src/lib/nfc.c
T

233 lines
4.9 KiB
C

/*
* NFC Reader Interface to real modules
* WHowe <github.com/whowechina>
*
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "hardware/i2c.h"
#include "hardware/gpio.h"
#include "nfc.h"
#include "pn532.h"
#include "pn5180.h"
static enum {
NFC_MODULE_PN532 = 0,
NFC_MODULE_PN5180,
NFC_MODULE_UNKNOWN,
} nfc_module = NFC_MODULE_UNKNOWN;
static const char *nfc_module_names[] = {
"PN532",
"PN5180",
"Unknown",
};
const char *nfc_module_name()
{
return nfc_module_names[nfc_module];
}
static const char *nfc_card_names[] = {
"None",
"MIFARE",
"FeliCa",
"15693"
};
const char *nfc_card_name(nfc_card_type card_type)
{
if (card_type >= sizeof(nfc_card_names) / sizeof(nfc_card_names[0])) {
return "Unknown";
}
return nfc_card_names[card_type];
}
#define func_null NULL
struct {
bool (*poll_mifare)(uint8_t uid[7], int *len);
bool (*poll_felica)(uint8_t uid[8], uint8_t pmm[8], uint8_t syscode[2], bool from_cache);
bool (*poll_vicinity)(uint8_t uid[8]);
void (*rf_field)(bool on);
bool (*mifare_auth)(const uint8_t uid[4], uint8_t block_id, uint8_t key_id, const uint8_t *key);
bool (*mifare_read)(uint8_t block_id, uint8_t block_data[16]);
void (*set_wait_loop)(nfc_wait_loop_t loop);
} api[3] = {
{
pn532_poll_mifare, pn532_poll_felica, func_null,
pn532_rf_field,
pn532_mifare_auth, pn532_mifare_read,
pn532_set_wait_loop
},
{
pn5180_poll_mifare, pn5180_poll_felica, pn5180_poll_vicinity,
func_null,
func_null, func_null,
pn5180_set_wait_loop
},
{ 0 },
};
static struct {
i2c_inst_t *port;
uint32_t freq;
uint8_t scl;
uint8_t sda;
} i2c = {0};
void nfc_attach_i2c(i2c_inst_t *port)
{
i2c.port = port;
}
void nfc_init_i2c(i2c_inst_t *port, uint8_t scl, uint8_t sda, uint32_t freq)
{
i2c.port = port;
i2c.freq = freq;
i2c.scl = scl;
i2c.sda = sda;
}
static struct {
spi_inst_t *port;
uint8_t miso;
uint8_t sck;
uint8_t mosi;
uint8_t rst;
uint8_t nss;
uint8_t busy;
} spi = {0};
void nfc_init_spi(spi_inst_t *port, uint8_t miso, uint8_t sck, uint8_t mosi,
uint8_t rst, uint8_t nss, uint8_t busy)
{
spi.port = port;
spi.miso = miso;
spi.sck = sck;
spi.mosi = mosi;
spi.rst = rst;
spi.nss = nss;
spi.busy = busy;
}
void nfc_init()
{
if (i2c.port &&
pn532_init(i2c.port, i2c.scl, i2c.sda, i2c.freq)) {
nfc_module = NFC_MODULE_PN532;
} else if (spi.port &&
pn5180_init(spi.port, spi.miso, spi.sck, spi.mosi,
spi.rst, spi.nss, spi.busy)) {
nfc_module = NFC_MODULE_PN5180;
}
}
void nfc_set_wait_loop(nfc_wait_loop_t loop)
{
if (!api[nfc_module].set_wait_loop) {
return;
}
api[nfc_module].set_wait_loop(loop);
}
static bool nfc_detect_mifare(nfc_card_t *card)
{
uint8_t id[20] = { 0 };
int len = sizeof(id);
if (!api[nfc_module].poll_mifare ||
!api[nfc_module].poll_mifare(id, &len)) {
return false;
}
card->card_type = NFC_CARD_MIFARE;
card->len = len;
memcpy(card->uid, id, len);
return true;
}
static bool nfc_detect_felica(nfc_card_t *card)
{
uint8_t id[20] = { 0 };
if (!api[nfc_module].poll_felica ||
!api[nfc_module].poll_felica(id, id + 8, id + 16, false)) {
return false;
}
card->card_type = NFC_CARD_FELICA;
card->len = 8;
memcpy(card->uid, id, 8);
memcpy(card->pmm, id + 8, 8);
memcpy(card->syscode, id + 16, 2);
return true;
}
static bool nfc_detect_vicinity(nfc_card_t *card)
{
uint8_t id[8] = { 0 };
if (!api[nfc_module].poll_vicinity ||
!api[nfc_module].poll_vicinity(id)) {
return false;
}
card->card_type = NFC_CARD_VICINITY;
card->len = 8;
memcpy(card->uid, id, 8);
return true;
}
void nfc_rf_field(bool on)
{
if (api[nfc_module].rf_field) {
api[nfc_module].rf_field(on);
}
}
nfc_card_t nfc_detect_card()
{
nfc_card_t card = { 0 };
if (!nfc_detect_mifare(&card) &&
!nfc_detect_felica(&card) &&
!nfc_detect_vicinity(&card)) {
card.card_type = NFC_CARD_NONE;
}
return card;
}
void display_card(const nfc_card_t *card)
{
if (card->card_type != NFC_CARD_NONE) {
printf("\n%s:", nfc_card_name(card->card_type));
for (int i = 0; i < card->len; i++) {
printf(" %02X", card->uid[i]);
}
}
}
bool nfc_mifare_auth(const uint8_t uid[4], uint8_t block_id, uint8_t key_id, const uint8_t *key)
{
if (!api[nfc_module].mifare_auth) {
return false;
}
return api[nfc_module].mifare_auth(uid, block_id, key_id, key);
}
bool nfc_mifare_read(uint8_t block_id, uint8_t block_data[16])
{
if (!api[nfc_module].mifare_read) {
return false;
}
return api[nfc_module].mifare_read(block_id, block_data);
}