X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Frfid_asic_rc632.c;h=6fa4ee332ac76adf8b4c729d7c6ec51a38664119;hb=c1079ea487734f41f3e15ac80ec265c27299a078;hp=149a9a6597913a35c09fc29832cfdc61a0f6c02e;hpb=76eedfaff97d57125ed519a6e5608f88d28702bd;p=librfid diff --git a/src/rfid_asic_rc632.c b/src/rfid_asic_rc632.c index 149a9a6..6fa4ee3 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,6 +23,7 @@ #include #include #include +#include #include #include @@ -34,13 +35,15 @@ #include "rfid_iso14443_common.h" #include "rc632.h" -//#include "rc632_14443a.h" +#ifdef __MINGW32__ +#include "usleep.h" +#endif/*__MINGW32__*/ -#define RC632_TMO_AUTH1 14000 +#define RC632_TMO_AUTH1 140 #define ENTER() DEBUGP("entering\n") -struct rfid_asic rc632; +const struct rfid_asic rc632; /* Register and FIFO Access functions */ static int @@ -164,7 +167,110 @@ 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) @@ -255,19 +361,30 @@ rc632_transceive(struct rfid_asic_handle *handle, 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, cur_tx_len; + u_int8_t rx_avail; const u_int8_t *cur_tx_buf = tx_buf; + DEBUGP("timer = %u\n", timer); + 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, tx_len, tx_buf, 0x03); + ret = rc632_fifo_write(handle, cur_tx_len, cur_tx_buf, 0x03); if (ret < 0) return ret; @@ -285,8 +402,9 @@ rc632_transceive(struct rfid_asic_handle *handle, &fifo_fill); if (ret < 0) return ret; + cur_tx_len = 64 - fifo_fill; - printf("refilling tx fifo with %u bytes\n", cur_tx_len); + //printf("refilling tx fifo with %u bytes\n", cur_tx_len); } else cur_tx_len = 0; @@ -295,15 +413,21 @@ 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); 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"); @@ -315,6 +439,7 @@ rc632_transceive(struct rfid_asic_handle *handle, } return rc632_fifo_read(handle, *rx_len, rx_buf); + /* FIXME: discard addidional bytes in FIFO */ } static int @@ -443,6 +568,13 @@ rc632_init(struct rfid_asic_handle *ah) if (ret < 0) return ret; + /* switch off rf */ + ret = rc632_turn_off_rf(ah); + if (ret < 0) + return ret; + + usleep(100000); + /* switch on rf */ ret = rc632_turn_on_rf(ah); if (ret < 0) @@ -473,18 +605,20 @@ 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)); - h->asic = &rc632; + h->asic = (void*)&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; } @@ -495,14 +629,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 * */ @@ -514,7 +648,8 @@ rc632_iso14443a_init(struct rfid_asic_handle *handle) // FIXME: some fifo work (drain fifo?) /* flush fifo (our way) */ - ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01); + 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 | @@ -634,7 +769,7 @@ rc632_iso14443a_transceive_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; @@ -661,7 +796,8 @@ rc632_iso14443a_transceive_sf(struct rfid_asic_handle *handle, return ret; ret = rc632_transceive(handle, tx_buf, sizeof(tx_buf), - (u_int8_t *)atqa, &rx_len, 0x32, 0); + (u_int8_t *)atqa, &rx_len, + ISO14443A_FDT_ANTICOL_LAST1, 0); if (ret < 0) { DEBUGP("error during rc632_transceive()\n"); return ret; @@ -689,9 +825,14 @@ rc632_iso14443ab_transceive(struct rfid_asic_handle *handle, 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) { @@ -718,7 +859,7 @@ rc632_iso14443ab_transceive(struct rfid_asic_handle *handle, if (ret < 0) return ret; - ret = rc632_transceive(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; @@ -736,7 +877,7 @@ rc632_iso14443a_transceive_acf(struct rfid_asic_handle *handle, int ret; u_int8_t rx_buf[64]; u_int8_t rx_len = sizeof(rx_buf); - u_int8_t rx_align = 0, tx_last_bits, tx_bytes; + u_int8_t rx_align = 0, tx_last_bits, tx_bytes, tx_bytes_total; u_int8_t boc; u_int8_t error_flag; *bit_of_col = ISO14443A_BITOFCOL_NONE; @@ -760,14 +901,14 @@ rc632_iso14443a_transceive_acf(struct rfid_asic_handle *handle, if (ret < 0) return ret; - tx_last_bits = acf->nvb & 0x0f; /* lower nibble indicates bits */ - tx_bytes = acf->nvb >> 4; + tx_last_bits = acf->nvb & 0x07; /* lower nibble indicates bits */ + tx_bytes = ( acf->nvb >> 4 ) & 0x07; if (tx_last_bits) { - tx_bytes++; - rx_align = (tx_last_bits+1) % 8;/* rx frame complements tx */ + tx_bytes_total = tx_bytes+1; + rx_align = tx_last_bits & 0x07; /* rx frame complements tx */ } - - //rx_align = 8 - tx_last_bits;/* rx frame complements tx */ + else + tx_bytes_total = tx_bytes; /* set RxAlign and TxLastBits*/ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, @@ -775,7 +916,7 @@ rc632_iso14443a_transceive_acf(struct rfid_asic_handle *handle, if (ret < 0) return ret; - ret = rc632_transceive(handle, (u_int8_t *)acf, tx_bytes, + ret = rc632_transceive(handle, (u_int8_t *)acf, tx_bytes_total, rx_buf, &rx_len, 0x32, 0); if (ret < 0) return ret; @@ -784,8 +925,10 @@ rc632_iso14443a_transceive_acf(struct rfid_asic_handle *handle, acf->uid_bits[tx_bytes-2] = ( (acf->uid_bits[tx_bytes-2] & (0xff >> (8-tx_last_bits))) | rx_buf[0]); + /* copy the rest */ - memcpy(&acf->uid_bits[tx_bytes+1-2], &rx_buf[1], rx_len-1); + if(rx_len) + memcpy(&acf->uid_bits[tx_bytes-1], &rx_buf[1], rx_len-1); /* determine whether there was a collission */ ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag); @@ -872,8 +1015,7 @@ static struct tx_config tx_configs[] = { }; static int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle, - unsigned int tx, - u_int8_t rate) + unsigned int tx, unsigned int rate) { int rc; u_int8_t reg; @@ -935,7 +1077,8 @@ static int rc632_iso14443b_init(struct rfid_asic_handle *handle) // FIXME: some FIFO work /* flush fifo (our way) */ - ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01); + ret = rc632_reg_write(handle, RC632_REG_CONTROL, + RC632_CONTROL_FIFO_FLUSH); if (ret < 0) return ret; @@ -1323,6 +1466,11 @@ rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key) if (ret < 0) return ret; + /* Terminate probably running command */ + ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_IDLE); + if (ret < 0) + return ret; + ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03); if (ret < 0) return ret; @@ -1353,8 +1501,10 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, struct mifare_authcmd acmd; u_int8_t reg; - if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B) + if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B) { + DEBUGP("invalid auth command\n"); return -EINVAL; + } /* Initialize acmd */ acmd.block_address = block & 0xff; @@ -1362,9 +1512,16 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, //acmd.serno = htonl(serno); acmd.serno = serno; +#if 1 /* Clear Rx CRC */ ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY, RC632_CR_RX_CRC_ENABLE); +#else + /* Clear Rx CRC, Set Tx CRC and Odd Parity */ + ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY, + RC632_CR_TX_CRC_ENABLE | RC632_CR_PARITY_ODD | + RC632_CR_PARITY_ENABLE); +#endif if (ret < 0) return ret; @@ -1374,8 +1531,10 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, return ret; ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT1); - if (ret < 0) + if (ret < 0) { + DEBUGP("error during AUTHENT1"); return ret; + } /* Wait until transmitter is idle */ ret = rc632_wait_idle(h, RC632_TMO_AUTH1); @@ -1385,8 +1544,10 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, ret = rc632_reg_read(h, RC632_REG_SECONDARY_STATUS, ®); if (ret < 0) return ret; - if (reg & 0x07) + if (reg & 0x07) { + DEBUGP("bitframe?"); return -EIO; + } /* Clear Tx CRC */ ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY, @@ -1409,11 +1570,12 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, if (ret < 0) return ret; - if (!(reg & RC632_CONTROL_CRYPTO1_ON)) + if (!(reg & RC632_CONTROL_CRYPTO1_ON)) { + DEBUGP("authentication not successful"); return -EACCES; + } return 0; - } /* transceive regular frame */ @@ -1451,7 +1613,7 @@ rc632_mifare_transceive(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 = {