PN532 NFC library for Seeed Studio's NFC Shield

Fork of PN532 by Yihui Xiong

Committer:
yihui
Date:
Thu Nov 21 04:30:49 2013 +0000
Revision:
3:4189a10038e6
Parent:
2:f618fb2169c4
Child:
4:0774b8298eb8
sync with https://github.com/Seeed-Studio/PN532/releases/tag/v0.9.

Who changed what in which revision?

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