Prepare RFID compilation in firmware mode
[librfid] / src / rfid_asic_rc632.c
index 4377d73..f8a8483 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic Philips CL RC632 Routines
  *
- * (C) Harald Welte <laforge@gnumonks.org>
+ * (C) 2005-2006 Harald Welte <laforge@gnumonks.org>
  *
  */
 
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <limits.h>
 #include <sys/types.h>
 
-#include <rfid/rfid.h>
-#include <rfid/rfid_asic.h>
-#include <rfid/rfid_asic_rc632.h>
-#include <rfid/rfid_reader_cm5121.h>
-#include <rfid/rfid_layer2_iso14443a.h>
-#include <rfid/rfid_protocol_mifare_classic.h>
+#include <librfid/rfid.h>
+#include <librfid/rfid_asic.h>
+#include <librfid/rfid_asic_rc632.h>
+#include <librfid/rfid_reader_cm5121.h>
+#include <librfid/rfid_layer2_iso14443a.h>
+#include <librfid/rfid_protocol_mifare_classic.h>
 
 #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 <laforge@gnumonks.org>
+ * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org>
  *
  */
 
@@ -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,