PN532 Driver library This library provides an abstract API to drive the pn532 nfc chip, with I2C/HSU/SPI interface. Its based on the Seeed Studio's Arduino version.
Dependents: PN532_ReadUid Nfctest2
emulatetag.cpp
00001 /**************************************************************************/ 00002 /*! 00003 @file emulatetag.cpp 00004 @author Armin Wieser 00005 @license BSD 00006 */ 00007 /**************************************************************************/ 00008 00009 #include "emulatetag.h " 00010 #include "PN532_debug.h" 00011 00012 #include <string.h> 00013 00014 #define MAX_TGREAD 00015 00016 00017 // Command APDU 00018 #define C_APDU_CLA 0 00019 #define C_APDU_INS 1 // instruction 00020 #define C_APDU_P1 2 // parameter 1 00021 #define C_APDU_P2 3 // parameter 2 00022 #define C_APDU_LC 4 // length command 00023 #define C_APDU_DATA 5 // data 00024 00025 #define C_APDU_P1_SELECT_BY_ID 0x00 00026 #define C_APDU_P1_SELECT_BY_NAME 0x04 00027 00028 // Response APDU 00029 #define R_APDU_SW1_COMMAND_COMPLETE 0x90 00030 #define R_APDU_SW2_COMMAND_COMPLETE 0x00 00031 00032 #define R_APDU_SW1_NDEF_TAG_NOT_FOUND 0x6a 00033 #define R_APDU_SW2_NDEF_TAG_NOT_FOUND 0x82 00034 00035 #define R_APDU_SW1_FUNCTION_NOT_SUPPORTED 0x6A 00036 #define R_APDU_SW2_FUNCTION_NOT_SUPPORTED 0x81 00037 00038 #define R_APDU_SW1_MEMORY_FAILURE 0x65 00039 #define R_APDU_SW2_MEMORY_FAILURE 0x81 00040 00041 #define R_APDU_SW1_END_OF_FILE_BEFORE_REACHED_LE_BYTES 0x62 00042 #define R_APDU_SW2_END_OF_FILE_BEFORE_REACHED_LE_BYTES 0x82 00043 00044 // ISO7816-4 commands 00045 #define ISO7816_SELECT_FILE 0xA4 00046 #define ISO7816_READ_BINARY 0xB0 00047 #define ISO7816_UPDATE_BINARY 0xD6 00048 00049 typedef enum { NONE, CC, NDEF } tag_file; // CC ... Compatibility Container 00050 00051 bool EmulateTag::init(){ 00052 pn532.begin(); 00053 return pn532.SAMConfig(); 00054 } 00055 00056 void EmulateTag::setNdefFile(const uint8_t* ndef, const int16_t ndefLength){ 00057 if(ndefLength > (NDEF_MAX_LENGTH -2)){ 00058 DMSG("ndef file too large (> NDEF_MAX_LENGHT -2) - aborting"); 00059 return; 00060 } 00061 00062 ndef_file[0] = ndefLength >> 8; 00063 ndef_file[1] = ndefLength & 0xFF; 00064 memcpy(ndef_file+2, ndef, ndefLength); 00065 } 00066 00067 void EmulateTag::setUid(uint8_t* uid){ 00068 uidPtr = uid; 00069 } 00070 00071 bool EmulateTag::emulate(const uint16_t tgInitAsTargetTimeout){ 00072 00073 // http://www.nxp.com/documents/application_note/AN133910.pdf 00074 uint8_t command[] = { 00075 PN532_COMMAND_TGINITASTARGET, 00076 0x05, // MODE: PICC only, Passive only 00077 00078 0x04, 0x00, // SENS_RES 00079 0x00, 0x00, 0x00, // NFCID1 00080 0x20, // SEL_RES 00081 00082 0x01, 0xFE, // Parameters to build POL_RES 00083 0xA2, 0xA3, 0xA4, 00084 0xA5, 0xA6, 0xA7, 00085 0xC0, 0xC1, 0xC2, 00086 0xC3, 0xC4, 0xC5, 00087 0xC6, 0xC7, 0xFF, 00088 0xFF, 00089 0xAA, 0x99, 0x88, //NFCID3t (10 bytes) 00090 0x77, 0x66, 0x55, 0x44, 00091 0x33, 0x22, 0x11, 00092 00093 0, // length of general bytes 00094 0 // length of historical bytes 00095 }; 00096 00097 if(uidPtr != 0){ // if uid is set copy 3 bytes to nfcid1 00098 memcpy(command + 4, uidPtr, 3); 00099 } 00100 00101 if(1 != pn532.tgInitAsTarget(command,sizeof(command), tgInitAsTargetTimeout)){ 00102 DMSG("tgInitAsTarget failed or timed out!"); 00103 return false; 00104 } 00105 00106 uint8_t compatibility_container[] = { 00107 0, 0x0F, 00108 0x20, 00109 0, 0x54, 00110 0, 0xFF, 00111 0x04, // T 00112 0x06, // L 00113 0xE1, 0x04, // File identifier 00114 ((NDEF_MAX_LENGTH & 0xFF00) >> 8), (NDEF_MAX_LENGTH & 0xFF), // maximum NDEF file size 00115 0x00, // read access 0x0 = granted 00116 0x00 // write access 0x0 = granted | 0xFF = deny 00117 }; 00118 00119 if(tagWriteable == false){ 00120 compatibility_container[14] = 0xFF; 00121 } 00122 00123 tagWrittenByInitiator = false; 00124 00125 uint8_t rwbuf[128]; 00126 uint8_t sendlen; 00127 int16_t status; 00128 tag_file currentFile = NONE; 00129 uint16_t cc_size = sizeof(compatibility_container); 00130 bool runLoop = true; 00131 00132 while(runLoop){ 00133 status = pn532.tgGetData(rwbuf, sizeof(rwbuf)); 00134 if(status < 0){ 00135 DMSG("tgGetData failed!\n"); 00136 pn532.inRelease(); 00137 return true; 00138 } 00139 00140 uint8_t p1 = rwbuf[C_APDU_P1]; 00141 uint8_t p2 = rwbuf[C_APDU_P2]; 00142 uint8_t lc = rwbuf[C_APDU_LC]; 00143 uint16_t p1p2_length = ((int16_t) p1 << 8) + p2; 00144 00145 switch(rwbuf[C_APDU_INS]){ 00146 case ISO7816_SELECT_FILE: 00147 switch(p1){ 00148 case C_APDU_P1_SELECT_BY_ID: 00149 if(p2 != 0x0c){ 00150 DMSG("C_APDU_P2 != 0x0c\n"); 00151 setResponse(COMMAND_COMPLETE, rwbuf, &sendlen); 00152 } else if(lc == 2 && rwbuf[C_APDU_DATA] == 0xE1 && (rwbuf[C_APDU_DATA+1] == 0x03 || rwbuf[C_APDU_DATA+1] == 0x04)){ 00153 setResponse(COMMAND_COMPLETE, rwbuf, &sendlen); 00154 if(rwbuf[C_APDU_DATA+1] == 0x03){ 00155 currentFile = CC; 00156 } else if(rwbuf[C_APDU_DATA+1] == 0x04){ 00157 currentFile = NDEF; 00158 } 00159 } else { 00160 setResponse(TAG_NOT_FOUND, rwbuf, &sendlen); 00161 } 00162 break; 00163 case C_APDU_P1_SELECT_BY_NAME: 00164 const uint8_t ndef_tag_application_name_v2[] = {0, 0x7, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 }; 00165 if(0 == memcmp(ndef_tag_application_name_v2, rwbuf + C_APDU_P2, sizeof(ndef_tag_application_name_v2))){ 00166 setResponse(COMMAND_COMPLETE, rwbuf, &sendlen); 00167 } else{ 00168 DMSG("function not supported\n"); 00169 setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen); 00170 } 00171 break; 00172 } 00173 break; 00174 case ISO7816_READ_BINARY: 00175 switch(currentFile){ 00176 case NONE: 00177 setResponse(TAG_NOT_FOUND, rwbuf, &sendlen); 00178 break; 00179 case CC: 00180 if( p1p2_length > NDEF_MAX_LENGTH){ 00181 setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen); 00182 }else { 00183 memcpy(rwbuf,compatibility_container + p1p2_length, lc); 00184 setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc); 00185 } 00186 break; 00187 case NDEF: 00188 if( p1p2_length > NDEF_MAX_LENGTH){ 00189 setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen); 00190 }else { 00191 memcpy(rwbuf, ndef_file + p1p2_length, lc); 00192 setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc); 00193 } 00194 break; 00195 } 00196 break; 00197 case ISO7816_UPDATE_BINARY: 00198 if(!tagWriteable){ 00199 setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen); 00200 } else{ 00201 if( p1p2_length > NDEF_MAX_LENGTH){ 00202 setResponse(MEMORY_FAILURE, rwbuf, &sendlen); 00203 } 00204 else{ 00205 memcpy(ndef_file + p1p2_length, rwbuf + C_APDU_DATA, lc); 00206 setResponse(COMMAND_COMPLETE, rwbuf, &sendlen); 00207 tagWrittenByInitiator = true; 00208 00209 uint16_t ndef_length = (ndef_file[0] << 8) + ndef_file[1]; 00210 if ((ndef_length > 0) && (updateNdefCallback != 0)) { 00211 updateNdefCallback(ndef_file + 2, ndef_length); 00212 } 00213 } 00214 } 00215 break; 00216 default: 00217 DMSG("Command not supported!"); 00218 DMSG_HEX(rwbuf[C_APDU_INS]); 00219 DMSG("\n"); 00220 setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen); 00221 } 00222 status = pn532.tgSetData(rwbuf, sendlen); 00223 if(status < 0){ 00224 DMSG("tgSetData failed\n!"); 00225 pn532.inRelease(); 00226 return true; 00227 } 00228 } 00229 pn532.inRelease(); 00230 return true; 00231 } 00232 00233 void EmulateTag::setResponse(responseCommand cmd, uint8_t* buf, uint8_t* sendlen, uint8_t sendlenOffset){ 00234 switch(cmd){ 00235 case COMMAND_COMPLETE: 00236 buf[0] = R_APDU_SW1_COMMAND_COMPLETE; 00237 buf[1] = R_APDU_SW2_COMMAND_COMPLETE; 00238 *sendlen = 2 + sendlenOffset; 00239 break; 00240 case TAG_NOT_FOUND: 00241 buf[0] = R_APDU_SW1_NDEF_TAG_NOT_FOUND; 00242 buf[1] = R_APDU_SW2_NDEF_TAG_NOT_FOUND; 00243 *sendlen = 2; 00244 break; 00245 case FUNCTION_NOT_SUPPORTED: 00246 buf[0] = R_APDU_SW1_FUNCTION_NOT_SUPPORTED; 00247 buf[1] = R_APDU_SW2_FUNCTION_NOT_SUPPORTED; 00248 *sendlen = 2; 00249 break; 00250 case MEMORY_FAILURE: 00251 buf[0] = R_APDU_SW1_MEMORY_FAILURE; 00252 buf[1] = R_APDU_SW2_MEMORY_FAILURE; 00253 *sendlen = 2; 00254 break; 00255 case END_OF_FILE_BEFORE_REACHED_LE_BYTES: 00256 buf[0] = R_APDU_SW1_END_OF_FILE_BEFORE_REACHED_LE_BYTES; 00257 buf[1] = R_APDU_SW2_END_OF_FILE_BEFORE_REACHED_LE_BYTES; 00258 *sendlen= 2; 00259 break; 00260 } 00261 }
Generated on Tue Jul 12 2022 20:44:47 by 1.7.2