Trigger express transit

This commit is contained in:
Laura Hausmann 2023-04-22 02:07:35 +02:00
parent e63eb4c620
commit 179cb05cbf
Signed by: zotan
GPG key ID: D044E84C5BE01605
3 changed files with 147 additions and 13 deletions

View file

@ -131,6 +131,22 @@
#define NDEF_URIPREFIX_URN_EPC (0x22) ///< URN EPC
#define NDEF_URIPREFIX_URN_NFC (0x23) ///< URN NFC
// FeliCa Commands
#define FELICA_CMD_POLLING (0x00)
#define FELICA_CMD_REQUEST_SERVICE (0x02)
#define FELICA_CMD_REQUEST_RESPONSE (0x04)
#define FELICA_CMD_READ_WITHOUT_ENCRYPTION (0x06)
#define FELICA_CMD_WRITE_WITHOUT_ENCRYPTION (0x08)
#define FELICA_CMD_REQUEST_SYSTEM_CODE (0x0C)
// FeliCa consts
#define FELICA_READ_MAX_SERVICE_NUM 16
#define FELICA_READ_MAX_BLOCK_NUM 12 // for typical FeliCa card
#define FELICA_WRITE_MAX_SERVICE_NUM 16
#define FELICA_WRITE_MAX_BLOCK_NUM 10 // for typical FeliCa card
#define FELICA_REQ_SERVICE_MAX_NODE_NUM 32
#define PN532_GPIO_VALIDATIONBIT (0x80) ///< GPIO validation bit
#define PN532_GPIO_P30 (0) ///< GPIO 30
#define PN532_GPIO_P31 (1) ///< GPIO 31
@ -170,7 +186,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 readDetectedPassiveTargetIDFeliCa(uint8_t* IDm, uint8_t* IDmLength);
bool inDataExchange(uint8_t* send, uint8_t sendLength, uint8_t* response,
uint8_t* responseLength);
bool inListPassiveTarget();
@ -221,6 +237,11 @@ private:
Adafruit_SPIDevice* spi_dev = NULL;
Adafruit_I2CDevice* i2c_dev = NULL;
HardwareSerial* ser_dev = NULL;
bool releaseCardFeliCa();
int8_t requestServiceFeliCa(uint8_t numNode, const uint16_t* nodeCodeList, uint16_t* keyVersions, const uint8_t* idm);
int8_t readWithoutEncryptionFeliCa(uint8_t numService, const uint16_t* serviceCodeList, uint8_t numBlock, const uint16_t* blockList, uint8_t blockData[][16], const uint8_t* idm);
};
#endif

View file

@ -573,9 +573,10 @@ bool Adafruit_PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t* uid,
return readDetectedPassiveTargetID(uid, uidLength);
}
else { // FeliCa
pn532_packetbuffer[3] = 0x00;
pn532_packetbuffer[4] = 0xFF;
pn532_packetbuffer[5] = 0xFF;
uint16_t systemCode = 0x0003; // Trigger express transit for CJRC Standard cards (Suica, PASMO, etc.)
pn532_packetbuffer[3] = FELICA_CMD_POLLING;
pn532_packetbuffer[4] = (systemCode >> 8) & 0xFF;
pn532_packetbuffer[5] = systemCode & 0xFF;
pn532_packetbuffer[6] = 0x01;
pn532_packetbuffer[7] = 0x00;
@ -607,9 +608,10 @@ bool Adafruit_PN532::startPassiveTargetIDDetection(uint8_t cardbaudrate) {
return sendCommandCheckAck(pn532_packetbuffer, 3);
}
else { // FeliCa
pn532_packetbuffer[3] = 0x00;
pn532_packetbuffer[4] = 0xFF;
pn532_packetbuffer[5] = 0xFF;
uint16_t systemCode = 0x0003; // Trigger express transit for CJRC Standard cards (Suica, PASMO, etc.)
pn532_packetbuffer[3] = FELICA_CMD_POLLING;
pn532_packetbuffer[4] = (systemCode >> 8) & 0xFF;
pn532_packetbuffer[5] = systemCode & 0xFF;
pn532_packetbuffer[6] = 0x01;
pn532_packetbuffer[7] = 0x00;
@ -684,7 +686,7 @@ bool Adafruit_PN532::readDetectedPassiveTargetID(uint8_t* uid,
return 1;
}
bool Adafruit_PN532::readDetectedPassiveTargetIDFeliCa(uint8_t* uid, uint8_t* uidLength) {
bool Adafruit_PN532::readDetectedPassiveTargetIDFeliCa(uint8_t* IDm, uint8_t* IDmLength) {
// read data packet
readdata(pn532_packetbuffer, 28);
// check some basic stuff
@ -711,15 +713,17 @@ bool Adafruit_PN532::readDetectedPassiveTargetIDFeliCa(uint8_t* uid, uint8_t* ui
return 0;
uint8_t POL_RES = pn532_packetbuffer[9];
uint8_t uid_length = 8; //this is hard set in the protocol
uint8_t length = 8; //this is hard set in the protocol
/* Card appears to be Felica */
*uidLength = uid_length;
*IDmLength = length;
#ifdef PN532CARDDEBUG
PN532DEBUGPRINT.print(F("UID:"));
#endif
for (uint8_t i=0; i < uid_length; i++) {
uid[i] = pn532_packetbuffer[11+i];
for (uint8_t i=0; i < length; i++) {
IDm[i] = pn532_packetbuffer[11 + i];
IDm[0] = (IDm[0] & 0x0F);
#ifdef PN532CARDDEBUG
PN532DEBUGPRINT.print(F(" 0x"));
PN532DEBUGPRINT.print(uid[i], HEX);
@ -729,6 +733,115 @@ bool Adafruit_PN532::readDetectedPassiveTargetIDFeliCa(uint8_t* uid, uint8_t* ui
PN532DEBUGPRINT.println();
#endif
uint16_t serviceCodeList[1];
uint16_t returnKey[1];
uint16_t blockList[1];
uint8_t blockData[1][16];
serviceCodeList[0] = 0x090f;
blockList[0] = 0x8000;
//TODO: figure out how to release the card properly so the transaction doesn't time out on the Apple Pay side
//requestServiceFeliCa(1, serviceCodeList, returnKey, IDm);
//readWithoutEncryptionFeliCa(1, serviceCodeList, 1, blockList, blockData, IDm);
//releaseCardFeliCa();
return 1;
}
bool Adafruit_PN532::releaseCardFeliCa() {
Serial.println("Releasing FeliCa card");
pn532_packetbuffer[0] = PN532_COMMAND_INRELEASE;
pn532_packetbuffer[1] = 0x00; // All target
return sendCommandCheckAck(pn532_packetbuffer, 2);
}
int8_t Adafruit_PN532::requestServiceFeliCa(uint8_t numNode, const uint16_t* nodeCodeList, uint16_t* keyVersions, const uint8_t* idm)
{
if (numNode > FELICA_REQ_SERVICE_MAX_NODE_NUM) {
Serial.println("numNode is too large\n");
return -1;
}
uint8_t i, j=0;
uint8_t cmdLen = 1 + 8 + 1 + 2*numNode;
uint8_t cmd[cmdLen];
cmd[j++] = FELICA_CMD_REQUEST_SERVICE;
for (i=0; i<8; ++i) {
cmd[j++] = idm[i];
}
cmd[j++] = numNode;
for (i=0; i<numNode; ++i) {
cmd[j++] = nodeCodeList[i] & 0xFF;
cmd[j++] = (nodeCodeList[i] >> 8) & 0xff;
}
uint8_t response[10+2*numNode];
if (!sendCommandCheckAck(cmd, cmdLen)) {
Serial.println("Request Service command failed\n");
return -2;
}
for(i=0; i<numNode; i++) {
keyVersions[i] = (uint16_t)(response[10+i*2] + (response[10+i*2+1] << 8));
}
return 1;
}
int8_t Adafruit_PN532::readWithoutEncryptionFeliCa(uint8_t numService, const uint16_t* serviceCodeList, uint8_t numBlock, const uint16_t* blockList, uint8_t blockData[][16], const uint8_t* idm) {
if (numService > FELICA_READ_MAX_SERVICE_NUM) {
Serial.println("numService is too large\n");
return -1;
}
if (numBlock > FELICA_READ_MAX_BLOCK_NUM) {
Serial.println("numBlock is too large\n");
return -2;
}
uint8_t i, j = 0, k;
uint8_t cmdLen = 1 + 8 + 1 + 2 * numService + 1 + 2 * numBlock;
uint8_t cmd[cmdLen];
cmd[j++] = FELICA_CMD_READ_WITHOUT_ENCRYPTION;
for (i = 0; i < 8; ++i) {
cmd[j++] = idm[i];
}
cmd[j++] = numService;
for (i = 0; i < numService; ++i) {
cmd[j++] = serviceCodeList[i] & 0xFF;
cmd[j++] = (serviceCodeList[i] >> 8) & 0xff;
}
cmd[j++] = numBlock;
for (i = 0; i < numBlock; ++i) {
cmd[j++] = (blockList[i] >> 8) & 0xFF;
cmd[j++] = blockList[i] & 0xff;
}
uint8_t response[12 + 16 * numBlock];
uint8_t responseLength = 12 + 16 * numBlock;
if (!sendCommandCheckAck(cmd, cmdLen)) {
Serial.println("Read Without Encryption command failed\n");
return -3;
}
readdata(pn532_packetbuffer, responseLength);
// status flag check
if (pn532_packetbuffer[9] != 0 || pn532_packetbuffer[10] != 0) {
Serial.println("Read Without Encryption command failed (Status Flag: ");
Serial.println(pn532_packetbuffer[9], HEX);
Serial.println(pn532_packetbuffer[10], HEX);
Serial.println(")\n");
return -5;
}
k = 12;
for (i = 0; i < numBlock; i++) {
for (j = 0; j < 16; j++) {
blockData[i][j] = pn532_packetbuffer[k++];
}
}
return 1;
}

View file

@ -12,7 +12,7 @@ PN532Reader::PN532Reader(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss) {
void PN532Reader::begin() {
pn532->begin();
irq = 0;
mode = PN532_MIFARE_ISO14443A;
mode = PN532_FELICA_424;
pn532->startPassiveTargetIDDetection(mode);
}