to colorize a colorful pixel with a simple touch using nfc technology

Dependencies:   Chainable_RGB_LED mbed

use Arch, NFC Shield and Grove - Chainable RGB LED to DIY a touch pixel. Then use an Android with NFC support to colorize it.

The project is on https://github.com/Seeed-Studio/TouchPixel

Committer:
yihui
Date:
Fri Dec 27 01:46:32 2013 +0000
Revision:
0:88960f3eeb2c
initial

Who changed what in which revision?

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