From 9984e1bdcb86951554a52e41ef5dc1cd68636f2a Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Mon, 26 Jul 2010 12:41:46 +0000 Subject: [PATCH 01/32] Start of work on error handling. --- examples/mifare.c | 2 +- examples/mifare.h | 2 +- include/nfc/nfc-types.h | 2 + include/nfc/nfc.h | 22 +++++------ libnfc/chips/pn53x.c | 86 ++++++++++++++++++++++++++++++++++++++--- libnfc/chips/pn53x.h | 4 +- libnfc/nfc.c | 22 +++++------ 7 files changed, 109 insertions(+), 31 deletions(-) diff --git a/examples/mifare.c b/examples/mifare.c index 1deb523..d272e62 100644 --- a/examples/mifare.c +++ b/examples/mifare.c @@ -19,7 +19,7 @@ extern const byte_t pncmd_initiator_exchange_data [265]; * After a successful authentication it will be possible to execute other commands (e.g. Read/Write). * The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process. */ -bool nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp) +bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; diff --git a/examples/mifare.h b/examples/mifare.h index 886ebc2..1b98b22 100644 --- a/examples/mifare.h +++ b/examples/mifare.h @@ -63,7 +63,7 @@ typedef union { // Reset struct alignment to default #pragma pack() -bool nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp); +bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp); // Compiler directive, set struct alignment to 1 byte_t for compatibility #pragma pack(1) diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 61c02c9..51d07db 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -69,6 +69,8 @@ typedef struct { bool bPar; /** The last tx bits setting, we need to reset this if it does not apply anymore */ uint8_t ui8TxBits; +/** The last error encountered by the device */ + int iErrorCode; } nfc_device_t; diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 3ac66be..6756abc 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -62,21 +62,21 @@ NFC_EXPORT bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, /* NFC initiator: act as "reader" */ NFC_EXPORT bool nfc_initiator_init(const nfc_device_t* pnd); NFC_EXPORT bool nfc_initiator_select_passive_target(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pti); -NFC_EXPORT bool nfc_initiator_select_dep_target(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtPidData, const size_t szPidDataLen, const byte_t* pbtNFCID3i, const size_t szNFCID3iDataLen, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pti); -NFC_EXPORT bool nfc_initiator_deselect_target(const nfc_device_t* pnd); +NFC_EXPORT bool nfc_initiator_select_dep_target(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtPidData, const size_t szPidDataLen, const byte_t* pbtNFCID3i, const size_t szNFCID3iDataLen, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pti); +NFC_EXPORT bool nfc_initiator_deselect_target(nfc_device_t* pnd); NFC_EXPORT bool nfc_initiator_poll_targets(const nfc_device_t* pnd, const nfc_target_type_t* pnttTargetTypes, const size_t szTargetTypes, const byte_t btPollNr, const byte_t btPeriod, nfc_target_t* pntTargets, size_t* pszTargetFound); -NFC_EXPORT bool nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); -NFC_EXPORT bool nfc_initiator_transceive_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); -NFC_EXPORT bool nfc_initiator_transceive_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); +NFC_EXPORT bool nfc_initiator_transceive_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); +NFC_EXPORT bool nfc_initiator_transceive_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); +NFC_EXPORT bool nfc_initiator_transceive_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); /* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */ NFC_EXPORT bool nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits); -NFC_EXPORT bool nfc_target_receive_bits(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); -NFC_EXPORT bool nfc_target_receive_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); -NFC_EXPORT bool nfc_target_receive_dep_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); -NFC_EXPORT bool nfc_target_send_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar); -NFC_EXPORT bool nfc_target_send_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); -NFC_EXPORT bool nfc_target_send_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); +NFC_EXPORT bool nfc_target_receive_bits(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); +NFC_EXPORT bool nfc_target_receive_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); +NFC_EXPORT bool nfc_target_receive_dep_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); +NFC_EXPORT bool nfc_target_send_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar); +NFC_EXPORT bool nfc_target_send_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); +NFC_EXPORT bool nfc_target_send_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); /* Special data accessors */ NFC_EXPORT const char* nfc_device_name(nfc_device_t* pnd); diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 2881327..fafc605 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -60,8 +60,10 @@ const byte_t pncmd_target_receive [ 2] = { 0xD4,0x88 }; const byte_t pncmd_target_send [264] = { 0xD4,0x90 }; const byte_t pncmd_target_get_status [ 2] = { 0xD4,0x8A }; +const char * +pn53x_err2string (int iError, char const **ppcDescription); -bool pn53x_transceive(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) +bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; @@ -75,14 +77,24 @@ bool pn53x_transceive(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t *pszRxLen = MAX_FRAME_LEN; // Call the tranceive callback function of the current device + printf ("Entering transceive (bsin = %lu, bsout = %lu)\n", szTxLen, *pszRxLen); if (!pnd->pdc->transceive(pnd->nds,pbtTx,szTxLen,pbtRx,pszRxLen)) return false; + printf ("Leaving transceive (bsin = %lu, bsout = %lu)\n", szTxLen, *pszRxLen); + + pnd->iErrorCode = pbtRx[0] & 0x2f; // Make sure there was no failure reported by the PN53X chip (0x00 == OK) - // FIXME (0x00 == OK) is not always true... - if (pbtRx[0] != 0) return false; + if (pnd->iErrorCode != 0) { + const char *s, *l; + + s = pn53x_err2string (pnd->iErrorCode, &l); + if (s) { + printf (" s = %s\n l = %s\n", s, l); + } + } // Succesful transmission - return true; + return (0 == pnd->iErrorCode); } byte_t pn53x_get_reg(const nfc_device_t* pnd, uint16_t ui16Reg) @@ -302,7 +314,7 @@ pn53x_InListPassiveTarget(const nfc_device_t* pnd, } bool -pn53x_InDeselect(const nfc_device_t* pnd, const uint8_t ui8Target) +pn53x_InDeselect(nfc_device_t* pnd, const uint8_t ui8Target) { byte_t abtCmd[sizeof(pncmd_initiator_deselect)]; memcpy(abtCmd,pncmd_initiator_deselect,sizeof(pncmd_initiator_deselect)); @@ -310,3 +322,67 @@ pn53x_InDeselect(const nfc_device_t* pnd, const uint8_t ui8Target) return(pn53x_transceive(pnd,abtCmd,sizeof(abtCmd),NULL,NULL)); } + +struct sErrorMessage { + int iError; + const char *pcErrorMsg; + const char *pcErrorDescription; +} sErrorMessages[] = { + { 0x00, "success", "The request was successful." }, + { 0x01, "timout", "Time Out, the target has not answered." }, + { 0x02, "crc error", "A CRC error has been detected by the CIU." }, + { 0x03, "parity error", "A Parity error has been detected by the CIU." }, + { 0x04, "wrong bit count", "During an anti-collision/select operation (ISO/IEC14443-3 Type A and ISO/" + "IEC18092 106 kbps passive mode), an erroneous Bit Count has been detected." }, + { 0x05, "framing error", "Framing error during Mifare operation." }, + { 0x06, "bit-collision", "An abnormal bit-collision has been detected during bit wise anti-collision" + " at 106 kbps." }, + { 0x07, "buffer too small", "Communication buffer size insufficient." }, + { 0x09, "buffer overflow", "RF Buffer overflow has been detected by the CIU (bit BufferOvfl of the register" + " CIU_Error)." }, + { 0x0a, "timout", "In active communication mode, the RF field has not been switched on in time by" + " the counterpart (as defined in NFCIP-1 standard)." }, + { 0x0b, "protocol error", "RF Protocol error." }, + { 0x0d, "temerature", "The internal temperature sensor has detected overheating, and therefore has" + " automatically switched off the antenna drivers." }, + { 0x0e, "overflow", "Internal buffer overflow." }, + { 0x10, "invalid parameter", "Invalid parameter."}, + /* DEP Errors */ + { 0x12, "unknown command", "The PN532 configured in target mode does not support the command received from" + " the initiator." }, + { 0x13, "invalid parameter", "The data format does not match to the specification." }, + /* MIFARE */ + { 0x14, "authentication", "Authentication error." }, + { 0x23, "check byte", "ISO/IEC14443-3: UID Check byte is wrong." }, + { 0x25, "invalid state", "The system is in a state which does not allow the operation." }, + { 0x26, "operation not allowed", "Operation not allowed in this configuration (host controller interface)." }, + { 0x27, "command not acceptable", "This command is not acceptable due to the current context of the PN532" + " (Initiator vs. Target, unknown target number, Target not in the good state," + " ...)" }, + { 0x29, "target released", "The PN532 configured as target has been released by its initiator." }, + { 0x2a, "card id mismatch", "PN532 and ISO/IEC14443-3B only: the ID of the card does not match, meaning " + "that the expected card has been exchanged with another one." }, + { 0x2B, "card discarded", "PN532 and ISO/IEC14443-3B only: the card previously activated has disappeared." }, + { 0x2C, "NFCID3 mismatch", "Mismatch between the NFCID3 initiator and the NFCID3 target in DEP 212/424 kbps" + " passive." }, + { 0x2D, "over current", "An over-current event has been detected." }, + { 0x2E, "NAD missing", "NAD missing in DEP frame." }, +}; + +const char * +pn53x_err2string (int iError, char const **ppcDescription) +{ + const char *pcRes = NULL; + + for (size_t i=0; i < (sizeof (sErrorMessages) / sizeof (struct sErrorMessage)); i++) { + if (sErrorMessages[i].iError == iError) { + pcRes = sErrorMessages[i].pcErrorMsg; + if (ppcDescription) + *ppcDescription = sErrorMessages[i].pcErrorDescription; + break; + } + } + + return pcRes; +} + diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index cc6ce59..a371d22 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -69,7 +69,7 @@ #define RFCI_ANALOG_TYPE_B 0x0C // 3 #define RFCI_ANALOG_TYPE_14443_4 0x0D // 9 -bool pn53x_transceive(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); +bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); byte_t pn53x_get_reg(const nfc_device_t* pnd, uint16_t ui16Reg); bool pn53x_set_reg(const nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value); bool pn53x_set_parameters(const nfc_device_t* pnd, uint8_t ui8Value); @@ -79,7 +79,7 @@ bool pn53x_unwrap_frame(const byte_t* pbtFrame, const size_t szFrameBits, byte_t bool pn53x_decode_target_data(const byte_t* pbtRawData, size_t szDataLen, nfc_chip_t nc, nfc_target_type_t ntt, nfc_target_info_t* pnti); bool pn53x_InListPassiveTarget(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t szMaxTargets, const byte_t* pbtInitiatorData, const size_t szInitiatorDataLen, byte_t* pbtTargetsData, size_t* pszTargetsData); -bool pn53x_InDeselect(const nfc_device_t* pnd, const uint8_t ui8Target); +bool pn53x_InDeselect(nfc_device_t* pnd, const uint8_t ui8Target); #endif // __NFC_CHIPS_PN53X_H__ diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 7af985d..aa139be 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -354,7 +354,7 @@ bool nfc_initiator_init(const nfc_device_t* pnd) * The NFC device will try to find the available target. The standards (ISO18092 and ECMA-340) describe the modulation that can be used for reader to passive communications. * @note nfc_dep_info_t will be returned when the target was acquired successfully. */ -bool nfc_initiator_select_dep_target(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtPidData, const size_t szPidDataLen, const byte_t* pbtNFCID3i, const size_t szNFCID3iDataLen, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pnti) +bool nfc_initiator_select_dep_target(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtPidData, const size_t szPidDataLen, const byte_t* pbtNFCID3i, const size_t szNFCID3iDataLen, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pnti) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; @@ -548,7 +548,7 @@ nfc_initiator_select_passive_target(const nfc_device_t* pnd, * * After selecting and communicating with a passive tag, this function could be used to deactivate and release the tag. This is very useful when there are multiple tags available in the field. It is possible to use the nfc_initiator_select_passive_target() function to select the first available tag, test it for the available features and support, deselect it and skip to the next tag until the correct tag is found. */ -bool nfc_initiator_deselect_target(const nfc_device_t* pnd) +bool nfc_initiator_deselect_target(nfc_device_t* pnd) { return (pn53x_InDeselect(pnd, 0)); // 0 mean deselect all selected targets } @@ -634,7 +634,7 @@ nfc_initiator_poll_targets(const nfc_device_t* pnd, * * The NFC reader will transmit low-level messages where only the modulation is handled by the PN53X chip. Construction of the frame (data, CRC and parity) is completely done by libnfc. This can be very useful for testing purposes. Some protocols (e.g. MIFARE Classic) require to violate the ISO14443-A standard by sending incorrect parity and CRC bytes. Using this feature you are able to simulate these frames. */ -bool nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) +bool nfc_initiator_transceive_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; @@ -698,7 +698,7 @@ bool nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, * * The reader will transmit the supplied (data) bytes in pbtTx to the target (tag). It waits for the response and stores the received bytes in the pbtRx byte array. The difference between this function and nfc_initiator_transceive_bytes is that here pbtTx and pbtRx contain *only* the data sent and received and not any additional commands, that is all handled internally by the PN53X. */ -bool nfc_initiator_transceive_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) +bool nfc_initiator_transceive_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; @@ -736,7 +736,7 @@ bool nfc_initiator_transceive_dep_bytes(const nfc_device_t* pnd, const byte_t* p * The reader will transmit the supplied bytes in pbtTx to the target (tag). It waits for the response and stores the received bytes in the pbtRx byte array. The parity bits are handled by the PN53X chip. The CRC can be generated automatically or handled manually. Using this function, frames can be communicated very fast via the NFC reader to the tag. Tests show that on average this way of communicating is much faster than using the regular driver/middle-ware (often supplied by manufacturers). * @warning The configuration option NDO_HANDLE_PARITY must be set to true (the default value). */ -bool nfc_initiator_transceive_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) +bool nfc_initiator_transceive_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; @@ -833,7 +833,7 @@ bool nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits) * * This function makes it possible to receive (raw) bit-frames. It returns all the messages that are stored in the FIFO buffer of the PN53X chip. It does not require to send any frame and thereby could be used to snoop frames that are transmitted by a nearby reader. Check out the NDO_ACCEPT_MULTIPLE_FRAMES configuration option to avoid losing transmitted frames. */ -bool nfc_target_receive_bits(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) +bool nfc_target_receive_bits(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; @@ -871,7 +871,7 @@ bool nfc_target_receive_bits(const nfc_device_t* pnd, byte_t* pbtRx, size_t* psz * * The main receive function that returns the received data from a nearby reader. The difference between this function and nfc_target_receive_bytes is that here pbtRx contains *only* the data received and not any additional commands, that is all handled internally by the PN53X. */ -bool nfc_target_receive_dep_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) +bool nfc_target_receive_dep_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; @@ -895,7 +895,7 @@ bool nfc_target_receive_dep_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t * * The main receive function that returns the received frames from a nearby reader. */ -bool nfc_target_receive_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) +bool nfc_target_receive_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; @@ -919,7 +919,7 @@ bool nfc_target_receive_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* ps * * This function can be used to transmit (raw) bit-frames to the reader. */ -bool nfc_target_send_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar) +bool nfc_target_send_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar) { size_t szFrameBits = 0; size_t szFrameBytes = 0; @@ -962,7 +962,7 @@ bool nfc_target_send_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const si * * To communicate byte frames and APDU responses to the reader, this function could be used. */ -bool nfc_target_send_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) +bool nfc_target_send_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) { byte_t abtCmd[sizeof(pncmd_target_send)]; memcpy(abtCmd,pncmd_target_send,sizeof(pncmd_target_send)); @@ -986,7 +986,7 @@ bool nfc_target_send_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const s * * To communicate data to the reader, this function could be used. The difference between this function and nfc_target_send_bytes is that here pbtTx contains *only* the data sent and not any additional commands, that is all handled internally by the PN53X. */ -bool nfc_target_send_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) +bool nfc_target_send_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) { byte_t abtCmd[sizeof(pncmd_target_set_data)]; memcpy(abtCmd,pncmd_target_set_data,sizeof(pncmd_target_set_data)); From d63157a41d46f9835262dc38bd4bb9cb1affcb30 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Tue, 27 Jul 2010 09:29:54 +0000 Subject: [PATCH 02/32] Fix mask to extract "Error Code" from status byte. --- libnfc/chips/pn53x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index fafc605..4e53fd0 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -81,7 +81,7 @@ bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxL if (!pnd->pdc->transceive(pnd->nds,pbtTx,szTxLen,pbtRx,pszRxLen)) return false; printf ("Leaving transceive (bsin = %lu, bsout = %lu)\n", szTxLen, *pszRxLen); - pnd->iErrorCode = pbtRx[0] & 0x2f; + pnd->iErrorCode = pbtRx[0] & 0x3f; // Make sure there was no failure reported by the PN53X chip (0x00 == OK) if (pnd->iErrorCode != 0) { From 740b5b430d7bcfab92ddb605b85ea2e0a776fdf8 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Thu, 29 Jul 2010 10:53:14 +0000 Subject: [PATCH 03/32] libnfc-error-handling: Remove boring debug stuff. --- libnfc/chips/pn53x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 4e53fd0..d7b913e 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -77,9 +77,7 @@ bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxL *pszRxLen = MAX_FRAME_LEN; // Call the tranceive callback function of the current device - printf ("Entering transceive (bsin = %lu, bsout = %lu)\n", szTxLen, *pszRxLen); if (!pnd->pdc->transceive(pnd->nds,pbtTx,szTxLen,pbtRx,pszRxLen)) return false; - printf ("Leaving transceive (bsin = %lu, bsout = %lu)\n", szTxLen, *pszRxLen); pnd->iErrorCode = pbtRx[0] & 0x3f; From daa178b18f7a0d1dfae4b3cd7484e77045c72813 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Thu, 29 Jul 2010 14:16:11 +0000 Subject: [PATCH 04/32] Enhance error handeling. - New API functions: nfc_strerror(), nfc_strerror_r() and nfc_perror(); - Drivers now have a reference to chips callback methods; - Rename -pn53x_err2string to pn53x_strerror and add it to pn53x_callbacks_list. --- ChangeLog | 8 ++++ include/nfc/nfc-types.h | 11 +++++ include/nfc/nfc.h | 5 +++ libnfc/chips/pn53x.c | 89 +++++++++++++++-------------------------- libnfc/chips/pn53x.h | 6 +++ libnfc/drivers.h | 14 ++++--- libnfc/nfc.c | 26 ++++++++++++ 7 files changed, 96 insertions(+), 63 deletions(-) diff --git a/ChangeLog b/ChangeLog index ff1a91c..fab2442 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +??? +---- + +Changes: + - API: New nfc_perror(), nfc_strerror() and nfc_strerror_r() functions. + + + Apr 6, 2010 - 1.3.4 -------------------- diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 51d07db..2b0c4a8 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -93,6 +93,15 @@ typedef struct { uint32_t uiBusIndex; } nfc_device_desc_t; +/** + * @struct chip_callbacks + * @brief Functions for chip specific functions. + */ +struct chip_callbacks { + /** Error lookup */ + const char* (*strerror) (const nfc_device_t *pnd); +}; + /** * @struct driver_callbacks * @brief Generic structure to handle NFC device functions. @@ -100,6 +109,8 @@ typedef struct { struct driver_callbacks { /** Driver name */ const char* acDriver; + /** Chip specific callback functions */ + const struct chip_callbacks *pcc; /** Pick devices callback */ nfc_device_desc_t *(*pick_device)(void); /** List devices callback */ diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 6756abc..b1df6cc 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -78,6 +78,11 @@ NFC_EXPORT bool nfc_target_send_bits(nfc_device_t* pnd, const byte_t* pbtTx, con NFC_EXPORT bool nfc_target_send_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); NFC_EXPORT bool nfc_target_send_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); +/* Error reporting */ +NFC_EXPORT const char *nfc_strerror (const nfc_device_t *pnd); +NFC_EXPORT int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen); +NFC_EXPORT void nfc_perror (const nfc_device_t *pnd, const char *pcString); + /* Special data accessors */ NFC_EXPORT const char* nfc_device_name(nfc_device_t* pnd); diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index d7b913e..8e7cf92 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -60,9 +60,6 @@ const byte_t pncmd_target_receive [ 2] = { 0xD4,0x88 }; const byte_t pncmd_target_send [264] = { 0xD4,0x90 }; const byte_t pncmd_target_get_status [ 2] = { 0xD4,0x8A }; -const char * -pn53x_err2string (int iError, char const **ppcDescription); - bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; @@ -81,16 +78,6 @@ bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxL pnd->iErrorCode = pbtRx[0] & 0x3f; - // Make sure there was no failure reported by the PN53X chip (0x00 == OK) - if (pnd->iErrorCode != 0) { - const char *s, *l; - - s = pn53x_err2string (pnd->iErrorCode, &l); - if (s) { - printf (" s = %s\n l = %s\n", s, l); - } - } - // Succesful transmission return (0 == pnd->iErrorCode); } @@ -322,61 +309,49 @@ pn53x_InDeselect(nfc_device_t* pnd, const uint8_t ui8Target) } struct sErrorMessage { - int iError; + int iErrorCode; const char *pcErrorMsg; - const char *pcErrorDescription; } sErrorMessages[] = { - { 0x00, "success", "The request was successful." }, - { 0x01, "timout", "Time Out, the target has not answered." }, - { 0x02, "crc error", "A CRC error has been detected by the CIU." }, - { 0x03, "parity error", "A Parity error has been detected by the CIU." }, - { 0x04, "wrong bit count", "During an anti-collision/select operation (ISO/IEC14443-3 Type A and ISO/" - "IEC18092 106 kbps passive mode), an erroneous Bit Count has been detected." }, - { 0x05, "framing error", "Framing error during Mifare operation." }, - { 0x06, "bit-collision", "An abnormal bit-collision has been detected during bit wise anti-collision" - " at 106 kbps." }, - { 0x07, "buffer too small", "Communication buffer size insufficient." }, - { 0x09, "buffer overflow", "RF Buffer overflow has been detected by the CIU (bit BufferOvfl of the register" - " CIU_Error)." }, - { 0x0a, "timout", "In active communication mode, the RF field has not been switched on in time by" - " the counterpart (as defined in NFCIP-1 standard)." }, - { 0x0b, "protocol error", "RF Protocol error." }, - { 0x0d, "temerature", "The internal temperature sensor has detected overheating, and therefore has" - " automatically switched off the antenna drivers." }, - { 0x0e, "overflow", "Internal buffer overflow." }, - { 0x10, "invalid parameter", "Invalid parameter."}, + { 0x00, "Success" }, + { 0x01, "Timeout" }, + { 0x02, "CRC Error" }, + { 0x03, "Parity Error" }, + { 0x04, "Erroneous Bit Count" }, + { 0x05, "Framing Error" }, + { 0x06, "Bit-collision" }, + { 0x07, "Buffer Too Small" }, + { 0x09, "Buffer Overflow" }, + { 0x0a, "Timeout" }, + { 0x0b, "Protocol Error" }, + { 0x0d, "Overheating" }, + { 0x0e, "Internal Buffer overflow." }, + { 0x10, "Invalid Parameter" }, /* DEP Errors */ - { 0x12, "unknown command", "The PN532 configured in target mode does not support the command received from" - " the initiator." }, - { 0x13, "invalid parameter", "The data format does not match to the specification." }, + { 0x12, "Unknown DEP Command" }, + { 0x13, "Invalid Parameter" }, /* MIFARE */ - { 0x14, "authentication", "Authentication error." }, - { 0x23, "check byte", "ISO/IEC14443-3: UID Check byte is wrong." }, - { 0x25, "invalid state", "The system is in a state which does not allow the operation." }, - { 0x26, "operation not allowed", "Operation not allowed in this configuration (host controller interface)." }, - { 0x27, "command not acceptable", "This command is not acceptable due to the current context of the PN532" - " (Initiator vs. Target, unknown target number, Target not in the good state," - " ...)" }, - { 0x29, "target released", "The PN532 configured as target has been released by its initiator." }, - { 0x2a, "card id mismatch", "PN532 and ISO/IEC14443-3B only: the ID of the card does not match, meaning " - "that the expected card has been exchanged with another one." }, - { 0x2B, "card discarded", "PN532 and ISO/IEC14443-3B only: the card previously activated has disappeared." }, - { 0x2C, "NFCID3 mismatch", "Mismatch between the NFCID3 initiator and the NFCID3 target in DEP 212/424 kbps" - " passive." }, - { 0x2D, "over current", "An over-current event has been detected." }, - { 0x2E, "NAD missing", "NAD missing in DEP frame." }, + { 0x14, "Authentication Error" }, + /* */ + { 0x23, "Wrong ISO/IEC14443-3 Check Byte" }, + { 0x25, "Invalid State" }, + { 0x26, "Operation Not Allowed" }, + { 0x27, "Command Not Acceptable" }, + { 0x29, "Target Released" }, + { 0x2a, "Card ID Mismatch" }, + { 0x2B, "Card Discarded" }, + { 0x2C, "NFCID3 Mismatch" }, + { 0x2D, "Over Current" }, + { 0x2E, "NAD Missing in DEP Frame" } }; const char * -pn53x_err2string (int iError, char const **ppcDescription) +pn53x_strerror (const nfc_device_t *pnd) { - const char *pcRes = NULL; + const char *pcRes = "Unknown error"; for (size_t i=0; i < (sizeof (sErrorMessages) / sizeof (struct sErrorMessage)); i++) { - if (sErrorMessages[i].iError == iError) { + if (sErrorMessages[i].iErrorCode == pnd->iErrorCode) { pcRes = sErrorMessages[i].pcErrorMsg; - if (ppcDescription) - *ppcDescription = sErrorMessages[i].pcErrorDescription; break; } } diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index a371d22..efef7d7 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -81,5 +81,11 @@ bool pn53x_decode_target_data(const byte_t* pbtRawData, size_t szDataLen, nfc_ch bool pn53x_InListPassiveTarget(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t szMaxTargets, const byte_t* pbtInitiatorData, const size_t szInitiatorDataLen, byte_t* pbtTargetsData, size_t* pszTargetsData); bool pn53x_InDeselect(nfc_device_t* pnd, const uint8_t ui8Target); +const char *pn53x_strerror (const nfc_device_t *pnd); + +static const struct chip_callbacks pn53x_callbacks_list = { + pn53x_strerror +}; + #endif // __NFC_CHIPS_PN53X_H__ diff --git a/libnfc/drivers.h b/libnfc/drivers.h index b79228d..399b53f 100644 --- a/libnfc/drivers.h +++ b/libnfc/drivers.h @@ -27,6 +27,8 @@ #include +#include "chips/pn53x.h" + #if defined (DRIVER_ACR122_ENABLED) #include "drivers/acr122.h" #endif /* DRIVER_ACR122_ENABLED */ @@ -55,21 +57,21 @@ #define MAX_FRAME_LEN 264 static const struct driver_callbacks drivers_callbacks_list[] = { -// Driver Name Pick Device List Devices Connect Transceive Disconnect +// Driver Name Chip callbacks Pick Device List Devices Connect Transceive Disconnect #if defined (DRIVER_ACR122_ENABLED) - { ACR122_DRIVER_NAME, acr122_pick_device, acr122_list_devices, acr122_connect, acr122_transceive, acr122_disconnect }, + { ACR122_DRIVER_NAME, &pn53x_callbacks_list, acr122_pick_device, acr122_list_devices, acr122_connect, acr122_transceive, acr122_disconnect }, #endif /* DRIVER_ACR122_ENABLED */ #if defined (DRIVER_PN531_USB_ENABLED) - { PN531_USB_DRIVER_NAME, pn531_usb_pick_device, pn531_usb_list_devices, pn531_usb_connect, pn53x_usb_transceive, pn53x_usb_disconnect }, + { PN531_USB_DRIVER_NAME, &pn53x_callbacks_list, pn531_usb_pick_device, pn531_usb_list_devices, pn531_usb_connect, pn53x_usb_transceive, pn53x_usb_disconnect }, #endif /* DRIVER_PN531_USB_ENABLED */ #if defined (DRIVER_PN533_USB_ENABLED) - { PN533_USB_DRIVER_NAME, pn533_usb_pick_device, pn533_usb_list_devices, pn533_usb_connect, pn53x_usb_transceive, pn53x_usb_disconnect }, + { PN533_USB_DRIVER_NAME, &pn53x_callbacks_list, pn533_usb_pick_device, pn533_usb_list_devices, pn533_usb_connect, pn53x_usb_transceive, pn53x_usb_disconnect }, #endif /* DRIVER_PN533_USB_ENABLED */ #if defined (DRIVER_ARYGON_ENABLED) - { ARYGON_DRIVER_NAME, arygon_pick_device, arygon_list_devices, arygon_connect, arygon_transceive, arygon_disconnect }, + { ARYGON_DRIVER_NAME, &pn53x_callbacks_list, arygon_pick_device, arygon_list_devices, arygon_connect, arygon_transceive, arygon_disconnect }, #endif /* DRIVER_ARYGON_ENABLED */ #if defined (DRIVER_PN532_UART_ENABLED) - { PN532_UART_DRIVER_NAME, pn532_uart_pick_device, pn532_uart_list_devices, pn532_uart_connect, pn532_uart_transceive, pn532_uart_disconnect }, + { PN532_UART_DRIVER_NAME, &pn53x_callbacks_list, pn532_uart_pick_device, pn532_uart_list_devices, pn532_uart_connect, pn532_uart_transceive, pn532_uart_disconnect }, #endif /* DRIVER_PN532_UART_ENABLED */ }; diff --git a/libnfc/nfc.c b/libnfc/nfc.c index aa139be..460a60c 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1004,6 +1004,32 @@ bool nfc_target_send_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const siz return true; } +/** + * @brief Return the PCD error string + * @return Returns a string + */ +const char *nfc_strerror (const nfc_device_t *pnd) +{ + return pnd->pdc->pcc->strerror (pnd); +} + +/** + * @brief Renders the PCD error in pcStrErrBuf for a maximum size of szBufLen caracters + * @return Returns 0 upon success + */ +int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen) +{ + return (snprintf (pcStrErrBuf, szBufLen, "%s", nfc_strerror (pnd)) < 0) ? -1 : 0; +} + +/** + * @brief Display the PCD error a-la perror + */ +void nfc_perror (const nfc_device_t *pnd, const char *pcString) +{ + fprintf (stderr, "%s: %s\n", pcString, nfc_strerror (pnd)); +} + /* Special data accessors */ /** From 705e037b129acc69d446a59b7d97abdcd2a3261c Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Sat, 31 Jul 2010 09:19:22 +0000 Subject: [PATCH 05/32] Only report status error for commands that provide it in pn53x_transceive(). This is the first step for improving abstraction in libnfc. --- libnfc/chips/pn53x.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index b4acff3..cfa785e 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -76,9 +76,29 @@ bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxL // Call the tranceive callback function of the current device if (!pnd->pdc->transceive(pnd->nds,pbtTx,szTxLen,pbtRx,pszRxLen)) return false; - pnd->iErrorCode = pbtRx[0] & 0x3f; + switch (pbtTx[1]) { + case 0x16: + case 0x40: + case 0x42: + case 0x44: + case 0x46: + case 0x4e: + case 0x50: + case 0x52: + case 0x54: + case 0x56: + case 0x86: + case 0x88: + case 0x8e: + case 0x90: + case 0x93: + case 0x94: + pnd->iErrorCode = pbtRx[0] & 0x3f; + break; + default: + pnd->iErrorCode = 0; + } - // Succesful transmission return (0 == pnd->iErrorCode); } From fb6d9d2d208800e3c0b12d801ee26f9986039f0d Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Sat, 31 Jul 2010 09:40:29 +0000 Subject: [PATCH 06/32] Yes we can... remove all those pnd->pdc->transceive() from nfc.c. Within the ongoing effort to improve the NFC devices abstraction, and now that pn53x_transceive() does not fail when it reads a response that has no status-code, do not call directly pnd->pdc->transceive() from nfc.c. In a mid-term future this will be changed again, and calling pn53x_transceive() from nfc.c will be forbiden, in favor of colling some pnd->transceive() function, but that's another part of the story. Of course, it changes the API one more and it's not going to be the last time in this branch. --- include/nfc/nfc.h | 4 ++-- libnfc/nfc.c | 20 ++++++++------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index bc6250e..6f00b01 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -63,7 +63,7 @@ NFC_EXPORT bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, NFC_EXPORT bool nfc_initiator_init(const nfc_device_t* pnd); NFC_EXPORT bool nfc_initiator_select_passive_target(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pti); NFC_EXPORT bool nfc_initiator_list_passive_targets(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, nfc_target_info_t anti[], const size_t szTargets, size_t *pszTargetFound ); -NFC_EXPORT bool nfc_initiator_poll_targets(const nfc_device_t* pnd, const nfc_target_type_t* pnttTargetTypes, const size_t szTargetTypes, const byte_t btPollNr, const byte_t btPeriod, nfc_target_t* pntTargets, size_t* pszTargetFound); +NFC_EXPORT bool nfc_initiator_poll_targets(nfc_device_t* pnd, const nfc_target_type_t* pnttTargetTypes, const size_t szTargetTypes, const byte_t btPollNr, const byte_t btPeriod, nfc_target_t* pntTargets, size_t* pszTargetFound); NFC_EXPORT bool nfc_initiator_select_dep_target(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtPidData, const size_t szPidDataLen, const byte_t* pbtNFCID3i, const size_t szNFCID3iDataLen, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pti); NFC_EXPORT bool nfc_initiator_deselect_target(nfc_device_t* pnd); NFC_EXPORT bool nfc_initiator_transceive_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); @@ -71,7 +71,7 @@ NFC_EXPORT bool nfc_initiator_transceive_bytes(nfc_device_t* pnd, const byte_t* NFC_EXPORT bool nfc_initiator_transceive_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); /* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */ -NFC_EXPORT bool nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits); +NFC_EXPORT bool nfc_target_init(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits); NFC_EXPORT bool nfc_target_receive_bits(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); NFC_EXPORT bool nfc_target_receive_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); NFC_EXPORT bool nfc_target_receive_dep_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 9b976fa..6888ebd 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -181,8 +181,7 @@ nfc_device_t* nfc_connect(nfc_device_desc_t* pndd) pnd->pdc = &(drivers_callbacks_list[uiDriver]); // Try to retrieve PN53x chip revision - // We can not use pn53x_transceive() because abtRx[0] gives no status info - if (!pnd->pdc->transceive(pnd->nds,pncmd_get_firmware_version,2,abtFw,&szFwLen)) + if (!pn53x_transceive(pnd,pncmd_get_firmware_version,2,abtFw,&szFwLen)) { // Failed to get firmware revision??, whatever...let's disconnect and clean up and return err DBG("Failed to get firmware revision for: %s", pnd->acName); @@ -275,8 +274,7 @@ bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool case NDO_ACTIVATE_FIELD: abtCmd[2] = RFCI_FIELD; abtCmd[3] = (bEnable) ? 1 : 0; - // We can not use pn53x_transceive() because abtRx[0] gives no status info - if (!pnd->pdc->transceive(pnd->nds,abtCmd,4,NULL,NULL)) return false; + if (!pn53x_transceive(pnd,abtCmd,4,NULL,NULL)) return false; break; case NDO_ACTIVATE_CRYPTO1: @@ -290,8 +288,7 @@ bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool abtCmd[3] = (bEnable) ? 0xff : 0x00; // MxRtyATR, default: active = 0xff, passive = 0x02 abtCmd[4] = (bEnable) ? 0xff : 0x00; // MxRtyPSL, default: 0x01 abtCmd[5] = (bEnable) ? 0xff : 0x00; // MxRtyPassiveActivation, default: 0xff - // We can not use pn53x_transceive() because abtRx[0] gives no status info - if (!pnd->pdc->transceive(pnd->nds,abtCmd,6,NULL,NULL)) return false; + if (!pn53x_transceive(pnd,abtCmd,6,NULL,NULL)) return false; break; case NDO_ACCEPT_INVALID_FRAMES: @@ -637,7 +634,7 @@ bool nfc_initiator_deselect_target(nfc_device_t* pnd) * @param pszTargetFound found targets count */ bool -nfc_initiator_poll_targets(const nfc_device_t* pnd, +nfc_initiator_poll_targets(nfc_device_t* pnd, const nfc_target_type_t* pnttTargetTypes, const size_t szTargetTypes, const byte_t btPollNr, const byte_t btPeriod, nfc_target_t* pntTargets, size_t* pszTargetFound) @@ -662,7 +659,7 @@ nfc_initiator_poll_targets(const nfc_device_t* pnd, } szRxLen = 256; - res = pnd->pdc->transceive(pnd->nds, pbtTxInAutoPoll, szTxInAutoPoll, abtRx, &szRxLen); + res = pn53x_transceive(pnd, pbtTxInAutoPoll, szTxInAutoPoll, abtRx, &szRxLen); if((szRxLen == 0)||(res == false)) { DBG("pnd->pdc->tranceive() failed: szRxLen=%ld, res=%d", (unsigned long) szRxLen, res); @@ -852,7 +849,7 @@ bool nfc_initiator_transceive_bytes(nfc_device_t* pnd, const byte_t* pbtTx, cons * * @warning Be aware that this function will wait (hang) until a command is received that is not part of the anti-collision. The RATS command for example would wake up the emulator. After this is received, the send and receive functions can be used. */ -bool nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits) +bool nfc_target_init(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; @@ -885,10 +882,9 @@ bool nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits) // Let the PN53X be activated by the RF level detector from power down mode if (!pn53x_set_reg(pnd,REG_CIU_TX_AUTO, SYMBOL_INITIAL_RF_ON,0x04)) return false; - // Request the initialization as a target, we can not use pn53x_transceive() because - // abtRx[0] contains the emulation mode (baudrate, 14443-4?, DEP and framing type) + // Request the initialization as a target szRxLen = MAX_FRAME_LEN; - if (!pnd->pdc->transceive(pnd->nds,abtCmd,39,abtRx,&szRxLen)) return false; + if (!pn53x_transceive(pnd,abtCmd,39,abtRx,&szRxLen)) return false; // Get the last bit-count that is stored in the received byte ui8Bits = pn53x_get_reg(pnd,REG_CIU_CONTROL) & SYMBOL_RX_LAST_BITS; From d498fcd48ecf3ca852a3f249cd9041e99c3629ea Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Sat, 31 Jul 2010 09:50:04 +0000 Subject: [PATCH 07/32] Comment all commands that return a status code in the list. Found a typo at that occasion so s/0x93/0x92/. --- libnfc/chips/pn53x.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index cfa785e..dd77460 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -77,22 +77,22 @@ bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxL if (!pnd->pdc->transceive(pnd->nds,pbtTx,szTxLen,pbtRx,pszRxLen)) return false; switch (pbtTx[1]) { - case 0x16: - case 0x40: - case 0x42: - case 0x44: - case 0x46: - case 0x4e: - case 0x50: - case 0x52: - case 0x54: - case 0x56: - case 0x86: - case 0x88: - case 0x8e: - case 0x90: - case 0x93: - case 0x94: + case 0x16: // PowerDown + case 0x40: // InDataExchange + case 0x42: // InCommunicateThru + case 0x44: // InDeselect + case 0x46: // InJumpForPSL + case 0x4e: // InPSL + case 0x50: // InATR + case 0x52: // InRelease + case 0x54: // InSelect + case 0x56: // InJumpForDEP + case 0x86: // TgGetData + case 0x88: // TgGetInitiatorCommand + case 0x8e: // TgSetData + case 0x90: // TgResponseToInitiator + case 0x92: // TgSetGeneralBytes + case 0x94: // TgSetMetaData pnd->iErrorCode = pbtRx[0] & 0x3f; break; default: From 301d692e8a635c9ec2d2dc96fc53fa1d8168f3cc Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Sat, 31 Jul 2010 14:02:46 +0000 Subject: [PATCH 08/32] Flag references to deprecated usage of pn53x_transceive(). New issue Summary: pn53x_transceive() workaround reverences in examples/nfc-poll.c comments Status: New Owner: rconty@il4p.fr Cc: rtartiere@il4p.fr The source code of nfc-poll has references to no using pn53x_transceive() for the status-byte workaround reason in a comment. However this function is not called in the code. While I guess that's some comment that should have been removed and have never reached the svn repo, I prefer to be sure that it can be removed. The comments where introduced at the same time of the file, at r353. --- examples/nfc-poll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index 9c70859..905246b 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -94,6 +94,7 @@ main (int argc, const char *argv[]) printf ("Connected to NFC reader: %s\n", pnd->acName); // NOTE we can't use pn53x_transceive() because rx[0] is not status byte (0x00 != status OK) +// XXX: as of r491, this is no longer the case. Unfortunately I can't be sure that these comments can be removed. // bool pn53x_transceive(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); // bool res = pn53x_transceive(pnd, abtTx, szTxLen, abtRx, &szRxLen); From 79aeaa6287bcc98671d7441ed5fc67d3b979c782 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Sat, 31 Jul 2010 14:20:15 +0000 Subject: [PATCH 09/32] Factorise code. Avoid redundant code in PN53x usb and uart drivers. Since it makes sense to report errors at the nfc_device_t level, pass it directly to pn53x_transceive(). Programs using the libnfc MAY use pn53x_transceive() to communicate with a NFC device, and SHALL not use anymore pnd->pdc->transceive(). Code in the library itself SHOULD avoid calling pnd->pdc->transceive(), so such construct have been updated accordingly. --- examples/nfc-sam.c | 3 ++- examples/pn53x-diagnose.c | 6 ++--- include/nfc/nfc-types.h | 2 +- include/nfc/nfc.h | 4 +-- libnfc/chips/pn53x.c | 54 ++++++++++++++++++++++++++----------- libnfc/chips/pn53x.h | 11 ++++---- libnfc/drivers/acr122.c | 4 +-- libnfc/drivers/acr122.h | 2 +- libnfc/drivers/arygon.c | 8 +++--- libnfc/drivers/arygon.h | 2 +- libnfc/drivers/pn532_uart.c | 35 +++++++----------------- libnfc/drivers/pn532_uart.h | 2 +- libnfc/drivers/pn53x_usb.c | 11 ++++---- libnfc/drivers/pn53x_usb.h | 2 +- libnfc/nfc.c | 4 +-- 15 files changed, 80 insertions(+), 70 deletions(-) diff --git a/examples/nfc-sam.c b/examples/nfc-sam.c index d2581ec..fb32f5e 100644 --- a/examples/nfc-sam.c +++ b/examples/nfc-sam.c @@ -45,6 +45,7 @@ #include #include #include "nfc-utils.h" +#include "chips/pn53x.h" #define MAX_FRAME_LEN 264 #define TIMEOUT 60 // secs. @@ -80,7 +81,7 @@ bool sam_connection(nfc_device_t* pnd, int mode) break; } - if (!pnd->pdc->transceive(pnd->nds,pncmd_sam_config,szCmd,abtRx,&szRxLen)) { + if (!pn53x_transceive(pnd,pncmd_sam_config,szCmd,abtRx,&szRxLen)) { ERR("%s %d", "Unable to execute SAMConfiguration command with mode byte:", mode); return false; } diff --git a/examples/pn53x-diagnose.c b/examples/pn53x-diagnose.c index 4436503..f3fc0d6 100644 --- a/examples/pn53x-diagnose.c +++ b/examples/pn53x-diagnose.c @@ -78,19 +78,19 @@ int main(int argc, const char* argv[]) printf("NFC device [%s] connected.\n",pnd->acName); - result = pnd->pdc->transceive(pnd->nds,pncmd_diagnose_communication_line_test,sizeof(pncmd_diagnose_communication_line_test),abtRx,&szRxLen); + result = pn53x_transceive(pnd,pncmd_diagnose_communication_line_test,sizeof(pncmd_diagnose_communication_line_test),abtRx,&szRxLen); if ( result ) { result = (memcmp(pncmd_diagnose_communication_line_test+2, abtRx, sizeof(pncmd_diagnose_communication_line_test)-2 ) == 0); } printf(" Communication line test: %s\n", result ? "OK" : "Failed"); - result = pnd->pdc->transceive(pnd->nds,pncmd_diagnose_rom_test,sizeof(pncmd_diagnose_rom_test),abtRx,&szRxLen); + result = pn53x_transceive(pnd,pncmd_diagnose_rom_test,sizeof(pncmd_diagnose_rom_test),abtRx,&szRxLen); if ( result ) { result = ((szRxLen == 1) && (abtRx[0] == 0x00)); } printf(" ROM test: %s\n", result ? "OK" : "Failed"); - result = pnd->pdc->transceive(pnd->nds,pncmd_diagnose_ram_test,sizeof(pncmd_diagnose_ram_test),abtRx,&szRxLen); + result = pn53x_transceive(pnd,pncmd_diagnose_ram_test,sizeof(pncmd_diagnose_ram_test),abtRx,&szRxLen); if ( result ) { result = ((szRxLen == 1) && (abtRx[0] == 0x00)); } diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 2b0c4a8..45df928 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -118,7 +118,7 @@ struct driver_callbacks { /** Connect callback */ nfc_device_t* (*connect)(const nfc_device_desc_t* pndd); /** Transceive callback */ - bool (*transceive)(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); + bool (*transceive)(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); /** Disconnect callback */ void (*disconnect)(nfc_device_t* pnd); }; diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 6f00b01..a106dba 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -60,8 +60,8 @@ NFC_EXPORT void nfc_disconnect(nfc_device_t* pnd); NFC_EXPORT bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool bEnable); /* NFC initiator: act as "reader" */ -NFC_EXPORT bool nfc_initiator_init(const nfc_device_t* pnd); -NFC_EXPORT bool nfc_initiator_select_passive_target(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pti); +NFC_EXPORT bool nfc_initiator_init(nfc_device_t* pnd); +NFC_EXPORT bool nfc_initiator_select_passive_target(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pti); NFC_EXPORT bool nfc_initiator_list_passive_targets(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, nfc_target_info_t anti[], const size_t szTargets, size_t *pszTargetFound ); NFC_EXPORT bool nfc_initiator_poll_targets(nfc_device_t* pnd, const nfc_target_type_t* pnttTargetTypes, const size_t szTargetTypes, const byte_t btPollNr, const byte_t btPeriod, nfc_target_t* pntTargets, size_t* pszTargetFound); NFC_EXPORT bool nfc_initiator_select_dep_target(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtPidData, const size_t szPidDataLen, const byte_t* pbtNFCID3i, const size_t szNFCID3iDataLen, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pti); diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index dd77460..df60767 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -26,8 +26,12 @@ #include "config.h" #endif // HAVE_CONFIG_H -#include #include +#include +#include + +// FIXME: WTF are doing debug macros in this file? +#include #include "pn53x.h" #include "../mirror-subr.h" @@ -60,6 +64,30 @@ const byte_t pncmd_target_receive [ 2] = { 0xD4,0x88 }; const byte_t pncmd_target_send [264] = { 0xD4,0x90 }; const byte_t pncmd_target_get_status [ 2] = { 0xD4,0x8A }; +static const byte_t pn53x_ack_frame[] = { 0x00,0x00,0xff,0x00,0xff,0x00 }; +static const byte_t pn53x_nack_frame[] = { 0x00,0x00,0xff,0xff,0x00,0x00 }; + +bool pn53x_transceive_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen) +{ + (void) pnd; // I guess we will want to set some error here at some point + + if (szRxFrameLen == sizeof (pn53x_ack_frame)) { + if (0 == memcmp (pbtRxFrame, pn53x_ack_frame, sizeof (pn53x_ack_frame))) { + DBG("%s", "PN53x ACKed"); + return true; + } else if (0 == memcmp (pbtRxFrame, pn53x_nack_frame, sizeof (pn53x_nack_frame))) { + DBG("%s", "PN53x NACKed"); + return false; + } + } + ERR("%s", "Unexpected PN53x reply!"); +#if defined(DEBUG) + // coredump so that we can have a backtrace about how this code was reached. + abort(); +#endif + return false; +} + bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; @@ -74,7 +102,7 @@ bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxL *pszRxLen = MAX_FRAME_LEN; // Call the tranceive callback function of the current device - if (!pnd->pdc->transceive(pnd->nds,pbtTx,szTxLen,pbtRx,pszRxLen)) return false; + if (!pnd->pdc->transceive(pnd,pbtTx,szTxLen,pbtRx,pszRxLen)) return false; switch (pbtTx[1]) { case 0x16: // PowerDown @@ -102,7 +130,7 @@ bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxL return (0 == pnd->iErrorCode); } -byte_t pn53x_get_reg(const nfc_device_t* pnd, uint16_t ui16Reg) +byte_t pn53x_get_reg(nfc_device_t* pnd, uint16_t ui16Reg) { uint8_t ui8Value; size_t szValueLen = 1; @@ -111,12 +139,11 @@ byte_t pn53x_get_reg(const nfc_device_t* pnd, uint16_t ui16Reg) abtCmd[2] = ui16Reg >> 8; abtCmd[3] = ui16Reg & 0xff; - // We can not use pn53x_transceive() because abtRx[0] gives no status info - pnd->pdc->transceive(pnd->nds,abtCmd,4,&ui8Value,&szValueLen); + pn53x_transceive(pnd,abtCmd,4,&ui8Value,&szValueLen); return ui8Value; } -bool pn53x_set_reg(const nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value) +bool pn53x_set_reg(nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value) { byte_t abtCmd[sizeof(pncmd_set_register)]; memcpy(abtCmd,pncmd_set_register,sizeof(pncmd_set_register)); @@ -124,21 +151,19 @@ bool pn53x_set_reg(const nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolM abtCmd[2] = ui16Reg >> 8; abtCmd[3] = ui16Reg & 0xff; abtCmd[4] = ui8Value | (pn53x_get_reg(pnd,ui16Reg) & (~ui8SybmolMask)); - // We can not use pn53x_transceive() because abtRx[0] gives no status info - return pnd->pdc->transceive(pnd->nds,abtCmd,5,NULL,NULL); + return pn53x_transceive(pnd,abtCmd,5,NULL,NULL); } -bool pn53x_set_parameters(const nfc_device_t* pnd, uint8_t ui8Value) +bool pn53x_set_parameters(nfc_device_t* pnd, uint8_t ui8Value) { byte_t abtCmd[sizeof(pncmd_set_parameters)]; memcpy(abtCmd,pncmd_set_parameters,sizeof(pncmd_set_parameters)); abtCmd[2] = ui8Value; - // We can not use pn53x_transceive() because abtRx[0] gives no status info - return pnd->pdc->transceive(pnd->nds,abtCmd,3,NULL,NULL); + return pn53x_transceive(pnd,abtCmd,3,NULL,NULL); } -bool pn53x_set_tx_bits(const nfc_device_t* pnd, uint8_t ui8Bits) +bool pn53x_set_tx_bits(nfc_device_t* pnd, uint8_t ui8Bits) { // Test if we need to update the transmission bits register setting if (pnd->ui8TxBits != ui8Bits) @@ -307,7 +332,7 @@ pn53x_decode_target_data(const byte_t* pbtRawData, size_t szDataLen, nfc_chip_t * @note To decode theses TargetData[n], there is @fn pn53x_decode_target_data */ bool -pn53x_InListPassiveTarget(const nfc_device_t* pnd, +pn53x_InListPassiveTarget(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t szMaxTargets, const byte_t* pbtInitiatorData, const size_t szInitiatorDataLen, byte_t* pbtTargetsData, size_t* pszTargetsData) @@ -324,8 +349,7 @@ pn53x_InListPassiveTarget(const nfc_device_t* pnd, // Try to find a tag, call the tranceive callback function of the current device size_t szRxLen = MAX_FRAME_LEN; - // We can not use pn53x_transceive() because abtRx[0] gives no status info - if(pnd->pdc->transceive(pnd->nds,abtCmd,4+szInitiatorDataLen,pbtTargetsData,&szRxLen)) { + if(pn53x_transceive(pnd,abtCmd,4+szInitiatorDataLen,pbtTargetsData,&szRxLen)) { *pszTargetsData = szRxLen; return true; } else { diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index efef7d7..1f1a578 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -69,16 +69,17 @@ #define RFCI_ANALOG_TYPE_B 0x0C // 3 #define RFCI_ANALOG_TYPE_14443_4 0x0D // 9 +bool pn53x_transceive_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen); bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); -byte_t pn53x_get_reg(const nfc_device_t* pnd, uint16_t ui16Reg); -bool pn53x_set_reg(const nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value); -bool pn53x_set_parameters(const nfc_device_t* pnd, uint8_t ui8Value); -bool pn53x_set_tx_bits(const nfc_device_t* pnd, uint8_t ui8Bits); +byte_t pn53x_get_reg(nfc_device_t* pnd, uint16_t ui16Reg); +bool pn53x_set_reg(nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value); +bool pn53x_set_parameters(nfc_device_t* pnd, uint8_t ui8Value); +bool pn53x_set_tx_bits(nfc_device_t* pnd, uint8_t ui8Bits); bool pn53x_wrap_frame(const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtFrame, size_t* pszFrameBits); bool pn53x_unwrap_frame(const byte_t* pbtFrame, const size_t szFrameBits, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); bool pn53x_decode_target_data(const byte_t* pbtRawData, size_t szDataLen, nfc_chip_t nc, nfc_target_type_t ntt, nfc_target_info_t* pnti); -bool pn53x_InListPassiveTarget(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t szMaxTargets, const byte_t* pbtInitiatorData, const size_t szInitiatorDataLen, byte_t* pbtTargetsData, size_t* pszTargetsData); +bool pn53x_InListPassiveTarget(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t szMaxTargets, const byte_t* pbtInitiatorData, const size_t szInitiatorDataLen, byte_t* pbtTargetsData, size_t* pszTargetsData); bool pn53x_InDeselect(nfc_device_t* pnd, const uint8_t ui8Target); const char *pn53x_strerror (const nfc_device_t *pnd); diff --git a/libnfc/drivers/acr122.c b/libnfc/drivers/acr122.c index 47357e8..78a97b1 100644 --- a/libnfc/drivers/acr122.c +++ b/libnfc/drivers/acr122.c @@ -259,14 +259,14 @@ void acr122_disconnect(nfc_device_t* pnd) free(pnd); } -bool acr122_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) +bool acr122_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRxCmd[5] = { 0xFF,0xC0,0x00,0x00 }; size_t szRxCmdLen = sizeof(abtRxCmd); byte_t abtRxBuf[ACR122_RESPONSE_LEN]; size_t szRxBufLen; byte_t abtTxBuf[ACR122_WRAP_LEN+ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00 }; - acr122_spec_t* pas = (acr122_spec_t*)nds; + acr122_spec_t* pas = (acr122_spec_t*)pnd->nds; // Make sure the command does not overflow the send buffer if (szTxLen > ACR122_COMMAND_LEN) return false; diff --git a/libnfc/drivers/acr122.h b/libnfc/drivers/acr122.h index 69ab71e..ac3b1c2 100644 --- a/libnfc/drivers/acr122.h +++ b/libnfc/drivers/acr122.h @@ -40,7 +40,7 @@ nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd); void acr122_disconnect(nfc_device_t* pnd); // Callback function used by libnfc to transmit commands to the PN53X chip -bool acr122_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); +bool acr122_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); // Various additional features this device supports char* acr122_firmware(const nfc_device_spec_t nds); diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 2d5fbd6..c6161d9 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -214,7 +214,7 @@ void arygon_disconnect(nfc_device_t* pnd) free(pnd); } -bool arygon_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) +bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtTxBuf[BUFFER_LENGTH] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" byte_t abtRxBuf[BUFFER_LENGTH]; @@ -244,12 +244,12 @@ bool arygon_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const s #ifdef DEBUG PRINT_HEX("TX", abtTxBuf,szTxLen+8); #endif - if (!uart_send((serial_port)nds,abtTxBuf,szTxLen+8)) { + if (!uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+8)) { ERR("%s", "Unable to transmit data. (TX)"); return false; } - if (!uart_receive((serial_port)nds,abtRxBuf,&szRxBufLen)) { + if (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { ERR("%s", "Unable to receive data. (RX)"); return false; } @@ -279,7 +279,7 @@ bool arygon_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const s if(szRxBufLen == 0) { // There was no more data than ACK frame, we need to wait next frame DBG("%s", "There was no more data than ACK frame, we need to wait next frame"); - while (!uart_receive((serial_port)nds,abtRxBuf,&szRxBufLen)) { + while (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { delay_ms(10); } } diff --git a/libnfc/drivers/arygon.h b/libnfc/drivers/arygon.h index 8d419ca..47d3a9f 100644 --- a/libnfc/drivers/arygon.h +++ b/libnfc/drivers/arygon.h @@ -36,7 +36,7 @@ nfc_device_t* arygon_connect(const nfc_device_desc_t* pndd); void arygon_disconnect(nfc_device_t* pnd); // Callback function used by libnfc to transmit commands to the PN53X chip -bool arygon_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); +bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); #endif // ! __NFC_DRIVER_ARYGON_H__ diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 981a7dc..e8013f1 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -29,6 +29,7 @@ #endif // HAVE_CONFIG_H #include "../drivers.h" +#include "../chips/pn53x.h" #include #include @@ -197,14 +198,12 @@ void pn532_uart_disconnect(nfc_device_t* pnd) free(pnd); } -bool pn532_uart_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) +bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtTxBuf[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" byte_t abtRxBuf[BUFFER_LENGTH]; size_t szRxBufLen = BUFFER_LENGTH; size_t szPos; - const byte_t pn53x_ack_frame[] = { 0x00,0x00,0xff,0x00,0xff,0x00 }; - const byte_t pn53x_nack_frame[] = { 0x00,0x00,0xff,0xff,0x00,0x00 }; // Packet length = data length (len) + checksum (1) + end of stream marker (1) abtTxBuf[3] = szTxLen; @@ -226,12 +225,13 @@ bool pn532_uart_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, con #ifdef DEBUG PRINT_HEX("TX", abtTxBuf,szTxLen+7); #endif - if (!uart_send((serial_port)nds,abtTxBuf,szTxLen+7)) { + if (!uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+7)) { ERR("%s", "Unable to transmit data. (TX)"); return false; } - if (!uart_receive((serial_port)nds,abtRxBuf,&szRxBufLen)) { + szRxBufLen = 6; + if (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { ERR("%s", "Unable to receive data. (RX)"); return false; } @@ -240,31 +240,14 @@ bool pn532_uart_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, con PRINT_HEX("RX", abtRxBuf,szRxBufLen); #endif - if(szRxBufLen >= sizeof(pn53x_ack_frame)) { + if (!pn53x_transceive_callback(pnd, abtRxBuf, szRxBufLen)) + return false; - // Check if PN53x reply ACK - if(0!=memcmp(pn53x_ack_frame, abtRxBuf, sizeof(pn53x_ack_frame))) { - DBG("%s", "PN53x doesn't respond ACK frame."); - if (0==memcmp(pn53x_nack_frame, abtRxBuf, sizeof(pn53x_nack_frame))) { - ERR("%s", "PN53x reply NACK frame."); - // FIXME Handle NACK frame i.e. resend frame, PN53x doesn't received it correctly - } - return false; - } + szRxBufLen = BUFFER_LENGTH; - szRxBufLen -= sizeof(pn53x_ack_frame); - if(szRxBufLen) { - memmove(abtRxBuf, abtRxBuf+sizeof(pn53x_ack_frame), szRxBufLen); - } - } - - if(szRxBufLen == 0) { - // There was no more data than ACK frame, we need to wait next frame - DBG("%s", "There was no more data than ACK frame, we need to wait next frame"); - while (!uart_receive((serial_port)nds,abtRxBuf,&szRxBufLen)) { + while (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { delay_ms(10); } - } #ifdef DEBUG PRINT_HEX("RX", abtRxBuf,szRxBufLen); diff --git a/libnfc/drivers/pn532_uart.h b/libnfc/drivers/pn532_uart.h index d364f10..d192fa5 100644 --- a/libnfc/drivers/pn532_uart.h +++ b/libnfc/drivers/pn532_uart.h @@ -36,7 +36,7 @@ nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd); void pn532_uart_disconnect(nfc_device_t* pnd); // Callback function used by libnfc to transmit commands to the PN53X chip -bool pn532_uart_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); +bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); #endif // ! __NFC_DRIVER_PN532_UART_H__ diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 1fd9d39..4c5156c 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -38,6 +38,7 @@ Thanks to d18c7db and Okko for example code #include #include "../drivers.h" +#include "../chips/pn53x.h" #include @@ -235,13 +236,13 @@ void pn53x_usb_disconnect(nfc_device_t* pnd) free(pnd); } -bool pn53x_usb_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) +bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { size_t uiPos = 0; int ret = 0; byte_t abtTx[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" byte_t abtRx[BUFFER_LENGTH]; - usb_spec_t* pus = (usb_spec_t*)nds; + usb_spec_t* pus = (usb_spec_t*)pnd->nds; // Packet length = data length (len) + checksum (1) + end of stream marker (1) abtTx[3] = szTxLen; @@ -282,8 +283,9 @@ bool pn53x_usb_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, cons PRINT_HEX("RX", abtRx,ret); #endif - if( ret == 6 ) - { + if (!pn53x_transceive_callback (pnd, abtRx, ret)) + return false; + ret = usb_bulk_read(pus->pudh, pus->uiEndPointIn, (char*)abtRx, BUFFER_LENGTH, USB_TIMEOUT); if( ret < 0 ) { @@ -294,7 +296,6 @@ bool pn53x_usb_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, cons #ifdef DEBUG PRINT_HEX("RX", abtRx,ret); #endif - } // When the answer should be ignored, just return a succesful result if(pbtRx == NULL || pszRxLen == NULL) return true; diff --git a/libnfc/drivers/pn53x_usb.h b/libnfc/drivers/pn53x_usb.h index 00a3091..e2c7ba8 100644 --- a/libnfc/drivers/pn53x_usb.h +++ b/libnfc/drivers/pn53x_usb.h @@ -37,5 +37,5 @@ typedef struct { nfc_device_t* pn53x_usb_connect(const nfc_device_desc_t* pndd,const char * target_name, int target_chip); void get_end_points(struct usb_device *dev, usb_spec_t* pus); void pn53x_usb_disconnect(nfc_device_t* pnd); -bool pn53x_usb_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); +bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); bool pn53x_usb_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound,usb_candidate_t candidates[], int num_candidates, char * target_name); diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 6888ebd..72ca52c 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -318,7 +318,7 @@ bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool * After initialization it can be used to communicate to passive RFID tags and active NFC devices. * The reader will act as initiator to communicate peer 2 peer (NFCIP) to other active NFC devices. */ -bool nfc_initiator_init(const nfc_device_t* pnd) +bool nfc_initiator_init(nfc_device_t* pnd) { // Make sure we are dealing with a active device if (!pnd->bActive) return false; @@ -412,7 +412,7 @@ bool nfc_initiator_select_dep_target(nfc_device_t* pnd, const nfc_modulation_t n * @note For every initial modulation type there is a different collection of information returned (in nfc_target_info_t pointer pti) They all fit in the data-type which is called nfc_target_info_t. This is a union which contains the tag information that belongs to the according initial modulation type. */ bool -nfc_initiator_select_passive_target(const nfc_device_t* pnd, +nfc_initiator_select_passive_target(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pnti) From 8fef257d16a934cd8f2e61abf5326562a7f461c2 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Sun, 8 Aug 2010 15:25:06 +0000 Subject: [PATCH 10/32] Also use pn53x_transceive_callback() in the arygon driver. While here, remove unneeded header in pn532_uart.c. --- libnfc/drivers/arygon.c | 27 ++++----------------------- libnfc/drivers/pn532_uart.c | 1 - 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index d3261d8..3f421da 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -219,9 +219,6 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx size_t szRxBufLen = BUFFER_LENGTH; size_t szPos; - const byte_t pn53x_ack_frame[] = { 0x00,0x00,0xff,0x00,0xff,0x00 }; - const byte_t pn53x_nack_frame[] = { 0x00,0x00,0xff,0xff,0x00,0x00 }; - // Packet length = data length (len) + checksum (1) + end of stream marker (1) abtTxBuf[4] = szTxLen; // Packet length checksum @@ -247,6 +244,7 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx return false; } + szRxBufLen = 6; if (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { ERR("%s", "Unable to receive data. (RX)"); return false; @@ -256,31 +254,14 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx PRINT_HEX("RX", abtRxBuf,szRxBufLen); #endif - if(szRxBufLen >= sizeof(pn53x_ack_frame)) { + if (!pn53x_transceive_callback(pnd, abtRxBuf, szRxBufLen)) + return false; - // Check if PN53x reply ACK - if(0!=memcmp(pn53x_ack_frame, abtRxBuf, sizeof(pn53x_ack_frame))) { - DBG("%s", "PN53x doesn't respond ACK frame."); - if (0==memcmp(pn53x_nack_frame, abtRxBuf, sizeof(pn53x_nack_frame))) { - ERR("%s", "PN53x reply NACK frame."); - // FIXME Handle NACK frame i.e. resend frame, PN53x doesn't received it correctly - } - return false; - } + szRxBufLen = BUFFER_LENGTH; - szRxBufLen -= sizeof(pn53x_ack_frame); - if(szRxBufLen) { - memmove(abtRxBuf, abtRxBuf+sizeof(pn53x_ack_frame), szRxBufLen); - } - } - - if(szRxBufLen == 0) { - // There was no more data than ACK frame, we need to wait next frame - DBG("%s", "There was no more data than ACK frame, we need to wait next frame"); while (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { delay_ms(10); } - } #ifdef DEBUG PRINT_HEX("RX", abtRxBuf,szRxBufLen); diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 64e95f2..a9f4905 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -27,7 +27,6 @@ #endif // HAVE_CONFIG_H #include "../drivers.h" -#include "../chips/pn53x.h" #include #include From 4a5347e5aedb5bbf007d6a9ca50492ad07584408 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Tue, 10 Aug 2010 21:41:42 +0000 Subject: [PATCH 11/32] Merge r512 from trunk. --- examples/mifare.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/mifare.c b/examples/mifare.c index 9680b7b..75dafcb 100644 --- a/examples/mifare.c +++ b/examples/mifare.c @@ -4,8 +4,6 @@ #include -#include "chips/pn53x.h" - /** * @brief Execute a MIFARE Classic Command * @return Returns true if action was successfully performed; otherwise returns false. @@ -21,7 +19,7 @@ */ bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp) { - byte_t abtRx[MAX_FRAME_LEN]; + byte_t abtRx[265]; size_t szRxLen; size_t szParamLen; byte_t abtCmd[265]; From ca6b768a679953715cd0a5a994ebd084fdc53d47 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Tue, 10 Aug 2010 21:45:30 +0000 Subject: [PATCH 12/32] Fix build on Microsoft Windows. --- libnfc/chips/pn53x.c | 3 ++- windows/win32/nfc.def | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index c53e10d..c5d3c1b 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -418,8 +418,9 @@ const char * pn53x_strerror (const nfc_device_t *pnd) { const char *pcRes = "Unknown error"; + size_t i; - for (size_t i=0; i < (sizeof (sErrorMessages) / sizeof (struct sErrorMessage)); i++) { + for (i=0; i < (sizeof (sErrorMessages) / sizeof (struct sErrorMessage)); i++) { if (sErrorMessages[i].iErrorCode == pnd->iErrorCode) { pcRes = sErrorMessages[i].pcErrorMsg; break; diff --git a/windows/win32/nfc.def b/windows/win32/nfc.def index ba83eaf..9627a18 100644 --- a/windows/win32/nfc.def +++ b/windows/win32/nfc.def @@ -26,3 +26,6 @@ EXPORTS iso14443a_crc append_iso14443a_crc nfc_version + nfc_perror + nfc_strerror + nfc_strerror_r From caa594eba84e237becd37e841d3e091a25e9e51d Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Wed, 11 Aug 2010 09:46:14 +0000 Subject: [PATCH 13/32] Remove deprecated code. Reported by: rconty@il4p.fr --- libnfc/drivers/pn53x_usb.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 1c58d35..47af10c 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -281,11 +281,6 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s #ifdef DEBUG PRINT_HEX("RX", abtRx,ret); #endif - - if ((ret != 6) || (memcmp (abtRx, ack_frame, 6))) { - DBG ("%s", "===> No ACK!!!!!!"); - return false; - } if (!pn53x_transceive_callback (pnd, abtRx, ret)) return false; From 0502401a295b7c1e48753ffcfd267c7a57d39fb2 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Fri, 13 Aug 2010 08:31:16 +0000 Subject: [PATCH 14/32] Minor tweaks. - Rename the nfc_device_t's struct iErrorCode member to iPICCError (We are likely to have both PICC and PCD errors fields to avoid unneeded complexity at some point); - Make the PN53x error descriptions static; - Enhance some comments here and there. --- include/nfc/nfc-types.h | 4 ++-- libnfc/chips/pn53x.c | 10 +++++----- libnfc/nfc.c | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 45df928..c3a1c47 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -69,8 +69,8 @@ typedef struct { bool bPar; /** The last tx bits setting, we need to reset this if it does not apply anymore */ uint8_t ui8TxBits; -/** The last error encountered by the device */ - int iErrorCode; +/** Last error reported by the PICC */ + int iPICCError; } nfc_device_t; diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index c5d3c1b..080031f 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -121,13 +121,13 @@ bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxL case 0x90: // TgResponseToInitiator case 0x92: // TgSetGeneralBytes case 0x94: // TgSetMetaData - pnd->iErrorCode = pbtRx[0] & 0x3f; + pnd->iPICCError = pbtRx[0] & 0x3f; break; default: - pnd->iErrorCode = 0; + pnd->iPICCError = 0; } - return (0 == pnd->iErrorCode); + return (0 == pnd->iPICCError); } byte_t pn53x_get_reg(nfc_device_t* pnd, uint16_t ui16Reg) @@ -378,7 +378,7 @@ pn53x_InRelease(nfc_device_t* pnd, const uint8_t ui8Target) return(pn53x_transceive(pnd,abtCmd,sizeof(abtCmd),NULL,NULL)); } -struct sErrorMessage { +static struct sErrorMessage { int iErrorCode; const char *pcErrorMsg; } sErrorMessages[] = { @@ -421,7 +421,7 @@ pn53x_strerror (const nfc_device_t *pnd) size_t i; for (i=0; i < (sizeof (sErrorMessages) / sizeof (struct sErrorMessage)); i++) { - if (sErrorMessages[i].iErrorCode == pnd->iErrorCode) { + if (sErrorMessages[i].iErrorCode == pnd->iPICCError) { pcRes = sErrorMessages[i].pcErrorMsg; break; } diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 1c39816..24a682e 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1088,7 +1088,7 @@ bool nfc_target_send_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const siz } /** - * @brief Return the PCD error string + * @brief Return the PICC/PCD error string * @return Returns a string */ const char *nfc_strerror (const nfc_device_t *pnd) @@ -1097,7 +1097,7 @@ const char *nfc_strerror (const nfc_device_t *pnd) } /** - * @brief Renders the PCD error in pcStrErrBuf for a maximum size of szBufLen caracters + * @brief Renders the PICC/PCD error in pcStrErrBuf for a maximum size of szBufLen caracters * @return Returns 0 upon success */ int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen) @@ -1106,7 +1106,7 @@ int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen) } /** - * @brief Display the PCD error a-la perror + * @brief Display the PICC/PCD error a-la perror */ void nfc_perror (const nfc_device_t *pnd, const char *pcString) { From f4bc39bf41e29b3e1bc2cd4892e5dff240332b2a Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Fri, 13 Aug 2010 09:02:20 +0000 Subject: [PATCH 15/32] Mostly revert r521. It was obviously an April joke: iErrorCode which was renamed iPICCError is indeed a PCD Error, so I renamed it to iLastError since communications errors are also to handle at the device driver level (read chip level), although I guess that some errors would be common to distinct devices. PICC error are irrelevant because they can either be transmission error detection (in which case the libnfc should retry the transmission) or application-level errors the libnfc cannot be aware of. --- include/nfc/nfc-types.h | 4 ++-- libnfc/chips/pn53x.c | 8 ++++---- libnfc/nfc.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index c3a1c47..621e617 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -69,8 +69,8 @@ typedef struct { bool bPar; /** The last tx bits setting, we need to reset this if it does not apply anymore */ uint8_t ui8TxBits; -/** Last error reported by the PICC */ - int iPICCError; +/** Last error reported by the PCD / encountered by the PCD driver */ + int iLastError; } nfc_device_t; diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 080031f..757daa8 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -121,13 +121,13 @@ bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxL case 0x90: // TgResponseToInitiator case 0x92: // TgSetGeneralBytes case 0x94: // TgSetMetaData - pnd->iPICCError = pbtRx[0] & 0x3f; + pnd->iLastError = pbtRx[0] & 0x3f; break; default: - pnd->iPICCError = 0; + pnd->iLastError = 0; } - return (0 == pnd->iPICCError); + return (0 == pnd->iLastError); } byte_t pn53x_get_reg(nfc_device_t* pnd, uint16_t ui16Reg) @@ -421,7 +421,7 @@ pn53x_strerror (const nfc_device_t *pnd) size_t i; for (i=0; i < (sizeof (sErrorMessages) / sizeof (struct sErrorMessage)); i++) { - if (sErrorMessages[i].iErrorCode == pnd->iPICCError) { + if (sErrorMessages[i].iErrorCode == pnd->iLastError) { pcRes = sErrorMessages[i].pcErrorMsg; break; } diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 24a682e..1c39816 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1088,7 +1088,7 @@ bool nfc_target_send_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const siz } /** - * @brief Return the PICC/PCD error string + * @brief Return the PCD error string * @return Returns a string */ const char *nfc_strerror (const nfc_device_t *pnd) @@ -1097,7 +1097,7 @@ const char *nfc_strerror (const nfc_device_t *pnd) } /** - * @brief Renders the PICC/PCD error in pcStrErrBuf for a maximum size of szBufLen caracters + * @brief Renders the PCD error in pcStrErrBuf for a maximum size of szBufLen caracters * @return Returns 0 upon success */ int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen) @@ -1106,7 +1106,7 @@ int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen) } /** - * @brief Display the PICC/PCD error a-la perror + * @brief Display the PCD error a-la perror */ void nfc_perror (const nfc_device_t *pnd, const char *pcString) { From 57b775bae2029fb7cb79f3817f102593bebec951 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Fri, 13 Aug 2010 16:02:18 +0000 Subject: [PATCH 16/32] Always ACK on transmission. New issue Summary: Make sending ACK on message transmission skipable. Owner: rtartiere@il4p.fr Cc: rtartiere@il4p.fr Status: New I guess that for performance reasons, some advance users would prefer to skip sending the non-mandatory ACK on data transmission. They may also perform a quicker check of the ACK returned by the chip after sending the command and before receiving the response (not sure about this one). It will probably be a ./configure option disabled by default that allows some "shortcuts" to perform NFC hacking. --- libnfc/drivers/arygon.c | 10 ++++++++++ libnfc/drivers/pn532_uart.c | 10 ++++++++++ libnfc/drivers/pn53x_usb.c | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 2d022ac..a64f219 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -199,6 +199,8 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx byte_t abtRxBuf[BUFFER_LENGTH]; size_t szRxBufLen = BUFFER_LENGTH; size_t szPos; + // TODO: Move this one level up for libnfc-1.6 + uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; // Packet length = data length (len) + checksum (1) + end of stream marker (1) abtTxBuf[4] = szTxLen; @@ -254,6 +256,14 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) if(szRxBufLen < 9) return false; +#ifdef DEBUG + PRINT_HEX("TX", ack_frame, 6); +#endif + if (!uart_send((serial_port)pnd->nds, ack_frame, 6)) { + ERR("%s", "Unable to transmit data. (TX)"); + return false; + } + // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable) *pszRxLen = szRxBufLen - 9; memcpy(pbtRx, abtRxBuf+7, *pszRxLen); diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 0cf6bc2..709275a 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -181,6 +181,8 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t byte_t abtRxBuf[BUFFER_LENGTH]; size_t szRxBufLen = BUFFER_LENGTH; size_t szPos; + // TODO: Move this one level up for libnfc-1.6 + uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; // Packet length = data length (len) + checksum (1) + end of stream marker (1) abtTxBuf[3] = szTxLen; @@ -236,6 +238,14 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) if(szRxBufLen < 9) return false; +#ifdef DEBUG + PRINT_HEX("TX", ack_frame,6); +#endif + if (!uart_send((serial_port)pnd->nds,ack_frame,6)) { + ERR("%s", "Unable to transmit data. (TX)"); + return false; + } + // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable) *pszRxLen = szRxBufLen - 9; memcpy(pbtRx, abtRxBuf+7, *pszRxLen); diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 929a45e..16bc92f 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -243,6 +243,7 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s byte_t abtTx[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" byte_t abtRx[BUFFER_LENGTH]; usb_spec_t* pus = (usb_spec_t*)pnd->nds; + // TODO: Move this one level up for libnfc-1.6 uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; // Packet length = data length (len) + checksum (1) + end of stream marker (1) @@ -298,6 +299,9 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s PRINT_HEX("RX", abtRx,ret); #endif +#ifdef DEBUG + PRINT_HEX("TX", ack_frame,6); +#endif usb_bulk_write(pus->pudh, pus->uiEndPointOut, (char *)ack_frame, 6, USB_TIMEOUT); // When the answer should be ignored, just return a succesful result From d7e0b926acee5d847169d15e21fac7dea6007b4c Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Fri, 13 Aug 2010 18:34:30 +0000 Subject: [PATCH 17/32] Rename the only test of the regression test suite to a more explicit name. - While here, add assertions, enhance slightly the code and decrease the number of loop turns. --- test/Makefile.am | 6 ++-- test/test_access.c | 56 --------------------------------- test/test_access_storm.c | 67 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 59 deletions(-) delete mode 100644 test/test_access.c create mode 100644 test/test_access_storm.c diff --git a/test/Makefile.am b/test/Makefile.am index 9c8fafd..a55e5cf 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -8,12 +8,12 @@ TESTS = run-test.sh TESTS_ENVIRONMENT = NO_MAKE=yes CUTTER="$(CUTTER)" noinst_LTLIBRARIES = \ - test_access.la + test_access_storm.la AM_LDFLAGS = -module -rpath $(libdir) -avoid-version -no-undefined -test_access_la_SOURCES = test_access.c -test_access_la_LIBADD = $(top_builddir)/libnfc/libnfc.la +test_access_storm_la_SOURCES = test_access_storm.c +test_access_storm_la_LIBADD = $(top_builddir)/libnfc/libnfc.la echo-cutter: @echo $(CUTTER) diff --git a/test/test_access.c b/test/test_access.c deleted file mode 100644 index df96156..0000000 --- a/test/test_access.c +++ /dev/null @@ -1,56 +0,0 @@ -#include - -#include - -#define NTESTS 42 -#define MAX_TARGET_COUNT 8 - -void -test_access (void) -{ - int n = NTESTS; - nfc_device_desc_t devices[8]; - size_t device_count, ref_device_count, target_count; - bool res; - - nfc_list_devices (devices, 8, &ref_device_count); - if (!ref_device_count) - cut_omit ("No NFC device found"); - - while (n) { - size_t i; - - nfc_list_devices (devices, 8, &device_count); - cut_assert_equal_int (ref_device_count, device_count, cut_message ("device count")); - - for (i = 0; i < device_count; i++) { - nfc_device_t *device; - nfc_target_info_t anti[MAX_TARGET_COUNT]; - - device = nfc_connect (&(devices[i])); - cut_assert_not_null (device, cut_message ("nfc_connect")); - - nfc_initiator_init(device); - - // Drop the field for a while - nfc_configure(device,NDO_ACTIVATE_FIELD,false); - - // Let the reader only try once to find a tag - nfc_configure(device,NDO_INFINITE_SELECT,false); - - // Configure the CRC and Parity settings - nfc_configure(device,NDO_HANDLE_CRC,true); - nfc_configure(device,NDO_HANDLE_PARITY,true); - - // Enable field so more power consuming cards can power themselves - nfc_configure(device,NDO_ACTIVATE_FIELD,true); - - res = nfc_initiator_list_passive_targets(device, NM_ISO14443A_106, anti, MAX_TARGET_COUNT, &target_count); - cut_assert_true (res, cut_message ("nfc_initiator_list_passive_targets")); - - nfc_disconnect (device); - } - - n--; - } -} diff --git a/test/test_access_storm.c b/test/test_access_storm.c new file mode 100644 index 0000000..de1e715 --- /dev/null +++ b/test/test_access_storm.c @@ -0,0 +1,67 @@ +#include + +#include + +#define NTESTS 10 +#define MAX_DEVICE_COUNT 8 +#define MAX_TARGET_COUNT 8 + +/* + * This is basically a stress-test to ensure we don't left a device in an + * inconsistent state after use. + */ +void +test_access_storm (void) +{ + int n = NTESTS; + nfc_device_desc_t devices[MAX_DEVICE_COUNT]; + size_t device_count, ref_device_count, target_count; + bool res; + + nfc_list_devices (devices, MAX_DEVICE_COUNT, &ref_device_count); + if (!ref_device_count) + cut_omit ("No NFC device found"); + + while (n) { + size_t i; + + nfc_list_devices (devices, MAX_DEVICE_COUNT, &device_count); + cut_assert_equal_int (ref_device_count, device_count, cut_message ("device count")); + + for (i = 0; i < device_count; i++) { + nfc_device_t *device; + nfc_target_info_t anti[MAX_TARGET_COUNT]; + + device = nfc_connect (&(devices[i])); + cut_assert_not_null (device, cut_message ("nfc_connect")); + + res = nfc_initiator_init(device); + cut_assert_true (res, cut_message ("nfc_initiator_init")); + + // Drop the field for a while + res = nfc_configure(device,NDO_ACTIVATE_FIELD,false); + cut_assert_true (res, cut_message ("nfc_configure")); + + // Let the reader only try once to find a tag + res = nfc_configure(device,NDO_INFINITE_SELECT,false); + cut_assert_true (res, cut_message ("nfc_configure")); + + // Configure the CRC and Parity settings + res = nfc_configure(device,NDO_HANDLE_CRC,true); + cut_assert_true (res, cut_message ("nfc_configure")); + res = nfc_configure(device,NDO_HANDLE_PARITY,true); + cut_assert_true (res, cut_message ("nfc_configure")); + + // Enable field so more power consuming cards can power themselves + res = nfc_configure(device,NDO_ACTIVATE_FIELD,true); + cut_assert_true (res, cut_message ("nfc_configure")); + + res = nfc_initiator_list_passive_targets(device, NM_ISO14443A_106, anti, MAX_TARGET_COUNT, &target_count); + cut_assert_true (res, cut_message ("nfc_initiator_list_passive_targets")); + + nfc_disconnect (device); + } + + n--; + } +} From 08eb21aa9da2192687f3fde672a6ece2b235f17e Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Sun, 15 Aug 2010 14:08:29 +0000 Subject: [PATCH 18/32] Second part of error handling. - Define two sets of DE macros: the first one for 'generic' errors which could be encountered regardless of the NFC device the library is acting with (0xX000), and ont set for device-dependant errors (0x0X00). - Make some more functions accept a nfc_device_t* as first argument to have access to the iLastError; - Reset errors when entering public API functions; - Save errors when applicable; - Distinguish system-level errors (e.g. I/O error) and operational errors (the PCD returns an unexpected value); - Minor tweaks. Update issue 65 Status: Feedback New review: Owner: rconty@il4p.fr Cc: rtartiere@il4p.fr Summary: Review the error-handling code. Branch: /branches/libnfc-error-handling For this development, a strong emphasis has been set on making changes that will not go through our way on the way to libnfc-1.6+. For this reason, some constructs are not natural (e.g. error codes defined in two different places), please keep this in mind when reviewing. --- include/nfc/nfc-types.h | 9 +++++- include/nfc/nfc.h | 5 ++++ libnfc/buses/uart.c | 51 ++++++++++++++++++++++++++-------- libnfc/buses/uart.h | 8 +++--- libnfc/chips/pn53x.c | 19 +++++++++++-- libnfc/chips/pn53x.h | 5 ++++ libnfc/drivers/pn532_uart.c | 37 ++++++++++++++++++------- libnfc/drivers/pn53x_usb.c | 8 ++++++ libnfc/nfc.c | 55 +++++++++++++++++++++++++++++++++++-- 9 files changed, 166 insertions(+), 31 deletions(-) diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 621e617..56b211e 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -69,7 +69,14 @@ typedef struct { bool bPar; /** The last tx bits setting, we need to reset this if it does not apply anymore */ uint8_t ui8TxBits; -/** Last error reported by the PCD / encountered by the PCD driver */ +/** Last error reported by the PCD / encountered by the PCD driver + * MSB LSB + * | 00 | 00 | + * || || + * || ++----- Chip-level error (as reported by the PCD) + * |+---------- Driver-level specific error + * +----------- Driver-level general error (common to all drivers) + */ int iLastError; } nfc_device_t; diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index a106dba..91bc012 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -92,6 +92,11 @@ NFC_EXPORT void iso14443a_crc(byte_t* pbtData, size_t szLen, byte_t* pbtCrc); NFC_EXPORT void append_iso14443a_crc(byte_t* pbtData, size_t szLen); NFC_EXPORT const char* nfc_version(void); +/* Common device-level errors */ +#define DEIO 0x1000 /* Input/output error */ +#define DEINVAL 0x2000 /* Invalid argument */ +#define DETIMEOUT 0x3000 /* Operation timeout */ + #ifdef __cplusplus } #endif // __cplusplus diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index 45d555d..8faba95 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -36,6 +36,7 @@ http://www.teuniz.net/RS-232/index.html #include "uart.h" +#include #include // Test if we are dealing with unix operating systems @@ -106,8 +107,9 @@ serial_port uart_open(const char* pcPortName) return sp; } -void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) +void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed) { + serial_port sp = (serial_port)pnd->nds; DBG("Serial port speed requested to be set to %d bauds.", uiPortSpeed); // Set port speed (Input and Output) @@ -149,8 +151,9 @@ void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) } } -uint32_t uart_get_speed(const serial_port sp) +uint32_t uart_get_speed(const nfc_device_t* pnd) { + serial_port sp = (serial_port)pnd->nds; uint32_t uiPortSpeed = 0; const serial_port_unix* spu = (serial_port_unix*)sp; switch (cfgetispeed(&spu->tiNew)) @@ -191,12 +194,13 @@ void uart_close(const serial_port sp) free(sp); } -bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t* pszRxLen) +bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) { int res; int byteCount; fd_set rfds; struct timeval tv; + serial_port sp = (serial_port)pnd->nds; // Reset the output count *pszRxLen = 0; @@ -211,6 +215,7 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t* pszRxLen) // Read error if (res < 0) { DBG("%s", "RX error."); + pnd->iLastError = DEIO; return false; } @@ -219,6 +224,7 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t* pszRxLen) if (*pszRxLen == 0) { // Error, we received no data DBG("%s", "RX time-out, buffer empty."); + pnd->iLastError = DETIMEOUT; return false; } else { // We received some data, but nothing more is available @@ -228,13 +234,19 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t* pszRxLen) // Retrieve the count of the incoming bytes res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); - if (res < 0) return false; + if (res < 0) { + pnd->iLastError = DEIO; + return false; + } // There is something available, read the data res = read(((serial_port_unix*)sp)->fd,pbtRx+(*pszRxLen),byteCount); // Stop if the OS has some troubles reading the data - if (res <= 0) return false; + if (res <= 0) { + pnd->iLastError = DEIO; + return false; + } *pszRxLen += res; @@ -243,12 +255,13 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t* pszRxLen) return true; } -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) +bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) { int32_t res; size_t szPos = 0; fd_set rfds; struct timeval tv; + serial_port sp = (serial_port)pnd->nds; while (szPos < szTxLen) { @@ -261,12 +274,14 @@ bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) // Write error if (res < 0) { DBG("%s", "TX error."); + pnd->iLastError = DEIO; return false; } // Write time-out if (res == 0) { DBG("%s", "TX time-out."); + pnd->iLastError = DETIMEOUT; return false; } @@ -274,7 +289,10 @@ bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) res = write(((serial_port_unix*)sp)->fd,pbtTx+szPos,szTxLen-szPos); // Stop if the OS has some troubles sending the data - if (res <= 0) return false; + if (res <= 0) { + pnd->iLastError = DEIO; + return false; + } szPos += res; } @@ -342,6 +360,7 @@ serial_port uart_open(const char* pcPortName) void uart_close(const serial_port sp) { + serial_port sp = (serial_port)pnd->nds; if (((serial_port_windows*)sp)->hPort != INVALID_HANDLE_VALUE) { CloseHandle(((serial_port_windows*)sp)->hPort); } @@ -350,6 +369,7 @@ void uart_close(const serial_port sp) void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { + serial_port sp = (serial_port)pnd->nds; serial_port_windows* spw; DBG("Serial port speed requested to be set to %d bauds.", uiPortSpeed); @@ -377,6 +397,7 @@ void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) uint32_t uart_get_speed(const serial_port sp) { + serial_port sp = (serial_port)pnd->nds; const serial_port_windows* spw = (serial_port_windows*)sp; if (!GetCommState(spw->hPort, (serial_port)&spw->dcb)) return spw->dcb.BaudRate; @@ -384,16 +405,24 @@ uint32_t uart_get_speed(const serial_port sp) return 0; } -bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t* pszRxLen) +bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) { - ReadFile(((serial_port_windows*)sp)->hPort,pbtRx,*pszRxLen,(LPDWORD)pszRxLen,NULL); + serial_port sp = (serial_port)pnd->nds; + if (!ReadFile(((serial_port_windows*)sp)->hPort,pbtRx,*pszRxLen,(LPDWORD)pszRxLen,NULL)) { + pnd->iLastError = DEIO; + return false; + } return (*pszRxLen != 0); } -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) +bool uart_send(nfc_device_t* pnd, const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) { + serial_port sp = (serial_port)pnd->nds; DWORD dwTxLen = 0; - return WriteFile(((serial_port_windows*)sp)->hPort,pbtTx,szTxLen,&dwTxLen,NULL); + if (!WriteFile(((serial_port_windows*)sp)->hPort,pbtTx,szTxLen,&dwTxLen,NULL)) { + pnd->iLastError = DEIO; + return false; + } return (dwTxLen != 0); } diff --git a/libnfc/buses/uart.h b/libnfc/buses/uart.h index 8b0ea8a..995afcc 100644 --- a/libnfc/buses/uart.h +++ b/libnfc/buses/uart.h @@ -81,11 +81,11 @@ typedef void* serial_port; serial_port uart_open(const char* pcPortName); void uart_close(const serial_port sp); -void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed); -uint32_t uart_get_speed(const serial_port sp); +void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed); +uint32_t uart_get_speed(const nfc_device_t* pnd); -bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t* pszRxLen); -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen); +bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); +bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); #endif // __NFC_BUS_UART_H__ diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 757daa8..3570bcd 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -30,6 +30,7 @@ #include #include +#include // FIXME: WTF are doing debug macros in this file? #include @@ -69,17 +70,19 @@ static const byte_t pn53x_nack_frame[] = { 0x00,0x00,0xff,0xff,0x00,0x00 }; bool pn53x_transceive_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen) { - (void) pnd; // I guess we will want to set some error here at some point - if (szRxFrameLen == sizeof (pn53x_ack_frame)) { if (0 == memcmp (pbtRxFrame, pn53x_ack_frame, sizeof (pn53x_ack_frame))) { DBG("%s", "PN53x ACKed"); return true; } else if (0 == memcmp (pbtRxFrame, pn53x_nack_frame, sizeof (pn53x_nack_frame))) { DBG("%s", "PN53x NACKed"); + // TODO: Try to recover + // A counter could allow the command to be sent again (e.g. max 3 times) + pnd->iLastError = DENACK; return false; } } + pnd->iLastError = DEACKMISMATCH; ERR("%s", "Unexpected PN53x reply!"); #if defined(DEBUG) // coredump so that we can have a backtrace about how this code was reached. @@ -382,6 +385,7 @@ static struct sErrorMessage { int iErrorCode; const char *pcErrorMsg; } sErrorMessages[] = { + /* Chip-level errors */ { 0x00, "Success" }, { 0x01, "Timeout" }, { 0x02, "CRC Error" }, @@ -411,7 +415,16 @@ static struct sErrorMessage { { 0x2B, "Card Discarded" }, { 0x2C, "NFCID3 Mismatch" }, { 0x2D, "Over Current" }, - { 0x2E, "NAD Missing in DEP Frame" } + { 0x2E, "NAD Missing in DEP Frame" }, + + /* Driver-level error */ + { DENACK, "Received NACK" }, + { DEACKMISMATCH, "Expected ACK/NACK" }, + { DEISERRFRAME, "Received an error frame" }, + /* TODO: Move me in more generic code for libnfc 1.6 */ + { DEINVAL, "Invalid argument" }, + { DEIO, "Input/output error" }, + { DETIMEOUT, "Operation timed-out" } }; const char * diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index 634223c..0b2bea3 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -69,6 +69,11 @@ #define RFCI_ANALOG_TYPE_B 0x0C // 3 #define RFCI_ANALOG_TYPE_14443_4 0x0D // 9 +/* PN53x specific device-level errors */ +#define DENACK 0x0100 /* NACK */ +#define DEACKMISMATCH 0x0200 /* Unexpected data */ +#define DEISERRFRAME 0x0300 /* Error frame */ + bool pn53x_transceive_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen); bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); byte_t pn53x_get_reg(nfc_device_t* pnd, uint16_t ui16Reg); diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 709275a..4664191 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -33,6 +33,7 @@ #include "pn532_uart.h" +#include #include // Bus @@ -43,7 +44,7 @@ #define SERIAL_DEFAULT_PORT_SPEED 115200 void pn532_uart_wakeup(const nfc_device_spec_t nds); -bool pn532_uart_check_communication(const nfc_device_spec_t nds); +bool pn532_uart_check_communication(const nfc_device_spec_t nds, bool* success); nfc_device_desc_t * pn532_uart_pick_device (void) @@ -101,12 +102,16 @@ pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_ if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) { + bool bComOk; // Serial port claimed but we need to check if a PN532_UART is connected. uart_set_speed(sp, SERIAL_DEFAULT_PORT_SPEED); // PN532 could be powered down, we need to wake it up before line testing. pn532_uart_wakeup((nfc_device_spec_t)sp); // Check communication using "Diagnose" command, with "Comunication test" (0x00) - if(!pn532_uart_check_communication((nfc_device_spec_t)sp)) continue; + if(!pn532_uart_check_communication((nfc_device_spec_t)sp), &bComOk) + return false; + if (!bComOk) + continue; uart_close(sp); snprintf(pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", acPort); @@ -134,6 +139,7 @@ nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd) { serial_port sp; nfc_device_t* pnd = NULL; + bool bComOk; if( pndd == NULL ) { DBG("%s", "pn532_uart_connect() need an nfc_device_desc_t struct."); @@ -151,7 +157,10 @@ nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd) // PN532 could be powered down, we need to wake it up before line testing. pn532_uart_wakeup((nfc_device_spec_t)sp); // Check communication using "Diagnose" command, with "Comunication test" (0x00) - if(!pn532_uart_check_communication((nfc_device_spec_t)sp)) return NULL; + if(!pn532_uart_check_communication((nfc_device_spec_t)sp, &bComOk)) + return NULL; + if (!bComOk) + return NULL; DBG("Successfully connected to: %s",pndd->pcPort); @@ -206,12 +215,14 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t #endif if (!uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+7)) { ERR("%s", "Unable to transmit data. (TX)"); + pnd->iLastError = DEIO; return false; } szRxBufLen = 6; if (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { ERR("%s", "Unable to receive data. (RX)"); + pnd->iLastError = DEIO; return false; } @@ -236,13 +247,17 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t if(pbtRx == NULL || pszRxLen == NULL) return true; // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) - if(szRxBufLen < 9) return false; + if(szRxBufLen < 9) { + pnd->iLastError = DEINVAL; + return false; + } #ifdef DEBUG PRINT_HEX("TX", ack_frame,6); #endif if (!uart_send((serial_port)pnd->nds,ack_frame,6)) { ERR("%s", "Unable to transmit data. (TX)"); + pnd->iLastError = DEIO; return false; } @@ -274,7 +289,7 @@ pn532_uart_wakeup(const nfc_device_spec_t nds) } bool -pn532_uart_check_communication(const nfc_device_spec_t nds) +pn532_uart_check_communication(const nfc_device_spec_t nds, bool* success) { byte_t abtRx[BUFFER_LENGTH]; size_t szRxLen; @@ -283,10 +298,13 @@ pn532_uart_check_communication(const nfc_device_spec_t nds) /** To be sure that PN532 is alive, we have put a "Diagnose" command to execute a "Communication Line Test" */ const byte_t pncmd_communication_test[] = { 0x00,0x00,0xff,0x09,0xf7,0xd4,0x00,0x00,'l','i','b','n','f','c',0xbe,0x00 }; + *success = false; + #ifdef DEBUG PRINT_HEX("TX", pncmd_communication_test,sizeof(pncmd_communication_test)); #endif - uart_send((serial_port)nds, pncmd_communication_test, sizeof(pncmd_communication_test)); + if (!uart_send((serial_port)nds, pncmd_communication_test, sizeof(pncmd_communication_test))) + return false; if(!uart_receive((serial_port)nds,abtRx,&szRxLen)) { return false; @@ -295,10 +313,9 @@ pn532_uart_check_communication(const nfc_device_spec_t nds) PRINT_HEX("RX", abtRx,szRxLen); #endif - if(0 != memcmp(abtRx,attempted_result,sizeof(attempted_result))) { - DBG("%s", "Communication test failed, result doesn't match to attempted one."); - return false; - } + if(0 == memcmp(abtRx,attempted_result,sizeof(attempted_result))) + *success = true; + return true; } diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 16bc92f..18d9224 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -39,6 +39,7 @@ Thanks to d18c7db and Okko for example code #include "../drivers.h" #include "../chips/pn53x.h" +#include #include #define BUFFER_LENGTH 256 @@ -271,6 +272,7 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s if( ret < 0 ) { DBG("usb_bulk_write failed with error %d", ret); + pnd->iLastError = DEIO; return false; } @@ -278,6 +280,7 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s if( ret < 0 ) { DBG( "usb_bulk_read failed with error %d", ret); + pnd->iLastError = DEIO; return false; } @@ -292,6 +295,7 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s if( ret < 0 ) { DBG("usb_bulk_read failed with error %d", ret); + pnd->iLastError = DEIO; return false; } @@ -311,6 +315,7 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s if(ret < 9) { DBG("%s","No data"); + pnd->iLastError = DEINVAL; return false; } @@ -327,5 +332,8 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s memcpy( pbtRx, abtRx + 7, *pszRxLen); + if (abtRx[5] != pbtTx[0] + 1) { + pnd->iLastError = DEISERRFRAME; + } return true; } diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 1c39816..61bda75 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -258,6 +258,9 @@ bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool { byte_t btValue; byte_t abtCmd[sizeof(pncmd_rf_configure)]; + + pnd->iLastError = 0; + memcpy(abtCmd,pncmd_rf_configure,sizeof(pncmd_rf_configure)); // Make sure we are dealing with a active device @@ -330,6 +333,9 @@ bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool */ bool nfc_initiator_init(nfc_device_t* pnd) { + + pnd->iLastError = 0; + // Make sure we are dealing with a active device if (!pnd->bActive) return false; @@ -364,6 +370,9 @@ bool nfc_initiator_select_dep_target(nfc_device_t* pnd, const nfc_modulation_t n size_t szRxLen; size_t offset; byte_t abtCmd[sizeof(pncmd_initiator_jump_for_dep)]; + + pnd->iLastError = 0; + memcpy(abtCmd,pncmd_initiator_jump_for_dep,sizeof(pncmd_initiator_jump_for_dep)); if(nmInitModulation == NM_ACTIVE_DEP) { @@ -433,6 +442,9 @@ nfc_initiator_select_passive_target(nfc_device_t* pnd, size_t szTargetsData; byte_t abtTargetsData[MAX_FRAME_LEN]; + pnd->iLastError = 0; + + // Make sure we are dealing with a active device if (!pnd->bActive) return false; @@ -551,6 +563,9 @@ bool nfc_initiator_list_passive_targets(nfc_device_t* pnd, const nfc_modulation_ bool bCollisionDetected = false; size_t szTargetFound = 0; + pnd->iLastError = 0; + + // Let the reader only try once to find a target nfc_configure (pnd, NDO_INFINITE_SELECT, false); @@ -628,6 +643,9 @@ bool nfc_initiator_list_passive_targets(nfc_device_t* pnd, const nfc_modulation_ */ bool nfc_initiator_deselect_target(nfc_device_t* pnd) { + + pnd->iLastError = 0; + return (pn53x_InDeselect(pnd, 0)); // 0 mean deselect all selected targets } @@ -652,6 +670,9 @@ nfc_initiator_poll_targets(nfc_device_t* pnd, byte_t abtRx[256]; bool res; byte_t *pbtTxInAutoPoll; + + pnd->iLastError = 0; + if(pnd->nc == NC_PN531) { // errno = ENOSUPP return false; @@ -671,7 +692,7 @@ nfc_initiator_poll_targets(nfc_device_t* pnd, res = pn53x_transceive(pnd, pbtTxInAutoPoll, szTxInAutoPoll, abtRx, &szRxLen); if((szRxLen == 0)||(res == false)) { - DBG("pnd->pdc->tranceive() failed: szRxLen=%ld, res=%d", (unsigned long) szRxLen, res); + DBG("pn53x_transceive() failed: szRxLen=%ld, res=%d", (unsigned long) szRxLen, res); return false; } else { *pszTargetFound = abtRx[0]; @@ -720,6 +741,9 @@ bool nfc_initiator_transceive_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szFrameBytes = 0; uint8_t ui8Bits = 0; byte_t abtCmd[sizeof(pncmd_initiator_exchange_raw_data)]; + + pnd->iLastError = 0; + memcpy(abtCmd,pncmd_initiator_exchange_raw_data,sizeof(pncmd_initiator_exchange_raw_data)); // Check if we should prepare the parity bits ourself @@ -781,6 +805,9 @@ bool nfc_initiator_transceive_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; byte_t abtCmd[sizeof(pncmd_initiator_exchange_data)]; + + pnd->iLastError = 0; + memcpy(abtCmd,pncmd_initiator_exchange_data,sizeof(pncmd_initiator_exchange_data)); // We can not just send bytes without parity if while the PN53X expects we handled them @@ -825,6 +852,9 @@ bool nfc_initiator_transceive_bytes(nfc_device_t* pnd, const byte_t* pbtTx, cons byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; byte_t abtCmd[sizeof(pncmd_initiator_exchange_raw_data)]; + + pnd->iLastError = 0; + memcpy(abtCmd,pncmd_initiator_exchange_raw_data,sizeof(pncmd_initiator_exchange_raw_data)); // We can not just send bytes without parity if while the PN53X expects we handled them @@ -867,6 +897,9 @@ bool nfc_target_init(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits) bool bCrc = pnd->bCrc; bool bPar = pnd->bPar; byte_t abtCmd[sizeof(pncmd_target_init)]; + + pnd->iLastError = 0; + memcpy(abtCmd,pncmd_target_init,sizeof(pncmd_target_init)); // Clear the target init struct, reset to all zeros @@ -923,6 +956,9 @@ bool nfc_target_receive_bits(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits size_t szFrameBits; uint8_t ui8Bits; + pnd->iLastError = 0; + + // Try to gather a received frame from the reader if (!pn53x_transceive(pnd,pncmd_target_receive,2,abtRx,&szRxLen)) return false; @@ -959,6 +995,9 @@ bool nfc_target_receive_dep_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszR byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; + pnd->iLastError = 0; + + // Try to gather a received frame from the reader if (!pn53x_transceive(pnd,pncmd_target_get_data,2,abtRx,&szRxLen)) return false; @@ -983,6 +1022,9 @@ bool nfc_target_receive_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; + pnd->iLastError = 0; + + // Try to gather a received frame from the reader if (!pn53x_transceive(pnd,pncmd_target_receive,2,abtRx,&szRxLen)) return false; @@ -1008,6 +1050,9 @@ bool nfc_target_send_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s size_t szFrameBytes = 0; uint8_t ui8Bits = 0; byte_t abtCmd[sizeof(pncmd_target_send)]; + + pnd->iLastError = 0; + memcpy(abtCmd,pncmd_target_send,sizeof(pncmd_target_send)); // Check if we should prepare the parity bits ourself @@ -1048,6 +1093,9 @@ bool nfc_target_send_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s bool nfc_target_send_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) { byte_t abtCmd[sizeof(pncmd_target_send)]; + + pnd->iLastError = 0; + memcpy(abtCmd,pncmd_target_send,sizeof(pncmd_target_send)); // We can not just send bytes without parity if while the PN53X expects we handled them @@ -1072,6 +1120,9 @@ bool nfc_target_send_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t bool nfc_target_send_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) { byte_t abtCmd[sizeof(pncmd_target_set_data)]; + + pnd->iLastError = 0; + memcpy(abtCmd,pncmd_target_set_data,sizeof(pncmd_target_set_data)); // We can not just send bytes without parity if while the PN53X expects we handled them @@ -1097,7 +1148,7 @@ const char *nfc_strerror (const nfc_device_t *pnd) } /** - * @brief Renders the PCD error in pcStrErrBuf for a maximum size of szBufLen caracters + * @brief Renders the PCD error in pcStrErrBuf for a maximum size of szBufLen chars * @return Returns 0 upon success */ int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen) From f797d737d305f8ab18d7347a1db7f0dcd15b63f5 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Mon, 16 Aug 2010 17:43:48 +0000 Subject: [PATCH 19/32] Fix build on Microsoft Windows. --- libnfc/buses/uart.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index 8faba95..b602381 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -360,14 +360,13 @@ serial_port uart_open(const char* pcPortName) void uart_close(const serial_port sp) { - serial_port sp = (serial_port)pnd->nds; if (((serial_port_windows*)sp)->hPort != INVALID_HANDLE_VALUE) { CloseHandle(((serial_port_windows*)sp)->hPort); } free(sp); } -void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) +void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed) { serial_port sp = (serial_port)pnd->nds; serial_port_windows* spw; @@ -395,7 +394,7 @@ void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) } } -uint32_t uart_get_speed(const serial_port sp) +uint32_t uart_get_speed(const nfc_device_t* pnd) { serial_port sp = (serial_port)pnd->nds; const serial_port_windows* spw = (serial_port_windows*)sp; @@ -415,7 +414,7 @@ bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) return (*pszRxLen != 0); } -bool uart_send(nfc_device_t* pnd, const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) +bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) { serial_port sp = (serial_port)pnd->nds; DWORD dwTxLen = 0; From c9f88e17a1c50061159f779934f8d91ea1b3edd5 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Wed, 18 Aug 2010 14:44:19 +0000 Subject: [PATCH 20/32] Reset pnd->iLastError in nfc.c. --- libnfc/chips/pn53x.c | 2 -- libnfc/nfc.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index e1b4555..9580cb9 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -463,8 +463,6 @@ pn53x_InAutoPoll(nfc_device_t* pnd, bool res; byte_t *pbtTxInAutoPoll; - pnd->iLastError = 0; - if(pnd->nc == NC_PN531) { // TODO This function is not supported by pn531 (set errno = ENOSUPP or similar) return false; diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 53368c6..ec5c4c2 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -593,6 +593,8 @@ nfc_initiator_poll_targets(nfc_device_t* pnd, const byte_t btPollNr, const byte_t btPeriod, nfc_target_t* pntTargets, size_t* pszTargetFound) { + pnd->iLastError = 0; + return pn53x_InAutoPoll(pnd, pnttTargetTypes, szTargetTypes, btPollNr, btPeriod, pntTargets, pszTargetFound); } From 0a09c8d8e706e355448e2fffa516e1ab3e18c784 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Wed, 18 Aug 2010 14:44:40 +0000 Subject: [PATCH 21/32] Flag some problems in the examples. --- examples/nfc-sam.c | 2 ++ examples/pn53x-diagnose.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/examples/nfc-sam.c b/examples/nfc-sam.c index 8976b58..547d6da 100644 --- a/examples/nfc-sam.c +++ b/examples/nfc-sam.c @@ -45,6 +45,7 @@ #include #include #include "nfc-utils.h" +// FIXME: Remove me #include "chips/pn53x.h" #define MAX_FRAME_LEN 264 @@ -81,6 +82,7 @@ bool sam_connection(nfc_device_t* pnd, int mode) break; } + // FIXME: Direct call if (!pn53x_transceive(pnd,pncmd_sam_config,szCmd,abtRx,&szRxLen)) { ERR("%s %d", "Unable to execute SAMConfiguration command with mode byte:", mode); return false; diff --git a/examples/pn53x-diagnose.c b/examples/pn53x-diagnose.c index f3fc0d6..462204c 100644 --- a/examples/pn53x-diagnose.c +++ b/examples/pn53x-diagnose.c @@ -29,6 +29,7 @@ #include #include "nfc-utils.h" +// FIXME: Delete me #include "chips/pn53x.h" #define MAX_DEVICE_COUNT 16 @@ -78,18 +79,21 @@ int main(int argc, const char* argv[]) printf("NFC device [%s] connected.\n",pnd->acName); + // FIXME: Direct call result = pn53x_transceive(pnd,pncmd_diagnose_communication_line_test,sizeof(pncmd_diagnose_communication_line_test),abtRx,&szRxLen); if ( result ) { result = (memcmp(pncmd_diagnose_communication_line_test+2, abtRx, sizeof(pncmd_diagnose_communication_line_test)-2 ) == 0); } printf(" Communication line test: %s\n", result ? "OK" : "Failed"); + // FIXME: Direct call result = pn53x_transceive(pnd,pncmd_diagnose_rom_test,sizeof(pncmd_diagnose_rom_test),abtRx,&szRxLen); if ( result ) { result = ((szRxLen == 1) && (abtRx[0] == 0x00)); } printf(" ROM test: %s\n", result ? "OK" : "Failed"); + // FIXME: Direct call result = pn53x_transceive(pnd,pncmd_diagnose_ram_test,sizeof(pncmd_diagnose_ram_test),abtRx,&szRxLen); if ( result ) { result = ((szRxLen == 1) && (abtRx[0] == 0x00)); From eb90b92c12280d45e51833a5b8444e57ef72604a Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Wed, 18 Aug 2010 17:22:13 +0000 Subject: [PATCH 22/32] Detect errors in examples. --- examples/mifare.c | 5 ++++- examples/nfc-anticol.c | 24 +++++++++++++++++++----- examples/nfc-emulate.c | 12 +++++++++--- examples/nfc-list.c | 25 ++++++++++++++++++++----- examples/nfc-mfclassic.c | 25 ++++++++++++++++++++----- examples/nfc-mfultralight.c | 25 ++++++++++++++++++++----- examples/nfc-poll.c | 25 ++++++++++++++++++++----- examples/nfc-relay.c | 33 ++++++++++++++++++++++++--------- examples/nfc-sam.c | 27 +++++++++++++++++++++------ 9 files changed, 157 insertions(+), 44 deletions(-) diff --git a/examples/mifare.c b/examples/mifare.c index d436812..75a0b76 100644 --- a/examples/mifare.c +++ b/examples/mifare.c @@ -66,7 +66,10 @@ bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint if (szParamLen) memcpy(abtCmd+2,(byte_t*)pmp,szParamLen); // Fire the mifare command - if (!nfc_initiator_transceive_dep_bytes(pnd,abtCmd,2+szParamLen,abtRx,&szRxLen)) return false; + if (!nfc_initiator_transceive_dep_bytes(pnd,abtCmd,2+szParamLen,abtRx,&szRxLen)) { + nfc_perror (pnd, "nfc_initiator_transceive_dep_bytes"); + return false; + } // When we have executed a read command, copy the received bytes into the param if (mc == MC_READ) { diff --git a/examples/nfc-anticol.c b/examples/nfc-anticol.c index b1cd476..477eb08 100644 --- a/examples/nfc-anticol.c +++ b/examples/nfc-anticol.c @@ -143,14 +143,28 @@ int main(int argc,char* argv[]) nfc_initiator_init(pnd); // Drop the field for a while - nfc_configure(pnd,NDO_ACTIVATE_FIELD,false); + if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,false)) { + nfc_perror (pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } - // Configure the CRC and Parity settings - nfc_configure(pnd,NDO_HANDLE_CRC,false); - nfc_configure(pnd,NDO_HANDLE_PARITY,true); + // Configure the CRC + if (!nfc_configure(pnd,NDO_HANDLE_CRC,false)) { + nfc_perror (pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } + + // Configure parity settings + if (!nfc_configure(pnd,NDO_HANDLE_PARITY,true)) { + nfc_perror (pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } // Enable field so more power consuming cards can power themselves up - nfc_configure(pnd,NDO_ACTIVATE_FIELD,true); + if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,true)) { + nfc_perror (pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } printf("\nConnected to NFC reader: %s\n\n",pnd->acName); diff --git a/examples/nfc-emulate.c b/examples/nfc-emulate.c index 3e3036e..1652f8f 100644 --- a/examples/nfc-emulate.c +++ b/examples/nfc-emulate.c @@ -113,8 +113,10 @@ int main(int argc, char *argv[]) printf("[+] Received initiator command: "); print_hex_bits(abtRecv,szRecvBits); printf("[+] Configuring communication\n"); - nfc_configure(pnd,NDO_HANDLE_CRC,false); - nfc_configure(pnd,NDO_HANDLE_PARITY,true); + if (!nfc_configure(pnd,NDO_HANDLE_CRC,false) || !nfc_configure(pnd,NDO_HANDLE_PARITY,true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } printf("[+] Done, the emulated tag is initialized with UID: %02X%02X%02X%02X\n\n",abtUidBcc[0],abtUidBcc[1],abtUidBcc[2],abtUidBcc[3]); while(true) @@ -157,7 +159,10 @@ int main(int argc, char *argv[]) if(szTxBits) { // Send and print the command to the screen - nfc_target_send_bits(pnd,pbtTx,szTxBits,NULL); + if (!nfc_target_send_bits(pnd,pbtTx,szTxBits,NULL)) { + nfc_perror(pnd, "nfc_target_send_bits"); + exit(EXIT_FAILURE); + } if(!quiet_output) { printf("T: "); @@ -168,5 +173,6 @@ int main(int argc, char *argv[]) } nfc_disconnect(pnd); + exit(EXIT_SUCCESS); } diff --git a/examples/nfc-list.c b/examples/nfc-list.c index b6249d0..24a2e18 100644 --- a/examples/nfc-list.c +++ b/examples/nfc-list.c @@ -117,17 +117,32 @@ int main(int argc, const char* argv[]) nfc_initiator_init(pnd); // Drop the field for a while - nfc_configure(pnd,NDO_ACTIVATE_FIELD,false); + if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,false)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Let the reader only try once to find a tag - nfc_configure(pnd,NDO_INFINITE_SELECT,false); + if (!nfc_configure(pnd,NDO_INFINITE_SELECT,false)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Configure the CRC and Parity settings - nfc_configure(pnd,NDO_HANDLE_CRC,true); - nfc_configure(pnd,NDO_HANDLE_PARITY,true); + if (!nfc_configure(pnd,NDO_HANDLE_CRC,true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } + if (!nfc_configure(pnd,NDO_HANDLE_PARITY,true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Enable field so more power consuming cards can power themselves up - nfc_configure(pnd,NDO_ACTIVATE_FIELD,true); + if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } printf("Connected to NFC reader: %s\n",pnd->acName); diff --git a/examples/nfc-mfclassic.c b/examples/nfc-mfclassic.c index 7b1e628..c53a394 100644 --- a/examples/nfc-mfclassic.c +++ b/examples/nfc-mfclassic.c @@ -414,15 +414,30 @@ main (int argc, const char *argv[]) nfc_initiator_init (pnd); // Drop the field for a while - nfc_configure (pnd, NDO_ACTIVATE_FIELD, false); + if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) { + nfc_perror(pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } // Let the reader only try once to find a tag - nfc_configure (pnd, NDO_INFINITE_SELECT, false); - nfc_configure (pnd, NDO_HANDLE_CRC, true); - nfc_configure (pnd, NDO_HANDLE_PARITY, true); + if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) { + nfc_perror(pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } + if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) { + nfc_perror(pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } + if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) { + nfc_perror(pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } // Enable field so more power consuming cards can power themselves up - nfc_configure (pnd, NDO_ACTIVATE_FIELD, true); + if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) { + nfc_perror(pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } printf ("Connected to NFC reader: %s\n", pnd->acName); diff --git a/examples/nfc-mfultralight.c b/examples/nfc-mfultralight.c index 5e59446..a2fe548 100644 --- a/examples/nfc-mfultralight.c +++ b/examples/nfc-mfultralight.c @@ -190,15 +190,30 @@ main (int argc, const char *argv[]) nfc_initiator_init (pnd); // Drop the field for a while - nfc_configure (pnd, NDO_ACTIVATE_FIELD, false); + if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Let the reader only try once to find a tag - nfc_configure (pnd, NDO_INFINITE_SELECT, false); - nfc_configure (pnd, NDO_HANDLE_CRC, true); - nfc_configure (pnd, NDO_HANDLE_PARITY, true); + if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } + if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } + if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Enable field so more power consuming cards can power themselves up - nfc_configure (pnd, NDO_ACTIVATE_FIELD, true); + if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } printf ("Connected to NFC reader: %s\n", pnd->acName); diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index 304816a..b2426d3 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -88,17 +88,32 @@ main (int argc, const char *argv[]) nfc_initiator_init (pnd); // Drop the field for a while - nfc_configure (pnd, NDO_ACTIVATE_FIELD, false); + if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Let the reader only try once to find a tag - nfc_configure (pnd, NDO_INFINITE_SELECT, false); + if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Configure the CRC and Parity settings - nfc_configure (pnd, NDO_HANDLE_CRC, true); - nfc_configure (pnd, NDO_HANDLE_PARITY, true); + if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } + if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Enable field so more power consuming cards can power themselves up - nfc_configure (pnd, NDO_ACTIVATE_FIELD, true); + if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } printf ("Connected to NFC reader: %s\n", pnd->acName); diff --git a/examples/nfc-relay.c b/examples/nfc-relay.c index 99dfa71..d0b06ae 100644 --- a/examples/nfc-relay.c +++ b/examples/nfc-relay.c @@ -132,9 +132,12 @@ int main(int argc,char* argv[]) return EXIT_FAILURE; } printf("%s", "Configuring emulator settings..."); - nfc_configure(pndTag,NDO_HANDLE_CRC,false); - nfc_configure(pndTag,NDO_HANDLE_PARITY,false); - nfc_configure(pndTag,NDO_ACCEPT_INVALID_FRAMES,true); + if (!nfc_configure(pndTag,NDO_HANDLE_CRC,false) || + !nfc_configure(pndTag,NDO_HANDLE_PARITY,false) || + !nfc_configure(pndTag,NDO_ACCEPT_INVALID_FRAMES,true)) { + nfc_perror(pndTag, "nfc_configure"); + exit(EXIT_FAILURE); + } printf("%s", "Done, emulated tag is initialized"); // Try to open the NFC reader @@ -143,9 +146,12 @@ int main(int argc,char* argv[]) printf("Connected to the NFC reader device: %s", pndReader->acName); printf("%s", "Configuring NFC reader settings..."); nfc_initiator_init(pndReader); - nfc_configure(pndReader,NDO_HANDLE_CRC,false); - nfc_configure(pndReader,NDO_HANDLE_PARITY,false); - nfc_configure(pndReader,NDO_ACCEPT_INVALID_FRAMES,true); + if (!nfc_configure(pndReader,NDO_HANDLE_CRC,false) || + !nfc_configure(pndReader,NDO_HANDLE_PARITY,false) || + !nfc_configure(pndReader,NDO_ACCEPT_INVALID_FRAMES,true)) { + nfc_perror(pndReader, "nfc_configure"); + exit(EXIT_FAILURE); + } printf("%s", "Done, relaying frames now!"); while(!quitting) @@ -157,10 +163,16 @@ int main(int argc,char* argv[]) if (szReaderRxBits == 7 && abtReaderRx[0] == 0x26) { // Drop down field for a very short time (original tag will reboot) - nfc_configure(pndReader,NDO_ACTIVATE_FIELD,false); + if (!nfc_configure(pndReader,NDO_ACTIVATE_FIELD,false)) { + nfc_perror(pndReader, "nfc_configure"); + exit(EXIT_FAILURE); + } if(!quiet_output) printf("\n"); - nfc_configure(pndReader,NDO_ACTIVATE_FIELD,true); + if (!nfc_configure(pndReader,NDO_ACTIVATE_FIELD,true)) { + nfc_perror(pndReader, "nfc_configure"); + exit(EXIT_FAILURE); + } } // Print the reader frame to the screen @@ -173,7 +185,10 @@ int main(int argc,char* argv[]) if (nfc_initiator_transceive_bits(pndReader,abtReaderRx,szReaderRxBits,abtReaderRxPar,abtTagRx,&szTagRxBits,abtTagRxPar)) { // Redirect the answer back to the reader - nfc_target_send_bits(pndTag,abtTagRx,szTagRxBits,abtTagRxPar); + if (!nfc_target_send_bits(pndTag,abtTagRx,szTagRxBits,abtTagRxPar)) { + nfc_perror(pndTag, "nfc_target_send_bits"); + exit(EXIT_FAILURE); + } // Print the tag frame to the screen if(!quiet_output) diff --git a/examples/nfc-sam.c b/examples/nfc-sam.c index 547d6da..6a744e0 100644 --- a/examples/nfc-sam.c +++ b/examples/nfc-sam.c @@ -167,18 +167,33 @@ int main(int argc, const char* argv[]) nfc_initiator_init(pnd); // Drop the field for a while - nfc_configure(pnd,NDO_ACTIVATE_FIELD,false); + if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,false)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Let the reader only try once to find a tag - nfc_configure(pnd,NDO_INFINITE_SELECT,false); + if (!nfc_configure(pnd,NDO_INFINITE_SELECT,false)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Configure the CRC and Parity settings - nfc_configure(pnd,NDO_HANDLE_CRC,true); - nfc_configure(pnd,NDO_HANDLE_PARITY,true); + if (!nfc_configure(pnd,NDO_HANDLE_CRC,true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } + if (!nfc_configure(pnd,NDO_HANDLE_PARITY,true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } // Enable field so more power consuming cards can power themselves up - nfc_configure(pnd,NDO_ACTIVATE_FIELD,true); - + if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,true)) { + nfc_perror(pnd, "nfc_configure"); + exit(EXIT_FAILURE); + } + // Read the SAM's info if (!nfc_initiator_select_passive_target(pnd,NM_ISO14443A_106,NULL,0,&nti)) { ERR("%s", "Reading of SAM info failed."); From edba53c5da40a14d64f24a4fcea768d7ac93dba3 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Thu, 19 Aug 2010 09:01:39 +0000 Subject: [PATCH 23/32] Fix pn532_uart driver. --- libnfc/buses/uart.c | 62 +++++++++++++++++++------------------ libnfc/buses/uart.h | 9 +++--- libnfc/chips/pn53x.c | 3 +- libnfc/drivers/pn532_uart.c | 38 ++++++++++++++--------- 4 files changed, 61 insertions(+), 51 deletions(-) diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index d7c25fa..0f6ecec 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -107,11 +107,10 @@ serial_port uart_open(const char* pcPortName) return sp; } -void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed) +void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { - serial_port sp = (serial_port)pnd->nds; DBG("Serial port speed requested to be set to %d bauds.", uiPortSpeed); - // Set port speed (Input and Output) + const serial_port_unix* spu = (serial_port_unix*)sp; // Portability note: on some systems, B9600 != 9600 so we have to do // uint32_t <=> speed_t associations by hand. @@ -142,18 +141,18 @@ void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed) default: ERR("Unable to set serial port speed to %d bauds. Speed value must be one of those defined in termios(3).", uiPortSpeed); }; - const serial_port_unix* spu = (serial_port_unix*)sp; - cfsetispeed((struct termios*)&spu->tiNew, stPortSpeed); - cfsetospeed((struct termios*)&spu->tiNew, stPortSpeed); - if( tcsetattr(spu->fd, TCSADRAIN, &spu->tiNew) == -1) + + // Set port speed (Input and Output) + cfsetispeed((struct termios*)&(spu->tiNew), stPortSpeed); + cfsetospeed((struct termios*)&(spu->tiNew), stPortSpeed); + if( tcsetattr(spu->fd, TCSADRAIN, &(spu->tiNew)) == -1) { ERR("%s", "Unable to apply new speed settings."); } } -uint32_t uart_get_speed(const nfc_device_t* pnd) +uint32_t uart_get_speed(serial_port sp) { - serial_port sp = (serial_port)pnd->nds; uint32_t uiPortSpeed = 0; const serial_port_unix* spu = (serial_port_unix*)sp; switch (cfgetispeed(&spu->tiNew)) @@ -194,13 +193,18 @@ void uart_close(const serial_port sp) free(sp); } -bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) +/** + * @brief Receive data from UART and copy data to \a pbtRx + * + * @return 0 on success, otherwise driver error code + */ +int +uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen) { int res; int byteCount; fd_set rfds; struct timeval tv; - serial_port sp = (serial_port)pnd->nds; // Reset the output count *pszRxLen = 0; @@ -215,8 +219,7 @@ bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) // Read error if (res < 0) { DBG("%s", "RX error."); - pnd->iLastError = DEIO; - return false; + return DEIO; } // Read time-out @@ -224,19 +227,17 @@ bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) if (*pszRxLen == 0) { // Error, we received no data DBG("%s", "RX time-out, buffer empty."); - pnd->iLastError = DETIMEOUT; - return false; + return DETIMEOUT; } else { // We received some data, but nothing more is available - return true; + return 0; } } // Retrieve the count of the incoming bytes res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); if (res < 0) { - pnd->iLastError = DEIO; - return false; + return DEIO; } // There is something available, read the data @@ -244,24 +245,28 @@ bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) // Stop if the OS has some troubles reading the data if (res <= 0) { - pnd->iLastError = DEIO; - return false; + return DEIO; } *pszRxLen += res; } while (byteCount); - return true; + return 0; } -bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) +/** + * @brief Send \a pbtTx content to UART + * + * @return 0 on success, otherwise a driver error is returned + */ +int +uart_send(serial_port sp, const byte_t* pbtTx, const size_t szTxLen) { int32_t res; size_t szPos = 0; fd_set rfds; struct timeval tv; - serial_port sp = (serial_port)pnd->nds; while (szPos < szTxLen) { @@ -274,15 +279,13 @@ bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) // Write error if (res < 0) { DBG("%s", "TX error."); - pnd->iLastError = DEIO; - return false; + return DEIO; } // Write time-out if (res == 0) { DBG("%s", "TX time-out."); - pnd->iLastError = DETIMEOUT; - return false; + return DETIMEOUT; } // Send away the bytes @@ -290,13 +293,12 @@ bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) // Stop if the OS has some troubles sending the data if (res <= 0) { - pnd->iLastError = DEIO; - return false; + return DEIO; } szPos += res; } - return true; + return 0; } #else diff --git a/libnfc/buses/uart.h b/libnfc/buses/uart.h index 483e7a3..35b37d3 100644 --- a/libnfc/buses/uart.h +++ b/libnfc/buses/uart.h @@ -81,12 +81,11 @@ typedef void* serial_port; serial_port uart_open(const char* pcPortName); void uart_close(const serial_port sp); -void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed); -uint32_t uart_get_speed(const nfc_device_t* pnd); +void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed); +uint32_t uart_get_speed(const serial_port sp); -bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); -bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); +int uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen); +int uart_send(serial_port sp, const byte_t* pbtTx, const size_t szTxLen); #endif // __NFC_BUS_UART_H__ - diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 25861c2..5987dc3 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -69,9 +69,10 @@ const byte_t pncmd_target_get_status [ 2] = { 0xD4,0x8A }; static const byte_t pn53x_ack_frame[] = { 0x00,0x00,0xff,0x00,0xff,0x00 }; static const byte_t pn53x_nack_frame[] = { 0x00,0x00,0xff,0xff,0x00,0x00 }; +// XXX: Is this function correctly named ? bool pn53x_transceive_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen) { - if (szRxFrameLen == sizeof (pn53x_ack_frame)) { + if (szRxFrameLen >= sizeof (pn53x_ack_frame)) { if (0 == memcmp (pbtRxFrame, pn53x_ack_frame, sizeof (pn53x_ack_frame))) { DBG("%s", "PN53x ACKed"); return true; diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index ac34129..2bef198 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -100,7 +100,7 @@ pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_ // PN532 could be powered down, we need to wake it up before line testing. pn532_uart_wakeup((nfc_device_spec_t)sp); // Check communication using "Diagnose" command, with "Comunication test" (0x00) - if(!pn532_uart_check_communication((nfc_device_spec_t)sp), &bComOk) + if(!pn532_uart_check_communication((nfc_device_spec_t)sp, &bComOk)) return false; if (!bComOk) continue; @@ -200,16 +200,19 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t #ifdef DEBUG PRINT_HEX("TX", abtTxBuf,szTxLen+7); #endif - if (!uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+7)) { + int res; + res = uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+7); + if(res != 0) { ERR("%s", "Unable to transmit data. (TX)"); - pnd->iLastError = DEIO; + pnd->iLastError = res; return false; } szRxBufLen = 6; - if (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { + res = uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen); + if (res != 0) { ERR("%s", "Unable to receive data. (RX)"); - pnd->iLastError = DEIO; + pnd->iLastError = res; return false; } @@ -217,18 +220,22 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t PRINT_HEX("RX", abtRxBuf,szRxBufLen); #endif + // WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time if (!pn53x_transceive_callback(pnd, abtRxBuf, szRxBufLen)) return false; + szRxBufLen -= sizeof(ack_frame); + memmove(abtRxBuf, abtRxBuf+sizeof(ack_frame), szRxBufLen); - szRxBufLen = BUFFER_LENGTH; - - while (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { + if (szRxBufLen == 0) { + szRxBufLen = BUFFER_LENGTH; + do { delay_ms(10); - } - + res = uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen); + } while (res != 0 ); #ifdef DEBUG PRINT_HEX("RX", abtRxBuf,szRxBufLen); #endif + } // When the answer should be ignored, just return a successful result if(pbtRx == NULL || pszRxLen == NULL) return true; @@ -242,9 +249,10 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t #ifdef DEBUG PRINT_HEX("TX", ack_frame,6); #endif - if (!uart_send((serial_port)pnd->nds,ack_frame,6)) { + res = uart_send((serial_port)pnd->nds,ack_frame,6); + if (res != 0) { ERR("%s", "Unable to transmit data. (TX)"); - pnd->iLastError = DEIO; + pnd->iLastError = res; return false; } @@ -268,7 +276,7 @@ pn532_uart_wakeup(const nfc_device_spec_t nds) PRINT_HEX("TX", pncmd_pn532c106_wakeup_preamble,sizeof(pncmd_pn532c106_wakeup_preamble)); #endif uart_send((serial_port)nds, pncmd_pn532c106_wakeup_preamble, sizeof(pncmd_pn532c106_wakeup_preamble)); - if(uart_receive((serial_port)nds,abtRx,&szRxLen)) { + if(0 == uart_receive((serial_port)nds,abtRx,&szRxLen)) { #ifdef DEBUG PRINT_HEX("RX", abtRx,szRxLen); #endif @@ -290,10 +298,10 @@ pn532_uart_check_communication(const nfc_device_spec_t nds, bool* success) #ifdef DEBUG PRINT_HEX("TX", pncmd_communication_test,sizeof(pncmd_communication_test)); #endif - if (!uart_send((serial_port)nds, pncmd_communication_test, sizeof(pncmd_communication_test))) + if (0 != uart_send((serial_port)nds, pncmd_communication_test, sizeof(pncmd_communication_test))) return false; - if(!uart_receive((serial_port)nds,abtRx,&szRxLen)) { + if (0 != uart_receive((serial_port)nds,abtRx,&szRxLen)) { return false; } #ifdef DEBUG From 5744c6703958ce249e58409c72cea6e53e753082 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Thu, 19 Aug 2010 18:19:40 +0000 Subject: [PATCH 24/32] Fix build on Microsoft Windows (not tested, no hardware). --- libnfc/buses/uart.c | 26 ++++++++++++-------------- libnfc/drivers/pn532_uart.c | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index 0f6ecec..1b835e2 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -368,9 +368,8 @@ void uart_close(const serial_port sp) free(sp); } -void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed) +void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { - serial_port sp = (serial_port)pnd->nds; serial_port_windows* spw; DBG("Serial port speed requested to be set to %d bauds.", uiPortSpeed); @@ -396,9 +395,8 @@ void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed) } } -uint32_t uart_get_speed(const nfc_device_t* pnd) +uint32_t uart_get_speed(const serial_port sp) { - serial_port sp = (serial_port)pnd->nds; const serial_port_windows* spw = (serial_port_windows*)sp; if (!GetCommState(spw->hPort, (serial_port)&spw->dcb)) return spw->dcb.BaudRate; @@ -406,25 +404,25 @@ uint32_t uart_get_speed(const nfc_device_t* pnd) return 0; } -bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) +int uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen) { - serial_port sp = (serial_port)pnd->nds; if (!ReadFile(((serial_port_windows*)sp)->hPort,pbtRx,*pszRxLen,(LPDWORD)pszRxLen,NULL)) { - pnd->iLastError = DEIO; - return false; + return DEIO; } - return (*pszRxLen != 0); + if (!*pszRxLen) + return DEIO; + return 0; } -bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) +int uart_send(serial_port sp, const byte_t* pbtTx, const size_t szTxLen) { - serial_port sp = (serial_port)pnd->nds; DWORD dwTxLen = 0; if (!WriteFile(((serial_port_windows*)sp)->hPort,pbtTx,szTxLen,&dwTxLen,NULL)) { - pnd->iLastError = DEIO; - return false; + return DEIO; } - return (dwTxLen != 0); + if (!dwTxLen) + return DEIO; + return 0; } #endif /* _WIN32 */ diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 2bef198..d6b18de 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -177,6 +177,7 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t byte_t abtRxBuf[BUFFER_LENGTH]; size_t szRxBufLen = BUFFER_LENGTH; size_t szPos; + int res; // TODO: Move this one level up for libnfc-1.6 uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; @@ -200,7 +201,6 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t #ifdef DEBUG PRINT_HEX("TX", abtTxBuf,szTxLen+7); #endif - int res; res = uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+7); if(res != 0) { ERR("%s", "Unable to transmit data. (TX)"); From b0737bd1a08e55d015278de7843691f08e5ebf94 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Fri, 20 Aug 2010 09:36:38 +0000 Subject: [PATCH 25/32] Fix pn53x_InAutoPoll(). --- libnfc/chips/pn53x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 5987dc3..7c23a14 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -482,7 +482,7 @@ pn53x_InAutoPoll(nfc_device_t* pnd, } szRxLen = 256; - res = pnd->pdc->transceive(pnd->nds, pbtTxInAutoPoll, szTxInAutoPoll, abtRx, &szRxLen); + res = pnd->pdc->transceive(pnd, pbtTxInAutoPoll, szTxInAutoPoll, abtRx, &szRxLen); if((szRxLen == 0)||(res == false)) { return false; From f4aa4edc947a429847b1ccfd5d8695865a58d57b Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Fri, 20 Aug 2010 10:06:19 +0000 Subject: [PATCH 26/32] Rework and fix error frames detection. While here, rename the pn53x_transceive_callback() function to pn53x_transceive_check_ack_frame_callback() to make it more obvious what it is supposed to do. --- libnfc/chips/pn53x.c | 16 +++++++++++++++- libnfc/chips/pn53x.h | 3 ++- libnfc/drivers/pn53x_usb.c | 8 ++++---- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 7c23a14..2ea3d49 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -68,9 +68,10 @@ const byte_t pncmd_target_get_status [ 2] = { 0xD4,0x8A }; static const byte_t pn53x_ack_frame[] = { 0x00,0x00,0xff,0x00,0xff,0x00 }; static const byte_t pn53x_nack_frame[] = { 0x00,0x00,0xff,0xff,0x00,0x00 }; +static const byte_t pn53x_error_frame[] = { 0x00,0x00,0xff,0x01,0xff,0x7f,0x81,0x00 }; // XXX: Is this function correctly named ? -bool pn53x_transceive_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen) +bool pn53x_transceive_check_ack_frame_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen) { if (szRxFrameLen >= sizeof (pn53x_ack_frame)) { if (0 == memcmp (pbtRxFrame, pn53x_ack_frame, sizeof (pn53x_ack_frame))) { @@ -93,6 +94,19 @@ bool pn53x_transceive_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, cons return false; } +bool pn53x_transceive_check_error_frame_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen) +{ + if (szRxFrameLen >= sizeof (pn53x_error_frame)) { + if (0 == memcmp (pbtRxFrame, pn53x_error_frame, sizeof (pn53x_error_frame))) { + DBG("%s", "PN53x sent an error frame"); + pnd->iLastError = DEISERRFRAME; + return false; + } + } + + return true; +} + bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index 8dea5e8..9d976d8 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -74,7 +74,8 @@ #define DEACKMISMATCH 0x0200 /* Unexpected data */ #define DEISERRFRAME 0x0300 /* Error frame */ -bool pn53x_transceive_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen); +bool pn53x_transceive_check_ack_frame_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen); +bool pn53x_transceive_check_error_frame_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen); bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); byte_t pn53x_get_reg(nfc_device_t* pnd, uint16_t ui16Reg); bool pn53x_set_reg(nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value); diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 0316719..7cde7c0 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -285,7 +285,7 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s PRINT_HEX("RX", abtRx,ret); #endif - if (!pn53x_transceive_callback (pnd, abtRx, ret)) + if (!pn53x_transceive_check_ack_frame_callback (pnd, abtRx, ret)) return false; ret = usb_bulk_read(pus->pudh, pus->uiEndPointIn, (char*)abtRx, BUFFER_LENGTH, USB_TIMEOUT); @@ -305,6 +305,9 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s #endif usb_bulk_write(pus->pudh, pus->uiEndPointOut, (char *)ack_frame, 6, USB_TIMEOUT); + if (!pn53x_transceive_check_error_frame_callback (pnd, abtRx, ret)) + return false; + // When the answer should be ignored, just return a succesful result if(pbtRx == NULL || pszRxLen == NULL) return true; @@ -329,8 +332,5 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s memcpy( pbtRx, abtRx + 7, *pszRxLen); - if (abtRx[5] != pbtTx[0] + 1) { - pnd->iLastError = DEISERRFRAME; - } return true; } From 084c001c11544c01b93810e0d400277b015227f0 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Fri, 20 Aug 2010 10:11:06 +0000 Subject: [PATCH 27/32] Generate an error before sending InAutoPoll command if chip does not support it. --- libnfc/chips/pn53x.c | 12 +++++++----- libnfc/chips/pn53x.h | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 2ea3d49..38fd778 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -475,12 +475,13 @@ pn53x_InAutoPoll(nfc_device_t* pnd, nfc_target_t* pntTargets, size_t* pszTargetFound) { size_t szTxInAutoPoll, n, szRxLen; - byte_t abtRx[256]; + byte_t abtRx[MAX_FRAME_LEN]; bool res; byte_t *pbtTxInAutoPoll; - if(pnd->nc == NC_PN531) { - // TODO This function is not supported by pn531 (set errno = ENOSUPP or similar) + if(pnd->nc != NC_PN532) { + // This function is not supported by pn531 neither pn533 + pnd->iLastError = DENOTSUP; return false; } @@ -495,7 +496,7 @@ pn53x_InAutoPoll(nfc_device_t* pnd, pbtTxInAutoPoll[4+n] = pnttTargetTypes[n]; } - szRxLen = 256; + szRxLen = MAX_FRAME_LEN; res = pnd->pdc->transceive(pnd, pbtTxInAutoPoll, szTxInAutoPoll, abtRx, &szRxLen); if((szRxLen == 0)||(res == false)) { @@ -569,7 +570,8 @@ static struct sErrorMessage { /* TODO: Move me in more generic code for libnfc 1.6 */ { DEINVAL, "Invalid argument" }, { DEIO, "Input/output error" }, - { DETIMEOUT, "Operation timed-out" } + { DETIMEOUT, "Operation timed-out" }, + { DENOTSUP, "Operation not supported" } }; const char * diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index 9d976d8..4de277a 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -73,6 +73,7 @@ #define DENACK 0x0100 /* NACK */ #define DEACKMISMATCH 0x0200 /* Unexpected data */ #define DEISERRFRAME 0x0300 /* Error frame */ +#define DENOTSUP 0x0400 /* Not supported */ bool pn53x_transceive_check_ack_frame_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen); bool pn53x_transceive_check_error_frame_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen); From 1e329529a7ed13cd48cc929429f345398d5df1b6 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Fri, 20 Aug 2010 10:16:52 +0000 Subject: [PATCH 28/32] Update nfc-poll example to enhance unsupported features detection. --- examples/nfc-poll.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index b2426d3..d8aacf6 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -117,12 +117,6 @@ main (int argc, const char *argv[]) printf ("Connected to NFC reader: %s\n", pnd->acName); - if (pnd->nc == NC_PN531) { - // PN531 doesn't support hardware polling (InAutoPoll) - // TODO find a way to handle this in higher level (i.e. libnfc) - WARN ("%s", "PN531 doesn't support hardware polling."); - continue; - } printf ("PN53x will poll during %ld ms\n", (unsigned long) btPollNr * szTargetTypes * btPeriod * 150); res = nfc_initiator_poll_targets (pnd, &nttMifare, 1, btPollNr, btPeriod, antTargets, &szTargetFound); if (res) { @@ -134,7 +128,8 @@ main (int argc, const char *argv[]) print_nfc_iso14443a_info (antTargets[n].nti.nai); } } else { - ERR ("%s", "Polling failed."); + nfc_perror (pnd, "nfc_initiator_poll_targets"); + exit (EXIT_FAILURE); } nfc_disconnect (pnd); From bd8a46c3c863eaf687aa17abd83d80b7b20f13b5 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Fri, 20 Aug 2010 10:25:37 +0000 Subject: [PATCH 29/32] Fix pn532_uart compilation --- libnfc/drivers/pn532_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index d6b18de..88d01f5 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -221,7 +221,7 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t #endif // WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time - if (!pn53x_transceive_callback(pnd, abtRxBuf, szRxBufLen)) + if (!pn53x_transceive_check_ack_frame_callback(pnd, abtRxBuf, szRxBufLen)) return false; szRxBufLen -= sizeof(ack_frame); memmove(abtRxBuf, abtRxBuf+sizeof(ack_frame), szRxBufLen); From dadaee4cc022ea2e694f9b069fd8825233ad2ddf Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Fri, 20 Aug 2010 10:28:11 +0000 Subject: [PATCH 30/32] Fix ARYGON compilation --- libnfc/drivers/arygon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 4b5ffa6..770f049 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -224,7 +224,7 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx PRINT_HEX("RX", abtRxBuf,szRxBufLen); #endif - if (!pn53x_transceive_callback(pnd, abtRxBuf, szRxBufLen)) + if (!pn53x_transceive_check_ack_frame_callback(pnd, abtRxBuf, szRxBufLen)) return false; szRxBufLen = BUFFER_LENGTH; From fd337dd0ccadd1bed36475409172009c610388d1 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Fri, 20 Aug 2010 10:40:00 +0000 Subject: [PATCH 31/32] Also detect error frames in pn532_uart (tested) and arygon drivers (not tested). --- libnfc/drivers/arygon.c | 14 +++++++++----- libnfc/drivers/pn532_uart.c | 20 ++++++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 770f049..4d5c8bf 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -237,11 +237,6 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx PRINT_HEX("RX", abtRxBuf,szRxBufLen); #endif - // When the answer should be ignored, just return a successful result - if(pbtRx == NULL || pszRxLen == NULL) return true; - - // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) - if(szRxBufLen < 9) return false; #ifdef DEBUG PRINT_HEX("TX", ack_frame, 6); @@ -251,6 +246,15 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx return false; } + if (!pn53x_transceive_check_error_frame_callback(pnd, abtRxBuf, szRxBufLen)) + return false; + + // When the answer should be ignored, just return a successful result + if(pbtRx == NULL || pszRxLen == NULL) return true; + + // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) + if(szRxBufLen < 9) return false; + // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable) *pszRxLen = szRxBufLen - 9; memcpy(pbtRx, abtRxBuf+7, *pszRxLen); diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 88d01f5..982cd82 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -237,14 +237,6 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t #endif } - // When the answer should be ignored, just return a successful result - if(pbtRx == NULL || pszRxLen == NULL) return true; - - // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) - if(szRxBufLen < 9) { - pnd->iLastError = DEINVAL; - return false; - } #ifdef DEBUG PRINT_HEX("TX", ack_frame,6); @@ -256,6 +248,18 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t return false; } + if (!pn53x_transceive_check_error_frame_callback (pnd, abtRxBuf, szRxBufLen)) + return false; + + // When the answer should be ignored, just return a successful result + if(pbtRx == NULL || pszRxLen == NULL) return true; + + // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) + if(szRxBufLen < 9) { + pnd->iLastError = DEINVAL; + return false; + } + // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable) *pszRxLen = szRxBufLen - 9; memcpy(pbtRx, abtRxBuf+7, *pszRxLen); From 6a6ae42a97c9675168819720935e1429d1742ec9 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Fri, 20 Aug 2010 10:42:31 +0000 Subject: [PATCH 32/32] Fix minor compilation warnings --- libnfc/drivers/arygon.c | 2 +- libnfc/drivers/pn532_uart.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 4d5c8bf..ffa70b6 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -113,7 +113,7 @@ arygon_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *p const char* pcPort; int iDevice = 0; - while( pcPort = pcPorts[iDevice++] ) { + while( (pcPort = pcPorts[iDevice++]) ) { sp = uart_open(pcPort); DBG("Trying to find ARYGON device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED); diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 982cd82..657cc1d 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -88,7 +88,7 @@ pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_ const char* pcPort; int iDevice = 0; - while( pcPort = pcPorts[iDevice++] ) { + while( (pcPort = pcPorts[iDevice++]) ) { sp = uart_open(pcPort); DBG("Trying to find PN532 device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);