summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlaforge <laforge@e0336214-984f-0b4b-a45f-81c69e1f0ede>2005-11-08 08:34:15 +0000
committerlaforge <laforge@e0336214-984f-0b4b-a45f-81c69e1f0ede>2005-11-08 08:34:15 +0000
commit05c7e304271bcf88901da3782fcd3f28a0c7c9cf (patch)
treec7972af3be2f8a6619af551faa980cd699399b1e /src
parentea11c6e508eb88d18847f4027bbc0a5ced0200b3 (diff)
use autoconf/automake
git-svn-id: https://svn.gnumonks.org/trunk/librfid@1658 e0336214-984f-0b4b-a45f-81c69e1f0ede
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am13
-rw-r--r--src/rc632.h214
-rw-r--r--src/rfid.c56
-rw-r--r--src/rfid_asic_rc632.c1295
-rw-r--r--src/rfid_asic_rc632_14443a.c394
-rw-r--r--src/rfid_asic_rc632_14443b.c69
-rw-r--r--src/rfid_asic_rc632_mifare.c25
-rw-r--r--src/rfid_iso14443_common.c58
-rw-r--r--src/rfid_iso14443_common.h11
-rw-r--r--src/rfid_layer2.c76
-rw-r--r--src/rfid_layer2_iso14443a.c294
-rw-r--r--src/rfid_layer2_iso14443b.c344
-rw-r--r--src/rfid_layer2_iso15693.c302
-rw-r--r--src/rfid_proto_mifare_classic.c148
-rw-r--r--src/rfid_proto_mifare_ul.c162
-rw-r--r--src/rfid_proto_tcl.c694
-rw-r--r--src/rfid_protocol.c113
-rw-r--r--src/rfid_reader.c65
-rw-r--r--src/rfid_reader_cm5121.c337
-rw-r--r--src/rfid_reader_cm5121_ccid_direct.c36
-rw-r--r--src/rfid_reader_cm5121_openct.c59
21 files changed, 4765 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..2f35d9b
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,13 @@
+LIBVERSION= 0:0:0
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+
+lib_LTLIBRARIES = librfid.la
+
+CORE=rfid.c rfid_layer2.c rfid_protocol.c rfid_reader.c
+L2=rfid_layer2_iso14443a.c rfid_layer2_14443b.c rfid_layer2_iso15693.c rfid_iso14443_common.o
+PROTO=rfid_proto_tcl.c rfid_proto_mifare_ul.c rfid_proto_mifare_classic.c
+READER=rfid_reader_cm5121.c rfid_asic_rc632.c
+
+librfid_la_LDFLAGS = -Wc,-nostartfiles -version-info $(LIBVERSION)
+librfid_la_SOURCES = $(CORE) $(L2) $(PROTO) $(READER)
+
diff --git a/src/rc632.h b/src/rc632.h
new file mode 100644
index 0000000..4ad0e99
--- /dev/null
+++ b/src/rc632.h
@@ -0,0 +1,214 @@
+/* Register definitions for Philips CL RC632 RFID Reader IC
+ *
+ * (C) 2005 Harald Welte <laforge@gnumonks.org>
+ *
+ * Licensed under GNU General Public License, Version 2
+ */
+
+enum rc632_registers {
+ RC632_REG_PAGE0 = 0x00,
+ RC632_REG_COMMAND = 0x01,
+ RC632_REG_FIFO_DATA = 0x02,
+ RC632_REG_PRIMARY_STATUS = 0x03,
+ RC632_REG_FIFO_LENGTH = 0x04,
+ RC632_REG_SECONDARY_STATUS = 0x05,
+ RC632_REG_INTERRUPT_EN = 0x06,
+ RC632_REG_INTERRUPT_RQ = 0x07,
+
+ RC632_REG_PAGE1 = 0x08,
+ RC632_REG_CONTROL = 0x09,
+ RC632_REG_ERROR_FLAG = 0x0a,
+ RC632_REG_COLL_POS = 0x0b,
+ RC632_REG_TIMER_VALUE = 0x0c,
+ RC632_REG_CRC_RESULT_LSB = 0x0d,
+ RC632_REG_CRC_RESULT_MSB = 0x0e,
+ RC632_REG_BIT_FRAMING = 0x0f,
+
+ RC632_REG_PAGE2 = 0x10,
+ RC632_REG_TX_CONTROL = 0x11,
+ RC632_REG_CW_CONDUCTANCE = 0x12,
+ RC632_REG_MOD_CONDUCTANCE = 0x13,
+ RC632_REG_CODER_CONTROL = 0x14,
+ RC632_REG_MOD_WIDTH = 0x15,
+ RC632_REG_MOD_WIDTH_SOF = 0x16,
+ RC632_REG_TYPE_B_FRAMING = 0x17,
+
+ RC632_REG_PAGE3 = 0x18,
+ RC632_REG_RX_CONTROL1 = 0x19,
+ RC632_REG_DECODER_CONTROL = 0x1a,
+ RC632_REG_BIT_PHASE = 0x1b,
+ RC632_REG_RX_THRESHOLD = 0x1c,
+ RC632_REG_BPSK_DEM_CONTROL = 0x1d,
+ RC632_REG_RX_CONTROL2 = 0x1e,
+ RC632_REG_CLOCK_Q_CONTROL = 0x1f,
+
+ RC632_REG_PAGE4 = 0x20,
+ RC632_REG_RX_WAIT = 0x21,
+ RC632_REG_CHANNEL_REDUNDANCY = 0x22,
+ RC632_REG_CRC_PRESET_LSB = 0x23,
+ RC632_REG_CRC_PRESET_MSB = 0x24,
+ RC632_REG_TIME_SLOT_PERIOD = 0x25,
+ RC632_REG_MFOUT_SELECT = 0x26,
+ RC632_REG_PRESET_27 = 0x27,
+
+ RC632_REG_PAGE5 = 0x28,
+ RC632_REG_FIFO_LEVEL = 0x29,
+ RC632_REG_TIMER_CLOCK = 0x2a,
+ RC632_REG_TIMER_CONTROL = 0x2b,
+ RC632_REG_TIMER_RELOAD = 0x2c,
+ RC632_REG_IRQ_PIN_CONFIG = 0x2d,
+ RC632_REG_PRESET_2E = 0x2e,
+ RC632_REG_PRESET_2F = 0x2f,
+
+ RC632_REG_PAGE6 = 0x30,
+
+ RC632_REG_PAGE7 = 0x38,
+ RC632_REG_TEST_ANA_SELECT = 0x3a,
+ RC632_REG_TEST_DIGI_SELECT = 0x3d,
+};
+
+enum rc632_reg_command {
+ RC632_CMD_IDLE = 0x00,
+ RC632_CMD_WRITE_E2 = 0x01,
+ RC632_CMD_READ_E2 = 0x03,
+ RC632_CMD_LOAD_CONFIG = 0x07,
+ RC632_CMD_LOAD_KEY_E2 = 0x0b,
+ RC632_CMD_AUTHENT1 = 0x0c,
+ RC632_CMD_CALC_CRC = 0x12,
+ RC632_CMD_AUTHENT2 = 0x14,
+ RC632_CMD_RECEIVE = 0x16,
+ RC632_CMD_LOAD_KEY = 0x19,
+ RC632_CMD_TRANSMIT = 0x1a,
+ RC632_CMD_TRANSCIEVE = 0x1e,
+ RC632_CMD_STARTUP = 0x3f,
+};
+
+enum rc632_reg_control {
+ RC632_CONTROL_CRYPTO1_ON = 0x08,
+ RC632_CONTROL_POWERDOWN = 0x10,
+};
+
+enum rc632_reg_error_flag {
+ RC632_ERR_FLAG_COL_ERR = 0x01,
+ RC632_ERR_FLAG_PARITY_ERR = 0x02,
+ RC632_ERR_FLAG_FRAMING_ERR = 0x04,
+ RC632_ERR_FLAG_CRC_ERR = 0x08,
+ RC632_ERR_FLAG_FIFO_OVERFLOW = 0x10,
+ RC632_ERR_FLAG_ACCESS_ERR = 0x20,
+ RC632_ERR_FLAG_KEY_ERR = 0x40,
+};
+
+enum rc632_reg_tx_control {
+ RC632_TXCTRL_TX1_RF_EN = 0x01,
+ RC632_TXCTRL_TX2_RF_EN = 0x02,
+ RC632_TXCTRL_TX2_CW = 0x04,
+ RC632_TXCTRL_TX2_INV = 0x08,
+ RC632_TXCTRL_FORCE_100_ASK = 0x10,
+
+ RC632_TXCTRL_MOD_SRC_LOW = 0x00,
+ RC632_TXCTRL_MOD_SRC_HIGH = 0x20,
+ RC632_TXCTRL_MOD_SRC_INT = 0x40,
+ RC632_TXCTRL_MOD_SRC_MFIN = 0x60,
+};
+
+enum rc632_reg_coder_control {
+ RC632_CDRCTRL_TXCD_NRZ = 0x00,
+ RC632_CDRCTRL_TXCD_14443A = 0x01,
+ RC632_CDRCTRL_TXCD_ICODE_STD = 0x04,
+
+ RC632_CDRCTRL_RATE_848K = 0x00,
+#if 0
+ /* See mc073930.pdf, page 41 */
+ RC632_CDRCTRL_RATE_424K = 0x80,
+#else
+ RC632_CDRCTRL_RATE_424K = 0x08,
+#endif
+ RC632_CDRCTRL_RATE_212K = 0x10,
+ RC632_CDRCTRL_RATE_106K = 0x18,
+ RC632_CDRCTRL_RATE_14443B = 0x20,
+ RC632_CDRCTRL_RATE_15693 = 0x28,
+ RC632_CDRCTRL_RATE_ICODE_FAST = 0x30,
+};
+
+enum rc632_erg_type_b_framing {
+ RC632_TBFRAMING_SOF_10L_2H = 0x00,
+ RC632_TBFRAMING_SOF_10L_3H = 0x01,
+ RC632_TBFRAMING_SOF_11L_2H = 0x02,
+ RC632_TBFRAMING_SOF_11L_3H = 0x03,
+
+ RC632_TBFRAMING_EOF_10 = 0x00,
+ RC632_TBFRAMING_EOF_11 = 0x20,
+
+ RC632_TBFRAMING_NO_TX_SOF = 0x80,
+ RC632_TBFRAMING_NO_TX_EOF = 0x40,
+};
+#define RC632_TBFRAMING_SPACE_SHIFT 2
+#define RC632_TBFRAMING_SPACE_MASK 7
+
+enum rc632_reg_rx_control1 {
+ RC632_RXCTRL1_GAIN_20DB = 0x00,
+ RC632_RXCTRL1_GAIN_24DB = 0x01,
+ RC632_RXCTRL1_GAIN_31DB = 0x02,
+ RC632_RXCTRL1_GAIN_35DB = 0x03,
+
+ RC632_RXCTRL1_LP_OFF = 0x04,
+ RC632_RXCTRL1_ISO15693 = 0x08,
+ RC632_RXCTRL1_ISO14443 = 0x10,
+
+ RC632_RXCTRL1_SUBCP_1 = 0x00,
+ RC632_RXCTRL1_SUBCP_2 = 0x20,
+ RC632_RXCTRL1_SUBCP_4 = 0x40,
+ RC632_RXCTRL1_SUBCP_8 = 0x60,
+ RC632_RXCTRL1_SUBCP_16 = 0x80,
+};
+
+enum rc632_reg_decoder_control {
+ RC632_DECCTRL_MANCHESTER = 0x00,
+ RC632_DECCTRL_BPSK = 0x01,
+
+ RC632_DECCTRL_RX_INVERT = 0x04,
+
+ RC632_DECCTRL_RXFR_ICODE = 0x00,
+ RC632_DECCTRL_RXFR_14443A = 0x08,
+ RC632_DECCTRL_RXFR_15693 = 0x10,
+ RC632_DECCTRL_RXFR_14443B = 0x18,
+
+ RC632_DECCTRL_ZEROAFTERCOL = 0x20,
+
+ RC632_DECCTRL_RX_MULTIPLE = 0x40,
+};
+
+enum rc632_reg_bpsk_dem_control {
+ RC632_BPSKD_TAUB_SHIFT = 0x00,
+ RC632_BPSKD_TAUB_MASK = 0x03,
+
+ RC632_BPSKD_TAUD_SHIFT = 0x02,
+ RC632_BPSKD_TAUD_MASK = 0x03,
+
+ RC632_BPSKD_FILTER_AMP_DETECT = 0x10,
+ RC632_BPSKD_NO_RX_EOF = 0x20,
+ RC632_BPSKD_NO_RX_EGT = 0x40,
+ RC632_BPSKD_NO_RX_SOF = 0x80,
+};
+
+enum rc632_reg_rx_control2 {
+ RC632_RXCTRL2_DECSRC_LOW = 0x00,
+ RC632_RXCTRL2_DECSRC_INT = 0x01,
+ RC632_RXCTRL2_DECSRC_SUBC_MFIN = 0x10,
+ RC632_RXCTRL2_DECSRC_BASE_MFIN = 0x11,
+
+ RC632_RXCTRL2_AUTO_PD = 0x40,
+ RC632_RXCTRL2_CLK_I = 0x80,
+ RC632_RXCTRL2_CLK_Q = 0x00,
+};
+
+enum rc632_reg_channel_redundancy {
+ RC632_CR_PARITY_ENABLE = 0x01,
+ RC632_CR_PARITY_ODD = 0x02,
+ RC632_CR_TX_CRC_ENABLE = 0x04,
+ RC632_CR_RX_CRC_ENABLE = 0x08,
+ RC632_CR_CRC8 = 0x10,
+ RC632_CR_CRC3309 = 0x20,
+};
+
+
diff --git a/src/rfid.c b/src/rfid.c
new file mode 100644
index 0000000..be72f12
--- /dev/null
+++ b/src/rfid.c
@@ -0,0 +1,56 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+
+#include <rfid/rfid_reader_cm5121.h>
+#include <rfid/rfid_protocol.h>
+#include <rfid/rfid_protocol_tcl.h>
+#include <rfid/rfid_protocol_mifare_ul.h>
+#include <rfid/rfid_protocol_mifare_classic.h>
+
+const char *
+rfid_hexdump(const void *data, unsigned int len)
+{
+ static char string[1024];
+ unsigned char *d = (unsigned char *) data;
+ unsigned int i, left;
+
+ string[0] = '\0';
+ left = sizeof(string);
+ for (i = 0; len--; i += 3) {
+ if (i >= sizeof(string) -4)
+ break;
+ snprintf(string+i, 4, " %02x", *d++);
+ }
+ return string;
+}
+
+int rfid_init()
+{
+ rfid_reader_register(&rfid_reader_cm5121);
+ rfid_layer2_register(&rfid_layer2_iso14443a);
+ rfid_layer2_register(&rfid_layer2_iso14443b);
+ rfid_protocol_register(&rfid_protocol_tcl);
+ rfid_protocol_register(&rfid_protocol_mful);
+ rfid_protocol_register(&rfid_protocol_mfcl);
+
+ return 0;
+}
+
+void rfid_fini()
+{
+ /* FIXME: implementation */
+}
diff --git a/src/rfid_asic_rc632.c b/src/rfid_asic_rc632.c
new file mode 100644
index 0000000..4377d73
--- /dev/null
+++ b/src/rfid_asic_rc632.c
@@ -0,0 +1,1295 @@
+/* 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 <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_asic.h>
+#include <rfid/rfid_asic_rc632.h>
+#include <rfid/rfid_reader_cm5121.h>
+#include <rfid/rfid_layer2_iso14443a.h>
+#include <rfid/rfid_protocol_mifare_classic.h>
+
+#include "rfid_iso14443_common.h"
+#include "rc632.h"
+//#include "rc632_14443a.h"
+
+
+#define RC632_TMO_AUTH1 14000
+
+#define ENTER() DEBUGP("entering\n")
+struct rfid_asic rc632;
+
+/* Register and FIFO Access functions */
+static int
+rc632_reg_write(struct rfid_asic_handle *handle,
+ u_int8_t reg,
+ u_int8_t val)
+{
+ return handle->rath->rat->priv.rc632.fn.reg_write(handle->rath, reg, val);
+}
+
+static int
+rc632_reg_read(struct rfid_asic_handle *handle,
+ u_int8_t reg,
+ u_int8_t *val)
+{
+ return handle->rath->rat->priv.rc632.fn.reg_read(handle->rath, reg, val);
+}
+
+static int
+rc632_fifo_write(struct rfid_asic_handle *handle,
+ u_int8_t len,
+ const u_int8_t *buf,
+ u_int8_t flags)
+{
+ return handle->rath->rat->priv.rc632.fn.fifo_write(handle->rath,
+ len, buf, flags);
+}
+
+static int
+rc632_fifo_read(struct rfid_asic_handle *handle,
+ u_int8_t len,
+ u_int8_t *buf)
+{
+ return handle->rath->rat->priv.rc632.fn.fifo_read(handle->rath, len, buf);
+}
+
+
+static int
+rc632_set_bits(struct rfid_asic_handle *handle,
+ u_int8_t reg,
+ u_int8_t val)
+{
+ int ret;
+ u_int8_t tmp;
+
+ ret = rc632_reg_read(handle, reg, &tmp);
+ if (ret < 0)
+ return -1;
+
+ /* if bits are already set, no need to set them again */
+ if ((tmp & val) == val)
+ return 0;
+
+ return rc632_reg_write(handle, reg, (tmp|val)&0xff);
+}
+
+static int
+rc632_clear_bits(struct rfid_asic_handle *handle,
+ u_int8_t reg,
+ u_int8_t val)
+{
+ int ret;
+ u_int8_t tmp;
+
+ ret = rc632_reg_read(handle, reg, &tmp);
+ if (ret < 0) {
+ DEBUGP("error during reg_read(%p, %d):%d\n",
+ handle, reg, ret);
+ return -1;
+ }
+ /* if bits are already cleared, no need to clear them again */
+ if ((tmp & val) == 0)
+ return 0;
+
+ return rc632_reg_write(handle, reg, (tmp & ~val)&0xff);
+}
+
+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);
+}
+
+/* Stupid RC623 implementations don't evaluate interrupts but poll the
+ * command register for "status idle" */
+static int
+rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t timeout)
+{
+ u_int8_t cmd = 0xff;
+ int ret;
+
+ while (cmd != 0) {
+ ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd);
+ if (ret < 0)
+ return ret;
+
+ if (cmd == 0) {
+ /* FIXME: read second time ?? */
+ return 0;
+ }
+
+ {
+ 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);
+ }
+
+ usleep(100);
+
+ /* Fixme: Abort after some timeout */
+ }
+
+ return 0;
+}
+
+static int
+rc632_transmit(struct rfid_asic_handle *handle,
+ const u_int8_t *buf,
+ u_int8_t len,
+ u_int64_t timeout)
+{
+ int ret;
+
+ ret = rc632_fifo_write(handle, len, buf, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_TRANSMIT);
+ if (ret < 0)
+ return ret;
+
+ 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_transcieve(struct rfid_asic_handle *handle,
+ const u_int8_t *tx_buf,
+ u_int8_t tx_len,
+ u_int8_t *rx_buf,
+ u_int8_t *rx_len,
+ unsigned int timer,
+ unsigned int toggle)
+{
+ int ret;
+
+ ret = rc632_fifo_write(handle, tx_len, tx_buf, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_TRANSCIEVE);
+ if (ret < 0)
+ return ret;
+
+ if (toggle == 1)
+ tcl_toggle_pcb(handle);
+
+ ret = rc632_wait_idle(handle, timer);
+ if (ret < 0)
+ return ret;
+
+ 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");
+
+ rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &tmp);
+ rc632_reg_read(handle, RC632_REG_CHANNEL_REDUNDANCY, &tmp);
+
+ return -1;
+ }
+
+ 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;
+}
+
+
+
+/* generic FIFO access functions (if no more efficient ones provided by
+ * transport driver) */
+
+static int
+generic_fifo_write()
+{
+ // FIXME: implementation (not needed for CM 5121)
+ return -1;
+}
+
+static int
+generic_fifo_read()
+{
+ // FIXME: implementation (not neded for CM 5121)
+ return -1;
+}
+
+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;
+}
+
+struct rfid_asic_handle *
+rc632_open(struct rfid_asic_transport_handle *th)
+{
+ struct rfid_asic_handle *h;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return NULL;
+ memset(h, 0, sizeof(*h));
+
+ h->asic = &rc632;
+ h->rath = th;
+ h->fc = h->asic->fc;
+ h->mtu = h->mru = 40; /* FIXME */
+
+ if (rc632_init(h) < 0) {
+ free(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+void
+rc632_close(struct rfid_asic_handle *h)
+{
+ rc632_fini(h);
+ free(h);
+}
+
+
+/*
+ * Philips CL RC632 primitives for ISO 14443-A compliant PICC's
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+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, 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,
+ 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);
+ 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 */
+static int
+rc632_iso14443a_transcieve_sf(struct rfid_asic_handle *handle,
+ u_int8_t cmd,
+ struct iso14443a_atqa *atqa)
+{
+ int ret;
+ u_int8_t tx_buf[1];
+ u_int8_t rx_len = 2;
+
+ memset(atqa, 0, sizeof(atqa));
+
+ tx_buf[0] = cmd;
+
+ /* transfer only 7 bits of last byte in frame */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x07);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+#if 0
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+#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_transcieve(handle, tx_buf, sizeof(tx_buf),
+ (u_int8_t *)atqa, &rx_len, 0x32, 0);
+ if (ret < 0) {
+ DEBUGP("error during rc632_transcieve()\n");
+ return ret;
+ }
+
+ /* switch back to normal 8bit last byte */
+ 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);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* transcieve regular frame */
+static int
+rc632_iso14443ab_transcieve(struct rfid_asic_handle *handle,
+ unsigned int frametype,
+ const u_int8_t *tx_buf, unsigned int tx_len,
+ u_int8_t *rx_buf, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags)
+{
+ int ret;
+ u_int8_t rxl = *rx_len & 0xff;
+ u_int8_t channel_red;
+
+ memset(rx_buf, 0, *rx_len);
+
+ switch (frametype) {
+ case RFID_14443A_FRAME_REGULAR:
+ case RFID_MIFARE_FRAME:
+ channel_red = RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE
+ |RC632_CR_PARITY_ENABLE|RC632_CR_PARITY_ODD;
+ break;
+ case RFID_14443B_FRAME_REGULAR:
+ channel_red = RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE
+ |RC632_CR_CRC3309;
+ break;
+#if 0
+ case RFID_MIFARE_FRAME:
+ channel_red = RC632_CR_PARITY_ENABLE|RC632_CR_PARITY_ODD;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ break;
+ }
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ channel_red);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0);
+ *rx_len = rxl;
+ if (ret < 0)
+ return ret;
+
+
+ return 0;
+}
+
+/* transcieve anti collission bitframe */
+static int
+rc632_iso14443a_transcieve_acf(struct rfid_asic_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col)
+{
+ int ret;
+ u_int8_t rx_buf[64];
+ u_int8_t rx_len = sizeof(rx_buf);
+ u_int8_t rx_align = 0, tx_last_bits, tx_bytes;
+ u_int8_t boc;
+ u_int8_t error_flag;
+ *bit_of_col = ISO14443A_BITOFCOL_NONE;
+ memset(rx_buf, 0, sizeof(rx_buf));
+
+ /* disable mifare cryto */
+ 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(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+#else
+ ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_TX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE);
+#endif
+ if (ret < 0)
+ return ret;
+
+ tx_last_bits = acf->nvb & 0x0f; /* lower nibble indicates bits */
+ tx_bytes = acf->nvb >> 4;
+ if (tx_last_bits) {
+ tx_bytes++;
+ rx_align = (tx_last_bits+1) % 8;/* rx frame complements tx */
+ }
+
+ //rx_align = 8 - tx_last_bits;/* rx frame complements tx */
+
+ /* set RxAlign and TxLastBits*/
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING,
+ (rx_align << 4) | (tx_last_bits));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, (u_int8_t *)acf, tx_bytes,
+ rx_buf, &rx_len, 0x32, 0);
+ if (ret < 0)
+ return ret;
+
+ /* bitwise-OR the two halves of the split byte */
+ acf->uid_bits[tx_bytes-2] = (
+ (acf->uid_bits[tx_bytes-2] & (0xff >> (8-tx_last_bits)))
+ | rx_buf[0]);
+ /* copy the rest */
+ memcpy(&acf->uid_bits[tx_bytes+1-2], &rx_buf[1], rx_len-1);
+
+ /* determine whether there was a collission */
+ 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 */
+ 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 (!) */
+ *bit_of_col = 2*8 + boc;
+ }
+
+ 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,
+ CM5121_14443B_BITPHASE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD,
+ CM5121_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;
+
+ ret = rc632_clear_bits(h, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+
+ /* Clear Rx CRC */
+ ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_RX_CRC_ENABLE);
+ 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;
+
+}
+
+/* transcieve regular frame */
+static int
+rc632_mifare_transcieve(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_transcieve(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0);
+ *rx_len = rxl;
+ if (ret < 0)
+ return ret;
+
+
+ return 0;
+}
+
+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,
+ .turn_on_rf = &rc632_turn_on_rf,
+ .turn_off_rf = &rc632_turn_off_rf,
+ .transcieve = &rc632_iso14443ab_transcieve,
+ .iso14443a = {
+ .init = &rc632_iso14443a_init,
+ .transcieve_sf = &rc632_iso14443a_transcieve_sf,
+ .transcieve_acf = &rc632_iso14443a_transcieve_acf,
+ },
+ .iso14443b = {
+ .init = &rc632_iso14443b_init,
+ },
+ .iso15693 = {
+ .init = &rc632_iso15693_init,
+ },
+ .mifare_classic = {
+ .setkey = &rc632_mifare_set_key,
+ .auth = &rc632_mifare_auth,
+ },
+ },
+ },
+};
diff --git a/src/rfid_asic_rc632_14443a.c b/src/rfid_asic_rc632_14443a.c
new file mode 100644
index 0000000..4c8a37b
--- /dev/null
+++ b/src/rfid_asic_rc632_14443a.c
@@ -0,0 +1,394 @@
+/*
+ * Philips CL RC632 primitives for ISO 14443-A compliant PICC's
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_asic_rc632.h>
+#include <rfid/rfid_layer2_iso14443a.h>
+
+#include "rc632.h"
+
+#include "cm5121_rfid.h" /* FIXME: this needs to be modular */
+
+static int
+rc632_iso14443a_init(struct rfid_asic_handle *handle)
+{
+ int ret;
+
+#if 0
+ ret = rc632_power_up(handle);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_turn_on_rf(handle);
+ if (ret < 0)
+ return ret;
+#endif
+
+ // 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,
+ 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;
+
+ 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_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;
+}
+
+#if 0
+int
+rc632_iso14443a_select(struct rc632_handle *handle,
+ unsigned char *retptr,
+ )
+{
+ int ret;
+ unsigned char tx_buf[7];
+ unsigned char rx_buf[64];
+ unsigned char rx_len = 1;
+
+ memset(rx_buf, 0, sizeof(rx_buf));
+
+ tx_buf[0] = arg_8;
+ tx_buf[1] = 0x70;
+ (u_int32_t *)tx_buf[2] = arg_4;
+ tx_buf[6] = arg4+4;
+
+ /* disable mifare cryto */
+ ret = rc632_clear_bit(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+ 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));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, tx_buf, sizeof(tx_buf),
+ rx_buf, &rx_len, 0x32, 0);
+
+ if (ret < 0 || rx_len != 1)
+ return ret;
+
+ *retptr = rx_buf[0];
+
+ return 0;
+}
+
+/* issue a 14443-3 A PCD -> PICC command, such as REQA, WUPA */
+int
+rc632_iso14443a_req(sutruct rc632_handle *handle, unsigned char req,
+ unsigned char *resp)
+{
+ int ret;
+ unsigned char tx_buf[1];
+ unsigned char rx_buf[0x40];
+ unsigned char rx_len = 2;
+
+ memset(rx_buf, 0, sizeof(rx_buf));
+
+ tx_buf[0] = req;
+
+ /* transfer only 7 bits of last byte in frame */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x07);
+ if (ret < 0)
+ return ret;
+
+
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ 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_transcieve(handle, tx_buf, sizeof(tx_buf), rx_buf,
+ &rx_len, 0x32, 0);
+ if (ret < 0)
+ return ret;
+
+ /* switch back to normal 8bit last byte */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ if ((rx_len != 2) || (rx_buf[1] != 0xf0))
+ return -1;
+
+ resp[0] = rx_buf[0];
+ resp[1] = rx_buf[1];
+
+ return 0;
+}
+#endif
+
+/* issue a 14443-3 A PCD -> PICC command in a short frame, such as REQA, WUPA */
+static int
+rc632_iso14443a_transcieve_sf(struct rfid_asic_handle *handle,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa)
+{
+ int ret;
+ unsigned char tx_buf[1];
+ unsigned char rx_len = 2;
+
+ memset(atqa, 0, sizeof(atqa));
+
+ tx_buf[0] = cmd;
+
+ /* transfer only 7 bits of last byte in frame */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x07);
+ if (ret < 0)
+ return ret;
+
+
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ 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_transcieve(handle, tx_buf, sizeof(tx_buf),
+ (unsigned char *)atqa, &rx_len, 0x32, 0);
+ if (ret < 0) {
+ DEBUGP("error during rc632_transcieve()\n");
+ return ret;
+ }
+
+ /* switch back to normal 8bit last byte */
+ 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);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* transcieve regular frame */
+static int
+rc632_iso14443a_transcieve(struct rfid_asic_handle *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ int ret;
+ unsigned char rxl = *rx_len & 0xff;
+
+ memset(rx_buf, 0, *rx_len);
+
+ 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));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0);
+ *rx_len = rxl;
+ if (ret < 0)
+ return ret;
+
+
+ return 0;
+}
+
+/* transcieve anti collission bitframe */
+static int
+rc632_iso14443a_transcieve_acf(struct rfid_asic_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col)
+{
+ int ret;
+ unsigned char rx_buf[64];
+ unsigned char rx_len = sizeof(rx_buf);
+ unsigned char rx_align = 0, tx_last_bits, tx_bytes;
+ unsigned char boc;
+ unsigned char error_flag;
+ *bit_of_col = ISO14443A_BITOFCOL_NONE;
+ memset(rx_buf, 0, sizeof(rx_buf));
+
+ /* disable mifare cryto */
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+ /* disalbe CRC summing */
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+ if (ret < 0)
+ return ret;
+
+ tx_last_bits = acf->nvb & 0x0f; /* lower nibble indicates bits */
+ tx_bytes = acf->nvb >> 4;
+ if (tx_last_bits) {
+ tx_bytes++;
+ rx_align = (tx_last_bits+1) % 8;/* rx frame complements tx */
+ }
+
+ //rx_align = 8 - tx_last_bits;/* rx frame complements tx */
+
+ /* set RxAlign and TxLastBits*/
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING,
+ (rx_align << 4) | (tx_last_bits));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, (unsigned char *)acf, tx_bytes,
+ rx_buf, &rx_len, 0x32, 0);
+ if (ret < 0)
+ return ret;
+
+ /* bitwise-OR the two halves of the split byte */
+ acf->uid_bits[tx_bytes-2] = (
+ (acf->uid_bits[tx_bytes-2] & (0xff >> (8-tx_last_bits)))
+ | rx_buf[0]);
+ /* copy the rest */
+ memcpy(&acf->uid_bits[tx_bytes+1-2], &rx_buf[1], rx_len-1);
+
+ /* determine whether there was a collission */
+ 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 */
+ 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 (!) */
+ *bit_of_col = 2*8 + boc;
+ }
+
+ return 0;
+}
+
+
diff --git a/src/rfid_asic_rc632_14443b.c b/src/rfid_asic_rc632_14443b.c
new file mode 100644
index 0000000..62aa224
--- /dev/null
+++ b/src/rfid_asic_rc632_14443b.c
@@ -0,0 +1,69 @@
+
+#include "rc632.h"
+
+int rc632_iso14443b_init(struct rc632_handle *handle)
+{
+ // FIXME: some FIFO work
+ //
+ 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));
+
+ ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE, 0x3f);
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE, 0x04);
+
+ ret = rc632_reg_write(handle, RC632_REG_CODE_CONTROL,
+ (RC632_CDRCTRL_TXCD_NRZ |
+ RC632_CDRCTRL_RATE_14443B));
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13);
+
+ ret = rc632_reg_write(handle, RC632_REG_SOF_WIDTH, 0x3f);
+
+ ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING,
+ (RC632_TBFRAMING_SOF_11L_3H |
+ (6 << RC632_TBFRAMING_SPACE_SHIFT) |
+ RC632_TBFRAMING_EOF_11));
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1,
+ (RC632_RXCTRL1_GAIN_35DB |
+ RC632_RXCTRL1_ISO14443 |
+ RC632_RXCTRL1_SUBCP_8));
+
+ ret = rc632_reg_write(handle, RC632_REG_DECODE_CONTROL,
+ (RC632_DECCTRL_BPSK |
+ RC632_DECCTRL_RXFR_14443B));
+
+ ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE,
+ CM5121_14443B_BITPHASE);
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD,
+ CM5121_14443B_THRESHOLD);
+
+ ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL,
+ ((0x10 & RC632_BPSKD_TAUB_MASK)<<RC632_BPSKD_TAUB_SHIFT |
+ (0x11 & RC632_BPSKD_TAUD_MASK)<<RC632_BPSKD_TAUD_SHIFT |
+ RC632_BPSKD_FILTER_AMP_DETECT |
+ RC632_BPSKD_NO_RX_EOF |
+ RC632_BPSKD_NO_RX_EGT));
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2,
+ (RC632_RXCTRL2_AUTO_PD |
+ RC632_RXCTRL2_DECSRC_INT));
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x03);
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_RDUNDANCY,
+ (RC632_CR_TX_CRC_ENABLE |
+ RC632_CR_RX_CRC_ENABLE |
+ RC632_CR_CR3309));
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0xff);
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xff);
+
+}
+
diff --git a/src/rfid_asic_rc632_mifare.c b/src/rfid_asic_rc632_mifare.c
new file mode 100644
index 0000000..9bfb0ae
--- /dev/null
+++ b/src/rfid_asic_rc632_mifare.c
@@ -0,0 +1,25 @@
+
+int
+rc632_mifare_read16()
+{
+ unsigned char sndbuf[2];
+ unsigned char recvbuf[0x40];
+ unsigned char recvlen = sizeof(recvbuf);
+
+ int ret;
+
+ sndbuf[0] = 0x30;
+ sndbuf[1] = arg_4;
+
+ memset(recvbuf, 0, sizeof(recvbuf));
+
+ ret = rc632_transcieve(handle, sndbuf, sizeof(sndbuf),
+ recvbuf, &recvlen, 0x32, 0);
+ if (ret < 0)
+ return ret;
+
+ if (recvlen != 0x10)
+ return -1;
+
+ return 0;
+}
diff --git a/src/rfid_iso14443_common.c b/src/rfid_iso14443_common.c
new file mode 100644
index 0000000..38fed6b
--- /dev/null
+++ b/src/rfid_iso14443_common.c
@@ -0,0 +1,58 @@
+
+/*
+ * 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
+ */
+
+
+static unsigned int fsdi_table[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
+
+int iso14443_fsdi_to_fsd(unsigned int *fsd, unsigned char fsdi)
+{
+ /* ISO 14443-4:2000(E) Section 5.1. */
+ if (fsdi > sizeof(fsdi_table)/sizeof(unsigned int))
+ return -1;
+
+ *fsd = fsdi_table[fsdi];
+ return 0;
+}
+
+int iso14443_fsd_to_fsdi(unsigned char *fsdi, unsigned int fsd)
+{
+ int i;
+
+ for (i = 0; i < sizeof(fsdi_table)/sizeof(unsigned int); i++) {
+ if (fsdi_table[i] == fsd) {
+ *fsdi = i;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* calculate the fsd that is equal or the closest smaller value
+ * that can be coded as fsd */
+unsigned int iso14443_fsd_approx(unsigned int fsd)
+{
+ unsigned int tbl_size = sizeof(fsdi_table)/sizeof(unsigned int);
+ int i;
+
+ for (i = tbl_size-1; i >= 0; i--) {
+ if (fsdi_table[i] <= fsd)
+ return fsdi_table[i];
+ }
+ /* not reached: return smallest possible FSD */
+ return fsdi_table[0];
+}
+
diff --git a/src/rfid_iso14443_common.h b/src/rfid_iso14443_common.h
new file mode 100644
index 0000000..848d983
--- /dev/null
+++ b/src/rfid_iso14443_common.h
@@ -0,0 +1,11 @@
+#ifndef __RFID_ISO14443_COMMON_H
+#define __RFID_ISO14443_COMMON_H
+
+int iso14443_fsdi_to_fsd(unsigned int *fsd, unsigned char fsdi);
+int iso14443_fsd_to_fsdi(unsigned char *fsdi, unsigned int fsd);
+unsigned int iso14443_fsd_approx(unsigned int fsd);
+
+#define ISO14443_FREQ_CARRIER 13560000
+#define ISO14443_FREQ_SUBCARRIER (ISO14443_FREQ_CARRIER/16)
+
+#endif
diff --git a/src/rfid_layer2.c b/src/rfid_layer2.c
new file mode 100644
index 0000000..c1ab6a6
--- /dev/null
+++ b/src/rfid_layer2.c
@@ -0,0 +1,76 @@
+/* librfid - layer 2 protocol handler
+ * (C) 2005 by 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 <stdlib.h>
+#include <stdio.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_layer2.h>
+
+static struct rfid_layer2 *rfid_layer2_list;
+
+struct rfid_layer2_handle *
+rfid_layer2_init(struct rfid_reader_handle *rh, unsigned int id)
+{
+ struct rfid_layer2 *p;
+
+ for (p = rfid_layer2_list; p; p = p->next)
+ if (p->id == id)
+ return p->fn.init(rh);
+
+ DEBUGP("unable to find matching layer2 protocol\n");
+ return NULL;
+}
+
+int
+rfid_layer2_open(struct rfid_layer2_handle *ph)
+{
+ return ph->l2->fn.open(ph);
+}
+
+int
+rfid_layer2_transcieve(struct rfid_layer2_handle *ph,
+ enum rfid_frametype frametype,
+ const unsigned char *tx_buf, unsigned int len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags)
+{
+ return ph->l2->fn.transcieve(ph, frametype, tx_buf, len, rx_buf,
+ rx_len, timeout, flags);
+}
+
+int rfid_layer2_fini(struct rfid_layer2_handle *ph)
+{
+ return ph->l2->fn.fini(ph);
+}
+
+int
+rfid_layer2_close(struct rfid_layer2_handle *ph)
+{
+ return ph->l2->fn.close(ph);
+}
+
+int
+rfid_layer2_register(struct rfid_layer2 *p)
+{
+ p->next = rfid_layer2_list;
+ rfid_layer2_list = p;
+
+ return 0;
+}
diff --git a/src/rfid_layer2_iso14443a.c b/src/rfid_layer2_iso14443a.c
new file mode 100644
index 0000000..d93f917
--- /dev/null
+++ b/src/rfid_layer2_iso14443a.c
@@ -0,0 +1,294 @@
+/* ISO 14443-3 A anticollision implementation
+ *
+ * (C) 2005 by 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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_reader.h>
+#include <rfid/rfid_layer2_iso14443a.h>
+
+#define TIMEOUT 1236
+
+/* Transcieve a 7-bit short frame */
+static int
+iso14443a_transcieve_sf(struct rfid_layer2_handle *handle,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa)
+{
+ struct rfid_reader *rdr = handle->rh->reader;
+
+ return rdr->iso14443a.transcieve_sf(handle->rh, cmd, atqa);
+}
+
+/* Transmit an anticollission bit frame */
+static int
+iso14443a_transcieve_acf(struct rfid_layer2_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col)
+{
+ struct rfid_reader *rdr = handle->rh->reader;
+
+ return rdr->iso14443a.transcieve_acf(handle->rh, acf, bit_of_col);
+}
+
+/* Transmit a regular frame */
+static int
+iso14443a_transcieve(struct rfid_layer2_handle *handle,
+ enum rfid_frametype frametype,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags)
+{
+ return handle->rh->reader->transcieve(handle->rh, frametype, tx_buf,
+ tx_len, rx_buf, rx_len, timeout, flags);
+}
+
+static int
+iso14443a_code_nvb_bits(unsigned char *nvb, unsigned int bits)
+{
+ unsigned int byte_count = bits / 8;
+ unsigned int bit_count = bits % 8;
+
+ if (byte_count < 2 || byte_count > 7)
+ return -1;
+
+ *nvb = ((byte_count & 0xf) << 4) | bit_count;
+
+ return 0;
+}
+
+/* first bit is '1', second bit '2' */
+static void
+set_bit_in_field(unsigned char *bitfield, unsigned int bit)
+{
+ unsigned int byte_count = bit / 8;
+ unsigned int bit_count = bit % 8;
+
+ DEBUGP("bitfield=%p, byte_count=%u, bit_count=%u\n",
+ bitfield, byte_count, bit_count);
+ DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count));
+ *(bitfield+byte_count) |= 1 << (bit_count-1);
+ DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count));
+}
+
+static int
+iso14443a_anticol(struct rfid_layer2_handle *handle)
+{
+ int ret;
+ unsigned int uid_size;
+ struct iso14443a_handle *h = &handle->priv.iso14443a;
+ struct iso14443a_atqa atqa;
+ struct iso14443a_anticol_cmd acf;
+ unsigned int bit_of_col;
+ unsigned char sak[3];
+ unsigned int rx_len = sizeof(sak);
+ char *aqptr = (char *) &atqa;
+
+ memset(handle->uid, 0, sizeof(handle->uid));
+ memset(sak, 0, sizeof(sak));
+ memset(&atqa, 0, sizeof(atqa));
+ memset(&acf, 0, sizeof(acf));
+
+ ret = iso14443a_transcieve_sf(handle, ISO14443A_SF_CMD_REQA, &atqa);
+ if (ret < 0) {
+ h->state = ISO14443A_STATE_REQA_SENT;
+ DEBUGP("error during transcieve_sf: %d\n", ret);
+ return ret;
+ }
+ h->state = ISO14443A_STATE_ATQA_RCVD;
+
+ DEBUGP("ATQA: 0x%02x 0x%02x\n", *aqptr, *(aqptr+1));
+
+ if (!atqa.bf_anticol) {
+ h->state = ISO14443A_STATE_NO_BITFRAME_ANTICOL;
+ DEBUGP("no bitframe anticollission bits set, aborting\n");
+ return -1;
+ }
+
+ if (atqa.uid_size == 2 || atqa.uid_size == 3)
+ uid_size = 3;
+ else if (atqa.uid_size == 1)
+ uid_size = 2;
+ else
+ uid_size = 1;
+
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL1;
+
+ h->state = ISO14443A_STATE_ANTICOL_RUNNING;
+ h->level = ISO14443A_LEVEL_CL1;
+
+cascade:
+ iso14443a_code_nvb_bits(&acf.nvb, 16);
+
+ ret = iso14443a_transcieve_acf(handle, &acf, &bit_of_col);
+ if (ret < 0)
+ return ret;
+ DEBUGP("bit_of_col = %u\n", bit_of_col);
+
+ while (bit_of_col != ISO14443A_BITOFCOL_NONE) {
+ set_bit_in_field(&acf.uid_bits[0], bit_of_col-16);
+ iso14443a_code_nvb_bits(&acf.nvb, bit_of_col);
+ ret = iso14443a_transcieve_acf(handle, &acf, &bit_of_col);
+ DEBUGP("bit_of_col = %u\n", bit_of_col);
+ if (ret < 0)
+ return ret;
+ }
+
+ iso14443a_code_nvb_bits(&acf.nvb, 7*8);
+ ret = iso14443a_transcieve(handle, RFID_14443A_FRAME_REGULAR,
+ (unsigned char *)&acf, 7,
+ (unsigned char *) &sak, &rx_len,
+ TIMEOUT, 0);
+ if (ret < 0)
+ return ret;
+
+ if (sak[0] & 0x04) {
+ /* Cascade bit set, UID not complete */
+ switch (acf.sel_code) {
+ case ISO14443A_AC_SEL_CODE_CL1:
+ /* cascading from CL1 to CL2 */
+ if (acf.uid_bits[0] != 0x88) {
+ DEBUGP("Cascade bit set, but UID0 != 0x88\n");
+ return -1;
+ }
+ memcpy(&handle->uid[0], &acf.uid_bits[1], 3);
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL2;
+ h->level = ISO14443A_LEVEL_CL2;
+ break;
+ case ISO14443A_AC_SEL_CODE_CL2:
+ /* cascading from CL2 to CL3 */
+ memcpy(&handle->uid[3], &acf.uid_bits[1], 3);
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL3;
+ h->level = ISO14443A_LEVEL_CL3;
+ break;
+ default:
+ DEBUGP("cannot cascade any further than CL3\n");
+ h->state = ISO14443A_STATE_ERROR;
+ return -1;
+ break;
+ }
+ goto cascade;
+
+ } else {
+ switch (acf.sel_code) {
+ case ISO14443A_AC_SEL_CODE_CL1:
+ /* single size UID (4 bytes) */
+ memcpy(&handle->uid[0], &acf.uid_bits[0], 4);
+ break;
+ case ISO14443A_AC_SEL_CODE_CL2:
+ /* double size UID (7 bytes) */
+ memcpy(&handle->uid[3], &acf.uid_bits[0], 4);
+ break;
+ case ISO14443A_AC_SEL_CODE_CL3:
+ /* triple size UID (10 bytes) */
+ memcpy(&handle->uid[6], &acf.uid_bits[0], 4);
+ break;
+ }
+ }
+
+ h->level = ISO14443A_LEVEL_NONE;
+ h->state = ISO14443A_STATE_SELECTED;
+
+ {
+ if (uid_size == 1)
+ handle->uid_len = 4;
+ else if (uid_size == 2)
+ handle->uid_len = 7;
+ else
+ handle->uid_len = 10;
+
+ DEBUGP("UID %s\n", rfid_hexdump(handle->uid, handle->uid_len));
+ }
+
+ if (sak[0] & 0x20) {
+ DEBUGP("we have a T=CL compliant PICC\n");
+ h->tcl_capable = 1;
+ } else {
+ DEBUGP("we have a T!=CL PICC\n");
+ h->tcl_capable = 0;
+ }
+
+ return 0;
+}
+
+static int
+iso14443a_hlta(struct rfid_layer2_handle *handle)
+{
+ int ret;
+ unsigned char tx_buf[2] = { 0x50, 0x00 };
+ unsigned char rx_buf[10];
+ unsigned int rx_len = sizeof(rx_buf);
+
+ ret = iso14443a_transcieve(handle, RFID_14443A_FRAME_REGULAR,
+ tx_buf, sizeof(tx_buf),
+ rx_buf, &rx_len, 1000 /* 1ms */, 0);
+ if (ret < 0) {
+ /* "error" case: we don't get somethng back from the card */
+ return 0;
+ }
+ return -1;
+}
+
+static struct rfid_layer2_handle *
+iso14443a_init(struct rfid_reader_handle *rh)
+{
+ int ret;
+ struct rfid_layer2_handle *h = malloc(sizeof(*h));
+ if (!h)
+ return NULL;
+
+ h->l2 = &rfid_layer2_iso14443a;
+ h->rh = rh;
+ h->priv.iso14443a.state = ISO14443A_STATE_NONE;
+ h->priv.iso14443a.level = ISO14443A_LEVEL_NONE;
+
+ ret = h->rh->reader->iso14443a.init(h->rh);
+ if (ret < 0) {
+ free(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+static int
+iso14443a_fini(struct rfid_layer2_handle *handle)
+{
+ free(handle);
+ return 0;
+}
+
+
+struct rfid_layer2 rfid_layer2_iso14443a = {
+ .id = RFID_LAYER2_ISO14443A,
+ .name = "ISO 14443-3 A",
+ .fn = {
+ .init = &iso14443a_init,
+ .open = &iso14443a_anticol,
+ .transcieve = &iso14443a_transcieve,
+ .close = &iso14443a_hlta,
+ .fini = &iso14443a_fini,
+ },
+};
+
diff --git a/src/rfid_layer2_iso14443b.c b/src/rfid_layer2_iso14443b.c
new file mode 100644
index 0000000..f874071
--- /dev/null
+++ b/src/rfid_layer2_iso14443b.c
@@ -0,0 +1,344 @@
+/* ISO 14443-3 B anticollision implementation
+ *
+ * (C) 2005 by 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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_reader.h>
+#include <rfid/rfid_layer2_iso14443b.h>
+
+#include "rfid_iso14443_common.h"
+
+#define ATQB_TIMEOUT ((256*10e6/ISO14443_FREQ_SUBCARRIER) \
+ +(200*10e6/ISO14443_FREQ_SUBCARRIER))
+
+static inline int
+fwi_to_fwt(struct rfid_layer2_handle *h, unsigned int *fwt, unsigned int fwi)
+{
+ unsigned int multiplier, tmp;
+
+ /* 15 is RFU */
+ if (fwi > 14)
+ return -1;
+
+ /* According to ISO 14443-3:200(E), Chapter 7.9.4.3, the forumala is
+ * (256 * 16 / fC) * 2^fwi We avoid floating point computations by
+ * shifting everything into the microsecond range. In integer
+ * calculations 1000000*256*16/13560000 evaluates to 302 (instead of
+ * 302.064897), which provides sufficient precision, IMHO. The max
+ * result is 302 * 16384 (4947968), which fits well within the 31/32
+ * bit range of an integer */
+
+ multiplier = 1 << fwi; /* 2 to the power of fwi */
+
+ tmp = (unsigned int) 1000000 * 256 * 16;
+
+ return (tmp / h->rh->ah->asic->fc) * multiplier;
+}
+
+static int
+parse_atqb(struct rfid_layer2_handle *h, struct iso14443b_atqb *atqb)
+{
+ int ret;
+
+ if (atqb->fifty != 0x50)
+ return -1;
+
+ if (atqb->protocol_info.fo & 0x01)
+ h->priv.iso14443b.flags |= ISO14443B_CID_SUPPORTED;
+ if (atqb->protocol_info.fo & 0x02)
+ h->priv.iso14443b.flags |= ISO14443B_NAD_SUPPORTED;
+
+ ret = fwi_to_fwt(h, &h->priv.iso14443b.fwt, atqb->protocol_info.fwi);
+ if (ret < 0) {
+ DEBUGP("invalid fwi %u\n", atqb->protocol_info.fwi);
+ return ret;
+ }
+
+ if (atqb->protocol_info.protocol_type == 0x1) {
+ DEBUGP("we have a T=CL compliant PICC\n");
+ h->priv.iso14443b.tcl_capable = 1;
+ } else {
+ DEBUGP("we have a T!=CL PICC\n");
+ h->priv.iso14443b.tcl_capable = 0;
+ }
+
+ iso14443_fsdi_to_fsd(&h->priv.iso14443b.fsc,
+ atqb->protocol_info.max_frame_size);
+
+ /* FIXME: speed capability */
+
+ memcpy(h->uid, atqb->pupi, sizeof(atqb->pupi));
+ h->uid_len = sizeof(atqb->pupi);
+
+ return 0;
+}
+
+static int
+send_reqb(struct rfid_layer2_handle *h, unsigned char afi,
+ unsigned int is_wup, unsigned int num_initial_slots)
+{
+ int ret;
+ unsigned char reqb[3];
+ struct iso14443b_atqb atqb;
+ unsigned int atqb_len = sizeof(atqb);
+ unsigned int num_slot_idx = num_initial_slots;
+
+ reqb[0] = 0x05;
+ reqb[1] = afi;
+
+ for (num_slot_idx = num_initial_slots; num_slot_idx <= 4;
+ num_slot_idx++) {
+ reqb[2] = num_slot_idx & 0x07;
+ if (is_wup)
+ reqb[2] |= 0x08;
+
+ ret = h->rh->reader->transcieve(h->rh, RFID_14443B_FRAME_REGULAR,
+ reqb, sizeof(reqb),
+ (unsigned char *)&atqb,
+ &atqb_len, ATQB_TIMEOUT, 0);
+ h->priv.iso14443b.state = ISO14443B_STATE_REQB_SENT;
+ if (ret < 0) {
+ DEBUGP("error during transcieve of REQB/WUBP\n");
+ continue;
+ }
+
+ /* FIXME: send N-1 slot marker frames */
+
+ if (atqb_len != sizeof(atqb)) {
+ DEBUGP("error: atqb_len = %u instead of %Zu\n",
+ atqb_len, sizeof(atqb));
+ continue;
+ }
+
+ /* FIXME: how to detect a collission at 14443B ? I guess we
+ * can only rely on the CRC checking (CRCErr in ErrorFlag
+ * register?) */
+
+ if (parse_atqb(h, &atqb) >= 0) {
+ h->priv.iso14443b.state = ISO14443B_STATE_ATQB_RCVD;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static inline unsigned int mbli_to_mbl(struct rfid_layer2_handle *h,
+ unsigned int mbli)
+{
+ return (h->priv.iso14443b.fsc * 2 ^ (mbli-1));
+}
+
+static int
+transcieve_attrib(struct rfid_layer2_handle *h, const unsigned char *inf,
+ unsigned int inf_len, unsigned char *rx_data, unsigned int *rx_len)
+{
+ struct iso14443b_attrib_hdr *attrib;
+ unsigned int attrib_size = sizeof(*attrib) + inf_len;
+ unsigned char *rx_buf;
+ unsigned char fsdi;
+ int ret = 0;
+
+ DEBUGP("fsd is %u\n", h->priv.iso14443b.fsd);
+ attrib = malloc(attrib_size);
+ if (!attrib) {
+ perror("attrib_alloc");
+ return -1;
+ }
+
+ DEBUGP("fsd is %u\n", h->priv.iso14443b.fsd);
+ rx_buf = malloc(*rx_len+1);
+ if (!rx_buf) {
+ perror("rx_buf malloc");
+ ret = -1;
+ goto out_attrib;
+ }
+
+ /* initialize attrib frame */
+ memset(attrib, 0, attrib_size);
+ if (inf_len)
+ memcpy((unsigned char *)attrib+sizeof(*attrib), inf, inf_len);
+
+ attrib->one_d = 0x1d;
+ memcpy(attrib->identifier, h->uid, 4);
+
+ /* FIXME: do we want to change TR0/TR1 from its default ? */
+ /* FIXME: do we want to change SOF/EOF from its default ? */
+
+ ret = iso14443_fsd_to_fsdi(&fsdi, h->priv.iso14443b.fsd);
+ if (ret < 0) {
+ DEBUGP("unable to map FSD(%u) to FSDI\n",
+ h->priv.iso14443b.fsd);
+ goto out_rx;
+ }
+ attrib->param2.fsdi = fsdi;
+
+ /* FIXME: spd_in / spd_out */
+ if (h->priv.iso14443b.tcl_capable == 1)
+ attrib->param3.protocol_type = 0x1;
+
+ *rx_len = *rx_len + 1;
+ ret = h->rh->reader->transcieve(h->rh, RFID_14443B_FRAME_REGULAR,
+ (unsigned char *) attrib,
+ sizeof(*attrib)+inf_len,
+ rx_buf, rx_len, h->priv.iso14443b.fwt,
+ 0);
+ h->priv.iso14443b.state = ISO14443B_STATE_ATTRIB_SENT;
+ if (ret < 0) {
+ DEBUGP("transcieve problem\n");
+ goto out_rx;
+ }
+
+ if ((rx_buf[0] & 0x0f) != h->priv.iso14443b.cid) {
+ DEBUGP("ATTRIB response with invalid CID %u\n",
+ rx_buf[0] & 0x0f);
+ ret = -1;
+ goto out_rx;
+ }
+
+ h->priv.iso14443b.state = ISO14443B_STATE_SELECTED;
+
+ h->priv.iso14443b.mbl = mbli_to_mbl(h, (rx_data[0] & 0xf0) >> 4);
+
+ *rx_len = *rx_len - 1;
+ memcpy(rx_data, rx_buf+1, *rx_len);
+
+out_rx:
+ free(rx_buf);
+out_attrib:
+ free(attrib);
+
+ return ret;
+}
+
+static int
+iso14443b_hltb(struct rfid_layer2_handle *h)
+{
+ int ret;
+ unsigned char hltb[5];
+ unsigned char hltb_resp[1];
+ unsigned int hltb_len = 1;
+
+ hltb[0] = 0x50;
+ memcpy(hltb+1, h->uid, 4);
+
+ ret = h->rh->reader->transcieve(h->rh, RFID_14443B_FRAME_REGULAR,
+ hltb, 5,
+ hltb_resp, &hltb_len,
+ h->priv.iso14443b.fwt, 0);
+ h->priv.iso14443b.state = ISO14443B_STATE_HLTB_SENT;
+ if (ret < 0) {
+ DEBUGP("transcieve problem\n");
+ return ret;
+ }
+
+ if (hltb_len != 1 || hltb_resp[0] != 0x00) {
+ DEBUGP("bad HLTB response\n");
+ return -1;
+ }
+ h->priv.iso14443b.state = ISO14443B_STATE_HALTED;
+
+ return 0;
+}
+
+static int
+iso14443b_anticol(struct rfid_layer2_handle *handle)
+{
+ unsigned char afi = 0; /* FIXME */
+ int ret;
+ unsigned char buf[255];
+ unsigned int buf_len = sizeof(buf);
+
+ ret = send_reqb(handle, afi, 0, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = transcieve_attrib(handle, NULL, 0, buf, &buf_len);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct rfid_layer2_handle *
+iso14443b_init(struct rfid_reader_handle *rh)
+{
+ int ret;
+ struct rfid_layer2_handle *h = malloc(sizeof(*h));
+ if (!h)
+ return NULL;
+
+ h->l2 = &rfid_layer2_iso14443b;
+ h->rh = rh;
+ h->priv.iso14443b.state = ISO14443B_STATE_NONE;
+
+ h->priv.iso14443b.fsd = iso14443_fsd_approx(rh->ah->mru);
+ DEBUGP("fsd is %u\n", h->priv.iso14443b.fsd);
+
+ /* 14443-3 Section 7.1.6 */
+ h->priv.iso14443b.tr0 = (256/ISO14443_FREQ_SUBCARRIER)*10e6;
+ h->priv.iso14443b.tr1 = (200/ISO14443_FREQ_SUBCARRIER)*10e6;
+
+ ret = h->rh->reader->iso14443b.init(h->rh);
+ if (ret < 0) {
+ DEBUGP("error during reader 14443b init\n");
+ free(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+static int
+iso14443b_fini(struct rfid_layer2_handle *handle)
+{
+ free(handle);
+ return 0;
+}
+
+static int
+iso14443b_transcieve(struct rfid_layer2_handle *handle,
+ enum rfid_frametype frametype,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags)
+{
+ DEBUGP("transcieving %u bytes, expecting max %u\n", tx_len, *rx_len);
+ return handle->rh->reader->transcieve(handle->rh, frametype,
+ tx_buf, tx_len,
+ rx_buf, rx_len, timeout, flags);
+}
+
+struct rfid_layer2 rfid_layer2_iso14443b = {
+ .id = RFID_LAYER2_ISO14443B,
+ .name = "ISO 14443-3 B",
+ .fn = {
+ .init = &iso14443b_init,
+ .open = &iso14443b_anticol,
+ .transcieve = &iso14443b_transcieve,
+ .close = &iso14443b_hltb,
+ .fini = &iso14443b_fini,
+ },
+};
diff --git a/src/rfid_layer2_iso15693.c b/src/rfid_layer2_iso15693.c
new file mode 100644
index 0000000..15ff18a
--- /dev/null
+++ b/src/rfid_layer2_iso15693.c
@@ -0,0 +1,302 @@
+/* ISO 15693 anticollision implementation
+ *
+ * (C) 2005 by 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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_reader.h>
+#include <rfid/rfid_layer2_iso15693.h>
+
+#if 0
+/* Transcieve a 7-bit short frame */
+static int
+iso14443a_transcieve_sf(struct rfid_layer2_handle *handle,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa)
+{
+ struct rfid_reader *rdr = handle->rh->reader;
+
+ return rdr->iso14443a.transcieve_sf(handle->rh, cmd, atqa);
+}
+
+/* Transmit an anticollission bit frame */
+static int
+iso14443a_transcieve_acf(struct rfid_layer2_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col)
+{
+ struct rfid_reader *rdr = handle->rh->reader;
+
+ return rdr->iso14443a.transcieve_acf(handle->rh, acf, bit_of_col);
+}
+
+/* Transmit a regular frame */
+static int
+iso14443a_transcieve(struct rfid_layer2_handle *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ u_int64_t, unsigned int flags)
+{
+ return handle->rh->reader->transcieve(handle->rh, tx_buf, tx_len,
+ rx_buf, rx_len, timeout, flags);
+}
+
+static int
+iso14443a_code_nvb_bits(unsigned char *nvb, unsigned int bits)
+{
+ unsigned int byte_count = bits / 8;
+ unsigned int bit_count = bits % 8;
+
+ if (byte_count < 2 || byte_count > 7)
+ return -1;
+
+ *nvb = ((byte_count & 0xf) << 4) | bit_count;
+
+ return 0;
+}
+
+/* first bit is '1', second bit '2' */
+static void
+set_bit_in_field(unsigned char *bitfield, unsigned int bit)
+{
+ unsigned int byte_count = bit / 8;
+ unsigned int bit_count = bit % 8;
+
+ DEBUGP("bitfield=%p, byte_count=%u, bit_count=%u\n",
+ bitfield, byte_count, bit_count);
+ DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count));
+ *(bitfield+byte_count) |= 1 << (bit_count-1);
+ DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count));
+}
+
+static int
+iso14443a_anticol(struct rfid_layer2_handle *handle)
+{
+ int ret;
+ unsigned int uid_size;
+ struct iso14443a_atqa atqa;
+ struct iso14443a_anticol_cmd acf;
+ unsigned int bit_of_col;
+ unsigned char sak[3];
+ unsigned char uid[10]; // triple size equals 10 bytes;
+ unsigned int rx_len = sizeof(sak);
+ char *aqptr = (char *) &atqa;
+ static int first = 0;
+
+ memset(uid, 0, sizeof(uid));
+ memset(sak, 0, sizeof(sak));
+ memset(&atqa, 0, sizeof(atqa));
+ memset(&acf, 0, sizeof(acf));
+
+ if (first == 0) {
+ DEBUGP("Sending REQA\n");
+ ret = iso14443a_transcieve_sf(handle, ISO14443A_SF_CMD_REQA, &atqa);
+ first = 1;
+ } else {
+ DEBUGP("Sending WUPA\n");
+ ret = iso14443a_transcieve_sf(handle, ISO14443A_SF_CMD_WUPA, &atqa);
+ }
+
+ if (ret < 0) {
+ handle->priv.iso14443a.state = ISO14443A_STATE_REQA_SENT;
+ DEBUGP("error during transcieve_sf: %d\n", ret);
+ return ret;
+ }
+ handle->priv.iso14443a.state = ISO14443A_STATE_ATQA_RCVD;
+
+ DEBUGP("ATQA: 0x%02x 0x%02x\n", *aqptr, *(aqptr+1));
+
+ if (!atqa.bf_anticol) {
+ handle->priv.iso14443a.state =ISO14443A_STATE_NO_BITFRAME_ANTICOL;
+ DEBUGP("no bitframe anticollission bits set, aborting\n");
+ return -1;
+ }
+
+ if (atqa.uid_size == 2 || atqa.uid_size == 3)
+ uid_size = 3;
+ else if (atqa.uid_size == 1)
+ uid_size = 2;
+ else
+ uid_size = 1;
+
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL1;
+
+ handle->priv.iso14443a.state = ISO14443A_STATE_ANTICOL_RUNNING;
+ handle->priv.iso14443a.level = ISO14443A_LEVEL_CL1;
+
+cascade:
+ iso14443a_code_nvb_bits(&acf.nvb, 16);
+
+ ret = iso14443a_transcieve_acf(handle, &acf, &bit_of_col);
+ if (ret < 0)
+ return ret;
+ DEBUGP("bit_of_col = %u\n", bit_of_col);
+
+ while (bit_of_col != ISO14443A_BITOFCOL_NONE) {
+ set_bit_in_field(&acf.uid_bits[0], bit_of_col-16);
+ iso14443a_code_nvb_bits(&acf.nvb, bit_of_col);
+ ret = iso14443a_transcieve_acf(handle, &acf, &bit_of_col);
+ DEBUGP("bit_of_col = %u\n", bit_of_col);
+ if (ret < 0)
+ return ret;
+ }
+
+ iso14443a_code_nvb_bits(&acf.nvb, 7*8);
+ ret = iso14443a_transcieve(handle, (unsigned char *)&acf, 7,
+ (unsigned char *) &sak, &rx_len,
+ TIMEOUT, 0);
+ if (ret < 0)
+ return ret;
+
+ if (sak[0] & 0x04) {
+ /* Cascade bit set, UID not complete */
+ switch (acf.sel_code) {
+ case ISO14443A_AC_SEL_CODE_CL1:
+ /* cascading from CL1 to CL2 */
+ if (acf.uid_bits[0] != 0x88) {
+ DEBUGP("Cascade bit set, but UID0 != 0x88\n");
+ return -1;
+ }
+ memcpy(&uid[0], &acf.uid_bits[1], 3);
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL2;
+ handle->priv.iso14443a.level = ISO14443A_LEVEL_CL2;
+ break;
+ case ISO14443A_AC_SEL_CODE_CL2:
+ /* cascading from CL2 to CL3 */
+ memcpy(&uid[3], &acf.uid_bits[1], 3);
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL3;
+ handle->priv.iso14443a.level = ISO14443A_LEVEL_CL3;
+ break;
+ default:
+ DEBUGP("cannot cascade any further than CL3\n");
+ handle->priv.iso14443a.state = ISO14443A_STATE_ERROR;
+ return -1;
+ break;
+ }
+ goto cascade;
+
+ } else {
+ switch (acf.sel_code) {
+ case ISO14443A_AC_SEL_CODE_CL1:
+ /* single size UID (4 bytes) */
+ memcpy(&uid[0], &acf.uid_bits[0], 4);
+ break;
+ case ISO14443A_AC_SEL_CODE_CL2:
+ /* double size UID (7 bytes) */
+ memcpy(&uid[3], &acf.uid_bits[0], 4);
+ break;
+ case ISO14443A_AC_SEL_CODE_CL3:
+ /* triple size UID (10 bytes) */
+ memcpy(&uid[6], &acf.uid_bits[0], 4);
+ break;
+ }
+ }
+
+ handle->priv.iso14443a.level = ISO14443A_LEVEL_NONE;
+ handle->priv.iso14443a.state = ISO14443A_STATE_SELECTED;
+
+ {
+ int uid_len;
+ if (uid_size == 1)
+ uid_len = 4;
+ else if (uid_size == 2)
+ uid_len = 7;
+ else
+ uid_len = 10;
+
+ DEBUGP("UID %s\n", rfid_hexdump(uid, uid_len));
+ }
+
+ if (sak[0] & 0x20) {
+ DEBUGP("we have a T=CL compliant PICC\n");
+ handle->priv.iso14443a.tcl_capable = 1;
+ } else {
+ DEBUGP("we have a T!=CL PICC\n");
+ handle->priv.iso14443a.tcl_capable = 0;
+ }
+
+ return 0;
+}
+
+static int
+iso14443a_hlta(struct rfid_layer2_handle *handle)
+{
+ int ret;
+ unsigned char tx_buf[2] = { 0x50, 0x00 };
+ unsigned char rx_buf[10];
+ unsigned int rx_len = sizeof(rx_buf);
+
+ return 0;
+
+ ret = iso14443a_transcieve(handle, tx_buf, sizeof(tx_buf),
+ rx_buf, &rx_len, 1000 /* 1ms */, 0);
+ if (ret < 0) {
+ /* "error" case: we don't get somethng back from the card */
+ return 0;
+ }
+ return -1;
+}
+#endif
+
+static struct rfid_layer2_handle *
+iso15693_init(struct rfid_reader_handle *rh)
+{
+ int ret;
+ struct rfid_layer2_handle *h = malloc(sizeof(*h));
+ if (!h)
+ return NULL;
+
+ h->l2 = &rfid_layer2_iso15693;
+ h->rh = rh;
+ h->priv.iso15693.state = ISO15693_STATE_NONE;
+
+ ret = h->rh->reader->iso15693.init(h->rh);
+ if (ret < 0) {
+ free(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+static int
+iso15693_fini(struct rfid_layer2_handle *handle)
+{
+ free(handle);
+ return 0;
+}
+
+
+struct rfid_layer2 rfid_layer2_iso15693 = {
+ .id = RFID_LAYER2_ISO15693,
+ .name = "ISO 15693",
+ .fn = {
+ .init = &iso15693_init,
+ //.open = &iso15693_anticol,
+ //.transcieve = &iso15693_transcieve,
+ //.close = &iso14443a_hlta,
+ .fini = &iso15693_fini,
+ },
+};
+
diff --git a/src/rfid_proto_mifare_classic.c b/src/rfid_proto_mifare_classic.c
new file mode 100644
index 0000000..10de288
--- /dev/null
+++ b/src/rfid_proto_mifare_classic.c
@@ -0,0 +1,148 @@
+
+/* Mifare Classic implementation, PCD side.
+ *
+ * (C) 2005 by 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_protocol.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_protocol_mifare_classic.h>
+
+#include <rfid/rfid_reader.h>
+
+#include "rfid_iso14443_common.h"
+
+
+#define MIFARE_UL_CMD_WRITE 0xA2
+#define MIFARE_UL_CMD_READ 0x30
+
+/* FIXME */
+#define MIFARE_CL_READ_FWT 100
+#define MIFARE_CL_WRITE_FWT 100
+
+static int
+mfcl_read(struct rfid_protocol_handle *ph, unsigned int page,
+ unsigned char *rx_data, unsigned int *rx_len)
+{
+ unsigned char rx_buf[16];
+ unsigned int real_rx_len = sizeof(rx_buf);
+ unsigned char tx[2];
+ int ret;
+
+ if (page > MIFARE_CL_PAGE_MAX)
+ return -EINVAL;
+
+ tx[0] = MIFARE_CL_CMD_READ;
+ tx[1] = page & 0xff;
+
+ ret = ph->l2h->l2->fn.transcieve(ph->l2h, RFID_MIFARE_FRAME, tx,
+ sizeof(tx), rx_buf, &real_rx_len,
+ MIFARE_CL_READ_FWT, 0);
+
+ if (ret < 0)
+ return ret;
+
+ if (real_rx_len < *rx_len)
+ *rx_len = real_rx_len;
+
+ memcpy(rx_data, rx_buf, *rx_len);
+
+ return ret;
+}
+
+static int
+mfcl_write(struct rfid_protocol_handle *ph, unsigned int page,
+ unsigned char *tx_data, unsigned int tx_len)
+{
+ unsigned int i;
+ unsigned char tx[18];
+ unsigned char rx[1];
+ unsigned int rx_len;
+ int ret;
+
+ if (tx_len != 16 || page > MIFARE_CL_PAGE_MAX)
+ return -EINVAL;
+
+ tx[0] = MIFARE_CL_CMD_WRITE16;
+ tx[1] = page & 0xff;
+
+ memcpy(tx+2, tx_data, 16);
+
+ ret = ph->l2h->l2->fn.transcieve(ph->l2h, RFID_MIFARE_FRAME, tx,
+ sizeof(tx), rx, &rx_len,
+ MIFARE_CL_WRITE_FWT, 0);
+
+ if (ret < 0)
+ return ret;
+
+ if (rx[0] != MIFARE_UL_RESP_ACK)
+ return -EIO;
+
+ return ret;
+}
+
+static struct rfid_protocol_handle *
+mfcl_init(struct rfid_layer2_handle *l2h)
+{
+ struct rfid_protocol_handle *ph;
+ ph = malloc(sizeof(struct rfid_protocol_handle));
+ return ph;
+}
+
+static int mfcl_fini(struct rfid_protocol_handle *ph)
+{
+ free(ph);
+ return 0;
+}
+
+struct rfid_protocol rfid_protocol_mfcl = {
+ .id = RFID_PROTOCOL_MIFARE_CLASSIC,
+ .name = "Mifare Classic",
+ .fn = {
+ .init = &mfcl_init,
+ .read = &mfcl_read,
+ .write = &mfcl_write,
+ .fini = &mfcl_fini,
+ },
+};
+
+int mfcl_set_key(struct rfid_protocol_handle *ph, unsigned char *key)
+{
+ if (!ph->l2h->rh->reader->mifare_classic.setkey)
+ return -ENODEV;
+
+ return ph->l2h->rh->reader->mifare_classic.setkey(ph->l2h->rh, key);
+}
+
+int mfcl_auth(struct rfid_protocol_handle *ph, u_int8_t cmd, u_int8_t block)
+{
+ u_int32_t serno = *((u_int32_t *)ph->l2h->uid);
+
+ if (!ph->l2h->rh->reader->mifare_classic.auth)
+ return -ENODEV;
+
+ return ph->l2h->rh->reader->mifare_classic.auth(ph->l2h->rh, cmd,
+ serno, block);
+}
diff --git a/src/rfid_proto_mifare_ul.c b/src/rfid_proto_mifare_ul.c
new file mode 100644
index 0000000..9e5363f
--- /dev/null
+++ b/src/rfid_proto_mifare_ul.c
@@ -0,0 +1,162 @@
+
+/* Mifare Ultralight implementation, PCD side.
+ *
+ * (C) 2005 by 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_protocol.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_protocol_mifare_ul.h>
+
+#include "rfid_iso14443_common.h"
+
+
+/* FIXME */
+#define MIFARE_UL_READ_FWT 100
+#define MIFARE_UL_WRITE_FWT 100
+
+static int
+mful_read(struct rfid_protocol_handle *ph, unsigned int page,
+ unsigned char *rx_data, unsigned int *rx_len)
+{
+ unsigned char rx_buf[16];
+ unsigned int real_rx_len = sizeof(rx_buf);
+ unsigned char tx[2];
+ int ret;
+
+ if (page > MIFARE_UL_PAGE_MAX)
+ return -EINVAL;
+
+ tx[0] = MIFARE_UL_CMD_READ;
+ tx[1] = page & 0xff;
+
+ ret = ph->l2h->l2->fn.transcieve(ph->l2h, RFID_14443A_FRAME_REGULAR,
+ tx, sizeof(tx), rx_buf,
+ &real_rx_len, MIFARE_UL_READ_FWT, 0);
+
+ if (ret < 0)
+ return ret;
+
+ if (real_rx_len < *rx_len)
+ *rx_len = real_rx_len;
+
+ memcpy(rx_data, rx_buf, *rx_len);
+
+ return ret;
+}
+
+static int
+mful_write(struct rfid_protocol_handle *ph, unsigned int page,
+ unsigned char *tx_data, unsigned int tx_len)
+{
+ unsigned int i;
+ unsigned char tx[6];
+ unsigned char rx[10];
+ unsigned int rx_len = sizeof(rx);
+ int ret;
+
+ if (tx_len != 4 || page > MIFARE_UL_PAGE_MAX)
+ return -EINVAL;
+
+ tx[0] = MIFARE_UL_CMD_WRITE;
+ tx[1] = page & 0xff;
+
+ for (i = 0; i < 4; i++)
+ tx[2+i] = tx_data[i];
+
+ ret = ph->l2h->l2->fn.transcieve(ph->l2h, RFID_14443A_FRAME_REGULAR,
+ tx, sizeof(tx), rx, &rx_len,
+ MIFARE_UL_WRITE_FWT, 0);
+
+ if (ret < 0)
+ return ret;
+
+ if (rx[0] != MIFARE_UL_RESP_ACK)
+ return -EIO;
+
+ return ret;
+}
+
+static int
+mful_transcieve(struct rfid_protocol_handle *ph,
+ const unsigned char *tx_data, unsigned int tx_len,
+ unsigned char *rx_data, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ return -EINVAL;
+}
+
+static struct rfid_protocol_handle *
+mful_init(struct rfid_layer2_handle *l2h)
+{
+ struct rfid_protocol_handle *ph;
+ ph = malloc(sizeof(struct rfid_protocol_handle));
+ return ph;
+}
+
+static int mful_fini(struct rfid_protocol_handle *ph)
+{
+ free(ph);
+ return 0;
+}
+
+struct rfid_protocol rfid_protocol_mful = {
+ .id = RFID_PROTOCOL_MIFARE_UL,
+ .name = "Mifare Ultralight",
+ .fn = {
+ .init = &mful_init,
+ .read = &mful_read,
+ .write = &mful_write,
+ .fini = &mful_fini,
+ },
+};
+
+/* Functions below are not (yet? covered in the generic librfid api */
+
+
+/* lock a certain page */
+int rfid_mful_lock_page(struct rfid_protocol_handle *ph, unsigned int page)
+{
+ unsigned char buf[4] = { 0x00, 0x00, 0x00, 0x00 };
+
+ if (ph->proto != &rfid_protocol_mful)
+ return -EINVAL;
+
+ if (page < 3 || page > 15)
+ return -EINVAL;
+
+ if (page > 8)
+ buf[2] = (1 << page);
+ else
+ buf[3] = (1 << (page - 8));
+
+ return mful_write(ph, MIFARE_UL_PAGE_LOCK, buf, sizeof(buf));
+}
+
+/* convenience wrapper to lock the otp page */
+int rfid_mful_lock_otp(struct rfid_protocol_handle *ph)
+{
+ return rfid_mful_lock_page(ph, MIFARE_UL_PAGE_OTP);
+}
diff --git a/src/rfid_proto_tcl.c b/src/rfid_proto_tcl.c
new file mode 100644
index 0000000..f070614
--- /dev/null
+++ b/src/rfid_proto_tcl.c
@@ -0,0 +1,694 @@
+/* ISO 14443-4 (T=CL) implementation, PCD side.
+ *
+ * (C) 2005 by 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_protocol_tcl.h>
+#include <rfid/rfid_protocol.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_layer2_iso14443b.h>
+
+#include <rfid/rfid_asic.h>
+#include <rfid/rfid_reader.h>
+
+#include "rfid_iso14443_common.h"
+
+#if 1
+#ifdef DEBUGP
+#undef DEBUGP
+#define DEBUGP(x, ...)
+#define DEBUGPC(x, ...)
+#endif
+#endif
+
+static enum rfid_frametype l2_to_frame(unsigned int layer2)
+{
+ switch (layer2) {
+ case RFID_LAYER2_ISO14443A:
+ return RFID_14443A_FRAME_REGULAR;
+ break;
+ case RFID_LAYER2_ISO14443B:
+ return RFID_14443B_FRAME_REGULAR;
+ break;
+ }
+ return 0;
+}
+
+static unsigned int sfgi_to_sfgt(struct rfid_protocol_handle *h,
+ unsigned char sfgi)
+{
+ unsigned int multiplier;
+ unsigned int tmp;
+
+ if (sfgi > 14)
+ sfgi = 14;
+
+ multiplier = 1 << sfgi; /* 2 to the power of sfgi */
+
+ /* ISO 14443-4:2000(E) Section 5.2.5:
+ * (256 * 16 / h->l2h->rh->ah->fc) * (2 ^ sfgi) */
+ tmp = (unsigned int) 1000000 * 256 * 16;
+
+ return (tmp / h->l2h->rh->ah->fc) * multiplier;
+}
+
+static unsigned int fwi_to_fwt(struct rfid_protocol_handle *h,
+ unsigned char fwi)
+{
+ unsigned int multiplier, tmp;
+
+ if (fwi > 14)
+ fwi = 14;
+
+ multiplier = 1 << fwi; /* 2 to the power of fwi */
+
+ /* ISO 14443-4:2000(E) Section 7.2.:
+ * (256*16 / h->l2h->rh->ah->fc) * (2 ^ fwi) */
+
+ tmp = (unsigned int) 1000000 * 256 * 16;
+
+ return (tmp / h->l2h->rh->ah->fc) * multiplier;
+}
+
+/* 4.9seconds as microseconds (4.9 billion seconds) exceeds 2^32 */
+#define activation_fwt(x) (((u_int64_t)1000000 * 65536 / x->l2h->rh->ah->fc))
+#define deactivation_fwt(x) activation_fwt(x)
+
+static int
+tcl_parse_ats(struct rfid_protocol_handle *h,
+ unsigned char *ats, unsigned int size)
+{
+ unsigned char len = ats[0];
+ unsigned char t0;
+ unsigned char *cur;
+
+ if (len == 0 || size == 0)
+ return -1;
+
+ if (size < len)
+ len = size;
+
+ h->priv.tcl.ta = 0;
+
+ if (len == 1) {
+ /* FIXME: assume some default values */
+ h->priv.tcl.fsc = 32;
+ h->priv.tcl.ta = 0x80; /* 0x80 (same d for both dirs) */
+ h->priv.tcl.sfgt = sfgi_to_sfgt(h, 0);
+ if (h->l2h->l2->id == RFID_LAYER2_ISO14443A) {
+ /* Section 7.2: fwi default for type A is 4 */
+ h->priv.tcl.fwt = fwi_to_fwt(h, 4);
+ } else {
+ /* Section 7.2: fwi for type B is always in ATQB */
+ /* Value is assigned in tcl_connect() */
+ /* This function is never called for Type B, since it has no (R)ATS */
+ }
+ return 0;
+ }
+
+ /* guarateed to be at least 2 bytes in size */
+
+ t0 = ats[1];
+ cur = &ats[2];
+
+ iso14443_fsdi_to_fsd(&h->priv.tcl.fsc, t0 & 0x0f);
+
+ if (t0 & (1 << 4)) {
+ /* TA is transmitted */
+ h->priv.tcl.ta = *cur++;
+ }
+
+ if (t0 & (1 << 5)) {
+ /* TB is transmitted */
+ h->priv.tcl.sfgt = sfgi_to_sfgt(h, *cur & 0x0f);
+ h->priv.tcl.fwt = fwi_to_fwt(h, (*cur & 0xf0) >> 4);
+ cur++;
+ }
+
+ if (t0 & (1 << 6)) {
+ /* TC is transmitted */
+ if (*cur & 0x01)
+ h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED;
+ if (*cur & 0x02)
+ h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED;
+ cur++;
+ }
+
+ h->priv.tcl.historical_len = (ats+len) - cur;
+ h->priv.tcl.historical_bytes = cur;
+
+ return 0;
+}
+
+
+/* request an ATS from the PICC */
+static int
+tcl_request_ats(struct rfid_protocol_handle *h)
+{
+ int ret;
+ unsigned char rats[2];
+ unsigned char fsdi;
+
+ if (h->priv.tcl.state != TCL_STATE_INITIAL)
+ return -1;
+
+ ret = iso14443_fsd_to_fsdi(&fsdi, h->priv.tcl.fsd);
+ if (ret < 0) {
+ DEBUGP("unable to encode FSD of %u as FSDI\n", h->priv.tcl.fsd);
+ return ret;
+ }
+
+ rats[0] = 0xe0;
+ rats[1] = (h->priv.tcl.cid & 0x0f) | ((fsdi << 4) & 0xf0);
+
+ /* transcieve (with CRC) */
+ ret = h->l2h->l2->fn.transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
+ rats, 2, h->priv.tcl.ats,
+ &h->priv.tcl.ats_len, activation_fwt(h),
+ TCL_TRANSP_F_TX_CRC);
+ if (ret < 0) {
+ DEBUGP("transcieve of rats failed\n");
+ h->priv.tcl.state = TCL_STATE_RATS_SENT;
+ /* FIXME: retransmit */
+ return ret;
+ }
+ h->priv.tcl.state = TCL_STATE_ATS_RCVD;
+
+ ret = tcl_parse_ats(h, h->priv.tcl.ats, h->priv.tcl.ats_len);
+ if (ret < 0) {
+ DEBUGP("parsing of ats failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+#define ATS_TA_DIV_2 1
+#define ATS_TA_DIV_4 2
+#define ATS_TA_DIV_8 4
+
+#define PPS_DIV_8 3
+#define PPS_DIV_4 2
+#define PPS_DIV_2 1
+#define PPS_DIV_1 0
+static unsigned char d_to_di(struct rfid_protocol_handle *h, unsigned char D)
+{
+ static char DI;
+ unsigned int speed = h->l2h->rh->reader->iso14443a.speed;
+
+ if ((D & ATS_TA_DIV_8) && (speed & RFID_READER_SPEED_848K))
+ DI = PPS_DIV_8;
+ else if ((D & ATS_TA_DIV_4) && (speed & RFID_READER_SPEED_424K))
+ DI = PPS_DIV_4;
+ else if ((D & ATS_TA_DIV_2) && (speed & RFID_READER_SPEED_212K))
+ DI = PPS_DIV_2;
+ else
+ DI = PPS_DIV_1;
+
+ return DI;
+}
+
+
+/* start a PSS run (autimatically configure highest possible speed */
+static int
+tcl_do_pps(struct rfid_protocol_handle *h)
+{
+#if 0
+ int ret;
+ unsigned char ppss[3];
+ unsigned char pps_response[1];
+ unsigned int rx_len = 1;
+ unsigned char Dr, Ds, DrI, DsI;
+
+ if (h->priv.tcl.state != TCL_STATE_ATS_RCVD)
+ return -1;
+
+ Dr = h->priv.tcl.ta & 0x07;
+ Ds = h->priv.tcl.ta & 0x70 >> 4;
+
+ if (Dr != Ds && !(h->priv.tcl.ta & 0x80)) {
+ /* device supports different divisors for rx and tx, but not ?!? */
+ DEBUGP("PICC has contradictory TA, aborting PPS\n");
+ return -1;
+ };
+
+ /* ISO 14443-4:2000(E) Section 5.3. */
+
+ ppss[0] = 0xd0 & (h->priv.tcl.cid & 0x0f);
+ ppss[1] = 0x11;
+
+ /* FIXME: deal with different speed for each direction */
+ DrI = d_to_di(h, Dr);
+ DsI = d_to_di(h, Ds);
+
+ ppss[2] = (ppss[2] & 0xf0) | (DrI | DsI << 2);
+
+ ret = h->l2h->l2->fn.transcieve(h->l2h, ppss, 3, pps_response,
+ &rx_len, h->priv.tcl.fwt,
+ TCL_TRANSP_F_TX_CRC);
+ if (ret < 0)
+ return ret;
+
+ if (pps_response[0] != ppss[0]) {
+ DEBUGP("PPS Response != PPSS\n");
+ return -1;
+ }
+
+ h->priv.tcl.state = TCL_STATE_ESTABLISHED;
+#endif
+ return 0;
+}
+
+
+static int
+tcl_build_prologue2(struct tcl_handle *th,
+ unsigned char *prlg, unsigned int *prlg_len,
+ unsigned char pcb)
+{
+ *prlg_len = 1;
+
+ *prlg = pcb;
+
+ if (th->toggle) {
+ /* we've sent a toggle bit last time */
+ th->toggle = 0;
+ } else {
+ /* we've not sent a toggle last time: send one */
+ th->toggle = 1;
+ *prlg |= 0x01;
+ }
+
+ if (th->flags & TCL_HANDLE_F_CID_USED) {
+ /* ISO 14443-4:2000(E) Section 7.1.1.2 */
+ *prlg |= TCL_PCB_CID_FOLLOWING;
+ (*prlg_len)++;
+ prlg[*prlg_len] = th->cid & 0x0f;
+ }
+
+ /* nad only for I-block (0xc0 == 00) */
+ if ((th->flags & TCL_HANDLE_F_NAD_USED) &&
+ ((pcb & 0xc0) == 0x00)) {
+ /* ISO 14443-4:2000(E) Section 7.1.1.3 */
+ /* FIXME: in case of chaining only for first frame */
+ *prlg |= TCL_PCB_NAD_FOLLOWING;
+ prlg[*prlg_len] = th->nad;
+ (*prlg_len)++;
+ }
+
+ return 0;
+}
+
+static int
+tcl_build_prologue_i(struct tcl_handle *th,
+ unsigned char *prlg, unsigned int *prlg_len)
+{
+ /* ISO 14443-4:2000(E) Section 7.1.1.1 */
+ return tcl_build_prologue2(th, prlg, prlg_len, 0x02);
+}
+
+static int
+tcl_build_prologue_r(struct tcl_handle *th,
+ unsigned char *prlg, unsigned int *prlg_len,
+ unsigned int nak)
+{
+ unsigned char pcb = 0xa2;
+ /* ISO 14443-4:2000(E) Section 7.1.1.1 */
+
+ if (nak)
+ pcb |= 0x10;
+
+ return tcl_build_prologue2(th, prlg, prlg_len, pcb);
+}
+
+static int
+tcl_build_prologue_s(struct tcl_handle *th,
+ unsigned char *prlg, unsigned int *prlg_len)
+{
+ /* ISO 14443-4:2000(E) Section 7.1.1.1 */
+
+ /* the only S-block from PCD->PICC is DESELECT,
+ * well, actually there is the S(WTX) response. */
+ return tcl_build_prologue2(th, prlg, prlg_len, 0xc2);
+}
+
+/* FIXME: WTXM implementation */
+
+static int tcl_prlg_len(struct tcl_handle *th)
+{
+ int prlg_len = 1;
+
+ if (th->flags & TCL_HANDLE_F_CID_USED)
+ prlg_len++;
+
+ if (th->flags & TCL_HANDLE_F_NAD_USED)
+ prlg_len++;
+
+ return prlg_len;
+}
+
+#define max_net_tx_framesize(x) (x->fsc - tcl_prlg_len(x))
+
+static int
+tcl_connect(struct rfid_protocol_handle *h)
+{
+ int ret;
+
+ if (h->priv.tcl.state != TCL_STATE_DESELECTED &&
+ h->priv.tcl.state != TCL_STATE_INITIAL)
+ return -1;
+
+ switch (h->l2h->l2->id) {
+ case RFID_LAYER2_ISO14443A:
+ /* Start Type A T=CL Activation Sequence */
+ ret = tcl_request_ats(h);
+ if (ret < 0)
+ return ret;
+
+ /* Only do PPS if any non-default divisors supported */
+ if (h->priv.tcl.ta & 0x77) {
+ ret = tcl_do_pps(h);
+ if (ret < 0)
+ return ret;
+ }
+ break;
+ case RFID_LAYER2_ISO14443B:
+ /* initialized T=CL state from Type B Activation Data */
+ h->priv.tcl.cid = h->l2h->priv.iso14443b.cid;
+ h->priv.tcl.fsc = h->l2h->priv.iso14443b.fsc;
+ h->priv.tcl.fsd = h->l2h->priv.iso14443b.fsd;
+ h->priv.tcl.fwt = h->l2h->priv.iso14443b.fwt;
+
+ /* what about ta? sfgt? */
+
+ if (h->l2h->priv.iso14443b.flags & ISO14443B_CID_SUPPORTED)
+ h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED;
+ if (h->l2h->priv.iso14443b.flags & ISO14443B_NAD_SUPPORTED)
+ h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED;
+
+ switch (h->l2h->priv.iso14443b.state) {
+ case ISO14443B_STATE_SELECTED:
+ h->priv.tcl.state = TCL_STATE_ATS_RCVD;
+ break;
+ case ISO14443B_STATE_ATTRIB_SENT:
+ h->priv.tcl.state = TCL_STATE_RATS_SENT;
+ break;
+ }
+
+ /* PUPI will be presented as ATS/historical bytes */
+ memcpy(h->priv.tcl.ats, h->l2h->uid, 4);
+ h->priv.tcl.ats_len = 4;
+ h->priv.tcl.historical_bytes = h->priv.tcl.ats;
+
+ break;
+ default:
+ DEBUGP("unsupported l2: %u\n", h->l2h->l2->id);
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+static int
+tcl_deselect(struct rfid_protocol_handle *h)
+{
+ /* ISO 14443-4:2000(E) Section 8 */
+ int ret;
+ unsigned char frame[3]; /* 3 bytes prologue, no information */
+ unsigned char rx[3];
+ unsigned int rx_len = sizeof(rx);
+ unsigned int prlg_len;
+ struct tcl_handle *th = &h->priv.tcl;
+
+ if (th->state != TCL_STATE_ESTABLISHED) {
+ /* FIXME: not sure whether deselect is possible here,
+ * probably better send a HLTA? */
+ }
+
+ /* build DESELECT S-block */
+ ret = tcl_build_prologue_s(th, frame, &prlg_len);
+ if (ret < 0)
+ return ret;
+
+ ret = h->l2h->l2->fn.transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
+ frame, prlg_len, rx,
+ &rx_len, deactivation_fwt(h),
+ TCL_TRANSP_F_TX_CRC);
+ if (ret < 0) {
+ /* FIXME: retransmit, HLT(A|B) */
+ return ret;
+ }
+
+ th->state = TCL_STATE_DESELECTED;
+
+ return 0;
+}
+
+#define is_s_block(x) ((x & 0xc0) == 0xc0)
+#define is_r_block(x) ((x & 0xc0) == 0x80)
+#define is_i_block(x) ((x & 0xc0) == 0x00)
+
+static int
+tcl_transcieve(struct rfid_protocol_handle *h,
+ const unsigned char *tx_data, unsigned int tx_len,
+ unsigned char *rx_data, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ int ret;
+ unsigned char *tx_buf, *rx_buf;
+ unsigned char *_rx_data = rx_data;
+ unsigned int _rx_len;
+ unsigned int max_rx_len = *rx_len; /* maximum number of payoload that
+ caller has requested */
+ unsigned int prlg_len;
+ struct tcl_handle *th = &h->priv.tcl;
+
+ unsigned char *_tx;
+ unsigned int _tx_len, _timeout;
+ unsigned char wtx_resp[3];
+ unsigned char ack[10];
+ unsigned int ack_len;
+
+ if (tx_len > max_net_tx_framesize(th)) {
+ /* slow path: we need to use chaining */
+ return -1;
+ }
+
+ tx_buf = malloc(tcl_prlg_len(th) + tx_len);
+ if (!tx_buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ rx_buf = malloc(tcl_prlg_len(th) + *rx_len);
+ if (!rx_buf) {
+ ret = -ENOMEM;
+ goto out_txb;
+ }
+
+ if (tcl_build_prologue_i(th, tx_buf, &prlg_len) < 0) {
+ ret = -1;
+ goto out_rxb;
+ }
+ memcpy(tx_buf + prlg_len, tx_data, tx_len);
+
+ /* intialize to data-to-be-transferred */
+ _tx = tx_buf;
+ _tx_len = tx_len+prlg_len;
+ _timeout = th->fwt;
+ _rx_len = *rx_len;
+ *rx_len = 0;
+
+do_tx:
+ ret = h->l2h->l2->fn.transcieve(h->l2h, l2_to_frame(h->l2h->l2->id),
+ _tx, _tx_len,
+ rx_buf, &_rx_len, _timeout, 0);
+ DEBUGP("l2 transcieve finished\n");
+ if (ret < 0)
+ goto out_rxb;
+
+ if ((*rx_buf & 0x01) != h->priv.tcl.toggle) {
+ DEBUGP("response with wrong toggle bit\n");
+ goto out_rxb;
+ }
+
+ if (is_r_block(*rx_buf)) {
+ unsigned int txed = _tx - tx_buf;
+ DEBUGP("R-Block\n");
+ /* Handle ACK frame in case of chaining */
+ if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
+ if (*(rx_buf+1) != h->priv.tcl.cid) {
+ DEBUGP("CID %u is not valid\n", *(rx_buf)+1);
+ goto out_rxb;
+ }
+ }
+ /* set up parameters for next frame in chain */
+ if (txed < tx_len) {
+ /* move tx pointer by the amount of bytes transferred
+ * in last frame */
+ _tx += _tx_len;
+ _tx_len = (tx_len - txed);
+ if (_tx_len > max_net_tx_framesize(th)) {
+ /* not last frame in chain */
+ _tx_len = max_net_tx_framesize(th);
+ } else {
+ /* last frame in chain */
+ }
+ goto do_tx;
+ } else {
+ DEBUGP("Received ACK in response to last frame in "
+ "chain?!? Expected I-frame.\n");
+ ret = -1;
+ goto out_rxb;
+ }
+ } else if (is_s_block(*rx_buf)) {
+ unsigned char inf;
+ unsigned int prlg_len;
+
+ DEBUGP("S-Block\n");
+ /* Handle Wait Time Extension */
+ if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
+ if (_rx_len < 3) {
+ DEBUGP("S-Block with CID but short len\n");
+ ret = -1;
+ goto out_rxb;
+ }
+ if (*(rx_buf+1) != h->priv.tcl.cid) {
+ DEBUGP("CID %u is not valid\n", *(rx_buf)+1);
+ goto out_rxb;
+ }
+ inf = *(rx_buf+2);
+ } else
+ inf = *(rx_buf+1);
+
+ if ((*rx_buf & 0x30) != 0x30) {
+ DEBUGP("S-Block but not WTX?\n");
+ ret = -1;
+ goto out_rxb;
+ }
+ inf &= 0x3f; /* only lower 6 bits code WTXM */
+ if (inf == 0 || (inf >= 60 && inf <= 63)) {
+ DEBUGP("WTXM %u is RFU!\n", inf);
+ ret = -1;
+ goto out_rxb;
+ }
+
+ /* Acknowledge WTXM */
+ tcl_build_prologue_s(&h->priv.tcl, wtx_resp, &prlg_len);
+ /* set two bits that make this block a wtx */
+ wtx_resp[0] |= 0x30;
+ wtx_resp[prlg_len] = inf;
+ _tx = wtx_resp;
+ _tx_len = prlg_len+1;
+ _timeout = th->fwt * inf;
+
+ /* start over with next transcieve */
+ goto do_tx; /* FIXME: do transcieve locally since we use
+ totally different buffer */
+
+ } else if (is_i_block(*rx_buf)) {
+ unsigned char *inf = rx_buf+1;
+ unsigned int net_payload_len;
+ /* we're actually receiving payload data */
+
+ DEBUGP("I-Block: ");
+ if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
+ if (*(rx_buf+1) != h->priv.tcl.cid) {
+ DEBUGPC("CID %u is not valid\n", *(rx_buf)+1);
+ goto out_rxb;
+ }
+ inf++;
+ }
+ if (*rx_buf & TCL_PCB_NAD_FOLLOWING) {
+ inf++;
+ }
+ net_payload_len = _rx_len - (inf - rx_buf);
+ DEBUGPC("%u bytes\n", net_payload_len);
+ memcpy(_rx_data, inf, net_payload_len);
+ /* increment the number of payload bytes that we actually received */
+ *rx_len += net_payload_len;
+ _rx_data += net_payload_len;
+
+ if (*rx_buf & 0x10) {
+ /* we're not the last frame in the chain, continue rx */
+ DEBUGP("we're not the last frame in the chain, continue\n");
+ ack_len = sizeof(ack);
+ tcl_build_prologue_r(&h->priv.tcl, ack, &ack_len, 0);
+ _tx = ack;
+ _tx_len = ack_len;
+ goto do_tx;
+ }
+ }
+
+out_rxb:
+ free(rx_buf);
+out_txb:
+ free(tx_buf);
+out:
+ return ret;
+}
+
+static struct rfid_protocol_handle *
+tcl_init(struct rfid_layer2_handle *l2h)
+{
+ struct rfid_protocol_handle *th;
+ unsigned int mru = l2h->rh->ah->mru;
+
+ th = malloc(sizeof(struct rfid_protocol_handle) + mru);
+ if (!th)
+ return NULL;
+
+ /* FIXME: mru should be attribute of layer2 (in case it adds/removes
+ * some overhead */
+ memset(th, 0, sizeof(struct rfid_protocol_handle) + mru);
+
+ /* maximum received ats length equals mru of asic/reader */
+ th->priv.tcl.state = TCL_STATE_INITIAL;
+ th->priv.tcl.ats_len = mru;
+ th->priv.tcl.toggle = 1;
+
+ th->priv.tcl.fsd = iso14443_fsd_approx(mru);
+
+ return th;
+}
+
+static int
+tcl_fini(struct rfid_protocol_handle *ph)
+{
+ free(ph);
+ return 0;
+}
+
+struct rfid_protocol rfid_protocol_tcl = {
+ .id = RFID_PROTOCOL_TCL,
+ .name = "ISO 14443-4 / T=CL",
+ .fn = {
+ .init = &tcl_init,
+ .open = &tcl_connect,
+ .transcieve = &tcl_transcieve,
+ .close = &tcl_deselect,
+ .fini = &tcl_fini,
+ },
+};
diff --git a/src/rfid_protocol.c b/src/rfid_protocol.c
new file mode 100644
index 0000000..abbd04d
--- /dev/null
+++ b/src/rfid_protocol.c
@@ -0,0 +1,113 @@
+/* librfid - layer 3 protocol handler
+ * (C) 2005 by 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 <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_protocol.h>
+
+static struct rfid_protocol *rfid_protocol_list;
+
+struct rfid_protocol_handle *
+rfid_protocol_init(struct rfid_layer2_handle *l2h, unsigned int id)
+{
+ struct rfid_protocol *p;
+ struct rfid_protocol_handle *ph = NULL;
+
+ for (p = rfid_protocol_list; p; p = p->next) {
+ if (p->id == id) {
+ ph = p->fn.init(l2h);
+ break;
+ }
+ }
+
+ if (!ph)
+ return NULL;
+
+ ph->proto = p;
+ ph->l2h = l2h;
+
+ return ph;
+}
+
+int
+rfid_protocol_open(struct rfid_protocol_handle *ph)
+{
+ if (ph->proto->fn.open)
+ return ph->proto->fn.open(ph);
+ return 0;
+}
+
+int
+rfid_protocol_transcieve(struct rfid_protocol_handle *ph,
+ const unsigned char *tx_buf, unsigned int len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ return ph->proto->fn.transcieve(ph, tx_buf, len, rx_buf, rx_len,
+ timeout, flags);
+}
+
+int
+rfid_protocol_read(struct rfid_protocol_handle *ph,
+ unsigned int page,
+ unsigned char *rx_data,
+ unsigned int *rx_len)
+{
+ if (ph->proto->fn.read)
+ return ph->proto->fn.read(ph, page, rx_data, rx_len);
+ else
+ return -EINVAL;
+}
+
+int
+rfid_protocol_write(struct rfid_protocol_handle *ph,
+ unsigned int page,
+ unsigned char *tx_data,
+ unsigned int tx_len)
+{
+ if (ph->proto->fn.write)
+ return ph->proto->fn.write(ph, page, tx_data, tx_len);
+ else
+ return -EINVAL;
+}
+
+int rfid_protocol_fini(struct rfid_protocol_handle *ph)
+{
+ return ph->proto->fn.fini(ph);
+}
+
+int
+rfid_protocol_close(struct rfid_protocol_handle *ph)
+{
+ if (ph->proto->fn.close)
+ return ph->proto->fn.close(ph);
+ return 0;
+}
+
+int
+rfid_protocol_register(struct rfid_protocol *p)
+{
+ p->next = rfid_protocol_list;
+ rfid_protocol_list = p;
+
+ return 0;
+}
diff --git a/src/rfid_reader.c b/src/rfid_reader.c
new file mode 100644
index 0000000..9e46a29
--- /dev/null
+++ b/src/rfid_reader.c
@@ -0,0 +1,65 @@
+/* librfid - core reader handling
+ * (C) 2005 by 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 <stdlib.h>
+#include <stdio.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_reader.h>
+
+static struct rfid_reader *rfid_reader_list;
+
+struct rfid_reader_handle *
+rfid_reader_open(void *data, unsigned int id)
+{
+ struct rfid_reader *p;
+
+ for (p = rfid_reader_list; p; p = p->next)
+ if (p->id == id)
+ return p->open(data);
+
+ DEBUGP("unable to find matching reader\n");
+ return NULL;
+}
+
+int
+rfid_reader_transcieve(struct rfid_reader_handle *rh,
+ enum rfid_frametype frametype,
+ const unsigned char *tx_buf, unsigned int len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags)
+{
+ return rh->reader->transcieve(rh, frametype, tx_buf, len, rx_buf,
+ rx_len, timeout, flags);
+}
+
+void
+rfid_reader_close(struct rfid_reader_handle *rh)
+{
+ rh->reader->close(rh);
+}
+
+int
+rfid_reader_register(struct rfid_reader *r)
+{
+ r->next = rfid_reader_list;
+ rfid_reader_list = r;
+
+ return 0;
+}
diff --git a/src/rfid_reader_cm5121.c b/src/rfid_reader_cm5121.c
new file mode 100644
index 0000000..978e18f
--- /dev/null
+++ b/src/rfid_reader_cm5121.c
@@ -0,0 +1,337 @@
+/* Omnikey CardMan 5121 specific RC632 transport layer
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * The 5121 is an Atmel AT98C5122 based USB CCID reader (probably the same
+ * design like the 3121). It's CL RC632 is connected via address/data bus,
+ * not via SPI.
+ *
+ * The vendor-supplied reader firmware provides some undocumented extensions
+ * to CCID (via PC_to_RDR_Escape) that allow access to registers and FIFO of
+ * the RC632.
+ *
+ */
+
+/*
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_reader.h>
+#include <rfid/rfid_asic.h>
+#include <rfid/rfid_asic_rc632.h>
+#include <rfid/rfid_reader_cm5121.h>
+
+//#define SENDBUF_LEN 40
+#define SENDBUF_LEN 100
+#define RECVBUF_LEN 40
+
+#if 1
+#ifdef DEBUGP
+#undef DEBUGP
+#define DEBUGP(x, ...)
+#define DEBUGPC(x, ...)
+#endif
+#endif
+
+static
+int Write1ByteToReg(struct rfid_asic_transport_handle *rath,
+ unsigned char reg, unsigned char value)
+{
+ unsigned char sndbuf[SENDBUF_LEN];
+ unsigned char rcvbuf[RECVBUF_LEN];
+ unsigned int retlen = RECVBUF_LEN;
+
+ sndbuf[0] = 0x20;
+ sndbuf[1] = 0x00;
+ sndbuf[2] = 0x01;
+ sndbuf[3] = 0x00;
+ sndbuf[4] = 0x00;
+ sndbuf[5] = 0x00;
+ sndbuf[6] = reg;
+ sndbuf[7] = value;
+
+ DEBUGP("reg=0x%02x, val=%02x: ", reg, value);
+
+ if (PC_to_RDR_Escape(rath->data, sndbuf, 8, rcvbuf,
+ &retlen) == 0) {
+ DEBUGPC("OK\n");
+ return 0;
+ }
+
+ DEBUGPC("ERROR\n");
+ return -1;
+}
+
+static int Read1ByteFromReg(struct rfid_asic_transport_handle *rath,
+ unsigned char reg,
+ unsigned char *value)
+{
+ unsigned char sndbuf[SENDBUF_LEN];
+ unsigned char recvbuf[RECVBUF_LEN];
+ unsigned int retlen = sizeof(recvbuf);
+
+ sndbuf[0] = 0x20;
+ sndbuf[1] = 0x00;
+ sndbuf[2] = 0x00;
+ sndbuf[3] = 0x00;
+ sndbuf[4] = 0x01;
+ sndbuf[5] = 0x00;
+ sndbuf[6] = reg;
+
+ if (PC_to_RDR_Escape(rath->data, sndbuf, 7, recvbuf,
+ &retlen) == 0) {
+ *value = recvbuf[1];
+ DEBUGP("reg=0x%02x, val=%02x: ", reg, *value);
+ DEBUGPC("OK\n");
+ return 0;
+ }
+
+ DEBUGPC("ERROR\n");
+ return -1;
+}
+
+static int ReadNBytesFromFIFO(struct rfid_asic_transport_handle *rath,
+ unsigned char num_bytes,
+ unsigned char *buf)
+{
+ unsigned char sndbuf[SENDBUF_LEN];
+ unsigned char recvbuf[0x7f];
+ unsigned int retlen = sizeof(recvbuf);
+
+ sndbuf[0] = 0x20;
+ sndbuf[1] = 0x00;
+ sndbuf[2] = 0x00;
+ sndbuf[3] = 0x00;
+ sndbuf[4] = num_bytes;
+ sndbuf[5] = 0x00;
+ sndbuf[6] = 0x02;
+
+ DEBUGP("num_bytes=%u: ", num_bytes);
+ if (PC_to_RDR_Escape(rath->data, sndbuf, 7, recvbuf, &retlen) == 0) {
+ DEBUGPC("%u [%s]\n", retlen,
+ rfid_hexdump(recvbuf+1, num_bytes));
+ memcpy(buf, recvbuf+1, num_bytes); // len == 0x7f
+ return 0;
+ }
+
+ DEBUGPC("ERROR\n");
+ return -1;
+}
+
+static int WriteNBytesToFIFO(struct rfid_asic_transport_handle *rath,
+ unsigned char len,
+ const unsigned char *bytes,
+ unsigned char flags)
+{
+ unsigned char sndbuf[SENDBUF_LEN];
+ unsigned char recvbuf[0x7f];
+ unsigned int retlen = sizeof(recvbuf);
+
+ sndbuf[0] = 0x20;
+ sndbuf[1] = 0x00;
+ sndbuf[2] = len;
+ sndbuf[3] = 0x00;
+ sndbuf[4] = 0x00;
+ sndbuf[5] = flags;
+ sndbuf[6] = 0x02;
+
+ DEBUGP("%u [%s]: ", len, rfid_hexdump(bytes, len));
+
+ memcpy(sndbuf+7, bytes, len);
+
+ if (PC_to_RDR_Escape(rath->data, sndbuf, len+7, recvbuf, &retlen) == 0) {
+ DEBUGPC("OK (%u [%s])\n", retlen, rfid_hexdump(recvbuf, retlen));
+ return 0;
+ }
+
+ DEBUGPC("ERROR\n");
+ return -1;
+}
+
+#if 0
+static int TestFIFO(struct rc632_handle *handle)
+{
+ unsigned char sndbuf[60]; // 0x3c
+
+ // FIXME: repne stosd, call
+
+ memset(sndbuf, 0, sizeof(sndbuf));
+
+ if (WriteNBytesToFIFO(handle, sizeof(sndbuf), sndbuf, 0) < 0)
+ return -1;
+
+ return ReadNBytesFromFIFO(handle, sizeof(sndbuf), sndbuf);
+}
+#endif
+
+static int cm5121_transcieve(struct rfid_reader_handle *rh,
+ enum rfid_frametype frametype,
+ const unsigned char *tx_data, unsigned int tx_len,
+ unsigned char *rx_data, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags)
+{
+ return rh->ah->asic->priv.rc632.fn.transcieve(rh->ah, frametype,
+ tx_data, tx_len, rx_data,
+ rx_len, timeout, flags);
+}
+
+static int cm5121_transcieve_sf(struct rfid_reader_handle *rh,
+ unsigned char cmd, struct iso14443a_atqa *atqa)
+{
+ return rh->ah->asic->priv.rc632.fn.iso14443a.transcieve_sf(rh->ah,
+ cmd,
+ atqa);
+}
+
+static int
+cm5121_transcieve_acf(struct rfid_reader_handle *rh,
+ struct iso14443a_anticol_cmd *cmd,
+ unsigned int *bit_of_col)
+{
+ return rh->ah->asic->priv.rc632.fn.iso14443a.transcieve_acf(rh->ah,
+ cmd, bit_of_col);
+}
+
+static int
+cm5121_14443a_init(struct rfid_reader_handle *rh)
+{
+ return rh->ah->asic->priv.rc632.fn.iso14443a.init(rh->ah);
+}
+
+static int
+cm5121_14443b_init(struct rfid_reader_handle *rh)
+{
+ return rh->ah->asic->priv.rc632.fn.iso14443b.init(rh->ah);
+}
+
+static int
+cm5121_15693_init(struct rfid_reader_handle *rh)
+{
+ return rh->ah->asic->priv.rc632.fn.iso15693.init(rh->ah);
+}
+
+static int
+cm5121_mifare_setkey(struct rfid_reader_handle *rh, const u_int8_t *key)
+{
+ return rh->ah->asic->priv.rc632.fn.mifare_classic.setkey(rh->ah, key);
+}
+
+static int
+cm5121_mifare_auth(struct rfid_reader_handle *rh, u_int8_t cmd,
+ u_int32_t serno, u_int8_t block)
+{
+ return rh->ah->asic->priv.rc632.fn.mifare_classic.auth(rh->ah,
+ cmd, serno, block);
+}
+
+struct rfid_asic_transport cm5121_ccid = {
+ .name = "CM5121 OpenCT",
+ .priv.rc632 = {
+ .fn = {
+ .reg_write = &Write1ByteToReg,
+ .reg_read = &Read1ByteFromReg,
+ .fifo_write = &WriteNBytesToFIFO,
+ .fifo_read = &ReadNBytesFromFIFO,
+ },
+ },
+};
+
+static int cm5121_enable_rc632(struct rfid_asic_transport_handle *rath)
+{
+ unsigned char tx_buf[1] = { 0x01 };
+ unsigned char rx_buf[64];
+ unsigned int rx_len = sizeof(rx_buf);
+
+ PC_to_RDR_Escape(rath->data, tx_buf, 1, rx_buf, &rx_len);
+ printf("received %u bytes from 01 command\n", rx_len);
+
+ return 0;
+}
+
+static struct rfid_reader_handle *
+cm5121_open(void *data)
+{
+ struct rfid_reader_handle *rh;
+ struct rfid_asic_transport_handle *rath;
+
+ rh = malloc(sizeof(*rh));
+ if (!rh)
+ return NULL;
+ memset(rh, 0, sizeof(*rh));
+
+ rath = malloc(sizeof(*rath));
+ if (!rath)
+ goto out_rh;
+ memset(rath, 0, sizeof(*rath));
+
+ rath->rat = &cm5121_ccid;
+ rh->reader = &rfid_reader_cm5121;
+
+ if (cm5121_source_init(rath) < 0)
+ goto out_rath;
+
+ if (cm5121_enable_rc632(rath) < 0)
+ goto out_rath;
+
+ rh->ah = rc632_open(rath);
+ if (!rh->ah)
+ goto out_rath;
+
+ DEBUGP("returning %p\n", rh);
+ return rh;
+
+out_rath:
+ free(rath);
+out_rh:
+ free(rh);
+
+ return NULL;
+}
+
+static void
+cm5121_close(struct rfid_reader_handle *rh)
+{
+ struct rfid_asic_transport_handle *rath = rh->ah->rath;
+ rc632_close(rh->ah);
+ free(rath);
+ free(rh);
+}
+
+struct rfid_reader rfid_reader_cm5121 = {
+ .name = "Omnikey CardMan 5121 RFID",
+ .open = &cm5121_open,
+ .close = &cm5121_close,
+ .transcieve = &cm5121_transcieve,
+ .iso14443a = {
+ .init = &cm5121_14443a_init,
+ .transcieve_sf = &cm5121_transcieve_sf,
+ .transcieve_acf = &cm5121_transcieve_acf,
+ .speed = RFID_READER_SPEED_106K | RFID_READER_SPEED_212K |
+ RFID_READER_SPEED_424K | RFID_READER_SPEED_848K,
+ },
+ .iso14443b = {
+ .init = &cm5121_14443b_init,
+ },
+ .mifare_classic = {
+ .setkey = &cm5121_mifare_setkey,
+ .auth = &cm5121_mifare_auth,
+ },
+};
+
+
diff --git a/src/rfid_reader_cm5121_ccid_direct.c b/src/rfid_reader_cm5121_ccid_direct.c
new file mode 100644
index 0000000..7f53bb7
--- /dev/null
+++ b/src/rfid_reader_cm5121_ccid_direct.c
@@ -0,0 +1,36 @@
+/* CM5121 backend for 'internal' CCID driver */
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <rfid/rfid_asic.h>
+
+#include "ccid/ccid-driver.h"
+
+/* this is the sole function required by rfid_reader_cm5121.c */
+int
+PC_to_RDR_Escape(void *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len)
+{
+ int rc;
+ ccid_driver_t ch = handle;
+ size_t maxrxlen = *rx_len;
+
+ rc = ccid_transceive_escape (ch, tx_buf, tx_len,
+ rx_buf, maxrxlen, rx_len);
+
+ return rc;
+}
+
+int cm5121_source_init(struct rfid_asic_transport_handle *rath)
+{
+ int rc;
+
+ rc = ccid_open_reader(&rath->data, NULL);
+ if (rc) {
+ fprintf (stderr, "failed to open CCID reader: %#x\n", rc);
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/rfid_reader_cm5121_openct.c b/src/rfid_reader_cm5121_openct.c
new file mode 100644
index 0000000..9d96638
--- /dev/null
+++ b/src/rfid_reader_cm5121_openct.c
@@ -0,0 +1,59 @@
+/* CM5121 backend for OpenCT virtual slot */
+
+#include <stdio.h>
+
+#include <rfid/rfid_asic.h>
+#include <openct/openct.h>
+
+/* FIXME: get rid of this global crap. In fact this needs to become part of
+ * struct rfid_reader_handle */
+static ct_lock_handle lock;
+static int slot = 1;
+
+/* this is the sole function required by rfid_reader_cm5121.c */
+int
+PC_to_RDR_Escape(void *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len)
+{
+ int rc;
+ ct_handle *h = (ct_handle *) handle;
+
+ rc = ct_card_transact(h, 1, tx_buf, tx_len, rx_buf, *rx_len);
+ if (rc >= 0) {
+ *rx_len = rc;
+ return 0;
+ }
+
+ return rc;
+}
+
+
+int cm5121_source_init(struct rfid_asic_transport_handle *rath)
+{
+ struct ct_handle *h;
+ int rc;
+ unsigned char atr[64];
+
+ h = ct_reader_connect(0);
+ if (!h)
+ return -1;
+
+ printf("acquiring card lock\n");
+ rc = ct_card_lock(h, slot, IFD_LOCK_EXCLUSIVE, &lock);
+ if (rc < 0) {
+ fprintf(stderr, "error, no card lock\n");
+ return -1;
+ }
+
+ rc = ct_card_reset(h, slot, atr, sizeof(atr));
+ if (rc < 0) {
+ fprintf(stderr, "error, can't reset virtual card\n");
+ return -1;
+ }
+
+ rath->data = h;
+
+ return 0;
+}
+
personal git repositories of Harald Welte. Your mileage may vary