diff --git a/AfRApay.MateCard/include/Adafruit_PN532.h b/AfRApay.MateCard/include/Adafruit_PN532.h index 094c2cc..a352028 100644 --- a/AfRApay.MateCard/include/Adafruit_PN532.h +++ b/AfRApay.MateCard/include/Adafruit_PN532.h @@ -170,6 +170,7 @@ public: uint16_t timeout = 0); // timeout 0 means no timeout - will block forever. bool startPassiveTargetIDDetection(uint8_t cardbaudrate); bool readDetectedPassiveTargetID(uint8_t* uid, uint8_t* uidLength); + bool readDetectedPassiveTargetIDFeliCa(uint8_t* uid, uint8_t* uidLength); bool inDataExchange(uint8_t* send, uint8_t sendLength, uint8_t* response, uint8_t* responseLength); bool inListPassiveTarget(); diff --git a/AfRApay.MateCard/include/readers.h b/AfRApay.MateCard/include/readers.h index 769451a..af6ee31 100644 --- a/AfRApay.MateCard/include/readers.h +++ b/AfRApay.MateCard/include/readers.h @@ -43,14 +43,16 @@ public: class PN532Reader : public Reader { private: Adafruit_PN532* pn532; - uint8_t uid[7]; + uint8_t uid[16]; uint8_t uidLength; + uint8_t mode = 0; public: static volatile int irq; explicit PN532Reader(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss); bool canHaveUnstableIdentifier() override; bool isNewCardPresent() override; String getCardUid() override; + void cycleMode(); void begin() override; void reset() override; void init() override; diff --git a/AfRApay.MateCard/src/Adafruit_PN532.cpp b/AfRApay.MateCard/src/Adafruit_PN532.cpp index 60955ab..aeb71ac 100644 --- a/AfRApay.MateCard/src/Adafruit_PN532.cpp +++ b/AfRApay.MateCard/src/Adafruit_PN532.cpp @@ -71,7 +71,7 @@ byte pn532response_firmwarevers[] = { // related code #define PN532DEBUG -// #define MIFAREDEBUG +#define PN532CARDDEBUG // If using Native Port on Arduino Zero or Due define as SerialUSB #define PN532DEBUGPRINT Serial ///< Fixed name for debug Serial instance @@ -527,7 +527,7 @@ bool Adafruit_PN532::setPassiveActivationRetries(uint8_t maxRetries) { pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01) pn532_packetbuffer[4] = maxRetries; -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Setting MxRtyPassiveActivation to ")); PN532DEBUGPRINT.print(maxRetries, DEC); PN532DEBUGPRINT.println(F(" ")); @@ -562,14 +562,32 @@ bool Adafruit_PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t* uid, pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) pn532_packetbuffer[2] = cardbaudrate; - if (!sendCommandCheckAck(pn532_packetbuffer, 3, timeout)) { + if (cardbaudrate == PN532_MIFARE_ISO14443A) { + if (!sendCommandCheckAck(pn532_packetbuffer, 3, timeout)) { #ifdef PN532DEBUG - PN532DEBUGPRINT.println(F("No card(s) read")); + PN532DEBUGPRINT.println(F("No card(s) read")); #endif - return 0x0; // no cards read - } + return 0x0; // no cards read + } - return readDetectedPassiveTargetID(uid, uidLength); + return readDetectedPassiveTargetID(uid, uidLength); + } + else { // FeliCa + pn532_packetbuffer[3] = 0x00; + pn532_packetbuffer[4] = 0xFF; + pn532_packetbuffer[5] = 0xFF; + pn532_packetbuffer[6] = 0x01; + pn532_packetbuffer[7] = 0x00; + + if (!sendCommandCheckAck(pn532_packetbuffer, 8, timeout)) { +#ifdef PN532DEBUG + PN532DEBUGPRINT.println(F("No card(s) read")); +#endif + return 0x0; // no cards read + } + + return readDetectedPassiveTargetIDFeliCa(uid, uidLength); + } } /**************************************************************************/ @@ -585,7 +603,18 @@ bool Adafruit_PN532::startPassiveTargetIDDetection(uint8_t cardbaudrate) { pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) pn532_packetbuffer[2] = cardbaudrate; - return sendCommandCheckAck(pn532_packetbuffer, 3); + if (cardbaudrate == PN532_MIFARE_ISO14443A) { + return sendCommandCheckAck(pn532_packetbuffer, 3); + } + else { // FeliCa + pn532_packetbuffer[3] = 0x00; + pn532_packetbuffer[4] = 0xFF; + pn532_packetbuffer[5] = 0xFF; + pn532_packetbuffer[6] = 0x01; + pn532_packetbuffer[7] = 0x00; + + return sendCommandCheckAck(pn532_packetbuffer, 8); + } } /**************************************************************************/ @@ -618,7 +647,7 @@ bool Adafruit_PN532::readDetectedPassiveTargetID(uint8_t* uid, b12 NFCID Length b13..NFCIDLen NFCID */ -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Found ")); PN532DEBUGPRINT.print(pn532_packetbuffer[7], DEC); PN532DEBUGPRINT.println(F(" tags")); @@ -629,7 +658,7 @@ bool Adafruit_PN532::readDetectedPassiveTargetID(uint8_t* uid, uint16_t sens_res = pn532_packetbuffer[9]; sens_res <<= 8; sens_res |= pn532_packetbuffer[10]; -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("ATQA: 0x")); PN532DEBUGPRINT.println(sens_res, HEX); PN532DEBUGPRINT.print(F("SAK: 0x")); @@ -638,17 +667,65 @@ bool Adafruit_PN532::readDetectedPassiveTargetID(uint8_t* uid, /* Card appears to be Mifare Classic */ *uidLength = pn532_packetbuffer[12]; -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("UID:")); #endif for (uint8_t i = 0; i < pn532_packetbuffer[12]; i++) { uid[i] = pn532_packetbuffer[13 + i]; -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F(" 0x")); PN532DEBUGPRINT.print(uid[i], HEX); #endif } -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG + PN532DEBUGPRINT.println(); +#endif + + return 1; +} + +bool Adafruit_PN532::readDetectedPassiveTargetIDFeliCa(uint8_t* uid, uint8_t* uidLength) { + // read data packet + readdata(pn532_packetbuffer, 28); + // check some basic stuff + + /* Felica card response should be in the following format: page 116 of http://www.nxp.com/documents/user_manual/141520.pdf + byte Description + ------------- ------------------------------------------ + b0..6 Frame header and preamble + b7 Tags Found + b8 Tag Number (only one used in this example) + b9 POL_RES length + b10 0x01 (response code) + b11..18 NFCID2t + b19..26 Pad + b27..28 SYST_CODE (optional) + */ + +#ifdef PN532CARDDEBUG + PN532DEBUGPRINT.print(F("Found ")); + PN532DEBUGPRINT.print(pn532_packetbuffer[7], DEC); + PN532DEBUGPRINT.println(F(" tags")); +#endif + if (pn532_packetbuffer[7] != 1) + return 0; + + uint8_t POL_RES = pn532_packetbuffer[9]; + uint8_t uid_length = 8; //this is hard set in the protocol + + /* Card appears to be Felica */ + *uidLength = uid_length; +#ifdef PN532CARDDEBUG + PN532DEBUGPRINT.print(F("UID:")); +#endif + for (uint8_t i=0; i < uid_length; i++) { + uid[i] = pn532_packetbuffer[11+i]; +#ifdef PN532CARDDEBUG + PN532DEBUGPRINT.print(F(" 0x")); + PN532DEBUGPRINT.print(uid[i], HEX); +#endif + } +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(); #endif @@ -880,13 +957,13 @@ uint8_t Adafruit_PN532::mifareclassic_AuthenticateBlock(uint8_t* uid, memcpy(_uid, uid, uidLen); _uidLen = uidLen; -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Trying to authenticate card ")); - Adafruit_PN532::PrintHex(_uid, _uidLen); + Adafruit_PN532::PrintHex(reinterpret_cast(_uid), _uidLen); PN532DEBUGPRINT.print(F("Using authentication KEY ")); PN532DEBUGPRINT.print(keyNumber ? 'B' : 'A'); PN532DEBUGPRINT.print(F(": ")); - Adafruit_PN532::PrintHex(_key, 6); + Adafruit_PN532::PrintHex(reinterpret_cast(_key), 6); #endif // Prepare the authentication command // @@ -937,7 +1014,7 @@ uint8_t Adafruit_PN532::mifareclassic_AuthenticateBlock(uint8_t* uid, /**************************************************************************/ uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock(uint8_t blockNumber, uint8_t* data) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Trying to read 16 bytes from block ")); PN532DEBUGPRINT.println(blockNumber); #endif @@ -951,7 +1028,7 @@ uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock(uint8_t blockNumber, /* Send the command */ if (!sendCommandCheckAck(pn532_packetbuffer, 4)) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Failed to receive ACK for read command")); #endif return 0; @@ -962,7 +1039,7 @@ uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock(uint8_t blockNumber, /* If byte 8 isn't 0x00 we probably have an error */ if (pn532_packetbuffer[7] != 0x00) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Unexpected response")); Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); #endif @@ -974,7 +1051,7 @@ uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock(uint8_t blockNumber, memcpy(data, pn532_packetbuffer + 8, 16); /* Display data for debug if requested */ -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Block ")); PN532DEBUGPRINT.println(blockNumber); Adafruit_PN532::PrintHexChar(data, 16); @@ -997,7 +1074,7 @@ uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock(uint8_t blockNumber, /**************************************************************************/ uint8_t Adafruit_PN532::mifareclassic_WriteDataBlock(uint8_t blockNumber, uint8_t* data) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Trying to write 16 bytes to block ")); PN532DEBUGPRINT.println(blockNumber); #endif @@ -1012,7 +1089,7 @@ uint8_t Adafruit_PN532::mifareclassic_WriteDataBlock(uint8_t blockNumber, /* Send the command */ if (!sendCommandCheckAck(pn532_packetbuffer, 20)) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); #endif return 0; @@ -1169,13 +1246,13 @@ uint8_t Adafruit_PN532::mifareclassic_WriteNDEFURI(uint8_t sectorNumber, uint8_t Adafruit_PN532::mifareultralight_ReadPage(uint8_t page, uint8_t* buffer) { if (page >= 64) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Page value out of range")); #endif return 0; } -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Reading page ")); PN532DEBUGPRINT.println(page); #endif @@ -1188,7 +1265,7 @@ uint8_t Adafruit_PN532::mifareultralight_ReadPage(uint8_t page, /* Send the command */ if (!sendCommandCheckAck(pn532_packetbuffer, 4)) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); #endif return 0; @@ -1196,7 +1273,7 @@ uint8_t Adafruit_PN532::mifareultralight_ReadPage(uint8_t page, /* Read the response packet */ readdata(pn532_packetbuffer, 26); -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Received: ")); Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); #endif @@ -1210,7 +1287,7 @@ uint8_t Adafruit_PN532::mifareultralight_ReadPage(uint8_t page, /* bytes */ memcpy(buffer, pn532_packetbuffer + 8, 4); } else { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Unexpected response reading block: ")); Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); #endif @@ -1218,7 +1295,7 @@ uint8_t Adafruit_PN532::mifareultralight_ReadPage(uint8_t page, } /* Display data for debug if requested */ -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Page ")); PN532DEBUGPRINT.print(page); PN532DEBUGPRINT.println(F(":")); @@ -1245,14 +1322,14 @@ uint8_t Adafruit_PN532::mifareultralight_WritePage(uint8_t page, uint8_t* data) { if (page >= 64) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Page value out of range")); #endif // Return Failed Signal return 0; } -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Trying to write 4 byte page")); PN532DEBUGPRINT.println(page); #endif @@ -1267,7 +1344,7 @@ uint8_t Adafruit_PN532::mifareultralight_WritePage(uint8_t page, /* Send the command */ if (!sendCommandCheckAck(pn532_packetbuffer, 8)) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); #endif @@ -1304,13 +1381,13 @@ uint8_t Adafruit_PN532::ntag2xx_ReadPage(uint8_t page, uint8_t* buffer) { // NTAG 216 231 4 225 if (page >= 231) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Page value out of range")); #endif return 0; } -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Reading page ")); PN532DEBUGPRINT.println(page); #endif @@ -1323,7 +1400,7 @@ uint8_t Adafruit_PN532::ntag2xx_ReadPage(uint8_t page, uint8_t* buffer) { /* Send the command */ if (!sendCommandCheckAck(pn532_packetbuffer, 4)) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); #endif return 0; @@ -1331,7 +1408,7 @@ uint8_t Adafruit_PN532::ntag2xx_ReadPage(uint8_t page, uint8_t* buffer) { /* Read the response packet */ readdata(pn532_packetbuffer, 26); -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Received: ")); Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); #endif @@ -1345,7 +1422,7 @@ uint8_t Adafruit_PN532::ntag2xx_ReadPage(uint8_t page, uint8_t* buffer) { /* bytes */ memcpy(buffer, pn532_packetbuffer + 8, 4); } else { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Unexpected response reading block: ")); Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); #endif @@ -1353,7 +1430,7 @@ uint8_t Adafruit_PN532::ntag2xx_ReadPage(uint8_t page, uint8_t* buffer) { } /* Display data for debug if requested */ -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Page ")); PN532DEBUGPRINT.print(page); PN532DEBUGPRINT.println(F(":")); @@ -1385,14 +1462,14 @@ uint8_t Adafruit_PN532::ntag2xx_WritePage(uint8_t page, uint8_t* data) { // NTAG 216 231 4 225 if ((page < 4) || (page > 225)) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Page value out of range")); #endif // Return Failed Signal return 0; } -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.print(F("Trying to write 4 byte page")); PN532DEBUGPRINT.println(page); #endif @@ -1407,7 +1484,7 @@ uint8_t Adafruit_PN532::ntag2xx_WritePage(uint8_t page, uint8_t* data) { /* Send the command */ if (!sendCommandCheckAck(pn532_packetbuffer, 8)) { -#ifdef MIFAREDEBUG +#ifdef PN532CARDDEBUG PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); #endif diff --git a/AfRApay.MateCard/src/readers/pn532.cpp b/AfRApay.MateCard/src/readers/pn532.cpp index 3610728..0bf0ecc 100644 --- a/AfRApay.MateCard/src/readers/pn532.cpp +++ b/AfRApay.MateCard/src/readers/pn532.cpp @@ -12,7 +12,25 @@ PN532Reader::PN532Reader(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss) { void PN532Reader::begin() { pn532->begin(); irq = 0; - pn532->startPassiveTargetIDDetection(PN532_MIFARE_ISO14443A); + mode = PN532_MIFARE_ISO14443A; + pn532->startPassiveTargetIDDetection(mode); +} + +void PN532Reader::cycleMode() { + this->end(); + pn532->begin(); + irq = 0; + + if (mode == PN532_MIFARE_ISO14443A) { + mode = PN532_FELICA_424; + Serial.println("Mode is now FELICA"); + } + else { + mode = PN532_MIFARE_ISO14443A; + Serial.println("Mode is now MIFARE"); + } + + pn532->startPassiveTargetIDDetection(mode); } void PN532Reader::end() { @@ -20,11 +38,34 @@ void PN532Reader::end() { } bool PN532Reader::isNewCardPresent() { - return irq > 1; + if (irq > 1) + return true; + + //cycleMode(); + return false; } String PN532Reader::getCardUid() { - pn532->readDetectedPassiveTargetID(uid, &uidLength); + if (mode == PN532_MIFARE_ISO14443A) { + Serial.println("Reading MIFARE UID"); + pn532->readDetectedPassiveTargetID(uid, &uidLength); + + uint8_t felica_idm[16]; + uint8_t felica_length; + Serial.println("Checking if a FeliCa card is present as well"); + this->end(); + pn532->begin(); + if (pn532->readPassiveTargetID(PN532_FELICA_424, felica_idm, &felica_length, 500)) { + memcpy(uid, felica_idm, felica_length); + uidLength = felica_length; + } + } + else { + Serial.println("Reading FeliCa IDm"); + pn532->readDetectedPassiveTargetIDFeliCa(uid, &uidLength); + } + + Serial.println(uidLength); Serial.println(byteArrayAsHexString(uid, uidLength)); return byteArrayAsHexString(uid, uidLength); }