/* * NFC Reader Interface to real modules * WHowe * */ #include #include #include #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); }