diff options
-rw-r--r-- | openpcd/firmware/include/rfid.h | 14 | ||||
-rw-r--r-- | openpcd/firmware/include/rfid_protocol_mifare_classic.h | 28 | ||||
-rw-r--r-- | openpcd/firmware/src/dbgu.c | 8 | ||||
-rw-r--r-- | openpcd/firmware/src/main_dumbreader.c | 12 | ||||
-rw-r--r-- | openpcd/firmware/src/rc632.c | 99 | ||||
-rw-r--r-- | openpcd/firmware/src/rc632.h | 24 | ||||
-rw-r--r-- | openpcd/firmware/src/rc632_highlevel.c | 1149 |
7 files changed, 1165 insertions, 169 deletions
diff --git a/openpcd/firmware/include/rfid.h b/openpcd/firmware/include/rfid.h new file mode 100644 index 0000000..5684884 --- /dev/null +++ b/openpcd/firmware/include/rfid.h @@ -0,0 +1,14 @@ +#ifndef _RFID_H +#define _RFID_H + +struct rfid_asic_handle { +}; + +struct rfid_asic { +}; + +#define RAH NULL + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#endif diff --git a/openpcd/firmware/include/rfid_protocol_mifare_classic.h b/openpcd/firmware/include/rfid_protocol_mifare_classic.h new file mode 100644 index 0000000..e6b2400 --- /dev/null +++ b/openpcd/firmware/include/rfid_protocol_mifare_classic.h @@ -0,0 +1,28 @@ +#ifndef _MIFARE_CLASSIC_H + +#define MIFARE_CL_KEYA_DEFAULT "\xa0\xa1\xa2\xa3\xa4\xa5" +#define MIFARE_CL_KEYB_DEFAULT "\xb0\xb1\xb2\xb3\xb4\xb5" + +#define MIFARE_CL_KEYA_DEFAULT_INFINEON "\xff\xff\xff\xff\xff\xff" +#define MIFARE_CL_KEYB_DEFAULT_INFINEON MIFARE_CL_KEYA_DEFAULT_INFINEON + +#define MIFARE_CL_PAGE_MAX 0xff + +#define RFID_CMD_MIFARE_AUTH1A 0x60 +#define RFID_CMD_MIFARE_AUTH1B 0x61 + +#ifdef __LIBRFID__ + +extern struct rfid_protocol rfid_protocol_mfcl; + + +#define MIFARE_CL_CMD_WRITE16 0xA0 +#define MIFARE_CL_CMD_READ 0x30 + +#define MIFARE_CL_RESP_ACK 0x0a +#define MIFARE_CL_RESP_NAK 0x00 + + +#endif /* __LIBRFID__ */ + +#endif /* _MIFARE_CLASSIC_H */ diff --git a/openpcd/firmware/src/dbgu.c b/openpcd/firmware/src/dbgu.c index 3f21565..1b0ede0 100644 --- a/openpcd/firmware/src/dbgu.c +++ b/openpcd/firmware/src/dbgu.c @@ -78,20 +78,20 @@ static void DBGU_irq_handler(void) break; case '4': AT91F_DBGU_Printk("Testing RC632 : "); - if (rc632_test() == 0) + if (rc632_test(RAH) == 0) AT91F_DBGU_Printk("SUCCESS!\n\r"); else AT91F_DBGU_Printk("ERROR!\n\r"); break; case '5': - DEBUGPCR("Reading RC632 Reg RxWait: 0x%02xr", - rc632_reg_read(RC632_REG_RX_WAIT)); + rc632_reg_read(RAH, RC632_REG_RX_WAIT, &value); + DEBUGPCR("Reading RC632 Reg RxWait: 0x%02xr", value); break; case '6': DEBUGPCR("Writing RC632 Reg RxWait: 0x55"); - rc632_reg_write(RC632_REG_RX_WAIT, 0x55); + rc632_reg_write(RAH, RC632_REG_RX_WAIT, 0x55); break; case '7': rc632_dump(); diff --git a/openpcd/firmware/src/main_dumbreader.c b/openpcd/firmware/src/main_dumbreader.c index 43801f6..c165182 100644 --- a/openpcd/firmware/src/main_dumbreader.c +++ b/openpcd/firmware/src/main_dumbreader.c @@ -27,22 +27,22 @@ static int usb_in(struct req_ctx *rctx) switch (poh->cmd) { case OPENPCD_CMD_READ_REG: DEBUGP("READ REG(0x%02x) ", poh->reg); - pih->val = rc632_reg_read(poh->reg); + rc632_reg_read(RAH, poh->reg, &pih->val); break; case OPENPCD_CMD_READ_FIFO: DEBUGP("READ FIFO(len=%u) ", poh->val); - pih->len = rc632_fifo_read(poh->val, pih->data); + rc632_fifo_read(RAH, poh->val, pih->data); rctx->tx.tot_len += pih->len; break; case OPENPCD_CMD_WRITE_REG: DEBUGP("WRITE_REG(0x%02x, 0x%02x) ", poh->reg, poh->val); - rc632_reg_write(poh->reg, poh->val); + rc632_reg_write(RAH, poh->reg, poh->val); break; case OPENPCD_CMD_WRITE_FIFO: DEBUGP("WRITE FIFO(len=%u) ", poh->len); if (len - sizeof(*poh) < poh->len) return -EINVAL; - rc632_fifo_write(poh->len, poh->data); + rc632_fifo_write(RAH, poh->len, poh->data, 0); break; case OPENPCD_CMD_READ_VFIFO: DEBUGP("READ VFIFO "); @@ -54,11 +54,11 @@ static int usb_in(struct req_ctx *rctx) break; case OPENPCD_CMD_REG_BITS_CLEAR: DEBUGP("CLEAR BITS "); - pih->val = rc632_clear_bits(poh->reg, poh->val); + pih->val = rc632_clear_bits(RAH, poh->reg, poh->val); break; case OPENPCD_CMD_REG_BITS_SET: DEBUGP("SET BITS "); - pih->val = rc632_set_bits(poh->reg, poh->val); + pih->val = rc632_set_bits(RAH, poh->reg, poh->val); break; case OPENPCD_CMD_SET_LED: DEBUGP("SET LED(%u,%u) ", poh->reg, poh->val); diff --git a/openpcd/firmware/src/rc632.c b/openpcd/firmware/src/rc632.c index 306db3c..d4b2c5c 100644 --- a/openpcd/firmware/src/rc632.c +++ b/openpcd/firmware/src/rc632.c @@ -1,6 +1,11 @@ -/* Philips CL RC632 driver (via SPI) +/* Philips CL RC632 driver (via SPI) for OpenPCD firmware * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> * + * This is heavily based on the librfid RC632 driver. All primitive access + * functions such as rc632_{reg,fifo}_{read,write}() are API compatible to + * librfid in order to be able to leverage higher-level code from librfid + * to this OpenPCD firmware. + * * */ #include <string.h> @@ -12,6 +17,9 @@ #include "fifo.h" #include "dbgu.h" #include "pcd_enumerate.h" +#include "rc632.h" + +/* SPI driver */ //#define SPI_DEBUG_LOOPBACK #define SPI_USES_DMA @@ -110,7 +118,11 @@ int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, } #endif -/* static buffers used by routines below */ +/* RC632 driver */ + +/* static buffers used by RC632 access primitives below. + * Since we only have one */ + static u_int8_t spi_outbuf[64+1]; static u_int8_t spi_inbuf[64+1]; @@ -125,7 +137,8 @@ static struct rc632 rc632; /* RC632 access primitives */ -void rc632_reg_write(u_int8_t addr, u_int8_t data) +int rc632_reg_write(struct rfid_asic_handle *hdl, + u_int8_t addr, u_int8_t data) { u_int16_t rx_len = 2; addr = (addr << 1) & 0x7e; @@ -134,10 +147,11 @@ void rc632_reg_write(u_int8_t addr, u_int8_t data) spi_outbuf[1] = data; //spi_transceive(spi_outbuf, 2, NULL, NULL); - spi_transceive(spi_outbuf, 2, spi_inbuf, &rx_len); + return spi_transceive(spi_outbuf, 2, spi_inbuf, &rx_len); } -int rc632_fifo_write(u_int8_t len, u_int8_t *data) +int rc632_fifo_write(struct rfid_asic_handle *hdl, + u_int8_t len, u_int8_t *data, u_int8_t flags) { if (len > sizeof(spi_outbuf)-1) len = sizeof(spi_outbuf)-1; @@ -145,12 +159,11 @@ int rc632_fifo_write(u_int8_t len, u_int8_t *data) spi_outbuf[0] = FIFO_ADDR; memcpy(&spi_outbuf[1], data, len); - spi_transceive(spi_outbuf, len+1, NULL, NULL); - - return len; + return spi_transceive(spi_outbuf, len+1, NULL, NULL); } -u_int8_t rc632_reg_read(u_int8_t addr) +int rc632_reg_read(struct rfid_asic_handle *hdl, + u_int8_t addr, u_int8_t *val) { u_int16_t rx_len = 2; @@ -161,14 +174,24 @@ u_int8_t rc632_reg_read(u_int8_t addr) spi_transceive(spi_outbuf, 2, spi_inbuf, &rx_len); - return spi_inbuf[1]; + *val = spi_inbuf[1]; + + return 0; } -u_int8_t rc632_fifo_read(u_int8_t max_len, u_int8_t *data) +int rc632_fifo_read(struct rfid_asic_handle *hdl, + u_int8_t max_len, u_int8_t *data) { - u_int8_t fifo_length = rc632_reg_read(RC632_REG_FIFO_LENGTH); + int ret; + u_int8_t fifo_length; u_int8_t i; - u_int16_t rx_len = fifo_length+1; + u_int16_t rx_len; + + ret = rc632_reg_read(hdl, RC632_REG_FIFO_LENGTH, &fifo_length); + if (ret < 0) + return ret; + + rx_len = fifo_length+1; if (max_len < fifo_length) fifo_length = max_len; @@ -182,25 +205,37 @@ u_int8_t rc632_fifo_read(u_int8_t max_len, u_int8_t *data) spi_transceive(spi_outbuf, fifo_length+1, spi_inbuf, &rx_len); memcpy(data, spi_inbuf+1, rx_len-1); - return rx_len-1; + return 0; } -u_int8_t rc632_set_bits(u_int8_t reg, u_int8_t bits) +int rc632_set_bits(struct rfid_asic_handle *hdl, + u_int8_t reg, u_int8_t bits) { - u_int8_t val = rc632_reg_read(reg); + u_int8_t val; + int ret; + + ret = rc632_reg_read(hdl, reg, &val); + if (ret < 0) + return ret; + val |= bits; - rc632_reg_write(reg, val); - return val; + return rc632_reg_write(hdl, reg, val); } -u_int8_t rc632_clear_bits(u_int8_t reg, u_int8_t bits) +int rc632_clear_bits(struct rfid_asic_handle *hdl, + u_int8_t reg, u_int8_t bits) { - u_int8_t val = rc632_reg_read(reg); + u_int8_t val; + int ret; + + ret = rc632_reg_read(hdl, reg, &val); + if (ret < 0) + return ret; + val &= ~bits; - rc632_reg_write(reg, val); - return val; + return rc632_reg_write(hdl, reg, val); } /* RC632 interrupt handling */ @@ -209,10 +244,11 @@ static struct openpcd_hdr irq_opcdh; static void rc632_irq(void) { /* CL RC632 has interrupted us */ - u_int8_t cause = rc632_reg_read(RC632_REG_INTERRUPT_RQ); + u_int8_t cause; + rc632_reg_read(RAH, RC632_REG_INTERRUPT_RQ, &cause); /* ACK all interrupts */ - rc632_reg_write(RC632_REG_INTERRUPT_RQ, cause); + rc632_reg_write(RAH, RC632_REG_INTERRUPT_RQ, cause); DEBUGP("rc632_irq: "); if (cause & RC632_INT_LOALERT) { @@ -265,7 +301,7 @@ void rc632_reset(void) rc632_power(1); /* turn off register paging */ - rc632_reg_write(RC632_REG_PAGE0, 0x00); + rc632_reg_write(RAH, RC632_REG_PAGE0, 0x00); } void rc632_init(void) @@ -331,12 +367,13 @@ void rc632_exit(void) #ifdef DEBUG -static int rc632_reg_write_verify(u_int8_t reg, u_int8_t val) +static int rc632_reg_write_verify(struct rfid_asic_handle *hdl, + u_int8_t reg, u_int8_t val) { u_int8_t tmp; - rc632_reg_write(reg, val); - tmp = rc632_reg_read(reg); + rc632_reg_write(hdl, reg, val); + rc632_reg_read(hdl, reg, &tmp); DEBUGP("reg=0x%02x, write=0x%02x, read=0x%02x ", reg, val, tmp); @@ -371,12 +408,12 @@ int rc632_dump(void) return 0; } -int rc632_test(void) +int rc632_test(struct rfid_asic_handle *hdl) { - if (rc632_reg_write_verify(RC632_REG_RX_WAIT, 0x55) != 1) + if (rc632_reg_write_verify(hdl, RC632_REG_RX_WAIT, 0x55) != 1) return -1; - if (rc632_reg_write_verify(RC632_REG_RX_WAIT, 0xAA) != 1) + if (rc632_reg_write_verify(hdl, RC632_REG_RX_WAIT, 0xAA) != 1) return -1; return 0; diff --git a/openpcd/firmware/src/rc632.h b/openpcd/firmware/src/rc632.h index acede11..ef5dfa7 100644 --- a/openpcd/firmware/src/rc632.h +++ b/openpcd/firmware/src/rc632.h @@ -2,19 +2,27 @@ #define _RC632_API_H #include <sys/types.h> -#include <include/cl_rc632.h> +#include <cl_rc632.h> +#include <rfid.h> + +extern int rc632_reg_write(struct rfid_asic_handle *hdl, + u_int8_t addr, u_int8_t data); +extern int rc632_fifo_write(struct rfid_asic_handle *hdl, + u_int8_t len, u_int8_t *data, u_int8_t flags); +extern int rc632_reg_read(struct rfid_asic_handle *hdl, + u_int8_t addr, u_int8_t *val); +extern int rc632_fifo_read(struct rfid_asic_handle *hdl, + u_int8_t max_len, u_int8_t *data); +extern int rc632_clear_bits(struct rfid_asic_handle *hdl, + u_int8_t reg, u_int8_t bits); +extern int rc632_set_bits(struct rfid_asic_handle *hdl, + u_int8_t reg, u_int8_t bits); -extern void rc632_reg_write(u_int8_t addr, u_int8_t data); -extern void rc632_fifo_write(u_int8_t len, u_int8_t *data); -extern u_int8_t rc632_reg_read(u_int8_t addr); -extern u_int8_t rc632_fifo_read(u_int8_t max_len, u_int8_t *data); -extern u_int8_t rc632_clear_bits(u_int8_t reg, u_int8_t bits); -extern u_int8_t rc632_set_bits(u_int8_t reg, u_int8_t bits); extern void rc632_init(void); extern void rc632_exit(void); #ifdef DEBUG -extern int rc632_test(void); +extern int rc632_test(struct rfid_asic_handle *hdl); extern int rc632_dump(void); #endif diff --git a/openpcd/firmware/src/rc632_highlevel.c b/openpcd/firmware/src/rc632_highlevel.c index e039bc3..e0fcffa 100644 --- a/openpcd/firmware/src/rc632_highlevel.c +++ b/openpcd/firmware/src/rc632_highlevel.c @@ -1,5 +1,22 @@ -/* ISO 14443 WUPA / SELECT anticollision implementation, part of OpenPCD - * (C) 2006 by Harald Welte <laforge@gnumonks.org> +/* Generic Philips CL RC632 Routines + * + * (C) Harald Welte <laforge@gnumonks.org> + * + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <sys/types.h> @@ -9,6 +26,7 @@ #include "rc632.h" #include "dbgu.h" #include <rfid_layer2_iso14443a.h> +#include <rfid_protocol_mifare_classic.h> /* initially we use the same values as cm5121 */ #define OPENPCD_CW_CONDUCTANCE 0x3f @@ -18,15 +36,67 @@ #define OPENPCD_14443B_BITPHASE 0xad #define OPENPCD_14443B_THRESHOLD 0xff +#define RC632_TMO_AUTH1 14000 + +#define ENTER() DEBUGPCRF("entering") +struct rfid_asic rc632; + +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_turn_on_rf(struct rfid_asic_handle *handle) +{ + ENTER(); + return rc632_set_bits(handle, RC632_REG_TX_CONTROL, 0x03); +} + +static int +rc632_turn_off_rf(struct rfid_asic_handle *handle) +{ + ENTER(); + return rc632_clear_bits(handle, RC632_REG_TX_CONTROL, 0x03); +} + +static int +rc632_power_up(struct rfid_asic_handle *handle) +{ + ENTER(); + return rc632_clear_bits(handle, RC632_REG_CONTROL, + RC632_CONTROL_POWERDOWN); +} + +static int +rc632_power_down(struct rfid_asic_handle *handle) +{ + return rc632_set_bits(handle, RC632_REG_CONTROL, + RC632_CONTROL_POWERDOWN); +} + /* 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 bst_prescaler, best_divisor, i; + u_int8_t best_presc, best_divisor, i; int64_t smallest_diff; smallest_diff = 0x7fffffffffffffff; - bst_prescaler = 0; + best_presc = 0; for (i = 0; i < 21; i++) { u_int64_t clk, tmp_div, res; @@ -45,143 +115,168 @@ static int best_prescaler(u_int64_t timeout, u_int8_t *prescaler, continue; if (diff < smallest_diff) { - bst_prescaler = i; + best_presc = i; best_divisor = tmp_div; smallest_diff = diff; } } - *prescaler = bst_prescaler; + *prescaler = best_presc; *divisor = best_divisor; DEBUGP("timeout %u usec, prescaler = %u, divisor = %u\n", - timeout, bst_prescaler, best_divisor); + timeout, best_presc, best_divisor); return 0; } - static int -rc632_timer_set(u_int64_t timeout) +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); - rc632_reg_write(RC632_REG_TIMER_CLOCK, prescaler & 0x1f); + ret = rc632_reg_write(handle, RC632_REG_TIMER_CLOCK, + prescaler & 0x1f); + if (ret < 0) + return ret; - rc632_reg_write(RC632_REG_TIMER_CONTROL, - RC632_TMR_START_TX_END|RC632_TMR_STOP_RX_BEGIN); + ret = rc632_reg_write(handle, RC632_REG_TIMER_CONTROL, + RC632_TMR_START_TX_END|RC632_TMR_STOP_RX_BEGIN); /* clear timer irq bit */ - rc632_set_bits(RC632_REG_INTERRUPT_RQ, RC632_IRQ_TIMER); + ret = rc632_set_bits(handle, RC632_REG_INTERRUPT_RQ, RC632_IRQ_TIMER); - rc632_reg_write(RC632_REG_TIMER_RELOAD, divisor); + 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(void) +static int rc632_wait_idle_timer(struct rfid_asic_handle *handle) { + int ret; u_int8_t irq, cmd; while (1) { - irq = rc632_reg_read(RC632_REG_INTERRUPT_RQ); + 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; - foo = rc632_reg_read(RC632_REG_PRIMARY_STATUS); + rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &foo); if (foo & 0x04) - foo = rc632_reg_read(RC632_REG_ERROR_FLAG); + rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &foo); return -110; } - cmd = rc632_reg_read(RC632_REG_COMMAND); + ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd); + if (ret < 0) + return ret; if (cmd == 0) return 0; /* poll every millisecond */ - // usleep(1000); + /* FIXME usleep(1000);*/ } } - +/* Stupid RC632 implementations don't evaluate interrupts but poll the + * command register for "status idle" */ static int -rc632_iso14443a_init(void) +rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t timeout) { - // FIXME: some fifo work (drain fifo?) - - /* flush fifo (our way) */ - rc632_reg_write(RC632_REG_CONTROL, 0x01); - - rc632_reg_write(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)); - - rc632_reg_write(RC632_REG_CW_CONDUCTANCE, - OPENPCD_CW_CONDUCTANCE); + u_int8_t cmd = 0xff; + int ret, cycles = 0; +#define USLEEP_PER_CYCLE 128 - /* Since FORCE_100_ASK is set (cf mc073930.pdf), this line may be left out? */ - rc632_reg_write(RC632_REG_MOD_CONDUCTANCE, - OPENPCD_MOD_CONDUCTANCE); - - rc632_reg_write(RC632_REG_CODER_CONTROL, - (RC632_CDRCTRL_TXCD_14443A | - RC632_CDRCTRL_RATE_106K)); - - rc632_reg_write(RC632_REG_MOD_WIDTH, 0x13); + while (cmd != 0) { + ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd); + if (ret < 0) + return ret; - rc632_reg_write(RC632_REG_MOD_WIDTH_SOF, 0x3f); - - rc632_reg_write(RC632_REG_TYPE_B_FRAMING, 0x00); + if (cmd == 0) { + /* FIXME: read second time ?? */ + return 0; + } - rc632_reg_write(RC632_REG_RX_CONTROL1, - (RC632_RXCTRL1_GAIN_35DB | - RC632_RXCTRL1_ISO14443 | - RC632_RXCTRL1_SUBCP_8)); + { + 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); + } - rc632_reg_write(RC632_REG_DECODER_CONTROL, - (RC632_DECCTRL_MANCHESTER | - RC632_DECCTRL_RXFR_14443A)); + /* Abort after some timeout */ + if (cycles > timeout*100/USLEEP_PER_CYCLE) { + return -ETIMEDOUT; + } - rc632_reg_write(RC632_REG_BIT_PHASE, - OPENPCD_14443A_BITPHASE); + cycles++; + usleep(USLEEP_PER_CYCLE); + } - rc632_reg_write(RC632_REG_RX_THRESHOLD, - OPENPCD_14443A_THRESHOLD); + return 0; +} - rc632_reg_write(RC632_REG_BPSK_DEM_CONTROL, 0x00); - - rc632_reg_write(RC632_REG_RX_CONTROL2, - (RC632_RXCTRL2_DECSRC_INT | - RC632_RXCTRL2_CLK_Q)); +static int +rc632_transmit(struct rfid_asic_handle *handle, + const u_int8_t *buf, + u_int8_t len, + u_int64_t timeout) +{ + int ret, cur_len; + const u_int8_t *cur_buf = buf; - /* Omnikey proprietary driver has 0x03, but 0x06 is the default reset - * value ?!? */ - rc632_reg_write(RC632_REG_RX_WAIT, 0x06); + 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; + + 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; + } - rc632_reg_write(RC632_REG_CHANNEL_REDUNDANCY, - (RC632_CR_PARITY_ENABLE | - RC632_CR_PARITY_ODD)); + 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; - rc632_reg_write(RC632_REG_CRC_PRESET_LSB, 0x63); + } while (cur_len); - rc632_reg_write(RC632_REG_CRC_PRESET_MSB, 0x63); + return rc632_wait_idle(handle, timeout); +} +static int +tcl_toggle_pcb(struct rfid_asic_handle *handle) +{ + // FIXME: toggle something between 0x0a and 0x0b return 0; } static int -rc632_transceive(const u_int8_t *tx_buf, +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, @@ -198,58 +293,330 @@ rc632_transceive(const u_int8_t *tx_buf, else cur_tx_len = tx_len; - ret = rc632_timer_set(timer); + ret = rc632_timer_set(handle, timer); if (ret < 0) return ret; /* clear all interrupts */ - rc632_reg_write(RC632_REG_INTERRUPT_RQ, 0x7f); + ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_RQ, 0x7f); do { - rc632_fifo_write(cur_tx_len, cur_tx_buf); - - if (cur_tx_buf == tx_buf) - rc632_reg_write(RC632_REG_COMMAND, - RC632_CMD_TRANSCEIVE); + 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; - fifo_fill = rc632_reg_read(RC632_REG_FIFO_LENGTH); + ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, + &fifo_fill); + if (ret < 0) + return ret; cur_tx_len = 64 - fifo_fill; - DEBUGPCR("refilling tx fifo with %u bytes", cur_tx_len); + DEBUGPCRF("refilling tx fifo with %u bytes", cur_tx_len); } else cur_tx_len = 0; } while (cur_tx_len); - //if (toggle == 1) - //tcl_toggle_pcb(handle); + if (toggle == 1) + tcl_toggle_pcb(handle); - ret = rc632_wait_idle_timer(); + ret = rc632_wait_idle_timer(handle); if (ret < 0) return ret; - *rx_len = rc632_reg_read(RC632_REG_FIFO_LENGTH); + ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, rx_len); + if (ret < 0) + return ret; if (*rx_len == 0) { u_int8_t tmp; DEBUGP("rx_len == 0\n"); - tmp = rc632_reg_read(RC632_REG_ERROR_FLAG); - tmp = rc632_reg_read(RC632_REG_CHANNEL_REDUNDANCY); + rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &tmp); + rc632_reg_read(handle, RC632_REG_CHANNEL_REDUNDANCY, &tmp); return -1; } - return rc632_fifo_read(*rx_len, rx_buf); + return rc632_fifo_read(handle, *rx_len, rx_buf); +} + +static int +rc632_read_eeprom(struct rfid_asic_handle *handle) +{ + u_int8_t recvbuf[60]; + u_int8_t sndbuf[3]; + int ret; + + sndbuf[0] = 0x00; + sndbuf[1] = 0x00; + sndbuf[2] = 0x3c; + + ret = rc632_fifo_write(handle, 3, sndbuf, 0x03); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_READ_E2); + if (ret < 0) + return ret; + + usleep(20000); + + ret = rc632_fifo_read(handle, sizeof(recvbuf), recvbuf); + if (ret < 0) + return ret; + + // FIXME: do something with eeprom contents + return ret; +} + +static int +rc632_calc_crc16_from(struct rfid_asic_handle *handle) +{ + u_int8_t sndbuf[2] = { 0x01, 0x02 }; + u_int8_t crc_lsb = 0x00 , crc_msb = 0x00; + int ret; + + ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0x12); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xe0); + if (ret < 0) + return ret; + + ret = rc632_fifo_write(handle, sizeof(sndbuf), sndbuf, 3); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_CALC_CRC); + if (ret < 0) + return ret; + + usleep(10000); // FIXME: no checking for cmd completion? + + ret = rc632_reg_read(handle, RC632_REG_CRC_RESULT_LSB, &crc_lsb); + if (ret < 0) + return ret; + + ret = rc632_reg_read(handle, RC632_REG_CRC_RESULT_MSB, &crc_msb); + if (ret < 0) + return ret; + + // FIXME: what to do with crc result? + return ret; +} + + +int +rc632_register_dump(struct rfid_asic_handle *handle, u_int8_t *buf) +{ + int ret; + u_int8_t i; + + for (i = 0; i <= 0x3f; i++) { + ret = rc632_reg_read(handle, i, &buf[i]); + // do we want error checks? + } + return 0; +} + + +#if 0 +static int +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); + if (ret < 0) + return ret; + + usleep(10000); + + /* switch on rf */ + ret = rc632_power_up(ah); + if (ret < 0) + return ret; + + /* disable register paging */ + ret = rc632_reg_write(ah, 0x00, 0x00); + if (ret < 0) + return ret; + + /* set some sane default values */ + ret = rc632_reg_write(ah, 0x11, 0x5b); + if (ret < 0) + return ret; + + /* switch on rf */ + ret = rc632_turn_on_rf(ah); + if (ret < 0) + return ret; + + return 0; } +static int +rc632_fini(struct rfid_asic_handle *ah) +{ + int ret; + + /* switch off rf */ + ret = rc632_turn_off_rf(ah); + if (ret < 0) + return ret; + + ret = rc632_power_down(ah); + if (ret < 0) + return ret; + + return 0; +} +#endif + + +/* + * Philips CL RC632 primitives for ISO 14443-A compliant PICC's + * + * (C) 2005 by Harald Welte <laforge@gnumonks.org> + * + */ + +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, 0x01); + + 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, + OPENPCD_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, + OPENPCD_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, + OPENPCD_14443A_BITPHASE); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD, + OPENPCD_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); + if (ret < 0) + return ret; + + return 0; +} + +static int +rc632_iso14443a_fini(struct iso14443a_handle *handle_14443) +{ + +#if 0 + ret = rc632_turn_off_rf(handle); + if (ret < 0) + return ret; +#endif + + + return 0; +} + + /* issue a 14443-3 A PCD -> PICC command in a short frame, such as REQA, WUPA */ int -rc632_iso14443a_transceive_sf(u_int8_t cmd, +rc632_iso14443a_transceive_sf(struct rfid_asic_handle *handle, + u_int8_t cmd, struct iso14443a_atqa *atqa) { int ret; @@ -261,22 +628,28 @@ rc632_iso14443a_transceive_sf(u_int8_t cmd, tx_buf[0] = cmd; /* transfer only 7 bits of last byte in frame */ - rc632_reg_write(RC632_REG_BIT_FRAMING, 0x07); + ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x07); + if (ret < 0) + return ret; - rc632_clear_bits(RC632_REG_CONTROL, - RC632_CONTROL_CRYPTO1_ON); + ret = rc632_clear_bits(handle, RC632_REG_CONTROL, + RC632_CONTROL_CRYPTO1_ON); + if (ret < 0) + return ret; #if 0 - ret = rc632_reg_write(RC632_REG_CHANNEL_REDUNDANCY, + ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, (RC632_CR_PARITY_ENABLE | RC632_CR_PARITY_ODD)); #else - rc632_clear_bits(RC632_REG_CHANNEL_REDUNDANCY, - RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE); + ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY, + RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE); #endif + if (ret < 0) + return ret; - ret = rc632_transceive(tx_buf, sizeof(tx_buf), + ret = rc632_transceive(handle, tx_buf, sizeof(tx_buf), (u_int8_t *)atqa, &rx_len, ISO14443A_FDT_ANTICOL_LAST1, 0); if (ret < 0) { @@ -285,7 +658,9 @@ rc632_iso14443a_transceive_sf(u_int8_t cmd, } /* switch back to normal 8bit last byte */ - rc632_reg_write(RC632_REG_BIT_FRAMING, 0x00); + ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x00); + if (ret < 0) + return ret; if (rx_len != 2) { DEBUGP("rx_len(%d) != 2\n", rx_len); @@ -296,8 +671,9 @@ rc632_iso14443a_transceive_sf(u_int8_t cmd, } /* transceive regular frame */ -static int -rc632_iso14443ab_transceive(unsigned int frametype, +int +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) @@ -327,20 +703,25 @@ rc632_iso14443ab_transceive(unsigned int frametype, return -EINVAL; break; } - rc632_reg_write(RC632_REG_CHANNEL_REDUNDANCY, channel_red); + ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, + channel_red); + if (ret < 0) + return ret; - ret = rc632_transceive(tx_buf, tx_len, rx_buf, &rxl, timeout, 0); + ret = rc632_transceive(handle, tx_buf, tx_len, rx_buf, &rxl, timeout, 0); *rx_len = rxl; if (ret < 0) return ret; + return 0; } /* transceive anti collission bitframe */ -static int -rc632_iso14443a_transceive_acf(struct iso14443a_anticol_cmd *acf, - unsigned int *bit_of_col) +int +rc632_iso14443a_transceive_acf(struct rfid_asic_handle *handle, + struct iso14443a_anticol_cmd *acf, + unsigned int *bit_of_col) { int ret; u_int8_t rx_buf[64]; @@ -352,18 +733,18 @@ rc632_iso14443a_transceive_acf(struct iso14443a_anticol_cmd *acf, memset(rx_buf, 0, sizeof(rx_buf)); /* disable mifare cryto */ - ret = rc632_clear_bits(RC632_REG_CONTROL, + ret = rc632_clear_bits(handle, RC632_REG_CONTROL, RC632_CONTROL_CRYPTO1_ON); if (ret < 0) return ret; /* disable CRC summing */ #if 0 - ret = rc632_reg_write(RC632_REG_CHANNEL_REDUNDANCY, + ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, (RC632_CR_PARITY_ENABLE | RC632_CR_PARITY_ODD)); #else - ret = rc632_clear_bits(RC632_REG_CHANNEL_REDUNDANCY, + ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY, RC632_CR_TX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE); #endif if (ret < 0) @@ -379,10 +760,12 @@ rc632_iso14443a_transceive_acf(struct iso14443a_anticol_cmd *acf, //rx_align = 8 - tx_last_bits;/* rx frame complements tx */ /* set RxAlign and TxLastBits*/ - rc632_reg_write(RC632_REG_BIT_FRAMING, - (rx_align << 4) | (tx_last_bits)); + ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, + (rx_align << 4) | (tx_last_bits)); + if (ret < 0) + return ret; - ret = rc632_transceive((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; @@ -395,11 +778,15 @@ rc632_iso14443a_transceive_acf(struct iso14443a_anticol_cmd *acf, memcpy(&acf->uid_bits[tx_bytes+1-2], &rx_buf[1], rx_len-1); /* determine whether there was a collission */ - error_flag = rc632_reg_read(RC632_REG_ERROR_FLAG); + ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag); + if (ret < 0) + return ret; if (error_flag & RC632_ERR_FLAG_COL_ERR) { /* retrieve bit of collission */ - boc = rc632_reg_read(RC632_REG_COLL_POS); + ret = rc632_reg_read(handle, RC632_REG_COLL_POS, &boc); + if (ret < 0) + return ret; /* bit of collission relative to start of part 1 of * anticollision frame (!) */ @@ -409,7 +796,6 @@ rc632_iso14443a_transceive_acf(struct iso14443a_anticol_cmd *acf, return 0; } -#if 0 enum rc632_rate { RC632_RATE_106 = 0x00, RC632_RATE_212 = 0x01, @@ -488,25 +874,25 @@ static int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle, if (rate > ARRAY_SIZE(rx_configs)) return -EINVAL; - rc = rc632_set_bit_mask(RC632_REG_RX_CONTROL1, + 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(RC632_REG_DECODER_CONTROL, + 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(RC632_REG_RX_THRESHOLD, + 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( + rc = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL, rx_configs[rate].bpsk_dem_ctrl); if (rc < 0) @@ -517,13 +903,13 @@ static int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle, if (rate > ARRAY_SIZE(tx_configs)) return -EINVAL; - rc = rc632_set_bit_mask(RC632_REG_CODER_CONTROL, + 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(RC632_REG_MOD_WIDTH, + rc = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, tx_configs[rate].mod_width); if (rc < 0) return rc; @@ -531,4 +917,527 @@ static int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle, return 0; } + +static int rc632_iso14443b_init(struct rfid_asic_handle *handle) +{ + int ret; + + // FIXME: some FIFO work + + /* flush fifo (our way) */ + ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01); + if (ret < 0) + return ret; + + 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_MOD_SRC_INT)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE, 0x04); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_CODER_CONTROL, + (RC632_CDRCTRL_TXCD_NRZ | + RC632_CDRCTRL_RATE_14443B)); + 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, + (RC632_TBFRAMING_SOF_11L_3H | + (6 << RC632_TBFRAMING_SPACE_SHIFT) | + RC632_TBFRAMING_EOF_11)); + 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_BPSK | + RC632_DECCTRL_RXFR_14443B)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE, + OPENPCD_14443B_BITPHASE); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD, + OPENPCD_14443B_THRESHOLD); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL, + ((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)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2, + (RC632_RXCTRL2_AUTO_PD | + RC632_RXCTRL2_DECSRC_INT)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x03); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, + (RC632_CR_TX_CRC_ENABLE | + RC632_CR_RX_CRC_ENABLE | + RC632_CR_CRC3309)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0xff); + if (ret < 0) + return ret; + + ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xff); + if (ret < 0) + return ret; + + return 0; +} + +static int +rc632_iso15693_init(struct rfid_asic_handle *h) +{ + int ret; + + ret = rc632_reg_write(h, RC632_REG_TX_CONTROL, + (RC632_TXCTRL_MOD_SRC_INT | + RC632_TXCTRL_TX2_INV | + RC632_TXCTRL_TX2_RF_EN | + RC632_TXCTRL_TX1_RF_EN)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CW_CONDUCTANCE, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_CONDUCTANCE, 0x03); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CODER_CONTROL, + (RC632_CDRCTRL_RATE_15693 | + 0x03)); /* FIXME */ + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_TYPE_B_FRAMING, 0x00); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_RX_CONTROL1, + (RC632_RXCTRL1_SUBCP_16 | + RC632_RXCTRL1_ISO15693 | + RC632_RXCTRL1_GAIN_35DB)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_DECODER_CONTROL, + (RC632_DECCTRL_RXFR_15693 | + RC632_DECCTRL_RX_INVERT)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_BIT_PHASE, 0xe0); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_RX_THRESHOLD, 0xff); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_BPSK_DEM_CONTROL, 0x00); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_RX_CONTROL2, + (RC632_RXCTRL2_AUTO_PD | + RC632_RXCTRL2_DECSRC_INT)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY, + (RC632_CR_CRC3309 | + RC632_CR_RX_CRC_ENABLE | + RC632_CR_TX_CRC_ENABLE)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_LSB, 0xff); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_MSB, 0xff); + if (ret < 0) + return ret; + + return 0; +} + +static int +rc632_iso15693_icode_init(struct rfid_asic_handle *h) +{ + int ret; + + ret = rc632_reg_write(h, RC632_REG_TX_CONTROL, + (RC632_TXCTRL_MOD_SRC_INT | + RC632_TXCTRL_TX2_INV | + RC632_TXCTRL_TX2_RF_EN | + RC632_TXCTRL_TX1_RF_EN)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CW_CONDUCTANCE, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_CONDUCTANCE, 0x02); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CODER_CONTROL, 0x2c); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_TYPE_B_FRAMING, 0x00); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_RX_CONTROL1, 0x8b); /* FIXME */ + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_DECODER_CONTROL, 0x00); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_BIT_PHASE, 0x52); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_RX_THRESHOLD, 0x66); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_BPSK_DEM_CONTROL, 0x00); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_RX_CONTROL2, + RC632_RXCTRL2_DECSRC_INT); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY, + (RC632_CR_RX_CRC_ENABLE | + RC632_CR_TX_CRC_ENABLE)); + ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_LSB, 0xfe); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_MSB, 0xff); + if (ret < 0) + return ret; + + return 0; +} + +static int +rc632_iso15693_icl_init(struct rfid_asic_handle *h) +{ + int ret; + + /* ICL */ + + ret = rc632_reg_write(h, RC632_REG_TX_CONTROL, + (RC632_TXCTRL_MOD_SRC_INT | + RC632_TXCTRL_TX2_INV | + RC632_TXCTRL_TX2_RF_EN | + RC632_TXCTRL_TX1_RF_EN)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CW_CONDUCTANCE, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_CONDUCTANCE, 0x11); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CODER_CONTROL, + (RC632_CDRCTRL_RATE_15693 | + RC632_CDRCTRL_TXCD_ICODE_STD | + 0x03)); /* FIXME */ + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH, 0x3f); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f); + if (ret < 0) + return ret; + ret = rc632_reg_write(h, RC632_REG_RX_CONTROL1, + (RC632_RXCTRL1_SUBCP_16| + RC632_RXCTRL1_ISO15693| + RC632_RXCTRL1_GAIN_35DB)); + if (ret < 0) + return ret; + ret = rc632_reg_write(h, RC632_REG_DECODER_CONTROL, + (RC632_DECCTRL_RX_INVERT| + RC632_DECCTRL_RXFR_15693)); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_BIT_PHASE, 0xbd); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_RX_THRESHOLD, 0xff); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_BPSK_DEM_CONTROL, 0x00); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_RX_CONTROL2, + RC632_RXCTRL2_DECSRC_INT); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY, 0x00); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_LSB, 0x12); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_MSB, 0xe0); + if (ret < 0) + return ret; + + return 0; +} + +struct mifare_authcmd { + u_int8_t auth_cmd; + u_int8_t block_address; + u_int32_t serno; /* lsb 1 2 msb */ +} __attribute__ ((packed)); + + +#define RFID_MIFARE_KEY_LEN 6 +#define RFID_MIFARE_KEY_CODED_LEN 12 + +/* Transform crypto1 key from generic 6byte into rc632 specific 12byte */ +static int +rc632_mifare_transform_key(const u_int8_t *key6, u_int8_t *key12) +{ + int i; + u_int8_t ln; + u_int8_t hn; + + for (i = 0; i < RFID_MIFARE_KEY_LEN; i++) { + ln = key6[i] & 0x0f; + hn = key6[i] >> 4; + key12[i * 2 + 1] = (~ln << 4) | ln; + key12[i * 2] = (~hn << 4) | hn; + } + return 0; +} + +static int +rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key) +{ + u_int8_t coded_key[RFID_MIFARE_KEY_CODED_LEN]; + u_int8_t reg; + int ret; + + ret = rc632_mifare_transform_key(key, coded_key); + if (ret < 0) + return ret; + + ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_LOAD_KEY); + if (ret < 0) + return ret; + + ret = rc632_wait_idle(h, RC632_TMO_AUTH1); + if (ret < 0) + return ret; + + ret = rc632_reg_read(h, RC632_REG_ERROR_FLAG, ®); + if (ret < 0) + return ret; + + if (reg & RC632_ERR_FLAG_KEY_ERR) + return -EINVAL; + + return 0; +} + +static int +rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, + u_int8_t block) +{ + int ret; + struct mifare_authcmd acmd; + u_int8_t reg; + + if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B) + return -EINVAL; + + /* Initialize acmd */ + acmd.block_address = block & 0xff; + acmd.auth_cmd = cmd; + //acmd.serno = htonl(serno); + acmd.serno = serno; + + /* Clear Rx CRC */ + ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY, + RC632_CR_RX_CRC_ENABLE); + if (ret < 0) + return ret; + + /* Send Authent1 Command */ + ret = rc632_fifo_write(h, sizeof(acmd), (unsigned char *)&acmd, 0x03); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT1); + if (ret < 0) + return ret; + + /* Wait until transmitter is idle */ + ret = rc632_wait_idle(h, RC632_TMO_AUTH1); + if (ret < 0) + return ret; + + ret = rc632_reg_read(h, RC632_REG_SECONDARY_STATUS, ®); + if (ret < 0) + return ret; + if (reg & 0x07) + return -EIO; + + /* Clear Tx CRC */ + ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY, + RC632_CR_TX_CRC_ENABLE); + 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); + if (ret < 0) + return ret; + + /* Check whether authentication was successful */ + ret = rc632_reg_read(h, RC632_REG_CONTROL, ®); + if (ret < 0) + return ret; + + if (!(reg & RC632_CONTROL_CRYPTO1_ON)) + return -EACCES; + + return 0; + +} + +/* transceive regular frame */ +static int +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) +{ + int ret; + u_int8_t rxl = *rx_len & 0xff; + + DEBUGP("entered\n"); + memset(rx_buf, 0, *rx_len); + +#if 1 + ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, + (RC632_CR_PARITY_ENABLE | + RC632_CR_PARITY_ODD | + RC632_CR_TX_CRC_ENABLE | + RC632_CR_RX_CRC_ENABLE)); +#else + ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY, + RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE); #endif + if (ret < 0) + return ret; + + ret = rc632_transceive(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0); + *rx_len = rxl; + if (ret < 0) + return ret; + + + return 0; +} + |