u_int64_t timeout)
{
int ret;
- u_int8_t prescaler, divisor;
+ u_int8_t prescaler, divisor, irq;
timeout *= TIMER_RELAX_FACTOR;
RC632_TMR_START_TX_END|RC632_TMR_STOP_RX_BEGIN);
/* clear timer irq bit */
- ret = rc632_set_bits(handle, RC632_REG_INTERRUPT_RQ, RC632_IRQ_TIMER);
+ ret = rc632_clear_irqs(handle, RC632_IRQ_TIMER);
+
+ /* enable timer IRQ */
+ ret |= rc632_reg_write(handle, RC632_REG_INTERRUPT_EN, RC632_IRQ_SET | RC632_IRQ_TIMER);
ret |= rc632_reg_write(handle, RC632_REG_TIMER_RELOAD, divisor);
int ret;
u_int8_t stat, irq, cmd;
+ ret = rc632_reg_read(handle, RC632_REG_INTERRUPT_EN, &irq);
+ if (ret < 0)
+ return ret;
+ DEBUGP_INTERRUPT_FLAG("irq_en",irq);
+
+ ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_EN, RC632_IRQ_SET
+ | RC632_IRQ_TIMER
+ | RC632_IRQ_IDLE
+ | RC632_IRQ_RX );
+ if (ret < 0)
+ return ret;
+
while (1) {
rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &stat);
DEBUGP_STATUS_FLAG(stat);
if (stat & RC632_STAT_ERR) {
u_int8_t err;
- rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &err);
+ ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &err);
+ if (ret < 0)
+ return ret;
DEBUGP_ERROR_FLAG(err);
if (err & (RC632_ERR_FLAG_COL_ERR |
RC632_ERR_FLAG_PARITY_ERR |
RC632_ERR_FLAG_FRAMING_ERR |
- RC632_ERR_FLAG_CRC_ERR))
+ /* FIXME: why get we CRC errors in CL2 anticol at iso14443a operation with mifare UL? */
+ /* RC632_ERR_FLAG_CRC_ERR | */
+ 0))
return -EIO;
}
if (stat & RC632_STAT_IRQ) {
ret = rc632_reg_read(handle, RC632_REG_INTERRUPT_RQ, &irq);
if (ret < 0)
return ret;
- DEBUGP_INTERRUPT_FLAG(irq);
+ DEBUGP_INTERRUPT_FLAG("irq_rq",irq);
if (irq & RC632_IRQ_TIMER && !(irq & RC632_IRQ_RX)) {
DEBUGP("timer expired before RX!!\n");
+ rc632_clear_irqs(handle, RC632_IRQ_TIMER);
return -ETIMEDOUT;
}
}
if (ret < 0)
return ret;
- if (cmd == 0)
+ if (cmd == 0) {
+ rc632_clear_irqs(handle, RC632_IRQ_RX);
return 0;
+ }
/* poll every millisecond */
usleep(1000);
/* check if IRQ has occurred (IRQ flag set)*/
if (foo & RC632_STAT_IRQ) {
ret = rc632_reg_read(handle, RC632_REG_INTERRUPT_RQ, &foo);
- DEBUGP_INTERRUPT_FLAG(foo);
+ DEBUGP_INTERRUPT_FLAG("irq_rq",foo);
/* clear all interrupts */
- rc632_clear_irqs(handle, 0xff);
+ ret = rc632_clear_irqs(handle, 0xff);
+ if (ret < 0)
+ return ret;
}
}
if (cmd == 0) {
cur_tx_len = tx_len;
- ret = rc632_reg_write(handle, RC632_REG_COMMAND, 0x00);
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_IDLE);
/* clear all interrupts */
ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_RQ, 0x7f);
- ret = rc632_reg_write(handle, RC632_REG_ERROR_FLAG, 0xff);
{ u_int8_t tmp;
rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &tmp);
DEBUGP_STATUS_FLAG(tmp);
- rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &tmp);
- DEBUGP_STATUS_FLAG(tmp);
- rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &tmp);
- DEBUGP_STATUS_FLAG(tmp);
rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &tmp);
DEBUGP_ERROR_FLAG(tmp);
}
rc632_reg_read(handle, RC632_REG_CHANNEL_REDUNDANCY, &tmp);
//return 0;
- return -1;
+ return -EIO;
}
return rc632_fifo_read(handle, *rx_len, rx_buf);
return ret;
if (rx_avail > *rx_len) {
- //printf("rx_avail(%d) > rx_len(%d), JFYI\n", rx_avail, *rx_len);
+ //DEBUGP("rx_avail(%d) > rx_len(%d), JFYI\n", rx_avail, *rx_len);
} else if (*rx_len > rx_avail)
*rx_len = rx_avail;
/* FIXME: discard additional bytes in FIFO */
}
+#define MAX_WRITE_LEN 16 /* see Sec. 18.6.1.2 of RC632 Spec Rev. 3.2. */
+
+static int
+rc632_write_eeprom(struct rfid_asic_handle *handle, u_int16_t addr,
+ u_int8_t *data, u_int8_t len)
+{
+ u_int8_t sndbuf[MAX_WRITE_LEN + 2];
+ u_int8_t reg;
+ int ret;
+
+ if (len > MAX_WRITE_LEN)
+ return -EINVAL;
+ if (addr < 0x10)
+ return -EPERM;
+ if (addr > 0x1ff)
+ return -EINVAL;
+
+ sndbuf[0] = addr & 0x00ff; /* LSB */
+ sndbuf[1] = addr >> 8; /* MSB */
+ memcpy(&sndbuf[2], data, len);
+
+ ret = rc632_fifo_write(handle, len + 2, sndbuf, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_WRITE_E2);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, ®);
+ if (ret < 0)
+ return ret;
+
+ if (reg & RC632_ERR_FLAG_ACCESS_ERR)
+ return -EPERM;
+
+ while (1) {
+ u_int8_t reg;
+ ret = rc632_reg_read(handle, RC632_REG_SECONDARY_STATUS, ®);
+ if (ret < 0)
+ return ret;
+
+ if (reg & RC632_SEC_ST_E2_READY) {
+ /* the E2Write command must be terminated, See sec. 18.6.1.3 */
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_IDLE);
+ break;
+ }
+ }
+
+ return ret;
+}
+
static int
-rc632_read_eeprom(struct rfid_asic_handle *handle)
+rc632_read_eeprom(struct rfid_asic_handle *handle, u_int16_t addr,
+ u_int8_t *buf, u_int8_t len)
{
- u_int8_t recvbuf[60];
u_int8_t sndbuf[3];
+ u_int8_t reg;
int ret;
- sndbuf[0] = 0x00;
- sndbuf[1] = 0x00;
- sndbuf[2] = 0x3c;
+ sndbuf[0] = addr & 0xff;
+ sndbuf[1] = addr >> 8;
+ sndbuf[2] = len;
ret = rc632_fifo_write(handle, 3, sndbuf, 0x03);
if (ret < 0)
if (ret < 0)
return ret;
- usleep(20000);
-
- ret = rc632_fifo_read(handle, sizeof(recvbuf), recvbuf);
+ ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, ®);
if (ret < 0)
return ret;
- /* FIXME: do something with eeprom contents */
- return ret;
+ if (reg & RC632_ERR_FLAG_ACCESS_ERR)
+ return -EPERM;
+
+ usleep(20000);
+
+ return rc632_fifo_read(handle, len, buf);
}
static int
}, {
.reg = RC632_REG_CRC_PRESET_MSB,
.val = 0xff,
+ /* }, {
+ .reg = RC632_REG_INTERRUPT_EN,
+ .val = RC632_INT_IDLE |
+ RC632_INT_TIMER |
+ RC632_INT_RX |
+ RC632_INT_TX, */
}
};
const struct iso15693_anticol_cmd *acf,
unsigned int acf_len,
struct iso15693_anticol_resp *resp,
- unsigned int *rx_len, char *bit_of_col)
+ unsigned int *rx_len, unsigned char *bit_of_col)
{
u_int8_t error_flag, boc;
//u_int8_t rx_len;
if (acf->req.flags & RFID_15693_F_RATE_HIGH)
rate = ISO15693_T_FAST;
- printf("acf = %s\n", rfid_hexdump(acf, acf_len));
+ DEBUGP("acf = %s\n", rfid_hexdump(acf, acf_len));
ret = rc632_transceive(handle, (u_int8_t *)acf, acf_len,
(u_int8_t *) resp, rx_len,
iso15693_timing[rate][ISO15693_T1], 0);
- if (ret == -ETIMEDOUT)
+ if (ret == -ETIMEDOUT || ret == -EIO)
return ret;
/* determine whether there was a collission */
return ret;
DEBUGP_ERROR_FLAG(error_flag);
+ //FIXME: check for framing and crc errors...
if (error_flag & RC632_ERR_FLAG_COL_ERR) {
/* retrieve bit of collission */
ret = rc632_reg_read(handle, RC632_REG_COLL_POS, &boc);
if (ret < 0)
return ret;
*bit_of_col = boc;
+ } else {
+ *bit_of_col = 0;
+ if (error_flag & RC632_ERR_FLAG_CRC_ERR)
+ return -EIO;
}
return 0;
return 0;
}
+static int
+rc632_mifare_set_key_ee(struct rfid_asic_handle *h, unsigned int addr)
+{
+ int ret;
+ u_int8_t cmd_addr[2];
+ u_int8_t reg;
+
+ if (addr > 0xffff - RFID_MIFARE_KEY_CODED_LEN)
+ return -EINVAL;
+
+ cmd_addr[0] = addr & 0xff; /* LSB */
+ cmd_addr[1] = (addr >> 8) & 0xff; /* MSB */
+
+ /* Terminate probably running command */
+ ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_IDLE);
+ if (ret < 0)
+ return ret;
+
+ /* Write the key address to the FIFO */
+ ret = rc632_fifo_write(h, 2, cmd_addr, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_LOAD_KEY_E2);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_timer_set(h, RC632_TMO_AUTH1);
+ if (ret < 0)
+ return ret;
+
+ //ret = rc632_wait_idle(h, RC632_TMO_AUTH1);
+ ret = rc632_wait_idle_timer(h);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_read(h, RC632_REG_ERROR_FLAG, ®);
+ if (ret < 0)
+ return ret;
+
+ if (reg & RC632_ERR_FLAG_KEY_ERR)
+ return -EINVAL;
+
+ return 0;
+}
+
static int
rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
u_int8_t block)
},
.mifare_classic = {
.setkey = &rc632_mifare_set_key,
+ .setkey_ee = &rc632_mifare_set_key_ee,
.auth = &rc632_mifare_auth,
},
},