bool KeyDuino::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout) { pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) pn532_packetbuffer[2] = cardbaudrate; if (HAL(writeCommand)(pn532_packetbuffer, 3)) { DMSG_STR("\nFailed writing"); return 0x0; // command failed } // read data packet if (HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { DMSG_STR("\nFailed reading response"); return 0x0; } // check some basic stuff /* ISO14443A card response should be in the following format: byte Description ------------- ------------------------------------------ b0 Tags Found b1 Tag Number (only one used in this example) b2..3 SENS_RES b4 SEL_RES b5 NFCID Length b6..NFCIDLen NFCID */ if (pn532_packetbuffer[0] != 1) return 0; inListedTag = pn532_packetbuffer[1]; uint16_t sens_res = pn532_packetbuffer[2]; sens_res <<= 8; sens_res |= pn532_packetbuffer[3]; DMSG("\nATQA: 0x"); DMSG_HEX(sens_res); DMSG("\nSAK: 0x"); DMSG_HEX(pn532_packetbuffer[4]); DMSG("\n"); /* Card appears to be Mifare Classic */ *uidLength = pn532_packetbuffer[5]; this->_uidLen = pn532_packetbuffer[5]; for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) { uid[i] = pn532_packetbuffer[6 + i]; this->_uid[i] = pn532_packetbuffer[6 + i]; } return 1; }
bool KeyDuino::inListPassiveTarget(uint8_t cardbaudrate, uint16_t timeout) { pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; pn532_packetbuffer[1] = 1; pn532_packetbuffer[2] = cardbaudrate; DMSG_STR("\ninList passive target"); if(cardbaudrate == PN532_ISO14443B){ pn532_packetbuffer[3] = 0x00; if (HAL(writeCommand)(pn532_packetbuffer, 4)) return false; } else { if (HAL(writeCommand)(pn532_packetbuffer, 3)) return false; } int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout); if (status < 0) { return false; } if (pn532_packetbuffer[0] != 1) { return false; } inListedTag = pn532_packetbuffer[1]; return true; }
int8_t PN532_SPI::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) { command = header[0]; writeFrame(header, hlen, body, blen); uint8_t timeout = PN532_ACK_WAIT_TIME; while (!isReady()) { delay(1); timeout--; if (0 == timeout) { DMSG_STR("Time out when waiting for ACK"); return -2; } } if (readAckFrame()) { DMSG_STR("Invalid ACK"); return PN532_INVALID_ACK; } return 0; }
bool KeyDuino::inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength) { uint8_t i; DMSG_STR("\ninDataExchange"); pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; pn532_packetbuffer[1] = inListedTag; if (HAL(writeCommand)(pn532_packetbuffer, 2, send, sendLength)) { DMSG_STR("\nWrite error"); return false; } int16_t status = HAL(readResponse)(response, *responseLength, 1000); if (status < 0) { DMSG("\nStatus error: "); DMSG_STR(status); return false; } if ((response[0] & 0x3f) != 0) { DMSG_STR("\nStatus code indicates an error"); return false; } uint8_t length = status; length -= 1; if (length > *responseLength) { length = *responseLength; // silent truncation... } for (uint8_t i = 0; i < length; i++) { response[i] = response[i + 1]; } *responseLength = length; return true; }
bool KeyDuino::SAMConfig(void) { pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; pn532_packetbuffer[1] = 0x01; // normal mode; pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second pn532_packetbuffer[3] = 0x01; // use IRQ pin! DMSG_STR("SAMConfig"); if (HAL(writeCommand)(pn532_packetbuffer, 4)) return false; return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); }
bool KeyDuino::writeGPIO(uint8_t pinstate) { // Make sure pinstate does not try to toggle P32 or P34 pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34); // Fill command buffer pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO; pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by I2C) DMSG_STR("Writing P3 GPIO: "); DMSG_HEX(pn532_packetbuffer[1]); DMSG("\n"); // Send the WRITEGPIO command (0x0E) if (HAL(writeCommand)(pn532_packetbuffer, 3)) return 0; return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); }
void PN532_SPI::writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) { digitalWrite(_ss, LOW); delay(2); // wake up PN532 write(DATA_WRITE); write(PN532_PREAMBLE); write(PN532_STARTCODE1); write(PN532_STARTCODE2); uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA write(length); write(~length + 1); // checksum of length write(PN532_HOSTTOPN532); uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA DMSG("write: "); for (uint8_t i = 0; i < hlen; i++) { write(header[i]); sum += header[i]; DMSG_HEX(header[i]); } for (uint8_t i = 0; i < blen; i++) { write(body[i]); sum += body[i]; DMSG_HEX(body[i]); } uint8_t checksum = ~sum + 1; // checksum of TFI + DATA write(checksum); write(PN532_POSTAMBLE); digitalWrite(_ss, HIGH); DMSG_STR(); }
int16_t PN532_SPI::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout) { uint16_t time = 0; while (!isReady()) { delay(1); time++; if (timeout > 0 && time > timeout) { return PN532_TIMEOUT; } } digitalWrite(_ss, LOW); delay(1); int16_t result; do { write(DATA_READ); if (0x00 != read() || // PREAMBLE 0x00 != read() || // STARTCODE1 0xFF != read() // STARTCODE2 ) { result = PN532_INVALID_FRAME; break; } uint8_t length = read(); if (0 != (uint8_t)(length + read())) { // checksum of length result = PN532_INVALID_FRAME; break; } uint8_t cmd = command + 1; // response command if (PN532_PN532TOHOST != read() || (cmd) != read()) { result = PN532_INVALID_FRAME; break; } DMSG("read: "); DMSG_HEX(cmd); length -= 2; if (length > len) { for (uint8_t i = 0; i < length; i++) { DMSG_HEX(read()); // dump message } DMSG_STR("\nNot enough space"); read(); read(); result = PN532_NO_SPACE; // not enough space break; } uint8_t sum = PN532_PN532TOHOST + cmd; for (uint8_t i = 0; i < length; i++) { buf[i] = read(); sum += buf[i]; DMSG_HEX(buf[i]); } DMSG_STR(); uint8_t checksum = read(); if (0 != (uint8_t)(sum + checksum)) { DMSG_STR("checksum is not ok"); result = PN532_INVALID_FRAME; break; } read(); // POSTAMBLE result = length; } while (0); digitalWrite(_ss, HIGH); return result; }
bool KeyDuino::readPassiveTargetID_B(uint8_t *uid, uint8_t *uidLength, uint16_t timeout) { pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) pn532_packetbuffer[2] = PN532_ISO14443B; pn532_packetbuffer[3] = 0x00; //AFI if (HAL(writeCommand)(pn532_packetbuffer, 4)) { DMSG_STR("\nFailed writing"); return 0x0; // command failed } // read data packet if (HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { DMSG_STR("\nFailed reading response"); return 0x0; } /* ISO14443B card response should be in the following format: byte Description ------------------ ------------------------------------------ b0 Tags Found b1 Tag Number (only one used in this example) b2..13 ATQB b14 ATTRIB_RES Length b15..ATTRIB_RESLen ATTRIB_RES */ if (pn532_packetbuffer[0] != 1) return 0; inListedTag = pn532_packetbuffer[1]; /* ISO14443B ATQ_B format: byte Description ----- ------------------------------------------ b0 0x50 b1..4 PUPI b5..8 Application Data b9 Bit Rate Capacity b10 Max Frame Size/-4 Info b11 FWI/Coding Options */ uint8_t atqb[12]; DMSG("\nATQ_B: "); if (pn532_packetbuffer[2] == 0x50) { //Looking for the 0x50 to check if ATQ_B is well shaped for (uint8_t i = 0; i < 12; i++) { atqb[i] = pn532_packetbuffer[i+2]; DMSG_HEX(atqb[i]); } DMSG("\n"); } else //Sometimes there are remnant bytes, in that case just let it go ... return 0; DMSG_STR("\nATTRIB_RES: "); for (uint8_t i = 0; i < pn532_packetbuffer[14]; i++) { DMSG_HEX(pn532_packetbuffer[15 + i]); } DMSG("\n"); *uidLength = 4; this->_uidLen = 4; for (uint8_t i = 0; i < 4; i++) { uid[i] = atqb[1 + i]; this->_uid[i] = atqb[1 + i]; } return 1; }