More RC522 stuff

This commit is contained in:
Marcos Vives Del Sol 2015-06-18 21:39:06 +02:00
parent 2823a0e276
commit 9daec49f3e
3 changed files with 111 additions and 74 deletions

View File

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

View File

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

View File

@ -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 = {