Generic library for working with PN532-like chips

Fork of PN532 by Seeed

Committer:
r4z0r7o3
Date:
Wed Feb 04 19:04:54 2015 +0000
Revision:
10:f959b305a571
Parent:
8:7ffdaea03ff9
Try multiple known auth. keys on classic.  Also fixed all debugging messages so they all end with newlines.

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