Further work for RC522
This commit is contained in:
parent
09ceb92db4
commit
94b2ddab04
@ -97,8 +97,6 @@ struct serial_port_unix {
|
|||||||
int fd; // Serial port file descriptor
|
int fd; // Serial port file descriptor
|
||||||
struct termios termios_backup; // Terminal info before using the port
|
struct termios termios_backup; // Terminal info before using the port
|
||||||
struct termios termios_new; // Terminal info during the transaction
|
struct termios termios_new; // Terminal info during the transaction
|
||||||
int pins_backup;
|
|
||||||
int pins_new;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define UART_DATA( X ) ((struct serial_port_unix *) X)
|
#define UART_DATA( X ) ((struct serial_port_unix *) X)
|
||||||
@ -144,10 +142,6 @@ uart_open(const char *pcPortName)
|
|||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ioctl(sp->fd, TIOCMGET, &sp->pins_backup);
|
|
||||||
sp->pins_new = sp->pins_backup;
|
|
||||||
uart_set_pins(sp, 0);
|
|
||||||
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,13 +281,11 @@ uart_get_speed(serial_port sp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uart_close_ext(const serial_port sp, const bool restore_status)
|
uart_close_ext(const serial_port sp, const bool restore_termios)
|
||||||
{
|
{
|
||||||
if (UART_DATA(sp)->fd >= 0) {
|
if (UART_DATA(sp)->fd >= 0) {
|
||||||
if (restore_status) {
|
if (restore_termios)
|
||||||
tcsetattr(UART_DATA(sp)->fd, TCSANOW, &UART_DATA(sp)->termios_backup);
|
tcsetattr(UART_DATA(sp)->fd, TCSANOW, &UART_DATA(sp)->termios_backup);
|
||||||
ioctl(UART_DATA(sp)->fd, TIOCMSET, &UART_DATA(sp)->pins_backup);
|
|
||||||
}
|
|
||||||
close(UART_DATA(sp)->fd);
|
close(UART_DATA(sp)->fd);
|
||||||
}
|
}
|
||||||
free(sp);
|
free(sp);
|
||||||
@ -395,36 +387,6 @@ uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout)
|
|||||||
return NFC_EIO;
|
return NFC_EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Asserts/deasserts asynchronous control signals of RS232 ports
|
|
||||||
*
|
|
||||||
* @return 0 on success, otherwise a driver error is returned
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
uart_set_pins(serial_port sp, int status)
|
|
||||||
{
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "DTR: %d RTS: %d", (status & UART_DTR) ? 1 : 0, (status & UART_RTS) ? 1 : 0);
|
|
||||||
|
|
||||||
int posix = 0;
|
|
||||||
if (status & UART_DTR)
|
|
||||||
posix |= TIOCM_DTR;
|
|
||||||
if (status & UART_RTS)
|
|
||||||
posix |= TIOCM_RTS;
|
|
||||||
|
|
||||||
/* TODO - Uncomment after fixing Cygwin tcgetattr, which modifies pin status on its own
|
|
||||||
if (UART_DATA(sp)->pins_new == posix)
|
|
||||||
return NFC_SUCCESS;
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (ioctl(UART_DATA(sp)->fd, TIOCMSET, &posix) == -1) {
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set asynchronous control pins.");
|
|
||||||
return NFC_EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
UART_DATA(sp)->pins_new = posix;
|
|
||||||
return NFC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
char **
|
char **
|
||||||
uart_list_ports(void)
|
uart_list_ports(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -57,10 +57,6 @@ uint32_t uart_get_speed(const serial_port sp);
|
|||||||
int uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, int timeout);
|
int uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, int timeout);
|
||||||
int uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout);
|
int uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout);
|
||||||
|
|
||||||
#define UART_DTR (1 << 0)
|
|
||||||
#define UART_RTS (1 << 1)
|
|
||||||
int uart_set_pins(serial_port sp, int status);
|
|
||||||
|
|
||||||
char **uart_list_ports(void);
|
char **uart_list_ports(void);
|
||||||
void uart_list_free(char **acPorts);
|
void uart_list_free(char **acPorts);
|
||||||
|
|
||||||
|
|||||||
@ -333,6 +333,7 @@ pn53x_transceive(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
pnd->last_error = res;
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Chip error: \"%s\" (%02x), returned error: \"%s\" (%d))", pn53x_strerror(pnd), CHIP_DATA(pnd)->last_status_byte, nfc_strerror(pnd), res);
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Chip error: \"%s\" (%02x), returned error: \"%s\" (%d))", pn53x_strerror(pnd), CHIP_DATA(pnd)->last_status_byte, nfc_strerror(pnd), res);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@ -28,6 +28,7 @@ typedef enum {
|
|||||||
#define REG_CommandReg 0x01
|
#define REG_CommandReg 0x01
|
||||||
#define REG_CommandReg_RcvOff (1 << 5)
|
#define REG_CommandReg_RcvOff (1 << 5)
|
||||||
#define REG_CommandReg_PowerDown (1 << 4)
|
#define REG_CommandReg_PowerDown (1 << 4)
|
||||||
|
#define REG_CommandReg_Command_MASK 0x0F
|
||||||
|
|
||||||
#define REG_ComlEnReg 0x02
|
#define REG_ComlEnReg 0x02
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ typedef enum {
|
|||||||
#define REG_FIFODataReg 0x09
|
#define REG_FIFODataReg 0x09
|
||||||
|
|
||||||
#define REG_FIFOLevelReg 0x0A
|
#define REG_FIFOLevelReg 0x0A
|
||||||
|
#define REG_FIFOLevelReg_FlushBuffer (1 << 7)
|
||||||
|
|
||||||
#define REG_WaterLevelReg 0x0B
|
#define REG_WaterLevelReg 0x0B
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ const nfc_baud_rate rc522_iso14443a_supported_baud_rates[] = { NBR_847, NBR_424,
|
|||||||
|
|
||||||
struct rc522_chip_data {
|
struct rc522_chip_data {
|
||||||
const struct rc522_io * io;
|
const struct rc522_io * io;
|
||||||
rc522_type version;
|
uint8_t version;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CHIP_DATA(x) ((struct rc522_chip_data *) (x)->chip_data)
|
#define CHIP_DATA(x) ((struct rc522_chip_data *) (x)->chip_data)
|
||||||
@ -59,7 +59,7 @@ void rc522_data_free(struct nfc_device * pnd) {
|
|||||||
int rc522_read_bulk(struct nfc_device * pnd, uint8_t reg, uint8_t * val, size_t len) {
|
int rc522_read_bulk(struct nfc_device * pnd, uint8_t reg, uint8_t * val, size_t len) {
|
||||||
int ret = CHIP_DATA(pnd)->io->read(pnd, reg, val, len);
|
int ret = CHIP_DATA(pnd)->io->read(pnd, reg, val, len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read register %02X!", reg);
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read register %02X (err: %d)", reg, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ int rc522_write_reg(struct nfc_device * pnd, uint8_t reg, uint8_t val, uint8_t m
|
|||||||
}
|
}
|
||||||
|
|
||||||
int rc522_start_command(struct nfc_device * pnd, rc522_cmd cmd) {
|
int rc522_start_command(struct nfc_device * pnd, rc522_cmd cmd) {
|
||||||
bool needsRX = false;
|
bool needsRX;
|
||||||
|
|
||||||
// Disabling RX saves energy, so based on the command we'll also update the RxOff flag
|
// Disabling RX saves energy, so based on the command we'll also update the RxOff flag
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
@ -123,6 +123,7 @@ int rc522_start_command(struct nfc_device * pnd, rc522_cmd cmd) {
|
|||||||
case CMD_CALCCRC:
|
case CMD_CALCCRC:
|
||||||
case CMD_TRANSMIT:
|
case CMD_TRANSMIT:
|
||||||
case CMD_SOFTRESET:
|
case CMD_SOFTRESET:
|
||||||
|
needsRX = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_RECEIVE:
|
case CMD_RECEIVE:
|
||||||
@ -136,8 +137,7 @@ int rc522_start_command(struct nfc_device * pnd, rc522_cmd cmd) {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Attempted to execute non-existant command: %02X", cmd);
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Attempted to execute non-existant command: %02X", cmd);
|
||||||
pnd->last_error = NFC_ESOFT;
|
return NFC_ESOFT;
|
||||||
return pnd->last_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t regval = cmd;
|
uint8_t regval = cmd;
|
||||||
@ -153,9 +153,6 @@ int rc522_wait_wakeup(struct nfc_device * pnd) {
|
|||||||
timeout_t to;
|
timeout_t to;
|
||||||
timeout_init(&to, 50);
|
timeout_init(&to, 50);
|
||||||
|
|
||||||
// rc522_read_reg updates last_error. Backup it to ignore timeouts
|
|
||||||
int last_error = pnd->last_error;
|
|
||||||
|
|
||||||
while (timeout_check(&to)) {
|
while (timeout_check(&to)) {
|
||||||
int ret = rc522_read_reg(pnd, REG_CommandReg);
|
int ret = rc522_read_reg(pnd, REG_CommandReg);
|
||||||
if (ret < 0 && ret != NFC_ETIMEOUT) {
|
if (ret < 0 && ret != NFC_ETIMEOUT) {
|
||||||
@ -164,19 +161,68 @@ int rc522_wait_wakeup(struct nfc_device * pnd) {
|
|||||||
|
|
||||||
// If the powerdown bit is zero the RC522 is ready to kick asses!
|
// If the powerdown bit is zero the RC522 is ready to kick asses!
|
||||||
if ((ret & REG_CommandReg_PowerDown) == 0) {
|
if ((ret & REG_CommandReg_PowerDown) == 0) {
|
||||||
pnd->last_error = last_error;
|
|
||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "rc522_wait_wakeup timeout!");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_wait_wakeup timeout!");
|
||||||
pnd->last_error = NFC_ETIMEOUT;
|
return NFC_ETIMEOUT;
|
||||||
return pnd->last_error;
|
}
|
||||||
|
|
||||||
|
int rc522_send_baudrate(struct nfc_device * pnd, uint32_t baudrate) {
|
||||||
|
uint8_t regval;
|
||||||
|
|
||||||
|
// MFRC522 datasheet 8.1.3.2
|
||||||
|
switch (baudrate) {
|
||||||
|
case 7200:
|
||||||
|
regval = 0xFA;
|
||||||
|
break;
|
||||||
|
case 9600:
|
||||||
|
regval = 0xEB;
|
||||||
|
break;
|
||||||
|
case 14400:
|
||||||
|
regval = 0xDA;
|
||||||
|
break;
|
||||||
|
case 19200:
|
||||||
|
regval = 0xCB;
|
||||||
|
break;
|
||||||
|
case 38400:
|
||||||
|
regval = 0xAB;
|
||||||
|
break;
|
||||||
|
case 57600:
|
||||||
|
regval = 0x9A;
|
||||||
|
break;
|
||||||
|
case 115200:
|
||||||
|
regval = 0x7A;
|
||||||
|
break;
|
||||||
|
case 128000:
|
||||||
|
regval = 0x74;
|
||||||
|
break;
|
||||||
|
case 230400:
|
||||||
|
regval = 0x5A;
|
||||||
|
break;
|
||||||
|
case 460800:
|
||||||
|
regval = 0x3A;
|
||||||
|
break;
|
||||||
|
case 921600:
|
||||||
|
regval = 0x1C;
|
||||||
|
break;
|
||||||
|
case 1288000:
|
||||||
|
regval = 0x15;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "rc522_write_baudrate unsupported baud rate: %d bps.", baudrate);
|
||||||
|
return NFC_EDEVNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc522_write_reg(pnd, REG_SerialSpeedReg, regval, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc522_soft_reset(struct nfc_device * pnd) {
|
int rc522_soft_reset(struct nfc_device * pnd) {
|
||||||
return
|
return
|
||||||
|
// 1. Send soft reset
|
||||||
rc522_start_command(pnd, CMD_SOFTRESET) ||
|
rc522_start_command(pnd, CMD_SOFTRESET) ||
|
||||||
|
CHIP_DATA(pnd)->io->reset_baud_rate(pnd) ||
|
||||||
rc522_wait_wakeup(pnd);
|
rc522_wait_wakeup(pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,11 +365,7 @@ int rc522_set_property_bool(struct nfc_device * pnd, const nfc_property property
|
|||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = rc522_set_baud_rate(pnd, NBR_106);
|
return rc522_set_baud_rate(pnd, NBR_106);
|
||||||
if (ret) {
|
|
||||||
pnd->last_error = ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
case NP_ACCEPT_MULTIPLE_FRAMES:
|
case NP_ACCEPT_MULTIPLE_FRAMES:
|
||||||
case NP_AUTO_ISO14443_4:
|
case NP_AUTO_ISO14443_4:
|
||||||
@ -333,11 +375,9 @@ int rc522_set_property_bool(struct nfc_device * pnd, const nfc_property property
|
|||||||
case NP_TIMEOUT_COMMAND:
|
case NP_TIMEOUT_COMMAND:
|
||||||
case NP_TIMEOUT_ATR:
|
case NP_TIMEOUT_ATR:
|
||||||
case NP_TIMEOUT_COM:
|
case NP_TIMEOUT_COM:
|
||||||
pnd->last_error = NFC_EINVARG;
|
|
||||||
return NFC_EINVARG;
|
return NFC_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
pnd->last_error = NFC_EINVARG;
|
|
||||||
return NFC_EINVARG;
|
return NFC_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,11 +387,13 @@ 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 rc522_start_command(pnd, CMD_IDLE);
|
return
|
||||||
|
rc522_start_command(pnd, CMD_IDLE) ||
|
||||||
|
rc522_write_reg(pnd, REG_FIFOLevelReg, REG_FIFOLevelReg_FlushBuffer, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc522_powerdown(struct nfc_device * pnd) {
|
int rc522_powerdown(struct nfc_device * pnd) {
|
||||||
return rc522_write_reg(pnd, REG_CommandReg, REG_CommandReg_RcvOff | REG_CommandReg_PowerDown | CMD_IDLE, 0xFF);
|
return rc522_write_reg(pnd, REG_CommandReg, REG_CommandReg_RcvOff | REG_CommandReg_PowerDown | CMD_NOCMDCHANGE, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NXP MFRC522 datasheet section 16.1.1
|
// NXP MFRC522 datasheet section 16.1.1
|
||||||
@ -368,22 +410,9 @@ const uint8_t MFRC522_V2_SELFTEST[FIFO_SIZE] = {
|
|||||||
0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D, 0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F
|
0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D, 0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extracted from a FM17522 with version 0x88. Fudan Semiconductor datasheet does not include it, though.
|
|
||||||
const uint8_t FM17522_SELFTEST[FIFO_SIZE] = {
|
|
||||||
0x00, 0xD6, 0x78, 0x8C, 0xE2, 0xAA, 0x0C, 0x18, 0x2A, 0xB8, 0x7A, 0x7F, 0xD3, 0x6A, 0xCF, 0x0B,
|
|
||||||
0xB1, 0x37, 0x63, 0x4B, 0x69, 0xAE, 0x91, 0xC7, 0xC3, 0x97, 0xAE, 0x77, 0xF4, 0x37, 0xD7, 0x9B,
|
|
||||||
0x7C, 0xF5, 0x3C, 0x11, 0x8F, 0x15, 0xC3, 0xD7, 0xC1, 0x5B, 0x00, 0x2A, 0xD0, 0x75, 0xDE, 0x9E,
|
|
||||||
0x51, 0x64, 0xAB, 0x3E, 0xE9, 0x15, 0xB5, 0xAB, 0x56, 0x9A, 0x98, 0x82, 0x26, 0xEA, 0x2A, 0x62
|
|
||||||
};
|
|
||||||
|
|
||||||
int rc522_self_test(struct nfc_device * pnd) {
|
int rc522_self_test(struct nfc_device * pnd) {
|
||||||
int version = rc522_read_reg(pnd, REG_VersionReg);
|
|
||||||
if (version < 0) {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t * correct;
|
const uint8_t * correct;
|
||||||
switch (version) {
|
switch (CHIP_DATA(pnd)->version) {
|
||||||
case MFRC522_V1:
|
case MFRC522_V1:
|
||||||
correct = MFRC522_V1_SELFTEST;
|
correct = MFRC522_V1_SELFTEST;
|
||||||
break;
|
break;
|
||||||
@ -392,20 +421,17 @@ int rc522_self_test(struct nfc_device * pnd) {
|
|||||||
correct = MFRC522_V2_SELFTEST;
|
correct = MFRC522_V2_SELFTEST;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FM17522:
|
|
||||||
correct = FM17522_SELFTEST;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unknown chip version: 0x%02X", version);
|
return NFC_EDEVNOTSUPP;
|
||||||
return NFC_ECHIP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret;
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Executing self test");
|
||||||
|
|
||||||
uint8_t zeroes[25];
|
uint8_t zeroes[25];
|
||||||
memset(zeroes, 0x00, sizeof(zeroes));
|
memset(zeroes, 0x00, sizeof(zeroes));
|
||||||
|
|
||||||
// MFRC522 datasheet section 16.1.1
|
// MFRC522 datasheet section 16.1.1
|
||||||
ret =
|
int ret =
|
||||||
// 1. Perform a soft reset
|
// 1. Perform a soft reset
|
||||||
rc522_soft_reset(pnd) ||
|
rc522_soft_reset(pnd) ||
|
||||||
// 2. Clear the internal buffer by writing 25 bytes of 0x00 and execute the Mem command
|
// 2. Clear the internal buffer by writing 25 bytes of 0x00 and execute the Mem command
|
||||||
@ -422,9 +448,9 @@ int rc522_self_test(struct nfc_device * pnd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 6. Wait for the RC522 to calculate the selftest values
|
// 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 5ms
|
// The official datasheet does not mentions how much time does it take, let's use 50ms
|
||||||
timeout_t to;
|
timeout_t to;
|
||||||
timeout_init(&to, 5);
|
timeout_init(&to, 50);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!timeout_check(&to)) {
|
if (!timeout_check(&to)) {
|
||||||
@ -455,7 +481,5 @@ int rc522_self_test(struct nfc_device * pnd) {
|
|||||||
return NFC_ECHIP;
|
return NFC_ECHIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHIP_DATA(pnd)->version = version;
|
|
||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,12 +25,14 @@
|
|||||||
struct rc522_io {
|
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 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_self_test(struct nfc_device * pnd);
|
||||||
int rc522_wait_wakeup(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_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);
|
||||||
|
|||||||
@ -38,7 +38,8 @@
|
|||||||
#include "chips/rc522.h"
|
#include "chips/rc522.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
#define RC522_UART_DEFAULT_SPEED 9600
|
#define RC522_UART_BOOT_SPEED 9600
|
||||||
|
#define RC522_UART_DEFAULT_SPEED 115200
|
||||||
#define RC522_UART_DRIVER_NAME "rc522_uart"
|
#define RC522_UART_DRIVER_NAME "rc522_uart"
|
||||||
#define RC522_UART_IO_TIMEOUT 50
|
#define RC522_UART_IO_TIMEOUT 50
|
||||||
|
|
||||||
@ -49,76 +50,173 @@
|
|||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DRIVER_DATA(pnd) ((struct rc522_uart_data*)(pnd->driver_data))
|
#define DRIVER_DATA(pnd) ((struct rc522_uart_data*)(pnd->driver_data))
|
||||||
|
|
||||||
void rc522_uart_close(nfc_device * pnd) {
|
int rc522_uart_wakeup(struct nfc_device * pnd) {
|
||||||
// rc522_idle(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);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
// Release UART port
|
// Release UART port
|
||||||
uart_close(DRIVER_DATA(pnd)->port);
|
uart_close(DRIVER_DATA(pnd)->port);
|
||||||
rc522_data_free(pnd);
|
rc522_data_free(pnd);
|
||||||
nfc_device_free(pnd);
|
nfc_device_free(pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s.", portPath);
|
||||||
|
sp = uart_open(portPath);
|
||||||
|
if (sp == INVALID_SERIAL_PORT) {
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Invalid serial port: %s", portPath);
|
||||||
|
return NFC_EIO;
|
||||||
|
}
|
||||||
|
if (sp == CLAIMED_SERIAL_PORT) {
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Serial port already claimed: %s", portPath);
|
||||||
|
return NFC_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to flush input to be sure first reply does not comes from older byte transceive
|
||||||
|
if ((ret = uart_flush_input(sp, true)) < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_device * pnd = nfc_device_new(context, connstring);
|
||||||
|
if (!pnd) {
|
||||||
|
perror("nfc_device_new");
|
||||||
|
uart_close(sp);
|
||||||
|
return NFC_ESOFT;
|
||||||
|
}
|
||||||
|
pnd->driver = &rc522_uart_driver;
|
||||||
|
|
||||||
|
pnd->driver_data = malloc(sizeof(struct rc522_uart_data));
|
||||||
|
|
||||||
|
if (!pnd->driver_data) {
|
||||||
|
perror("malloc");
|
||||||
|
uart_close(sp);
|
||||||
|
nfc_device_free(pnd);
|
||||||
|
return NFC_ESOFT;
|
||||||
|
}
|
||||||
|
DRIVER_DATA(pnd)->port = sp;
|
||||||
|
|
||||||
|
// Alloc and init chip's data
|
||||||
|
if (rc522_data_new(pnd, &rc522_uart_io)) {
|
||||||
|
perror("rc522_data_new");
|
||||||
|
uart_close(sp);
|
||||||
|
nfc_device_free(pnd);
|
||||||
|
return NFC_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we'll have to address several posibilities:
|
||||||
|
// - The hard reset trick did the work, and the RC522 is up and listening at 9600
|
||||||
|
// - The hard reset didn't work, but the RC522 hasn't been used yet and therefore listens at 9600
|
||||||
|
// - The hard reset didn't work and the RC522 is not using the default, so we'll use the custom provided baud rate
|
||||||
|
|
||||||
|
// Let's try first with boot baud rate
|
||||||
|
if (
|
||||||
|
!rc522_uart_test_baudrate(pnd, RC522_UART_BOOT_SPEED) &&
|
||||||
|
!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);
|
||||||
|
rc522_uart_close(pnd);
|
||||||
|
return NFC_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change now the baud rate
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
size_t rc522_uart_scan(const nfc_context * context, nfc_connstring connstrings[], const size_t connstrings_len) {
|
size_t rc522_uart_scan(const nfc_context * context, nfc_connstring connstrings[], const size_t connstrings_len) {
|
||||||
size_t device_found = 0;
|
size_t device_found = 0;
|
||||||
serial_port sp;
|
|
||||||
char ** acPorts = uart_list_ports();
|
char ** acPorts = uart_list_ports();
|
||||||
const char * acPort;
|
const char * acPort;
|
||||||
size_t iDevice = 0;
|
size_t iDevice = 0;
|
||||||
|
|
||||||
while ((acPort = acPorts[iDevice++])) {
|
while ((acPort = acPorts[iDevice++])) {
|
||||||
sp = uart_open(acPort);
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find RC522 device on serial port: %s at %d baud.", acPort, RC522_UART_DEFAULT_SPEED);
|
|
||||||
|
|
||||||
if (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to flush input to be sure first reply does not comes from older byte transceive
|
|
||||||
uart_flush_input(sp, true);
|
|
||||||
// Serial port claimed but we need to check if a RC522_UART is opened.
|
|
||||||
uart_set_speed(sp, RC522_UART_DEFAULT_SPEED);
|
|
||||||
|
|
||||||
nfc_connstring connstring;
|
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, RC522_UART_DRIVER_NAME, acPort, RC522_UART_DEFAULT_SPEED);
|
||||||
nfc_device * pnd = nfc_device_new(context, connstring);
|
|
||||||
if (!pnd) {
|
nfc_device * pnd;
|
||||||
perror("nfc_device_new");
|
int ret = rc522_uart_create(context, connstring, acPort, RC522_UART_DEFAULT_SPEED, &pnd);
|
||||||
uart_close(sp);
|
if (ret == NFC_ESOFT) {
|
||||||
nfc_device_free(pnd);
|
|
||||||
uart_list_free(acPorts);
|
uart_list_free(acPorts);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pnd->driver = &rc522_uart_driver;
|
if (ret != NFC_SUCCESS) {
|
||||||
|
|
||||||
pnd->driver_data = malloc(sizeof(struct rc522_uart_data));
|
|
||||||
if (!pnd->driver_data) {
|
|
||||||
perror("malloc");
|
|
||||||
uart_close(sp);
|
|
||||||
nfc_device_free(pnd);
|
|
||||||
uart_list_free(acPorts);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
DRIVER_DATA(pnd)->port = sp;
|
|
||||||
|
|
||||||
// Alloc and init chip's data
|
|
||||||
if (rc522_data_new(pnd, &rc522_uart_io)) {
|
|
||||||
perror("rc522_data_new");
|
|
||||||
uart_close(sp);
|
|
||||||
nfc_device_free(pnd);
|
|
||||||
uart_list_free(acPorts);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check communication using self test
|
|
||||||
int res = rc522_self_test(pnd);
|
|
||||||
rc522_uart_close(pnd);
|
|
||||||
if (res < 0) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
rc522_uart_close(pnd);
|
||||||
|
|
||||||
memcpy(connstrings[device_found], connstring, sizeof(nfc_connstring));
|
memcpy(connstrings[device_found], connstring, sizeof(nfc_connstring));
|
||||||
device_found++;
|
device_found++;
|
||||||
@ -133,10 +231,11 @@ size_t rc522_uart_scan(const nfc_context * context, nfc_connstring connstrings[]
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct nfc_device * rc522_uart_open(const nfc_context * context, const nfc_connstring connstring) {
|
struct nfc_device * rc522_uart_open(const nfc_context * context, const nfc_connstring connstring) {
|
||||||
char * port_str;
|
char * port_str = NULL;
|
||||||
char * baud_str;
|
char * baud_str = NULL;
|
||||||
uint32_t baudrate;
|
uint32_t baudrate;
|
||||||
char * endptr;
|
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, RC522_UART_DRIVER_NAME, NULL, &port_str, &baud_str);
|
||||||
switch (decodelvl) {
|
switch (decodelvl) {
|
||||||
@ -162,78 +261,11 @@ struct nfc_device * rc522_uart_open(const nfc_context * context, const nfc_conns
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_port sp;
|
rc522_uart_create(context, connstring, port_str, baudrate, &pnd);
|
||||||
struct nfc_device * pnd = NULL;
|
|
||||||
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d baud.", port_str, baudrate);
|
|
||||||
sp = uart_open(port_str);
|
|
||||||
|
|
||||||
if (sp == INVALID_SERIAL_PORT) {
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Invalid serial port: %s", port_str);
|
|
||||||
free(port_str);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sp == CLAIMED_SERIAL_PORT) {
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Serial port already claimed: %s", port_str);
|
|
||||||
free(port_str);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to flush input to be sure first reply does not comes from older byte transceive
|
|
||||||
uart_flush_input(sp, true);
|
|
||||||
uart_set_speed(sp, baudrate);
|
|
||||||
|
|
||||||
// We have a connection
|
|
||||||
pnd = nfc_device_new(context, connstring);
|
|
||||||
if (!pnd) {
|
|
||||||
perror("nfc_device_new");
|
|
||||||
free(port_str);
|
|
||||||
uart_close(sp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(pnd->name, sizeof(pnd->name), "%s:%s", RC522_UART_DRIVER_NAME, port_str);
|
|
||||||
free(port_str);
|
free(port_str);
|
||||||
pnd->driver = &rc522_uart_driver;
|
|
||||||
pnd->driver_data = malloc(sizeof(struct rc522_uart_data));
|
|
||||||
if (!pnd->driver_data) {
|
|
||||||
perror("malloc");
|
|
||||||
uart_close(sp);
|
|
||||||
nfc_device_free(pnd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
DRIVER_DATA(pnd)->port = sp;
|
|
||||||
|
|
||||||
// Alloc and init chip's data
|
|
||||||
if (!rc522_data_new(pnd, &rc522_uart_io)) {
|
|
||||||
perror("rc522_data_new");
|
|
||||||
uart_close(sp);
|
|
||||||
nfc_device_free(pnd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc522_self_test(pnd)) {
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "rc522_self_test error");
|
|
||||||
rc522_uart_close(pnd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pnd;
|
return pnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 };
|
|
||||||
if ((ret = uart_send(DRIVER_DATA(pnd)->port, rc522_wakeup_preamble, sizeof(rc522_wakeup_preamble), 0)) < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc522_wait_wakeup(pnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define READ 1
|
#define READ 1
|
||||||
#define WRITE 0
|
#define WRITE 0
|
||||||
uint8_t rc522_uart_pack(int reg, int op) {
|
uint8_t rc522_uart_pack(int reg, int op) {
|
||||||
@ -248,11 +280,11 @@ int rc522_uart_read(struct nfc_device * pnd, uint8_t reg, uint8_t * data, size_t
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
if ((ret = uart_send(pnd->driver_data, &cmd, 1, RC522_UART_IO_TIMEOUT)) < 0) {
|
if ((ret = uart_send(DRIVER_DATA(pnd)->port, &cmd, 1, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = uart_receive(pnd->driver_data, data, 1, NULL, RC522_UART_IO_TIMEOUT)) < 0) {
|
if ((ret = uart_receive(DRIVER_DATA(pnd)->port, data, 1, NULL, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,35 +296,34 @@ int rc522_uart_read(struct nfc_device * pnd, uint8_t reg, uint8_t * data, size_t
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
uart_flush_input(DRIVER_DATA(pnd)->port, true);
|
uart_flush_input(DRIVER_DATA(pnd)->port, true);
|
||||||
return pnd->last_error;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc522_uart_write(struct nfc_device * pnd, uint8_t reg, const uint8_t * data, size_t size) {
|
int rc522_uart_write(struct nfc_device * pnd, uint8_t reg, const uint8_t * data, size_t size) {
|
||||||
uint8_t cmd = rc522_uart_pack(reg, WRITE);
|
uint8_t cmd = rc522_uart_pack(reg, WRITE);
|
||||||
|
int ret;
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
// First: send write request
|
// First: send write request
|
||||||
pnd->last_error = uart_send(pnd->driver_data, &cmd, 1, RC522_UART_IO_TIMEOUT);
|
if ((ret = uart_send(DRIVER_DATA(pnd)->port, &cmd, 1, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||||
if (pnd->last_error < 0) {
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second: wait for a reply
|
// Second: wait for a reply
|
||||||
uint8_t reply;
|
uint8_t reply;
|
||||||
pnd->last_error = uart_receive(pnd->driver_data, &reply, 1, NULL, RC522_UART_IO_TIMEOUT);
|
if ((ret = uart_receive(DRIVER_DATA(pnd)->port, &reply, 1, NULL, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||||
if (pnd->last_error < 0) {
|
return ret;
|
||||||
return pnd->last_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Third: compare sent and received. They must match.
|
// Third: compare sent and received. They must match.
|
||||||
if (cmd != reply) {
|
if (cmd != reply) {
|
||||||
pnd->last_error = NFC_EIO;
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "rc522_uart_write ack does not match (sent %02X, received %02X)", cmd, reply);
|
||||||
|
ret = NFC_ECHIP;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fourth: send register data
|
// Fourth: send register data
|
||||||
pnd->last_error = uart_send(pnd->driver_data, data, 1, RC522_UART_IO_TIMEOUT);
|
if ((ret = uart_send(DRIVER_DATA(pnd)->port, data, 1, RC522_UART_IO_TIMEOUT)) < 0) {
|
||||||
if (pnd->last_error < 0) {
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,12 +335,20 @@ int rc522_uart_write(struct nfc_device * pnd, uint8_t reg, const uint8_t * data,
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
uart_flush_input(DRIVER_DATA(pnd)->port, true);
|
uart_flush_input(DRIVER_DATA(pnd)->port, true);
|
||||||
return pnd->last_error;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc522_uart_reset_baud_rate(struct nfc_device * pnd) {
|
||||||
|
uint32_t userBaudRate = DRIVER_DATA(pnd)->baudrate;
|
||||||
|
return
|
||||||
|
rc522_uart_test_baudrate(pnd, RC522_UART_BOOT_SPEED) ||
|
||||||
|
rc522_uart_change_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,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct nfc_driver rc522_uart_driver = {
|
const struct nfc_driver rc522_uart_driver = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user