X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Frfid_asic_rc632.c;h=f8a8483f4eda41acc9742e24abc04961b7f3f881;hb=fb488a0210b1c694dba762ba086f43a5d4655c4f;hp=4377d7351498c10e1c85dc77d394a9b4b522c45f;hpb=5a21610814e1d8a6fd3b08ac030486b998871bb4;p=librfid diff --git a/src/rfid_asic_rc632.c b/src/rfid_asic_rc632.c index 4377d73..f8a8483 100644 --- a/src/rfid_asic_rc632.c +++ b/src/rfid_asic_rc632.c @@ -1,6 +1,6 @@ /* Generic Philips CL RC632 Routines * - * (C) Harald Welte + * (C) 2005-2006 Harald Welte * */ @@ -23,14 +23,15 @@ #include #include #include +#include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "rfid_iso14443_common.h" #include "rc632.h" @@ -40,7 +41,7 @@ #define RC632_TMO_AUTH1 14000 #define ENTER() DEBUGP("entering\n") -struct rfid_asic rc632; +const struct rfid_asic rc632; /* Register and FIFO Access functions */ static int @@ -96,6 +97,23 @@ rc632_set_bits(struct rfid_asic_handle *handle, return rc632_reg_write(handle, reg, (tmp|val)&0xff); } +static int +rc632_set_bit_mask(struct rfid_asic_handle *handle, + u_int8_t reg, u_int8_t mask, u_int8_t val) +{ + int ret; + u_int8_t tmp; + + ret = rc632_reg_read(handle, reg, &tmp); + if (ret < 0) + return ret; + + /* if bits are already like we want them, abort */ + if ((tmp & mask) == val) + return 0; + + return rc632_reg_write(handle, reg, (tmp & ~mask)|(val & mask)); +} static int rc632_clear_bits(struct rfid_asic_handle *handle, @@ -147,13 +165,117 @@ rc632_power_down(struct rfid_asic_handle *handle) RC632_CONTROL_POWERDOWN); } -/* Stupid RC623 implementations don't evaluate interrupts but poll the +/* calculate best 8bit prescaler and divisor for given usec timeout */ +static int best_prescaler(u_int64_t timeout, u_int8_t *prescaler, + u_int8_t *divisor) +{ + u_int8_t best_prescaler, best_divisor, i; + int64_t smallest_diff; + + smallest_diff = LLONG_MAX; + best_prescaler = 0; + + for (i = 0; i < 21; i++) { + u_int64_t clk, tmp_div, res; + int64_t diff; + clk = 13560000 / (1 << i); + tmp_div = (clk * timeout) / 1000000; + tmp_div++; + + if ((tmp_div > 0xff) || (tmp_div > clk)) + continue; + + res = 1000000 / (clk / tmp_div); + diff = res - timeout; + + if (diff < 0) + continue; + + if (diff < smallest_diff) { + best_prescaler = i; + best_divisor = tmp_div; + smallest_diff = diff; + } + } + + *prescaler = best_prescaler; + *divisor = best_divisor; + + DEBUGP("timeout %u usec, prescaler = %u, divisor = %u\n", + timeout, best_prescaler, best_divisor); + + return 0; +} + +static int +rc632_timer_set(struct rfid_asic_handle *handle, + u_int64_t timeout) +{ + int ret; + u_int8_t prescaler, divisor; + + ret = best_prescaler(timeout, &prescaler, &divisor); + + ret = rc632_reg_write(handle, RC632_REG_TIMER_CLOCK, + prescaler & 0x1f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_TIMER_CONTROL, + 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_reg_write(handle, RC632_REG_TIMER_RELOAD, divisor); + + return ret; +} + +/* Wait until RC632 is idle or TIMER IRQ has happened */ +static int rc632_wait_idle_timer(struct rfid_asic_handle *handle) +{ + int ret; + u_int8_t 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; + + /* 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); + + return -110; + } + + ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd); + if (ret < 0) + return ret; + + if (cmd == 0) + return 0; + + /* poll every millisecond */ + usleep(1000); + } +} + +/* Stupid RC632 implementations don't evaluate interrupts but poll the * command register for "status idle" */ static int rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t timeout) { u_int8_t cmd = 0xff; - int ret; + int ret, cycles = 0; +#define USLEEP_PER_CYCLE 128 while (cmd != 0) { ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd); @@ -172,9 +294,13 @@ rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t timeout) rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &foo); } - usleep(100); + /* Abort after some timeout */ + if (cycles > timeout*100/USLEEP_PER_CYCLE) { + return -ETIMEDOUT; + } - /* Fixme: Abort after some timeout */ + cycles++; + usleep(USLEEP_PER_CYCLE); } return 0; @@ -186,15 +312,36 @@ rc632_transmit(struct rfid_asic_handle *handle, u_int8_t len, u_int64_t timeout) { - int ret; + int ret, cur_len; + const u_int8_t *cur_buf = buf; - ret = rc632_fifo_write(handle, len, buf, 0x03); - if (ret < 0) - return ret; + if (len > 64) + cur_len = 64; + else + cur_len = len; + + do { + ret = rc632_fifo_write(handle, cur_len, cur_buf, 0x03); + if (ret < 0) + return ret; - ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_TRANSMIT); - if (ret < 0) - return ret; + if (cur_buf == buf) { + /* only start transmit first time */ + ret = rc632_reg_write(handle, RC632_REG_COMMAND, + RC632_CMD_TRANSMIT); + if (ret < 0) + return ret; + } + + cur_buf += cur_len; + if (cur_buf < buf + len) { + cur_len = buf - cur_buf; + if (cur_len > 64) + cur_len = 64; + } else + cur_len = 0; + + } while (cur_len); return rc632_wait_idle(handle, timeout); } @@ -207,36 +354,78 @@ tcl_toggle_pcb(struct rfid_asic_handle *handle) } static int -rc632_transcieve(struct rfid_asic_handle *handle, +rc632_transceive(struct rfid_asic_handle *handle, const u_int8_t *tx_buf, u_int8_t tx_len, u_int8_t *rx_buf, u_int8_t *rx_len, - unsigned int timer, + u_int64_t timer, unsigned int toggle) { - int ret; + int ret, cur_tx_len; + u_int8_t rx_avail; + const u_int8_t *cur_tx_buf = tx_buf; - ret = rc632_fifo_write(handle, tx_len, tx_buf, 0x03); - if (ret < 0) - return ret; + DEBUGP("timer = %u\n", timer); - ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_TRANSCIEVE); + if (tx_len > 64) + cur_tx_len = 64; + else + cur_tx_len = tx_len; + + ret = rc632_timer_set(handle, timer*10); 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); + + do { + ret = rc632_fifo_write(handle, cur_tx_len, cur_tx_buf, 0x03); + if (ret < 0) + return ret; + + if (cur_tx_buf == tx_buf) { + ret = rc632_reg_write(handle, RC632_REG_COMMAND, + RC632_CMD_TRANSCEIVE); + if (ret < 0) + return ret; + } + + cur_tx_buf += cur_tx_len; + if (cur_tx_buf < tx_buf + tx_len) { + u_int8_t fifo_fill; + ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, + &fifo_fill); + if (ret < 0) + return ret; + + cur_tx_len = 64 - fifo_fill; + printf("refilling tx fifo with %u bytes\n", cur_tx_len); + } else + cur_tx_len = 0; + + } while (cur_tx_len); if (toggle == 1) tcl_toggle_pcb(handle); + //ret = rc632_wait_idle_timer(handle); ret = rc632_wait_idle(handle, timer); if (ret < 0) return ret; - ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, rx_len); + ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, &rx_avail); if (ret < 0) return ret; - if (*rx_len == 0) { + if (rx_avail > *rx_len) + printf("rx_avail(%d) > rx_len(%d), JFYI\n", rx_avail, *rx_len); + else if (*rx_len > rx_avail) + *rx_len = rx_avail; + + if (rx_avail == 0) { u_int8_t tmp; DEBUGP("rx_len == 0\n"); @@ -248,6 +437,7 @@ rc632_transcieve(struct rfid_asic_handle *handle, } return rc632_fifo_read(handle, *rx_len, rx_buf); + /* FIXME: discard addidional bytes in FIFO */ } static int @@ -406,7 +596,7 @@ rc632_open(struct rfid_asic_transport_handle *th) { struct rfid_asic_handle *h; - h = malloc(sizeof(*h)); + h = malloc_asic_handle(sizeof(*h)); if (!h) return NULL; memset(h, 0, sizeof(*h)); @@ -414,10 +604,12 @@ rc632_open(struct rfid_asic_transport_handle *th) h->asic = &rc632; h->rath = th; h->fc = h->asic->fc; - h->mtu = h->mru = 40; /* FIXME */ + /* FIXME: this is only cm5121 specific, since the latency + * down to the RC632 FIFO is too long to refill during TX/RX */ + h->mtu = h->mru = 64; if (rc632_init(h) < 0) { - free(h); + free_asic_handle(h); return NULL; } @@ -428,14 +620,14 @@ void rc632_close(struct rfid_asic_handle *h) { rc632_fini(h); - free(h); + free_asic_handle(h); } /* * Philips CL RC632 primitives for ISO 14443-A compliant PICC's * - * (C) 2005 by Harald Welte + * (C) 2005-2006 by Harald Welte * */ @@ -559,7 +751,7 @@ rc632_iso14443a_fini(struct iso14443a_handle *handle_14443) /* issue a 14443-3 A PCD -> PICC command in a short frame, such as REQA, WUPA */ static int -rc632_iso14443a_transcieve_sf(struct rfid_asic_handle *handle, +rc632_iso14443a_transceive_sf(struct rfid_asic_handle *handle, u_int8_t cmd, struct iso14443a_atqa *atqa) { @@ -567,7 +759,7 @@ rc632_iso14443a_transcieve_sf(struct rfid_asic_handle *handle, u_int8_t tx_buf[1]; u_int8_t rx_len = 2; - memset(atqa, 0, sizeof(atqa)); + memset(atqa, 0, sizeof(*atqa)); tx_buf[0] = cmd; @@ -593,10 +785,11 @@ rc632_iso14443a_transcieve_sf(struct rfid_asic_handle *handle, if (ret < 0) return ret; - ret = rc632_transcieve(handle, tx_buf, sizeof(tx_buf), - (u_int8_t *)atqa, &rx_len, 0x32, 0); + ret = rc632_transceive(handle, tx_buf, sizeof(tx_buf), + (u_int8_t *)atqa, &rx_len, + ISO14443A_FDT_ANTICOL_LAST1, 0); if (ret < 0) { - DEBUGP("error during rc632_transcieve()\n"); + DEBUGP("error during rc632_transceive()\n"); return ret; } @@ -613,18 +806,23 @@ rc632_iso14443a_transcieve_sf(struct rfid_asic_handle *handle, return 0; } -/* transcieve regular frame */ +/* transceive regular frame */ static int -rc632_iso14443ab_transcieve(struct rfid_asic_handle *handle, +rc632_iso14443ab_transceive(struct rfid_asic_handle *handle, unsigned int frametype, const u_int8_t *tx_buf, unsigned int tx_len, u_int8_t *rx_buf, unsigned int *rx_len, u_int64_t timeout, unsigned int flags) { int ret; - u_int8_t rxl = *rx_len & 0xff; + u_int8_t rxl; u_int8_t channel_red; + if (*rx_len > 0xff) + rxl = 0xff; + else + rxl = *rx_len; + memset(rx_buf, 0, *rx_len); switch (frametype) { @@ -651,7 +849,7 @@ rc632_iso14443ab_transcieve(struct rfid_asic_handle *handle, if (ret < 0) return ret; - ret = rc632_transcieve(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0); + ret = rc632_transceive(handle, tx_buf, tx_len, rx_buf, &rxl, timeout, 0); *rx_len = rxl; if (ret < 0) return ret; @@ -660,9 +858,9 @@ rc632_iso14443ab_transcieve(struct rfid_asic_handle *handle, return 0; } -/* transcieve anti collission bitframe */ +/* transceive anti collission bitframe */ static int -rc632_iso14443a_transcieve_acf(struct rfid_asic_handle *handle, +rc632_iso14443a_transceive_acf(struct rfid_asic_handle *handle, struct iso14443a_anticol_cmd *acf, unsigned int *bit_of_col) { @@ -708,7 +906,7 @@ rc632_iso14443a_transcieve_acf(struct rfid_asic_handle *handle, if (ret < 0) return ret; - ret = rc632_transcieve(handle, (u_int8_t *)acf, tx_bytes, + ret = rc632_transceive(handle, (u_int8_t *)acf, tx_bytes, rx_buf, &rx_len, 0x32, 0); if (ret < 0) return ret; @@ -739,6 +937,127 @@ rc632_iso14443a_transcieve_acf(struct rfid_asic_handle *handle, 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; +}; + +static struct rx_config rx_configs[] = { + { + .subc_pulses = RC632_RXCTRL1_SUBCP_8, + .rx_coding = RC632_DECCTRL_MANCHESTER, + .rx_threshold = 0x88, + .bpsk_dem_ctrl = 0x00, + }, + { + .subc_pulses = RC632_RXCTRL1_SUBCP_4, + .rx_coding = RC632_DECCTRL_BPSK, + .rx_threshold = 0x50, + .bpsk_dem_ctrl = 0x0c, + }, + { + .subc_pulses = RC632_RXCTRL1_SUBCP_2, + .rx_coding = RC632_DECCTRL_BPSK, + .rx_threshold = 0x50, + .bpsk_dem_ctrl = 0x0c, + }, + { + .subc_pulses = RC632_RXCTRL1_SUBCP_1, + .rx_coding = RC632_DECCTRL_BPSK, + .rx_threshold = 0x50, + .bpsk_dem_ctrl = 0x0c, + }, +}; + +static struct tx_config tx_configs[] = { + { + .rate = RC632_CDRCTRL_RATE_106K, + .mod_width = 0x13, + }, + { + .rate = RC632_CDRCTRL_RATE_212K, + .mod_width = 0x07, + }, + { + .rate = RC632_CDRCTRL_RATE_424K, + .mod_width = 0x03, + }, + { + .rate = RC632_CDRCTRL_RATE_848K, + .mod_width = 0x01, + }, +}; + +static int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle, + unsigned int tx, unsigned int rate) +{ + int rc; + u_int8_t reg; + + + if (!tx) { + /* Rx */ + if (rate > ARRAY_SIZE(rx_configs)) + return -EINVAL; + + rc = rc632_set_bit_mask(handle, RC632_REG_RX_CONTROL1, + RC632_RXCTRL1_SUBCP_MASK, + rx_configs[rate].subc_pulses); + if (rc < 0) + return rc; + + rc = rc632_set_bit_mask(handle, RC632_REG_DECODER_CONTROL, + RC632_DECCTRL_BPSK, + rx_configs[rate].rx_coding); + if (rc < 0) + return rc; + + rc = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD, + rx_configs[rate].rx_threshold); + if (rc < 0) + return rc; + + if (rx_configs[rate].rx_coding == RC632_DECCTRL_BPSK) { + rc = rc632_reg_write(handle, + RC632_REG_BPSK_DEM_CONTROL, + rx_configs[rate].bpsk_dem_ctrl); + if (rc < 0) + return rc; + } + } else { + /* Tx */ + if (rate > ARRAY_SIZE(tx_configs)) + return -EINVAL; + + rc = rc632_set_bit_mask(handle, RC632_REG_CODER_CONTROL, + RC632_CDRCTRL_RATE_MASK, + tx_configs[rate].rate); + if (rc < 0) + return rc; + + rc = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, + tx_configs[rate].mod_width); + if (rc < 0) + return rc; + } + + return 0; +} + static int rc632_iso14443b_init(struct rfid_asic_handle *handle) { int ret; @@ -1173,9 +1492,6 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, //acmd.serno = htonl(serno); acmd.serno = serno; - ret = rc632_clear_bits(h, RC632_REG_CONTROL, - RC632_CONTROL_CRYPTO1_ON); - /* Clear Rx CRC */ ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY, RC632_CR_RX_CRC_ENABLE); @@ -1230,9 +1546,9 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, } -/* transcieve regular frame */ +/* transceive regular frame */ static int -rc632_mifare_transcieve(struct rfid_asic_handle *handle, +rc632_mifare_transceive(struct rfid_asic_handle *handle, const u_int8_t *tx_buf, unsigned int tx_len, u_int8_t *rx_buf, unsigned int *rx_len, u_int64_t timeout, unsigned int flags) @@ -1256,7 +1572,7 @@ rc632_mifare_transcieve(struct rfid_asic_handle *handle, if (ret < 0) return ret; - ret = rc632_transcieve(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0); + ret = rc632_transceive(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0); *rx_len = rxl; if (ret < 0) return ret; @@ -1265,7 +1581,7 @@ rc632_mifare_transcieve(struct rfid_asic_handle *handle, return 0; } -struct rfid_asic rc632 = { +const struct rfid_asic rc632 = { .name = "Philips CL RC632", .fc = ISO14443_FREQ_CARRIER, .priv.rc632 = { @@ -1274,11 +1590,12 @@ struct rfid_asic rc632 = { .power_down = &rc632_power_down, .turn_on_rf = &rc632_turn_on_rf, .turn_off_rf = &rc632_turn_off_rf, - .transcieve = &rc632_iso14443ab_transcieve, + .transceive = &rc632_iso14443ab_transceive, .iso14443a = { .init = &rc632_iso14443a_init, - .transcieve_sf = &rc632_iso14443a_transcieve_sf, - .transcieve_acf = &rc632_iso14443a_transcieve_acf, + .transceive_sf = &rc632_iso14443a_transceive_sf, + .transceive_acf = &rc632_iso14443a_transceive_acf, + .set_speed = &rc632_iso14443a_set_speed, }, .iso14443b = { .init = &rc632_iso14443b_init,