pn532_error_t pn532_bus_Wakeup(void) { pn532_error_t error = PN532_ERROR_NONE; byte_t abtWakeUp[] = { 0x55,0x55,0x00,0x00,0x00,0x00,0x00,0xff,0x03,0xfd,0xd4,0x14,0x01,0x17,0x00,0x00,0xff,0x03,0xfd,0xd4,0x14,0x01,0x17,0x00 }; pn532_pcb_t *pn532 = pn532GetPCB(); #ifdef PN532_DEBUGMODE PN532_DEBUG("Sending Wakeup Sequence%s", CFG_PRINTF_NEWLINE); #endif error = pn532_bus_i2c_WriteData(abtWakeUp,sizeof(abtWakeUp)); if (error) { #ifdef PN532_DEBUGMODE PN532_DEBUG("Wakeup Failed (Error: %d)%s", error, CFG_PRINTF_NEWLINE); #endif return error; } systickDelay(100); // Wait for the IRQ/Ready flag to indicate a response is ready if (!(pn532_bus_i2c_WaitForReady(PN532_I2C_TIMEOUT))) { #ifdef PN532_DEBUGMODE PN532_DEBUG ("Timed out waiting for IRQ/Ready%s", CFG_PRINTF_NEWLINE); #endif error = PN532_ERROR_READYSTATUSTIMEOUT; } // Read and discard the ACK frame I2CWriteLength = 0; I2CReadLength = 7; // ACK + Ready bit = 7 I2CMasterBuffer[0] = PN532_I2C_ADDRESS | PN532_I2C_READBIT; i2cEngine(); systickDelay(1); // Wait for the IRQ/Ready flag to indicate a response is ready if (!(pn532_bus_i2c_WaitForReady(PN532_I2C_TIMEOUT))) { error = PN532_ERROR_READYSTATUSTIMEOUT; } #ifdef PN532_DEBUGMODE PN532_DEBUG("Wakeup Complete%s", CFG_PRINTF_NEWLINE); #endif pn532->state = PN532_STATE_READY; return error; }
pn532_error_t pn532_bus_Wakeup(void) { size_t szLen; byte_t abtWakeUp[] = { 0x55,0x55,0x00,0x00,0x00,0x00,0x00,0xff,0x03,0xfd,0xd4,0x14,0x01,0x17,0x00,0x00,0xff,0x03,0xfd,0xd4,0x14,0x01,0x17,0x00 }; pn532_pcb_t *pn532 = pn532GetPCB(); #ifdef PN532_DEBUGMODE PN532_DEBUG("Sending Wakeup Sequence%s", CFG_PRINTF_NEWLINE); #endif uartSend(abtWakeUp,sizeof(abtWakeUp)); delay(100); byte_t response[32]; pn532_bus_ReadResponse(response, &szLen); // Todo: Check for error ... currently throws a checksum error // that isn't really an error pn532->state = PN532_STATE_READY; return PN532_ERROR_NONE; }
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; }
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; }
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; }
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; }