summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--openpcd/firmware/include/rfid.h14
-rw-r--r--openpcd/firmware/include/rfid_protocol_mifare_classic.h28
-rw-r--r--openpcd/firmware/src/dbgu.c8
-rw-r--r--openpcd/firmware/src/main_dumbreader.c12
-rw-r--r--openpcd/firmware/src/rc632.c99
-rw-r--r--openpcd/firmware/src/rc632.h24
-rw-r--r--openpcd/firmware/src/rc632_highlevel.c1149
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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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;
+}
+
personal git repositories of Harald Welte. Your mileage may vary