PN532 NFC library for Seeed Studio's NFC Shield

Fork of PN532 by Yihui Xiong

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

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 3:4189a10038e6 1
yihui 3:4189a10038e6 2 #include "llcp.h"
yihui 3:4189a10038e6 3 #include "PN532_debug.h"
yihui 3:4189a10038e6 4
yihui 3:4189a10038e6 5 // LLCP PDU Type Values
yihui 3:4189a10038e6 6 #define PDU_SYMM 0x00
yihui 3:4189a10038e6 7 #define PDU_PAX 0x01
yihui 3:4189a10038e6 8 #define PDU_CONNECT 0x04
yihui 3:4189a10038e6 9 #define PDU_DISC 0x05
yihui 3:4189a10038e6 10 #define PDU_CC 0x06
yihui 3:4189a10038e6 11 #define PDU_DM 0x07
yihui 3:4189a10038e6 12 #define PDU_I 0x0c
yihui 3:4189a10038e6 13 #define PDU_RR 0x0d
yihui 3:4189a10038e6 14
yihui 3:4189a10038e6 15 uint8_t LLCP::SYMM_PDU[2] = {0, 0};
yihui 3:4189a10038e6 16
yihui 3:4189a10038e6 17 inline uint8_t getPType(const uint8_t *buf)
yihui 3:4189a10038e6 18 {
yihui 3:4189a10038e6 19 return ((buf[0] & 0x3) << 2) + (buf[1] >> 6);
yihui 3:4189a10038e6 20 }
yihui 3:4189a10038e6 21
yihui 3:4189a10038e6 22 inline uint8_t getSSAP(const uint8_t *buf)
yihui 3:4189a10038e6 23 {
yihui 3:4189a10038e6 24 return buf[1] & 0x3f;
yihui 3:4189a10038e6 25 }
yihui 3:4189a10038e6 26
yihui 3:4189a10038e6 27 inline uint8_t getDSAP(const uint8_t *buf)
yihui 3:4189a10038e6 28 {
yihui 3:4189a10038e6 29 return buf[0] >> 2;
yihui 3:4189a10038e6 30 }
yihui 3:4189a10038e6 31
yihui 3:4189a10038e6 32 int8_t LLCP::activate(uint16_t timeout)
yihui 3:4189a10038e6 33 {
yihui 3:4189a10038e6 34 return link.activateAsTarget(timeout);
yihui 3:4189a10038e6 35 }
yihui 3:4189a10038e6 36
yihui 3:4189a10038e6 37 int8_t LLCP::waitForConnection(uint16_t timeout)
yihui 3:4189a10038e6 38 {
yihui 3:4189a10038e6 39 uint8_t type;
yihui 3:4189a10038e6 40
yihui 3:4189a10038e6 41 ns = 0;
yihui 3:4189a10038e6 42 nr = 0;
yihui 3:4189a10038e6 43
yihui 3:4189a10038e6 44 // Get CONNECT PDU
yihui 3:4189a10038e6 45 DMSG("wait for a CONNECT PDU\n");
yihui 3:4189a10038e6 46 do {
yihui 3:4189a10038e6 47 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 3:4189a10038e6 48 return -1;
yihui 3:4189a10038e6 49 }
yihui 3:4189a10038e6 50
yihui 3:4189a10038e6 51 type = getPType(headerBuf);
yihui 3:4189a10038e6 52 if (PDU_CONNECT == type) {
yihui 3:4189a10038e6 53 break;
yihui 3:4189a10038e6 54 } else if (PDU_SYMM == type) {
yihui 3:4189a10038e6 55 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 3:4189a10038e6 56 return -2;
yihui 3:4189a10038e6 57 }
yihui 3:4189a10038e6 58 } else {
yihui 3:4189a10038e6 59 return -3;
yihui 3:4189a10038e6 60 }
yihui 3:4189a10038e6 61
yihui 3:4189a10038e6 62 } while (1);
yihui 3:4189a10038e6 63
yihui 3:4189a10038e6 64 // Put CC PDU
yihui 3:4189a10038e6 65 DMSG("put a CC(Connection Complete) PDU to response the CONNECT PDU\n");
yihui 3:4189a10038e6 66 ssap = getDSAP(headerBuf);
yihui 3:4189a10038e6 67 dsap = getSSAP(headerBuf);
yihui 3:4189a10038e6 68 headerBuf[0] = (dsap << 2) + ((PDU_CC >> 2) & 0x3);
yihui 3:4189a10038e6 69 headerBuf[1] = ((PDU_CC & 0x3) << 6) + ssap;
yihui 3:4189a10038e6 70 if (!link.write(headerBuf, 2)) {
yihui 3:4189a10038e6 71 return -2;
yihui 3:4189a10038e6 72 }
yihui 3:4189a10038e6 73
yihui 3:4189a10038e6 74 return 1;
yihui 3:4189a10038e6 75 }
yihui 3:4189a10038e6 76
yihui 3:4189a10038e6 77 int8_t LLCP::waitForDisconnection(uint16_t timeout)
yihui 3:4189a10038e6 78 {
yihui 3:4189a10038e6 79 uint8_t type;
yihui 3:4189a10038e6 80
yihui 3:4189a10038e6 81 // Get DISC PDU
yihui 3:4189a10038e6 82 DMSG("wait for a DISC PDU\n");
yihui 3:4189a10038e6 83 do {
yihui 3:4189a10038e6 84 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 3:4189a10038e6 85 return -1;
yihui 3:4189a10038e6 86 }
yihui 3:4189a10038e6 87
yihui 3:4189a10038e6 88 type = getPType(headerBuf);
yihui 3:4189a10038e6 89 if (PDU_DISC == type) {
yihui 3:4189a10038e6 90 break;
yihui 3:4189a10038e6 91 } else if (PDU_SYMM == type) {
yihui 3:4189a10038e6 92 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 3:4189a10038e6 93 return -2;
yihui 3:4189a10038e6 94 }
yihui 3:4189a10038e6 95 } else {
yihui 3:4189a10038e6 96 return -3;
yihui 3:4189a10038e6 97 }
yihui 3:4189a10038e6 98
yihui 3:4189a10038e6 99 } while (1);
yihui 3:4189a10038e6 100
yihui 3:4189a10038e6 101 // Put DM PDU
yihui 3:4189a10038e6 102 DMSG("put a DM(Disconnect Mode) PDU to response the DISC PDU\n");
yihui 3:4189a10038e6 103 // ssap = getDSAP(headerBuf);
yihui 3:4189a10038e6 104 // dsap = getSSAP(headerBuf);
yihui 3:4189a10038e6 105 headerBuf[0] = (dsap << 2) + (PDU_DM >> 2);
yihui 3:4189a10038e6 106 headerBuf[1] = ((PDU_DM & 0x3) << 6) + ssap;
yihui 3:4189a10038e6 107 if (!link.write(headerBuf, 2)) {
yihui 3:4189a10038e6 108 return -2;
yihui 3:4189a10038e6 109 }
yihui 3:4189a10038e6 110
yihui 3:4189a10038e6 111 return 1;
yihui 3:4189a10038e6 112 }
yihui 3:4189a10038e6 113
yihui 3:4189a10038e6 114 int8_t LLCP::connect(uint16_t timeout)
yihui 3:4189a10038e6 115 {
yihui 3:4189a10038e6 116 uint8_t type;
yihui 3:4189a10038e6 117
yihui 3:4189a10038e6 118 ns = 0;
yihui 3:4189a10038e6 119 nr = 0;
yihui 3:4189a10038e6 120
yihui 3:4189a10038e6 121 // try to get a SYMM PDU
yihui 3:4189a10038e6 122 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 3:4189a10038e6 123 return -1;
yihui 3:4189a10038e6 124 }
yihui 3:4189a10038e6 125 type = getPType(headerBuf);
yihui 3:4189a10038e6 126 if (PDU_SYMM != type) {
yihui 3:4189a10038e6 127 return -1;
yihui 3:4189a10038e6 128 }
yihui 3:4189a10038e6 129
yihui 3:4189a10038e6 130 dsap = LLCP_DEFAULT_DSAP;
yihui 3:4189a10038e6 131 ssap = LLCP_DEFAULT_SSAP;
yihui 3:4189a10038e6 132
yihui 3:4189a10038e6 133 // put a CONNECT PDU
yihui 3:4189a10038e6 134 headerBuf[0] = (LLCP_DEFAULT_DSAP << 2) + (PDU_CONNECT >> 2);
yihui 3:4189a10038e6 135 headerBuf[1] = ((PDU_CONNECT & 0x03) << 6) + LLCP_DEFAULT_SSAP;
yihui 3:4189a10038e6 136 if (!link.write(headerBuf, 2)) {
yihui 3:4189a10038e6 137 return -2;
yihui 3:4189a10038e6 138 }
yihui 3:4189a10038e6 139
yihui 3:4189a10038e6 140 // wait for a CC PDU
yihui 3:4189a10038e6 141 DMSG("wait for a CC PDU\n");
yihui 3:4189a10038e6 142 do {
yihui 3:4189a10038e6 143 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 3:4189a10038e6 144 return -1;
yihui 3:4189a10038e6 145 }
yihui 3:4189a10038e6 146
yihui 3:4189a10038e6 147 type = getPType(headerBuf);
yihui 3:4189a10038e6 148 if (PDU_CC == type) {
yihui 3:4189a10038e6 149 break;
yihui 3:4189a10038e6 150 } else if (PDU_SYMM == type) {
yihui 3:4189a10038e6 151 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 3:4189a10038e6 152 return -2;
yihui 3:4189a10038e6 153 }
yihui 3:4189a10038e6 154 } else {
yihui 3:4189a10038e6 155 return -3;
yihui 3:4189a10038e6 156 }
yihui 3:4189a10038e6 157
yihui 3:4189a10038e6 158 } while (1);
yihui 3:4189a10038e6 159
yihui 3:4189a10038e6 160 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 3:4189a10038e6 161 return -2;
yihui 3:4189a10038e6 162 }
yihui 3:4189a10038e6 163
yihui 3:4189a10038e6 164 return 1;
yihui 3:4189a10038e6 165 }
yihui 3:4189a10038e6 166
yihui 3:4189a10038e6 167 int8_t LLCP::disconnect(uint16_t timeout)
yihui 3:4189a10038e6 168 {
yihui 3:4189a10038e6 169 uint8_t type;
yihui 3:4189a10038e6 170
yihui 3:4189a10038e6 171 // try to get a SYMM PDU
yihui 3:4189a10038e6 172 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 3:4189a10038e6 173 return -1;
yihui 3:4189a10038e6 174 }
yihui 3:4189a10038e6 175 type = getPType(headerBuf);
yihui 3:4189a10038e6 176 if (PDU_SYMM != type) {
yihui 3:4189a10038e6 177 return -1;
yihui 3:4189a10038e6 178 }
yihui 3:4189a10038e6 179
yihui 3:4189a10038e6 180 // put a DISC PDU
yihui 3:4189a10038e6 181 headerBuf[0] = (LLCP_DEFAULT_DSAP << 2) + (PDU_DISC >> 2);
yihui 3:4189a10038e6 182 headerBuf[1] = ((PDU_DISC & 0x03) << 6) + LLCP_DEFAULT_SSAP;
yihui 3:4189a10038e6 183 if (!link.write(headerBuf, 2)) {
yihui 3:4189a10038e6 184 return -2;
yihui 3:4189a10038e6 185 }
yihui 3:4189a10038e6 186
yihui 3:4189a10038e6 187 // wait for a DM PDU
yihui 3:4189a10038e6 188 DMSG("wait for a DM PDU\n");
yihui 3:4189a10038e6 189 do {
yihui 3:4189a10038e6 190 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 3:4189a10038e6 191 return -1;
yihui 3:4189a10038e6 192 }
yihui 3:4189a10038e6 193
yihui 3:4189a10038e6 194 type = getPType(headerBuf);
yihui 3:4189a10038e6 195 if (PDU_CC == type) {
yihui 3:4189a10038e6 196 break;
yihui 3:4189a10038e6 197 } else if (PDU_DM == type) {
yihui 3:4189a10038e6 198 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 3:4189a10038e6 199 return -2;
yihui 3:4189a10038e6 200 }
yihui 3:4189a10038e6 201 } else {
yihui 3:4189a10038e6 202 return -3;
yihui 3:4189a10038e6 203 }
yihui 3:4189a10038e6 204
yihui 3:4189a10038e6 205 } while (1);
yihui 3:4189a10038e6 206
yihui 3:4189a10038e6 207 return 1;
yihui 3:4189a10038e6 208 }
yihui 3:4189a10038e6 209
yihui 3:4189a10038e6 210 bool LLCP::write(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
yihui 3:4189a10038e6 211 {
yihui 3:4189a10038e6 212 uint8_t type;
yihui 3:4189a10038e6 213 uint8_t buf[3];
yihui 3:4189a10038e6 214
yihui 3:4189a10038e6 215 // Get a SYMM PDU
yihui 3:4189a10038e6 216 if (2 != link.read(buf, sizeof(buf))) {
yihui 3:4189a10038e6 217 return false;
yihui 3:4189a10038e6 218 }
yihui 3:4189a10038e6 219
yihui 3:4189a10038e6 220 if (headerBufLen < (hlen + 3)) {
yihui 3:4189a10038e6 221 return false;
yihui 3:4189a10038e6 222 }
yihui 3:4189a10038e6 223
yihui 3:4189a10038e6 224 for (int8_t i = hlen - 1; i >= 0; i--) {
yihui 3:4189a10038e6 225 headerBuf[i + 3] = header[i];
yihui 3:4189a10038e6 226 }
yihui 3:4189a10038e6 227
yihui 3:4189a10038e6 228 headerBuf[0] = (dsap << 2) + (PDU_I >> 2);
yihui 3:4189a10038e6 229 headerBuf[1] = ((PDU_I & 0x3) << 6) + ssap;
yihui 3:4189a10038e6 230 headerBuf[2] = (ns << 4) + nr;
yihui 3:4189a10038e6 231 if (!link.write(headerBuf, 3 + hlen, body, blen)) {
yihui 3:4189a10038e6 232 return false;
yihui 3:4189a10038e6 233 }
yihui 3:4189a10038e6 234
yihui 3:4189a10038e6 235 ns++;
yihui 3:4189a10038e6 236
yihui 3:4189a10038e6 237 // Get a RR PDU
yihui 3:4189a10038e6 238 int16_t status;
yihui 3:4189a10038e6 239 do {
yihui 3:4189a10038e6 240 status = link.read(headerBuf, headerBufLen);
yihui 3:4189a10038e6 241 if (2 > status) {
yihui 3:4189a10038e6 242 return false;
yihui 3:4189a10038e6 243 }
yihui 3:4189a10038e6 244
yihui 3:4189a10038e6 245 type = getPType(headerBuf);
yihui 3:4189a10038e6 246 if (PDU_RR == type) {
yihui 3:4189a10038e6 247 break;
yihui 3:4189a10038e6 248 } else if (PDU_SYMM == type) {
yihui 3:4189a10038e6 249 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 3:4189a10038e6 250 return false;
yihui 3:4189a10038e6 251 }
yihui 3:4189a10038e6 252 } else {
yihui 3:4189a10038e6 253 return false;
yihui 3:4189a10038e6 254 }
yihui 3:4189a10038e6 255 } while (1);
yihui 3:4189a10038e6 256
yihui 3:4189a10038e6 257 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 3:4189a10038e6 258 return false;
yihui 3:4189a10038e6 259 }
yihui 3:4189a10038e6 260
yihui 3:4189a10038e6 261 return true;
yihui 3:4189a10038e6 262 }
yihui 3:4189a10038e6 263
yihui 3:4189a10038e6 264 int16_t LLCP::read(uint8_t *buf, uint8_t length)
yihui 3:4189a10038e6 265 {
yihui 3:4189a10038e6 266 uint8_t type;
yihui 3:4189a10038e6 267 uint16_t status;
yihui 3:4189a10038e6 268
yihui 3:4189a10038e6 269 // Get INFO PDU
yihui 3:4189a10038e6 270 do {
yihui 3:4189a10038e6 271 status = link.read(buf, length);
yihui 3:4189a10038e6 272 if (2 > status) {
yihui 3:4189a10038e6 273 return -1;
yihui 3:4189a10038e6 274 }
yihui 3:4189a10038e6 275
yihui 3:4189a10038e6 276 type = getPType(buf);
yihui 3:4189a10038e6 277 if (PDU_I == type) {
yihui 3:4189a10038e6 278 break;
yihui 3:4189a10038e6 279 } else if (PDU_SYMM == type) {
yihui 3:4189a10038e6 280 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 3:4189a10038e6 281 return -2;
yihui 3:4189a10038e6 282 }
yihui 3:4189a10038e6 283 } else {
yihui 3:4189a10038e6 284 return -3;
yihui 3:4189a10038e6 285 }
yihui 3:4189a10038e6 286
yihui 3:4189a10038e6 287 } while (1);
yihui 3:4189a10038e6 288
yihui 3:4189a10038e6 289 uint8_t len = status - 3;
yihui 3:4189a10038e6 290 ssap = getDSAP(buf);
yihui 3:4189a10038e6 291 dsap = getSSAP(buf);
yihui 3:4189a10038e6 292
yihui 3:4189a10038e6 293 headerBuf[0] = (dsap << 2) + (PDU_RR >> 2);
yihui 3:4189a10038e6 294 headerBuf[1] = ((PDU_RR & 0x3) << 6) + ssap;
yihui 3:4189a10038e6 295 headerBuf[2] = (buf[2] >> 4) + 1;
yihui 3:4189a10038e6 296 if (!link.write(headerBuf, 3)) {
yihui 3:4189a10038e6 297 return -2;
yihui 3:4189a10038e6 298 }
yihui 3:4189a10038e6 299
yihui 3:4189a10038e6 300 for (uint8_t i = 0; i < len; i++) {
yihui 3:4189a10038e6 301 buf[i] = buf[i + 3];
yihui 3:4189a10038e6 302 }
yihui 3:4189a10038e6 303
yihui 3:4189a10038e6 304 nr++;
yihui 3:4189a10038e6 305
yihui 3:4189a10038e6 306 return len;
yihui 3:4189a10038e6 307 }