コード例 #1
0
pn532_error_t pn532_mifareclassic_WaitForPassiveTarget (byte_t * pbtCUID, size_t * szCUIDLen)
{
  byte_t abtResponse[PN532_RESPONSELEN_INLISTPASSIVETARGET];
  pn532_error_t error;
  size_t szLen;

  #ifdef PN532_DEBUGMODE
    PN532_DEBUG("Waiting for an ISO14443A Card%s", CFG_PRINTF_NEWLINE);
  #endif

  /* Try to initialise a single ISO14443A tag at 106KBPS                  */
  /* Note:  To wait for a card with a known UID, append the four byte     */
  /*        UID to the end of the command.                                */ 
  byte_t abtCommand[] = { PN532_COMMAND_INLISTPASSIVETARGET, 0x01, PN532_MODULATION_ISO14443A_106KBPS};
  error = pn532Write(abtCommand, sizeof(abtCommand));
  if (error) 
    return error;

  /* Wait until we get a valid response or a timeout                      */
  do
  {
    systickDelay(25);
    error = pn532Read(abtResponse, &szLen);
  } while (error == PN532_ERROR_RESPONSEBUFFEREMPTY);
  if (error) 
    return error;

  /* Check SENSE_RES to make sure this is a Mifare Classic card           */
  /*          Classic 1K       = 00 04                                    */
  /*          Classic 4K       = 00 02                                    */
  /*          Classic Emulated = 00 08                                    */
  if ((abtResponse[10] == 0x02) || 
      (abtResponse[10] == 0x04) || 
      (abtResponse[10] == 0x08))
  {
    /* Card appears to be Mifare Classic */
    *szCUIDLen = abtResponse[12];
    uint8_t i;
    for (i=0; i < *szCUIDLen; i++) 
    {
      pbtCUID[i] = abtResponse[13+i];
    }
    #ifdef PN532_DEBUGMODE
      PN532_DEBUG("Card Found: %s", CFG_PRINTF_NEWLINE);
      PN532_DEBUG("      ATQA: ");
      pn532PrintHex(abtResponse+9, 2);
      PN532_DEBUG("      SAK: %02x%s", abtResponse[11], CFG_PRINTF_NEWLINE);
      PN532_DEBUG("      UID: ");
      pn532PrintHex(pbtCUID, *szCUIDLen);
    #endif
  }
  else
  {
    /* Card is ISO14443A but doesn't appear to be Mifare Classic          */
    /*    Mifare Ultralight    = 0x0044                                   */
    /*    Mifare DESFire       = 0x0344                                   */
    /*    Innovision Jewel     = 0x0C00                                   */
    #ifdef PN532_DEBUGMODE
      PN532_DEBUG("Wrong Card Type (Expected ATQA 00 02, 00 04 or 00 08) %s%s", CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
      PN532_DEBUG("  ATQA       : ");
      pn532PrintHex(abtResponse+9, 2);
      PN532_DEBUG("  SAK        : %02x%s", abtResponse[11], CFG_PRINTF_NEWLINE);
      PN532_DEBUG("  UID Length : %d%s", abtResponse[12], CFG_PRINTF_NEWLINE);
      PN532_DEBUG("  UID        : ");
      size_t pos;
      for (pos=0; pos < abtResponse[12]; pos++) 
      {
        printf("%02x ", abtResponse[13 + pos]);
      }
      printf("%s%s", CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
    #endif
    return PN532_ERROR_WRONGCARDTYPE;
  }

  return PN532_ERROR_NONE;
}
コード例 #2
0
pn532_error_t pn532_mifareclassic_AuthenticateBlock (byte_t * pbtCUID, size_t szCUIDLen, uint32_t uiBlockNumber, uint8_t uiKeyType, byte_t * pbtKeys)
{
  pn532_error_t error;
  byte_t abtCommand[17];
  byte_t abtResponse[PN532_RESPONSELEN_INDATAEXCHANGE];
  size_t szLen;

  #ifdef PN532_DEBUGMODE
  PN532_DEBUG("Trying to authenticate card ");
  pn532PrintHex(pbtCUID, szCUIDLen);
  #endif

  /* Prepare the authentication command */
  abtCommand[0] = PN532_COMMAND_INDATAEXCHANGE;   /* Data Exchange Header */
  abtCommand[1] = 1;                              /* Max card numbers */
  abtCommand[2] = (uiKeyType) ? PN532_MIFARE_CMD_AUTH_A : PN532_MIFARE_CMD_AUTH_B;
  abtCommand[3] = uiBlockNumber;                  /* Block Number (1K = 0..63, 4K = 0..255 */
  memcpy (abtCommand+4, pbtKeys, 6);
  uint8_t i;
  for (i = 0; i < szCUIDLen; i++)
  {
    abtCommand[10+i] = pbtCUID[i];                /* 4 byte card ID */
  }
  
  /* Send the command */
  error = pn532Write(abtCommand, 10+szCUIDLen);
  if (error)
  {
    /* Problem with the serial bus, etc. */
    #ifdef PN532_DEBUGMODE
      PN532_DEBUG("Authentification failed%s", CFG_PRINTF_NEWLINE);
    #endif
    return error;
  }

  /* Read the authentication response */
  memset(abtResponse, 0, PN532_RESPONSELEN_INDATAEXCHANGE);
  do
  {
    systickDelay(25);
    error = pn532Read(abtResponse, &szLen);
  }
  while (error == PN532_ERROR_RESPONSEBUFFEREMPTY);
  if (error)
  {
    #ifdef PN532_DEBUGMODE
      PN532_DEBUG("Authentification failed%s", CFG_PRINTF_NEWLINE);
    #endif
    return error;
  }

  // ToDo: How to check if authentification really worked (bad key, etc.)?

  /* Output the authentification data */
  #ifdef PN532_DEBUGMODE
    PN532_DEBUG("Authenticated block %d %s", uiBlockNumber, CFG_PRINTF_NEWLINE);
  #endif

  // Return OK signal
  return PN532_ERROR_NONE;
}
コード例 #3
0
pn532_error_t pn532_bus_ReadResponse(byte_t * pbtResponse, size_t * pszRxLen)
{
  uint8_t i;
  pn532_pcb_t *pn532 = pn532GetPCB();

  // Check if we're busy
  if (pn532->state == PN532_STATE_BUSY)
  {
    return PN532_ERROR_BUSY;
  }

  // Flag the stack as busy
  pn532->state = PN532_STATE_BUSY;

  // Reset the app error flag
  pn532->appError = PN532_APPERROR_NONE;

  for ( i = 0; i < I2C_BUFSIZE; i++ )
  {
    I2CMasterBuffer[i] = 0x00;
  }
  I2CWriteLength = 0;
  I2CReadLength = I2C_BUFSIZE;
  I2CMasterBuffer[0] = PN532_I2C_ADDRESS | PN532_I2C_READBIT;
  i2cEngine();

  // Use the full I2C buffer size for now (until we're sure we have a good frame)
  *pszRxLen = I2C_BUFSIZE - 1;

  // Display the raw response data for debugging if requested
  #ifdef PN532_DEBUGMODE
  PN532_DEBUG("Received (%02d): ", I2C_BUFSIZE-1);
  pn532PrintHex(I2CSlaveBuffer+1, I2C_BUFSIZE-1);
  #endif

  // Check the frame type
  if ((0x01 == I2CSlaveBuffer[4]) && (0xff == I2CSlaveBuffer[5]))
  {
    // Error frame
    #ifdef PN532_DEBUGMODE
    PN532_DEBUG("Application level error (0x%02x)%s", I2CSlaveBuffer[6], CFG_PRINTF_NEWLINE);
    #endif
    // Set application error message ID
    pn532->appError = I2CSlaveBuffer[6];
    pn532->state = PN532_STATE_READY;
    return PN532_ERROR_APPLEVELERROR;
  }
  else if ((0xff == I2CSlaveBuffer[4]) && (0xff == I2CSlaveBuffer[5]))
  {
    // Extended frame
    #ifdef PN532_DEBUGMODE
    PN532_DEBUG("Extended frames currently unsupported%s", CFG_PRINTF_NEWLINE);
    #endif
    pn532->state = PN532_STATE_READY;
    return PN532_ERROR_EXTENDEDFRAME;
  }
  else
  {
    // Normal frame
    if (256 != ((I2CSlaveBuffer[4]) + (I2CSlaveBuffer[5])))
    {
      // TODO: Retry
      #ifdef PN532_DEBUGMODE
      PN532_DEBUG("Length checksum mismatch%s", CFG_PRINTF_NEWLINE);
      #endif
      pn532->state = PN532_STATE_READY;
      return PN532_ERROR_LENCHECKSUMMISMATCH;
    }
  }

  // Figure out how large the response really is
  // Response Frame Len = pbtResponse[4] + 7 (00 00 FF LEN LCS TFI [DATA] DCS)
  *pszRxLen = (I2CSlaveBuffer[4]) + 7;

  // TODO: Find a solution for this horribly ugly Mifare Classic block write hack!
  // Some responses to command 0x40 report the incorrect len, and don't take into
  // account the 16 byte payload when working with Mifare Classic sectors.
  // The response frame indicates len 10 (0x0A) in I2CSlaveBuffer[4] but it should be
  // 10+16 = 26 (0x1A)
  if ((*pszRxLen == 10) && (I2CSlaveBuffer[7] == 0x41) && (I2CSlaveBuffer[26] != 0x00))
  {
    // For some reason, the PN532 reports len 10 for responses to
    // command 0x40 which includes the command data but does not
    // take into account the response/payload data in the len byte
    *pszRxLen+=16;
  }

  // Fill the response buffer
  // memcpy(pbtResponse, I2CSlaveBuffer+1, *pszRxLen);
  for ( i = 0; i < *pszRxLen; i++ )
  {
    pbtResponse[i] = I2CSlaveBuffer[i+1];
  }

  pn532->state = PN532_STATE_READY;
  return PN532_ERROR_NONE;
}
コード例 #4
0
pn532_error_t pn532_bus_SendCommand(const byte_t * pbtData, const size_t szData)
{
  pn532_error_t error = PN532_ERROR_NONE;
  byte_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff };
  size_t szFrame = 0;
  pn532_pcb_t *pn532 = pn532GetPCB();
  uint32_t i;

  // Check if we're busy
  if (pn532->state == PN532_STATE_BUSY)
  {
    return PN532_ERROR_BUSY;
  }

  // Flag the stack as busy
  pn532->state = PN532_STATE_BUSY;

  // --------------------------------------------------------------------
  // Send the command frame
  // --------------------------------------------------------------------
  // Build the frame
  pn532_bus_i2c_BuildFrame (abtFrame, &szFrame, pbtData, szData);

  // Keep track of the last command that was sent
  pn532->lastCommand = pbtData[0];

  // Output the frame data for debugging if requested
  #ifdef PN532_DEBUGMODE
  PN532_DEBUG("Sending  (%02d): ", szFrame);
  pn532PrintHex(abtFrame, szFrame);
  #endif

  // Send data to the PN532
  error = pn532_bus_i2c_WriteData(abtFrame, szFrame);

  if (error == PN532_ERROR_I2C_NACK)
  {
    // Most likely error is PN532_ERROR_I2C_NACK
    // meaning no I2C ACK received from the PN532
    #ifdef PN532_DEBUGMODE
    PN532_DEBUG ("No ACK received on I2C bus%s", CFG_PRINTF_NEWLINE);
    #endif
    pn532->state = PN532_STATE_READY;
    return error;
  }

  // --------------------------------------------------------------------
  // Wait for the IRQ/Ready flag
  // --------------------------------------------------------------------
  if (!(pn532_bus_i2c_WaitForReady(PN532_I2C_TIMEOUT)))
  {
    pn532->state = PN532_STATE_READY;
    #ifdef PN532_DEBUGMODE
    PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE);
    #endif
    return PN532_ERROR_READYSTATUSTIMEOUT;
  }

  // --------------------------------------------------------------------
  // Read the ACK frame
  // --------------------------------------------------------------------
  I2CWriteLength = 0;
  I2CReadLength = 7;  // ACK + Ready bit = 7
  I2CMasterBuffer[0] = PN532_I2C_ADDRESS | PN532_I2C_READBIT;
  i2cEngine();

  // Make sure the received ACK matches the prototype
  do
  {
    const byte_t abtAck[6] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
    byte_t abtRxBuf[6];
    // memcpy(abtRxBuf, I2CSlaveBuffer+1, 6);
    for ( i = 0; i < 6; i++ )
    {
      abtRxBuf[i] = I2CSlaveBuffer[i+1];
    }
    if (0 != (memcmp (abtRxBuf, abtAck, 6)))
    {
      #ifdef PN532_DEBUGMODE
      PN532_DEBUG ("Invalid ACK: ");
      pn532PrintHex(abtRxBuf, 6);
      PN532_DEBUG("%s", CFG_PRINTF_NEWLINE);
      #endif
      pn532->state = PN532_STATE_READY;
      return PN532_ERROR_INVALIDACK;
    }

    // --------------------------------------------------------------------
    // Wait for the post-ACK IRQ/Ready flag
    // --------------------------------------------------------------------
    if (!(pn532_bus_i2c_WaitForReady(PN532_I2C_TIMEOUT)))
    {
      pn532->state = PN532_STATE_READY;
      #ifdef PN532_DEBUGMODE
      PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE);
      #endif
      return PN532_ERROR_READYSTATUSTIMEOUT;
    }
  } while(0);

  pn532->state = PN532_STATE_READY;
  return PN532_ERROR_NONE;
}
コード例 #5
0
ファイル: main.c プロジェクト: Miceuz/LPC1343CodeBase
int main (void)
{
  #ifdef CFG_INTERFACE
    //#error "CFG_INTERFACE must be disabled in projectconfig.h for this demo"
  #endif
  #if !defined CFG_PRINTF_USBCDC
    #error "CFG_PRINTF_USBCDC must be enabled in projectconfig.h for this demo"
  #endif

  // Configure cpu and mandatory peripherals
  systemInit();
  
  // Wait a bit for someone to open the USB connection for printf
  systickDelay(5000);

  // Initialise the PN532
  pn532Init();

  pn532_error_t error;
  byte_t response[64];
  size_t responseLen;

  // Setup command to initialise a single ISO14443A target at 106kbps (Mifare Classic, Ultralight, etc.)
  byte_t abtCommand[] = { PN532_COMMAND_INLISTPASSIVETARGET, 0x01, PN532_MODULATION_ISO14443A_106KBPS };

  while (1)
  {
    printf("%s", CFG_PRINTF_NEWLINE);
    printf("Waiting for an ISO14443A card (Mifare Classic, etc.)%s", CFG_PRINTF_NEWLINE);

    // Send the command (and handle the most common errors)
    error = pn532Write(abtCommand, sizeof(abtCommand));
    if (error)
    {
      // Something went wrong sending the command (probably the bus selection or wiring)
      switch(error)
      {
        case (PN532_ERROR_NOACK):
        case (PN532_ERROR_INVALIDACK):
          // No ACK response frame received from the PN532
          printf("Ooops ... No valid ACK frame received!%s", CFG_PRINTF_NEWLINE);
          break;
        case (PN532_ERROR_I2C_NACK):
          // No ACK bit received to I2C start ... not same as PN532 ACK frame (bus pins not set correctly?)
          printf("Ooops ... No I2C ACK received! Are the bus select pins sets to I2C?%s", CFG_PRINTF_NEWLINE);
          break;
        case (PN532_ERROR_READYSTATUSTIMEOUT):
          // Timed out waiting for the ready bit to clear ... this can be intentional, though, in the
          // case of PN532_COMMAND_INLISTPASSIVETARGET since it will only clear when a card
          // enters the magnetic field!  Handle with caution because it isn't always an error
          // Note: Only valid for I2C and SPI
          printf("Timed out waiting for Ready/IRQ%s", CFG_PRINTF_NEWLINE);
          break;
        default:
          printf("Ooops ... something went wrong! [PN532 Error Code: 0x%02X]%s", error, CFG_PRINTF_NEWLINE);
          break;
      }
    }
    else
    {
      // Commmand seems to have gone through ... 
      do
      {
        // Keep reading until we get a response or an unexpected error condition
        error = pn532Read(response, &responseLen);
        systickDelay(25);
      }
      while (error == PN532_ERROR_RESPONSEBUFFEREMPTY);

      printf("%s", CFG_PRINTF_NEWLINE);
      printf("%-12s: ", "Received");
      pn532PrintHex(response, responseLen);

      // Try to handle some potential frame errors
      // Unhandled errors are caught further down
      switch (error)
      {
        case (PN532_ERROR_PREAMBLEMISMATCH):
          // Frame should start with 0x00 0x00 0xFF!
          printf("Response frame doesn't start with expected preamble (00 00 FF)%s", CFG_PRINTF_NEWLINE);
          break;
        case (PN532_ERROR_APPLEVELERROR):
          printf("Application level error reported by PN532%s", CFG_PRINTF_NEWLINE);
          break;
        case (PN532_ERROR_LENCHECKSUMMISMATCH):          
          printf("Frame length check/checksum mismatch%s", CFG_PRINTF_NEWLINE);
          break;
        default:
          // Other errors handled below
          break;
      }
  
      // Print the card details if possible
      if (!error)
      {
        /* Response for ISO14443A 106KBPS (Mifare Classic, etc.)
           See UM0701-02 section 7.3.5 for more information
  
           byte            Description
           -------------   ------------------------------------------
           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
           
           SENS_RES   SEL_RES     Manufacturer/Card Type    NFCID Len
           --------   -------     -----------------------   ---------
           00 04      08          NXP Mifare Classic 1K     4 bytes   */
  
        printf("%-12s: %d %s", "Tags Found", response[7], CFG_PRINTF_NEWLINE);
        printf("%-12s: %02X %02X %s", "SENS_RES", response[9], response[10], CFG_PRINTF_NEWLINE);
        printf("%-12s: %02X %s", "SEL_RES", response[11], CFG_PRINTF_NEWLINE);
        printf("%-12s: ", "NFCID");
        size_t pos;
        for (pos=0; pos < response[12]; pos++) 
        {
          printf("%02x ", response[13 + pos]);
        }
        printf(CFG_PRINTF_NEWLINE);
        if ((response[9] == 0x00) && (response[10] == 0x04) && (response[11] == 0x08))
        {
          printf("Seems to be a Mifare Classic 1K Card%s", CFG_PRINTF_NEWLINE);
        }
      }
      else
      {
        // Oops .... something bad happened.  Check 'error'
        printf("Ooops! Error %02X %s", error, CFG_PRINTF_NEWLINE);
      }
    }

    // Wait at least one second before trying again
    systickDelay(1000);
  }
}
コード例 #6
0
pn532_error_t pn532_bus_ReadResponse(byte_t * pbtResponse, size_t * pszRxLen)
{
  pn532_pcb_t *pn532 = pn532GetPCB();

  // Check if we're busy
  if (pn532->state == PN532_STATE_BUSY)
  {
    return PN532_ERROR_BUSY;
  }

  // Flag the stack as busy
  pn532->state = PN532_STATE_BUSY;

  // Reset the app error flag
  pn532->appError = PN532_APPERROR_NONE;

  // Read response from uart
  if (!uartRxBufferReadArray(pbtResponse, pszRxLen))
  {
    pn532->state = PN532_STATE_READY;
    return PN532_ERROR_RESPONSEBUFFEREMPTY;
  }

  // Display the raw response data for debugging if requested
  #ifdef PN532_DEBUGMODE
  PN532_DEBUG("Received (%02d): ", *pszRxLen);
  pn532PrintHex(pbtResponse, *pszRxLen);
  #endif

  // Check preamble
  const byte_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
  if (0 != (memcmp (pbtResponse, pn53x_preamble, 3)))
  {
    #ifdef PN532_DEBUGMODE
    PN532_DEBUG("Frame preamble + start code mismatch%s", CFG_PRINTF_NEWLINE);
    #endif
    pn532->state = PN532_STATE_READY;
    return PN532_ERROR_PREAMBLEMISMATCH;
  }

  // Check the frame type
  if ((0x01 == pbtResponse[3]) && (0xff == pbtResponse[4]))
  {
    // Error frame
    #ifdef PN532_DEBUGMODE
    PN532_DEBUG("Application level error (0x%02x)%s", pbtResponse[5], CFG_PRINTF_NEWLINE);
    #endif
    // Set application error message ID
    pn532->appError = pbtResponse[5];
    pn532->state = PN532_STATE_READY;
    return PN532_ERROR_APPLEVELERROR;
  }
  else if ((0xff == pbtResponse[3]) && (0xff == pbtResponse[4]))
  {
    // Extended frame
    #ifdef PN532_DEBUGMODE
    PN532_DEBUG("Extended frames currently unsupported%s", CFG_PRINTF_NEWLINE);
    #endif
    pn532->state = PN532_STATE_READY;
    return PN532_ERROR_EXTENDEDFRAME;
  }
  else
  {
    // Normal frame
    if (256 != (pbtResponse[3] + pbtResponse[4]))
    {
      // TODO: Retry
      #ifdef PN532_DEBUGMODE
      PN532_DEBUG("Length checksum mismatch%s", CFG_PRINTF_NEWLINE);
      #endif
      pn532->state = PN532_STATE_READY;
      return PN532_ERROR_LENCHECKSUMMISMATCH;
    }
    // size_t szPayloadLen = abtRx[3] - 2;
  }

  pn532->state = PN532_STATE_READY;
  return PN532_ERROR_NONE;
}
コード例 #7
0
pn532_error_t pn532_bus_SendCommand(const byte_t * pbtData, const size_t szData)
{
  pn532_pcb_t *pn532 = pn532GetPCB();

  // Check if we're busy
  if (pn532->state == PN532_STATE_BUSY)
  {
    return PN532_ERROR_BUSY;
  }

  // Flag the stack as busy
  pn532->state = PN532_STATE_BUSY;

  // Every packet must start with "00 00 ff"
  byte_t  abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff };
  size_t szFrame = 0;

  // Build the frame
  pn532_bus_BuildFrame (abtFrame, &szFrame, pbtData, szData);

  // Keep track of the last command that was sent
  pn532->lastCommand = pbtData[0];

  // Output the frame data for debugging if requested
  #ifdef PN532_DEBUGMODE
  PN532_DEBUG("Sending  (%02d): ", szFrame);
  pn532PrintHex(abtFrame, szFrame);
  #endif

  // Send data to the PN532
  uartSend (abtFrame, szFrame);

  // Wait for ACK
  byte_t abtRxBuf[6];
  uart_pcb_t *uart = uartGetPCB();
  delay(10);   // FIXME: How long should we wait for ACK?
  if (uart->rxfifo.len < 6)
  {
    // Unable to read ACK
    #ifdef PN532_DEBUGMODE
    PN532_DEBUG ("Unable to read ACK%s", CFG_PRINTF_NEWLINE);
    #endif
    pn532->state = PN532_STATE_READY;
    return PN532_ERROR_NOACK;
  }

  // Read ACK ... this will also remove it from the buffer
  const byte_t abtAck[6] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
  abtRxBuf[0] = uartRxBufferRead();
  abtRxBuf[1] = uartRxBufferRead();
  abtRxBuf[2] = uartRxBufferRead();
  abtRxBuf[3] = uartRxBufferRead();
  abtRxBuf[4] = uartRxBufferRead();
  abtRxBuf[5] = uartRxBufferRead();

  // Make sure the received ACK matches the prototype
  if (0 != (memcmp (abtRxBuf, abtAck, 6)))
  {
    #ifdef PN532_DEBUGMODE
    PN532_DEBUG ("Invalid ACK: ");
    pn532PrintHex(abtRxBuf, 6);
    PN532_DEBUG("%s", CFG_PRINTF_NEWLINE);
    #endif
    pn532->state = PN532_STATE_READY;
    return PN532_ERROR_INVALIDACK;
  }

  pn532->state = PN532_STATE_READY;
  return PN532_ERROR_NONE;
}