Pn532 Emulated Card Not Read By An Android Phone
Solution 1:
Well, I tried a lot of solutions and I can bravely claim that Android only works in HCE mode with PN532 and Ios only works with NDEF.
Solution 2:
Give a look to this issue on Seeeds studio:
https://github.com/Seeed-Studio/PN532/issues/88
Android phones will only accept Felica Cards. If you put some random IDs, it will not be detected as NDEF card.
To emulate it right, you have to set the card ID in this way:
uint8_t command[] = {
PN532_COMMAND_TGINITASTARGET,
0x05, // MODE: 0x04 = PICC only, 0x01 = Passive only (0x02 = DEP only)// MIFARE PARAMS0x04, 0x00, // SENS_RES (seeeds studio set it to 0x04, nxp to 0x08)0x00, 0x00, 0x00, // NFCID1t (is set over sketch with setUID())0x20, // SEL_RES (0x20=Mifare DelFire, 0x60=custom)// FELICA PARAMS0x01, 0xFE, // NFCID2t (8 bytes) https://github.com/adafruit/Adafruit-PN532/blob/master/Adafruit_PN532.cpp FeliCa NEEDS TO BEGIN WITH 0x01 0xFE!0x05, 0x01, 0x86,
0x04, 0x02, 0x02,
0x03, 0x00, // PAD (8 bytes)0x4B, 0x02, 0x4F,
0x49, 0x8A, 0x00,
0xFF, 0xFF, // System code (2 bytes)0x01, 0x01, 0x66, // NFCID3t (10 bytes)0x6D, 0x01, 0x01, 0x10,
0x02, 0x00, 0x00,
0x00, // length of general bytes0x00// length of historical bytes
};
NFCID1t is the card UID, you can set something on your sketch. NFCID2t has to be exactly how I wrote in the code above => Felica card NFCID3t can be some random numbers.
You will see that there will be other issues with your sketch and sometimes it is impossible to debug or see why it does not work (for example if you have multiple NDEF Tags). So, the most important tool to test your PN532 is this one from NXP: https://play.google.com/store/apps/details?id=com.nxp.taginfolite
This will give you a lot of info. This app can also read your card, even if it is not formatted in the right way.
Edit: This is how I updated the emulatetag.cpp
from PN532 library:
boolEmulateTag::emulate(constuint16_t tgInitAsTargetTimeout){
// https://www.nxp.com/docs/en/nxp/application-notes/AN133910.pdf// Doc: // Mode: 0x00 any command is accepted. 0x02 only ATR_REQ. 0x04 only RATS (ISO1443-4)// Mifare: SENS_RES => bit 6 and 7 must be 0!// NFCID1t => first byte must be 0x08 according to the ISO// SEL_RES => bit 6 must be 1, to enable NFC protocol (example 0x40)// FeliCa: NFCID2t => first 2 bytes must be 0x01 and 0xFE// uint8_t command[] = {
PN532_COMMAND_TGINITASTARGET,
0x05, // MODE: 0x04 = PICC only, 0x01 = Passive only (0x02 = DEP only)// MIFARE PARAMS0x04, 0x00, // SENS_RES (seeeds studio set it to 0x04, nxp to 0x08)0x00, 0x00, 0x00, // NFCID1t (is set over sketch with setUID())0x20, // SEL_RES (0x20=Mifare DelFire, 0x60=custom)// FELICA PARAMS0x01, 0xFE, // NFCID2t (8 bytes) https://github.com/adafruit/Adafruit-PN532/blob/master/Adafruit_PN532.cpp FeliCa NEEDS TO BEGIN WITH 0x01 0xFE!0x05, 0x01, 0x86,
0x04, 0x02, 0x02,
0x03, 0x00, // PAD (8 bytes)0x4B, 0x02, 0x4F,
0x49, 0x8A, 0x00,
0xFF, 0xFF, // System code (2 bytes)0x01, 0x01, 0x66, // NFCID3t (10 bytes)0x6D, 0x01, 0x01, 0x10,
0x02, 0x00, 0x00,
0x00, // length of general bytes0x00// length of historical bytes
};
if(uidPtr != 0){ // if uid is set copy 3 bytes to nfcid1memcpy(command + 4, uidPtr, 3);
}
switch(pn532.tgInitAsTarget(command,sizeof(command), tgInitAsTargetTimeout))
{
case1: break;
case0: DMSG("tgInitAsTarget timed out!"); returnfalse; break;
case-2: DMSG("tgInitAsTarget failed!"); returnfalse; break;
}
uint8_t compatibility_container[] = {
0, 0x0F,
0x20,
0, 0x54,
0, 0xFF,
0x04, // T0x06, // L0xE1, 0x04, // File identifier
((NDEF_MAX_LENGTH & 0xFF00) >> 8), (NDEF_MAX_LENGTH & 0xFF), // maximum NDEF file size0x00, // read access 0x0 = granted0x00// write access 0x0 = granted | 0xFF = deny
};
if(tagWriteable == false){
compatibility_container[14] = 0xFF;
}
tagWrittenByInitiator = false;
uint8_t rwbuf[128];
uint8_t sendlen;
int16_t status;
int16_t totalReads = 0;
tag_file currentFile = NONE;
uint16_t cc_size = sizeof(compatibility_container);
bool runLoop = true;
while(runLoop){
status = pn532.tgGetData(rwbuf, sizeof(rwbuf));
if(status < 0){
if (status == -2)
{
if (totalReads == 0)
{
if (pn532.tgInitAsTarget(command, sizeof(command), 1000) == 1) continue;
}
else
{
DMSG("Transmission over.\n");
pn532.inRelease();
returntrue;
}
}
DMSG("tgGetData failed!\n");
pn532.inRelease();
returnfalse;
}
totalReads++;
uint8_t p1 = rwbuf[C_APDU_P1];
uint8_t p2 = rwbuf[C_APDU_P2];
uint8_t lc = rwbuf[C_APDU_LC];
uint16_t p1p2_length = ((int16_t) p1 << 8) + p2;
switch(rwbuf[C_APDU_INS]){
case ISO7816_SELECT_FILE:
switch(p1){
case C_APDU_P1_SELECT_BY_ID:
if(p2 != 0x0c){
DMSG("C_APDU_P2 != 0x0c\n");
setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
} elseif(lc == 2 && rwbuf[C_APDU_DATA] == 0xE1 && (rwbuf[C_APDU_DATA+1] == 0x03 || rwbuf[C_APDU_DATA+1] == 0x04)){
setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
if(rwbuf[C_APDU_DATA+1] == 0x03){
currentFile = CC;
} elseif(rwbuf[C_APDU_DATA+1] == 0x04){
currentFile = NDEF;
}
} else {
setResponse(TAG_NOT_FOUND, rwbuf, &sendlen);
}
break;
case C_APDU_P1_SELECT_BY_NAME:
constuint8_t ndef_tag_application_name_v2[] = {0, 0x07, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 };
if(0 == memcmp(ndef_tag_application_name_v2, rwbuf + C_APDU_P2, sizeof(ndef_tag_application_name_v2))){
setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
} else{
DMSG("function not supported\n");
setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
}
break;
}
break;
case ISO7816_READ_BINARY:
switch(currentFile){
case NONE:
setResponse(TAG_NOT_FOUND, rwbuf, &sendlen);
break;
case CC:
if( p1p2_length > NDEF_MAX_LENGTH){
setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen);
}else {
memcpy(rwbuf,compatibility_container + p1p2_length, lc);
setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc);
}
break;
case NDEF:
if( p1p2_length > NDEF_MAX_LENGTH){
setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen);
}else {
memcpy(rwbuf, ndef_file + p1p2_length, lc);
setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc);
}
break;
}
break;
case ISO7816_UPDATE_BINARY:
if(!tagWriteable){
setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
} else{
if( p1p2_length > NDEF_MAX_LENGTH){
setResponse(MEMORY_FAILURE, rwbuf, &sendlen);
}
else{
memcpy(ndef_file + p1p2_length, rwbuf + C_APDU_DATA, lc);
setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
tagWrittenByInitiator = true;
uint16_t ndef_length = (ndef_file[0] << 8) + ndef_file[1];
if ((ndef_length > 0) && (updateNdefCallback != 0)) {
updateNdefCallback(ndef_file + 2, ndef_length);
}
}
}
break;
default:
DMSG("Command not supported!");
DMSG_HEX(rwbuf[C_APDU_INS]);
DMSG("\n");
setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
}
status = pn532.tgSetData(rwbuf, sendlen);
if(status < 0){
DMSG("tgSetData failed\n!");
pn532.inRelease();
returntrue;
}
}
pn532.inRelease();
returntrue;
}
Solution 3:
just uncomment some stuff like I did and it should work.
voidsetup()
{
Serial.begin(115200);
Serial.println("------- Emulate Tag --------");
message = NdefMessage();
message.addUriRecord("http://www.elechouse.com");
messageSize = message.getEncodedSize();
if (messageSize > sizeof(ndefBuf)) {
Serial.println("ndefBuf is too small");
while (1) { }
}
Serial.print("Ndef encoded message size: ");
Serial.println(messageSize);
message.encode(ndefBuf);
// comment out this command for no ndef message
nfc.setNdefFile(ndefBuf, messageSize);
// uid must be 3 bytes!
nfc.setUid(uid);
nfc.init();
}
voidloop(){
// uncomment for overriding ndef in case a write to this tag occured
nfc.setNdefFile(ndefBuf, messageSize);
// start emulation (blocks)
nfc.emulate();
// or start emulation with timeoutif(!nfc.emulate(1000)){ // timeout 1 second
Serial.println("timed out");
}
// deny writing to the tag// nfc.setTagWriteable(false);if(nfc.writeOccured()){
Serial.println("\nWrite occured !");
uint8_t* tag_buf;
uint16_t length;
nfc.getContent(&tag_buf, &length);
NdefMessage msg = NdefMessage(tag_buf, length);
msg.print();
}
Post a Comment for "Pn532 Emulated Card Not Read By An Android Phone"