From 9daec49f3e21918d9d31d099599db6b38d5a2faf Mon Sep 17 00:00:00 2001 From: Marcos Vives Del Sol Date: Thu, 18 Jun 2015 21:39:06 +0200 Subject: [PATCH] More RC522 stuff --- libnfc/chips/rc522.c | 76 +++++++++++++++++++++++--- libnfc/chips/rc522.h | 4 +- libnfc/drivers/rc522_uart.c | 105 ++++++++++++++---------------------- 3 files changed, 111 insertions(+), 74 deletions(-) diff --git a/libnfc/chips/rc522.c b/libnfc/chips/rc522.c index aeb4fb1..9e0eaad 100644 --- a/libnfc/chips/rc522.c +++ b/libnfc/chips/rc522.c @@ -219,11 +219,33 @@ int rc522_send_baudrate(struct nfc_device * pnd, uint32_t baudrate) { } int rc522_soft_reset(struct nfc_device * pnd) { - return - // 1. Send soft reset - rc522_start_command(pnd, CMD_SOFTRESET) || - CHIP_DATA(pnd)->io->reset_baud_rate(pnd) || - rc522_wait_wakeup(pnd); + int ret; + + // 1. Execute reset command + if ((ret = rc522_start_command(pnd, CMD_SOFTRESET)) < 0) { + return ret; + } + + // 2. If using an UART, reset baud rate to RC522 default speed + if (CHIP_DATA(pnd)->io->reset_baud_rate) { + if ((ret = CHIP_DATA(pnd)->io->reset_baud_rate(pnd)) < 0) { + return ret; + } + } + + // 3. Wait for the RC522 to come back to life, as we shouldn't modify any register till that happens + if ((ret = rc522_wait_wakeup(pnd)) < 0) { + return ret; + } + + // 4. If using an UART, restore baud rate to user's choice + if (CHIP_DATA(pnd)->io->upgrade_baud_rate) { + if ((ret = CHIP_DATA(pnd)->io->upgrade_baud_rate(pnd)) < 0) { + return ret; + } + } + + return NFC_SUCCESS; } int rc522_set_baud_rate(struct nfc_device * pnd, nfc_baud_rate speed) { @@ -259,8 +281,7 @@ int rc522_set_baud_rate(struct nfc_device * pnd, nfc_baud_rate speed) { rc522_write_reg(pnd, REG_RxModeReg, rxVal, REG_RxModeReg_RxSpeed_MASK); } -int rc522_initiator_select_passive_target_ext(struct nfc_device * pnd, const nfc_modulation nm, const uint8_t * pbtInitData, const size_t szInitData, nfc_target * pnt, int timeout) -{ +int rc522_initiator_select_passive_target_ext(struct nfc_device * pnd, const nfc_modulation nm, const uint8_t * pbtInitData, const size_t szInitData, nfc_target * pnt, int timeout) { int ret; if (nm.nmt != NMT_ISO14443A) { @@ -276,6 +297,25 @@ int rc522_initiator_select_passive_target_ext(struct nfc_device * pnd, const nfc return NFC_ENOTIMPL; } +int rc522_initiator_transceive_bits(struct nfc_device * pnd, const uint8_t * txData, const size_t txBits, const uint8_t *pbtTxPar, uint8_t *pbtRx, uint8_t *pbtRxPar) { + return NFC_ENOTIMPL; +} + +int rc522_initiator_transceive_bytes(struct nfc_device * pnd, const uint8_t * txData, const size_t txSize, uint8_t * rxData, const size_t rxMaxSize, int timeout) { + int ret; + + if (txSize > FIFO_SIZE) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Attempted to send %d bytes, but FIFO has only %d bytes.", txSize, FIFO_SIZE); + return NFC_EOVFLOW; + } + + if ((ret = rc522_write_bulk(pnd, REG_FIFODataReg, txData, txSize)) < 0) { + return ret; + } + + +} + int rc522_get_supported_modulation(struct nfc_device * pnd, const nfc_mode mode, const nfc_modulation_type ** const supported_mt) { switch (mode) { case N_INITIATOR: @@ -388,7 +428,9 @@ int rc522_set_property_int(struct nfc_device * pnd, const nfc_property property, int rc522_abort(struct nfc_device * pnd) { return + // Halt any running commands rc522_start_command(pnd, CMD_IDLE) || + // Clear FIFO rc522_write_reg(pnd, REG_FIFOLevelReg, REG_FIFOLevelReg_FlushBuffer, 0xFF); } @@ -422,6 +464,7 @@ int rc522_self_test(struct nfc_device * pnd) { break; default: + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Aborting self test for unknown version %02X.", CHIP_DATA(pnd)->version); return NFC_EDEVNOTSUPP; } @@ -454,6 +497,7 @@ int rc522_self_test(struct nfc_device * pnd) { while (1) { if (!timeout_check(&to)) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Self test timeout"); return NFC_ETIMEOUT; } @@ -478,8 +522,26 @@ int rc522_self_test(struct nfc_device * pnd) { } if (memcmp(correct, response, FIFO_SIZE) != 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Self test values didn't match"); return NFC_ECHIP; } + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Self test executed successfully!"); return NFC_SUCCESS; } + +int rc522_init(struct nfc_device * pnd) { + int version = rc522_read_reg(pnd, REG_VersionReg); + if (version < 0) { + return version; + } + CHIP_DATA(pnd)->version = version; + + int ret = rc522_self_test(pnd); + if (ret == NFC_EDEVNOTSUPP) { + // TODO: Implement another test, maybe? + ret = rc522_soft_reset(pnd); + } + + return ret; +} diff --git a/libnfc/chips/rc522.h b/libnfc/chips/rc522.h index d8ee526..8f9ab0e 100644 --- a/libnfc/chips/rc522.h +++ b/libnfc/chips/rc522.h @@ -26,13 +26,13 @@ struct rc522_io { int (*read)(struct nfc_device * pnd, uint8_t reg, uint8_t * data, size_t size); int (*write)(struct nfc_device * pnd, uint8_t reg, const uint8_t * data, size_t size); int (*reset_baud_rate)(struct nfc_device * pnd); + int (*upgrade_baud_rate)(struct nfc_device * pnd); }; int rc522_data_new(struct nfc_device * pnd, const struct rc522_io * io); void rc522_data_free(struct nfc_device * pnd); -int rc522_self_test(struct nfc_device * pnd); -int rc522_wait_wakeup(struct nfc_device * pnd); int rc522_send_baudrate(struct nfc_device * pnd, uint32_t baudrate); +int rc522_init(struct nfc_device * pnd); int rc522_get_supported_modulation(nfc_device * pnd, const nfc_mode mode, const nfc_modulation_type ** const supported_mt); int rc522_get_supported_baud_rate(nfc_device * pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate ** const supported_br); diff --git a/libnfc/drivers/rc522_uart.c b/libnfc/drivers/rc522_uart.c index 0085db9..eb86e61 100644 --- a/libnfc/drivers/rc522_uart.c +++ b/libnfc/drivers/rc522_uart.c @@ -49,16 +49,16 @@ // Internal data structs const struct rc522_io rc522_uart_io; struct rc522_uart_data { - serial_port port; - uint32_t baudrate; + serial_port port; + uint32_t baudrate; }; #define DRIVER_DATA(pnd) ((struct rc522_uart_data*)(pnd->driver_data)) - +/* int rc522_uart_wakeup(struct nfc_device * pnd) { int ret; - /* High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for RC522 being wakeup. */ + // High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for RC522 being wakeup. const uint8_t rc522_wakeup_preamble[] = { 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ret = uart_send(DRIVER_DATA(pnd)->port, rc522_wakeup_preamble, sizeof(rc522_wakeup_preamble), RC522_UART_IO_TIMEOUT); if (ret < 0) { @@ -67,48 +67,7 @@ int rc522_uart_wakeup(struct nfc_device * pnd) { return rc522_wait_wakeup(pnd); } - -bool rc522_uart_test_baudrate(struct nfc_device * pnd, uint32_t baudrate) { - int ret; - - if ((ret = uart_set_speed(DRIVER_DATA(pnd)->port, baudrate)) < 0) { - return false; - } - - ret = rc522_wait_wakeup(pnd); - if (ret != NFC_SUCCESS) { - return false; - } - - DRIVER_DATA(pnd)->baudrate = baudrate; - return true; -} - -int rc522_uart_change_baudrate(struct nfc_device * pnd, uint32_t newBaudRate) { - uint32_t oldBaudRate = DRIVER_DATA(pnd)->baudrate; - int ret; - - if (oldBaudRate == newBaudRate) { - return NFC_SUCCESS; - } - - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Switching baud rate from %dbps to %dbps.", oldBaudRate, newBaudRate); - - if ((ret = rc522_send_baudrate(pnd, newBaudRate)) < 0) { - return ret; - } - - if ((ret = uart_set_speed(DRIVER_DATA(pnd)->port, newBaudRate)) < 0) { - return ret; - } - - if ((ret = rc522_wait_wakeup(pnd)) < 0) { - return ret; - } - - DRIVER_DATA(pnd)->baudrate = newBaudRate; - return NFC_SUCCESS; -} +*/ void rc522_uart_close(nfc_device * pnd) { rc522_powerdown(pnd); @@ -118,6 +77,26 @@ void rc522_uart_close(nfc_device * pnd) { nfc_device_free(pnd); } +bool rc522_uart_test_baudrate(struct nfc_device * pnd, uint32_t baudrate) { + int ret; + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempting to establish a connection at %d bps.", baudrate); + + // Update UART baudrate + if ((ret = uart_set_speed(DRIVER_DATA(pnd)->port, baudrate)) < 0) { + return false; + } + + // Attempt to test and initialize the device + if (rc522_init(pnd) != NFC_SUCCESS) { + return false; + } + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Connection with a RC522 at %d bps established successfully.", baudrate); + + return true; +} + int rc522_uart_create(const nfc_context * context, const nfc_connstring connstring, const char * portPath, uint32_t userBaudRate, struct nfc_device ** pndPtr) { int ret; serial_port sp; @@ -155,6 +134,7 @@ int rc522_uart_create(const nfc_context * context, const nfc_connstring connstri return NFC_ESOFT; } DRIVER_DATA(pnd)->port = sp; + DRIVER_DATA(pnd)->baudrate = userBaudRate; // Alloc and init chip's data if (rc522_data_new(pnd, &rc522_uart_io)) { @@ -179,22 +159,6 @@ int rc522_uart_create(const nfc_context * context, const nfc_connstring connstri return NFC_EIO; } - // Change now the baud rate - /* TODO - Check why this doesn't work on my FM17522 and try it with a real MFRC522 - if ((ret = rc522_uart_change_baudrate(pnd, userBaudRate)) < 0) { - rc522_uart_close(pnd); - return ret; - } - */ - - // Now the device is awake and listening at a known baudrate, execute a selftest - // Note that some devices (FM17522 for instance) aren't able to run it - ret = rc522_self_test(pnd); - if (ret != NFC_SUCCESS && ret != NFC_EDEVNOTSUPP) { - rc522_uart_close(pnd); - return ret; - } - *pndPtr = pnd; return NFC_SUCCESS; } @@ -341,16 +305,27 @@ error: } int rc522_uart_reset_baud_rate(struct nfc_device * pnd) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Restoring baud rate to default of %d bps.", RC522_UART_BOOT_SPEED); + return uart_set_speed(DRIVER_DATA(pnd)->port, RC522_UART_BOOT_SPEED); +} + +int rc522_uart_upgrade_baud_rate(struct nfc_device * pnd) { uint32_t userBaudRate = DRIVER_DATA(pnd)->baudrate; + if (userBaudRate == RC522_UART_BOOT_SPEED) { + return NFC_SUCCESS; + } + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Upgrading baud rate to user-specified %d bps.", userBaudRate); return - rc522_uart_test_baudrate(pnd, RC522_UART_BOOT_SPEED) || - rc522_uart_change_baudrate(pnd, userBaudRate); + uart_set_speed(DRIVER_DATA(pnd)->port, userBaudRate) || + rc522_send_baudrate(pnd, userBaudRate); } const struct rc522_io rc522_uart_io = { .read = rc522_uart_read, .write = rc522_uart_write, - .reset_baud_rate = rc522_uart_reset_baud_rate, + .reset_baud_rate = rc522_uart_reset_baud_rate, + .upgrade_baud_rate = rc522_uart_upgrade_baud_rate, }; const struct nfc_driver rc522_uart_driver = {