LEER TAG

Dependents:   NFC_HTM_READ EMULAR_TAGS Escribir_tag NFC_HTM_READ-WRITE

Committer:
mauroar211
Date:
Fri Apr 24 19:02:44 2015 +0000
Revision:
1:a549ef8b142a
Parent:
0:b805b487fbef
SE RESTAURARON LOS ARCHIVO DE LA LIBRER?A;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mauroar211 0:b805b487fbef 1 /**************************************************************************/
mauroar211 0:b805b487fbef 2 /*!
mauroar211 0:b805b487fbef 3 @file emulatetag.cpp
mauroar211 0:b805b487fbef 4 @author Armin Wieser
mauroar211 0:b805b487fbef 5 @license BSD
mauroar211 0:b805b487fbef 6 */
mauroar211 0:b805b487fbef 7 /**************************************************************************/
mauroar211 0:b805b487fbef 8
mauroar211 0:b805b487fbef 9 #include "emulatetag.h"
mauroar211 0:b805b487fbef 10 #include "PN532_debug.h"
mauroar211 0:b805b487fbef 11
mauroar211 0:b805b487fbef 12 #include <string.h>
mauroar211 0:b805b487fbef 13
mauroar211 0:b805b487fbef 14 #define MAX_TGREAD
mauroar211 0:b805b487fbef 15
mauroar211 0:b805b487fbef 16
mauroar211 0:b805b487fbef 17 // Command APDU
mauroar211 0:b805b487fbef 18 #define C_APDU_CLA 0
mauroar211 0:b805b487fbef 19 #define C_APDU_INS 1 // instruction
mauroar211 0:b805b487fbef 20 #define C_APDU_P1 2 // parameter 1
mauroar211 0:b805b487fbef 21 #define C_APDU_P2 3 // parameter 2
mauroar211 0:b805b487fbef 22 #define C_APDU_LC 4 // length command
mauroar211 0:b805b487fbef 23 #define C_APDU_DATA 5 // data
mauroar211 0:b805b487fbef 24
mauroar211 0:b805b487fbef 25 #define C_APDU_P1_SELECT_BY_ID 0x00
mauroar211 0:b805b487fbef 26 #define C_APDU_P1_SELECT_BY_NAME 0x04
mauroar211 0:b805b487fbef 27
mauroar211 0:b805b487fbef 28 // Response APDU
mauroar211 0:b805b487fbef 29 #define R_APDU_SW1_COMMAND_COMPLETE 0x90
mauroar211 0:b805b487fbef 30 #define R_APDU_SW2_COMMAND_COMPLETE 0x00
mauroar211 0:b805b487fbef 31
mauroar211 0:b805b487fbef 32 #define R_APDU_SW1_NDEF_TAG_NOT_FOUND 0x6a
mauroar211 0:b805b487fbef 33 #define R_APDU_SW2_NDEF_TAG_NOT_FOUND 0x82
mauroar211 0:b805b487fbef 34
mauroar211 0:b805b487fbef 35 #define R_APDU_SW1_FUNCTION_NOT_SUPPORTED 0x6A
mauroar211 0:b805b487fbef 36 #define R_APDU_SW2_FUNCTION_NOT_SUPPORTED 0x81
mauroar211 0:b805b487fbef 37
mauroar211 0:b805b487fbef 38 #define R_APDU_SW1_MEMORY_FAILURE 0x65
mauroar211 0:b805b487fbef 39 #define R_APDU_SW2_MEMORY_FAILURE 0x81
mauroar211 0:b805b487fbef 40
mauroar211 0:b805b487fbef 41 #define R_APDU_SW1_END_OF_FILE_BEFORE_REACHED_LE_BYTES 0x62
mauroar211 0:b805b487fbef 42 #define R_APDU_SW2_END_OF_FILE_BEFORE_REACHED_LE_BYTES 0x82
mauroar211 0:b805b487fbef 43
mauroar211 0:b805b487fbef 44 // ISO7816-4 commands
mauroar211 0:b805b487fbef 45 #define ISO7816_SELECT_FILE 0xA4
mauroar211 0:b805b487fbef 46 #define ISO7816_READ_BINARY 0xB0
mauroar211 0:b805b487fbef 47 #define ISO7816_UPDATE_BINARY 0xD6
mauroar211 0:b805b487fbef 48
mauroar211 0:b805b487fbef 49 typedef enum { NONE, CC, NDEF } tag_file; // CC ... Compatibility Container
mauroar211 0:b805b487fbef 50
mauroar211 0:b805b487fbef 51 const uint8_t compatibility_container[] = {
mauroar211 0:b805b487fbef 52 0, 0x0F,
mauroar211 0:b805b487fbef 53 0x20,
mauroar211 0:b805b487fbef 54 0, 0x54,
mauroar211 0:b805b487fbef 55 0, 0xFF,
mauroar211 0:b805b487fbef 56 0x04,
mauroar211 0:b805b487fbef 57 0x06,
mauroar211 0:b805b487fbef 58 0xE1, 0x04,
mauroar211 0:b805b487fbef 59 0xFF, 0xFE,
mauroar211 0:b805b487fbef 60 0x00,
mauroar211 0:b805b487fbef 61 0x00
mauroar211 0:b805b487fbef 62 };
mauroar211 0:b805b487fbef 63
mauroar211 0:b805b487fbef 64 bool EmulateTag::init(){
mauroar211 0:b805b487fbef 65 pn532.begin();
mauroar211 0:b805b487fbef 66 return pn532.SAMConfig();
mauroar211 0:b805b487fbef 67 }
mauroar211 0:b805b487fbef 68
mauroar211 0:b805b487fbef 69 void EmulateTag::setNdefFile(const uint8_t* ndef, const int16_t ndefLength){
mauroar211 0:b805b487fbef 70 if(ndefLength > (NDEF_MAX_LENGTH -2)){
mauroar211 0:b805b487fbef 71 DMSG("ndef file too large (> NDEF_MAX_LENGHT -2) - aborting");
mauroar211 0:b805b487fbef 72 return;
mauroar211 0:b805b487fbef 73 }
mauroar211 0:b805b487fbef 74
mauroar211 0:b805b487fbef 75 ndef_file[0] = ndefLength >> 8;
mauroar211 0:b805b487fbef 76 ndef_file[1] = ndefLength & 0xFF;
mauroar211 0:b805b487fbef 77 memcpy(ndef_file+2, ndef, ndefLength);
mauroar211 0:b805b487fbef 78 }
mauroar211 0:b805b487fbef 79
mauroar211 0:b805b487fbef 80 void EmulateTag::setUid(uint8_t* uid){
mauroar211 0:b805b487fbef 81 uidPtr = uid;
mauroar211 0:b805b487fbef 82 }
mauroar211 0:b805b487fbef 83
mauroar211 0:b805b487fbef 84 bool EmulateTag::emulate(const uint16_t tgInitAsTargetTimeout){
mauroar211 0:b805b487fbef 85
mauroar211 0:b805b487fbef 86 uint8_t command[] = {
mauroar211 0:b805b487fbef 87 PN532_COMMAND_TGINITASTARGET,
mauroar211 0:b805b487fbef 88 5, // MODE: PICC only, Passive only
mauroar211 0:b805b487fbef 89
mauroar211 0:b805b487fbef 90 0x04, 0x00, // SENS_RES
mauroar211 0:b805b487fbef 91 0x00, 0x00, 0x00, // NFCID1
mauroar211 0:b805b487fbef 92 0x20, // SEL_RES
mauroar211 0:b805b487fbef 93
mauroar211 0:b805b487fbef 94 0,0,0,0,0,0,0,0,
mauroar211 0:b805b487fbef 95 0,0,0,0,0,0,0,0, // FeliCaParams
mauroar211 0:b805b487fbef 96 0,0,
mauroar211 0:b805b487fbef 97
mauroar211 0:b805b487fbef 98 0,0,0,0,0,0,0,0,0,0, // NFCID3t
mauroar211 0:b805b487fbef 99
mauroar211 0:b805b487fbef 100 0, // length of general bytes
mauroar211 0:b805b487fbef 101 0 // length of historical bytes
mauroar211 0:b805b487fbef 102 };
mauroar211 0:b805b487fbef 103
mauroar211 0:b805b487fbef 104 if(uidPtr != 0){ // if uid is set copy 3 bytes to nfcid1
mauroar211 0:b805b487fbef 105 memcpy(command + 4, uidPtr, 3);
mauroar211 0:b805b487fbef 106 }
mauroar211 0:b805b487fbef 107
mauroar211 0:b805b487fbef 108 if(1 != pn532.tgInitAsTarget(command,sizeof(command), tgInitAsTargetTimeout)){
mauroar211 0:b805b487fbef 109 DMSG("tgInitAsTarget failed or timed out!");
mauroar211 0:b805b487fbef 110 return false;
mauroar211 0:b805b487fbef 111 }
mauroar211 0:b805b487fbef 112
mauroar211 0:b805b487fbef 113 tagWrittenByInitiator = false;
mauroar211 0:b805b487fbef 114
mauroar211 0:b805b487fbef 115 uint8_t rwbuf[128];
mauroar211 0:b805b487fbef 116 uint8_t sendlen;
mauroar211 0:b805b487fbef 117 int16_t status;
mauroar211 0:b805b487fbef 118 tag_file currentFile = NONE;
mauroar211 0:b805b487fbef 119 //uint16_t cc_size = sizeof(compatibility_container);
mauroar211 0:b805b487fbef 120 bool runLoop = true;
mauroar211 0:b805b487fbef 121
mauroar211 0:b805b487fbef 122 while(runLoop){
mauroar211 0:b805b487fbef 123 status = pn532.tgGetData(rwbuf, sizeof(rwbuf));
mauroar211 0:b805b487fbef 124 if(status < 0){
mauroar211 0:b805b487fbef 125 DMSG("tgGetData failed!\n");
mauroar211 0:b805b487fbef 126 pn532.inRelease();
mauroar211 0:b805b487fbef 127 return true;
mauroar211 0:b805b487fbef 128 }
mauroar211 0:b805b487fbef 129
mauroar211 0:b805b487fbef 130 uint8_t p1 = rwbuf[C_APDU_P1];
mauroar211 0:b805b487fbef 131 uint8_t p2 = rwbuf[C_APDU_P2];
mauroar211 0:b805b487fbef 132 uint8_t lc = rwbuf[C_APDU_LC];
mauroar211 0:b805b487fbef 133 uint16_t p1p2_length = ((int16_t) p1 << 8) + p2;
mauroar211 0:b805b487fbef 134
mauroar211 0:b805b487fbef 135 switch(rwbuf[C_APDU_INS]){
mauroar211 0:b805b487fbef 136 case ISO7816_SELECT_FILE:
mauroar211 0:b805b487fbef 137 switch(p1){
mauroar211 0:b805b487fbef 138 case C_APDU_P1_SELECT_BY_ID:
mauroar211 0:b805b487fbef 139 if(p2 != 0x0c){
mauroar211 0:b805b487fbef 140 DMSG("C_APDU_P2 != 0x0c\n");
mauroar211 0:b805b487fbef 141 setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 142 } else if(lc == 2 && rwbuf[C_APDU_DATA] == 0xE1 && (rwbuf[C_APDU_DATA+1] == 0x03 || rwbuf[C_APDU_DATA+1] == 0x04)){
mauroar211 0:b805b487fbef 143 setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 144 if(rwbuf[C_APDU_DATA+1] == 0x03){
mauroar211 0:b805b487fbef 145 currentFile = CC;
mauroar211 0:b805b487fbef 146 } else if(rwbuf[C_APDU_DATA+1] == 0x04){
mauroar211 0:b805b487fbef 147 currentFile = NDEF;
mauroar211 0:b805b487fbef 148 }
mauroar211 0:b805b487fbef 149 } else {
mauroar211 0:b805b487fbef 150 setResponse(TAG_NOT_FOUND, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 151 }
mauroar211 0:b805b487fbef 152 break;
mauroar211 0:b805b487fbef 153 case C_APDU_P1_SELECT_BY_NAME:
mauroar211 0:b805b487fbef 154 const uint8_t ndef_tag_application_name_v2[] = {0, 0x7, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 };
mauroar211 0:b805b487fbef 155 if(0 == memcmp(ndef_tag_application_name_v2, rwbuf + C_APDU_P2, sizeof(ndef_tag_application_name_v2))){
mauroar211 0:b805b487fbef 156 setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 157 } else{
mauroar211 0:b805b487fbef 158 DMSG("function not supported\n");
mauroar211 0:b805b487fbef 159 setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 160 }
mauroar211 0:b805b487fbef 161 break;
mauroar211 0:b805b487fbef 162 }
mauroar211 0:b805b487fbef 163 break;
mauroar211 0:b805b487fbef 164 case ISO7816_READ_BINARY:
mauroar211 0:b805b487fbef 165 switch(currentFile){
mauroar211 0:b805b487fbef 166 case NONE:
mauroar211 0:b805b487fbef 167 setResponse(TAG_NOT_FOUND, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 168 break;
mauroar211 0:b805b487fbef 169 case CC:
mauroar211 0:b805b487fbef 170 if( p1p2_length > NDEF_MAX_LENGTH){
mauroar211 0:b805b487fbef 171 setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 172 }else {
mauroar211 0:b805b487fbef 173 memcpy(rwbuf,compatibility_container + p1p2_length, lc);
mauroar211 0:b805b487fbef 174 setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc);
mauroar211 0:b805b487fbef 175 }
mauroar211 0:b805b487fbef 176 break;
mauroar211 0:b805b487fbef 177 case NDEF:
mauroar211 0:b805b487fbef 178 if( p1p2_length > NDEF_MAX_LENGTH){
mauroar211 0:b805b487fbef 179 setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 180 }else {
mauroar211 0:b805b487fbef 181 memcpy(rwbuf, ndef_file + p1p2_length, lc);
mauroar211 0:b805b487fbef 182 setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc);
mauroar211 0:b805b487fbef 183 }
mauroar211 0:b805b487fbef 184 break;
mauroar211 0:b805b487fbef 185 }
mauroar211 0:b805b487fbef 186 break;
mauroar211 0:b805b487fbef 187 case ISO7816_UPDATE_BINARY:
mauroar211 0:b805b487fbef 188 if( p1p2_length > NDEF_MAX_LENGTH){
mauroar211 0:b805b487fbef 189 setResponse(MEMORY_FAILURE, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 190 }
mauroar211 0:b805b487fbef 191 else{
mauroar211 0:b805b487fbef 192 memcpy(ndef_file + p1p2_length, rwbuf + C_APDU_DATA, lc);
mauroar211 0:b805b487fbef 193 setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 194 tagWrittenByInitiator = true;
mauroar211 0:b805b487fbef 195 }
mauroar211 0:b805b487fbef 196 break;
mauroar211 0:b805b487fbef 197 default:
mauroar211 0:b805b487fbef 198 DMSG("Command not supported!");
mauroar211 0:b805b487fbef 199 DMSG_HEX(rwbuf[C_APDU_INS]);
mauroar211 0:b805b487fbef 200 DMSG("\n");
mauroar211 0:b805b487fbef 201 setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
mauroar211 0:b805b487fbef 202 }
mauroar211 0:b805b487fbef 203 status = pn532.tgSetData(rwbuf, sendlen);
mauroar211 0:b805b487fbef 204 if(status < 0){
mauroar211 0:b805b487fbef 205 DMSG("tgSetData failed\n!");
mauroar211 0:b805b487fbef 206 pn532.inRelease();
mauroar211 0:b805b487fbef 207 return true;
mauroar211 0:b805b487fbef 208 }
mauroar211 0:b805b487fbef 209 }
mauroar211 0:b805b487fbef 210 pn532.inRelease();
mauroar211 0:b805b487fbef 211 return true;
mauroar211 0:b805b487fbef 212 }
mauroar211 0:b805b487fbef 213
mauroar211 0:b805b487fbef 214 void EmulateTag::setResponse(responseCommand cmd, uint8_t* buf, uint8_t* sendlen, uint8_t sendlenOffset){
mauroar211 0:b805b487fbef 215 switch(cmd){
mauroar211 0:b805b487fbef 216 case COMMAND_COMPLETE:
mauroar211 0:b805b487fbef 217 buf[0] = R_APDU_SW1_COMMAND_COMPLETE;
mauroar211 0:b805b487fbef 218 buf[1] = R_APDU_SW2_COMMAND_COMPLETE;
mauroar211 0:b805b487fbef 219 *sendlen = 2 + sendlenOffset;
mauroar211 0:b805b487fbef 220 break;
mauroar211 0:b805b487fbef 221 case TAG_NOT_FOUND:
mauroar211 0:b805b487fbef 222 buf[0] = R_APDU_SW1_NDEF_TAG_NOT_FOUND;
mauroar211 0:b805b487fbef 223 buf[1] = R_APDU_SW2_NDEF_TAG_NOT_FOUND;
mauroar211 0:b805b487fbef 224 *sendlen = 2;
mauroar211 0:b805b487fbef 225 break;
mauroar211 0:b805b487fbef 226 case FUNCTION_NOT_SUPPORTED:
mauroar211 0:b805b487fbef 227 buf[0] = R_APDU_SW1_FUNCTION_NOT_SUPPORTED;
mauroar211 0:b805b487fbef 228 buf[1] = R_APDU_SW2_FUNCTION_NOT_SUPPORTED;
mauroar211 0:b805b487fbef 229 *sendlen = 2;
mauroar211 0:b805b487fbef 230 break;
mauroar211 0:b805b487fbef 231 case MEMORY_FAILURE:
mauroar211 0:b805b487fbef 232 buf[0] = R_APDU_SW1_MEMORY_FAILURE;
mauroar211 0:b805b487fbef 233 buf[1] = R_APDU_SW2_MEMORY_FAILURE;
mauroar211 0:b805b487fbef 234 *sendlen = 2;
mauroar211 0:b805b487fbef 235 break;
mauroar211 0:b805b487fbef 236 case END_OF_FILE_BEFORE_REACHED_LE_BYTES:
mauroar211 0:b805b487fbef 237 buf[0] = R_APDU_SW1_END_OF_FILE_BEFORE_REACHED_LE_BYTES;
mauroar211 0:b805b487fbef 238 buf[1] = R_APDU_SW2_END_OF_FILE_BEFORE_REACHED_LE_BYTES;
mauroar211 0:b805b487fbef 239 *sendlen= 2;
mauroar211 0:b805b487fbef 240 break;
mauroar211 0:b805b487fbef 241 }
mauroar211 0:b805b487fbef 242 }