Forked from LibPN532

Dependents:   NFC_Secure_Access NFC_Secure_Access

Fork of LibPN532 by dotnfc Tang

Committer:
udareaniket
Date:
Sun Apr 22 23:29:20 2018 +0000
Revision:
2:9a2ab3fa7862
Parent:
0:db8030e71f55
Initial commit;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dotnfc 0:db8030e71f55 1 /**************************************************************************/
dotnfc 0:db8030e71f55 2 /*!
dotnfc 0:db8030e71f55 3 @file PN532.cpp
dotnfc 0:db8030e71f55 4 @author Adafruit Industries & Seeed Studio
dotnfc 0:db8030e71f55 5 @license BSD
dotnfc 0:db8030e71f55 6 */
dotnfc 0:db8030e71f55 7 /**************************************************************************/
dotnfc 0:db8030e71f55 8
dotnfc 0:db8030e71f55 9 #include "Arduino.h"
dotnfc 0:db8030e71f55 10 #include "PN532.h"
dotnfc 0:db8030e71f55 11 #include "PN532_debug.h"
dotnfc 0:db8030e71f55 12 #include <string.h>
dotnfc 0:db8030e71f55 13
dotnfc 0:db8030e71f55 14 #define HAL(func) (_interface->func)
dotnfc 0:db8030e71f55 15
dotnfc 0:db8030e71f55 16 PN532::PN532(PN532Interface &interface)
dotnfc 0:db8030e71f55 17 {
dotnfc 0:db8030e71f55 18 _interface = &interface;
dotnfc 0:db8030e71f55 19 }
dotnfc 0:db8030e71f55 20
dotnfc 0:db8030e71f55 21 /**************************************************************************/
dotnfc 0:db8030e71f55 22 /*!
dotnfc 0:db8030e71f55 23 @brief Setups the HW
dotnfc 0:db8030e71f55 24 */
dotnfc 0:db8030e71f55 25 /**************************************************************************/
dotnfc 0:db8030e71f55 26 void PN532::begin()
dotnfc 0:db8030e71f55 27 {
dotnfc 0:db8030e71f55 28 HAL(begin)();
dotnfc 0:db8030e71f55 29 HAL(wakeup)();
dotnfc 0:db8030e71f55 30 }
dotnfc 0:db8030e71f55 31
dotnfc 0:db8030e71f55 32 /**************************************************************************/
dotnfc 0:db8030e71f55 33 /*!
dotnfc 0:db8030e71f55 34 @brief Prints a hexadecimal value in plain characters
dotnfc 0:db8030e71f55 35
dotnfc 0:db8030e71f55 36 @param data Pointer to the uint8_t data
dotnfc 0:db8030e71f55 37 @param numBytes Data length in bytes
dotnfc 0:db8030e71f55 38 */
dotnfc 0:db8030e71f55 39 /**************************************************************************/
dotnfc 0:db8030e71f55 40 void PN532::PrintHex(const uint8_t *data, const uint32_t numBytes)
dotnfc 0:db8030e71f55 41 {
dotnfc 0:db8030e71f55 42 #ifdef ARDUINO
dotnfc 0:db8030e71f55 43 for (uint8_t i = 0; i < numBytes; i++) {
dotnfc 0:db8030e71f55 44 if (data[i] < 0x10) {
dotnfc 0:db8030e71f55 45 Serial.print(" 0");
dotnfc 0:db8030e71f55 46 } else {
dotnfc 0:db8030e71f55 47 Serial.print(' ');
dotnfc 0:db8030e71f55 48 }
dotnfc 0:db8030e71f55 49 Serial.print(data[i], HEX);
dotnfc 0:db8030e71f55 50 }
dotnfc 0:db8030e71f55 51 Serial.println("");
dotnfc 0:db8030e71f55 52 #else
dotnfc 0:db8030e71f55 53 for (uint8_t i = 0; i < numBytes; i++) {
dotnfc 0:db8030e71f55 54 printf(" %2X", data[i]);
dotnfc 0:db8030e71f55 55 }
dotnfc 0:db8030e71f55 56 printf("\n");
dotnfc 0:db8030e71f55 57 #endif
dotnfc 0:db8030e71f55 58 }
dotnfc 0:db8030e71f55 59
dotnfc 0:db8030e71f55 60 /**************************************************************************/
dotnfc 0:db8030e71f55 61 /*!
dotnfc 0:db8030e71f55 62 @brief Prints a hexadecimal value in plain characters, along with
dotnfc 0:db8030e71f55 63 the char equivalents in the following format
dotnfc 0:db8030e71f55 64
dotnfc 0:db8030e71f55 65 00 00 00 00 00 00 ......
dotnfc 0:db8030e71f55 66
dotnfc 0:db8030e71f55 67 @param data Pointer to the data
dotnfc 0:db8030e71f55 68 @param numBytes Data length in bytes
dotnfc 0:db8030e71f55 69 */
dotnfc 0:db8030e71f55 70 /**************************************************************************/
dotnfc 0:db8030e71f55 71 void PN532::PrintHexChar(const uint8_t *data, const uint32_t numBytes)
dotnfc 0:db8030e71f55 72 {
dotnfc 0:db8030e71f55 73 #ifdef ARDUINO
dotnfc 0:db8030e71f55 74 for (uint8_t i = 0; i < numBytes; i++) {
dotnfc 0:db8030e71f55 75 if (data[i] < 0x10) {
dotnfc 0:db8030e71f55 76 Serial.print(" 0");
dotnfc 0:db8030e71f55 77 } else {
dotnfc 0:db8030e71f55 78 Serial.print(' ');
dotnfc 0:db8030e71f55 79 }
dotnfc 0:db8030e71f55 80 Serial.print(data[i], HEX);
dotnfc 0:db8030e71f55 81 }
dotnfc 0:db8030e71f55 82 Serial.print(" ");
dotnfc 0:db8030e71f55 83 for (uint8_t i = 0; i < numBytes; i++) {
dotnfc 0:db8030e71f55 84 char c = data[i];
dotnfc 0:db8030e71f55 85 if (c <= 0x1f || c > 0x7f) {
dotnfc 0:db8030e71f55 86 Serial.print('.');
dotnfc 0:db8030e71f55 87 } else {
dotnfc 0:db8030e71f55 88 Serial.print(c);
dotnfc 0:db8030e71f55 89 }
dotnfc 0:db8030e71f55 90 }
dotnfc 0:db8030e71f55 91 Serial.println("");
dotnfc 0:db8030e71f55 92 #else
dotnfc 0:db8030e71f55 93 for (uint8_t i = 0; i < numBytes; i++) {
dotnfc 0:db8030e71f55 94 printf(" %2X", data[i]);
dotnfc 0:db8030e71f55 95 }
dotnfc 0:db8030e71f55 96 printf(" ");
dotnfc 0:db8030e71f55 97 for (uint8_t i = 0; i < numBytes; i++) {
dotnfc 0:db8030e71f55 98 char c = data[i];
dotnfc 0:db8030e71f55 99 if (c <= 0x1f || c > 0x7f) {
dotnfc 0:db8030e71f55 100 printf(".");
dotnfc 0:db8030e71f55 101 } else {
dotnfc 0:db8030e71f55 102 printf("%c", c);
dotnfc 0:db8030e71f55 103 }
dotnfc 0:db8030e71f55 104 printf("\n");
dotnfc 0:db8030e71f55 105 }
dotnfc 0:db8030e71f55 106 #endif
dotnfc 0:db8030e71f55 107 }
dotnfc 0:db8030e71f55 108
dotnfc 0:db8030e71f55 109 /**************************************************************************/
dotnfc 0:db8030e71f55 110 /*!
dotnfc 0:db8030e71f55 111 @brief Checks the firmware version of the PN5xx chip
dotnfc 0:db8030e71f55 112
dotnfc 0:db8030e71f55 113 @returns The chip's firmware version and ID
dotnfc 0:db8030e71f55 114 */
dotnfc 0:db8030e71f55 115 /**************************************************************************/
dotnfc 0:db8030e71f55 116 uint32_t PN532::getFirmwareVersion(void)
dotnfc 0:db8030e71f55 117 {
dotnfc 0:db8030e71f55 118 uint32_t response;
dotnfc 0:db8030e71f55 119
dotnfc 0:db8030e71f55 120 pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
dotnfc 0:db8030e71f55 121
dotnfc 0:db8030e71f55 122 if (HAL(writeCommand)(pn532_packetbuffer, 1)) {
dotnfc 0:db8030e71f55 123 return 0;
dotnfc 0:db8030e71f55 124 }
dotnfc 0:db8030e71f55 125
dotnfc 0:db8030e71f55 126 // read data packet
dotnfc 0:db8030e71f55 127 int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
dotnfc 0:db8030e71f55 128 if (0 > status) {
dotnfc 0:db8030e71f55 129 return 0;
dotnfc 0:db8030e71f55 130 }
dotnfc 0:db8030e71f55 131
dotnfc 0:db8030e71f55 132 response = pn532_packetbuffer[0];
dotnfc 0:db8030e71f55 133 response <<= 8;
dotnfc 0:db8030e71f55 134 response |= pn532_packetbuffer[1];
dotnfc 0:db8030e71f55 135 response <<= 8;
dotnfc 0:db8030e71f55 136 response |= pn532_packetbuffer[2];
dotnfc 0:db8030e71f55 137 response <<= 8;
dotnfc 0:db8030e71f55 138 response |= pn532_packetbuffer[3];
dotnfc 0:db8030e71f55 139
dotnfc 0:db8030e71f55 140 return response;
dotnfc 0:db8030e71f55 141 }
dotnfc 0:db8030e71f55 142
dotnfc 0:db8030e71f55 143
dotnfc 0:db8030e71f55 144 /**************************************************************************/
dotnfc 0:db8030e71f55 145 /*!
dotnfc 0:db8030e71f55 146 Writes an 8-bit value that sets the state of the PN532's GPIO pins
dotnfc 0:db8030e71f55 147
dotnfc 0:db8030e71f55 148 @warning This function is provided exclusively for board testing and
dotnfc 0:db8030e71f55 149 is dangerous since it will throw an error if any pin other
dotnfc 0:db8030e71f55 150 than the ones marked "Can be used as GPIO" are modified! All
dotnfc 0:db8030e71f55 151 pins that can not be used as GPIO should ALWAYS be left high
dotnfc 0:db8030e71f55 152 (value = 1) or the system will become unstable and a HW reset
dotnfc 0:db8030e71f55 153 will be required to recover the PN532.
dotnfc 0:db8030e71f55 154
dotnfc 0:db8030e71f55 155 pinState[0] = P30 Can be used as GPIO
dotnfc 0:db8030e71f55 156 pinState[1] = P31 Can be used as GPIO
dotnfc 0:db8030e71f55 157 pinState[2] = P32 *** RESERVED (Must be 1!) ***
dotnfc 0:db8030e71f55 158 pinState[3] = P33 Can be used as GPIO
dotnfc 0:db8030e71f55 159 pinState[4] = P34 *** RESERVED (Must be 1!) ***
dotnfc 0:db8030e71f55 160 pinState[5] = P35 Can be used as GPIO
dotnfc 0:db8030e71f55 161
dotnfc 0:db8030e71f55 162 @returns 1 if everything executed properly, 0 for an error
dotnfc 0:db8030e71f55 163 */
dotnfc 0:db8030e71f55 164 /**************************************************************************/
dotnfc 0:db8030e71f55 165 bool PN532::writeGPIO(uint8_t pinstate)
dotnfc 0:db8030e71f55 166 {
dotnfc 0:db8030e71f55 167 // Make sure pinstate does not try to toggle P32 or P34
dotnfc 0:db8030e71f55 168 pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34);
dotnfc 0:db8030e71f55 169
dotnfc 0:db8030e71f55 170 // Fill command buffer
dotnfc 0:db8030e71f55 171 pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO;
dotnfc 0:db8030e71f55 172 pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins
dotnfc 0:db8030e71f55 173 pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by I2C)
dotnfc 0:db8030e71f55 174
dotnfc 0:db8030e71f55 175 DMSG("Writing P3 GPIO: ");
dotnfc 0:db8030e71f55 176 DMSG_HEX(pn532_packetbuffer[1]);
dotnfc 0:db8030e71f55 177 DMSG("\n");
dotnfc 0:db8030e71f55 178
dotnfc 0:db8030e71f55 179 // Send the WRITEGPIO command (0x0E)
dotnfc 0:db8030e71f55 180 if (HAL(writeCommand)(pn532_packetbuffer, 3))
dotnfc 0:db8030e71f55 181 return 0;
dotnfc 0:db8030e71f55 182
dotnfc 0:db8030e71f55 183 return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
dotnfc 0:db8030e71f55 184 }
dotnfc 0:db8030e71f55 185
dotnfc 0:db8030e71f55 186 /**************************************************************************/
dotnfc 0:db8030e71f55 187 /*!
dotnfc 0:db8030e71f55 188 Reads the state of the PN532's GPIO pins
dotnfc 0:db8030e71f55 189
dotnfc 0:db8030e71f55 190 @returns An 8-bit value containing the pin state where:
dotnfc 0:db8030e71f55 191
dotnfc 0:db8030e71f55 192 pinState[0] = P30
dotnfc 0:db8030e71f55 193 pinState[1] = P31
dotnfc 0:db8030e71f55 194 pinState[2] = P32
dotnfc 0:db8030e71f55 195 pinState[3] = P33
dotnfc 0:db8030e71f55 196 pinState[4] = P34
dotnfc 0:db8030e71f55 197 pinState[5] = P35
dotnfc 0:db8030e71f55 198 */
dotnfc 0:db8030e71f55 199 /**************************************************************************/
dotnfc 0:db8030e71f55 200 uint8_t PN532::readGPIO(void)
dotnfc 0:db8030e71f55 201 {
dotnfc 0:db8030e71f55 202 pn532_packetbuffer[0] = PN532_COMMAND_READGPIO;
dotnfc 0:db8030e71f55 203
dotnfc 0:db8030e71f55 204 // Send the READGPIO command (0x0C)
dotnfc 0:db8030e71f55 205 if (HAL(writeCommand)(pn532_packetbuffer, 1))
dotnfc 0:db8030e71f55 206 return 0x0;
dotnfc 0:db8030e71f55 207
dotnfc 0:db8030e71f55 208 HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
dotnfc 0:db8030e71f55 209
dotnfc 0:db8030e71f55 210 /* READGPIO response without prefix and suffix should be in the following format:
dotnfc 0:db8030e71f55 211
dotnfc 0:db8030e71f55 212 byte Description
dotnfc 0:db8030e71f55 213 ------------- ------------------------------------------
dotnfc 0:db8030e71f55 214 b0 P3 GPIO Pins
dotnfc 0:db8030e71f55 215 b1 P7 GPIO Pins (not used ... taken by I2C)
dotnfc 0:db8030e71f55 216 b2 Interface Mode Pins (not used ... bus select pins)
dotnfc 0:db8030e71f55 217 */
dotnfc 0:db8030e71f55 218
dotnfc 0:db8030e71f55 219
dotnfc 0:db8030e71f55 220 DMSG("P3 GPIO: "); DMSG_HEX(pn532_packetbuffer[7]);
dotnfc 0:db8030e71f55 221 DMSG("P7 GPIO: "); DMSG_HEX(pn532_packetbuffer[8]);
dotnfc 0:db8030e71f55 222 DMSG("I0I1 GPIO: "); DMSG_HEX(pn532_packetbuffer[9]);
dotnfc 0:db8030e71f55 223 DMSG("\n");
dotnfc 0:db8030e71f55 224
dotnfc 0:db8030e71f55 225 return pn532_packetbuffer[0];
dotnfc 0:db8030e71f55 226 }
dotnfc 0:db8030e71f55 227
dotnfc 0:db8030e71f55 228 /**************************************************************************/
dotnfc 0:db8030e71f55 229 /*!
dotnfc 0:db8030e71f55 230 @brief Configures the SAM (Secure Access Module)
dotnfc 0:db8030e71f55 231 */
dotnfc 0:db8030e71f55 232 /**************************************************************************/
dotnfc 0:db8030e71f55 233 bool PN532::SAMConfig(void)
dotnfc 0:db8030e71f55 234 {
dotnfc 0:db8030e71f55 235 pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
dotnfc 0:db8030e71f55 236 pn532_packetbuffer[1] = 0x01; // normal mode;
dotnfc 0:db8030e71f55 237 pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
dotnfc 0:db8030e71f55 238 pn532_packetbuffer[3] = 0x01; // use IRQ pin!
dotnfc 0:db8030e71f55 239
dotnfc 0:db8030e71f55 240 DMSG("SAMConfig\n");
dotnfc 0:db8030e71f55 241
dotnfc 0:db8030e71f55 242 if (HAL(writeCommand)(pn532_packetbuffer, 4))
dotnfc 0:db8030e71f55 243 return false;
dotnfc 0:db8030e71f55 244
dotnfc 0:db8030e71f55 245 return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
dotnfc 0:db8030e71f55 246 }
dotnfc 0:db8030e71f55 247
dotnfc 0:db8030e71f55 248 /**************************************************************************/
dotnfc 0:db8030e71f55 249 /*!
dotnfc 0:db8030e71f55 250 Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register
dotnfc 0:db8030e71f55 251
dotnfc 0:db8030e71f55 252 @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout
dotnfc 0:db8030e71f55 253 after mxRetries
dotnfc 0:db8030e71f55 254
dotnfc 0:db8030e71f55 255 @returns 1 if everything executed properly, 0 for an error
dotnfc 0:db8030e71f55 256 */
dotnfc 0:db8030e71f55 257 /**************************************************************************/
dotnfc 0:db8030e71f55 258 bool PN532::setPassiveActivationRetries(uint8_t maxRetries)
dotnfc 0:db8030e71f55 259 {
dotnfc 0:db8030e71f55 260 pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
dotnfc 0:db8030e71f55 261 pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries)
dotnfc 0:db8030e71f55 262 pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF)
dotnfc 0:db8030e71f55 263 pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01)
dotnfc 0:db8030e71f55 264 pn532_packetbuffer[4] = maxRetries;
dotnfc 0:db8030e71f55 265
dotnfc 0:db8030e71f55 266 if (HAL(writeCommand)(pn532_packetbuffer, 5))
dotnfc 0:db8030e71f55 267 return 0x0; // no ACK
dotnfc 0:db8030e71f55 268
dotnfc 0:db8030e71f55 269 return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
dotnfc 0:db8030e71f55 270 }
dotnfc 0:db8030e71f55 271
dotnfc 0:db8030e71f55 272 /***** ISO14443A Commands ******/
dotnfc 0:db8030e71f55 273
dotnfc 0:db8030e71f55 274 /**************************************************************************/
dotnfc 0:db8030e71f55 275 /*!
dotnfc 0:db8030e71f55 276 Waits for an ISO14443A target to enter the field
dotnfc 0:db8030e71f55 277
dotnfc 0:db8030e71f55 278 @param cardBaudRate Baud rate of the card
dotnfc 0:db8030e71f55 279 @param uid Pointer to the array that will be populated
dotnfc 0:db8030e71f55 280 with the card's UID (up to 7 bytes)
dotnfc 0:db8030e71f55 281 @param uidLength Pointer to the variable that will hold the
dotnfc 0:db8030e71f55 282 length of the card's UID.
dotnfc 0:db8030e71f55 283 @param timeout The number of tries before timing out
dotnfc 0:db8030e71f55 284 @param inlist If set to true, the card will be inlisted
dotnfc 0:db8030e71f55 285
dotnfc 0:db8030e71f55 286 @returns 1 if everything executed properly, 0 for an error
dotnfc 0:db8030e71f55 287 */
dotnfc 0:db8030e71f55 288 /**************************************************************************/
dotnfc 0:db8030e71f55 289 bool PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout, bool inlist)
dotnfc 0:db8030e71f55 290 {
dotnfc 0:db8030e71f55 291 pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
dotnfc 0:db8030e71f55 292 pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later)
dotnfc 0:db8030e71f55 293 pn532_packetbuffer[2] = cardbaudrate;
dotnfc 0:db8030e71f55 294
dotnfc 0:db8030e71f55 295 if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
dotnfc 0:db8030e71f55 296 return 0x0; // command failed
dotnfc 0:db8030e71f55 297 }
dotnfc 0:db8030e71f55 298
dotnfc 0:db8030e71f55 299 // read data packet
dotnfc 0:db8030e71f55 300 if (HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) {
dotnfc 0:db8030e71f55 301 return 0x0;
dotnfc 0:db8030e71f55 302 }
dotnfc 0:db8030e71f55 303
dotnfc 0:db8030e71f55 304 // check some basic stuff
dotnfc 0:db8030e71f55 305 /* ISO14443A card response should be in the following format:
dotnfc 0:db8030e71f55 306
dotnfc 0:db8030e71f55 307 byte Description
dotnfc 0:db8030e71f55 308 ------------- ------------------------------------------
dotnfc 0:db8030e71f55 309 b0 Tags Found
dotnfc 0:db8030e71f55 310 b1 Tag Number (only one used in this example)
dotnfc 0:db8030e71f55 311 b2..3 SENS_RES
dotnfc 0:db8030e71f55 312 b4 SEL_RES
dotnfc 0:db8030e71f55 313 b5 NFCID Length
dotnfc 0:db8030e71f55 314 b6..NFCIDLen NFCID
dotnfc 0:db8030e71f55 315 */
dotnfc 0:db8030e71f55 316
dotnfc 0:db8030e71f55 317 if (pn532_packetbuffer[0] != 1)
dotnfc 0:db8030e71f55 318 return 0;
dotnfc 0:db8030e71f55 319
dotnfc 0:db8030e71f55 320 uint16_t sens_res = pn532_packetbuffer[2];
dotnfc 0:db8030e71f55 321 sens_res <<= 8;
dotnfc 0:db8030e71f55 322 sens_res |= pn532_packetbuffer[3];
dotnfc 0:db8030e71f55 323
dotnfc 0:db8030e71f55 324 DMSG("ATQA: 0x"); DMSG_HEX(sens_res);
udareaniket 2:9a2ab3fa7862 325 DMSG("\n\r");
dotnfc 0:db8030e71f55 326 DMSG("SAK: 0x"); DMSG_HEX(pn532_packetbuffer[4]);
udareaniket 2:9a2ab3fa7862 327 DMSG("\n\r");
dotnfc 0:db8030e71f55 328
dotnfc 0:db8030e71f55 329 /* Card appears to be Mifare Classic */
dotnfc 0:db8030e71f55 330 *uidLength = pn532_packetbuffer[5];
dotnfc 0:db8030e71f55 331
dotnfc 0:db8030e71f55 332 for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) {
dotnfc 0:db8030e71f55 333 uid[i] = pn532_packetbuffer[6 + i];
dotnfc 0:db8030e71f55 334 }
dotnfc 0:db8030e71f55 335
dotnfc 0:db8030e71f55 336 if (inlist) {
dotnfc 0:db8030e71f55 337 inListedTag = pn532_packetbuffer[1];
dotnfc 0:db8030e71f55 338 }
dotnfc 0:db8030e71f55 339
dotnfc 0:db8030e71f55 340 return 1;
dotnfc 0:db8030e71f55 341 }
dotnfc 0:db8030e71f55 342
dotnfc 0:db8030e71f55 343
dotnfc 0:db8030e71f55 344 /***** Mifare Classic Functions ******/
dotnfc 0:db8030e71f55 345
dotnfc 0:db8030e71f55 346 /**************************************************************************/
dotnfc 0:db8030e71f55 347 /*!
dotnfc 0:db8030e71f55 348 Indicates whether the specified block number is the first block
dotnfc 0:db8030e71f55 349 in the sector (block 0 relative to the current sector)
dotnfc 0:db8030e71f55 350 */
dotnfc 0:db8030e71f55 351 /**************************************************************************/
dotnfc 0:db8030e71f55 352 bool PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock)
dotnfc 0:db8030e71f55 353 {
dotnfc 0:db8030e71f55 354 // Test if we are in the small or big sectors
dotnfc 0:db8030e71f55 355 if (uiBlock < 128)
dotnfc 0:db8030e71f55 356 return ((uiBlock) % 4 == 0);
dotnfc 0:db8030e71f55 357 else
dotnfc 0:db8030e71f55 358 return ((uiBlock) % 16 == 0);
dotnfc 0:db8030e71f55 359 }
dotnfc 0:db8030e71f55 360
dotnfc 0:db8030e71f55 361 /**************************************************************************/
dotnfc 0:db8030e71f55 362 /*!
dotnfc 0:db8030e71f55 363 Indicates whether the specified block number is the sector trailer
dotnfc 0:db8030e71f55 364 */
dotnfc 0:db8030e71f55 365 /**************************************************************************/
dotnfc 0:db8030e71f55 366 bool PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock)
dotnfc 0:db8030e71f55 367 {
dotnfc 0:db8030e71f55 368 // Test if we are in the small or big sectors
dotnfc 0:db8030e71f55 369 if (uiBlock < 128)
dotnfc 0:db8030e71f55 370 return ((uiBlock + 1) % 4 == 0);
dotnfc 0:db8030e71f55 371 else
dotnfc 0:db8030e71f55 372 return ((uiBlock + 1) % 16 == 0);
dotnfc 0:db8030e71f55 373 }
dotnfc 0:db8030e71f55 374
dotnfc 0:db8030e71f55 375 /**************************************************************************/
dotnfc 0:db8030e71f55 376 /*!
dotnfc 0:db8030e71f55 377 Tries to authenticate a block of memory on a MIFARE card using the
dotnfc 0:db8030e71f55 378 INDATAEXCHANGE command. See section 7.3.8 of the PN532 User Manual
dotnfc 0:db8030e71f55 379 for more information on sending MIFARE and other commands.
dotnfc 0:db8030e71f55 380
dotnfc 0:db8030e71f55 381 @param uid Pointer to a byte array containing the card UID
dotnfc 0:db8030e71f55 382 @param uidLen The length (in bytes) of the card's UID (Should
dotnfc 0:db8030e71f55 383 be 4 for MIFARE Classic)
dotnfc 0:db8030e71f55 384 @param blockNumber The block number to authenticate. (0..63 for
dotnfc 0:db8030e71f55 385 1KB cards, and 0..255 for 4KB cards).
dotnfc 0:db8030e71f55 386 @param keyNumber Which key type to use during authentication
dotnfc 0:db8030e71f55 387 (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
dotnfc 0:db8030e71f55 388 @param keyData Pointer to a byte array containing the 6 bytes
dotnfc 0:db8030e71f55 389 key value
dotnfc 0:db8030e71f55 390
dotnfc 0:db8030e71f55 391 @returns 1 if everything executed properly, 0 for an error
dotnfc 0:db8030e71f55 392 */
dotnfc 0:db8030e71f55 393 /**************************************************************************/
dotnfc 0:db8030e71f55 394 uint8_t PN532::mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
dotnfc 0:db8030e71f55 395 {
dotnfc 0:db8030e71f55 396 uint8_t i;
dotnfc 0:db8030e71f55 397
dotnfc 0:db8030e71f55 398 // Hang on to the key and uid data
dotnfc 0:db8030e71f55 399 memcpy (_key, keyData, 6);
dotnfc 0:db8030e71f55 400 memcpy (_uid, uid, uidLen);
dotnfc 0:db8030e71f55 401 _uidLen = uidLen;
dotnfc 0:db8030e71f55 402
dotnfc 0:db8030e71f55 403 // Prepare the authentication command //
dotnfc 0:db8030e71f55 404 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */
dotnfc 0:db8030e71f55 405 pn532_packetbuffer[1] = 1; /* Max card numbers */
dotnfc 0:db8030e71f55 406 pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
dotnfc 0:db8030e71f55 407 pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */
dotnfc 0:db8030e71f55 408 memcpy (pn532_packetbuffer + 4, _key, 6);
dotnfc 0:db8030e71f55 409 for (i = 0; i < _uidLen; i++) {
dotnfc 0:db8030e71f55 410 pn532_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */
dotnfc 0:db8030e71f55 411 }
dotnfc 0:db8030e71f55 412
dotnfc 0:db8030e71f55 413 if (HAL(writeCommand)(pn532_packetbuffer, 10 + _uidLen))
dotnfc 0:db8030e71f55 414 return 0;
dotnfc 0:db8030e71f55 415
dotnfc 0:db8030e71f55 416 // Read the response packet
dotnfc 0:db8030e71f55 417 HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
dotnfc 0:db8030e71f55 418
dotnfc 0:db8030e71f55 419 // Check if the response is valid and we are authenticated???
dotnfc 0:db8030e71f55 420 // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
dotnfc 0:db8030e71f55 421 // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
dotnfc 0:db8030e71f55 422 if (pn532_packetbuffer[0] != 0x00) {
dotnfc 0:db8030e71f55 423 DMSG("Authentification failed\n");
dotnfc 0:db8030e71f55 424 return 0;
dotnfc 0:db8030e71f55 425 }
dotnfc 0:db8030e71f55 426
dotnfc 0:db8030e71f55 427 return 1;
dotnfc 0:db8030e71f55 428 }
dotnfc 0:db8030e71f55 429
dotnfc 0:db8030e71f55 430 /**************************************************************************/
dotnfc 0:db8030e71f55 431 /*!
dotnfc 0:db8030e71f55 432 Tries to read an entire 16-bytes data block at the specified block
dotnfc 0:db8030e71f55 433 address.
dotnfc 0:db8030e71f55 434
dotnfc 0:db8030e71f55 435 @param blockNumber The block number to authenticate. (0..63 for
dotnfc 0:db8030e71f55 436 1KB cards, and 0..255 for 4KB cards).
dotnfc 0:db8030e71f55 437 @param data Pointer to the byte array that will hold the
dotnfc 0:db8030e71f55 438 retrieved data (if any)
dotnfc 0:db8030e71f55 439
dotnfc 0:db8030e71f55 440 @returns 1 if everything executed properly, 0 for an error
dotnfc 0:db8030e71f55 441 */
dotnfc 0:db8030e71f55 442 /**************************************************************************/
dotnfc 0:db8030e71f55 443 uint8_t PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data)
dotnfc 0:db8030e71f55 444 {
dotnfc 0:db8030e71f55 445 DMSG("Trying to read 16 bytes from block ");
dotnfc 0:db8030e71f55 446 DMSG_INT(blockNumber);
dotnfc 0:db8030e71f55 447
dotnfc 0:db8030e71f55 448 /* Prepare the command */
dotnfc 0:db8030e71f55 449 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
dotnfc 0:db8030e71f55 450 pn532_packetbuffer[1] = 1; /* Card number */
dotnfc 0:db8030e71f55 451 pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
dotnfc 0:db8030e71f55 452 pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
dotnfc 0:db8030e71f55 453
dotnfc 0:db8030e71f55 454 /* Send the command */
dotnfc 0:db8030e71f55 455 if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
dotnfc 0:db8030e71f55 456 return 0;
dotnfc 0:db8030e71f55 457 }
dotnfc 0:db8030e71f55 458
dotnfc 0:db8030e71f55 459 /* Read the response packet */
dotnfc 0:db8030e71f55 460 HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
dotnfc 0:db8030e71f55 461
dotnfc 0:db8030e71f55 462 /* If byte 8 isn't 0x00 we probably have an error */
dotnfc 0:db8030e71f55 463 if (pn532_packetbuffer[0] != 0x00) {
dotnfc 0:db8030e71f55 464 return 0;
dotnfc 0:db8030e71f55 465 }
dotnfc 0:db8030e71f55 466
dotnfc 0:db8030e71f55 467 /* Copy the 16 data bytes to the output buffer */
dotnfc 0:db8030e71f55 468 /* Block content starts at byte 9 of a valid response */
dotnfc 0:db8030e71f55 469 memcpy (data, pn532_packetbuffer + 1, 16);
dotnfc 0:db8030e71f55 470
dotnfc 0:db8030e71f55 471 return 1;
dotnfc 0:db8030e71f55 472 }
dotnfc 0:db8030e71f55 473
dotnfc 0:db8030e71f55 474 /**************************************************************************/
dotnfc 0:db8030e71f55 475 /*!
dotnfc 0:db8030e71f55 476 Tries to write an entire 16-bytes data block at the specified block
dotnfc 0:db8030e71f55 477 address.
dotnfc 0:db8030e71f55 478
dotnfc 0:db8030e71f55 479 @param blockNumber The block number to authenticate. (0..63 for
dotnfc 0:db8030e71f55 480 1KB cards, and 0..255 for 4KB cards).
dotnfc 0:db8030e71f55 481 @param data The byte array that contains the data to write.
dotnfc 0:db8030e71f55 482
dotnfc 0:db8030e71f55 483 @returns 1 if everything executed properly, 0 for an error
dotnfc 0:db8030e71f55 484 */
dotnfc 0:db8030e71f55 485 /**************************************************************************/
dotnfc 0:db8030e71f55 486 uint8_t PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data)
dotnfc 0:db8030e71f55 487 {
dotnfc 0:db8030e71f55 488 /* Prepare the first command */
dotnfc 0:db8030e71f55 489 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
dotnfc 0:db8030e71f55 490 pn532_packetbuffer[1] = 1; /* Card number */
dotnfc 0:db8030e71f55 491 pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */
dotnfc 0:db8030e71f55 492 pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
dotnfc 0:db8030e71f55 493 memcpy (pn532_packetbuffer + 4, data, 16); /* Data Payload */
dotnfc 0:db8030e71f55 494
dotnfc 0:db8030e71f55 495 /* Send the command */
dotnfc 0:db8030e71f55 496 if (HAL(writeCommand)(pn532_packetbuffer, 20)) {
dotnfc 0:db8030e71f55 497 return 0;
dotnfc 0:db8030e71f55 498 }
dotnfc 0:db8030e71f55 499
dotnfc 0:db8030e71f55 500 /* Read the response packet */
dotnfc 0:db8030e71f55 501 return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
dotnfc 0:db8030e71f55 502 }
dotnfc 0:db8030e71f55 503
dotnfc 0:db8030e71f55 504 /**************************************************************************/
dotnfc 0:db8030e71f55 505 /*!
dotnfc 0:db8030e71f55 506 Formats a Mifare Classic card to store NDEF Records
dotnfc 0:db8030e71f55 507
dotnfc 0:db8030e71f55 508 @returns 1 if everything executed properly, 0 for an error
dotnfc 0:db8030e71f55 509 */
dotnfc 0:db8030e71f55 510 /**************************************************************************/
dotnfc 0:db8030e71f55 511 uint8_t PN532::mifareclassic_FormatNDEF (void)
dotnfc 0:db8030e71f55 512 {
dotnfc 0:db8030e71f55 513 uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
dotnfc 0:db8030e71f55 514 uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
dotnfc 0:db8030e71f55 515 uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
dotnfc 0:db8030e71f55 516
dotnfc 0:db8030e71f55 517 // Note 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 must be used for key A
dotnfc 0:db8030e71f55 518 // for the MAD sector in NDEF records (sector 0)
dotnfc 0:db8030e71f55 519
dotnfc 0:db8030e71f55 520 // Write block 1 and 2 to the card
dotnfc 0:db8030e71f55 521 if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1)))
dotnfc 0:db8030e71f55 522 return 0;
dotnfc 0:db8030e71f55 523 if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2)))
dotnfc 0:db8030e71f55 524 return 0;
dotnfc 0:db8030e71f55 525 // Write key A and access rights card
dotnfc 0:db8030e71f55 526 if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3)))
dotnfc 0:db8030e71f55 527 return 0;
dotnfc 0:db8030e71f55 528
dotnfc 0:db8030e71f55 529 // Seems that everything was OK (?!)
dotnfc 0:db8030e71f55 530 return 1;
dotnfc 0:db8030e71f55 531 }
dotnfc 0:db8030e71f55 532
dotnfc 0:db8030e71f55 533 /**************************************************************************/
dotnfc 0:db8030e71f55 534 /*!
dotnfc 0:db8030e71f55 535 Writes an NDEF URI Record to the specified sector (1..15)
dotnfc 0:db8030e71f55 536
dotnfc 0:db8030e71f55 537 Note that this function assumes that the Mifare Classic card is
dotnfc 0:db8030e71f55 538 already formatted to work as an "NFC Forum Tag" and uses a MAD1
dotnfc 0:db8030e71f55 539 file system. You can use the NXP TagWriter app on Android to
dotnfc 0:db8030e71f55 540 properly format cards for this.
dotnfc 0:db8030e71f55 541
dotnfc 0:db8030e71f55 542 @param sectorNumber The sector that the URI record should be written
dotnfc 0:db8030e71f55 543 to (can be 1..15 for a 1K card)
dotnfc 0:db8030e71f55 544 @param uriIdentifier The uri identifier code (0 = none, 0x01 =
dotnfc 0:db8030e71f55 545 "http://www.", etc.)
dotnfc 0:db8030e71f55 546 @param url The uri text to write (max 38 characters).
dotnfc 0:db8030e71f55 547
dotnfc 0:db8030e71f55 548 @returns 1 if everything executed properly, 0 for an error
dotnfc 0:db8030e71f55 549 */
dotnfc 0:db8030e71f55 550 /**************************************************************************/
dotnfc 0:db8030e71f55 551 uint8_t PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char *url)
dotnfc 0:db8030e71f55 552 {
dotnfc 0:db8030e71f55 553 // Figure out how long the string is
dotnfc 0:db8030e71f55 554 uint8_t len = strlen(url);
dotnfc 0:db8030e71f55 555
dotnfc 0:db8030e71f55 556 // Make sure we're within a 1K limit for the sector number
dotnfc 0:db8030e71f55 557 if ((sectorNumber < 1) || (sectorNumber > 15))
dotnfc 0:db8030e71f55 558 return 0;
dotnfc 0:db8030e71f55 559
dotnfc 0:db8030e71f55 560 // Make sure the URI payload is between 1 and 38 chars
dotnfc 0:db8030e71f55 561 if ((len < 1) || (len > 38))
dotnfc 0:db8030e71f55 562 return 0;
dotnfc 0:db8030e71f55 563
dotnfc 0:db8030e71f55 564 // Note 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 must be used for key A
dotnfc 0:db8030e71f55 565 // in NDEF records
dotnfc 0:db8030e71f55 566
dotnfc 0:db8030e71f55 567 // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message)
dotnfc 0:db8030e71f55 568 uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len + 5, 0xD1, 0x01, len + 1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
dotnfc 0:db8030e71f55 569 uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
dotnfc 0:db8030e71f55 570 uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
dotnfc 0:db8030e71f55 571 uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
dotnfc 0:db8030e71f55 572 if (len <= 6) {
dotnfc 0:db8030e71f55 573 // Unlikely we'll get a url this short, but why not ...
dotnfc 0:db8030e71f55 574 memcpy (sectorbuffer1 + 9, url, len);
dotnfc 0:db8030e71f55 575 sectorbuffer1[len + 9] = 0xFE;
dotnfc 0:db8030e71f55 576 } else if (len == 7) {
dotnfc 0:db8030e71f55 577 // 0xFE needs to be wrapped around to next block
dotnfc 0:db8030e71f55 578 memcpy (sectorbuffer1 + 9, url, len);
dotnfc 0:db8030e71f55 579 sectorbuffer2[0] = 0xFE;
dotnfc 0:db8030e71f55 580 } else if ((len > 7) || (len <= 22)) {
dotnfc 0:db8030e71f55 581 // Url fits in two blocks
dotnfc 0:db8030e71f55 582 memcpy (sectorbuffer1 + 9, url, 7);
dotnfc 0:db8030e71f55 583 memcpy (sectorbuffer2, url + 7, len - 7);
dotnfc 0:db8030e71f55 584 sectorbuffer2[len - 7] = 0xFE;
dotnfc 0:db8030e71f55 585 } else if (len == 23) {
dotnfc 0:db8030e71f55 586 // 0xFE needs to be wrapped around to final block
dotnfc 0:db8030e71f55 587 memcpy (sectorbuffer1 + 9, url, 7);
dotnfc 0:db8030e71f55 588 memcpy (sectorbuffer2, url + 7, len - 7);
dotnfc 0:db8030e71f55 589 sectorbuffer3[0] = 0xFE;
dotnfc 0:db8030e71f55 590 } else {
dotnfc 0:db8030e71f55 591 // Url fits in three blocks
dotnfc 0:db8030e71f55 592 memcpy (sectorbuffer1 + 9, url, 7);
dotnfc 0:db8030e71f55 593 memcpy (sectorbuffer2, url + 7, 16);
dotnfc 0:db8030e71f55 594 memcpy (sectorbuffer3, url + 23, len - 24);
dotnfc 0:db8030e71f55 595 sectorbuffer3[len - 22] = 0xFE;
dotnfc 0:db8030e71f55 596 }
dotnfc 0:db8030e71f55 597
dotnfc 0:db8030e71f55 598 // Now write all three blocks back to the card
dotnfc 0:db8030e71f55 599 if (!(mifareclassic_WriteDataBlock (sectorNumber * 4, sectorbuffer1)))
dotnfc 0:db8030e71f55 600 return 0;
dotnfc 0:db8030e71f55 601 if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 1, sectorbuffer2)))
dotnfc 0:db8030e71f55 602 return 0;
dotnfc 0:db8030e71f55 603 if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 2, sectorbuffer3)))
dotnfc 0:db8030e71f55 604 return 0;
dotnfc 0:db8030e71f55 605 if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 3, sectorbuffer4)))
dotnfc 0:db8030e71f55 606 return 0;
dotnfc 0:db8030e71f55 607
dotnfc 0:db8030e71f55 608 // Seems that everything was OK (?!)
dotnfc 0:db8030e71f55 609 return 1;
dotnfc 0:db8030e71f55 610 }
dotnfc 0:db8030e71f55 611
dotnfc 0:db8030e71f55 612 /***** Mifare Ultralight Functions ******/
dotnfc 0:db8030e71f55 613
dotnfc 0:db8030e71f55 614 /**************************************************************************/
dotnfc 0:db8030e71f55 615 /*!
dotnfc 0:db8030e71f55 616 Tries to read an entire 4-bytes page at the specified address.
dotnfc 0:db8030e71f55 617
dotnfc 0:db8030e71f55 618 @param page The page number (0..63 in most cases)
dotnfc 0:db8030e71f55 619 @param buffer Pointer to the byte array that will hold the
dotnfc 0:db8030e71f55 620 retrieved data (if any)
dotnfc 0:db8030e71f55 621 */
dotnfc 0:db8030e71f55 622 /**************************************************************************/
dotnfc 0:db8030e71f55 623 uint8_t PN532::mifareultralight_ReadPage (uint8_t page, uint8_t *buffer)
dotnfc 0:db8030e71f55 624 {
dotnfc 0:db8030e71f55 625 if (page >= 64) {
dotnfc 0:db8030e71f55 626 DMSG("Page value out of range\n");
dotnfc 0:db8030e71f55 627 return 0;
dotnfc 0:db8030e71f55 628 }
dotnfc 0:db8030e71f55 629
dotnfc 0:db8030e71f55 630 /* Prepare the command */
dotnfc 0:db8030e71f55 631 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
dotnfc 0:db8030e71f55 632 pn532_packetbuffer[1] = 1; /* Card number */
dotnfc 0:db8030e71f55 633 pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
dotnfc 0:db8030e71f55 634 pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */
dotnfc 0:db8030e71f55 635
dotnfc 0:db8030e71f55 636 /* Send the command */
dotnfc 0:db8030e71f55 637 if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
dotnfc 0:db8030e71f55 638 return 0;
dotnfc 0:db8030e71f55 639 }
dotnfc 0:db8030e71f55 640
dotnfc 0:db8030e71f55 641 /* Read the response packet */
dotnfc 0:db8030e71f55 642 HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
dotnfc 0:db8030e71f55 643
dotnfc 0:db8030e71f55 644 /* If byte 8 isn't 0x00 we probably have an error */
dotnfc 0:db8030e71f55 645 if (pn532_packetbuffer[0] == 0x00) {
dotnfc 0:db8030e71f55 646 /* Copy the 4 data bytes to the output buffer */
dotnfc 0:db8030e71f55 647 /* Block content starts at byte 9 of a valid response */
dotnfc 0:db8030e71f55 648 /* Note that the command actually reads 16 bytes or 4 */
dotnfc 0:db8030e71f55 649 /* pages at a time ... we simply discard the last 12 */
dotnfc 0:db8030e71f55 650 /* bytes */
dotnfc 0:db8030e71f55 651 memcpy (buffer, pn532_packetbuffer + 1, 4);
dotnfc 0:db8030e71f55 652 } else {
dotnfc 0:db8030e71f55 653 return 0;
dotnfc 0:db8030e71f55 654 }
dotnfc 0:db8030e71f55 655
dotnfc 0:db8030e71f55 656 // Return OK signal
dotnfc 0:db8030e71f55 657 return 1;
dotnfc 0:db8030e71f55 658 }
dotnfc 0:db8030e71f55 659
dotnfc 0:db8030e71f55 660 /**************************************************************************/
dotnfc 0:db8030e71f55 661 /*!
dotnfc 0:db8030e71f55 662 Tries to write an entire 4-bytes data buffer at the specified page
dotnfc 0:db8030e71f55 663 address.
dotnfc 0:db8030e71f55 664
dotnfc 0:db8030e71f55 665 @param page The page number to write into. (0..63).
dotnfc 0:db8030e71f55 666 @param buffer The byte array that contains the data to write.
dotnfc 0:db8030e71f55 667
dotnfc 0:db8030e71f55 668 @returns 1 if everything executed properly, 0 for an error
dotnfc 0:db8030e71f55 669 */
dotnfc 0:db8030e71f55 670 /**************************************************************************/
dotnfc 0:db8030e71f55 671 uint8_t PN532::mifareultralight_WritePage (uint8_t page, uint8_t *buffer)
dotnfc 0:db8030e71f55 672 {
dotnfc 0:db8030e71f55 673 /* Prepare the first command */
dotnfc 0:db8030e71f55 674 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
dotnfc 0:db8030e71f55 675 pn532_packetbuffer[1] = 1; /* Card number */
dotnfc 0:db8030e71f55 676 pn532_packetbuffer[2] = MIFARE_CMD_WRITE_ULTRALIGHT; /* Mifare UL Write cmd = 0xA2 */
dotnfc 0:db8030e71f55 677 pn532_packetbuffer[3] = page; /* page Number (0..63) */
dotnfc 0:db8030e71f55 678 memcpy (pn532_packetbuffer + 4, buffer, 4); /* Data Payload */
dotnfc 0:db8030e71f55 679
dotnfc 0:db8030e71f55 680 /* Send the command */
dotnfc 0:db8030e71f55 681 if (HAL(writeCommand)(pn532_packetbuffer, 8)) {
dotnfc 0:db8030e71f55 682 return 0;
dotnfc 0:db8030e71f55 683 }
dotnfc 0:db8030e71f55 684
dotnfc 0:db8030e71f55 685 /* Read the response packet */
dotnfc 0:db8030e71f55 686 return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
dotnfc 0:db8030e71f55 687 }
dotnfc 0:db8030e71f55 688
dotnfc 0:db8030e71f55 689 /**************************************************************************/
dotnfc 0:db8030e71f55 690 /*!
dotnfc 0:db8030e71f55 691 @brief Exchanges an APDU with the currently inlisted peer
dotnfc 0:db8030e71f55 692
dotnfc 0:db8030e71f55 693 @param send Pointer to data to send
dotnfc 0:db8030e71f55 694 @param sendLength Length of the data to send
dotnfc 0:db8030e71f55 695 @param response Pointer to response data
dotnfc 0:db8030e71f55 696 @param responseLength Pointer to the response data length
dotnfc 0:db8030e71f55 697 */
dotnfc 0:db8030e71f55 698 /**************************************************************************/
dotnfc 0:db8030e71f55 699 bool PN532::inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength)
dotnfc 0:db8030e71f55 700 {
dotnfc 0:db8030e71f55 701 uint8_t i;
dotnfc 0:db8030e71f55 702
dotnfc 0:db8030e71f55 703 pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE;
dotnfc 0:db8030e71f55 704 pn532_packetbuffer[1] = inListedTag;
dotnfc 0:db8030e71f55 705
dotnfc 0:db8030e71f55 706 if (HAL(writeCommand)(pn532_packetbuffer, 2, send, sendLength)) {
dotnfc 0:db8030e71f55 707 return false;
dotnfc 0:db8030e71f55 708 }
dotnfc 0:db8030e71f55 709
dotnfc 0:db8030e71f55 710 int16_t status = HAL(readResponse)(response, *responseLength, 1000);
dotnfc 0:db8030e71f55 711 if (status < 0) {
dotnfc 0:db8030e71f55 712 return false;
dotnfc 0:db8030e71f55 713 }
dotnfc 0:db8030e71f55 714
dotnfc 0:db8030e71f55 715 if ((response[0] & 0x3f) != 0) {
dotnfc 0:db8030e71f55 716 DMSG("Status code indicates an error\n");
dotnfc 0:db8030e71f55 717 return false;
dotnfc 0:db8030e71f55 718 }
dotnfc 0:db8030e71f55 719
dotnfc 0:db8030e71f55 720 uint8_t length = status;
dotnfc 0:db8030e71f55 721 length -= 1;
dotnfc 0:db8030e71f55 722
dotnfc 0:db8030e71f55 723 if (length > *responseLength) {
dotnfc 0:db8030e71f55 724 length = *responseLength; // silent truncation...
dotnfc 0:db8030e71f55 725 }
dotnfc 0:db8030e71f55 726
dotnfc 0:db8030e71f55 727 for (uint8_t i = 0; i < length; i++) {
dotnfc 0:db8030e71f55 728 response[i] = response[i + 1];
dotnfc 0:db8030e71f55 729 }
dotnfc 0:db8030e71f55 730 *responseLength = length;
dotnfc 0:db8030e71f55 731
dotnfc 0:db8030e71f55 732 return true;
dotnfc 0:db8030e71f55 733 }
dotnfc 0:db8030e71f55 734
dotnfc 0:db8030e71f55 735 /**************************************************************************/
dotnfc 0:db8030e71f55 736 /*!
dotnfc 0:db8030e71f55 737 @brief 'InLists' a passive target. PN532 acting as reader/initiator,
dotnfc 0:db8030e71f55 738 peer acting as card/responder.
dotnfc 0:db8030e71f55 739 */
dotnfc 0:db8030e71f55 740 /**************************************************************************/
dotnfc 0:db8030e71f55 741 bool PN532::inListPassiveTarget()
dotnfc 0:db8030e71f55 742 {
dotnfc 0:db8030e71f55 743 pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
dotnfc 0:db8030e71f55 744 pn532_packetbuffer[1] = 1;
dotnfc 0:db8030e71f55 745 pn532_packetbuffer[2] = 0;
dotnfc 0:db8030e71f55 746
dotnfc 0:db8030e71f55 747 DMSG("inList passive target\n");
dotnfc 0:db8030e71f55 748
dotnfc 0:db8030e71f55 749 if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
dotnfc 0:db8030e71f55 750 return false;
dotnfc 0:db8030e71f55 751 }
dotnfc 0:db8030e71f55 752
dotnfc 0:db8030e71f55 753 int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 30000);
dotnfc 0:db8030e71f55 754 if (status < 0) {
dotnfc 0:db8030e71f55 755 return false;
dotnfc 0:db8030e71f55 756 }
dotnfc 0:db8030e71f55 757
dotnfc 0:db8030e71f55 758 if (pn532_packetbuffer[0] != 1) {
dotnfc 0:db8030e71f55 759 return false;
dotnfc 0:db8030e71f55 760 }
dotnfc 0:db8030e71f55 761
dotnfc 0:db8030e71f55 762 inListedTag = pn532_packetbuffer[1];
dotnfc 0:db8030e71f55 763
dotnfc 0:db8030e71f55 764 return true;
dotnfc 0:db8030e71f55 765 }
dotnfc 0:db8030e71f55 766
dotnfc 0:db8030e71f55 767 int8_t PN532::tgInitAsTarget(const uint8_t* command, const uint8_t len, const uint16_t timeout){
dotnfc 0:db8030e71f55 768
dotnfc 0:db8030e71f55 769 int8_t status = HAL(writeCommand)(command, len);
dotnfc 0:db8030e71f55 770 if (status < 0) {
dotnfc 0:db8030e71f55 771 return -1;
dotnfc 0:db8030e71f55 772 }
dotnfc 0:db8030e71f55 773
dotnfc 0:db8030e71f55 774 status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout);
dotnfc 0:db8030e71f55 775 if (status > 0) {
dotnfc 0:db8030e71f55 776 return 1;
dotnfc 0:db8030e71f55 777 } else if (PN532_TIMEOUT == status) {
dotnfc 0:db8030e71f55 778 return 0;
dotnfc 0:db8030e71f55 779 } else {
dotnfc 0:db8030e71f55 780 return -2;
dotnfc 0:db8030e71f55 781 }
dotnfc 0:db8030e71f55 782 }
dotnfc 0:db8030e71f55 783
dotnfc 0:db8030e71f55 784 /**
dotnfc 0:db8030e71f55 785 * Peer to Peer
dotnfc 0:db8030e71f55 786 */
dotnfc 0:db8030e71f55 787 int8_t PN532::tgInitAsTarget(uint16_t timeout)
dotnfc 0:db8030e71f55 788 {
dotnfc 0:db8030e71f55 789 const uint8_t command[] = {
dotnfc 0:db8030e71f55 790 PN532_COMMAND_TGINITASTARGET,
dotnfc 0:db8030e71f55 791 0,
dotnfc 0:db8030e71f55 792 0x00, 0x00, //SENS_RES
dotnfc 0:db8030e71f55 793 0x00, 0x00, 0x00, //NFCID1
dotnfc 0:db8030e71f55 794 0x40, //SEL_RES
dotnfc 0:db8030e71f55 795
dotnfc 0:db8030e71f55 796 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, // POL_RES
dotnfc 0:db8030e71f55 797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
dotnfc 0:db8030e71f55 798 0xFF, 0xFF,
dotnfc 0:db8030e71f55 799
dotnfc 0:db8030e71f55 800 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, //NFCID3t: Change this to desired value
dotnfc 0:db8030e71f55 801
dotnfc 0:db8030e71f55 802 0x0a, 0x46, 0x66, 0x6D, 0x01, 0x01, 0x10, 0x02, 0x02, 0x00, 0x80, // LLCP magic number, version parameter and MIUX
dotnfc 0:db8030e71f55 803 0x00
dotnfc 0:db8030e71f55 804 };
dotnfc 0:db8030e71f55 805 return tgInitAsTarget(command, sizeof(command), timeout);
dotnfc 0:db8030e71f55 806 }
dotnfc 0:db8030e71f55 807
dotnfc 0:db8030e71f55 808 int16_t PN532::tgGetData(uint8_t *buf, uint8_t len)
dotnfc 0:db8030e71f55 809 {
dotnfc 0:db8030e71f55 810 buf[0] = PN532_COMMAND_TGGETDATA;
dotnfc 0:db8030e71f55 811
dotnfc 0:db8030e71f55 812 if (HAL(writeCommand)(buf, 1)) {
dotnfc 0:db8030e71f55 813 return -1;
dotnfc 0:db8030e71f55 814 }
dotnfc 0:db8030e71f55 815
dotnfc 0:db8030e71f55 816 int16_t status = HAL(readResponse)(buf, len, 3000);
dotnfc 0:db8030e71f55 817 if (0 >= status) {
dotnfc 0:db8030e71f55 818 return status;
dotnfc 0:db8030e71f55 819 }
dotnfc 0:db8030e71f55 820
dotnfc 0:db8030e71f55 821 uint16_t length = status - 1;
dotnfc 0:db8030e71f55 822
dotnfc 0:db8030e71f55 823
dotnfc 0:db8030e71f55 824 if (buf[0] != 0) {
dotnfc 0:db8030e71f55 825 DMSG("status is not ok\n");
dotnfc 0:db8030e71f55 826 return -5;
dotnfc 0:db8030e71f55 827 }
dotnfc 0:db8030e71f55 828
dotnfc 0:db8030e71f55 829 for (uint8_t i = 0; i < length; i++) {
dotnfc 0:db8030e71f55 830 buf[i] = buf[i + 1];
dotnfc 0:db8030e71f55 831 }
dotnfc 0:db8030e71f55 832
dotnfc 0:db8030e71f55 833 return length;
dotnfc 0:db8030e71f55 834 }
dotnfc 0:db8030e71f55 835
dotnfc 0:db8030e71f55 836 bool PN532::tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
dotnfc 0:db8030e71f55 837 {
dotnfc 0:db8030e71f55 838 if (hlen > (sizeof(pn532_packetbuffer) - 1)) {
dotnfc 0:db8030e71f55 839 if ((body != 0) || (header == pn532_packetbuffer)) {
dotnfc 0:db8030e71f55 840 DMSG("tgSetData:buffer too small\n");
dotnfc 0:db8030e71f55 841 return false;
dotnfc 0:db8030e71f55 842 }
dotnfc 0:db8030e71f55 843
dotnfc 0:db8030e71f55 844 pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA;
dotnfc 0:db8030e71f55 845 if (HAL(writeCommand)(pn532_packetbuffer, 1, header, hlen)) {
dotnfc 0:db8030e71f55 846 return false;
dotnfc 0:db8030e71f55 847 }
dotnfc 0:db8030e71f55 848 } else {
dotnfc 0:db8030e71f55 849 for (int8_t i = hlen - 1; i >= 0; i--){
dotnfc 0:db8030e71f55 850 pn532_packetbuffer[i + 1] = header[i];
dotnfc 0:db8030e71f55 851 }
dotnfc 0:db8030e71f55 852 pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA;
dotnfc 0:db8030e71f55 853
dotnfc 0:db8030e71f55 854 if (HAL(writeCommand)(pn532_packetbuffer, hlen + 1, body, blen)) {
dotnfc 0:db8030e71f55 855 return false;
dotnfc 0:db8030e71f55 856 }
dotnfc 0:db8030e71f55 857 }
dotnfc 0:db8030e71f55 858
dotnfc 0:db8030e71f55 859 if (0 > HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 3000)) {
dotnfc 0:db8030e71f55 860 return false;
dotnfc 0:db8030e71f55 861 }
dotnfc 0:db8030e71f55 862
dotnfc 0:db8030e71f55 863 if (0 != pn532_packetbuffer[0]) {
dotnfc 0:db8030e71f55 864 return false;
dotnfc 0:db8030e71f55 865 }
dotnfc 0:db8030e71f55 866
dotnfc 0:db8030e71f55 867 return true;
dotnfc 0:db8030e71f55 868 }
dotnfc 0:db8030e71f55 869
dotnfc 0:db8030e71f55 870 int16_t PN532::inRelease(const uint8_t relevantTarget){
dotnfc 0:db8030e71f55 871
dotnfc 0:db8030e71f55 872 pn532_packetbuffer[0] = PN532_COMMAND_INRELEASE;
dotnfc 0:db8030e71f55 873 pn532_packetbuffer[1] = relevantTarget;
dotnfc 0:db8030e71f55 874
dotnfc 0:db8030e71f55 875 if (HAL(writeCommand)(pn532_packetbuffer, 2)) {
dotnfc 0:db8030e71f55 876 return 0;
dotnfc 0:db8030e71f55 877 }
dotnfc 0:db8030e71f55 878
dotnfc 0:db8030e71f55 879 // read data packet
dotnfc 0:db8030e71f55 880 return HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
dotnfc 0:db8030e71f55 881 }
dotnfc 0:db8030e71f55 882
dotnfc 0:db8030e71f55 883