X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Frfid_asic_rc632.c;h=28bd5a175d4bad453ea0a09b11b5359ce58b4e12;hb=bd19f4d89b69f5f68f843ae6e0978e57cab16621;hp=da1b1ccfcd0b04f5d6409d6ef1ec67be6efd007a;hpb=693a8bcb83d0088f457fd03e980e654cb3f25a18;p=librfid diff --git a/src/rfid_asic_rc632.c b/src/rfid_asic_rc632.c index da1b1cc..28bd5a1 100644 --- a/src/rfid_asic_rc632.c +++ b/src/rfid_asic_rc632.c @@ -240,7 +240,7 @@ rc632_timer_set(struct rfid_asic_handle *handle, u_int64_t timeout) { int ret; - u_int8_t prescaler, divisor; + u_int8_t prescaler, divisor, irq; timeout *= TIMER_RELAX_FACTOR; @@ -255,7 +255,10 @@ rc632_timer_set(struct rfid_asic_handle *handle, 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); @@ -268,27 +271,44 @@ static int rc632_wait_idle_timer(struct rfid_asic_handle *handle) 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; } } @@ -297,8 +317,10 @@ static int rc632_wait_idle_timer(struct rfid_asic_handle *handle) 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); @@ -333,9 +355,11 @@ rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t timeout) /* 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) { @@ -427,18 +451,13 @@ rc632_transceive(struct rfid_asic_handle *handle, 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); } @@ -506,7 +525,7 @@ rc632_transceive(struct rfid_asic_handle *handle, rc632_reg_read(handle, RC632_REG_CHANNEL_REDUNDANCY, &tmp); //return 0; - return -1; + return -EIO; } return rc632_fifo_read(handle, *rx_len, rx_buf); @@ -554,7 +573,7 @@ rc632_receive(struct rfid_asic_handle *handle, 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; @@ -578,16 +597,69 @@ rc632_receive(struct rfid_asic_handle *handle, /* 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) @@ -597,14 +669,16 @@ rc632_read_eeprom(struct rfid_asic_handle *handle) 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 @@ -1523,6 +1597,12 @@ static struct register_file icode1_std_script[] = { }, { .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, */ } }; @@ -1677,7 +1757,7 @@ rc632_iso15693_transceive_ac(struct rfid_asic_handle *handle, 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; @@ -1688,12 +1768,12 @@ rc632_iso15693_transceive_ac(struct rfid_asic_handle *handle, 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 */ @@ -1702,12 +1782,17 @@ rc632_iso15693_transceive_ac(struct rfid_asic_handle *handle, 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; @@ -1869,6 +1954,52 @@ rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key) 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) @@ -2037,6 +2168,7 @@ const struct rfid_asic rc632 = { }, .mifare_classic = { .setkey = &rc632_mifare_set_key, + .setkey_ee = &rc632_mifare_set_key_ee, .auth = &rc632_mifare_auth, }, },