Start of work on error handling.

This commit is contained in:
Romain Tartiere 2010-07-26 12:41:46 +00:00
parent 9a7ffc38a1
commit 9984e1bdcb
7 changed files with 109 additions and 31 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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__

View file

@ -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));