Add WRITE support for ISO15693 (Bjoern Riemer)
[librfid] / src / rfid_asic_rc632.c
index 8fc5cb9..28bd5a1 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic Philips CL RC632 Routines
  *
- * (C) 2005-2006 Harald Welte <laforge@gnumonks.org>
+ * (C) 2005-2008 Harald Welte <laforge@gnumonks.org>
  *
  */
 
 
 #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, &reg);
+       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, &reg);
+               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, &reg);
        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 <laforge@gnumonks.org>
- *
+/*
+ * 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)<<RC632_BPSKD_TAUB_SHIFT |
+                          (0x3 & RC632_BPSKD_TAUD_MASK)<<RC632_BPSKD_TAUD_SHIFT |
+                          RC632_BPSKD_FILTER_AMP_DETECT |
+                          RC632_BPSKD_NO_RX_EOF |
+                          RC632_BPSKD_NO_RX_EGT),
+       }, {
+               .reg    = RC632_REG_RX_CONTROL2,
+               .val    = (RC632_RXCTRL2_AUTO_PD |
+                          RC632_RXCTRL2_DECSRC_INT),
+       }, {
+               .reg    = RC632_REG_RX_WAIT,
+               .val    = 0x03,
+       }, {
+               .reg    = RC632_REG_CHANNEL_REDUNDANCY,
+               .val    = (RC632_CR_TX_CRC_ENABLE |
+                          RC632_CR_RX_CRC_ENABLE |
+                          RC632_CR_CRC3309),
+       }, {
+               .reg    = RC632_REG_CRC_PRESET_LSB,
+               .val    = 0xff,
+       }, { 
+               .reg    = RC632_REG_CRC_PRESET_MSB,
+               .val    = 0xff,
+       },
+};
+#endif
+
 static int rc632_iso14443b_init(struct rfid_asic_handle *handle)
 {
        int ret;
@@ -1414,10 +1457,11 @@ static int rc632_iso14443b_init(struct rfid_asic_handle *handle)
        return 0;
 }
 
-struct register_file {
-       u_int8_t reg;
-       u_int8_t val;
-};
+
+
+/*
+ * ISO15693
+ */
 
 /* Register file for ISO15693 standard */
 static struct register_file iso15693_fast_script[] = {
@@ -1553,6 +1597,12 @@ static struct register_file icode1_std_script[] = {
        }, {
                .reg    = RC632_REG_CRC_PRESET_MSB,
                .val    = 0xff,
+       /* }, {
+               .reg    = RC632_REG_INTERRUPT_EN,
+               .val    = RC632_INT_IDLE |
+                         RC632_INT_TIMER |
+                         RC632_INT_RX |
+                         RC632_INT_TX, */
        }
 };
 
@@ -1568,47 +1618,45 @@ static struct register_file icode1_fast_patch[] = {
        },
 };
 
+
 static int
 rc632_iso15693_init(struct rfid_asic_handle *h)
 {
-       int ret, i;
-       ENTER();
+       int ret;
 
        /* flush fifo (our way) */
        ret = rc632_reg_write(h, RC632_REG_CONTROL,
                              RC632_CONTROL_FIFO_FLUSH);
+       if (ret < 0)
+               return ret;
 
-       for (i = 0; i < ARRAY_SIZE(iso15693_fast_script); i++) {
-               ret = rc632_reg_write(h, iso15693_fast_script[i].reg,
-                                     iso15693_fast_script[i].val);
-               if (ret < 0)
-                       return ret;
-       }
+       ret = rc632_execute_script(h, iso15693_fast_script,
+                                  ARRAY_SIZE(iso15693_fast_script));
+       if (ret < 0)
+               return ret;
 
        return 0;
 }
 
 static int
-rc632_iso15693_icode1_init(struct rfid_asic_handle *h, int fast)
+rc632_iso15693_icode1_init(struct rfid_asic_handle *h)
 {
        int ret;
-       int i;
 
-       for (i = 0; i < ARRAY_SIZE(icode1_std_script); i++) {
-               ret = rc632_reg_write(h, icode1_std_script[i].reg,
-                                     icode1_std_script[i].val);
-               if (ret < 0)
-                       return ret;
-       }
+       ret = rc632_execute_script(h, icode1_std_script,
+                                  ARRAY_SIZE(icode1_std_script));
+       if (ret < 0)
+               return ret;
 
+       /* FIXME: how to configure fast/slow properly? */
+#if 0
        if (fast) {
-               for (i = 0; i < ARRAY_SIZE(icode1_fast_patch); i++) {
-                       ret = rc632_reg_write(h, icode1_fast_patch[i].reg,
-                                             icode1_fast_patch[i].val);
-                       if (ret < 0)
-                               return ret;
-               }
+               ret = rc632_execute_script(h, icode1_fast_patch,
+                                          ARRAY_SIZE(icode1_fast_patch));
+               if (ret < 0)
+                       return ret;
        }
+#endif
 
        return 0;
 }
@@ -1694,6 +1742,148 @@ rc632_iso15693_icl_init(struct rfid_asic_handle *h)
        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,
+                            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, &reg);
+       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,
                        },
                },