QAQ ==!
Dependencies: mbed QEI-1 nRF24L01P xiugai
PN532/PN532.cpp@15:934289377f7a, 2019-12-14 (annotated)
- Committer:
- AlexQian
- Date:
- Sat Dec 14 05:45:16 2019 +0000
- Revision:
- 15:934289377f7a
- Parent:
- 9:d03b1af2b8d8
Balance_Car;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
zhangyx | 9:d03b1af2b8d8 | 1 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 2 | /*! |
zhangyx | 9:d03b1af2b8d8 | 3 | @file PN532.cpp |
zhangyx | 9:d03b1af2b8d8 | 4 | @author Adafruit Industries & Seeed Studio |
zhangyx | 9:d03b1af2b8d8 | 5 | @license BSD |
zhangyx | 9:d03b1af2b8d8 | 6 | */ |
zhangyx | 9:d03b1af2b8d8 | 7 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 8 | |
zhangyx | 9:d03b1af2b8d8 | 9 | #include "Arduino.h" |
zhangyx | 9:d03b1af2b8d8 | 10 | #include "PN532.h" |
zhangyx | 9:d03b1af2b8d8 | 11 | #include "PN532_debug.h" |
zhangyx | 9:d03b1af2b8d8 | 12 | #include <string.h> |
zhangyx | 9:d03b1af2b8d8 | 13 | |
zhangyx | 9:d03b1af2b8d8 | 14 | #define HAL(func) (_interface->func) |
zhangyx | 9:d03b1af2b8d8 | 15 | |
zhangyx | 9:d03b1af2b8d8 | 16 | PN532::PN532(PN532Interface &interface) |
zhangyx | 9:d03b1af2b8d8 | 17 | { |
zhangyx | 9:d03b1af2b8d8 | 18 | _interface = &interface; |
zhangyx | 9:d03b1af2b8d8 | 19 | } |
zhangyx | 9:d03b1af2b8d8 | 20 | |
zhangyx | 9:d03b1af2b8d8 | 21 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 22 | /*! |
zhangyx | 9:d03b1af2b8d8 | 23 | @brief Setups the HW |
zhangyx | 9:d03b1af2b8d8 | 24 | */ |
zhangyx | 9:d03b1af2b8d8 | 25 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 26 | void PN532::begin() |
zhangyx | 9:d03b1af2b8d8 | 27 | { |
zhangyx | 9:d03b1af2b8d8 | 28 | HAL(begin)(); |
zhangyx | 9:d03b1af2b8d8 | 29 | HAL(wakeup)(); |
zhangyx | 9:d03b1af2b8d8 | 30 | } |
zhangyx | 9:d03b1af2b8d8 | 31 | |
zhangyx | 9:d03b1af2b8d8 | 32 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 33 | /*! |
zhangyx | 9:d03b1af2b8d8 | 34 | @brief Prints a hexadecimal value in plain characters |
zhangyx | 9:d03b1af2b8d8 | 35 | |
zhangyx | 9:d03b1af2b8d8 | 36 | @param data Pointer to the uint8_t data |
zhangyx | 9:d03b1af2b8d8 | 37 | @param numBytes Data length in bytes |
zhangyx | 9:d03b1af2b8d8 | 38 | */ |
zhangyx | 9:d03b1af2b8d8 | 39 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 40 | void PN532::PrintHex(const uint8_t *data, const uint32_t numBytes) |
zhangyx | 9:d03b1af2b8d8 | 41 | { |
zhangyx | 9:d03b1af2b8d8 | 42 | #ifdef ARDUINO |
zhangyx | 9:d03b1af2b8d8 | 43 | for (uint8_t i = 0; i < numBytes; i++) { |
zhangyx | 9:d03b1af2b8d8 | 44 | if (data[i] < 0x10) { |
zhangyx | 9:d03b1af2b8d8 | 45 | Serial.print(" 0"); |
zhangyx | 9:d03b1af2b8d8 | 46 | } else { |
zhangyx | 9:d03b1af2b8d8 | 47 | Serial.print(' '); |
zhangyx | 9:d03b1af2b8d8 | 48 | } |
zhangyx | 9:d03b1af2b8d8 | 49 | Serial.print(data[i], HEX); |
zhangyx | 9:d03b1af2b8d8 | 50 | } |
zhangyx | 9:d03b1af2b8d8 | 51 | Serial.println(""); |
zhangyx | 9:d03b1af2b8d8 | 52 | #else |
zhangyx | 9:d03b1af2b8d8 | 53 | for (uint8_t i = 0; i < numBytes; i++) { |
zhangyx | 9:d03b1af2b8d8 | 54 | printf(" %2X", data[i]); |
zhangyx | 9:d03b1af2b8d8 | 55 | } |
zhangyx | 9:d03b1af2b8d8 | 56 | printf("\n"); |
zhangyx | 9:d03b1af2b8d8 | 57 | #endif |
zhangyx | 9:d03b1af2b8d8 | 58 | } |
zhangyx | 9:d03b1af2b8d8 | 59 | |
zhangyx | 9:d03b1af2b8d8 | 60 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 61 | /*! |
zhangyx | 9:d03b1af2b8d8 | 62 | @brief Prints a hexadecimal value in plain characters, along with |
zhangyx | 9:d03b1af2b8d8 | 63 | the char equivalents in the following format |
zhangyx | 9:d03b1af2b8d8 | 64 | |
zhangyx | 9:d03b1af2b8d8 | 65 | 00 00 00 00 00 00 ...... |
zhangyx | 9:d03b1af2b8d8 | 66 | |
zhangyx | 9:d03b1af2b8d8 | 67 | @param data Pointer to the data |
zhangyx | 9:d03b1af2b8d8 | 68 | @param numBytes Data length in bytes |
zhangyx | 9:d03b1af2b8d8 | 69 | */ |
zhangyx | 9:d03b1af2b8d8 | 70 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 71 | void PN532::PrintHexChar(const uint8_t *data, const uint32_t numBytes) |
zhangyx | 9:d03b1af2b8d8 | 72 | { |
zhangyx | 9:d03b1af2b8d8 | 73 | #ifdef ARDUINO |
zhangyx | 9:d03b1af2b8d8 | 74 | for (uint8_t i = 0; i < numBytes; i++) { |
zhangyx | 9:d03b1af2b8d8 | 75 | if (data[i] < 0x10) { |
zhangyx | 9:d03b1af2b8d8 | 76 | Serial.print(" 0"); |
zhangyx | 9:d03b1af2b8d8 | 77 | } else { |
zhangyx | 9:d03b1af2b8d8 | 78 | Serial.print(' '); |
zhangyx | 9:d03b1af2b8d8 | 79 | } |
zhangyx | 9:d03b1af2b8d8 | 80 | Serial.print(data[i], HEX); |
zhangyx | 9:d03b1af2b8d8 | 81 | } |
zhangyx | 9:d03b1af2b8d8 | 82 | Serial.print(" "); |
zhangyx | 9:d03b1af2b8d8 | 83 | for (uint8_t i = 0; i < numBytes; i++) { |
zhangyx | 9:d03b1af2b8d8 | 84 | char c = data[i]; |
zhangyx | 9:d03b1af2b8d8 | 85 | if (c <= 0x1f || c > 0x7f) { |
zhangyx | 9:d03b1af2b8d8 | 86 | Serial.print('.'); |
zhangyx | 9:d03b1af2b8d8 | 87 | } else { |
zhangyx | 9:d03b1af2b8d8 | 88 | Serial.print(c); |
zhangyx | 9:d03b1af2b8d8 | 89 | } |
zhangyx | 9:d03b1af2b8d8 | 90 | } |
zhangyx | 9:d03b1af2b8d8 | 91 | Serial.println(""); |
zhangyx | 9:d03b1af2b8d8 | 92 | #else |
zhangyx | 9:d03b1af2b8d8 | 93 | for (uint8_t i = 0; i < numBytes; i++) { |
zhangyx | 9:d03b1af2b8d8 | 94 | printf(" %2X", data[i]); |
zhangyx | 9:d03b1af2b8d8 | 95 | } |
zhangyx | 9:d03b1af2b8d8 | 96 | printf(" "); |
zhangyx | 9:d03b1af2b8d8 | 97 | for (uint8_t i = 0; i < numBytes; i++) { |
zhangyx | 9:d03b1af2b8d8 | 98 | char c = data[i]; |
zhangyx | 9:d03b1af2b8d8 | 99 | if (c <= 0x1f || c > 0x7f) { |
zhangyx | 9:d03b1af2b8d8 | 100 | printf("."); |
zhangyx | 9:d03b1af2b8d8 | 101 | } else { |
zhangyx | 9:d03b1af2b8d8 | 102 | printf("%c", c); |
zhangyx | 9:d03b1af2b8d8 | 103 | } |
zhangyx | 9:d03b1af2b8d8 | 104 | printf("\n"); |
zhangyx | 9:d03b1af2b8d8 | 105 | } |
zhangyx | 9:d03b1af2b8d8 | 106 | #endif |
zhangyx | 9:d03b1af2b8d8 | 107 | } |
zhangyx | 9:d03b1af2b8d8 | 108 | |
zhangyx | 9:d03b1af2b8d8 | 109 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 110 | /*! |
zhangyx | 9:d03b1af2b8d8 | 111 | @brief Checks the firmware version of the PN5xx chip |
zhangyx | 9:d03b1af2b8d8 | 112 | |
zhangyx | 9:d03b1af2b8d8 | 113 | @returns The chip's firmware version and ID |
zhangyx | 9:d03b1af2b8d8 | 114 | */ |
zhangyx | 9:d03b1af2b8d8 | 115 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 116 | uint32_t PN532::getFirmwareVersion(void) |
zhangyx | 9:d03b1af2b8d8 | 117 | { |
zhangyx | 9:d03b1af2b8d8 | 118 | uint32_t response; |
zhangyx | 9:d03b1af2b8d8 | 119 | |
zhangyx | 9:d03b1af2b8d8 | 120 | pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; |
zhangyx | 9:d03b1af2b8d8 | 121 | |
zhangyx | 9:d03b1af2b8d8 | 122 | if (HAL(writeCommand)(pn532_packetbuffer, 1)) { |
zhangyx | 9:d03b1af2b8d8 | 123 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 124 | } |
zhangyx | 9:d03b1af2b8d8 | 125 | |
zhangyx | 9:d03b1af2b8d8 | 126 | // read data packet |
zhangyx | 9:d03b1af2b8d8 | 127 | int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); |
zhangyx | 9:d03b1af2b8d8 | 128 | if (0 > status) { |
zhangyx | 9:d03b1af2b8d8 | 129 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 130 | } |
zhangyx | 9:d03b1af2b8d8 | 131 | |
zhangyx | 9:d03b1af2b8d8 | 132 | response = pn532_packetbuffer[0]; |
zhangyx | 9:d03b1af2b8d8 | 133 | response <<= 8; |
zhangyx | 9:d03b1af2b8d8 | 134 | response |= pn532_packetbuffer[1]; |
zhangyx | 9:d03b1af2b8d8 | 135 | response <<= 8; |
zhangyx | 9:d03b1af2b8d8 | 136 | response |= pn532_packetbuffer[2]; |
zhangyx | 9:d03b1af2b8d8 | 137 | response <<= 8; |
zhangyx | 9:d03b1af2b8d8 | 138 | response |= pn532_packetbuffer[3]; |
zhangyx | 9:d03b1af2b8d8 | 139 | |
zhangyx | 9:d03b1af2b8d8 | 140 | return response; |
zhangyx | 9:d03b1af2b8d8 | 141 | } |
zhangyx | 9:d03b1af2b8d8 | 142 | |
zhangyx | 9:d03b1af2b8d8 | 143 | |
zhangyx | 9:d03b1af2b8d8 | 144 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 145 | /*! |
zhangyx | 9:d03b1af2b8d8 | 146 | Writes an 8-bit value that sets the state of the PN532's GPIO pins |
zhangyx | 9:d03b1af2b8d8 | 147 | |
zhangyx | 9:d03b1af2b8d8 | 148 | @warning This function is provided exclusively for board testing and |
zhangyx | 9:d03b1af2b8d8 | 149 | is dangerous since it will throw an error if any pin other |
zhangyx | 9:d03b1af2b8d8 | 150 | than the ones marked "Can be used as GPIO" are modified! All |
zhangyx | 9:d03b1af2b8d8 | 151 | pins that can not be used as GPIO should ALWAYS be left high |
zhangyx | 9:d03b1af2b8d8 | 152 | (value = 1) or the system will become unstable and a HW reset |
zhangyx | 9:d03b1af2b8d8 | 153 | will be required to recover the PN532. |
zhangyx | 9:d03b1af2b8d8 | 154 | |
zhangyx | 9:d03b1af2b8d8 | 155 | pinState[0] = P30 Can be used as GPIO |
zhangyx | 9:d03b1af2b8d8 | 156 | pinState[1] = P31 Can be used as GPIO |
zhangyx | 9:d03b1af2b8d8 | 157 | pinState[2] = P32 *** RESERVED (Must be 1!) *** |
zhangyx | 9:d03b1af2b8d8 | 158 | pinState[3] = P33 Can be used as GPIO |
zhangyx | 9:d03b1af2b8d8 | 159 | pinState[4] = P34 *** RESERVED (Must be 1!) *** |
zhangyx | 9:d03b1af2b8d8 | 160 | pinState[5] = P35 Can be used as GPIO |
zhangyx | 9:d03b1af2b8d8 | 161 | |
zhangyx | 9:d03b1af2b8d8 | 162 | @returns 1 if everything executed properly, 0 for an error |
zhangyx | 9:d03b1af2b8d8 | 163 | */ |
zhangyx | 9:d03b1af2b8d8 | 164 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 165 | bool PN532::writeGPIOP3(uint8_t pinstate) |
zhangyx | 9:d03b1af2b8d8 | 166 | { |
zhangyx | 9:d03b1af2b8d8 | 167 | // Make sure pinstate does not try to toggle P32 or P34 |
zhangyx | 9:d03b1af2b8d8 | 168 | pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34); |
zhangyx | 9:d03b1af2b8d8 | 169 | |
zhangyx | 9:d03b1af2b8d8 | 170 | // Fill command buffer |
zhangyx | 9:d03b1af2b8d8 | 171 | pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO; |
zhangyx | 9:d03b1af2b8d8 | 172 | pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins |
zhangyx | 9:d03b1af2b8d8 | 173 | pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by I2C) |
zhangyx | 9:d03b1af2b8d8 | 174 | |
zhangyx | 9:d03b1af2b8d8 | 175 | DMSG("Writing P3 GPIO: "); |
zhangyx | 9:d03b1af2b8d8 | 176 | DMSG_HEX(pn532_packetbuffer[1]); |
zhangyx | 9:d03b1af2b8d8 | 177 | DMSG("\n"); |
zhangyx | 9:d03b1af2b8d8 | 178 | |
zhangyx | 9:d03b1af2b8d8 | 179 | // Send the WRITEGPIO command (0x0E) |
zhangyx | 9:d03b1af2b8d8 | 180 | if (HAL(writeCommand)(pn532_packetbuffer, 3)) |
zhangyx | 9:d03b1af2b8d8 | 181 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 182 | |
zhangyx | 9:d03b1af2b8d8 | 183 | return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); |
zhangyx | 9:d03b1af2b8d8 | 184 | } |
zhangyx | 9:d03b1af2b8d8 | 185 | |
zhangyx | 9:d03b1af2b8d8 | 186 | bool PN532::writeGPIOP7(uint8_t pinstate) |
zhangyx | 9:d03b1af2b8d8 | 187 | { |
zhangyx | 9:d03b1af2b8d8 | 188 | pinstate &= (1 << PN532_GPIO_P70) | (1 << PN532_GPIO_P71) | (1 << PN532_GPIO_P72); |
zhangyx | 9:d03b1af2b8d8 | 189 | |
zhangyx | 9:d03b1af2b8d8 | 190 | // Fill command buffer |
zhangyx | 9:d03b1af2b8d8 | 191 | pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO; |
zhangyx | 9:d03b1af2b8d8 | 192 | pn532_packetbuffer[1] = 0x00; // P3 Pins are not changed |
zhangyx | 9:d03b1af2b8d8 | 193 | pn532_packetbuffer[2] = PN532_GPIO_VALIDATIONBIT | pinstate; // P7 Pins |
zhangyx | 9:d03b1af2b8d8 | 194 | |
zhangyx | 9:d03b1af2b8d8 | 195 | DMSG("Writing P7 GPIO: "); |
zhangyx | 9:d03b1af2b8d8 | 196 | DMSG_HEX(pn532_packetbuffer[1]); |
zhangyx | 9:d03b1af2b8d8 | 197 | DMSG("\n"); |
zhangyx | 9:d03b1af2b8d8 | 198 | |
zhangyx | 9:d03b1af2b8d8 | 199 | // Send the WRITEGPIO command (0x0E) |
zhangyx | 9:d03b1af2b8d8 | 200 | if (HAL(writeCommand)(pn532_packetbuffer, 3)) |
zhangyx | 9:d03b1af2b8d8 | 201 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 202 | |
zhangyx | 9:d03b1af2b8d8 | 203 | return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); |
zhangyx | 9:d03b1af2b8d8 | 204 | } |
zhangyx | 9:d03b1af2b8d8 | 205 | |
zhangyx | 9:d03b1af2b8d8 | 206 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 207 | /*! |
zhangyx | 9:d03b1af2b8d8 | 208 | Reads the state of the PN532's GPIO pins |
zhangyx | 9:d03b1af2b8d8 | 209 | |
zhangyx | 9:d03b1af2b8d8 | 210 | @returns An 8-bit value containing the pin state where: |
zhangyx | 9:d03b1af2b8d8 | 211 | |
zhangyx | 9:d03b1af2b8d8 | 212 | pinState[0] = P30 |
zhangyx | 9:d03b1af2b8d8 | 213 | pinState[1] = P31 |
zhangyx | 9:d03b1af2b8d8 | 214 | pinState[2] = P32 |
zhangyx | 9:d03b1af2b8d8 | 215 | pinState[3] = P33 |
zhangyx | 9:d03b1af2b8d8 | 216 | pinState[4] = P34 |
zhangyx | 9:d03b1af2b8d8 | 217 | pinState[5] = P35 |
zhangyx | 9:d03b1af2b8d8 | 218 | */ |
zhangyx | 9:d03b1af2b8d8 | 219 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 220 | uint8_t PN532::readGPIO(void) |
zhangyx | 9:d03b1af2b8d8 | 221 | { |
zhangyx | 9:d03b1af2b8d8 | 222 | pn532_packetbuffer[0] = PN532_COMMAND_READGPIO; |
zhangyx | 9:d03b1af2b8d8 | 223 | |
zhangyx | 9:d03b1af2b8d8 | 224 | // Send the READGPIO command (0x0C) |
zhangyx | 9:d03b1af2b8d8 | 225 | if (HAL(writeCommand)(pn532_packetbuffer, 1)) |
zhangyx | 9:d03b1af2b8d8 | 226 | return 0x0; |
zhangyx | 9:d03b1af2b8d8 | 227 | |
zhangyx | 9:d03b1af2b8d8 | 228 | HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); |
zhangyx | 9:d03b1af2b8d8 | 229 | |
zhangyx | 9:d03b1af2b8d8 | 230 | /* READGPIO response without prefix and suffix should be in the following format: |
zhangyx | 9:d03b1af2b8d8 | 231 | |
zhangyx | 9:d03b1af2b8d8 | 232 | byte Description |
zhangyx | 9:d03b1af2b8d8 | 233 | ------------- ------------------------------------------ |
zhangyx | 9:d03b1af2b8d8 | 234 | b0 P3 GPIO Pins |
zhangyx | 9:d03b1af2b8d8 | 235 | b1 P7 GPIO Pins (not used ... taken by I2C) |
zhangyx | 9:d03b1af2b8d8 | 236 | b2 Interface Mode Pins (not used ... bus select pins) |
zhangyx | 9:d03b1af2b8d8 | 237 | */ |
zhangyx | 9:d03b1af2b8d8 | 238 | |
zhangyx | 9:d03b1af2b8d8 | 239 | |
zhangyx | 9:d03b1af2b8d8 | 240 | DMSG("P3 GPIO: "); DMSG_HEX(pn532_packetbuffer[7]); |
zhangyx | 9:d03b1af2b8d8 | 241 | DMSG("P7 GPIO: "); DMSG_HEX(pn532_packetbuffer[8]); |
zhangyx | 9:d03b1af2b8d8 | 242 | DMSG("I0I1 GPIO: "); DMSG_HEX(pn532_packetbuffer[9]); |
zhangyx | 9:d03b1af2b8d8 | 243 | DMSG("\n"); |
zhangyx | 9:d03b1af2b8d8 | 244 | |
zhangyx | 9:d03b1af2b8d8 | 245 | return pn532_packetbuffer[0]; |
zhangyx | 9:d03b1af2b8d8 | 246 | } |
zhangyx | 9:d03b1af2b8d8 | 247 | |
zhangyx | 9:d03b1af2b8d8 | 248 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 249 | /*! |
zhangyx | 9:d03b1af2b8d8 | 250 | @brief Configures the SAM (Secure Access Module) |
zhangyx | 9:d03b1af2b8d8 | 251 | */ |
zhangyx | 9:d03b1af2b8d8 | 252 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 253 | bool PN532::SAMConfig(void) |
zhangyx | 9:d03b1af2b8d8 | 254 | { |
zhangyx | 9:d03b1af2b8d8 | 255 | pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; |
zhangyx | 9:d03b1af2b8d8 | 256 | pn532_packetbuffer[1] = 0x01; // normal mode; |
zhangyx | 9:d03b1af2b8d8 | 257 | pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second |
zhangyx | 9:d03b1af2b8d8 | 258 | pn532_packetbuffer[3] = 0x01; // use IRQ pin! |
zhangyx | 9:d03b1af2b8d8 | 259 | |
zhangyx | 9:d03b1af2b8d8 | 260 | DMSG("SAMConfig\n"); |
zhangyx | 9:d03b1af2b8d8 | 261 | |
zhangyx | 9:d03b1af2b8d8 | 262 | if (HAL(writeCommand)(pn532_packetbuffer, 4)) |
zhangyx | 9:d03b1af2b8d8 | 263 | return false; |
zhangyx | 9:d03b1af2b8d8 | 264 | |
zhangyx | 9:d03b1af2b8d8 | 265 | return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); |
zhangyx | 9:d03b1af2b8d8 | 266 | } |
zhangyx | 9:d03b1af2b8d8 | 267 | |
zhangyx | 9:d03b1af2b8d8 | 268 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 269 | /*! |
zhangyx | 9:d03b1af2b8d8 | 270 | Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register |
zhangyx | 9:d03b1af2b8d8 | 271 | |
zhangyx | 9:d03b1af2b8d8 | 272 | @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout |
zhangyx | 9:d03b1af2b8d8 | 273 | after mxRetries |
zhangyx | 9:d03b1af2b8d8 | 274 | |
zhangyx | 9:d03b1af2b8d8 | 275 | @returns 1 if everything executed properly, 0 for an error |
zhangyx | 9:d03b1af2b8d8 | 276 | */ |
zhangyx | 9:d03b1af2b8d8 | 277 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 278 | bool PN532::setPassiveActivationRetries(uint8_t maxRetries) |
zhangyx | 9:d03b1af2b8d8 | 279 | { |
zhangyx | 9:d03b1af2b8d8 | 280 | pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; |
zhangyx | 9:d03b1af2b8d8 | 281 | pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries) |
zhangyx | 9:d03b1af2b8d8 | 282 | pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF) |
zhangyx | 9:d03b1af2b8d8 | 283 | pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01) |
zhangyx | 9:d03b1af2b8d8 | 284 | pn532_packetbuffer[4] = maxRetries; |
zhangyx | 9:d03b1af2b8d8 | 285 | |
zhangyx | 9:d03b1af2b8d8 | 286 | if (HAL(writeCommand)(pn532_packetbuffer, 5)) |
zhangyx | 9:d03b1af2b8d8 | 287 | return 0x0; // no ACK |
zhangyx | 9:d03b1af2b8d8 | 288 | |
zhangyx | 9:d03b1af2b8d8 | 289 | return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); |
zhangyx | 9:d03b1af2b8d8 | 290 | } |
zhangyx | 9:d03b1af2b8d8 | 291 | |
zhangyx | 9:d03b1af2b8d8 | 292 | bool PN532::rfConfiguration(uint8_t item, uint8_t dataLen, const uint8_t* data) |
zhangyx | 9:d03b1af2b8d8 | 293 | { |
zhangyx | 9:d03b1af2b8d8 | 294 | pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; |
zhangyx | 9:d03b1af2b8d8 | 295 | pn532_packetbuffer[1] = item; |
zhangyx | 9:d03b1af2b8d8 | 296 | |
zhangyx | 9:d03b1af2b8d8 | 297 | if (HAL(writeCommand)(pn532_packetbuffer, 2, data, dataLen)) |
zhangyx | 9:d03b1af2b8d8 | 298 | return 0x0; // no ACK |
zhangyx | 9:d03b1af2b8d8 | 299 | |
zhangyx | 9:d03b1af2b8d8 | 300 | return (0 < HAL(readResponse)(pn532_packetbuffer, 0)); |
zhangyx | 9:d03b1af2b8d8 | 301 | } |
zhangyx | 9:d03b1af2b8d8 | 302 | |
zhangyx | 9:d03b1af2b8d8 | 303 | /***** ISO14443A Commands ******/ |
zhangyx | 9:d03b1af2b8d8 | 304 | |
zhangyx | 9:d03b1af2b8d8 | 305 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 306 | /*! |
zhangyx | 9:d03b1af2b8d8 | 307 | Waits for an ISO14443A target to enter the field |
zhangyx | 9:d03b1af2b8d8 | 308 | |
zhangyx | 9:d03b1af2b8d8 | 309 | @param cardBaudRate Baud rate of the card |
zhangyx | 9:d03b1af2b8d8 | 310 | @param uid Pointer to the array that will be populated |
zhangyx | 9:d03b1af2b8d8 | 311 | with the card's UID (up to 7 bytes) |
zhangyx | 9:d03b1af2b8d8 | 312 | @param uidLength Pointer to the variable that will hold the |
zhangyx | 9:d03b1af2b8d8 | 313 | length of the card's UID. |
zhangyx | 9:d03b1af2b8d8 | 314 | @param timeout The number of tries before timing out |
zhangyx | 9:d03b1af2b8d8 | 315 | @param inlist If set to true, the card will be inlisted |
zhangyx | 9:d03b1af2b8d8 | 316 | |
zhangyx | 9:d03b1af2b8d8 | 317 | @returns 1 if everything executed properly, 0 for an error |
zhangyx | 9:d03b1af2b8d8 | 318 | */ |
zhangyx | 9:d03b1af2b8d8 | 319 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 320 | bool PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout, bool inlist) |
zhangyx | 9:d03b1af2b8d8 | 321 | { |
zhangyx | 9:d03b1af2b8d8 | 322 | pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; |
zhangyx | 9:d03b1af2b8d8 | 323 | pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) |
zhangyx | 9:d03b1af2b8d8 | 324 | pn532_packetbuffer[2] = cardbaudrate; |
zhangyx | 9:d03b1af2b8d8 | 325 | |
zhangyx | 9:d03b1af2b8d8 | 326 | if (HAL(writeCommand)(pn532_packetbuffer, 3)) { |
zhangyx | 9:d03b1af2b8d8 | 327 | return 0x0; // command failed |
zhangyx | 9:d03b1af2b8d8 | 328 | } |
zhangyx | 9:d03b1af2b8d8 | 329 | |
zhangyx | 9:d03b1af2b8d8 | 330 | // read data packet |
zhangyx | 9:d03b1af2b8d8 | 331 | if (HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { |
zhangyx | 9:d03b1af2b8d8 | 332 | return 0x0; |
zhangyx | 9:d03b1af2b8d8 | 333 | } |
zhangyx | 9:d03b1af2b8d8 | 334 | |
zhangyx | 9:d03b1af2b8d8 | 335 | // check some basic stuff |
zhangyx | 9:d03b1af2b8d8 | 336 | /* ISO14443A card response should be in the following format: |
zhangyx | 9:d03b1af2b8d8 | 337 | |
zhangyx | 9:d03b1af2b8d8 | 338 | byte Description |
zhangyx | 9:d03b1af2b8d8 | 339 | ------------- ------------------------------------------ |
zhangyx | 9:d03b1af2b8d8 | 340 | b0 Tags Found |
zhangyx | 9:d03b1af2b8d8 | 341 | b1 Tag Number (only one used in this example) |
zhangyx | 9:d03b1af2b8d8 | 342 | b2..3 SENS_RES |
zhangyx | 9:d03b1af2b8d8 | 343 | b4 SEL_RES |
zhangyx | 9:d03b1af2b8d8 | 344 | b5 NFCID Length |
zhangyx | 9:d03b1af2b8d8 | 345 | b6..NFCIDLen NFCID |
zhangyx | 9:d03b1af2b8d8 | 346 | */ |
zhangyx | 9:d03b1af2b8d8 | 347 | |
zhangyx | 9:d03b1af2b8d8 | 348 | if (pn532_packetbuffer[0] != 1) |
zhangyx | 9:d03b1af2b8d8 | 349 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 350 | |
zhangyx | 9:d03b1af2b8d8 | 351 | uint16_t sens_res = pn532_packetbuffer[2]; |
zhangyx | 9:d03b1af2b8d8 | 352 | sens_res <<= 8; |
zhangyx | 9:d03b1af2b8d8 | 353 | sens_res |= pn532_packetbuffer[3]; |
zhangyx | 9:d03b1af2b8d8 | 354 | |
zhangyx | 9:d03b1af2b8d8 | 355 | DMSG("ATQA: 0x"); DMSG_HEX(sens_res); |
zhangyx | 9:d03b1af2b8d8 | 356 | DMSG("\n"); |
zhangyx | 9:d03b1af2b8d8 | 357 | DMSG("SAK: 0x"); DMSG_HEX(pn532_packetbuffer[4]); |
zhangyx | 9:d03b1af2b8d8 | 358 | DMSG("\n"); |
zhangyx | 9:d03b1af2b8d8 | 359 | |
zhangyx | 9:d03b1af2b8d8 | 360 | /* Card appears to be Mifare Classic */ |
zhangyx | 9:d03b1af2b8d8 | 361 | *uidLength = pn532_packetbuffer[5]; |
zhangyx | 9:d03b1af2b8d8 | 362 | |
zhangyx | 9:d03b1af2b8d8 | 363 | for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) { |
zhangyx | 9:d03b1af2b8d8 | 364 | uid[i] = pn532_packetbuffer[6 + i]; |
zhangyx | 9:d03b1af2b8d8 | 365 | } |
zhangyx | 9:d03b1af2b8d8 | 366 | |
zhangyx | 9:d03b1af2b8d8 | 367 | if (inlist) { |
zhangyx | 9:d03b1af2b8d8 | 368 | inListedTag = pn532_packetbuffer[1]; |
zhangyx | 9:d03b1af2b8d8 | 369 | } |
zhangyx | 9:d03b1af2b8d8 | 370 | |
zhangyx | 9:d03b1af2b8d8 | 371 | return 1; |
zhangyx | 9:d03b1af2b8d8 | 372 | } |
zhangyx | 9:d03b1af2b8d8 | 373 | |
zhangyx | 9:d03b1af2b8d8 | 374 | |
zhangyx | 9:d03b1af2b8d8 | 375 | /***** Mifare Classic Functions ******/ |
zhangyx | 9:d03b1af2b8d8 | 376 | |
zhangyx | 9:d03b1af2b8d8 | 377 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 378 | /*! |
zhangyx | 9:d03b1af2b8d8 | 379 | Indicates whether the specified block number is the first block |
zhangyx | 9:d03b1af2b8d8 | 380 | in the sector (block 0 relative to the current sector) |
zhangyx | 9:d03b1af2b8d8 | 381 | */ |
zhangyx | 9:d03b1af2b8d8 | 382 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 383 | bool PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock) |
zhangyx | 9:d03b1af2b8d8 | 384 | { |
zhangyx | 9:d03b1af2b8d8 | 385 | // Test if we are in the small or big sectors |
zhangyx | 9:d03b1af2b8d8 | 386 | if (uiBlock < 128) |
zhangyx | 9:d03b1af2b8d8 | 387 | return ((uiBlock) % 4 == 0); |
zhangyx | 9:d03b1af2b8d8 | 388 | else |
zhangyx | 9:d03b1af2b8d8 | 389 | return ((uiBlock) % 16 == 0); |
zhangyx | 9:d03b1af2b8d8 | 390 | } |
zhangyx | 9:d03b1af2b8d8 | 391 | |
zhangyx | 9:d03b1af2b8d8 | 392 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 393 | /*! |
zhangyx | 9:d03b1af2b8d8 | 394 | Indicates whether the specified block number is the sector trailer |
zhangyx | 9:d03b1af2b8d8 | 395 | */ |
zhangyx | 9:d03b1af2b8d8 | 396 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 397 | bool PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock) |
zhangyx | 9:d03b1af2b8d8 | 398 | { |
zhangyx | 9:d03b1af2b8d8 | 399 | // Test if we are in the small or big sectors |
zhangyx | 9:d03b1af2b8d8 | 400 | if (uiBlock < 128) |
zhangyx | 9:d03b1af2b8d8 | 401 | return ((uiBlock + 1) % 4 == 0); |
zhangyx | 9:d03b1af2b8d8 | 402 | else |
zhangyx | 9:d03b1af2b8d8 | 403 | return ((uiBlock + 1) % 16 == 0); |
zhangyx | 9:d03b1af2b8d8 | 404 | } |
zhangyx | 9:d03b1af2b8d8 | 405 | |
zhangyx | 9:d03b1af2b8d8 | 406 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 407 | /*! |
zhangyx | 9:d03b1af2b8d8 | 408 | Tries to authenticate a block of memory on a MIFARE card using the |
zhangyx | 9:d03b1af2b8d8 | 409 | INDATAEXCHANGE command. See section 7.3.8 of the PN532 User Manual |
zhangyx | 9:d03b1af2b8d8 | 410 | for more information on sending MIFARE and other commands. |
zhangyx | 9:d03b1af2b8d8 | 411 | |
zhangyx | 9:d03b1af2b8d8 | 412 | @param uid Pointer to a byte array containing the card UID |
zhangyx | 9:d03b1af2b8d8 | 413 | @param uidLen The length (in bytes) of the card's UID (Should |
zhangyx | 9:d03b1af2b8d8 | 414 | be 4 for MIFARE Classic) |
zhangyx | 9:d03b1af2b8d8 | 415 | @param blockNumber The block number to authenticate. (0..63 for |
zhangyx | 9:d03b1af2b8d8 | 416 | 1KB cards, and 0..255 for 4KB cards). |
zhangyx | 9:d03b1af2b8d8 | 417 | @param keyNumber Which key type to use during authentication |
zhangyx | 9:d03b1af2b8d8 | 418 | (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B) |
zhangyx | 9:d03b1af2b8d8 | 419 | @param keyData Pointer to a byte array containing the 6 bytes |
zhangyx | 9:d03b1af2b8d8 | 420 | key value |
zhangyx | 9:d03b1af2b8d8 | 421 | |
zhangyx | 9:d03b1af2b8d8 | 422 | @returns 1 if everything executed properly, 0 for an error |
zhangyx | 9:d03b1af2b8d8 | 423 | */ |
zhangyx | 9:d03b1af2b8d8 | 424 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 425 | uint8_t PN532::mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) |
zhangyx | 9:d03b1af2b8d8 | 426 | { |
zhangyx | 9:d03b1af2b8d8 | 427 | uint8_t i; |
zhangyx | 9:d03b1af2b8d8 | 428 | |
zhangyx | 9:d03b1af2b8d8 | 429 | // Hang on to the key and uid data |
zhangyx | 9:d03b1af2b8d8 | 430 | memcpy (_key, keyData, 6); |
zhangyx | 9:d03b1af2b8d8 | 431 | memcpy (_uid, uid, uidLen); |
zhangyx | 9:d03b1af2b8d8 | 432 | _uidLen = uidLen; |
zhangyx | 9:d03b1af2b8d8 | 433 | |
zhangyx | 9:d03b1af2b8d8 | 434 | // Prepare the authentication command // |
zhangyx | 9:d03b1af2b8d8 | 435 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */ |
zhangyx | 9:d03b1af2b8d8 | 436 | pn532_packetbuffer[1] = 1; /* Max card numbers */ |
zhangyx | 9:d03b1af2b8d8 | 437 | pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; |
zhangyx | 9:d03b1af2b8d8 | 438 | pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */ |
zhangyx | 9:d03b1af2b8d8 | 439 | memcpy (pn532_packetbuffer + 4, _key, 6); |
zhangyx | 9:d03b1af2b8d8 | 440 | for (i = 0; i < _uidLen; i++) { |
zhangyx | 9:d03b1af2b8d8 | 441 | pn532_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */ |
zhangyx | 9:d03b1af2b8d8 | 442 | } |
zhangyx | 9:d03b1af2b8d8 | 443 | |
zhangyx | 9:d03b1af2b8d8 | 444 | if (HAL(writeCommand)(pn532_packetbuffer, 10 + _uidLen)) |
zhangyx | 9:d03b1af2b8d8 | 445 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 446 | |
zhangyx | 9:d03b1af2b8d8 | 447 | // Read the response packet |
zhangyx | 9:d03b1af2b8d8 | 448 | HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); |
zhangyx | 9:d03b1af2b8d8 | 449 | |
zhangyx | 9:d03b1af2b8d8 | 450 | // Check if the response is valid and we are authenticated??? |
zhangyx | 9:d03b1af2b8d8 | 451 | // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00 |
zhangyx | 9:d03b1af2b8d8 | 452 | // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good |
zhangyx | 9:d03b1af2b8d8 | 453 | if (pn532_packetbuffer[0] != 0x00) { |
zhangyx | 9:d03b1af2b8d8 | 454 | DMSG("Authentification failed\n"); |
zhangyx | 9:d03b1af2b8d8 | 455 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 456 | } |
zhangyx | 9:d03b1af2b8d8 | 457 | |
zhangyx | 9:d03b1af2b8d8 | 458 | return 1; |
zhangyx | 9:d03b1af2b8d8 | 459 | } |
zhangyx | 9:d03b1af2b8d8 | 460 | |
zhangyx | 9:d03b1af2b8d8 | 461 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 462 | /*! |
zhangyx | 9:d03b1af2b8d8 | 463 | Tries to read an entire 16-bytes data block at the specified block |
zhangyx | 9:d03b1af2b8d8 | 464 | address. |
zhangyx | 9:d03b1af2b8d8 | 465 | |
zhangyx | 9:d03b1af2b8d8 | 466 | @param blockNumber The block number to authenticate. (0..63 for |
zhangyx | 9:d03b1af2b8d8 | 467 | 1KB cards, and 0..255 for 4KB cards). |
zhangyx | 9:d03b1af2b8d8 | 468 | @param data Pointer to the byte array that will hold the |
zhangyx | 9:d03b1af2b8d8 | 469 | retrieved data (if any) |
zhangyx | 9:d03b1af2b8d8 | 470 | |
zhangyx | 9:d03b1af2b8d8 | 471 | @returns 1 if everything executed properly, 0 for an error |
zhangyx | 9:d03b1af2b8d8 | 472 | */ |
zhangyx | 9:d03b1af2b8d8 | 473 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 474 | uint8_t PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) |
zhangyx | 9:d03b1af2b8d8 | 475 | { |
zhangyx | 9:d03b1af2b8d8 | 476 | DMSG("Trying to read 16 bytes from block "); |
zhangyx | 9:d03b1af2b8d8 | 477 | DMSG_INT(blockNumber); |
zhangyx | 9:d03b1af2b8d8 | 478 | |
zhangyx | 9:d03b1af2b8d8 | 479 | /* Prepare the command */ |
zhangyx | 9:d03b1af2b8d8 | 480 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; |
zhangyx | 9:d03b1af2b8d8 | 481 | pn532_packetbuffer[1] = 1; /* Card number */ |
zhangyx | 9:d03b1af2b8d8 | 482 | pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ |
zhangyx | 9:d03b1af2b8d8 | 483 | pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ |
zhangyx | 9:d03b1af2b8d8 | 484 | |
zhangyx | 9:d03b1af2b8d8 | 485 | /* Send the command */ |
zhangyx | 9:d03b1af2b8d8 | 486 | if (HAL(writeCommand)(pn532_packetbuffer, 4)) { |
zhangyx | 9:d03b1af2b8d8 | 487 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 488 | } |
zhangyx | 9:d03b1af2b8d8 | 489 | |
zhangyx | 9:d03b1af2b8d8 | 490 | /* Read the response packet */ |
zhangyx | 9:d03b1af2b8d8 | 491 | HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); |
zhangyx | 9:d03b1af2b8d8 | 492 | |
zhangyx | 9:d03b1af2b8d8 | 493 | /* If byte 8 isn't 0x00 we probably have an error */ |
zhangyx | 9:d03b1af2b8d8 | 494 | if (pn532_packetbuffer[0] != 0x00) { |
zhangyx | 9:d03b1af2b8d8 | 495 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 496 | } |
zhangyx | 9:d03b1af2b8d8 | 497 | |
zhangyx | 9:d03b1af2b8d8 | 498 | /* Copy the 16 data bytes to the output buffer */ |
zhangyx | 9:d03b1af2b8d8 | 499 | /* Block content starts at byte 9 of a valid response */ |
zhangyx | 9:d03b1af2b8d8 | 500 | memcpy (data, pn532_packetbuffer + 1, 16); |
zhangyx | 9:d03b1af2b8d8 | 501 | |
zhangyx | 9:d03b1af2b8d8 | 502 | return 1; |
zhangyx | 9:d03b1af2b8d8 | 503 | } |
zhangyx | 9:d03b1af2b8d8 | 504 | |
zhangyx | 9:d03b1af2b8d8 | 505 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 506 | /*! |
zhangyx | 9:d03b1af2b8d8 | 507 | Tries to write an entire 16-bytes data block at the specified block |
zhangyx | 9:d03b1af2b8d8 | 508 | address. |
zhangyx | 9:d03b1af2b8d8 | 509 | |
zhangyx | 9:d03b1af2b8d8 | 510 | @param blockNumber The block number to authenticate. (0..63 for |
zhangyx | 9:d03b1af2b8d8 | 511 | 1KB cards, and 0..255 for 4KB cards). |
zhangyx | 9:d03b1af2b8d8 | 512 | @param data The byte array that contains the data to write. |
zhangyx | 9:d03b1af2b8d8 | 513 | |
zhangyx | 9:d03b1af2b8d8 | 514 | @returns 1 if everything executed properly, 0 for an error |
zhangyx | 9:d03b1af2b8d8 | 515 | */ |
zhangyx | 9:d03b1af2b8d8 | 516 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 517 | uint8_t PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) |
zhangyx | 9:d03b1af2b8d8 | 518 | { |
zhangyx | 9:d03b1af2b8d8 | 519 | /* Prepare the first command */ |
zhangyx | 9:d03b1af2b8d8 | 520 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; |
zhangyx | 9:d03b1af2b8d8 | 521 | pn532_packetbuffer[1] = 1; /* Card number */ |
zhangyx | 9:d03b1af2b8d8 | 522 | pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */ |
zhangyx | 9:d03b1af2b8d8 | 523 | pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ |
zhangyx | 9:d03b1af2b8d8 | 524 | memcpy (pn532_packetbuffer + 4, data, 16); /* Data Payload */ |
zhangyx | 9:d03b1af2b8d8 | 525 | |
zhangyx | 9:d03b1af2b8d8 | 526 | /* Send the command */ |
zhangyx | 9:d03b1af2b8d8 | 527 | if (HAL(writeCommand)(pn532_packetbuffer, 20)) { |
zhangyx | 9:d03b1af2b8d8 | 528 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 529 | } |
zhangyx | 9:d03b1af2b8d8 | 530 | |
zhangyx | 9:d03b1af2b8d8 | 531 | /* Read the response packet */ |
zhangyx | 9:d03b1af2b8d8 | 532 | return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); |
zhangyx | 9:d03b1af2b8d8 | 533 | } |
zhangyx | 9:d03b1af2b8d8 | 534 | |
zhangyx | 9:d03b1af2b8d8 | 535 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 536 | /*! |
zhangyx | 9:d03b1af2b8d8 | 537 | Formats a Mifare Classic card to store NDEF Records |
zhangyx | 9:d03b1af2b8d8 | 538 | |
zhangyx | 9:d03b1af2b8d8 | 539 | @returns 1 if everything executed properly, 0 for an error |
zhangyx | 9:d03b1af2b8d8 | 540 | */ |
zhangyx | 9:d03b1af2b8d8 | 541 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 542 | uint8_t PN532::mifareclassic_FormatNDEF (void) |
zhangyx | 9:d03b1af2b8d8 | 543 | { |
zhangyx | 9:d03b1af2b8d8 | 544 | uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; |
zhangyx | 9:d03b1af2b8d8 | 545 | uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; |
zhangyx | 9:d03b1af2b8d8 | 546 | uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
zhangyx | 9:d03b1af2b8d8 | 547 | |
zhangyx | 9:d03b1af2b8d8 | 548 | // Note 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 must be used for key A |
zhangyx | 9:d03b1af2b8d8 | 549 | // for the MAD sector in NDEF records (sector 0) |
zhangyx | 9:d03b1af2b8d8 | 550 | |
zhangyx | 9:d03b1af2b8d8 | 551 | // Write block 1 and 2 to the card |
zhangyx | 9:d03b1af2b8d8 | 552 | if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1))) |
zhangyx | 9:d03b1af2b8d8 | 553 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 554 | if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2))) |
zhangyx | 9:d03b1af2b8d8 | 555 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 556 | // Write key A and access rights card |
zhangyx | 9:d03b1af2b8d8 | 557 | if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3))) |
zhangyx | 9:d03b1af2b8d8 | 558 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 559 | |
zhangyx | 9:d03b1af2b8d8 | 560 | // Seems that everything was OK (?!) |
zhangyx | 9:d03b1af2b8d8 | 561 | return 1; |
zhangyx | 9:d03b1af2b8d8 | 562 | } |
zhangyx | 9:d03b1af2b8d8 | 563 | |
zhangyx | 9:d03b1af2b8d8 | 564 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 565 | /*! |
zhangyx | 9:d03b1af2b8d8 | 566 | Writes an NDEF URI Record to the specified sector (1..15) |
zhangyx | 9:d03b1af2b8d8 | 567 | |
zhangyx | 9:d03b1af2b8d8 | 568 | Note that this function assumes that the Mifare Classic card is |
zhangyx | 9:d03b1af2b8d8 | 569 | already formatted to work as an "NFC Forum Tag" and uses a MAD1 |
zhangyx | 9:d03b1af2b8d8 | 570 | file system. You can use the NXP TagWriter app on Android to |
zhangyx | 9:d03b1af2b8d8 | 571 | properly format cards for this. |
zhangyx | 9:d03b1af2b8d8 | 572 | |
zhangyx | 9:d03b1af2b8d8 | 573 | @param sectorNumber The sector that the URI record should be written |
zhangyx | 9:d03b1af2b8d8 | 574 | to (can be 1..15 for a 1K card) |
zhangyx | 9:d03b1af2b8d8 | 575 | @param uriIdentifier The uri identifier code (0 = none, 0x01 = |
zhangyx | 9:d03b1af2b8d8 | 576 | "http://www.", etc.) |
zhangyx | 9:d03b1af2b8d8 | 577 | @param url The uri text to write (max 38 characters). |
zhangyx | 9:d03b1af2b8d8 | 578 | |
zhangyx | 9:d03b1af2b8d8 | 579 | @returns 1 if everything executed properly, 0 for an error |
zhangyx | 9:d03b1af2b8d8 | 580 | */ |
zhangyx | 9:d03b1af2b8d8 | 581 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 582 | uint8_t PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char *url) |
zhangyx | 9:d03b1af2b8d8 | 583 | { |
zhangyx | 9:d03b1af2b8d8 | 584 | // Figure out how long the string is |
zhangyx | 9:d03b1af2b8d8 | 585 | uint8_t len = strlen(url); |
zhangyx | 9:d03b1af2b8d8 | 586 | |
zhangyx | 9:d03b1af2b8d8 | 587 | // Make sure we're within a 1K limit for the sector number |
zhangyx | 9:d03b1af2b8d8 | 588 | if ((sectorNumber < 1) || (sectorNumber > 15)) |
zhangyx | 9:d03b1af2b8d8 | 589 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 590 | |
zhangyx | 9:d03b1af2b8d8 | 591 | // Make sure the URI payload is between 1 and 38 chars |
zhangyx | 9:d03b1af2b8d8 | 592 | if ((len < 1) || (len > 38)) |
zhangyx | 9:d03b1af2b8d8 | 593 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 594 | |
zhangyx | 9:d03b1af2b8d8 | 595 | // Note 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 must be used for key A |
zhangyx | 9:d03b1af2b8d8 | 596 | // in NDEF records |
zhangyx | 9:d03b1af2b8d8 | 597 | |
zhangyx | 9:d03b1af2b8d8 | 598 | // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message) |
zhangyx | 9:d03b1af2b8d8 | 599 | uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len + 5, 0xD1, 0x01, len + 1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
zhangyx | 9:d03b1af2b8d8 | 600 | uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
zhangyx | 9:d03b1af2b8d8 | 601 | uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
zhangyx | 9:d03b1af2b8d8 | 602 | uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
zhangyx | 9:d03b1af2b8d8 | 603 | if (len <= 6) { |
zhangyx | 9:d03b1af2b8d8 | 604 | // Unlikely we'll get a url this short, but why not ... |
zhangyx | 9:d03b1af2b8d8 | 605 | memcpy (sectorbuffer1 + 9, url, len); |
zhangyx | 9:d03b1af2b8d8 | 606 | sectorbuffer1[len + 9] = 0xFE; |
zhangyx | 9:d03b1af2b8d8 | 607 | } else if (len == 7) { |
zhangyx | 9:d03b1af2b8d8 | 608 | // 0xFE needs to be wrapped around to next block |
zhangyx | 9:d03b1af2b8d8 | 609 | memcpy (sectorbuffer1 + 9, url, len); |
zhangyx | 9:d03b1af2b8d8 | 610 | sectorbuffer2[0] = 0xFE; |
zhangyx | 9:d03b1af2b8d8 | 611 | } else if ((len > 7) || (len <= 22)) { |
zhangyx | 9:d03b1af2b8d8 | 612 | // Url fits in two blocks |
zhangyx | 9:d03b1af2b8d8 | 613 | memcpy (sectorbuffer1 + 9, url, 7); |
zhangyx | 9:d03b1af2b8d8 | 614 | memcpy (sectorbuffer2, url + 7, len - 7); |
zhangyx | 9:d03b1af2b8d8 | 615 | sectorbuffer2[len - 7] = 0xFE; |
zhangyx | 9:d03b1af2b8d8 | 616 | } else if (len == 23) { |
zhangyx | 9:d03b1af2b8d8 | 617 | // 0xFE needs to be wrapped around to final block |
zhangyx | 9:d03b1af2b8d8 | 618 | memcpy (sectorbuffer1 + 9, url, 7); |
zhangyx | 9:d03b1af2b8d8 | 619 | memcpy (sectorbuffer2, url + 7, len - 7); |
zhangyx | 9:d03b1af2b8d8 | 620 | sectorbuffer3[0] = 0xFE; |
zhangyx | 9:d03b1af2b8d8 | 621 | } else { |
zhangyx | 9:d03b1af2b8d8 | 622 | // Url fits in three blocks |
zhangyx | 9:d03b1af2b8d8 | 623 | memcpy (sectorbuffer1 + 9, url, 7); |
zhangyx | 9:d03b1af2b8d8 | 624 | memcpy (sectorbuffer2, url + 7, 16); |
zhangyx | 9:d03b1af2b8d8 | 625 | memcpy (sectorbuffer3, url + 23, len - 24); |
zhangyx | 9:d03b1af2b8d8 | 626 | sectorbuffer3[len - 22] = 0xFE; |
zhangyx | 9:d03b1af2b8d8 | 627 | } |
zhangyx | 9:d03b1af2b8d8 | 628 | |
zhangyx | 9:d03b1af2b8d8 | 629 | // Now write all three blocks back to the card |
zhangyx | 9:d03b1af2b8d8 | 630 | if (!(mifareclassic_WriteDataBlock (sectorNumber * 4, sectorbuffer1))) |
zhangyx | 9:d03b1af2b8d8 | 631 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 632 | if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 1, sectorbuffer2))) |
zhangyx | 9:d03b1af2b8d8 | 633 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 634 | if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 2, sectorbuffer3))) |
zhangyx | 9:d03b1af2b8d8 | 635 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 636 | if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 3, sectorbuffer4))) |
zhangyx | 9:d03b1af2b8d8 | 637 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 638 | |
zhangyx | 9:d03b1af2b8d8 | 639 | // Seems that everything was OK (?!) |
zhangyx | 9:d03b1af2b8d8 | 640 | return 1; |
zhangyx | 9:d03b1af2b8d8 | 641 | } |
zhangyx | 9:d03b1af2b8d8 | 642 | |
zhangyx | 9:d03b1af2b8d8 | 643 | /***** Mifare Ultralight Functions ******/ |
zhangyx | 9:d03b1af2b8d8 | 644 | |
zhangyx | 9:d03b1af2b8d8 | 645 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 646 | /*! |
zhangyx | 9:d03b1af2b8d8 | 647 | Tries to read an entire 4-bytes page at the specified address. |
zhangyx | 9:d03b1af2b8d8 | 648 | |
zhangyx | 9:d03b1af2b8d8 | 649 | @param page The page number (0..63 in most cases) |
zhangyx | 9:d03b1af2b8d8 | 650 | @param buffer Pointer to the byte array that will hold the |
zhangyx | 9:d03b1af2b8d8 | 651 | retrieved data (if any) |
zhangyx | 9:d03b1af2b8d8 | 652 | */ |
zhangyx | 9:d03b1af2b8d8 | 653 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 654 | uint8_t PN532::mifareultralight_ReadPage (uint8_t page, uint8_t *buffer) |
zhangyx | 9:d03b1af2b8d8 | 655 | { |
zhangyx | 9:d03b1af2b8d8 | 656 | if (page >= 64) { |
zhangyx | 9:d03b1af2b8d8 | 657 | DMSG("Page value out of range\n"); |
zhangyx | 9:d03b1af2b8d8 | 658 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 659 | } |
zhangyx | 9:d03b1af2b8d8 | 660 | |
zhangyx | 9:d03b1af2b8d8 | 661 | /* Prepare the command */ |
zhangyx | 9:d03b1af2b8d8 | 662 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; |
zhangyx | 9:d03b1af2b8d8 | 663 | pn532_packetbuffer[1] = 1; /* Card number */ |
zhangyx | 9:d03b1af2b8d8 | 664 | pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ |
zhangyx | 9:d03b1af2b8d8 | 665 | pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */ |
zhangyx | 9:d03b1af2b8d8 | 666 | |
zhangyx | 9:d03b1af2b8d8 | 667 | /* Send the command */ |
zhangyx | 9:d03b1af2b8d8 | 668 | if (HAL(writeCommand)(pn532_packetbuffer, 4)) { |
zhangyx | 9:d03b1af2b8d8 | 669 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 670 | } |
zhangyx | 9:d03b1af2b8d8 | 671 | |
zhangyx | 9:d03b1af2b8d8 | 672 | /* Read the response packet */ |
zhangyx | 9:d03b1af2b8d8 | 673 | HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); |
zhangyx | 9:d03b1af2b8d8 | 674 | |
zhangyx | 9:d03b1af2b8d8 | 675 | /* If byte 8 isn't 0x00 we probably have an error */ |
zhangyx | 9:d03b1af2b8d8 | 676 | if (pn532_packetbuffer[0] == 0x00) { |
zhangyx | 9:d03b1af2b8d8 | 677 | /* Copy the 4 data bytes to the output buffer */ |
zhangyx | 9:d03b1af2b8d8 | 678 | /* Block content starts at byte 9 of a valid response */ |
zhangyx | 9:d03b1af2b8d8 | 679 | /* Note that the command actually reads 16 bytes or 4 */ |
zhangyx | 9:d03b1af2b8d8 | 680 | /* pages at a time ... we simply discard the last 12 */ |
zhangyx | 9:d03b1af2b8d8 | 681 | /* bytes */ |
zhangyx | 9:d03b1af2b8d8 | 682 | memcpy (buffer, pn532_packetbuffer + 1, 4); |
zhangyx | 9:d03b1af2b8d8 | 683 | } else { |
zhangyx | 9:d03b1af2b8d8 | 684 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 685 | } |
zhangyx | 9:d03b1af2b8d8 | 686 | |
zhangyx | 9:d03b1af2b8d8 | 687 | // Return OK signal |
zhangyx | 9:d03b1af2b8d8 | 688 | return 1; |
zhangyx | 9:d03b1af2b8d8 | 689 | } |
zhangyx | 9:d03b1af2b8d8 | 690 | |
zhangyx | 9:d03b1af2b8d8 | 691 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 692 | /*! |
zhangyx | 9:d03b1af2b8d8 | 693 | Tries to write an entire 4-bytes data buffer at the specified page |
zhangyx | 9:d03b1af2b8d8 | 694 | address. |
zhangyx | 9:d03b1af2b8d8 | 695 | |
zhangyx | 9:d03b1af2b8d8 | 696 | @param page The page number to write into. (0..63). |
zhangyx | 9:d03b1af2b8d8 | 697 | @param buffer The byte array that contains the data to write. |
zhangyx | 9:d03b1af2b8d8 | 698 | |
zhangyx | 9:d03b1af2b8d8 | 699 | @returns 1 if everything executed properly, 0 for an error |
zhangyx | 9:d03b1af2b8d8 | 700 | */ |
zhangyx | 9:d03b1af2b8d8 | 701 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 702 | uint8_t PN532::mifareultralight_WritePage (uint8_t page, uint8_t *buffer) |
zhangyx | 9:d03b1af2b8d8 | 703 | { |
zhangyx | 9:d03b1af2b8d8 | 704 | /* Prepare the first command */ |
zhangyx | 9:d03b1af2b8d8 | 705 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; |
zhangyx | 9:d03b1af2b8d8 | 706 | pn532_packetbuffer[1] = 1; /* Card number */ |
zhangyx | 9:d03b1af2b8d8 | 707 | pn532_packetbuffer[2] = MIFARE_CMD_WRITE_ULTRALIGHT; /* Mifare UL Write cmd = 0xA2 */ |
zhangyx | 9:d03b1af2b8d8 | 708 | pn532_packetbuffer[3] = page; /* page Number (0..63) */ |
zhangyx | 9:d03b1af2b8d8 | 709 | memcpy (pn532_packetbuffer + 4, buffer, 4); /* Data Payload */ |
zhangyx | 9:d03b1af2b8d8 | 710 | |
zhangyx | 9:d03b1af2b8d8 | 711 | /* Send the command */ |
zhangyx | 9:d03b1af2b8d8 | 712 | if (HAL(writeCommand)(pn532_packetbuffer, 8)) { |
zhangyx | 9:d03b1af2b8d8 | 713 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 714 | } |
zhangyx | 9:d03b1af2b8d8 | 715 | |
zhangyx | 9:d03b1af2b8d8 | 716 | /* Read the response packet */ |
zhangyx | 9:d03b1af2b8d8 | 717 | return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); |
zhangyx | 9:d03b1af2b8d8 | 718 | } |
zhangyx | 9:d03b1af2b8d8 | 719 | |
zhangyx | 9:d03b1af2b8d8 | 720 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 721 | /*! |
zhangyx | 9:d03b1af2b8d8 | 722 | @brief Exchanges an APDU with the currently inlisted peer |
zhangyx | 9:d03b1af2b8d8 | 723 | |
zhangyx | 9:d03b1af2b8d8 | 724 | @param send Pointer to data to send |
zhangyx | 9:d03b1af2b8d8 | 725 | @param sendLength Length of the data to send |
zhangyx | 9:d03b1af2b8d8 | 726 | @param response Pointer to response data |
zhangyx | 9:d03b1af2b8d8 | 727 | @param responseLength Pointer to the response data length |
zhangyx | 9:d03b1af2b8d8 | 728 | */ |
zhangyx | 9:d03b1af2b8d8 | 729 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 730 | bool PN532::inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength) |
zhangyx | 9:d03b1af2b8d8 | 731 | { |
zhangyx | 9:d03b1af2b8d8 | 732 | //uint8_t i; |
zhangyx | 9:d03b1af2b8d8 | 733 | |
zhangyx | 9:d03b1af2b8d8 | 734 | pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE; |
zhangyx | 9:d03b1af2b8d8 | 735 | pn532_packetbuffer[1] = inListedTag; |
zhangyx | 9:d03b1af2b8d8 | 736 | |
zhangyx | 9:d03b1af2b8d8 | 737 | if (HAL(writeCommand)(pn532_packetbuffer, 2, send, sendLength)) { |
zhangyx | 9:d03b1af2b8d8 | 738 | return false; |
zhangyx | 9:d03b1af2b8d8 | 739 | } |
zhangyx | 9:d03b1af2b8d8 | 740 | |
zhangyx | 9:d03b1af2b8d8 | 741 | int16_t status = HAL(readResponse)(response, *responseLength, 1000); |
zhangyx | 9:d03b1af2b8d8 | 742 | if (status < 0) { |
zhangyx | 9:d03b1af2b8d8 | 743 | return false; |
zhangyx | 9:d03b1af2b8d8 | 744 | } |
zhangyx | 9:d03b1af2b8d8 | 745 | |
zhangyx | 9:d03b1af2b8d8 | 746 | if ((response[0] & 0x3f) != 0) { |
zhangyx | 9:d03b1af2b8d8 | 747 | DMSG("Status code indicates an error\n"); |
zhangyx | 9:d03b1af2b8d8 | 748 | return false; |
zhangyx | 9:d03b1af2b8d8 | 749 | } |
zhangyx | 9:d03b1af2b8d8 | 750 | |
zhangyx | 9:d03b1af2b8d8 | 751 | uint8_t length = status; |
zhangyx | 9:d03b1af2b8d8 | 752 | length -= 1; |
zhangyx | 9:d03b1af2b8d8 | 753 | |
zhangyx | 9:d03b1af2b8d8 | 754 | if (length > *responseLength) { |
zhangyx | 9:d03b1af2b8d8 | 755 | length = *responseLength; // silent truncation... |
zhangyx | 9:d03b1af2b8d8 | 756 | } |
zhangyx | 9:d03b1af2b8d8 | 757 | |
zhangyx | 9:d03b1af2b8d8 | 758 | for (uint8_t i = 0; i < length; i++) { |
zhangyx | 9:d03b1af2b8d8 | 759 | response[i] = response[i + 1]; |
zhangyx | 9:d03b1af2b8d8 | 760 | } |
zhangyx | 9:d03b1af2b8d8 | 761 | *responseLength = length; |
zhangyx | 9:d03b1af2b8d8 | 762 | |
zhangyx | 9:d03b1af2b8d8 | 763 | return true; |
zhangyx | 9:d03b1af2b8d8 | 764 | } |
zhangyx | 9:d03b1af2b8d8 | 765 | |
zhangyx | 9:d03b1af2b8d8 | 766 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 767 | /*! |
zhangyx | 9:d03b1af2b8d8 | 768 | @brief 'InLists' a passive target. PN532 acting as reader/initiator, |
zhangyx | 9:d03b1af2b8d8 | 769 | peer acting as card/responder. |
zhangyx | 9:d03b1af2b8d8 | 770 | */ |
zhangyx | 9:d03b1af2b8d8 | 771 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 772 | bool PN532::inListPassiveTarget(uint8_t cardbaudrate, uint8_t initiatorDataLen, uint8_t* initiatorData, uint16_t timeout) |
zhangyx | 9:d03b1af2b8d8 | 773 | { |
zhangyx | 9:d03b1af2b8d8 | 774 | pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; |
zhangyx | 9:d03b1af2b8d8 | 775 | pn532_packetbuffer[1] = 1; |
zhangyx | 9:d03b1af2b8d8 | 776 | pn532_packetbuffer[2] = cardbaudrate; |
zhangyx | 9:d03b1af2b8d8 | 777 | |
zhangyx | 9:d03b1af2b8d8 | 778 | DMSG("inList passive target\n"); |
zhangyx | 9:d03b1af2b8d8 | 779 | |
zhangyx | 9:d03b1af2b8d8 | 780 | if (HAL(writeCommand)(pn532_packetbuffer, 3, initiatorData, initiatorDataLen)) { |
zhangyx | 9:d03b1af2b8d8 | 781 | return false; |
zhangyx | 9:d03b1af2b8d8 | 782 | } |
zhangyx | 9:d03b1af2b8d8 | 783 | |
zhangyx | 9:d03b1af2b8d8 | 784 | int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout); |
zhangyx | 9:d03b1af2b8d8 | 785 | if (status < 0) { |
zhangyx | 9:d03b1af2b8d8 | 786 | return false; |
zhangyx | 9:d03b1af2b8d8 | 787 | } |
zhangyx | 9:d03b1af2b8d8 | 788 | |
zhangyx | 9:d03b1af2b8d8 | 789 | if (pn532_packetbuffer[0] != 1) { |
zhangyx | 9:d03b1af2b8d8 | 790 | return false; |
zhangyx | 9:d03b1af2b8d8 | 791 | } |
zhangyx | 9:d03b1af2b8d8 | 792 | |
zhangyx | 9:d03b1af2b8d8 | 793 | inListedTag = pn532_packetbuffer[1]; |
zhangyx | 9:d03b1af2b8d8 | 794 | |
zhangyx | 9:d03b1af2b8d8 | 795 | return true; |
zhangyx | 9:d03b1af2b8d8 | 796 | } |
zhangyx | 9:d03b1af2b8d8 | 797 | |
zhangyx | 9:d03b1af2b8d8 | 798 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 799 | /*! |
zhangyx | 9:d03b1af2b8d8 | 800 | @brief Basic data exchanges between the PN532 and a target. |
zhangyx | 9:d03b1af2b8d8 | 801 | @param send Pointer to data to send |
zhangyx | 9:d03b1af2b8d8 | 802 | @param sendLength Length of the data to send |
zhangyx | 9:d03b1af2b8d8 | 803 | @param response Pointer to response data |
zhangyx | 9:d03b1af2b8d8 | 804 | @param responseLength Pointer to the response data length |
zhangyx | 9:d03b1af2b8d8 | 805 | */ |
zhangyx | 9:d03b1af2b8d8 | 806 | /**************************************************************************/ |
zhangyx | 9:d03b1af2b8d8 | 807 | bool PN532::inCommunicateThru(const uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength) |
zhangyx | 9:d03b1af2b8d8 | 808 | { |
zhangyx | 9:d03b1af2b8d8 | 809 | uint8_t i; |
zhangyx | 9:d03b1af2b8d8 | 810 | |
zhangyx | 9:d03b1af2b8d8 | 811 | pn532_packetbuffer[0] = PN532_COMMAND_INCOMMUNICATETHRU; |
zhangyx | 9:d03b1af2b8d8 | 812 | |
zhangyx | 9:d03b1af2b8d8 | 813 | if (HAL(writeCommand)(pn532_packetbuffer, 1, send, sendLength)) { |
zhangyx | 9:d03b1af2b8d8 | 814 | return false; |
zhangyx | 9:d03b1af2b8d8 | 815 | } |
zhangyx | 9:d03b1af2b8d8 | 816 | |
zhangyx | 9:d03b1af2b8d8 | 817 | int16_t status = HAL(readResponse)(response, *responseLength, 1000); |
zhangyx | 9:d03b1af2b8d8 | 818 | if (status < 0) { |
zhangyx | 9:d03b1af2b8d8 | 819 | return false; |
zhangyx | 9:d03b1af2b8d8 | 820 | } |
zhangyx | 9:d03b1af2b8d8 | 821 | |
zhangyx | 9:d03b1af2b8d8 | 822 | if ((response[0] & 0x3f) != 0) { |
zhangyx | 9:d03b1af2b8d8 | 823 | DMSG("Status code indicates an error\n"); |
zhangyx | 9:d03b1af2b8d8 | 824 | return false; |
zhangyx | 9:d03b1af2b8d8 | 825 | } |
zhangyx | 9:d03b1af2b8d8 | 826 | |
zhangyx | 9:d03b1af2b8d8 | 827 | uint8_t length = status; |
zhangyx | 9:d03b1af2b8d8 | 828 | length -= 1; |
zhangyx | 9:d03b1af2b8d8 | 829 | |
zhangyx | 9:d03b1af2b8d8 | 830 | if (length > *responseLength) { |
zhangyx | 9:d03b1af2b8d8 | 831 | length = *responseLength; // silent truncation... |
zhangyx | 9:d03b1af2b8d8 | 832 | } |
zhangyx | 9:d03b1af2b8d8 | 833 | |
zhangyx | 9:d03b1af2b8d8 | 834 | for (uint8_t i = 0; i < length; i++) { |
zhangyx | 9:d03b1af2b8d8 | 835 | response[i] = response[i + 1]; |
zhangyx | 9:d03b1af2b8d8 | 836 | } |
zhangyx | 9:d03b1af2b8d8 | 837 | *responseLength = length; |
zhangyx | 9:d03b1af2b8d8 | 838 | |
zhangyx | 9:d03b1af2b8d8 | 839 | return true; |
zhangyx | 9:d03b1af2b8d8 | 840 | } |
zhangyx | 9:d03b1af2b8d8 | 841 | |
zhangyx | 9:d03b1af2b8d8 | 842 | bool PN532::writeRegister(uint8_t number, const uint16_t *addrs, const uint8_t *values){ |
zhangyx | 9:d03b1af2b8d8 | 843 | uint8_t j = 1; |
zhangyx | 9:d03b1af2b8d8 | 844 | pn532_packetbuffer[0] = PN532_COMMAND_WRITEREGISTER; |
zhangyx | 9:d03b1af2b8d8 | 845 | for (uint8_t i = 0; i < number; ++i) |
zhangyx | 9:d03b1af2b8d8 | 846 | { |
zhangyx | 9:d03b1af2b8d8 | 847 | pn532_packetbuffer[j++] = addrs[i] >> 8; |
zhangyx | 9:d03b1af2b8d8 | 848 | pn532_packetbuffer[j++] = addrs[i] & 0xff; |
zhangyx | 9:d03b1af2b8d8 | 849 | pn532_packetbuffer[j++] = values[i]; |
zhangyx | 9:d03b1af2b8d8 | 850 | } |
zhangyx | 9:d03b1af2b8d8 | 851 | if (HAL(writeCommand)(pn532_packetbuffer, j)) { |
zhangyx | 9:d03b1af2b8d8 | 852 | return false; |
zhangyx | 9:d03b1af2b8d8 | 853 | } |
zhangyx | 9:d03b1af2b8d8 | 854 | int16_t status = HAL(readResponse)(pn532_packetbuffer, 0, 100); |
zhangyx | 9:d03b1af2b8d8 | 855 | if (status < 0) { |
zhangyx | 9:d03b1af2b8d8 | 856 | return false; |
zhangyx | 9:d03b1af2b8d8 | 857 | } |
zhangyx | 9:d03b1af2b8d8 | 858 | return true; |
zhangyx | 9:d03b1af2b8d8 | 859 | } |
zhangyx | 9:d03b1af2b8d8 | 860 | |
zhangyx | 9:d03b1af2b8d8 | 861 | bool PN532::readRegister(uint8_t number, const uint16_t *addrs, uint8_t *values){ |
zhangyx | 9:d03b1af2b8d8 | 862 | uint8_t j = 1; |
zhangyx | 9:d03b1af2b8d8 | 863 | pn532_packetbuffer[0] = PN532_COMMAND_READREGISTER; |
zhangyx | 9:d03b1af2b8d8 | 864 | for (uint8_t i = 0; i < number; ++i) |
zhangyx | 9:d03b1af2b8d8 | 865 | { |
zhangyx | 9:d03b1af2b8d8 | 866 | pn532_packetbuffer[j++] = addrs[i] >> 8; |
zhangyx | 9:d03b1af2b8d8 | 867 | pn532_packetbuffer[j++] = addrs[i] & 0xff; |
zhangyx | 9:d03b1af2b8d8 | 868 | } |
zhangyx | 9:d03b1af2b8d8 | 869 | if (HAL(writeCommand)(pn532_packetbuffer, j)) { |
zhangyx | 9:d03b1af2b8d8 | 870 | return false; |
zhangyx | 9:d03b1af2b8d8 | 871 | } |
zhangyx | 9:d03b1af2b8d8 | 872 | int16_t status = HAL(readResponse)(values, number, 100); |
zhangyx | 9:d03b1af2b8d8 | 873 | if (status < 0) { |
zhangyx | 9:d03b1af2b8d8 | 874 | return false; |
zhangyx | 9:d03b1af2b8d8 | 875 | } |
zhangyx | 9:d03b1af2b8d8 | 876 | return true; |
zhangyx | 9:d03b1af2b8d8 | 877 | } |
zhangyx | 9:d03b1af2b8d8 | 878 | |
zhangyx | 9:d03b1af2b8d8 | 879 | int8_t PN532::tgInitAsTarget(const uint8_t* command, const uint8_t len, const uint16_t timeout){ |
zhangyx | 9:d03b1af2b8d8 | 880 | |
zhangyx | 9:d03b1af2b8d8 | 881 | int8_t status = HAL(writeCommand)(command, len); |
zhangyx | 9:d03b1af2b8d8 | 882 | if (status < 0) { |
zhangyx | 9:d03b1af2b8d8 | 883 | return -1; |
zhangyx | 9:d03b1af2b8d8 | 884 | } |
zhangyx | 9:d03b1af2b8d8 | 885 | |
zhangyx | 9:d03b1af2b8d8 | 886 | status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout); |
zhangyx | 9:d03b1af2b8d8 | 887 | if (status > 0) { |
zhangyx | 9:d03b1af2b8d8 | 888 | return 1; |
zhangyx | 9:d03b1af2b8d8 | 889 | } else if (PN532_TIMEOUT == status) { |
zhangyx | 9:d03b1af2b8d8 | 890 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 891 | } else { |
zhangyx | 9:d03b1af2b8d8 | 892 | return -2; |
zhangyx | 9:d03b1af2b8d8 | 893 | } |
zhangyx | 9:d03b1af2b8d8 | 894 | } |
zhangyx | 9:d03b1af2b8d8 | 895 | |
zhangyx | 9:d03b1af2b8d8 | 896 | /** |
zhangyx | 9:d03b1af2b8d8 | 897 | * Peer to Peer |
zhangyx | 9:d03b1af2b8d8 | 898 | */ |
zhangyx | 9:d03b1af2b8d8 | 899 | int8_t PN532::tgInitAsTarget(uint16_t timeout) |
zhangyx | 9:d03b1af2b8d8 | 900 | { |
zhangyx | 9:d03b1af2b8d8 | 901 | const uint8_t command[] = { |
zhangyx | 9:d03b1af2b8d8 | 902 | PN532_COMMAND_TGINITASTARGET, |
zhangyx | 9:d03b1af2b8d8 | 903 | 0, |
zhangyx | 9:d03b1af2b8d8 | 904 | 0x00, 0x00, //SENS_RES |
zhangyx | 9:d03b1af2b8d8 | 905 | 0x00, 0x00, 0x00, //NFCID1 |
zhangyx | 9:d03b1af2b8d8 | 906 | 0x40, //SEL_RES |
zhangyx | 9:d03b1af2b8d8 | 907 | |
zhangyx | 9:d03b1af2b8d8 | 908 | 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, // POL_RES |
zhangyx | 9:d03b1af2b8d8 | 909 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
zhangyx | 9:d03b1af2b8d8 | 910 | 0xFF, 0xFF, |
zhangyx | 9:d03b1af2b8d8 | 911 | |
zhangyx | 9:d03b1af2b8d8 | 912 | 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, //NFCID3t: Change this to desired value |
zhangyx | 9:d03b1af2b8d8 | 913 | |
zhangyx | 9:d03b1af2b8d8 | 914 | 0x0a, 0x46, 0x66, 0x6D, 0x01, 0x01, 0x10, 0x02, 0x02, 0x00, 0x80, // LLCP magic number, version parameter and MIUX |
zhangyx | 9:d03b1af2b8d8 | 915 | 0x00 |
zhangyx | 9:d03b1af2b8d8 | 916 | }; |
zhangyx | 9:d03b1af2b8d8 | 917 | return tgInitAsTarget(command, sizeof(command), timeout); |
zhangyx | 9:d03b1af2b8d8 | 918 | } |
zhangyx | 9:d03b1af2b8d8 | 919 | |
zhangyx | 9:d03b1af2b8d8 | 920 | int16_t PN532::tgGetData(uint8_t *buf, uint8_t len) |
zhangyx | 9:d03b1af2b8d8 | 921 | { |
zhangyx | 9:d03b1af2b8d8 | 922 | buf[0] = PN532_COMMAND_TGGETDATA; |
zhangyx | 9:d03b1af2b8d8 | 923 | |
zhangyx | 9:d03b1af2b8d8 | 924 | if (HAL(writeCommand)(buf, 1)) { |
zhangyx | 9:d03b1af2b8d8 | 925 | return -1; |
zhangyx | 9:d03b1af2b8d8 | 926 | } |
zhangyx | 9:d03b1af2b8d8 | 927 | |
zhangyx | 9:d03b1af2b8d8 | 928 | int16_t status = HAL(readResponse)(buf, len, 3000); |
zhangyx | 9:d03b1af2b8d8 | 929 | if (0 >= status) { |
zhangyx | 9:d03b1af2b8d8 | 930 | return status; |
zhangyx | 9:d03b1af2b8d8 | 931 | } |
zhangyx | 9:d03b1af2b8d8 | 932 | |
zhangyx | 9:d03b1af2b8d8 | 933 | uint16_t length = status - 1; |
zhangyx | 9:d03b1af2b8d8 | 934 | |
zhangyx | 9:d03b1af2b8d8 | 935 | |
zhangyx | 9:d03b1af2b8d8 | 936 | if (buf[0] != 0) { |
zhangyx | 9:d03b1af2b8d8 | 937 | DMSG("status is not ok\n"); |
zhangyx | 9:d03b1af2b8d8 | 938 | return -5; |
zhangyx | 9:d03b1af2b8d8 | 939 | } |
zhangyx | 9:d03b1af2b8d8 | 940 | |
zhangyx | 9:d03b1af2b8d8 | 941 | for (uint8_t i = 0; i < length; i++) { |
zhangyx | 9:d03b1af2b8d8 | 942 | buf[i] = buf[i + 1]; |
zhangyx | 9:d03b1af2b8d8 | 943 | } |
zhangyx | 9:d03b1af2b8d8 | 944 | |
zhangyx | 9:d03b1af2b8d8 | 945 | return length; |
zhangyx | 9:d03b1af2b8d8 | 946 | } |
zhangyx | 9:d03b1af2b8d8 | 947 | |
zhangyx | 9:d03b1af2b8d8 | 948 | bool PN532::tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) |
zhangyx | 9:d03b1af2b8d8 | 949 | { |
zhangyx | 9:d03b1af2b8d8 | 950 | if (hlen > (sizeof(pn532_packetbuffer) - 1)) { |
zhangyx | 9:d03b1af2b8d8 | 951 | if ((body != 0) || (header == pn532_packetbuffer)) { |
zhangyx | 9:d03b1af2b8d8 | 952 | DMSG("tgSetData:buffer too small\n"); |
zhangyx | 9:d03b1af2b8d8 | 953 | return false; |
zhangyx | 9:d03b1af2b8d8 | 954 | } |
zhangyx | 9:d03b1af2b8d8 | 955 | |
zhangyx | 9:d03b1af2b8d8 | 956 | pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA; |
zhangyx | 9:d03b1af2b8d8 | 957 | if (HAL(writeCommand)(pn532_packetbuffer, 1, header, hlen)) { |
zhangyx | 9:d03b1af2b8d8 | 958 | return false; |
zhangyx | 9:d03b1af2b8d8 | 959 | } |
zhangyx | 9:d03b1af2b8d8 | 960 | } else { |
zhangyx | 9:d03b1af2b8d8 | 961 | for (int8_t i = hlen - 1; i >= 0; i--){ |
zhangyx | 9:d03b1af2b8d8 | 962 | pn532_packetbuffer[i + 1] = header[i]; |
zhangyx | 9:d03b1af2b8d8 | 963 | } |
zhangyx | 9:d03b1af2b8d8 | 964 | pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA; |
zhangyx | 9:d03b1af2b8d8 | 965 | |
zhangyx | 9:d03b1af2b8d8 | 966 | if (HAL(writeCommand)(pn532_packetbuffer, hlen + 1, body, blen)) { |
zhangyx | 9:d03b1af2b8d8 | 967 | return false; |
zhangyx | 9:d03b1af2b8d8 | 968 | } |
zhangyx | 9:d03b1af2b8d8 | 969 | } |
zhangyx | 9:d03b1af2b8d8 | 970 | |
zhangyx | 9:d03b1af2b8d8 | 971 | if (0 > HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 3000)) { |
zhangyx | 9:d03b1af2b8d8 | 972 | return false; |
zhangyx | 9:d03b1af2b8d8 | 973 | } |
zhangyx | 9:d03b1af2b8d8 | 974 | |
zhangyx | 9:d03b1af2b8d8 | 975 | if (0 != pn532_packetbuffer[0]) { |
zhangyx | 9:d03b1af2b8d8 | 976 | return false; |
zhangyx | 9:d03b1af2b8d8 | 977 | } |
zhangyx | 9:d03b1af2b8d8 | 978 | |
zhangyx | 9:d03b1af2b8d8 | 979 | return true; |
zhangyx | 9:d03b1af2b8d8 | 980 | } |
zhangyx | 9:d03b1af2b8d8 | 981 | |
zhangyx | 9:d03b1af2b8d8 | 982 | int16_t PN532::inRelease(const uint8_t relevantTarget){ |
zhangyx | 9:d03b1af2b8d8 | 983 | |
zhangyx | 9:d03b1af2b8d8 | 984 | pn532_packetbuffer[0] = PN532_COMMAND_INRELEASE; |
zhangyx | 9:d03b1af2b8d8 | 985 | pn532_packetbuffer[1] = relevantTarget; |
zhangyx | 9:d03b1af2b8d8 | 986 | |
zhangyx | 9:d03b1af2b8d8 | 987 | if (HAL(writeCommand)(pn532_packetbuffer, 2)) { |
zhangyx | 9:d03b1af2b8d8 | 988 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 989 | } |
zhangyx | 9:d03b1af2b8d8 | 990 | |
zhangyx | 9:d03b1af2b8d8 | 991 | // read data packet |
zhangyx | 9:d03b1af2b8d8 | 992 | return HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); |
zhangyx | 9:d03b1af2b8d8 | 993 | } |
zhangyx | 9:d03b1af2b8d8 | 994 | |
zhangyx | 9:d03b1af2b8d8 | 995 | void PN532::configFor14443B() |
zhangyx | 9:d03b1af2b8d8 | 996 | { |
zhangyx | 9:d03b1af2b8d8 | 997 | uint8_t param[] = {1}; |
zhangyx | 9:d03b1af2b8d8 | 998 | rfConfiguration(1, 1, param); //RF On |
zhangyx | 9:d03b1af2b8d8 | 999 | delay(50); |
zhangyx | 9:d03b1af2b8d8 | 1000 | setPN532RegsForTypeB(); |
zhangyx | 9:d03b1af2b8d8 | 1001 | } |
zhangyx | 9:d03b1af2b8d8 | 1002 | |
zhangyx | 9:d03b1af2b8d8 | 1003 | void PN532::resetConfigFor14443B() |
zhangyx | 9:d03b1af2b8d8 | 1004 | { |
zhangyx | 9:d03b1af2b8d8 | 1005 | uint8_t param[] = {0}; |
zhangyx | 9:d03b1af2b8d8 | 1006 | restorePN532RegsForTypeB(); |
zhangyx | 9:d03b1af2b8d8 | 1007 | rfConfiguration(1, 1, param); //RF Off |
zhangyx | 9:d03b1af2b8d8 | 1008 | } |
zhangyx | 9:d03b1af2b8d8 | 1009 | |
zhangyx | 9:d03b1af2b8d8 | 1010 | bool PN532::readTsighuaStuCard(uint8_t cardId[3], uint8_t expire[3], char studentId[11], char *genderByte, char *name21) |
zhangyx | 9:d03b1af2b8d8 | 1011 | { |
zhangyx | 9:d03b1af2b8d8 | 1012 | bool result; |
zhangyx | 9:d03b1af2b8d8 | 1013 | configFor14443B(); |
zhangyx | 9:d03b1af2b8d8 | 1014 | result = doReadTsighuaStuCard(cardId, expire, studentId, genderByte, name21); |
zhangyx | 9:d03b1af2b8d8 | 1015 | return result; |
zhangyx | 9:d03b1af2b8d8 | 1016 | } |
zhangyx | 9:d03b1af2b8d8 | 1017 | bool PN532::doReadTsighuaStuCard(uint8_t cardId[3], uint8_t expire[3], char studentId[11], char *genderByte, char *name21) |
zhangyx | 9:d03b1af2b8d8 | 1018 | { |
zhangyx | 9:d03b1af2b8d8 | 1019 | uint8_t sz; |
zhangyx | 9:d03b1af2b8d8 | 1020 | |
zhangyx | 9:d03b1af2b8d8 | 1021 | static uint8_t cmd_atqb[] = {0x05, 0, 0, 0x71, 0xff}; |
zhangyx | 9:d03b1af2b8d8 | 1022 | // ComputeCrc(CRC_B, cmd_atqb, sizeof(cmd_atqb)-2, cmd_atqb+3, cmd_atqb+4); |
zhangyx | 9:d03b1af2b8d8 | 1023 | sz = sizeof(pn532_packetbuffer); |
zhangyx | 9:d03b1af2b8d8 | 1024 | if(!inCommunicateThru(cmd_atqb, sizeof(cmd_atqb), pn532_packetbuffer, &sz)) |
zhangyx | 9:d03b1af2b8d8 | 1025 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1026 | DMSG("ATQB returned"); DMSG_INT(sz); DMSG(" bytes\n"); |
zhangyx | 9:d03b1af2b8d8 | 1027 | |
zhangyx | 9:d03b1af2b8d8 | 1028 | uint8_t cmd_attrib[] = { |
zhangyx | 9:d03b1af2b8d8 | 1029 | 0x1d, |
zhangyx | 9:d03b1af2b8d8 | 1030 | /* PUPI */ pn532_packetbuffer[1], pn532_packetbuffer[2], pn532_packetbuffer[3], pn532_packetbuffer[4], |
zhangyx | 9:d03b1af2b8d8 | 1031 | 0x00, 0x08, 0x00, 0x00, |
zhangyx | 9:d03b1af2b8d8 | 1032 | /* CRC */ 0, 0 |
zhangyx | 9:d03b1af2b8d8 | 1033 | }; |
zhangyx | 9:d03b1af2b8d8 | 1034 | ComputeCrc(CRC_B, cmd_attrib, sizeof(cmd_attrib)-2, cmd_attrib+9, cmd_attrib+10); |
zhangyx | 9:d03b1af2b8d8 | 1035 | sz = sizeof(pn532_packetbuffer); |
zhangyx | 9:d03b1af2b8d8 | 1036 | if(!inCommunicateThru(cmd_attrib, sizeof(cmd_attrib), pn532_packetbuffer, &sz)) |
zhangyx | 9:d03b1af2b8d8 | 1037 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1038 | DMSG("ATTRIB returned"); DMSG_INT(sz); DMSG(" bytes\n"); |
zhangyx | 9:d03b1af2b8d8 | 1039 | |
zhangyx | 9:d03b1af2b8d8 | 1040 | static uint8_t cmd_cid[] = {0x0b, 0x00, 0x00, 0xb0, 0x95, 0x00, 0x0f, 0x5d, 0xd3}; |
zhangyx | 9:d03b1af2b8d8 | 1041 | sz = sizeof(pn532_packetbuffer); |
zhangyx | 9:d03b1af2b8d8 | 1042 | if(!inCommunicateThru(cmd_cid, sizeof(cmd_cid), pn532_packetbuffer, &sz)) |
zhangyx | 9:d03b1af2b8d8 | 1043 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1044 | DMSG("CMD-CID returned"); DMSG_INT(sz); DMSG(" bytes\n"); |
zhangyx | 9:d03b1af2b8d8 | 1045 | if(pn532_packetbuffer[sz-4] != 0x90 || pn532_packetbuffer[sz-3] != 0x00) |
zhangyx | 9:d03b1af2b8d8 | 1046 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1047 | for (int i = 0; i < 3; ++i) |
zhangyx | 9:d03b1af2b8d8 | 1048 | { |
zhangyx | 9:d03b1af2b8d8 | 1049 | cardId[i] = pn532_packetbuffer[9+i]; |
zhangyx | 9:d03b1af2b8d8 | 1050 | } |
zhangyx | 9:d03b1af2b8d8 | 1051 | for (int i = 0; i < 3; ++i) |
zhangyx | 9:d03b1af2b8d8 | 1052 | { |
zhangyx | 9:d03b1af2b8d8 | 1053 | expire[i] = pn532_packetbuffer[14+i]; |
zhangyx | 9:d03b1af2b8d8 | 1054 | } |
zhangyx | 9:d03b1af2b8d8 | 1055 | |
zhangyx | 9:d03b1af2b8d8 | 1056 | static uint8_t cmd_2[] = {0x0b, 0x00, 0x00, 0xa4, 0x04, 0x00, 0x09, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x86, 0x98, 0x07, 0x01, 0x6e, 0x1b}; |
zhangyx | 9:d03b1af2b8d8 | 1057 | sz = sizeof(pn532_packetbuffer); |
zhangyx | 9:d03b1af2b8d8 | 1058 | if(!inCommunicateThru(cmd_2, sizeof(cmd_2), pn532_packetbuffer, &sz)) |
zhangyx | 9:d03b1af2b8d8 | 1059 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1060 | DMSG("CMD-2 returned"); DMSG_INT(sz); DMSG(" bytes\n"); |
zhangyx | 9:d03b1af2b8d8 | 1061 | if(pn532_packetbuffer[sz-4] != 0x90 || pn532_packetbuffer[sz-3] != 0x00) |
zhangyx | 9:d03b1af2b8d8 | 1062 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1063 | |
zhangyx | 9:d03b1af2b8d8 | 1064 | static uint8_t cmd_3[] = {0x0a, 0x00, 0x00, 0xb0, 0x95, 0x00, 0x1e, 0x80, 0x4d}; |
zhangyx | 9:d03b1af2b8d8 | 1065 | sz = sizeof(pn532_packetbuffer); |
zhangyx | 9:d03b1af2b8d8 | 1066 | if(!inCommunicateThru(cmd_3, sizeof(cmd_3), pn532_packetbuffer, &sz)) |
zhangyx | 9:d03b1af2b8d8 | 1067 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1068 | DMSG("CMD-3 returned"); DMSG_INT(sz); DMSG(" bytes\n"); |
zhangyx | 9:d03b1af2b8d8 | 1069 | if(pn532_packetbuffer[sz-4] != 0x90 || pn532_packetbuffer[sz-3] != 0x00) |
zhangyx | 9:d03b1af2b8d8 | 1070 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1071 | |
zhangyx | 9:d03b1af2b8d8 | 1072 | static uint8_t cmd_sid[] = {0x0b, 0x00, 0x00, 0xb0, 0x96, 0x1c, 0x1f, 0x00, 0x00}; |
zhangyx | 9:d03b1af2b8d8 | 1073 | ComputeCrc(CRC_B, cmd_sid, sizeof(cmd_sid)-2, cmd_sid+7, cmd_sid+8); |
zhangyx | 9:d03b1af2b8d8 | 1074 | sz = sizeof(pn532_packetbuffer); |
zhangyx | 9:d03b1af2b8d8 | 1075 | if(!inCommunicateThru(cmd_sid, sizeof(cmd_sid), pn532_packetbuffer, &sz)) |
zhangyx | 9:d03b1af2b8d8 | 1076 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1077 | DMSG("CMD-SID returned"); DMSG_INT(sz); DMSG(" bytes\n"); |
zhangyx | 9:d03b1af2b8d8 | 1078 | if(pn532_packetbuffer[sz-4] != 0x90 || pn532_packetbuffer[sz-3] != 0x00) |
zhangyx | 9:d03b1af2b8d8 | 1079 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1080 | for (int i = 0; i < 10; ++i) |
zhangyx | 9:d03b1af2b8d8 | 1081 | { |
zhangyx | 9:d03b1af2b8d8 | 1082 | studentId[i] = pn532_packetbuffer[2+i]; |
zhangyx | 9:d03b1af2b8d8 | 1083 | } |
zhangyx | 9:d03b1af2b8d8 | 1084 | studentId[10] = '\0'; |
zhangyx | 9:d03b1af2b8d8 | 1085 | |
zhangyx | 9:d03b1af2b8d8 | 1086 | if(genderByte) |
zhangyx | 9:d03b1af2b8d8 | 1087 | *genderByte = pn532_packetbuffer[2+27]; |
zhangyx | 9:d03b1af2b8d8 | 1088 | |
zhangyx | 9:d03b1af2b8d8 | 1089 | if(name21){ |
zhangyx | 9:d03b1af2b8d8 | 1090 | static uint8_t cmd_name[] = {0x0b, 0x00, 0x00, 0xb0, 0x96, 0x00, 0x14, 0x00, 0x00}; |
zhangyx | 9:d03b1af2b8d8 | 1091 | ComputeCrc(CRC_B, cmd_name, sizeof(cmd_name)-2, cmd_name+7, cmd_name+8); |
zhangyx | 9:d03b1af2b8d8 | 1092 | sz = sizeof(pn532_packetbuffer); |
zhangyx | 9:d03b1af2b8d8 | 1093 | if(!inCommunicateThru(cmd_name, sizeof(cmd_name), pn532_packetbuffer, &sz)) |
zhangyx | 9:d03b1af2b8d8 | 1094 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1095 | DMSG("CMD-NAME returned"); DMSG_INT(sz); DMSG(" bytes\n"); |
zhangyx | 9:d03b1af2b8d8 | 1096 | if(pn532_packetbuffer[sz-4] != 0x90 || pn532_packetbuffer[sz-3] != 0x00) |
zhangyx | 9:d03b1af2b8d8 | 1097 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1098 | for (int i = 0; i < 20; ++i) |
zhangyx | 9:d03b1af2b8d8 | 1099 | { |
zhangyx | 9:d03b1af2b8d8 | 1100 | name21[i] = pn532_packetbuffer[2+i]; |
zhangyx | 9:d03b1af2b8d8 | 1101 | } |
zhangyx | 9:d03b1af2b8d8 | 1102 | name21[20] = '\0'; |
zhangyx | 9:d03b1af2b8d8 | 1103 | } |
zhangyx | 9:d03b1af2b8d8 | 1104 | return true; |
zhangyx | 9:d03b1af2b8d8 | 1105 | } |
zhangyx | 9:d03b1af2b8d8 | 1106 | bool PN532::stuCardIsPresent() |
zhangyx | 9:d03b1af2b8d8 | 1107 | { |
zhangyx | 9:d03b1af2b8d8 | 1108 | uint8_t sz; |
zhangyx | 9:d03b1af2b8d8 | 1109 | static uint8_t cmd_3[] = {0x0a, 0x00, 0x00, 0xb0, 0x95, 0x00, 0x1e, 0x80, 0x4d}; |
zhangyx | 9:d03b1af2b8d8 | 1110 | sz = sizeof(pn532_packetbuffer); |
zhangyx | 9:d03b1af2b8d8 | 1111 | if(!inCommunicateThru(cmd_3, sizeof(cmd_3), pn532_packetbuffer, &sz)) |
zhangyx | 9:d03b1af2b8d8 | 1112 | return false; |
zhangyx | 9:d03b1af2b8d8 | 1113 | DMSG("CMD-3 returned"); DMSG_INT(sz); DMSG(" bytes\n"); |
zhangyx | 9:d03b1af2b8d8 | 1114 | return true; |
zhangyx | 9:d03b1af2b8d8 | 1115 | } |
zhangyx | 9:d03b1af2b8d8 | 1116 | |
zhangyx | 9:d03b1af2b8d8 | 1117 | unsigned short PN532::UpdateCrc(unsigned char ch, unsigned short *lpwCrc) |
zhangyx | 9:d03b1af2b8d8 | 1118 | { |
zhangyx | 9:d03b1af2b8d8 | 1119 | ch = (ch ^ (unsigned char)((*lpwCrc) & 0x00FF)); |
zhangyx | 9:d03b1af2b8d8 | 1120 | ch = (ch ^ (ch << 4)); |
zhangyx | 9:d03b1af2b8d8 | 1121 | *lpwCrc = (*lpwCrc >> 8) ^ ((unsigned short)ch << 8) ^ ((unsigned short)ch << 3) ^ ((unsigned short)ch >> 4); |
zhangyx | 9:d03b1af2b8d8 | 1122 | return (*lpwCrc); |
zhangyx | 9:d03b1af2b8d8 | 1123 | } |
zhangyx | 9:d03b1af2b8d8 | 1124 | void PN532::ComputeCrc(uint8_t CRCType, uint8_t *Data, uint8_t Length, uint8_t *TransmitFirst, uint8_t *TransmitSecond) |
zhangyx | 9:d03b1af2b8d8 | 1125 | { |
zhangyx | 9:d03b1af2b8d8 | 1126 | unsigned char chBlock; |
zhangyx | 9:d03b1af2b8d8 | 1127 | unsigned short wCrc; |
zhangyx | 9:d03b1af2b8d8 | 1128 | switch (CRCType) { |
zhangyx | 9:d03b1af2b8d8 | 1129 | case CRC_A: |
zhangyx | 9:d03b1af2b8d8 | 1130 | wCrc = 0x6363; /* ITU-V.41 */ |
zhangyx | 9:d03b1af2b8d8 | 1131 | break; |
zhangyx | 9:d03b1af2b8d8 | 1132 | case CRC_B: |
zhangyx | 9:d03b1af2b8d8 | 1133 | wCrc = 0xFFFF; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ |
zhangyx | 9:d03b1af2b8d8 | 1134 | break; |
zhangyx | 9:d03b1af2b8d8 | 1135 | default: |
zhangyx | 9:d03b1af2b8d8 | 1136 | return; |
zhangyx | 9:d03b1af2b8d8 | 1137 | } |
zhangyx | 9:d03b1af2b8d8 | 1138 | do { |
zhangyx | 9:d03b1af2b8d8 | 1139 | chBlock = *Data++; UpdateCrc(chBlock, &wCrc); |
zhangyx | 9:d03b1af2b8d8 | 1140 | } while (--Length); |
zhangyx | 9:d03b1af2b8d8 | 1141 | if (CRCType == CRC_B) |
zhangyx | 9:d03b1af2b8d8 | 1142 | wCrc = ~wCrc; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ *TransmitFirst = (uint8_t) (wCrc & 0xFF); |
zhangyx | 9:d03b1af2b8d8 | 1143 | *TransmitSecond = (uint8_t) ((wCrc >> 8) & 0xFF); |
zhangyx | 9:d03b1af2b8d8 | 1144 | return; |
zhangyx | 9:d03b1af2b8d8 | 1145 | } |
zhangyx | 9:d03b1af2b8d8 | 1146 | |
zhangyx | 9:d03b1af2b8d8 | 1147 | void PN532::setPN532RegsForTypeB() |
zhangyx | 9:d03b1af2b8d8 | 1148 | { |
zhangyx | 9:d03b1af2b8d8 | 1149 | if(!readRegister(6, registerAddrForTypeB, registerValueBackup)){ |
zhangyx | 9:d03b1af2b8d8 | 1150 | DMSG("failed to backup registers for type B\n"); |
zhangyx | 9:d03b1af2b8d8 | 1151 | return; |
zhangyx | 9:d03b1af2b8d8 | 1152 | } |
zhangyx | 9:d03b1af2b8d8 | 1153 | if(!readRegister(6, registerAddrForTypeB+6, registerValueBackup+6)){ |
zhangyx | 9:d03b1af2b8d8 | 1154 | DMSG("failed to backup registers for type B\n"); |
zhangyx | 9:d03b1af2b8d8 | 1155 | return; |
zhangyx | 9:d03b1af2b8d8 | 1156 | } |
zhangyx | 9:d03b1af2b8d8 | 1157 | if(!writeRegister(6, registerAddrForTypeB, registerValueForTypeB)){ |
zhangyx | 9:d03b1af2b8d8 | 1158 | DMSG("failed to set registers for type B\n"); |
zhangyx | 9:d03b1af2b8d8 | 1159 | return; |
zhangyx | 9:d03b1af2b8d8 | 1160 | } |
zhangyx | 9:d03b1af2b8d8 | 1161 | if(!writeRegister(6, registerAddrForTypeB+6, registerValueForTypeB+6)){ |
zhangyx | 9:d03b1af2b8d8 | 1162 | DMSG("failed to set registers for type B\n"); |
zhangyx | 9:d03b1af2b8d8 | 1163 | return; |
zhangyx | 9:d03b1af2b8d8 | 1164 | } |
zhangyx | 9:d03b1af2b8d8 | 1165 | } |
zhangyx | 9:d03b1af2b8d8 | 1166 | |
zhangyx | 9:d03b1af2b8d8 | 1167 | void PN532::restorePN532RegsForTypeB() |
zhangyx | 9:d03b1af2b8d8 | 1168 | { |
zhangyx | 9:d03b1af2b8d8 | 1169 | if(!writeRegister(6, registerAddrForTypeB, registerValueBackup)){ |
zhangyx | 9:d03b1af2b8d8 | 1170 | DMSG("failed to restore registers for type B\n"); |
zhangyx | 9:d03b1af2b8d8 | 1171 | return; |
zhangyx | 9:d03b1af2b8d8 | 1172 | } |
zhangyx | 9:d03b1af2b8d8 | 1173 | if(!writeRegister(6, registerAddrForTypeB+6, registerValueBackup+6)){ |
zhangyx | 9:d03b1af2b8d8 | 1174 | DMSG("failed to restore registers for type B\n"); |
zhangyx | 9:d03b1af2b8d8 | 1175 | return; |
zhangyx | 9:d03b1af2b8d8 | 1176 | } |
zhangyx | 9:d03b1af2b8d8 | 1177 | } |
zhangyx | 9:d03b1af2b8d8 | 1178 | |
zhangyx | 9:d03b1af2b8d8 | 1179 | const uint16_t PN532::registerAddrForTypeB[12] = |
zhangyx | 9:d03b1af2b8d8 | 1180 | { |
zhangyx | 9:d03b1af2b8d8 | 1181 | PN53X_REG_CIU_Mode, |
zhangyx | 9:d03b1af2b8d8 | 1182 | PN53X_REG_CIU_TxAuto, |
zhangyx | 9:d03b1af2b8d8 | 1183 | PN53X_REG_CIU_TxMode, |
zhangyx | 9:d03b1af2b8d8 | 1184 | PN53X_REG_CIU_RxMode, |
zhangyx | 9:d03b1af2b8d8 | 1185 | PN53X_REG_CIU_TypeB, |
zhangyx | 9:d03b1af2b8d8 | 1186 | PN53X_REG_CIU_Demod, |
zhangyx | 9:d03b1af2b8d8 | 1187 | PN53X_REG_CIU_GsNOn, |
zhangyx | 9:d03b1af2b8d8 | 1188 | PN53X_REG_CIU_CWGsP, |
zhangyx | 9:d03b1af2b8d8 | 1189 | PN53X_REG_CIU_ModGsP, |
zhangyx | 9:d03b1af2b8d8 | 1190 | PN53X_REG_CIU_RxThreshold, |
zhangyx | 9:d03b1af2b8d8 | 1191 | PN53X_REG_CIU_ModWidth, |
zhangyx | 9:d03b1af2b8d8 | 1192 | PN53X_REG_CIU_ManualRCV, |
zhangyx | 9:d03b1af2b8d8 | 1193 | }; |
zhangyx | 9:d03b1af2b8d8 | 1194 | |
zhangyx | 9:d03b1af2b8d8 | 1195 | const uint8_t PN532::registerValueForTypeB[12] = |
zhangyx | 9:d03b1af2b8d8 | 1196 | { |
zhangyx | 9:d03b1af2b8d8 | 1197 | 0xff, |
zhangyx | 9:d03b1af2b8d8 | 1198 | 0x00, |
zhangyx | 9:d03b1af2b8d8 | 1199 | 0x03, |
zhangyx | 9:d03b1af2b8d8 | 1200 | 0x03, |
zhangyx | 9:d03b1af2b8d8 | 1201 | 0x03, |
zhangyx | 9:d03b1af2b8d8 | 1202 | 0x4d, |
zhangyx | 9:d03b1af2b8d8 | 1203 | 0xff, |
zhangyx | 9:d03b1af2b8d8 | 1204 | 0x3f, |
zhangyx | 9:d03b1af2b8d8 | 1205 | 0x18, |
zhangyx | 9:d03b1af2b8d8 | 1206 | 0x4d, |
zhangyx | 9:d03b1af2b8d8 | 1207 | 0x68, |
zhangyx | 9:d03b1af2b8d8 | 1208 | 0x10, |
zhangyx | 9:d03b1af2b8d8 | 1209 | }; |
zhangyx | 9:d03b1af2b8d8 | 1210 |