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) { int rc522_soft_reset(struct nfc_device * pnd) {
return int ret;
// 1. Send soft reset
rc522_start_command(pnd, CMD_SOFTRESET) || // 1. Execute reset command
CHIP_DATA(pnd)->io->reset_baud_rate(pnd) || if ((ret = rc522_start_command(pnd, CMD_SOFTRESET)) < 0) {
rc522_wait_wakeup(pnd); 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) { 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); 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; int ret;
if (nm.nmt != NMT_ISO14443A) { 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; 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) { int rc522_get_supported_modulation(struct nfc_device * pnd, const nfc_mode mode, const nfc_modulation_type ** const supported_mt) {
switch (mode) { switch (mode) {
case N_INITIATOR: 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) { int rc522_abort(struct nfc_device * pnd) {
return return
// Halt any running commands
rc522_start_command(pnd, CMD_IDLE) || rc522_start_command(pnd, CMD_IDLE) ||
// Clear FIFO
rc522_write_reg(pnd, REG_FIFOLevelReg, REG_FIFOLevelReg_FlushBuffer, 0xFF); rc522_write_reg(pnd, REG_FIFOLevelReg, REG_FIFOLevelReg_FlushBuffer, 0xFF);
} }
@ -422,6 +464,7 @@ int rc522_self_test(struct nfc_device * pnd) {
break; break;
default: 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; return NFC_EDEVNOTSUPP;
} }
@ -454,6 +497,7 @@ int rc522_self_test(struct nfc_device * pnd) {
while (1) { while (1) {
if (!timeout_check(&to)) { if (!timeout_check(&to)) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Self test timeout");
return NFC_ETIMEOUT; return NFC_ETIMEOUT;
} }
@ -478,8 +522,26 @@ int rc522_self_test(struct nfc_device * pnd) {
} }
if (memcmp(correct, response, FIFO_SIZE) != 0) { 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; return NFC_ECHIP;
} }
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Self test executed successfully!");
return NFC_SUCCESS; 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 (*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 (*write)(struct nfc_device * pnd, uint8_t reg, const uint8_t * data, size_t size);
int (*reset_baud_rate)(struct nfc_device * pnd); 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); int rc522_data_new(struct nfc_device * pnd, const struct rc522_io * io);
void rc522_data_free(struct nfc_device * pnd); 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_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_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); 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 // Internal data structs
const struct rc522_io rc522_uart_io; const struct rc522_io rc522_uart_io;
struct rc522_uart_data { struct rc522_uart_data {
serial_port port; serial_port port;
uint32_t baudrate; uint32_t baudrate;
}; };
#define DRIVER_DATA(pnd) ((struct rc522_uart_data*)(pnd->driver_data)) #define DRIVER_DATA(pnd) ((struct rc522_uart_data*)(pnd->driver_data))
/*
int rc522_uart_wakeup(struct nfc_device * pnd) { int rc522_uart_wakeup(struct nfc_device * pnd) {
int ret; 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 }; 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); ret = uart_send(DRIVER_DATA(pnd)->port, rc522_wakeup_preamble, sizeof(rc522_wakeup_preamble), RC522_UART_IO_TIMEOUT);
if (ret < 0) { if (ret < 0) {
@ -67,48 +67,7 @@ int rc522_uart_wakeup(struct nfc_device * pnd) {
return rc522_wait_wakeup(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) { void rc522_uart_close(nfc_device * pnd) {
rc522_powerdown(pnd); rc522_powerdown(pnd);
@ -118,6 +77,26 @@ void rc522_uart_close(nfc_device * pnd) {
nfc_device_free(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 rc522_uart_create(const nfc_context * context, const nfc_connstring connstring, const char * portPath, uint32_t userBaudRate, struct nfc_device ** pndPtr) {
int ret; int ret;
serial_port sp; serial_port sp;
@ -155,6 +134,7 @@ int rc522_uart_create(const nfc_context * context, const nfc_connstring connstri
return NFC_ESOFT; return NFC_ESOFT;
} }
DRIVER_DATA(pnd)->port = sp; DRIVER_DATA(pnd)->port = sp;
DRIVER_DATA(pnd)->baudrate = userBaudRate;
// Alloc and init chip's data // Alloc and init chip's data
if (rc522_data_new(pnd, &rc522_uart_io)) { 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; 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; *pndPtr = pnd;
return NFC_SUCCESS; return NFC_SUCCESS;
} }
@ -341,16 +305,27 @@ error:
} }
int rc522_uart_reset_baud_rate(struct nfc_device * pnd) { 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; 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 return
rc522_uart_test_baudrate(pnd, RC522_UART_BOOT_SPEED) || uart_set_speed(DRIVER_DATA(pnd)->port, userBaudRate) ||
rc522_uart_change_baudrate(pnd, userBaudRate); rc522_send_baudrate(pnd, userBaudRate);
} }
const struct rc522_io rc522_uart_io = { const struct rc522_io rc522_uart_io = {
.read = rc522_uart_read, .read = rc522_uart_read,
.write = rc522_uart_write, .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 = { const struct nfc_driver rc522_uart_driver = {