Replaced short-circuit logic with macros
This commit is contained in:
parent
6cd025ed00
commit
6641097d48
@ -61,6 +61,8 @@ typedef enum {
|
||||
|
||||
#define REG_FIFOLevelReg 0x0A
|
||||
#define REG_FIFOLevelReg_FlushBuffer (1 << 7)
|
||||
#define REG_FIFOLevelReg_Level_PACK(x) ((x & 0x7F) << 0)
|
||||
#define REG_FIFOLevelReg_Level_UNPACK(x) ((x >> 0) & 0x7F)
|
||||
|
||||
#define REG_WaterLevelReg 0x0B
|
||||
|
||||
|
||||
@ -27,10 +27,15 @@
|
||||
|
||||
// This divides by 8 with rounding towards infinity
|
||||
#define BITS2BYTES(x) ((x >> 3) + ((x & 7) ? 1 : 0))
|
||||
#define CHIP_DATA(x) ((struct rc522_chip_data *) (x)->chip_data)
|
||||
#define CHK(x) ret = (x); if (ret < 0) { return ret; }
|
||||
|
||||
#define LOG_CATEGORY "libnfc.chip.rc522"
|
||||
#define LOG_GROUP NFC_LOG_GROUP_CHIP
|
||||
|
||||
#define TIMEOUT_DEFAULT -1
|
||||
#define TIMEOUT_NEVER 0
|
||||
|
||||
const nfc_modulation_type rc522_initiator_modulation[] = { NMT_ISO14443A, 0 };
|
||||
const nfc_modulation_type rc522_target_modulation[] = { 0 };
|
||||
|
||||
@ -42,7 +47,6 @@ struct rc522_chip_data {
|
||||
int default_timeout;
|
||||
};
|
||||
|
||||
#define CHIP_DATA(x) ((struct rc522_chip_data *) (x)->chip_data)
|
||||
|
||||
int rc522_data_new(struct nfc_device * pnd, const struct rc522_io * io) {
|
||||
pnd->chip_data = malloc(sizeof(struct rc522_chip_data));
|
||||
@ -96,11 +100,7 @@ int rc522_write_bulk(struct nfc_device * pnd, uint8_t reg, const uint8_t * val,
|
||||
int rc522_read_reg(struct nfc_device * pnd, uint8_t reg) {
|
||||
uint8_t val;
|
||||
int ret;
|
||||
|
||||
if ((ret = rc522_read_bulk(pnd, reg, &val, 1)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
CHK(rc522_read_bulk(pnd, reg, &val, 1));
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -231,27 +231,19 @@ int rc522_soft_reset(struct nfc_device * pnd) {
|
||||
int ret;
|
||||
|
||||
// 1. Execute reset command
|
||||
if ((ret = rc522_start_command(pnd, CMD_SOFTRESET)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
CHK(rc522_start_command(pnd, CMD_SOFTRESET));
|
||||
|
||||
// 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;
|
||||
}
|
||||
CHK(CHIP_DATA(pnd)->io->reset_baud_rate(pnd));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
CHK(rc522_wait_wakeup(pnd));
|
||||
|
||||
// 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;
|
||||
}
|
||||
CHK(CHIP_DATA(pnd)->io->upgrade_baud_rate(pnd));
|
||||
}
|
||||
|
||||
return NFC_SUCCESS;
|
||||
@ -259,6 +251,7 @@ int rc522_soft_reset(struct nfc_device * pnd) {
|
||||
|
||||
int rc522_set_rf_baud_rate(struct nfc_device * pnd, nfc_baud_rate speed) {
|
||||
uint8_t txVal, rxVal;
|
||||
int ret;
|
||||
|
||||
switch (speed) {
|
||||
case NBR_106:
|
||||
@ -290,9 +283,10 @@ int rc522_set_rf_baud_rate(struct nfc_device * pnd, nfc_baud_rate speed) {
|
||||
return NFC_EINVARG;
|
||||
}
|
||||
|
||||
return
|
||||
rc522_write_reg_mask(pnd, REG_TxModeReg, txVal, REG_TxModeReg_TxSpeed_MASK) ||
|
||||
rc522_write_reg_mask(pnd, REG_RxModeReg, rxVal, REG_RxModeReg_RxSpeed_MASK);
|
||||
CHK(rc522_write_reg_mask(pnd, REG_TxModeReg, txVal, REG_TxModeReg_TxSpeed_MASK));
|
||||
CHK(rc522_write_reg_mask(pnd, REG_RxModeReg, rxVal, REG_RxModeReg_RxSpeed_MASK));
|
||||
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -302,73 +296,67 @@ int rc522_initiator_select_passive_target_ext(struct nfc_device * pnd, const nfc
|
||||
return NFC_EINVARG;
|
||||
}
|
||||
|
||||
ret = rc522_set_rf_baud_rate(pnd, nm.nbr);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
CHK(rc522_set_rf_baud_rate(pnd, nm.nbr));
|
||||
|
||||
// TODO
|
||||
return NFC_ENOTIMPL;
|
||||
}
|
||||
|
||||
int rc522_transceive(struct nfc_device * pnd, const uint8_t * txData, const size_t txBits, uint8_t * rxData, const size_t rxMaxBytes, int timeout) {
|
||||
void rc522_timeout_init(struct nfc_device * pnd, timeout_t * to, int timeout) {
|
||||
if (timeout == TIMEOUT_NEVER) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_timeout_init: creating timeout which doesn't expire.");
|
||||
timeout_never(to);
|
||||
} else {
|
||||
if (timeout == TIMEOUT_DEFAULT) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_timeout_init: creating with default time (%d ms).", CHIP_DATA(pnd)->default_timeout);
|
||||
timeout = CHIP_DATA(pnd)->default_timeout;
|
||||
} else {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_timeout_init: creating with custom time of %d ms.", timeout);
|
||||
}
|
||||
|
||||
timeout_init(to, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
int rc522_rf_tx(struct nfc_device * pnd, const uint8_t * txData, const size_t txBits, timeout_t * timeout, bool transceive) {
|
||||
size_t txBytes = BITS2BYTES(txBits);
|
||||
size_t transmitted = MIN(txBytes, FIFO_SIZE);
|
||||
int ret;
|
||||
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_transceive: sending %d bits (%d bytes).", txBits, txBytes);
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_tx: sending %d bits (%d bytes).", txBits, txBytes);
|
||||
|
||||
ret =
|
||||
// Halt the device (just in case)
|
||||
rc522_abort(pnd) ||
|
||||
// Clear interesting IRQs
|
||||
rc522_write_reg(pnd, REG_ComIrqReg, REG_ComIrqReg_TxIRq || REG_ComIrqReg_RxIRq || REG_ComIrqReg_LoAlertIRq || REG_ComIrqReg_ErrIRq) ||
|
||||
// Write as much data as possible
|
||||
rc522_write_bulk(pnd, REG_FIFODataReg, txData, transmitted) ||
|
||||
// Start command
|
||||
rc522_start_command(pnd, CMD_TRANSCEIVE) ||
|
||||
// Start transmission and adjust bit framing
|
||||
rc522_write_reg(pnd, REG_BitFramingReg, REG_BitFramingReg_StartSend | REG_BitFramingReg_RxAlign_PACK(0) | REG_BitFramingReg_TxLastBits_PACK(txBits));
|
||||
if (ret < 0) {
|
||||
goto abort;
|
||||
CHK(rc522_write_reg(pnd, REG_ComIrqReg, REG_ComIrqReg_TxIRq | REG_ComIrqReg_RxIRq | REG_ComIrqReg_LoAlertIRq | REG_ComIrqReg_ErrIRq));
|
||||
CHK(rc522_write_bulk(pnd, REG_FIFODataReg, txData, transmitted));
|
||||
|
||||
if (transceive) {
|
||||
// If transceiving we must first start the command and then configure framing and start transmission
|
||||
CHK(rc522_start_command(pnd, CMD_TRANSCEIVE));
|
||||
CHK(rc522_write_reg(pnd, REG_BitFramingReg, REG_BitFramingReg_StartSend | REG_BitFramingReg_RxAlign_PACK(0) | REG_BitFramingReg_TxLastBits_PACK(txBits)));
|
||||
} else {
|
||||
// If only transmitting we must configure framing and then start the transmission
|
||||
CHK(rc522_write_reg(pnd, REG_BitFramingReg, REG_BitFramingReg_RxAlign_PACK(0) | REG_BitFramingReg_TxLastBits_PACK(txBits)));
|
||||
CHK(rc522_start_command(pnd, CMD_TRANSMIT));
|
||||
}
|
||||
|
||||
timeout_t to;
|
||||
// If "timeout" is zero there's no timeout
|
||||
if (timeout != 0) {
|
||||
// If "timeout" is -1 then we'll use the default timeout
|
||||
if (timeout == -1) {
|
||||
timeout = CHIP_DATA(pnd)->default_timeout;
|
||||
}
|
||||
timeout_init(&to, timeout);
|
||||
}
|
||||
while (1) {
|
||||
if (timeout != 0 && !timeout_check(&to)) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_transceive: transmission timeout.");
|
||||
ret = NFC_ETIMEOUT;
|
||||
goto abort;
|
||||
if (!timeout_check(timeout)) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_tx: transmission timeout.");
|
||||
return NFC_ETIMEOUT;
|
||||
}
|
||||
|
||||
int irqs = rc522_read_reg(pnd, REG_ComIrqReg);
|
||||
if (irqs < 0) {
|
||||
// If a read error happens attempt to abort transmission and return the error code
|
||||
ret = irqs;
|
||||
goto abort;
|
||||
}
|
||||
int irqs = CHK(rc522_read_reg(pnd, REG_ComIrqReg));
|
||||
|
||||
if (irqs & REG_ComIrqReg_ErrIRq) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_transceive: RC522 set ErrIRq flag.");
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_tx: RC522 set ErrIRq flag.");
|
||||
// If the RC522 detects an error abort the transmission and notify the caller
|
||||
ret = NFC_ECHIP;
|
||||
goto abort;
|
||||
return NFC_ECHIP;
|
||||
}
|
||||
|
||||
if (irqs & REG_ComIrqReg_TxIRq) {
|
||||
// Check if the FIFO has underflowed (ie the transmission has ended before we've feeded all the bytes to the FIFO)
|
||||
if (transmitted < txBytes) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "rc522_transceive couldn't feed bytes fast enough. Only %d out of %d bytes have been sent. Aborting transmission.", transmitted, txBytes);
|
||||
ret = NFC_ESOFT;
|
||||
goto abort;
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "rc522_rf_tx: couldn't feed bytes fast enough. Only %d out of %d bytes have been sent. Aborting transmission.", transmitted, txBytes);
|
||||
return NFC_ESOFT;
|
||||
}
|
||||
// Otherwise we're done
|
||||
break;
|
||||
@ -377,39 +365,116 @@ int rc522_transceive(struct nfc_device * pnd, const uint8_t * txData, const size
|
||||
if ((irqs & REG_ComIrqReg_LoAlertIRq) && transmitted < txBytes) {
|
||||
// Okay, now attempt to write as many bytes as possible. This IRQ is generated based on the water level, so we know for sure we can feed at least FIFO_SIZE - DEFAULT_WATER_LEVEL bytes.
|
||||
size_t chunkSize = MIN(txBytes - transmitted, FIFO_SIZE - DEFAULT_WATER_LEVEL);
|
||||
if ((ret = rc522_write_bulk(pnd, REG_FIFODataReg, txData + transmitted, chunkSize)) < 0) {
|
||||
goto abort;
|
||||
}
|
||||
CHK(rc522_write_bulk(pnd, REG_FIFODataReg, txData + transmitted, chunkSize));
|
||||
transmitted += chunkSize;
|
||||
|
||||
// TODO: Should we clear the flag before or after feeding the data?
|
||||
if ((ret = rc522_write_reg(pnd, REG_ComIrqReg, REG_ComIrqReg_LoAlertIRq)) < 0) {
|
||||
goto abort;
|
||||
}
|
||||
CHK(rc522_write_reg(pnd, REG_ComIrqReg, REG_ComIrqReg_LoAlertIRq));
|
||||
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_transceive: fed another %d bytes to FIFO.", chunkSize);
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_tx: fed another %d bytes to FIFO.", chunkSize);
|
||||
}
|
||||
}
|
||||
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_transceive: transmission finished.");
|
||||
return 0;
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_tx: transmission finished.");
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
int rc522_rf_rx(struct nfc_device * pnd, uint8_t * rxData, const size_t rxMaxBytes, timeout_t * timeout, bool transceive) {
|
||||
int ret;
|
||||
size_t received = 0;
|
||||
|
||||
// Clear this as early as possible
|
||||
CHK(rc522_write_reg(pnd, REG_ComIrqReg, REG_ComIrqReg_HiAlertIRq));
|
||||
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_rx: receiving up to %d bytes.", rxMaxBytes);
|
||||
|
||||
if (!transceive) {
|
||||
CHK(rc522_write_reg(pnd, REG_ComIrqReg, REG_ComIrqReg_TxIRq | REG_ComIrqReg_RxIRq | REG_ComIrqReg_LoAlertIRq | REG_ComIrqReg_ErrIRq));
|
||||
CHK(rc522_start_command(pnd, CMD_RECEIVE));
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!timeout_check(timeout)) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_rx: transmission timeout.");
|
||||
return NFC_ETIMEOUT;
|
||||
}
|
||||
|
||||
int irqs = CHK(rc522_read_reg(pnd, REG_ComIrqReg));
|
||||
|
||||
if (irqs & REG_ComIrqReg_ErrIRq) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_rx: RC522 set ErrIRq flag.");
|
||||
// If the RC522 detects an error abort the transmission and notify the caller
|
||||
return NFC_ECHIP;
|
||||
}
|
||||
|
||||
if (irqs & REG_ComIrqReg_RxIRq) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (irqs & REG_ComIrqReg_HiAlertIRq) {
|
||||
size_t chunkSize = FIFO_SIZE - DEFAULT_WATER_LEVEL;
|
||||
if (rxMaxBytes - received < chunkSize) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_rx: RX buffer overflow (buffer contains %d bytes and may hold up to %d bytes, but needs %d more).", received, rxMaxBytes, chunkSize);
|
||||
return NFC_EOVFLOW;
|
||||
}
|
||||
|
||||
CHK(rc522_read_bulk(pnd, REG_FIFODataReg, rxData + received, chunkSize));
|
||||
received += chunkSize;
|
||||
|
||||
// TODO: Should we clear the flag before or after feeding the data?
|
||||
CHK(rc522_write_reg(pnd, REG_ComIrqReg, REG_ComIrqReg_HiAlertIRq));
|
||||
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_rx: read another %d bytes from FIFO.", chunkSize);
|
||||
}
|
||||
}
|
||||
|
||||
CHK(rc522_read_reg(pnd, REG_FIFOLevelReg));
|
||||
size_t remaining = REG_FIFOLevelReg_Level_UNPACK(ret);
|
||||
|
||||
if (rxMaxBytes - received < remaining) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_rx: RX buffer overflow (buffer contains %d bytes and may hold up to %d bytes, but needs %d more).", received, rxMaxBytes, remaining);
|
||||
return NFC_EOVFLOW;
|
||||
}
|
||||
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_rx: reading last %d bytes from FIFO.", remaining);
|
||||
CHK(rc522_read_bulk(pnd, REG_FIFODataReg, rxData + received, remaining));
|
||||
received += remaining;
|
||||
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_rf_rx: receive finished. Read %d bytes.", received);
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
int rc522_transceive(struct nfc_device * pnd, const uint8_t * txData, const size_t txBits, uint8_t * rxData, const size_t rxMaxBytes, int timeout) {
|
||||
int ret;
|
||||
timeout_t to;
|
||||
rc522_timeout_init(pnd, &to, timeout);
|
||||
|
||||
CHK(rc522_abort(pnd));
|
||||
|
||||
ret = rc522_rf_tx(pnd, txData, txBits, &to, true);
|
||||
if (ret < 0) {
|
||||
rc522_abort(pnd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rc522_rf_rx(pnd, rxData, rxMaxBytes, &to, true);
|
||||
if (ret < 0) {
|
||||
rc522_abort(pnd);
|
||||
}
|
||||
|
||||
abort:
|
||||
rc522_abort(pnd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rc522_initiator_transceive_bits(struct nfc_device * pnd, const uint8_t * txData, const size_t txBits, const uint8_t * pbtTxPar, uint8_t * rxData, uint8_t * pbtRxPar) {
|
||||
int ret;
|
||||
// TODO: Do something with pbtTxPar and pbtRxPar
|
||||
return rc522_transceive(pnd, txData, txBits, rxData, ~0, -1);
|
||||
CHK(rc522_transceive(pnd, txData, txBits, rxData, ~0, TIMEOUT_DEFAULT));
|
||||
return ret * 8;
|
||||
}
|
||||
|
||||
int rc522_initiator_transceive_bytes(struct nfc_device * pnd, const uint8_t * txData, const size_t txSize, uint8_t * rxData, const size_t rxMaxBytes, int timeout) {
|
||||
int ret = rc522_transceive(pnd, txData, txSize * 8, rxData, rxMaxBytes, timeout);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return ret / 8;
|
||||
return rc522_transceive(pnd, txData, txSize * 8, rxData, rxMaxBytes, timeout);
|
||||
}
|
||||
|
||||
int rc522_get_supported_modulation(struct nfc_device * pnd, const nfc_mode mode, const nfc_modulation_type ** const supported_mt) {
|
||||
@ -463,12 +528,8 @@ int rc522_set_property_bool(struct nfc_device * pnd, const nfc_property property
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
ret =
|
||||
rc522_write_reg_mask(pnd, REG_TxModeReg, enable ? ~0 : 0, REG_TxModeReg_TxCRCEn) ||
|
||||
rc522_write_reg_mask(pnd, REG_RxModeReg, enable ? ~0 : 0, REG_RxModeReg_RxCRCEn);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
CHK(rc522_write_reg_mask(pnd, REG_TxModeReg, enable ? ~0 : 0, REG_TxModeReg_TxCRCEn));
|
||||
CHK(rc522_write_reg_mask(pnd, REG_RxModeReg, enable ? ~0 : 0, REG_RxModeReg_RxCRCEn));
|
||||
|
||||
pnd->bCrc = enable;
|
||||
return NFC_SUCCESS;
|
||||
@ -479,10 +540,7 @@ int rc522_set_property_bool(struct nfc_device * pnd, const nfc_property property
|
||||
}
|
||||
|
||||
// Note it's parity DISABLE (ie active low)
|
||||
ret = rc522_write_reg_mask(pnd, REG_MfRxReg, enable ? 0 : ~0, REG_MfRxReg_ParityDisable);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
CHK(rc522_write_reg_mask(pnd, REG_MfRxReg, enable ? 0 : ~0, REG_MfRxReg_ParityDisable));
|
||||
|
||||
pnd->bPar = enable;
|
||||
return NFC_SUCCESS;
|
||||
@ -585,11 +643,14 @@ int rc522_initiator_init(struct nfc_device * pnd) {
|
||||
}
|
||||
|
||||
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);
|
||||
int ret;
|
||||
|
||||
// Halt any running commands
|
||||
CHK(rc522_start_command(pnd, CMD_IDLE));
|
||||
// Clear FIFO
|
||||
CHK(rc522_write_reg(pnd, REG_FIFOLevelReg, REG_FIFOLevelReg_FlushBuffer));
|
||||
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
int rc522_powerdown(struct nfc_device * pnd) {
|
||||
@ -631,22 +692,19 @@ int rc522_self_test(struct nfc_device * pnd) {
|
||||
uint8_t zeroes[25];
|
||||
memset(zeroes, 0x00, sizeof(zeroes));
|
||||
|
||||
int ret;
|
||||
// MFRC522 datasheet section 16.1.1
|
||||
int ret =
|
||||
// 1. Perform a soft reset
|
||||
rc522_soft_reset(pnd) ||
|
||||
// 2. Clear the internal buffer by writing 25 bytes of 0x00 and execute the Mem command
|
||||
rc522_write_bulk(pnd, REG_FIFODataReg, zeroes, sizeof(zeroes)) ||
|
||||
rc522_start_command(pnd, CMD_MEM) ||
|
||||
// 3. Enable the self test by writing 0x09 to the AutoTestReg register
|
||||
rc522_write_reg_mask(pnd, REG_AutoTestReg, REG_AutoTestReg_SelfTest_Enabled, REG_AutoTestReg_SelfTest_MASK) ||
|
||||
// 4. Write 0x00h to the FIFO buffer
|
||||
rc522_write_reg(pnd, REG_FIFODataReg, 0x00) ||
|
||||
// 5. Start the self test with the CalcCRC command
|
||||
rc522_start_command(pnd, CMD_CALCCRC);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
// 1. Perform a soft reset
|
||||
CHK(rc522_soft_reset(pnd));
|
||||
// 2. Clear the internal buffer by writing 25 bytes of 0x00 and execute the Mem command
|
||||
CHK(rc522_write_bulk(pnd, REG_FIFODataReg, zeroes, sizeof(zeroes)));
|
||||
CHK(rc522_start_command(pnd, CMD_MEM));
|
||||
// 3. Enable the self test by writing 0x09 to the AutoTestReg register
|
||||
CHK(rc522_write_reg_mask(pnd, REG_AutoTestReg, REG_AutoTestReg_SelfTest_Enabled, REG_AutoTestReg_SelfTest_MASK));
|
||||
// 4. Write 0x00h to the FIFO buffer
|
||||
CHK(rc522_write_reg(pnd, REG_FIFODataReg, 0x00));
|
||||
// 5. Start the self test with the CalcCRC command
|
||||
CHK(rc522_start_command(pnd, CMD_CALCCRC));
|
||||
|
||||
// 6. Wait for the RC522 to calculate the selftest values
|
||||
// The official datasheet does not mentions how much time does it take, let's use 50ms
|
||||
@ -659,9 +717,7 @@ int rc522_self_test(struct nfc_device * pnd) {
|
||||
return NFC_ETIMEOUT;
|
||||
}
|
||||
|
||||
if ((ret = rc522_read_reg(pnd, REG_DivIrqReg)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
CHK(rc522_read_reg(pnd, REG_DivIrqReg));
|
||||
|
||||
// If the RC522 has finished calculating the CRC proceed
|
||||
if (ret & REG_DivIrqReg_CRCIRq) {
|
||||
@ -670,14 +726,10 @@ int rc522_self_test(struct nfc_device * pnd) {
|
||||
}
|
||||
|
||||
uint8_t response[FIFO_SIZE];
|
||||
ret =
|
||||
// 7. Read selftest result
|
||||
rc522_read_bulk(pnd, REG_FIFODataReg, response, FIFO_SIZE) ||
|
||||
// 8. Disable selftest operation mode
|
||||
rc522_write_reg_mask(pnd, REG_AutoTestReg, REG_AutoTestReg_SelfTest_Disabled, REG_AutoTestReg_SelfTest_MASK);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
// 7. Read selftest result
|
||||
CHK(rc522_read_bulk(pnd, REG_FIFODataReg, response, FIFO_SIZE));
|
||||
// 8. Disable selftest operation mode
|
||||
CHK(rc522_write_reg_mask(pnd, REG_AutoTestReg, REG_AutoTestReg_SelfTest_Disabled, REG_AutoTestReg_SelfTest_MASK));
|
||||
|
||||
if (memcmp(correct, response, FIFO_SIZE) != 0) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Self test values didn't match");
|
||||
@ -689,13 +741,12 @@ int rc522_self_test(struct nfc_device * pnd) {
|
||||
}
|
||||
|
||||
int rc522_init(struct nfc_device * pnd) {
|
||||
int version = rc522_read_reg(pnd, REG_VersionReg);
|
||||
if (version < 0) {
|
||||
return version;
|
||||
}
|
||||
int ret;
|
||||
|
||||
int version = CHK(rc522_read_reg(pnd, REG_VersionReg));
|
||||
CHIP_DATA(pnd)->version = version;
|
||||
|
||||
int ret = rc522_self_test(pnd);
|
||||
ret = rc522_self_test(pnd);
|
||||
if (ret == NFC_EDEVNOTSUPP) {
|
||||
// TODO: Implement another test, maybe?
|
||||
ret = rc522_soft_reset(pnd);
|
||||
|
||||
@ -38,14 +38,17 @@
|
||||
#include "chips/rc522.h"
|
||||
#include "uart.h"
|
||||
|
||||
#define RC522_UART_BOOT_SPEED 9600
|
||||
#define RC522_UART_DEFAULT_SPEED 115200
|
||||
#define RC522_UART_DRIVER_NAME "rc522_uart"
|
||||
#define RC522_UART_IO_TIMEOUT 50
|
||||
|
||||
#define LOG_CATEGORY "libnfc.driver.rc522_uart"
|
||||
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
|
||||
|
||||
#define BOOT_BAUD_RATE 9600
|
||||
#define DEFAULT_BAUD_RATE 115200
|
||||
#define DRIVER_NAME "rc522_uart"
|
||||
#define IO_TIMEOUT 50
|
||||
|
||||
#define DRIVER_DATA(pnd) ((struct rc522_uart_data*)(pnd->driver_data))
|
||||
#define CHK(x) ret = (x); if (ret < 0) { return ret; }
|
||||
|
||||
// Internal data structs
|
||||
const struct rc522_io rc522_uart_io;
|
||||
struct rc522_uart_data {
|
||||
@ -53,14 +56,13 @@ struct rc522_uart_data {
|
||||
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.
|
||||
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), IO_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -151,10 +153,10 @@ int rc522_uart_create(const nfc_context * context, const nfc_connstring connstri
|
||||
|
||||
// Let's try first with boot baud rate
|
||||
if (
|
||||
!rc522_uart_test_baudrate(pnd, RC522_UART_BOOT_SPEED) &&
|
||||
!rc522_uart_test_baudrate(pnd, BOOT_BAUD_RATE) &&
|
||||
!rc522_uart_test_baudrate(pnd, userBaudRate)
|
||||
) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Could not connect with RC522 at %d or %d bps.", RC522_UART_BOOT_SPEED, userBaudRate);
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Could not connect with RC522 at %d or %d bps.", BOOT_BAUD_RATE, userBaudRate);
|
||||
rc522_uart_close(pnd);
|
||||
return NFC_EIO;
|
||||
}
|
||||
@ -171,10 +173,10 @@ size_t rc522_uart_scan(const nfc_context * context, nfc_connstring connstrings[]
|
||||
|
||||
while ((acPort = acPorts[iDevice++])) {
|
||||
nfc_connstring connstring;
|
||||
snprintf(connstring, sizeof(nfc_connstring), "%s:%s:%"PRIu32, RC522_UART_DRIVER_NAME, acPort, RC522_UART_DEFAULT_SPEED);
|
||||
snprintf(connstring, sizeof(nfc_connstring), "%s:%s:%"PRIu32, DRIVER_NAME, acPort, DEFAULT_BAUD_RATE);
|
||||
|
||||
nfc_device * pnd;
|
||||
int ret = rc522_uart_create(context, connstring, acPort, RC522_UART_DEFAULT_SPEED, &pnd);
|
||||
int ret = rc522_uart_create(context, connstring, acPort, DEFAULT_BAUD_RATE, &pnd);
|
||||
if (ret == NFC_ESOFT) {
|
||||
uart_list_free(acPorts);
|
||||
return 0;
|
||||
@ -203,10 +205,10 @@ struct nfc_device * rc522_uart_open(const nfc_context * context, const nfc_conns
|
||||
char * endptr;
|
||||
struct nfc_device * pnd = NULL;
|
||||
|
||||
int decodelvl = connstring_decode(connstring, RC522_UART_DRIVER_NAME, NULL, &port_str, &baud_str);
|
||||
int decodelvl = connstring_decode(connstring, DRIVER_NAME, NULL, &port_str, &baud_str);
|
||||
switch (decodelvl) {
|
||||
case 2: // Got port but no speed
|
||||
baudrate = RC522_UART_DEFAULT_SPEED;
|
||||
baudrate = DEFAULT_BAUD_RATE;
|
||||
break;
|
||||
|
||||
case 3: // Got port and baud rate
|
||||
@ -246,11 +248,11 @@ int rc522_uart_read(struct nfc_device * pnd, uint8_t reg, uint8_t * data, size_t
|
||||
int ret;
|
||||
|
||||
while (size > 0) {
|
||||
if ((ret = uart_send(DRIVER_DATA(pnd)->port, &cmd, 1, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||
if ((ret = uart_send(DRIVER_DATA(pnd)->port, &cmd, 1, IO_TIMEOUT)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((ret = uart_receive(DRIVER_DATA(pnd)->port, data, 1, NULL, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||
if ((ret = uart_receive(DRIVER_DATA(pnd)->port, data, 1, NULL, IO_TIMEOUT)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -271,13 +273,13 @@ int rc522_uart_write(struct nfc_device * pnd, uint8_t reg, const uint8_t * data,
|
||||
|
||||
while (size > 0) {
|
||||
// First: send write request
|
||||
if ((ret = uart_send(DRIVER_DATA(pnd)->port, &cmd, 1, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||
if ((ret = uart_send(DRIVER_DATA(pnd)->port, &cmd, 1, IO_TIMEOUT)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Second: wait for a reply
|
||||
uint8_t reply;
|
||||
if ((ret = uart_receive(DRIVER_DATA(pnd)->port, &reply, 1, NULL, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||
if ((ret = uart_receive(DRIVER_DATA(pnd)->port, &reply, 1, NULL, IO_TIMEOUT)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -289,7 +291,7 @@ int rc522_uart_write(struct nfc_device * pnd, uint8_t reg, const uint8_t * data,
|
||||
}
|
||||
|
||||
// Fourth: send register data
|
||||
if ((ret = uart_send(DRIVER_DATA(pnd)->port, data, 1, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||
if ((ret = uart_send(DRIVER_DATA(pnd)->port, data, 1, IO_TIMEOUT)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -305,20 +307,22 @@ 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);
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Restoring baud rate to default of %d bps.", BOOT_BAUD_RATE);
|
||||
return uart_set_speed(DRIVER_DATA(pnd)->port, BOOT_BAUD_RATE);
|
||||
}
|
||||
|
||||
int rc522_uart_upgrade_baud_rate(struct nfc_device * pnd) {
|
||||
int ret;
|
||||
uint32_t userBaudRate = DRIVER_DATA(pnd)->baudrate;
|
||||
if (userBaudRate == RC522_UART_BOOT_SPEED) {
|
||||
if (userBaudRate == BOOT_BAUD_RATE) {
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Upgrading baud rate to user-specified %d bps.", userBaudRate);
|
||||
return
|
||||
uart_set_speed(DRIVER_DATA(pnd)->port, userBaudRate) ||
|
||||
rc522_send_baudrate(pnd, userBaudRate);
|
||||
CHK(uart_set_speed(DRIVER_DATA(pnd)->port, userBaudRate));
|
||||
CHK(rc522_send_baudrate(pnd, userBaudRate));
|
||||
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
const struct rc522_io rc522_uart_io = {
|
||||
@ -329,7 +333,7 @@ const struct rc522_io rc522_uart_io = {
|
||||
};
|
||||
|
||||
const struct nfc_driver rc522_uart_driver = {
|
||||
.name = RC522_UART_DRIVER_NAME,
|
||||
.name = DRIVER_NAME,
|
||||
.scan_type = INTRUSIVE,
|
||||
.scan = rc522_uart_scan,
|
||||
.open = rc522_uart_open,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user