X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Frfid_asic_rc632.c;h=28bd5a175d4bad453ea0a09b11b5359ce58b4e12;hb=893a580c6f1c7f1cc50d9bd1acc51c9fd6307a17;hp=8fc5cb9b6172071971c5e8f98bb4c6f8ea4c27e5;hpb=01d6be6f3a51be1aeaac4198b02d29ed3342af81;p=librfid diff --git a/src/rfid_asic_rc632.c b/src/rfid_asic_rc632.c index 8fc5cb9..28bd5a1 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 * */ @@ -43,9 +43,16 @@ #define RC632_TMO_AUTH1 140 +#define TIMER_RELAX_FACTOR 10 + #define ENTER() DEBUGP("entering\n") const struct rfid_asic rc632; +struct register_file { + u_int8_t reg; + u_int8_t val; +}; + /* Register and FIFO Access functions */ static int rc632_reg_write(struct rfid_asic_handle *handle, @@ -160,18 +167,30 @@ rc632_rf_power(struct rfid_asic_handle *handle, int on) } static int -rc632_power_up(struct rfid_asic_handle *handle) +rc632_power(struct rfid_asic_handle *handle, int on) { ENTER(); - return rc632_clear_bits(handle, RC632_REG_CONTROL, - RC632_CONTROL_POWERDOWN); + if (on) + return rc632_clear_bits(handle, RC632_REG_CONTROL, + RC632_CONTROL_POWERDOWN); + else + return rc632_set_bits(handle, RC632_REG_CONTROL, + RC632_CONTROL_POWERDOWN); } static int -rc632_power_down(struct rfid_asic_handle *handle) +rc632_execute_script(struct rfid_asic_handle *h, struct register_file *f, + int len) { - return rc632_set_bits(handle, RC632_REG_CONTROL, - RC632_CONTROL_POWERDOWN); + int i, ret; + + for (i = 0; i < len; i++) { + ret = rc632_reg_write(h, f[i].reg, f[i].val); + if (ret < 0) + return ret; + } + + return 0; } /* calculate best 8bit prescaler and divisor for given usec timeout */ @@ -221,7 +240,9 @@ 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; ret = best_prescaler(timeout, &prescaler, &divisor); @@ -234,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); @@ -245,32 +269,58 @@ rc632_timer_set(struct rfid_asic_handle *handle, static int rc632_wait_idle_timer(struct rfid_asic_handle *handle) { int ret; - u_int8_t irq, cmd; + u_int8_t stat, irq, cmd; - while (1) { - rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &irq); - rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &irq); - ret = rc632_reg_read(handle, RC632_REG_INTERRUPT_RQ, &irq); - if (ret < 0) - return ret; + ret = rc632_reg_read(handle, RC632_REG_INTERRUPT_EN, &irq); + if (ret < 0) + return ret; + DEBUGP_INTERRUPT_FLAG("irq_en",irq); - /* FIXME: currently we're lazy: If we actually received - * something even after the timer expired, we accept it */ - if (irq & RC632_IRQ_TIMER && !(irq & RC632_IRQ_RX)) { - u_int8_t foo; - rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &foo); - if (foo & 0x04) - rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &foo); + 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; + 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 | + /* 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_rq",irq); - return -110; + if (irq & RC632_IRQ_TIMER && !(irq & RC632_IRQ_RX)) { + DEBUGP("timer expired before RX!!\n"); + rc632_clear_irqs(handle, RC632_IRQ_TIMER); + return -ETIMEDOUT; + } } ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd); 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); @@ -286,6 +336,8 @@ rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t timeout) int ret, cycles = 0; #define USLEEP_PER_CYCLE 128 + timeout *= TIMER_RELAX_FACTOR; + while (cmd != 0) { ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd); if (ret < 0) @@ -303,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) { @@ -315,7 +369,7 @@ rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t timeout) } /* Abort after some timeout */ - if (cycles > timeout*100/USLEEP_PER_CYCLE) { + if (cycles > timeout/USLEEP_PER_CYCLE) { DEBUGP("timeout...\n"); return -ETIMEDOUT; } @@ -336,6 +390,8 @@ rc632_transmit(struct rfid_asic_handle *handle, int ret, cur_len; const u_int8_t *cur_buf = buf; + DEBUGP("timeout=%u, tx_len=%u\n", timeout, len); + if (len > 64) cur_len = 64; else @@ -387,22 +443,29 @@ rc632_transceive(struct rfid_asic_handle *handle, u_int8_t rx_avail; const u_int8_t *cur_tx_buf = tx_buf; - DEBUGP("timer=%u, rx_len=%u, tx_len=%u,", timer, rx_len, tx_len); + DEBUGP("timeout=%u, rx_len=%u, tx_len=%u\n", timer, *rx_len, tx_len); if (tx_len > 64) cur_tx_len = 64; else cur_tx_len = tx_len; + + ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_IDLE); + /* clear all interrupts */ + ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_RQ, 0x7f); + + { u_int8_t 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); + } + ret = rc632_timer_set(handle, timer); if (ret < 0) return ret; - ret = rc632_reg_write(handle, RC632_REG_COMMAND, 0x00); - /* clear all interrupts */ - ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_RQ, 0x7f); - ret = rc632_reg_write(handle, RC632_REG_ERROR_FLAG, 0xff); - do { ret = rc632_fifo_write(handle, cur_tx_len, cur_tx_buf, 0x03); if (ret < 0) @@ -432,10 +495,10 @@ rc632_transceive(struct rfid_asic_handle *handle, if (toggle == 1) tcl_toggle_pcb(handle); - //ret = rc632_wait_idle_timer(handle); - ret = rc632_wait_idle(handle, timer); + ret = rc632_wait_idle_timer(handle); + //ret = rc632_wait_idle(handle, timer); - DEBUGP("rc632_wait_idle>>ret=%d %s\n",ret,(ret==-ETIMEDOUT)?"ETIMEDOUT":""); + DEBUGP("rc632_wait_idle >> ret=%d %s\n",ret,(ret==-ETIMEDOUT)?"ETIMEDOUT":""); if (ret < 0) return ret; @@ -462,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); @@ -479,21 +542,29 @@ rc632_receive(struct rfid_asic_handle *handle, int ret, cur_tx_len, i; u_int8_t rx_avail; - /* - DEBUGP("timer = %u\n", timer); - ret = rc632_timer_set(handle, timer*10); - if (ret < 0) - return ret; - /* + DEBUGP("timeout=%u, rx_len=%u\n", timer, *rx_len); ret = rc632_reg_write(handle, RC632_REG_COMMAND, 0x00); /* IDLE */ /* clear all interrupts */ ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_RQ, 0x7f); + ret = rc632_timer_set(handle, timer); + if (ret < 0) + return ret; + ret = rc632_reg_write(handle, RC632_REG_COMMAND,RC632_CMD_RECEIVE); if (ret < 0) - return ret; + return ret; + + /* the timer cannot start in hardware based on the command we just + * sent. this means that our timing will always be quite a bit more lax, + * i.e. we'll always wait for a bit longer than the specs ask us to. */ + ret = rc632_set_bits(handle, RC632_REG_CONTROL, + RC632_CONTROL_TIMER_START); + if (ret < 0) + return ret; - ret = rc632_wait_idle(handle, timer); + //ret = rc632_wait_idle(handle, timer); + ret = rc632_wait_idle_timer(handle); if (ret < 0) return ret; @@ -502,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; @@ -526,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) @@ -545,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 @@ -628,14 +754,14 @@ rc632_init(struct rfid_asic_handle *ah) int ret; /* switch off rf (make sure PICCs are reset at init time) */ - ret = rc632_power_down(ah); + ret = rc632_power(ah, 0); if (ret < 0) return ret; usleep(10000); /* switch on rf */ - ret = rc632_power_up(ah); + ret = rc632_power(ah, 1); if (ret < 0) return ret; @@ -674,7 +800,7 @@ rc632_fini(struct rfid_asic_handle *ah) if (ret < 0) return ret; - ret = rc632_power_down(ah); + ret = rc632_power(ah, 0); if (ret < 0) return ret; @@ -713,112 +839,88 @@ rc632_close(struct rfid_asic_handle *h) free_asic_handle(h); } - -/* - * Philips CL RC632 primitives for ISO 14443-A compliant PICC's - * - * (C) 2005-2006 by Harald Welte - * +/* + * ISO14443A */ +/* Register file for ISO14443A standard */ +static struct register_file iso14443a_script[] = { + { + .reg = RC632_REG_TX_CONTROL, + .val = RC632_TXCTRL_MOD_SRC_INT | + RC632_TXCTRL_TX2_INV | + RC632_TXCTRL_FORCE_100_ASK | + RC632_TXCTRL_TX2_RF_EN | + RC632_TXCTRL_TX1_RF_EN, + }, { + .reg = RC632_REG_CW_CONDUCTANCE, + .val = CM5121_CW_CONDUCTANCE, + }, { + .reg = RC632_REG_MOD_CONDUCTANCE, + .val = CM5121_MOD_CONDUCTANCE, + }, { + .reg = RC632_REG_CODER_CONTROL, + .val = (RC632_CDRCTRL_TXCD_14443A | + RC632_CDRCTRL_RATE_106K), + }, { + .reg = RC632_REG_MOD_WIDTH, + .val = 0x13, + }, { + .reg = RC632_REG_MOD_WIDTH_SOF, + .val = 0x3f, + }, { + .reg = RC632_REG_TYPE_B_FRAMING, + .val = 0x00, + }, { + .reg = RC632_REG_RX_CONTROL1, + .val = (RC632_RXCTRL1_GAIN_35DB | + RC632_RXCTRL1_ISO14443 | + RC632_RXCTRL1_SUBCP_8), + }, { + .reg = RC632_REG_DECODER_CONTROL, + .val = (RC632_DECCTRL_MANCHESTER | + RC632_DECCTRL_RXFR_14443A), + }, { + .reg = RC632_REG_BIT_PHASE, + .val = CM5121_14443A_BITPHASE, + }, { + .reg = RC632_REG_RX_THRESHOLD, + .val = CM5121_14443A_THRESHOLD, + }, { + .reg = RC632_REG_BPSK_DEM_CONTROL, + .val = 0x00, + }, { + .reg = RC632_REG_RX_CONTROL2, + .val = (RC632_RXCTRL2_DECSRC_INT | + RC632_RXCTRL2_CLK_Q), + }, { + .reg = RC632_REG_RX_WAIT, + //.val = 0x03, /* default value */ + .val = 0x06, /* omnikey */ + }, { + .reg = RC632_REG_CHANNEL_REDUNDANCY, + .val = (RC632_CR_PARITY_ENABLE | + RC632_CR_PARITY_ODD), + }, { + .reg = RC632_REG_CRC_PRESET_LSB, + .val = 0x63, + }, { + .reg = RC632_REG_CRC_PRESET_MSB, + .val = 0x63, + }, +}; + static int rc632_iso14443a_init(struct rfid_asic_handle *handle) { int ret; - /* FIXME: some fifo work (drain fifo?) */ - /* flush fifo (our way) */ ret = rc632_reg_write(handle, RC632_REG_CONTROL, RC632_CONTROL_FIFO_FLUSH); - ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL, - (RC632_TXCTRL_TX1_RF_EN | - RC632_TXCTRL_TX2_RF_EN | - RC632_TXCTRL_TX2_INV | - RC632_TXCTRL_FORCE_100_ASK | - RC632_TXCTRL_MOD_SRC_INT)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE, - CM5121_CW_CONDUCTANCE); - if (ret < 0) - return ret; - - /* Since FORCE_100_ASK is set (cf mc073930.pdf), this line may be left out? */ - ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE, - CM5121_MOD_CONDUCTANCE); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CODER_CONTROL, - (RC632_CDRCTRL_TXCD_14443A | - RC632_CDRCTRL_RATE_106K)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH_SOF, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1, - (RC632_RXCTRL1_GAIN_35DB | - RC632_RXCTRL1_ISO14443 | - RC632_RXCTRL1_SUBCP_8)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_DECODER_CONTROL, - (RC632_DECCTRL_MANCHESTER | - RC632_DECCTRL_RXFR_14443A)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE, - CM5121_14443A_BITPHASE); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD, - CM5121_14443A_THRESHOLD); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2, - (RC632_RXCTRL2_DECSRC_INT | - RC632_RXCTRL2_CLK_Q)); - if (ret < 0) - return ret; - - /* Omnikey proprietary driver has 0x03, but 0x06 is the default reset value ?!? */ - ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x06); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, - (RC632_CR_PARITY_ENABLE | - RC632_CR_PARITY_ODD)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0x63); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0x63); + ret = rc632_execute_script(handle, iso14443a_script, + ARRAY_SIZE(iso14443a_script)); if (ret < 0) return ret; @@ -1052,156 +1154,24 @@ rc632_iso14443a_transceive_acf(struct rfid_asic_handle *handle, return 0; } -static void uuid_reversecpy(unsigned char* out, unsigned char* in, int len) -{ - int i = 0; - while (len > 0) { - out[i] = in[len]; - len--; - i++; - } -} - - -static int -rc632_iso15693_transceive_ac(struct rfid_asic_handle *handle, - struct iso15693_anticol_cmd *acf, - unsigned char uuid[ISO15693_UID_LEN], - char *bit_of_col) -{ - u_int8_t boc; - u_int8_t error_flag, tmp; - u_int8_t rx_len; - - int ret, tx_len, mask_len_bytes; - - struct iso15693_request_inventory { - struct iso15693_request head; - unsigned char mask_length; - /* mask_value[0] + (maybe crc[2]) */ - unsigned char data[ISO15693_UID_LEN]; - } req; - - struct { - struct iso15693_response head; - unsigned char dsfid; - unsigned char uuid[ISO15693_UID_LEN]; - } rx_buf; - - memset(uuid, 0, ISO15693_UID_LEN); - - *bit_of_col = 0; - rx_len = sizeof(rx_buf); - mask_len_bytes = (acf->mask_len % 8) ? acf->mask_len/8+1 : acf->mask_len/8; - +enum rc632_rate { + RC632_RATE_106 = 0x00, + RC632_RATE_212 = 0x01, + RC632_RATE_424 = 0x02, + RC632_RATE_848 = 0x03, +}; - if (acf->current_slot == 0) { - /* first call: transmit Inventory frame */ - DEBUGP("first_frame\n"); - req.head.command = ISO15693_CMD_INVENTORY; - req.head.flags = (acf->flags & 0xf0) - | RFID_15693_F_INV_TABLE_5 - | RFID_15693_F_RATE_HIGH; - //| RFID_15693_F_SUBC_TWO | RFID_15693_F_RATE_HIGH; - req.mask_length = acf->mask_len; - memset(req.data, 0, ISO15693_UID_LEN); - memcpy(req.data, acf->mask_bits, mask_len_bytes); +struct rx_config { + u_int8_t subc_pulses; + u_int8_t rx_coding; + u_int8_t rx_threshold; + u_int8_t bpsk_dem_ctrl; +}; - tx_len = sizeof(struct iso15693_request) + 1 + mask_len_bytes; - - ret = rc632_transceive(handle, (u_int8_t *)&req, tx_len, - (u_int8_t *)&rx_buf, &rx_len, 10, 0); - acf->current_slot = 1; - DEBUGP("rc632_transceive ret: %d rx_len: %d\n",ret,rx_len); - /* if ((ret < 0)&&(ret != -ETIMEDOUT)) - return ret; */ - - } else { - /* second++ call: end timeslot with EOFpulse and read */ - DEBUGP("second++_frame\n"); - if ((acf->current_slot > 16) || - ((acf->flags & RFID_15693_F5_NSLOTS_1 == 0) - && (acf->current_slot > 1))) { - - memset(uuid, 0, ISO15693_UID_LEN); - return -1; - } - - /* reset EOF-pulse-bit to 0 */ - ret = rc632_clear_bits(handle, RC632_REG_CODER_CONTROL, - RC632_CDRCTRL_15693_EOF_PULSE); - usleep(50); - /* generate EOF pulse */ - ret = rc632_set_bits(handle, RC632_REG_CODER_CONTROL, - RC632_CDRCTRL_15693_EOF_PULSE); - if (ret < 0) - return ret; - // DEBUGP("waiting for EOF pulse\n"); - // ret = rc632_wait_idle(handle, 10); //wait for idle - - rx_len = sizeof(rx_buf); - ret = rc632_receive(handle, (u_int8_t*)&rx_buf, &rx_len, 50); - DEBUGP("rc632_receive ret: %d rx_len: %d\n", ret, rx_len); - acf->current_slot++; - - /* if ((ret < 0)&&(ret != -ETIMEDOUT)) - return ret; */ - } - - rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &tmp); - DEBUGP_STATUS_FLAG(tmp); - - if (ret == -ETIMEDOUT) { - /* no VICC answer in this timeslot*/ - memset(uuid, 0, ISO15693_UID_LEN); - return -ETIMEDOUT; - } else { - /* determine whether there was a collission */ - ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag); - DEBUGP_ERROR_FLAG(error_flag); - if (ret < 0) - return ret; - - 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; - memcpy(uuid, rx_buf.uuid, ISO15693_UID_LEN); - // uuid_reversecpy(uuid, rx_buf.uuid, ISO15693_UID_LEN); - DEBUGP("Collision in slot %d bit %d\n", - acf->current_slot,boc); - return -ECOLLISION; - } else { - /* no collision-> retrieve uuid */ - DEBUGP("no collision in slot %d\n", acf->current_slot); - memcpy(uuid, rx_buf.uuid, ISO15693_UID_LEN); - //uuid_reversecpy(uuid, rx_buf.uuid, ISO15693_UID_LEN); - } - } - - return 0; -} - -enum rc632_rate { - RC632_RATE_106 = 0x00, - RC632_RATE_212 = 0x01, - RC632_RATE_424 = 0x02, - RC632_RATE_848 = 0x03, -}; - -struct rx_config { - u_int8_t subc_pulses; - u_int8_t rx_coding; - u_int8_t rx_threshold; - u_int8_t bpsk_dem_ctrl; -}; - -struct tx_config { - u_int8_t rate; - u_int8_t mod_width; -}; +struct tx_config { + u_int8_t rate; + u_int8_t mod_width; +}; static struct rx_config rx_configs[] = { { @@ -1305,6 +1275,79 @@ static int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle, return 0; } +#if 0 +static struct register_file iso14443b_script[] = { + { + .reg = RC632_REG_TX_CONTROL, + .val = (RC632_TXCTRL_TX1_RF_EN | + RC632_TXCTRL_TX2_RF_EN | + RC632_TXCTRL_TX2_INV | + RC632_TXCTRL_MOD_SRC_INT), + }, { + .reg = RC632_REG_CW_CONDUCTANCE, + .val = 0x3f, + }, { + .reg = RC632_REG_MOD_CONDUCTANCE, + .val = 0x04, + }, { + .reg = RC632_REG_CODER_CONTROL, + .val = (RC632_CDRCTRL_TXCD_NRZ | + RC632_CDRCTRL_RATE_14443B), + }, { + .reg = RC632_REG_MOD_WIDTH, + .val = 0x13, + }, { + .reg = RC632_REG_MOD_WIDTH_SOF, + .val = 0x3f, + }, { + .reg = RC632_REG_TYPE_B_FRAMING, + .val = (RC632_TBFRAMING_SOF_11L_3H | + (6 << RC632_TBFRAMING_SPACE_SHIFT) | + RC632_TBFRAMING_EOF_11); + }, { + .reg = RC632_REG_RX_CONTROL1, + .val = (RC632_RXCTRL1_GAIN_35DB | + RC632_RXCTRL1_ISO14443, + RC632_RXCTRL1_SUBCP_8), + }, { + .reg = RC632_REG_DECODER_CONTROL, + .val = (RC632_DECCTRL_BPSK | + RC632_DECCTRL_RXFR_14443B), + }, { + .reg = RC632_REG_BIT_PHASE, + .val = CM5121_14443B_BITPHASE, + }, { + .reg = RC632_REG_RX_THRESHOLD, + .val = CM5121_14443B_THRESHOLD, + }, { + .reg = RC632_REG_BPSK_DEM_CONTROL, + .val = ((0x2 & RC632_BPSKD_TAUB_MASK)< 0) { + out[i] = in[len]; + len--; + i++; + } +} + +static int +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, unsigned char *bit_of_col) +{ + u_int8_t error_flag, boc; + //u_int8_t rx_len; + + int ret, tx_len, mask_len_bytes; + unsigned int rate = ISO15693_T_SLOW; + + if (acf->req.flags & RFID_15693_F_RATE_HIGH) + rate = ISO15693_T_FAST; + + 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 || ret == -EIO) + return ret; + + /* determine whether there was a collission */ + ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag); + if (ret < 0) + 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; + +#if 0 + *bit_of_col = 0; + + mask_len_bytes = (acf->mask_len % 8) ? acf->mask_len/8+1 : acf->mask_len/8; + + if (acf->current_slot == 0) { + /* first call: transmit Inventory frame */ + DEBUGP("first_frame\n"); + + tx_len = sizeof(struct iso15693_request) + 1 + mask_len_bytes; + + ret = rc632_transceive(handle, (u_int8_t *)&req, tx_len, + (u_int8_t *)&rx_buf, &rx_len, ISO15693_T1, 0); + acf->current_slot = 1; + DEBUGP("rc632_transceive ret: %d rx_len: %d\n",ret,rx_len); + /* if ((ret < 0)&&(ret != -ETIMEDOUT)) + return ret; */ + + } else { + /* second++ call: end timeslot with EOFpulse and read */ + DEBUGP("second++_frame\n"); + if ((acf->current_slot > 16) || + ((acf->flags & RFID_15693_F5_NSLOTS_1 == 0) + && (acf->current_slot > 1))) { + + memset(uuid, 0, ISO15693_UID_LEN); + return -1; + } + + /* reset EOF-pulse-bit to 0 */ + ret = rc632_clear_bits(handle, RC632_REG_CODER_CONTROL, + RC632_CDRCTRL_15693_EOF_PULSE); + usleep(50); + /* generate EOF pulse */ + ret = rc632_set_bits(handle, RC632_REG_CODER_CONTROL, + RC632_CDRCTRL_15693_EOF_PULSE); + if (ret < 0) + return ret; + // DEBUGP("waiting for EOF pulse\n"); + // ret = rc632_wait_idle(handle, 10); //wait for idle + + rx_len = sizeof(rx_buf); + ret = rc632_receive(handle, (u_int8_t*)&rx_buf, &rx_len, ISO15693_T3); + DEBUGP("rc632_receive ret: %d rx_len: %d\n", ret, rx_len); + acf->current_slot++; + + /* if ((ret < 0)&&(ret != -ETIMEDOUT)) + return ret; */ + } + + rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &tmp); + DEBUGP_STATUS_FLAG(tmp); + + if (ret == -ETIMEDOUT) { + /* no VICC answer in this timeslot*/ + memset(uuid, 0, ISO15693_UID_LEN); + return -ETIMEDOUT; + } else { + /* determine whether there was a collission */ + ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag); + DEBUGP_ERROR_FLAG(error_flag); + if (ret < 0) + return ret; + + 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; + memcpy(uuid, rx_buf.uuid, ISO15693_UID_LEN); + // uuid_reversecpy(uuid, rx_buf.uuid, ISO15693_UID_LEN); + DEBUGP("Collision in slot %d bit %d\n", + acf->current_slot,boc); + return -ECOLLISION; + } else { + /* no collision-> retrieve uuid */ + DEBUGP("no collision in slot %d\n", acf->current_slot); + memcpy(uuid, rx_buf.uuid, ISO15693_UID_LEN); + //uuid_reversecpy(uuid, rx_buf.uuid, ISO15693_UID_LEN); + } + } + + return 0; +#endif +} + struct mifare_authcmd { u_int8_t auth_cmd; u_int8_t block_address; @@ -1745,7 +1935,58 @@ rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key) if (ret < 0) return ret; - ret = rc632_wait_idle(h, RC632_TMO_AUTH1); + 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_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; @@ -1803,7 +2044,12 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, } /* Wait until transmitter is idle */ - ret = rc632_wait_idle(h, RC632_TMO_AUTH1); + 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; @@ -1821,13 +2067,19 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, if (ret < 0) return ret; + /* Wait until transmitter is idle */ + ret = rc632_timer_set(h, RC632_TMO_AUTH1); + if (ret < 0) + return ret; + /* Send Authent2 Command */ ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT2); if (ret < 0) return ret; /* Wait until transmitter is idle */ - ret = rc632_wait_idle(h, RC632_TMO_AUTH1); + //ret = rc632_wait_idle(h, RC632_TMO_AUTH1); + ret = rc632_wait_idle_timer(h); if (ret < 0) return ret; @@ -1879,30 +2131,44 @@ rc632_mifare_transceive(struct rfid_asic_handle *handle, return 0; } + +static int +rc632_layer2_init(struct rfid_asic_handle *h, enum rfid_layer2_id l2) +{ + switch (l2) { + case RFID_LAYER2_ISO14443A: + return rc632_iso14443a_init(h); + case RFID_LAYER2_ISO14443B: + return rc632_iso14443b_init(h); + case RFID_LAYER2_ISO15693: + return rc632_iso15693_init(h); + case RFID_LAYER2_ICODE1: + return rc632_iso15693_icode1_init(h); + default: + return -EINVAL; + } +} + const struct rfid_asic rc632 = { .name = "Philips CL RC632", .fc = ISO14443_FREQ_CARRIER, .priv.rc632 = { .fn = { - .power_up = &rc632_power_up, - .power_down = &rc632_power_down, + .power = &rc632_power, .rf_power = &rc632_rf_power, .transceive = &rc632_iso14443ab_transceive, + .init = &rc632_layer2_init, .iso14443a = { - .init = &rc632_iso14443a_init, .transceive_sf = &rc632_iso14443a_transceive_sf, .transceive_acf = &rc632_iso14443a_transceive_acf, .set_speed = &rc632_iso14443a_set_speed, }, - .iso14443b = { - .init = &rc632_iso14443b_init, - }, .iso15693 = { - .init = &rc632_iso15693_init, .transceive_ac = &rc632_iso15693_transceive_ac, }, .mifare_classic = { .setkey = &rc632_mifare_set_key, + .setkey_ee = &rc632_mifare_set_key_ee, .auth = &rc632_mifare_auth, }, },