X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Frfid_asic_rc632.c;h=effe8136723d1133cfe03c6d4845c5c4773f5103;hb=967687ffce29d0034a16be9a0babdc91bf3187cd;hp=4286565da6dca5952f5be6329237d95fe7d3e0e3;hpb=a7c201deb99239d6d98a45b3cc642d8554231a22;p=librfid diff --git a/src/rfid_asic_rc632.c b/src/rfid_asic_rc632.c index 4286565..effe813 100644 --- a/src/rfid_asic_rc632.c +++ b/src/rfid_asic_rc632.c @@ -1,6 +1,6 @@ /* Generic Philips CL RC632 Routines * - * (C) 2005-2006 Harald Welte + * (C) 2005-2008 Harald Welte * */ @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#define DEBUG_LIBRFID - #include #include #include @@ -556,7 +554,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; @@ -580,16 +578,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) @@ -599,14 +650,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 @@ -1690,7 +1743,7 @@ 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, @@ -1871,6 +1924,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) @@ -2039,6 +2138,7 @@ const struct rfid_asic rc632 = { }, .mifare_classic = { .setkey = &rc632_mifare_set_key, + .setkey_ee = &rc632_mifare_set_key_ee, .auth = &rc632_mifare_auth, }, },