Initial FeliCa support

This commit is contained in:
Laura Hausmann 2023-04-21 20:44:41 +02:00
parent 6db86ea352
commit e6dafe8e66
Signed by: zotan
GPG key ID: D044E84C5BE01605
4 changed files with 165 additions and 44 deletions

View file

@ -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();

View file

@ -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;

View file

@ -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<const byte *>(_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<const byte *>(_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

View file

@ -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);
}