From ad530f6d026d5b798a34060b147128e1017e94c8 Mon Sep 17 00:00:00 2001 From: Romain Tartiere Date: Wed, 9 Mar 2011 13:37:16 +0000 Subject: [PATCH] Various cleanups. - New functions nfc_device_new(), nfc_device_free(); - Add experimental abort mechanism for the PN53x USB driver; - Move chip-specific variables from nfc_device_t to pn53x_data (Fixes Issue 124). --- include/nfc/nfc-types.h | 7 --- libnfc/Makefile.am | 2 +- libnfc/chips/pn53x.c | 29 +++++----- libnfc/chips/pn53x.h | 6 +++ libnfc/drivers/acr122.c | 10 ++-- libnfc/drivers/arygon.c | 82 ++++++++++++++-------------- libnfc/drivers/pn532_uart.c | 44 +++++++-------- libnfc/drivers/pn53x_usb.c | 103 ++++++++++++++++++------------------ libnfc/nfc-device.c | 35 ++++++++++++ libnfc/nfc-internal.h | 6 +++ 10 files changed, 181 insertions(+), 143 deletions(-) create mode 100644 libnfc/nfc-device.c diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 76d484d..2bddb7e 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -55,10 +55,6 @@ typedef struct { bool bEasyFraming; /** Should the PN53x chip switch automatically in ISO14443-4 when ISO14443 */ bool bAutoIso14443_4; -/** Register cache for REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS: The last TX bits setting, we need to reset this if it does not apply anymore */ - uint8_t ui8TxBits; -/** Register cache for SetParameters function. */ - uint8_t ui8Parameters; /** Supported modulation encoded in a byte */ byte_t btSupportByte; /** Last error reported by the PCD / encountered by the PCD driver @@ -70,11 +66,8 @@ typedef struct { * +----------- Driver-level general error (common to all drivers) */ int iLastError; -/** Last sent command */ - int iLastCommand; int iAbortFds[2]; } nfc_device_t; -// TODO: Move chip's specifics in a chips structure (e.g. iLastCommand, ui8Parameters, ui8TxBits) /** * @struct nfc_device_desc_t diff --git a/libnfc/Makefile.am b/libnfc/Makefile.am index f271671..e56f8dd 100644 --- a/libnfc/Makefile.am +++ b/libnfc/Makefile.am @@ -5,7 +5,7 @@ INCLUDES = $(all_includes) $(LIBNFC_CFLAGS) noinst_HEADERS = drivers.h mirror-subr.h nfc-internal.h lib_LTLIBRARIES = libnfc.la -libnfc_la_SOURCES = nfc.c iso14443-subr.c mirror-subr.c +libnfc_la_SOURCES = nfc.c iso14443-subr.c mirror-subr.c nfc-device.c libnfc_la_LDFLAGS = -no-undefined -version-info 1:0:0 libnfc_la_CFLAGS = @DRIVERS_CFLAGS@ libnfc_la_LIBADD = \ diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 918c052..3b98093 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -49,6 +49,8 @@ #include +#define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data)) + // TODO: reorder functions according to header // TODO: Count max bytes for InJumpForDEP reply @@ -78,7 +80,7 @@ pn53x_init(nfc_device_t * pnd) pnd->bPar = true; // Reset the ending transmission bits register, it is unknown what the last tranmission used there - pnd->ui8TxBits = 0; + CHIP_DATA (pnd)->ui8TxBits = 0; if (!pn53x_write_register (pnd, REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS, 0x00)) { return false; } @@ -145,6 +147,9 @@ pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, b return false; } + if (pnd->iLastError) + return false; + *pszRx = (size_t) res; switch (pbtTx[0]) { @@ -221,8 +226,8 @@ pn53x_write_register (nfc_device_t * pnd, const uint16_t ui16Reg, const uint8_t bool pn53x_set_parameters (nfc_device_t * pnd, const uint8_t ui8Parameter, const bool bEnable) { - uint8_t ui8Value = (bEnable) ? (pnd->ui8Parameters | ui8Parameter) : (pnd->ui8Parameters & ~(ui8Parameter)); - if (ui8Value != pnd->ui8Parameters) { + uint8_t ui8Value = (bEnable) ? (CHIP_DATA (pnd)->ui8Parameters | ui8Parameter) : (CHIP_DATA (pnd)->ui8Parameters & ~(ui8Parameter)); + if (ui8Value != CHIP_DATA (pnd)->ui8Parameters) { return pn53x_SetParameters(pnd, ui8Value); } return true; @@ -237,7 +242,7 @@ pn53x_SetParameters (nfc_device_t * pnd, const uint8_t ui8Value) return false; } // We save last parameters in register cache - pnd->ui8Parameters = ui8Value; + CHIP_DATA (pnd)->ui8Parameters = ui8Value; return true; } @@ -245,13 +250,13 @@ bool pn53x_set_tx_bits (nfc_device_t * pnd, const uint8_t ui8Bits) { // Test if we need to update the transmission bits register setting - if (pnd->ui8TxBits != ui8Bits) { + if (CHIP_DATA (pnd)->ui8TxBits != ui8Bits) { // Set the amount of transmission bits in the PN53X chip register if (!pn53x_write_register (pnd, REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS, ui8Bits)) return false; // Store the new setting - ((nfc_device_t *) pnd)->ui8TxBits = ui8Bits; + CHIP_DATA (pnd)->ui8TxBits = ui8Bits; } return true; } @@ -1416,10 +1421,6 @@ pn53x_TgInitAsTarget (nfc_device_t * pnd, pn53x_target_mode_t ptm, if (!pn53x_transceive (pnd, abtCmd, 36 + szOptionalBytes, abtRx, &szRx)) return false; - if (szRx == 0) { - return false; // transceive was aborted - } - // Note: the first byte is skip: // its the "mode" byte which contains baudrate, DEP and Framing type (Mifare, active or FeliCa) datas. if(pbtModeByte) { @@ -1474,7 +1475,9 @@ pn53x_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRx) { byte_t abtCmd[1]; - if (pnd->bEasyFraming) { + // FIXME In DEP mode we MUST use TgGetData but we don't known the current mode. + // DEP mode && EasyFramming || EasyFramming && ISO14443-4 && PN532 + if (pnd->bEasyFraming && (CHIP_DATA(pnd)->type == PN532)) { abtCmd[0] = TgGetData; } else { abtCmd[0] = TgGetInitiatorCommand; @@ -1489,6 +1492,8 @@ pn53x_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRx) // Save the received byte count *pszRx = szRx - 1; + // FIXME szRx can be 0 + // Copy the received bytes memcpy (pbtRx, abtRx + 1, *pszRx); @@ -1543,7 +1548,7 @@ pn53x_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t if (!pnd->bPar) return false; - if (pnd->bEasyFraming) { + if (pnd->bEasyFraming && (CHIP_DATA(pnd)->type == PN532)) { abtCmd[0] = TgSetData; } else { abtCmd[0] = TgResponseToInitiator; diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index 54914c8..b92ed21 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -125,6 +125,12 @@ struct pn53x_data { pn53x_type type; pn53x_state state; const struct pn53x_io * io; +/** Register cache for REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS: The last TX bits setting, we need to reset this if it does not apply anymore */ + uint8_t ui8TxBits; +/** Register cache for SetParameters function. */ + uint8_t ui8Parameters; +/** Last sent command */ + uint8_t ui8LastCommand; }; /* PN53x specific types */ diff --git a/libnfc/drivers/acr122.c b/libnfc/drivers/acr122.c index 1f7bc33..ef9c02a 100644 --- a/libnfc/drivers/acr122.c +++ b/libnfc/drivers/acr122.c @@ -194,7 +194,7 @@ nfc_device_t * acr122_connect (const nfc_device_desc_t * pndd) { char *pcFirmware; - nfc_device_t *pnd = malloc (sizeof (*pnd)); + nfc_device_t *pnd = nfc_device_new (); pnd->driver_data = malloc (sizeof (struct acr122_data)); pnd->chip_data = malloc (sizeof (struct pn53x_data)); @@ -233,9 +233,7 @@ acr122_connect (const nfc_device_desc_t * pndd) } error: - free (pnd->driver_data); - free (pnd->chip_data); - free (pnd); + nfc_device_free (pnd); return NULL; } @@ -246,9 +244,7 @@ acr122_disconnect (nfc_device_t * pnd) SCardDisconnect (DRIVER_DATA (pnd)->hCard, SCARD_LEAVE_CARD); acr122_free_scardcontext (); - free (pnd->driver_data); - free (pnd->chip_data); - free (pnd); + nfc_device_free (pnd); } bool diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 04b98c5..70de471 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -65,6 +65,9 @@ #define ARYGON_DEFAULT_SPEED 9600 #define ARYGON_DRIVER_NAME "ARYGON" +#define DRIVER_DATA(pnd) ((struct arygon_data*)(pnd->driver_data)) +#define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data)) + const struct pn53x_io arygon_tama_io; struct arygon_data { @@ -105,18 +108,17 @@ arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) { uart_set_speed (sp, ARYGON_DEFAULT_SPEED); - nfc_device_t nd; - nd.driver = &arygon_driver; - nd.driver_data = malloc(sizeof(struct arygon_data)); - ((struct arygon_data*)(nd.driver_data))->port = sp; - nd.chip_data = malloc(sizeof(struct pn53x_data)); - ((struct pn53x_data*)(nd.chip_data))->type = PN532; - ((struct pn53x_data*)(nd.chip_data))->state = NORMAL; - ((struct pn53x_data*)(nd.chip_data))->io = &arygon_tama_io; + nfc_device_t *pnd = nfc_device_new (); + pnd->driver = &arygon_driver; + pnd->driver_data = malloc(sizeof(struct arygon_data)); + DRIVER_DATA (pnd)->port = sp; + pnd->chip_data = malloc(sizeof(struct pn53x_data)); + CHIP_DATA (pnd)->type = PN532; + CHIP_DATA (pnd)->state = NORMAL; + CHIP_DATA (pnd)->io = &arygon_tama_io; - bool res = arygon_reset_tama(&nd); - free(nd.driver_data); - free(nd.chip_data); + bool res = arygon_reset_tama (pnd); + nfc_device_free (pnd); uart_close (sp); if(!res) continue; @@ -164,23 +166,21 @@ arygon_connect (const nfc_device_desc_t * pndd) uart_set_speed (sp, pndd->uiSpeed); // We have a connection - pnd = malloc (sizeof (nfc_device_t)); - strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1); + pnd = nfc_device_new (); + strncpy (pnd->acName, pndd->acDevice, sizeof (pnd->acName)); pnd->driver_data = malloc(sizeof(struct arygon_data)); - ((struct arygon_data*)(pnd->driver_data))->port = sp; + DRIVER_DATA (pnd)->port = sp; pnd->chip_data = malloc(sizeof(struct pn53x_data)); // The PN53x chip connected to ARYGON MCU doesn't seems to be in SLEEP mode - ((struct pn53x_data*)(pnd->chip_data))->state = NORMAL; - ((struct pn53x_data*)(pnd->chip_data))->io = &arygon_tama_io; + CHIP_DATA (pnd)->state = NORMAL; + CHIP_DATA (pnd)->io = &arygon_tama_io; pnd->driver = &arygon_driver; // Check communication using "Reset TAMA" command if (!arygon_reset_tama(pnd)) { - free(pnd->driver_data); - free(pnd->chip_data); - free(pnd); + nfc_device_free (pnd); return NULL; } @@ -191,10 +191,8 @@ arygon_connect (const nfc_device_desc_t * pndd) void arygon_disconnect (nfc_device_t * pnd) { - uart_close (((struct arygon_data*)(pnd->driver_data))->port); - free(pnd->driver_data); - free(pnd->chip_data); - free (pnd); + uart_close (DRIVER_DATA (pnd)->port); + nfc_device_free (pnd); } #define ARYGON_TX_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD + 1) @@ -204,11 +202,11 @@ arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szDat { byte_t abtFrame[ARYGON_TX_BUFFER_LEN] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "0x32 0x00 0x00 0xff" - pnd->iLastCommand = pbtData[0]; + CHIP_DATA (pnd)->ui8LastCommand = pbtData[0]; size_t szFrame = 0; pn53x_build_frame (abtFrame + 1, &szFrame, pbtData, szData); - int res = uart_send (((struct arygon_data*)(pnd->driver_data))->port, abtFrame, szFrame + 1); + int res = uart_send (DRIVER_DATA (pnd)->port, abtFrame, szFrame + 1); if (res != 0) { ERR ("%s", "Unable to transmit data. (TX)"); pnd->iLastError = res; @@ -216,7 +214,7 @@ arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szDat } byte_t abtRxBuf[6]; - res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, sizeof (abtRxBuf), 0); + res = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, sizeof (abtRxBuf), 0); if (res != 0) { ERR ("%s", "Unable to read ACK"); pnd->iLastError = res; @@ -224,7 +222,7 @@ arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szDat } if (pn53x_check_ack_frame (pnd, abtRxBuf, sizeof(abtRxBuf))) { - ((struct pn53x_data*)(pnd->chip_data))->state = EXECUTE; + CHIP_DATA (pnd)->state = EXECUTE; } else if (0 == memcmp(arygon_error_unknown_mode, abtRxBuf, sizeof(abtRxBuf))) { ERR( "Bad frame format." ); return false; @@ -237,12 +235,12 @@ arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szDat int arygon_abort (nfc_device_t *pnd) { - ((struct pn53x_data*)(pnd->chip_data))->state = NORMAL; + CHIP_DATA (pnd)->state = NORMAL; // Send a valid TAMA packet to wakup the PN53x (we will not have an answer, according to Arygon manual) byte_t dummy[] = { 0x32, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0xbe, 0x00 }; - uart_send (((struct arygon_data*)(pnd->driver_data))->port, dummy, sizeof (dummy)); + uart_send (DRIVER_DATA (pnd)->port, dummy, sizeof (dummy)); // Using Arygon device we can't send ACK frame to abort the running command return (pn53x_check_communication (pnd)) ? 0 : -1; @@ -255,7 +253,7 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe size_t len; int abort_fd = 0; - switch (pnd->iLastCommand) { + switch (CHIP_DATA (pnd)->ui8LastCommand) { case InAutoPoll: case TgInitAsTarget: case TgGetData: @@ -265,7 +263,7 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe break; } - int res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, 5, abort_fd); + int res = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 5, abort_fd); if (abort_fd && (DEABORT == res)) { return arygon_abort (pnd); @@ -286,7 +284,7 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe if ((0x01 == abtRxBuf[3]) && (0xff == abtRxBuf[4])) { // Error frame - uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, 3, 0); + uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 3, 0); ERR ("%s", "Application level error detected"); pnd->iLastError = DEISERRFRAME; return -1; @@ -314,7 +312,7 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe } // TFI + PD0 (CC+1) - res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, 2, 0); + res = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0); if (res != 0) { ERR ("%s", "Unable to receive data. (RX)"); pnd->iLastError = res; @@ -327,14 +325,14 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe return -1; } - if (abtRxBuf[1] != pnd->iLastCommand + 1) { + if (abtRxBuf[1] != CHIP_DATA (pnd)->ui8LastCommand + 1) { ERR ("%s", "Command Code verification failed"); pnd->iLastError = DEIO; return -1; } if (len) { - res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, pbtData, len, 0); + res = uart_receive (DRIVER_DATA (pnd)->port, pbtData, len, 0); if (res != 0) { ERR ("%s", "Unable to receive data. (RX)"); pnd->iLastError = res; @@ -342,7 +340,7 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe } } - res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, 2, 0); + res = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0); if (res != 0) { ERR ("%s", "Unable to receive data. (RX)"); pnd->iLastError = res; @@ -350,7 +348,7 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe } byte_t btDCS = (256 - 0xD5); - btDCS -= pnd->iLastCommand + 1; + btDCS -= CHIP_DATA (pnd)->ui8LastCommand + 1; for (size_t szPos = 0; szPos < len; szPos++) { btDCS -= pbtData[szPos]; } @@ -366,7 +364,7 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe pnd->iLastError = DEIO; return -1; } - ((struct pn53x_data*)(pnd->chip_data))->state = NORMAL; + CHIP_DATA (pnd)->state = NORMAL; return len; } @@ -378,12 +376,12 @@ arygon_firmware (nfc_device_t * pnd, char * str) size_t szRx = sizeof(abtRx); - int res = uart_send (((struct arygon_data*)(pnd->driver_data))->port, arygon_firmware_version_cmd, sizeof (arygon_firmware_version_cmd)); + int res = uart_send (DRIVER_DATA (pnd)->port, arygon_firmware_version_cmd, sizeof (arygon_firmware_version_cmd)); if (res != 0) { DBG ("Unable to send ARYGON firmware command."); return; } - res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRx, szRx, 0); + res = uart_receive (DRIVER_DATA (pnd)->port, abtRx, szRx, 0); if (res != 0) { DBG ("Unable to retrieve ARYGON firmware version."); return; @@ -406,11 +404,11 @@ arygon_reset_tama (nfc_device_t * pnd) size_t szRx = sizeof(abtRx); int res; - uart_send (((struct arygon_data*)(pnd->driver_data))->port, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd)); + uart_send (DRIVER_DATA (pnd)->port, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd)); // Two reply are possible from ARYGON device: arygon_error_none (ie. in case the byte is well-sent) // or arygon_error_unknown_mode (ie. in case of the first byte was bad-transmitted) - res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRx, szRx, 0); + res = uart_receive (DRIVER_DATA (pnd)->port, abtRx, szRx, 0); if (res != 0) { DBG ("No reply to 'reset TAMA' command."); return false; diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 5a70287..736c057 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -88,25 +88,26 @@ pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps // Serial port claimed but we need to check if a PN532_UART is connected. uart_set_speed (sp, PN532_UART_DEFAULT_SPEED); - nfc_device_t nd; - nd.driver = &pn532_uart_driver; - nd.driver_data = malloc(sizeof(struct pn532_uart_data)); - ((struct pn532_uart_data*)(nd.driver_data))->port = sp; - nd.chip_data = malloc(sizeof(struct pn53x_data)); - ((struct pn53x_data*)(nd.chip_data))->type = PN532; - ((struct pn53x_data*)(nd.chip_data))->state = SLEEP; - ((struct pn53x_data*)(nd.chip_data))->io = &pn532_uart_io; + nfc_device_t *pnd = nfc_device_new (); + pnd->iLastError = 0; + pnd->driver = &pn532_uart_driver; + pnd->driver_data = malloc(sizeof(struct pn532_uart_data)); + DRIVER_DATA (pnd)->port = sp; + pnd->chip_data = malloc(sizeof(struct pn53x_data)); + CHIP_DATA (pnd)->type = PN532; + CHIP_DATA (pnd)->state = SLEEP; + CHIP_DATA (pnd)->io = &pn532_uart_io; - - // PN532 could be powered down, we need to wake it up before line testing. - // TODO pn532_uart_wakeup ((nfc_device_spec_t) sp); // Check communication using "Diagnose" command, with "Communication test" (0x00) - bool res = pn53x_check_communication (&nd); - free(nd.driver_data); - free(nd.chip_data); + bool res = pn53x_check_communication (pnd); + if(!res) { + nfc_perror (pnd, "pn53x_check_communication"); + } + nfc_device_free (pnd); uart_close (sp); - if(!res) + if(!res) { continue; + } snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", pcPort); pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME; @@ -164,6 +165,7 @@ pn532_uart_connect (const nfc_device_desc_t * pndd) // Check communication using "Diagnose" command, with "Communication test" (0x00) if (!pn53x_check_communication (pnd)) { + nfc_perror (pnd, "pn53x_check_communication"); pn532_uart_disconnect(pnd); return NULL; } @@ -176,9 +178,7 @@ void pn532_uart_disconnect (nfc_device_t * pnd) { uart_close (DRIVER_DATA(pnd)->port); - free (pnd->driver_data); - free (pnd->chip_data); - free (pnd); + nfc_device_free (pnd); } #define PN532_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD) @@ -198,7 +198,7 @@ pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData } byte_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" - pnd->iLastCommand = pbtData[0]; + CHIP_DATA (pnd)->ui8LastCommand = pbtData[0]; size_t szFrame = 0; pn53x_build_frame (abtFrame, &szFrame, pbtData, szData); @@ -233,7 +233,7 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen size_t len; int abort_fd = 0; - switch (pnd->iLastCommand) { + switch (CHIP_DATA (pnd)->ui8LastCommand) { case InAutoPoll: case TgInitAsTarget: case TgGetData: @@ -305,7 +305,7 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen return -1; } - if (abtRxBuf[1] != pnd->iLastCommand + 1) { + if (abtRxBuf[1] != CHIP_DATA (pnd)->ui8LastCommand + 1) { ERR ("%s", "Command Code verification failed"); pnd->iLastError = DEIO; return -1; @@ -328,7 +328,7 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen } byte_t btDCS = (256 - 0xD5); - btDCS -= pnd->iLastCommand + 1; + btDCS -= CHIP_DATA (pnd)->ui8LastCommand + 1; for (size_t szPos = 0; szPos < len; szPos++) { btDCS -= pbtData[szPos]; } diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 09654dc..ee7eb22 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -21,7 +21,7 @@ /** * @file pn53x_usb.c - * @brief Driver common routines for PN53x chips using USB + * @brief Driver for PN53x using USB */ #ifdef HAVE_CONFIG_H @@ -32,6 +32,8 @@ Thanks to d18c7db and Okko for example code */ +#include +#include #include #include #include @@ -72,9 +74,18 @@ bool pn53x_usb_get_usb_device_name (struct usb_device *dev, usb_dev_handle *udev int pn53x_usb_bulk_read (struct pn53x_usb_data *data, byte_t abtRx[], const size_t szRx) { - int ret = usb_bulk_read (data->pudh, data->uiEndPointIn, (char *) abtRx, szRx, USB_TIMEOUT); - PRINT_HEX ("RX", abtRx, ret); - return ret; + int res = usb_bulk_read (data->pudh, data->uiEndPointIn, (char *) abtRx, szRx, USB_TIMEOUT); + PRINT_HEX ("RX", abtRx, res); + return res; +} +int + +pn53x_usb_bulk_read_ex (struct pn53x_usb_data *data, byte_t abtRx[], const size_t szRx, int timeout) +{ + int res = usb_bulk_read (data->pudh, data->uiEndPointIn, (char *) abtRx, szRx, timeout); + if (res > 0) + PRINT_HEX ("RX", abtRx, res); + return res; } int @@ -267,7 +278,7 @@ pn53x_usb_connect (const nfc_device_desc_t *pndd) } data.model = pn53x_usb_get_device_model (dev->descriptor.idVendor, dev->descriptor.idProduct); // Allocate memory for the device info and specification, fill it and return the info - pnd = malloc (sizeof (nfc_device_t)); + pnd = nfc_device_new (); pn53x_usb_get_usb_device_name (dev, data.pudh, pnd->acName, sizeof (pnd->acName)); pnd->driver_data = malloc(sizeof(struct pn53x_usb_data)); @@ -283,46 +294,10 @@ pn53x_usb_connect (const nfc_device_desc_t *pndd) // HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device // in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do -#if 1 if (!pn53x_init (pnd)) { usb_close (data.pudh); goto error; } -#else - byte_t abtTx[] = { 0x00, 0x00, 0xff, 0x02, 0xfe, 0xd4, 0x02, 0x2a, 0x00 }; - byte_t abtRx[BUFFER_LENGTH]; - int ret; - - ret = pn53x_usb_bulk_write (data, abtTx, sizeof(abtTx)); - if (ret < 0) { - DBG ("usb_bulk_write failed with error %d", ret); - usb_close (data.pudh); - // we failed to use the specified device - goto error; - } - ret = pn53x_usb_bulk_read (data, (char *) abtRx, s); - if (ret < 0) { - DBG ("usb_bulk_read failed with error %d", ret); - usb_close (us.pudh); - // we failed to use the specified device - goto error; - } - if (ret == 6) { // we got the ACK/NACK properly - if (!pn53x_check_ack_frame (pnd, abtRx, ret)) { - DBG ("pn53x_check_ack_frame failed"); - usb_close (us.pudh); - // we failed to use the specified device - goto error; - } - ret = pn53x_usb_bulk_read (data, (char *) abtRx, BUFFER_LENGTH); - if (ret < 0) { - DBG ("usb_bulk_read failed with error %d", ret); - usb_close (us.pudh); - // we failed to use the specified device - goto error; - } - } -#endif return pnd; } } @@ -332,9 +307,7 @@ pn53x_usb_connect (const nfc_device_desc_t *pndd) error: // Free allocated structure on error. - free(pnd->driver_data); - free(pnd->chip_data); - free(pnd); + nfc_device_free (pnd); return NULL; } @@ -352,9 +325,7 @@ pn53x_usb_disconnect (nfc_device_t * pnd) if ((res = usb_close (DRIVER_DATA (pnd)->pudh)) < 0) { ERR ("usb_close failed (%i)", res); } - free(pnd->driver_data); - free(pnd->chip_data); - free(pnd); + nfc_device_free (pnd); } #define PN53X_USB_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD) @@ -363,7 +334,7 @@ bool pn53x_usb_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData) { byte_t abtFrame[PN53X_USB_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" - pnd->iLastCommand = pbtData[0]; + CHIP_DATA (pnd)->ui8LastCommand = pbtData[0]; size_t szFrame = 0; pn53x_build_frame (abtFrame, &szFrame, pbtData, szData); @@ -406,7 +377,7 @@ pn53x_usb_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen) off_t offset = 0; int abort_fd = 0; - switch (pnd->iLastCommand) { + switch (CHIP_DATA (pnd)->ui8LastCommand) { case InAutoPoll: case TgInitAsTarget: case TgGetData: @@ -417,7 +388,35 @@ pn53x_usb_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen) } byte_t abtRxBuf[PN53X_USB_BUFFER_LEN]; - int res = pn53x_usb_bulk_read (DRIVER_DATA (pnd), abtRxBuf, sizeof (abtRxBuf)); + int res; + +read: + res = pn53x_usb_bulk_read_ex (DRIVER_DATA (pnd), abtRxBuf, sizeof (abtRxBuf), 250); + + if (res == -ETIMEDOUT) { + struct timeval tv = { + .tv_sec = 0, + .tv_usec = 0, + }; + + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(abort_fd, &readfds); + switch (select (abort_fd + 1, &readfds, NULL, NULL, &tv)) { + case -1: + // An error occured + return false; + break; + case 0: + // Timeout + goto read; + break; + case 1: + return (pn53x_usb_ack (pnd) >= 0) ? true : false; + break; + } + } + if (res < 0) { DBG ("usb_bulk_read failed with error %d", res); pnd->iLastError = DEIO; @@ -474,7 +473,7 @@ pn53x_usb_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen) } offset += 1; - if (abtRxBuf[offset] != pnd->iLastCommand + 1) { + if (abtRxBuf[offset] != CHIP_DATA (pnd)->ui8LastCommand + 1) { ERR ("%s", "Command Code verification failed"); pnd->iLastError = DEIO; return -1; @@ -485,7 +484,7 @@ pn53x_usb_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen) offset += len; byte_t btDCS = (256 - 0xD5); - btDCS -= pnd->iLastCommand + 1; + btDCS -= CHIP_DATA (pnd)->ui8LastCommand + 1; for (size_t szPos = 0; szPos < len; szPos++) { btDCS -= pbtData[szPos]; } diff --git a/libnfc/nfc-device.c b/libnfc/nfc-device.c new file mode 100644 index 0000000..567fc75 --- /dev/null +++ b/libnfc/nfc-device.c @@ -0,0 +1,35 @@ +/* vim:set et sw=2 ts=2: */ + +#include + +#include "nfc-internal.h" + +nfc_device_t * +nfc_device_new (void) +{ + nfc_device_t *res = malloc (sizeof (*res)); + + if (!res) { + err (EXIT_FAILURE, "nfc_device_new: malloc"); + } + + res->bCrc = true; + res->bPar = true; + res->bEasyFraming = true; + res->bAutoIso14443_4 = true; + res->iLastError = 0; + res->driver_data = NULL; + res->chip_data = NULL; + + return res; +} + +void +nfc_device_free (nfc_device_t *nfc_device) +{ + if (nfc_device) { + free (nfc_device->driver_data); + free (nfc_device->chip_data); + free (nfc_device); + } +} diff --git a/libnfc/nfc-internal.h b/libnfc/nfc-internal.h index d730a48..1bf8ab8 100644 --- a/libnfc/nfc-internal.h +++ b/libnfc/nfc-internal.h @@ -25,6 +25,8 @@ #ifndef __NFC_INTERNAL_H__ # define __NFC_INTERNAL_H__ +# include +# include # include // TODO: Put generic errors here @@ -122,4 +124,8 @@ struct nfc_driver_t { bool (*configure) (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable); }; +nfc_device_t *nfc_device_new (void); +void nfc_device_free (nfc_device_t *nfc_device); + + #endif // __NFC_INTERNAL_H__