Esempio n. 1
0
uint8_t PN532::readGPIO(void)
{
    pn532_packetbuffer[0] = PN532_COMMAND_READGPIO;

    // Send the READGPIO command (0x0C)
    if (HAL(writeCommand)(pn532_packetbuffer, 1))
        return 0x0;

    HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));

    /* READGPIO response without prefix and suffix should be in the following format:

      byte            Description
      -------------   ------------------------------------------
      b0              P3 GPIO Pins
      b1              P7 GPIO Pins (not used ... taken by I2C)
      b2              Interface Mode Pins (not used ... bus select pins)
    */


    DMSG("P3 GPIO: "); DMSG_HEX(pn532_packetbuffer[7]);
    DMSG("P7 GPIO: "); DMSG_HEX(pn532_packetbuffer[8]);
    DMSG("I0I1 GPIO: "); DMSG_HEX(pn532_packetbuffer[9]);
    DMSG("\n");

    return pn532_packetbuffer[0];
}
Esempio n. 2
0
// TODO this should return a Driver MifareClassic, MifareUltralight, Type 4, Unknown
// Guess Tag Type by looking at the ATQA and SAK values
// Need to follow spec for Card Identification. Maybe AN1303, AN1305 and ???
unsigned int NfcAdapter::guessTagType()
{

    // 4 uint8_t id - Mifare Classic
    //  - ATQA 0x4 && SAK 0x8
    // 7 uint8_t id
    //  - ATQA 0x44 && SAK 0x8 - Mifare Classic
    //  - ATQA 0x44 && SAK 0x0 - Mifare Ultralight NFC Forum Type 2
    //  - ATQA 0x344 && SAK 0x20 - NFC Forum Type 4
    DMSG("Guess type");
    DMSG("ATQA: 0x");  DMSG_HEX(ATQA);
    DMSG("SAK: 0x");  DMSG_HEX(SAK);
    /*if (uidLength == 4)
    {
        return TAG_TYPE_MIFARE_CLASSIC;
    }
    else
    {
        return TAG_TYPE_2;
    }*/
    if(ATQA==0x4&&SAK==0x8){
        return TAG_TYPE_MIFARE_CLASSIC;
    }
    if(ATQA==0x44&&SAK==0x0){
        return TAG_TYPE_2;
    }
    return TAG_TYPE_UNKNOWN;
}
Esempio n. 3
0
File: PN532.cpp Progetto: don/PN532
boolean PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength) {
  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("No card(s) read");
    return 0x0;  // no cards read
  }
  
  // Wait for a card to enter the field
  uint8_t status = PN532_I2C_BUSY;
 
  // read data packet
  HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
  
  // check some basic stuff
  /* ISO14443A card response should be in the following format:
  
    byte            Description
    -------------   ------------------------------------------
    b0..6           Frame header and preamble
    b7              Tags Found
    b8              Tag Number (only one used in this example)
    b9..10          SENS_RES
    b11             SEL_RES
    b12             NFCID Length
    b13..NFCIDLen   NFCID                                      */
  
  DMSG("Found "); DMSG(pn532_packetbuffer[0]); DMSG(" tags\n");

  if (pn532_packetbuffer[0] != 1) 
    return 0;
    
  uint16_t sens_res = pn532_packetbuffer[2];
  sens_res <<= 8;
  sens_res |= pn532_packetbuffer[3];

  DMSG("ATQA: 0x");  DMSG_HEX(sens_res); 
  DMSG("SAK: 0x");  DMSG_HEX(pn532_packetbuffer[4]); 
  
  /* Card appears to be Mifare Classic */
  *uidLength = pn532_packetbuffer[5];

  DMSG("UID:"); 
  for (uint8_t i=0; i < pn532_packetbuffer[5]; i++) 
  {
    uid[i] = pn532_packetbuffer[6+i];
    DMSG(uid[i]); 
  }
  DMSG('\n');

  return 1;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
int8_t PN532_I2C::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
{
    command = header[0];
    _wire->beginTransmission(PN532_I2C_ADDRESS);
    
    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++) {
        if (write(header[i])) {
            sum += header[i];
            
            DMSG_HEX(header[i]);
        } else {
            DMSG("\nToo many data to send, I2C doesn't support such a big packet\n");     // I2C max packet: 32 bytes
            return PN532_INVALID_FRAME;
        }
    }

    for (uint8_t i = 0; i < blen; i++) {
        if (write(body[i])) {
            sum += body[i];
            
            DMSG_HEX(body[i]);
        } else {
            DMSG("\nToo many data to send, I2C doesn't support such a big packet\n");     // I2C max packet: 32 bytes
            return PN532_INVALID_FRAME;
        }
    }
  
    uint8_t checksum = ~sum + 1;            // checksum of TFI + DATA
    write(checksum);
    write(PN532_POSTAMBLE);
    
    _wire->endTransmission();
    
    DMSG('\n');

    return readAckFrame();
}
Esempio n. 6
0
/**
    @brief receive data .
    @param buf --> return value buffer.
           len --> length expect to receive.
           timeout --> time of reveiving
    @retval number of received bytes, 0 means no data received.
*/
int8_t PN532_HSU::receive(uint8_t *buf, int len, uint16_t timeout)
{
  int read_bytes = 0;
  int ret;
  unsigned long start_millis;

  while (read_bytes < len) {
    start_millis = millis();
    do {
      ret = _serial->read();
      if (ret >= 0) {
        break;
     }
     delay(1);
    } while((timeout == 0) || ((millis()- start_millis ) < timeout));

    if (ret < 0) {
        if(read_bytes){
            return read_bytes;
        }else{
            return PN532_TIMEOUT;
        }
    }
    buf[read_bytes] = (uint8_t)ret;
    DMSG_HEX(ret);
    read_bytes++;
  }
  return read_bytes;
}
Esempio n. 7
0
int8_t PN532_HSU::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
{

    /** dump serial buffer */
    if(_serial->available()){
        DMSG("Dump serial buffer: ");
    }
    while(_serial->available()){
        uint8_t ret = _serial->read();
        DMSG_HEX(ret);
    }

    command = header[0];

    _serial->write(PN532_PREAMBLE);
    _serial->write(PN532_STARTCODE1);
    _serial->write(PN532_STARTCODE2);

    uint8_t length = hlen + blen + 1;   // length of data field: TFI + DATA
    _serial->write(length);
    _serial->write(~length + 1);         // checksum of length

    _serial->write(PN532_HOSTTOPN532);
    uint8_t sum = PN532_HOSTTOPN532;    // sum of TFI + DATA

    DMSG("\r\nWrite: ");

    _serial->write(header, hlen);
    for (uint8_t i = 0; i < hlen; i++) {
        sum += header[i];

        DMSG_HEX(header[i]);
    }

    _serial->write(body, blen);
    for (uint8_t i = 0; i < blen; i++) {
        sum += body[i];

        DMSG_HEX(body[i]);
    }

    uint8_t checksum = ~sum + 1;            // checksum of TFI + DATA
    _serial->write(checksum);
    _serial->write(PN532_POSTAMBLE);

    return readAckFrame();
}
Esempio n. 8
0
File: PN532.cpp Progetto: don/PN532
uint8_t PN532::readGPIO(void) {
  pn532_packetbuffer[0] = PN532_COMMAND_READGPIO;

  // Send the READGPIO command (0x0C)  
  if (HAL(writeCommand)(pn532_packetbuffer, 1))
    return 0x0;
  
  HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));

  /* READGPIO response without prefix and suffix should be in the following format:
  
    byte            Description
    -------------   ------------------------------------------
    b0              P3 GPIO Pins
    b1              P7 GPIO Pins (not used ... taken by I2C)
    b2              Interface Mode Pins (not used ... bus select pins) 
  */
  

  DMSG("P3 GPIO: "); DMSG_HEX(pn532_packetbuffer[7]);
  DMSG("P7 GPIO: "); DMSG_HEX(pn532_packetbuffer[8]);
  DMSG("I0I1 GPIO: "); DMSG_HEX(pn532_packetbuffer[9]);
    
  #ifdef DEBUG
    // Note: You can use the IO GPIO value to detect the serial bus being used
    switch(pn532_packetbuffer[3])
    {
      case 0x00:    // Using UART
        Serial.println("Using UART (IO = 0x00)");
        break;
      case 0x01:    // Using I2C 
        Serial.println("Using I2C (IO = 0x01)");
        break;
      case 0x02:    // Using I2C
        Serial.println("Using I2C (IO = 0x02)");
        break;
    }
  #endif

  return pn532_packetbuffer[0];
}
Esempio n. 9
0
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();
}
Esempio n. 10
0
void PN532_HSU::wakeup()
{
    _serial->write(0x55);
    _serial->write(0x55);
    _serial->write(0);
    _serial->write(0);
    _serial->write(0);

    /** dump serial buffer */
    if(_serial->available()){
        DMSG("Dump serial buffer: ");
    }
    while(_serial->available()){
        uint8_t ret = _serial->read();
        DMSG_HEX(ret);
    }

}
Esempio n. 11
0
bool PN532::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("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)));
}
Esempio n. 12
0
bool EmulateTag::emulate(const uint16_t tgInitAsTargetTimeout){

  uint8_t command[] = {
        PN532_COMMAND_TGINITASTARGET,
        5,                  // MODE: PICC only, Passive only

        0x04, 0x00,         // SENS_RES
        0x00, 0x00, 0x00,   // NFCID1
        0x20,               // SEL_RES

        0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,   // FeliCaParams
        0,0,

        0,0,0,0,0,0,0,0,0,0, // NFCID3t

        0, // length of general bytes
        0  // length of historical bytes
  };

  if(uidPtr != 0){  // if uid is set copy 3 bytes to nfcid1
    memcpy(command + 4, uidPtr, 3);
  }

  if(1 != pn532.tgInitAsTarget(command,sizeof(command), tgInitAsTargetTimeout)){
    DMSG("tgInitAsTarget failed or timed out!");
    pn532.inRelease();
    pn532.powerDown(0xF0);
    return false;
  }

  uint8_t compatibility_container[] = {
    0, 0x0F,
    0x20,
    0, 0x54,
    0, 0xFF,
    0x04,       // T
    0x06,       // L
    0xE1, 0x04, // File identifier
    ((NDEF_MAX_LENGTH & 0xFF00) >> 8), (NDEF_MAX_LENGTH & 0xFF), // maximum NDEF file size
    0x00,       // read access 0x0 = granted
    0x00        // write access 0x0 = granted | 0xFF = deny
  };

  if(tagWriteable == false){
    compatibility_container[14] = 0xFF;
  }

  tagWrittenByInitiator = false;

  uint8_t rwbuf[128];
  uint8_t sendlen;
  int16_t status;
  tag_file currentFile = NONE;
  uint16_t cc_size = sizeof(compatibility_container);
  bool runLoop = true;

  while(runLoop){
    status = pn532.tgGetData(rwbuf, sizeof(rwbuf));
    if(status < 0){
      DMSG("tgGetData failed!\n");
      pn532.inRelease();
      pn532.powerDown(0xF0);
      return true;
    }

    uint8_t p1 = rwbuf[C_APDU_P1];
    uint8_t p2 = rwbuf[C_APDU_P2];
    uint8_t lc = rwbuf[C_APDU_LC];
    uint16_t p1p2_length = ((int16_t) p1 << 8) + p2;

    switch(rwbuf[C_APDU_INS]){
    case ISO7816_SELECT_FILE:
      switch(p1){
      case C_APDU_P1_SELECT_BY_ID:
	if(p2 != 0x0c){
	  DMSG("C_APDU_P2 != 0x0c\n");
	  setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
	} else if(lc == 2 && rwbuf[C_APDU_DATA] == 0xE1 && (rwbuf[C_APDU_DATA+1] == 0x03 || rwbuf[C_APDU_DATA+1] == 0x04)){
	  setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
	  if(rwbuf[C_APDU_DATA+1] == 0x03){
	    currentFile = CC;
	  } else if(rwbuf[C_APDU_DATA+1] == 0x04){
	    currentFile = NDEF;
	  }
	} else {
	  setResponse(TAG_NOT_FOUND, rwbuf, &sendlen);
	}
	break;
      case C_APDU_P1_SELECT_BY_NAME: 
        const uint8_t ndef_tag_application_name_v2[] = {0, 0x7, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 };
	if(0 == memcmp(ndef_tag_application_name_v2, rwbuf + C_APDU_P2, sizeof(ndef_tag_application_name_v2))){
	  setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
	} else{
	  DMSG("function not supported\n");
	  setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
	} 
	break;
      }
      break;
    case ISO7816_READ_BINARY:
      switch(currentFile){
      case NONE:
	setResponse(TAG_NOT_FOUND, rwbuf, &sendlen);
	break;
      case CC:
	if( p1p2_length > NDEF_MAX_LENGTH){
	  setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen);
	}else {
	  memcpy(rwbuf,compatibility_container + p1p2_length, lc);
	  setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc);
	}
	break;
      case NDEF:
	if( p1p2_length > NDEF_MAX_LENGTH){
	  setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen);
	}else {
	  memcpy(rwbuf, ndef_file + p1p2_length, lc);
	  setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc);
	}
	break;
      }
      break;    
    case ISO7816_UPDATE_BINARY:
      if(!tagWriteable){
	  setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
      } else{      
	if( p1p2_length > NDEF_MAX_LENGTH){
	  setResponse(MEMORY_FAILURE, rwbuf, &sendlen);
	}
	else{
	  memcpy(ndef_file + p1p2_length, rwbuf + C_APDU_DATA, lc);
	  setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
	  tagWrittenByInitiator = true;
	}
      }
      break;
    default:
      DMSG("Command not supported!");
      DMSG_HEX(rwbuf[C_APDU_INS]);
      DMSG("\n");
      setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
    }
    status = pn532.tgSetData(rwbuf, sendlen);
    if(status < 0){
      DMSG("tgSetData failed\n!");
      pn532.inRelease();
      pn532.powerDown(0xF0);
      return true;
    }
  }
  pn532.inRelease();
  pn532.powerDown(0xF0);
  return true;
}
Esempio n. 13
0
int16_t PN532_I2C::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout)
{
    uint16_t time = 0;

    do {
        if (_wire->requestFrom(PN532_I2C_ADDRESS, len + 2)) {
            if (read() & 1) {  // check first byte --- status
                break;         // PN532 is ready
            }
        }

        delay(1);
        time++;
        if ((0 != timeout) && (time > timeout)) {
            return -1;
        }
    } while (1); 
    
    if (0x00 != read()      ||       // PREAMBLE
            0x00 != read()  ||       // STARTCODE1
            0xFF != read()           // STARTCODE2
        ) {
        
        return PN532_INVALID_FRAME;
    }
    
    uint8_t length = read();
    if (0 != (uint8_t)(length + read())) {   // checksum of length
        return PN532_INVALID_FRAME;
    }
    
    uint8_t cmd = command + 1;               // response command
    if (PN532_PN532TOHOST != read() || (cmd) != read()) {
        return PN532_INVALID_FRAME;
    }
    
    length -= 2;
    if (length > len) {
        return PN532_NO_SPACE;  // not enough space
    }
    
    DMSG("read:  ");
    DMSG_HEX(cmd);
    
    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('\n');
    
    uint8_t checksum = read();
    if (0 != (uint8_t)(sum + checksum)) {
        DMSG("checksum is not ok\n");
        return PN532_INVALID_FRAME;
    }
    read();         // POSTAMBLE
    
    return length;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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;
}