From fe49ccd701b723addbba430721348f8ba7337a12 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Wed, 13 Apr 2011 16:39:58 +0000 Subject: [PATCH] Implement extended frame send/receive for PN532_UART driver. --- libnfc/chips/pn53x.c | 41 +++++++++++++++++++++++++++++++++---- libnfc/chips/pn53x.h | 2 +- libnfc/drivers/pn532_uart.c | 17 ++++++++++++--- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 4e8c6da..ec524d7 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -358,8 +358,14 @@ pn53x_unwrap_frame (const byte_t * pbtFrame, const size_t szFrameBits, byte_t * } } -void -pn53x_build_frame(byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, const size_t szData) +/** + * @brief Build a PN53x frame + * + * @param pbtData payload (bytes array) of the frame, will become PD0, ..., PDn in PN53x frame + * @note The first byte of pbtData is the Command Code (CC) + */ +bool +pn53x_build_frame (byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, const size_t szData) { if (szData <= PN53x_NORMAL_FRAME__DATA_MAX_LEN) { // LEN - Packet length = data length (len) + checksum (1) + end of stream marker (1) @@ -382,10 +388,37 @@ pn53x_build_frame(byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, pbtFrame[szData + 7] = 0x00; (*pszFrame) = szData + PN53x_NORMAL_FRAME__OVERHEAD; + } else if (szData <= PN53x_EXTENDED_FRAME__DATA_MAX_LEN) { + // Extended frame marker + pbtFrame[3] = 0xff; + pbtFrame[4] = 0xff; + // LENm + pbtFrame[5] = (szData + 1) >> 8; + // LENl + pbtFrame[6] = (szData + 1) & 0xff; + // LCS + pbtFrame[7] = 256 - ((pbtFrame[5] + pbtFrame[6]) & 0xff); + // TFI + pbtFrame[8] = 0xD4; + // DATA - Copy the PN53X command into the packet buffer + memcpy (pbtFrame + 9, pbtData, szData); + + // DCS - Calculate data payload checksum + byte_t btDCS = (256 - 0xD4); + for (size_t szPos = 0; szPos < szData; szPos++) { + btDCS -= pbtData[szPos]; + } + pbtFrame[9 + szData] = btDCS; + + // 0x00 - End of stream marker + pbtFrame[szData + 10] = 0x00; + + (*pszFrame) = szData + PN53x_EXTENDED_FRAME__OVERHEAD; } else { - // FIXME: Build extended frame - abort(); + ERR ("We can't send more than %d bytes in a raw (requested: %zd)", PN53x_EXTENDED_FRAME__DATA_MAX_LEN, szData); + return false; } + return true; } bool diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index 843927e..fbc35d0 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -329,6 +329,6 @@ bool pn53x_TgInitAsTarget (nfc_device_t * pnd, pn53x_target_mode_t ptm, // Misc bool pn53x_check_ack_frame (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen); bool pn53x_check_error_frame (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen); -void pn53x_build_frame(byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, const size_t szData); +bool pn53x_build_frame (byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, const size_t szData); #endif // __NFC_CHIPS_PN53X_H__ diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index a43ed93..190e885 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -202,7 +202,10 @@ pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData CHIP_DATA (pnd)->ui8LastCommand = pbtData[0]; size_t szFrame = 0; - pn53x_build_frame (abtFrame, &szFrame, pbtData, szData); + if (!pn53x_build_frame (abtFrame, &szFrame, pbtData, szData)) { + pnd->iLastError = DEINVAL; + return false; + } int res = uart_send (DRIVER_DATA(pnd)->port, abtFrame, szFrame); if (res != 0) { @@ -271,8 +274,16 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen return -1; } else if ((0xff == abtRxBuf[3]) && (0xff == abtRxBuf[4])) { // Extended frame - // FIXME: Code this - abort (); + pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 3, 0); + + // (abtRxBuf[0] << 8) + abtRxBuf[1] (LEN) include TFI + (CC+1) + len = (abtRxBuf[0] << 8) + abtRxBuf[1] - 2; + if (((abtRxBuf[0] + abtRxBuf[1] + abtRxBuf[2]) % 256) != 0) { + // TODO: Retry + ERR ("%s", "Length checksum mismatch"); + pnd->iLastError = DEIO; + return -1; + } } else { // Normal frame if (256 != (abtRxBuf[3] + abtRxBuf[4])) {