From 05c7e304271bcf88901da3782fcd3f28a0c7c9cf Mon Sep 17 00:00:00 2001 From: laforge Date: Tue, 8 Nov 2005 08:34:15 +0000 Subject: use autoconf/automake git-svn-id: https://svn.gnumonks.org/trunk/librfid@1658 e0336214-984f-0b4b-a45f-81c69e1f0ede --- Makefile | 26 - Makefile.am | 8 + autogen.sh | 18 + include/Makefile.am | 2 + include/rfid/Makefile.am | 10 + openct-escape.c | 340 --------- rc632.h | 214 ------ rfid.c | 56 -- rfid_asic_rc632.c | 1295 ---------------------------------- rfid_asic_rc632_14443a.c | 394 ----------- rfid_asic_rc632_14443b.c | 69 -- rfid_asic_rc632_mifare.c | 25 - rfid_iso14443_common.c | 58 -- rfid_iso14443_common.h | 11 - rfid_layer2.c | 76 -- rfid_layer2_iso14443a.c | 294 -------- rfid_layer2_iso14443b.c | 344 --------- rfid_layer2_iso15693.c | 302 -------- rfid_proto_mifare_classic.c | 148 ---- rfid_proto_mifare_ul.c | 162 ----- rfid_proto_tcl.c | 694 ------------------ rfid_protocol.c | 113 --- rfid_reader.c | 65 -- rfid_reader_cm5121.c | 337 --------- rfid_reader_cm5121_ccid_direct.c | 36 - rfid_reader_cm5121_openct.c | 59 -- src/Makefile.am | 13 + src/rc632.h | 214 ++++++ src/rfid.c | 56 ++ src/rfid_asic_rc632.c | 1295 ++++++++++++++++++++++++++++++++++ src/rfid_asic_rc632_14443a.c | 394 +++++++++++ src/rfid_asic_rc632_14443b.c | 69 ++ src/rfid_asic_rc632_mifare.c | 25 + src/rfid_iso14443_common.c | 58 ++ src/rfid_iso14443_common.h | 11 + src/rfid_layer2.c | 76 ++ src/rfid_layer2_iso14443a.c | 294 ++++++++ src/rfid_layer2_iso14443b.c | 344 +++++++++ src/rfid_layer2_iso15693.c | 302 ++++++++ src/rfid_proto_mifare_classic.c | 148 ++++ src/rfid_proto_mifare_ul.c | 162 +++++ src/rfid_proto_tcl.c | 694 ++++++++++++++++++ src/rfid_protocol.c | 113 +++ src/rfid_reader.c | 65 ++ src/rfid_reader_cm5121.c | 337 +++++++++ src/rfid_reader_cm5121_ccid_direct.c | 36 + src/rfid_reader_cm5121_openct.c | 59 ++ utils/Makefile.am | 8 + utils/openct-escape.c | 340 +++++++++ 49 files changed, 5151 insertions(+), 5118 deletions(-) delete mode 100644 Makefile create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 include/Makefile.am create mode 100644 include/rfid/Makefile.am delete mode 100644 openct-escape.c delete mode 100644 rc632.h delete mode 100644 rfid.c delete mode 100644 rfid_asic_rc632.c delete mode 100644 rfid_asic_rc632_14443a.c delete mode 100644 rfid_asic_rc632_14443b.c delete mode 100644 rfid_asic_rc632_mifare.c delete mode 100644 rfid_iso14443_common.c delete mode 100644 rfid_iso14443_common.h delete mode 100644 rfid_layer2.c delete mode 100644 rfid_layer2_iso14443a.c delete mode 100644 rfid_layer2_iso14443b.c delete mode 100644 rfid_layer2_iso15693.c delete mode 100644 rfid_proto_mifare_classic.c delete mode 100644 rfid_proto_mifare_ul.c delete mode 100644 rfid_proto_tcl.c delete mode 100644 rfid_protocol.c delete mode 100644 rfid_reader.c delete mode 100644 rfid_reader_cm5121.c delete mode 100644 rfid_reader_cm5121_ccid_direct.c delete mode 100644 rfid_reader_cm5121_openct.c create mode 100644 src/Makefile.am create mode 100644 src/rc632.h create mode 100644 src/rfid.c create mode 100644 src/rfid_asic_rc632.c create mode 100644 src/rfid_asic_rc632_14443a.c create mode 100644 src/rfid_asic_rc632_14443b.c create mode 100644 src/rfid_asic_rc632_mifare.c create mode 100644 src/rfid_iso14443_common.c create mode 100644 src/rfid_iso14443_common.h create mode 100644 src/rfid_layer2.c create mode 100644 src/rfid_layer2_iso14443a.c create mode 100644 src/rfid_layer2_iso14443b.c create mode 100644 src/rfid_layer2_iso15693.c create mode 100644 src/rfid_proto_mifare_classic.c create mode 100644 src/rfid_proto_mifare_ul.c create mode 100644 src/rfid_proto_tcl.c create mode 100644 src/rfid_protocol.c create mode 100644 src/rfid_reader.c create mode 100644 src/rfid_reader_cm5121.c create mode 100644 src/rfid_reader_cm5121_ccid_direct.c create mode 100644 src/rfid_reader_cm5121_openct.c create mode 100644 utils/Makefile.am create mode 100644 utils/openct-escape.c diff --git a/Makefile b/Makefile deleted file mode 100644 index 691c24c..0000000 --- a/Makefile +++ /dev/null @@ -1,26 +0,0 @@ - -CFLAGS:=-Wall -g -I/usr/local/include -Iinclude -LDFLAGS:= -lusb - -LIBRFID_OBJS=rfid_layer2.o rfid_layer2_iso14443a.o rfid_layer2_iso14443b.o rfid_layer2_iso15693.o rfid_asic_rc632.o rfid_reader_cm5121.o rfid.o rfid_protocol.o rfid_proto_tcl.o rfid_proto_mifare_ul.o rfid_proto_mifare_classic.o rfid_iso14443_common.o rfid_reader.o - -# uncomment this if you want to use OpenCT -LDFLAGS+=-lopenct -LIBRFID_OBJS+=rfid_reader_cm5121_openct.o - -# uncomment this if you want to use our internal CCID driver -#LIBRFID_OBJS+=rfid_reader_cm5121_ccid_direct.o ccid/ccid-driver.o - -all: openct-escape - -openct-escape: openct-escape.o librfid.a - $(CC) $(LDFLAGS) -o $@ $^ - -librfid.a: $(LIBRFID_OBJS) - ar r $@ $^ - -%.o: %.c - $(CC) $(CFLAGS) -DHAVE_LIBUSB -DUSE_INTERNAL_CCID_DRIVER -o $@ -c $^ - -clean: - rm -f *.o openct-escape librfid.a diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..69140e2 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,8 @@ +AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 + +SUBDIRS = include src utils +LINKOPTS = -lusb + +$(OBJECTS): libtool +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..ccce4f0 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +run () +{ + echo "running: $*" + eval $* + + if test $? != 0 ; then + echo "error: while running '$*'" + exit 1 + fi +} + +run aclocal +#run autoheader +run libtoolize -f +run automake -a +run autoconf diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..df5706a --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,2 @@ + +SUBDIRS = rfid diff --git a/include/rfid/Makefile.am b/include/rfid/Makefile.am new file mode 100644 index 0000000..59ce8cb --- /dev/null +++ b/include/rfid/Makefile.am @@ -0,0 +1,10 @@ + +pkginclude_HEADERS = rfid.h rfid_asic.h rfid_asic_rc632.h \ + rfid_layer2.h rfid_layer2_iso14443a.h \ + rfid_layer2_iso14443b.h rfid_layer2_iso15693.h \ + rfid_protocol.h rfid_protocol_tcl.h \ + rfid_protocol_mifare_ul.h \ + rfid_protocol_mifare_classic.h \ + rfid_reader.h \ + rfid_reader_cm5121.h + diff --git a/openct-escape.c b/openct-escape.c deleted file mode 100644 index aec258c..0000000 --- a/openct-escape.c +++ /dev/null @@ -1,340 +0,0 @@ -/* -*- linux-c -*- - * 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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static struct rfid_reader_handle *rh; -static struct rfid_layer2_handle *l2h; -static struct rfid_protocol_handle *ph; - -static int init() -{ - unsigned char buf[0x3f]; - int rc; - - printf("initializing librfid\n"); - rfid_init(); - - printf("opening reader handle\n"); - rh = rfid_reader_open(NULL, RFID_READER_CM5121); - if (!rh) { - fprintf(stderr, "error, no cm5121 handle\n"); - return -1; - } - - sleep(2); - - printf("opening layer2 handle\n"); - l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443A); - //l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443B); - if (!l2h) { - fprintf(stderr, "error during iso14443a_init\n"); - return -1; - } - - //rc632_register_dump(rh->ah, buf); - - printf("running layer2 anticol\n"); - rc = rfid_layer2_open(l2h); - if (rc < 0) { - fprintf(stderr, "error during layer2_open\n"); - return rc; - } - - return 0; -} - -static int l3(int protocol) -{ - printf("running layer3 (ats)\n"); - ph = rfid_protocol_init(l2h, protocol); - if (!ph) { - fprintf(stderr, "error during protocol_init\n"); - return -1; - } - if (rfid_protocol_open(ph) < 0) { - fprintf(stderr, "error during protocol_open\n"); - return -1; - } - - printf("we now have layer3 up and running\n"); - - return 0; -} - -static int select_mf(void) -{ - unsigned char cmd[] = { 0x00, 0xa4, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00 }; - unsigned char ret[256]; - unsigned int rlen = sizeof(ret); - - int rv; - - rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), ret, &rlen, 0, 0); - if (rv < 0) - return rv; - - printf("%s\n", rfid_hexdump(ret, rlen)); - - return 0; -} - - -static int iso7816_get_challenge(unsigned char len) -{ - unsigned char cmd[] = { 0x00, 0x84, 0x00, 0x00, 0x08 }; - unsigned char ret[256]; - unsigned int rlen = sizeof(ret); - - cmd[4] = len; - - int rv; - - rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), ret, &rlen, 0, 0); - if (rv < 0) - return rv; - - printf("%d: [%s]\n", rlen, rfid_hexdump(ret, rlen)); - - return 0; -} - -int -iso7816_select_application(void) -{ - char cmd[] = { 0x00, 0xa4, 0x04, 0x0c, 0x07, - 0xa0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01 }; - char resp[7]; - unsigned int rlen = sizeof(resp); - - int rv; - - rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0); - if (rv < 0) - return rv; - - /* FIXME: parse response */ - printf("%s\n", rfid_hexdump(resp, rlen)); - - return 0; -} - -int -iso7816_select_ef(u_int16_t fid) -{ - unsigned char cmd[7] = { 0x00, 0xa4, 0x02, 0x0c, 0x02, 0x00, 0x00 }; - unsigned char resp[7]; - unsigned int rlen = sizeof(resp); - - int rv; - - cmd[5] = (fid >> 8) & 0xff; - cmd[6] = fid & 0xff; - - rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0); - if (rv < 0) - return rv; - - /* FIXME: parse response */ - printf("%s\n", rfid_hexdump(resp, rlen)); - - return 0; -} - -int -iso7816_read_binary(unsigned char *buf, unsigned int *len) -{ - unsigned char cmd[] = { 0x00, 0xb0, 0x00, 0x00, 0x00 }; - unsigned char resp[256]; - unsigned int rlen = sizeof(resp); - - int rv; - - rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0); - if (rv < 0) - return rv; - - /* FIXME: parse response, determine whether we need additional reads */ - - /* FIXME: copy 'len' number of response bytes to 'buf' */ - return 0; -} - -/* wrapper function around SELECT EF and READ BINARY */ -int -iso7816_read_ef(u_int16_t fid, unsigned char *buf, unsigned int *len) -{ - int rv; - - rv = iso7816_select_ef(fid); - if (rv < 0) - return rv; - - return iso7816_read_binary(buf, len); -} - -/* mifare ultralight helpers */ -int -mifare_ulight_write(struct rfid_protocol_handle *ph) -{ - unsigned char buf[4] = { 0xa1, 0xa2, 0xa3, 0xa4 }; - - return rfid_protocol_write(ph, 10, buf, 4); -} - -int -mifare_ulight_blank(struct rfid_protocol_handle *ph) -{ - unsigned char buf[4] = { 0x00, 0x00, 0x00, 0x00 }; - int i, ret; - - for (i = 4; i <= MIFARE_UL_PAGE_MAX; i++) { - ret = rfid_protocol_write(ph, i, buf, 4); - if (ret < 0) - return ret; - } - return 0; -} - -static int -mifare_ulight_read(struct rfid_protocol_handle *ph) -{ - unsigned char buf[20]; - unsigned int len = sizeof(buf); - int ret; - int i; - - for (i = 0; i <= MIFARE_UL_PAGE_MAX; i++) { - ret = rfid_protocol_read(ph, i, buf, &len); - if (ret < 0) - return ret; - - printf("Page 0x%x: %s\n", i, rfid_hexdump(buf, 4)); - } - return 0; -} - -/* mifare classic helpers */ -static int -mifare_classic_read(struct rfid_protocol_handle *ph) -{ - unsigned char buf[20]; - unsigned int len = sizeof(buf); - int ret; - int i; - - for (i = 0; i <= MIFARE_CL_PAGE_MAX; i++) { - ret = rfid_protocol_read(ph, i, buf, &len); - if (ret < 0) - return ret; - - printf("Page 0x%x: %s\n", i, rfid_hexdump(buf, 4)); - } - return 0; -} - - -int main(int argc, char **argv) -{ - int rc; - char buf[0x40]; - int i, protocol; - -#if 0 - if (argc) { - argc--; - argv++; - } - - while (argc) { - if ( !strcmp (*argv, "--list")) { - char *p; - p = ccid_get_reader_list (); - if (!p) - return 1; - fputs (p, stderr); - free (p); - return 0; - } - else if ( !strcmp (*argv, "--debug")) { - ccid_set_debug_level (ccid_set_debug_level (-1) + 1); - argc--; argv++; - } - else - break; - } -#endif - - if (init() < 0) - exit(1); - - //protocol = RFID_PROTOCOL_MIFARE_UL; - //protocol = RFID_PROTOCOL_MIFARE_CLASSIC; - protocol = RFID_PROTOCOL_TCL; - - if (l3(protocol) < 0) - exit(1); - - switch (protocol) { - case RFID_PROTOCOL_TCL: - /* we've established T=CL at this point */ - select_mf(); - - iso7816_select_application(); - iso7816_select_ef(0x011e); - iso7816_select_ef(0x0101); -#if 1 - for (i = 0; i < 4; i++) - iso7816_get_challenge(0x60); -#endif - break; - case RFID_PROTOCOL_MIFARE_UL: - mifare_ulight_read(ph); -#if 0 - mifare_ulight_blank(ph); - mifare_ulight_write(ph); - mifare_ulight_read(ph); -#endif - break; - case RFID_PROTOCOL_MIFARE_CLASSIC: - rc = mfcl_set_key(ph, MIFARE_CLASSIC_KEYB_DEFAULT); - if (rc < 0) { - printf("key format error\n"); - exit(1); - } - rc = mfcl_auth(ph, RFID_CMD_MIFARE_AUTH1B, 10); - if (rc < 0) { - printf("mifare auth error\n"); - exit(1); - } else - printf("mifare authe succeeded!\n"); - mifare_classic_read(ph); - break; - } - - rfid_reader_close(rh); - - exit(0); -} diff --git a/rc632.h b/rc632.h deleted file mode 100644 index 4ad0e99..0000000 --- a/rc632.h +++ /dev/null @@ -1,214 +0,0 @@ -/* Register definitions for Philips CL RC632 RFID Reader IC - * - * (C) 2005 Harald Welte - * - * 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/rfid.c b/rfid.c deleted file mode 100644 index be72f12..0000000 --- a/rfid.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 -#include - -#include -#include -#include -#include -#include - -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/rfid_asic_rc632.c b/rfid_asic_rc632.c deleted file mode 100644 index 4377d73..0000000 --- a/rfid_asic_rc632.c +++ /dev/null @@ -1,1295 +0,0 @@ -/* Generic Philips CL RC632 Routines - * - * (C) Harald Welte - * - */ - -/* - * 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#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 - * - */ - -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)<> 4; - key12[i * 2 + 1] = (~ln << 4) | ln; - key12[i * 2] = (~hn << 4) | hn; - } - return 0; -} - -static int -rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key) -{ - u_int8_t coded_key[RFID_MIFARE_KEY_CODED_LEN]; - u_int8_t reg; - int ret; - - ret = rc632_mifare_transform_key(key, coded_key); - if (ret < 0) - return ret; - - ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_LOAD_KEY); - if (ret < 0) - return ret; - - ret = rc632_wait_idle(h, RC632_TMO_AUTH1); - if (ret < 0) - return ret; - - ret = rc632_reg_read(h, RC632_REG_ERROR_FLAG, ®); - if (ret < 0) - return ret; - - if (reg & RC632_ERR_FLAG_KEY_ERR) - return -EINVAL; - - return 0; -} - -static int -rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, - u_int8_t block) -{ - int ret; - struct mifare_authcmd acmd; - u_int8_t reg; - - if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B) - return -EINVAL; - - /* Initialize acmd */ - acmd.block_address = block & 0xff; - acmd.auth_cmd = cmd; - //acmd.serno = htonl(serno); - acmd.serno = serno; - - 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, ®); - if (ret < 0) - return ret; - if (reg & 0x07) - return -EIO; - - /* Clear Tx CRC */ - ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY, - RC632_CR_TX_CRC_ENABLE); - if (ret < 0) - return ret; - - /* Send Authent2 Command */ - ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT2); - if (ret < 0) - return ret; - - /* Wait until transmitter is idle */ - ret = rc632_wait_idle(h, RC632_TMO_AUTH1); - if (ret < 0) - return ret; - - /* Check whether authentication was successful */ - ret = rc632_reg_read(h, RC632_REG_CONTROL, ®); - if (ret < 0) - return ret; - - if (!(reg & RC632_CONTROL_CRYPTO1_ON)) - return -EACCES; - - return 0; - -} - -/* 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/rfid_asic_rc632_14443a.c b/rfid_asic_rc632_14443a.c deleted file mode 100644 index 4c8a37b..0000000 --- a/rfid_asic_rc632_14443a.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Philips CL RC632 primitives for ISO 14443-A compliant PICC's - * - * (C) 2005 by Harald Welte - * - */ - -#include -#include -#include - -#include -#include -#include - -#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/rfid_asic_rc632_14443b.c b/rfid_asic_rc632_14443b.c deleted file mode 100644 index 62aa224..0000000 --- a/rfid_asic_rc632_14443b.c +++ /dev/null @@ -1,69 +0,0 @@ - -#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)< 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/rfid_iso14443_common.h b/rfid_iso14443_common.h deleted file mode 100644 index 848d983..0000000 --- a/rfid_iso14443_common.h +++ /dev/null @@ -1,11 +0,0 @@ -#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/rfid_layer2.c b/rfid_layer2.c deleted file mode 100644 index c1ab6a6..0000000 --- a/rfid_layer2.c +++ /dev/null @@ -1,76 +0,0 @@ -/* librfid - layer 2 protocol handler - * (C) 2005 by Harald Welte - */ - -/* - * 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 -#include - -#include -#include - -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/rfid_layer2_iso14443a.c b/rfid_layer2_iso14443a.c deleted file mode 100644 index d93f917..0000000 --- a/rfid_layer2_iso14443a.c +++ /dev/null @@ -1,294 +0,0 @@ -/* ISO 14443-3 A anticollision implementation - * - * (C) 2005 by Harald Welte - * - */ - -/* - * 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 -#include -#include - -#include -#include -#include -#include - -#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/rfid_layer2_iso14443b.c b/rfid_layer2_iso14443b.c deleted file mode 100644 index f874071..0000000 --- a/rfid_layer2_iso14443b.c +++ /dev/null @@ -1,344 +0,0 @@ -/* ISO 14443-3 B anticollision implementation - * - * (C) 2005 by Harald Welte - * - */ - -/* - * 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 -#include -#include - -#include -#include -#include -#include - -#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/rfid_layer2_iso15693.c b/rfid_layer2_iso15693.c deleted file mode 100644 index 15ff18a..0000000 --- a/rfid_layer2_iso15693.c +++ /dev/null @@ -1,302 +0,0 @@ -/* ISO 15693 anticollision implementation - * - * (C) 2005 by Harald Welte - * - */ - -/* - * 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 -#include -#include - -#include -#include -#include -#include - -#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/rfid_proto_mifare_classic.c b/rfid_proto_mifare_classic.c deleted file mode 100644 index 10de288..0000000 --- a/rfid_proto_mifare_classic.c +++ /dev/null @@ -1,148 +0,0 @@ - -/* Mifare Classic implementation, PCD side. - * - * (C) 2005 by Harald Welte - * - */ - -/* - * 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 -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#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/rfid_proto_mifare_ul.c b/rfid_proto_mifare_ul.c deleted file mode 100644 index 9e5363f..0000000 --- a/rfid_proto_mifare_ul.c +++ /dev/null @@ -1,162 +0,0 @@ - -/* Mifare Ultralight implementation, PCD side. - * - * (C) 2005 by Harald Welte - * - */ - -/* - * 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 -#include -#include -#include -#include - -#include -#include -#include -#include - -#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/rfid_proto_tcl.c b/rfid_proto_tcl.c deleted file mode 100644 index f070614..0000000 --- a/rfid_proto_tcl.c +++ /dev/null @@ -1,694 +0,0 @@ -/* ISO 14443-4 (T=CL) implementation, PCD side. - * - * (C) 2005 by Harald Welte - * - */ - -/* - * 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#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/rfid_protocol.c b/rfid_protocol.c deleted file mode 100644 index abbd04d..0000000 --- a/rfid_protocol.c +++ /dev/null @@ -1,113 +0,0 @@ -/* librfid - layer 3 protocol handler - * (C) 2005 by Harald Welte - */ - -/* - * 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 -#include -#include - -#include -#include - -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/rfid_reader.c b/rfid_reader.c deleted file mode 100644 index 9e46a29..0000000 --- a/rfid_reader.c +++ /dev/null @@ -1,65 +0,0 @@ -/* librfid - core reader handling - * (C) 2005 by Harald Welte - */ - -/* - * 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 -#include - -#include -#include - -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/rfid_reader_cm5121.c b/rfid_reader_cm5121.c deleted file mode 100644 index 978e18f..0000000 --- a/rfid_reader_cm5121.c +++ /dev/null @@ -1,337 +0,0 @@ -/* Omnikey CardMan 5121 specific RC632 transport layer - * - * (C) 2005 by Harald Welte - * - * 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 -#include -#include - -#include -#include -#include -#include -#include - -//#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/rfid_reader_cm5121_ccid_direct.c b/rfid_reader_cm5121_ccid_direct.c deleted file mode 100644 index 7f53bb7..0000000 --- a/rfid_reader_cm5121_ccid_direct.c +++ /dev/null @@ -1,36 +0,0 @@ -/* CM5121 backend for 'internal' CCID driver */ -#include -#include -#include - -#include - -#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/rfid_reader_cm5121_openct.c b/rfid_reader_cm5121_openct.c deleted file mode 100644 index 9d96638..0000000 --- a/rfid_reader_cm5121_openct.c +++ /dev/null @@ -1,59 +0,0 @@ -/* CM5121 backend for OpenCT virtual slot */ - -#include - -#include -#include - -/* 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; -} - 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 + * + * 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 +#include + +#include +#include +#include +#include +#include + +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 + * + */ + +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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 + * + */ + +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)<> 4; + key12[i * 2 + 1] = (~ln << 4) | ln; + key12[i * 2] = (~hn << 4) | hn; + } + return 0; +} + +static int +rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key) +{ + u_int8_t coded_key[RFID_MIFARE_KEY_CODED_LEN]; + u_int8_t reg; + int ret; + + ret = rc632_mifare_transform_key(key, coded_key); + if (ret < 0) + return ret; + + ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03); + if (ret < 0) + return ret; + + ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_LOAD_KEY); + if (ret < 0) + return ret; + + ret = rc632_wait_idle(h, RC632_TMO_AUTH1); + if (ret < 0) + return ret; + + ret = rc632_reg_read(h, RC632_REG_ERROR_FLAG, ®); + if (ret < 0) + return ret; + + if (reg & RC632_ERR_FLAG_KEY_ERR) + return -EINVAL; + + return 0; +} + +static int +rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, + u_int8_t block) +{ + int ret; + struct mifare_authcmd acmd; + u_int8_t reg; + + if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B) + return -EINVAL; + + /* Initialize acmd */ + acmd.block_address = block & 0xff; + acmd.auth_cmd = cmd; + //acmd.serno = htonl(serno); + acmd.serno = serno; + + 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, ®); + if (ret < 0) + return ret; + if (reg & 0x07) + return -EIO; + + /* Clear Tx CRC */ + ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY, + RC632_CR_TX_CRC_ENABLE); + if (ret < 0) + return ret; + + /* Send Authent2 Command */ + ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT2); + if (ret < 0) + return ret; + + /* Wait until transmitter is idle */ + ret = rc632_wait_idle(h, RC632_TMO_AUTH1); + if (ret < 0) + return ret; + + /* Check whether authentication was successful */ + ret = rc632_reg_read(h, RC632_REG_CONTROL, ®); + if (ret < 0) + return ret; + + if (!(reg & RC632_CONTROL_CRYPTO1_ON)) + return -EACCES; + + return 0; + +} + +/* 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 + * + */ + +#include +#include +#include + +#include +#include +#include + +#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)< 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 + */ + +/* + * 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 +#include + +#include +#include + +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 + * + */ + +/* + * 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 +#include +#include + +#include +#include +#include +#include + +#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 + * + */ + +/* + * 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 +#include +#include + +#include +#include +#include +#include + +#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 + * + */ + +/* + * 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 +#include +#include + +#include +#include +#include +#include + +#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 + * + */ + +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#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 + * + */ + +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 + * + */ + +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#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 + */ + +/* + * 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 +#include +#include + +#include +#include + +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 + */ + +/* + * 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 +#include + +#include +#include + +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 + * + * 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 +#include +#include + +#include +#include +#include +#include +#include + +//#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 +#include +#include + +#include + +#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 + +#include +#include + +/* 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; +} + diff --git a/utils/Makefile.am b/utils/Makefile.am new file mode 100644 index 0000000..cddde17 --- /dev/null +++ b/utils/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = $(all_includes) -I$(top_srcdir)/include + +bin_PROGRAMS = openct-escape + +openct_escape_SOURCES = openct-escape.c +openct_escape_LDADD = ../src/librfid.la +openct_escape_LDFLAGS = -dynamic + diff --git a/utils/openct-escape.c b/utils/openct-escape.c new file mode 100644 index 0000000..aec258c --- /dev/null +++ b/utils/openct-escape.c @@ -0,0 +1,340 @@ +/* -*- linux-c -*- + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static struct rfid_reader_handle *rh; +static struct rfid_layer2_handle *l2h; +static struct rfid_protocol_handle *ph; + +static int init() +{ + unsigned char buf[0x3f]; + int rc; + + printf("initializing librfid\n"); + rfid_init(); + + printf("opening reader handle\n"); + rh = rfid_reader_open(NULL, RFID_READER_CM5121); + if (!rh) { + fprintf(stderr, "error, no cm5121 handle\n"); + return -1; + } + + sleep(2); + + printf("opening layer2 handle\n"); + l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443A); + //l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443B); + if (!l2h) { + fprintf(stderr, "error during iso14443a_init\n"); + return -1; + } + + //rc632_register_dump(rh->ah, buf); + + printf("running layer2 anticol\n"); + rc = rfid_layer2_open(l2h); + if (rc < 0) { + fprintf(stderr, "error during layer2_open\n"); + return rc; + } + + return 0; +} + +static int l3(int protocol) +{ + printf("running layer3 (ats)\n"); + ph = rfid_protocol_init(l2h, protocol); + if (!ph) { + fprintf(stderr, "error during protocol_init\n"); + return -1; + } + if (rfid_protocol_open(ph) < 0) { + fprintf(stderr, "error during protocol_open\n"); + return -1; + } + + printf("we now have layer3 up and running\n"); + + return 0; +} + +static int select_mf(void) +{ + unsigned char cmd[] = { 0x00, 0xa4, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00 }; + unsigned char ret[256]; + unsigned int rlen = sizeof(ret); + + int rv; + + rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), ret, &rlen, 0, 0); + if (rv < 0) + return rv; + + printf("%s\n", rfid_hexdump(ret, rlen)); + + return 0; +} + + +static int iso7816_get_challenge(unsigned char len) +{ + unsigned char cmd[] = { 0x00, 0x84, 0x00, 0x00, 0x08 }; + unsigned char ret[256]; + unsigned int rlen = sizeof(ret); + + cmd[4] = len; + + int rv; + + rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), ret, &rlen, 0, 0); + if (rv < 0) + return rv; + + printf("%d: [%s]\n", rlen, rfid_hexdump(ret, rlen)); + + return 0; +} + +int +iso7816_select_application(void) +{ + char cmd[] = { 0x00, 0xa4, 0x04, 0x0c, 0x07, + 0xa0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01 }; + char resp[7]; + unsigned int rlen = sizeof(resp); + + int rv; + + rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0); + if (rv < 0) + return rv; + + /* FIXME: parse response */ + printf("%s\n", rfid_hexdump(resp, rlen)); + + return 0; +} + +int +iso7816_select_ef(u_int16_t fid) +{ + unsigned char cmd[7] = { 0x00, 0xa4, 0x02, 0x0c, 0x02, 0x00, 0x00 }; + unsigned char resp[7]; + unsigned int rlen = sizeof(resp); + + int rv; + + cmd[5] = (fid >> 8) & 0xff; + cmd[6] = fid & 0xff; + + rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0); + if (rv < 0) + return rv; + + /* FIXME: parse response */ + printf("%s\n", rfid_hexdump(resp, rlen)); + + return 0; +} + +int +iso7816_read_binary(unsigned char *buf, unsigned int *len) +{ + unsigned char cmd[] = { 0x00, 0xb0, 0x00, 0x00, 0x00 }; + unsigned char resp[256]; + unsigned int rlen = sizeof(resp); + + int rv; + + rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0); + if (rv < 0) + return rv; + + /* FIXME: parse response, determine whether we need additional reads */ + + /* FIXME: copy 'len' number of response bytes to 'buf' */ + return 0; +} + +/* wrapper function around SELECT EF and READ BINARY */ +int +iso7816_read_ef(u_int16_t fid, unsigned char *buf, unsigned int *len) +{ + int rv; + + rv = iso7816_select_ef(fid); + if (rv < 0) + return rv; + + return iso7816_read_binary(buf, len); +} + +/* mifare ultralight helpers */ +int +mifare_ulight_write(struct rfid_protocol_handle *ph) +{ + unsigned char buf[4] = { 0xa1, 0xa2, 0xa3, 0xa4 }; + + return rfid_protocol_write(ph, 10, buf, 4); +} + +int +mifare_ulight_blank(struct rfid_protocol_handle *ph) +{ + unsigned char buf[4] = { 0x00, 0x00, 0x00, 0x00 }; + int i, ret; + + for (i = 4; i <= MIFARE_UL_PAGE_MAX; i++) { + ret = rfid_protocol_write(ph, i, buf, 4); + if (ret < 0) + return ret; + } + return 0; +} + +static int +mifare_ulight_read(struct rfid_protocol_handle *ph) +{ + unsigned char buf[20]; + unsigned int len = sizeof(buf); + int ret; + int i; + + for (i = 0; i <= MIFARE_UL_PAGE_MAX; i++) { + ret = rfid_protocol_read(ph, i, buf, &len); + if (ret < 0) + return ret; + + printf("Page 0x%x: %s\n", i, rfid_hexdump(buf, 4)); + } + return 0; +} + +/* mifare classic helpers */ +static int +mifare_classic_read(struct rfid_protocol_handle *ph) +{ + unsigned char buf[20]; + unsigned int len = sizeof(buf); + int ret; + int i; + + for (i = 0; i <= MIFARE_CL_PAGE_MAX; i++) { + ret = rfid_protocol_read(ph, i, buf, &len); + if (ret < 0) + return ret; + + printf("Page 0x%x: %s\n", i, rfid_hexdump(buf, 4)); + } + return 0; +} + + +int main(int argc, char **argv) +{ + int rc; + char buf[0x40]; + int i, protocol; + +#if 0 + if (argc) { + argc--; + argv++; + } + + while (argc) { + if ( !strcmp (*argv, "--list")) { + char *p; + p = ccid_get_reader_list (); + if (!p) + return 1; + fputs (p, stderr); + free (p); + return 0; + } + else if ( !strcmp (*argv, "--debug")) { + ccid_set_debug_level (ccid_set_debug_level (-1) + 1); + argc--; argv++; + } + else + break; + } +#endif + + if (init() < 0) + exit(1); + + //protocol = RFID_PROTOCOL_MIFARE_UL; + //protocol = RFID_PROTOCOL_MIFARE_CLASSIC; + protocol = RFID_PROTOCOL_TCL; + + if (l3(protocol) < 0) + exit(1); + + switch (protocol) { + case RFID_PROTOCOL_TCL: + /* we've established T=CL at this point */ + select_mf(); + + iso7816_select_application(); + iso7816_select_ef(0x011e); + iso7816_select_ef(0x0101); +#if 1 + for (i = 0; i < 4; i++) + iso7816_get_challenge(0x60); +#endif + break; + case RFID_PROTOCOL_MIFARE_UL: + mifare_ulight_read(ph); +#if 0 + mifare_ulight_blank(ph); + mifare_ulight_write(ph); + mifare_ulight_read(ph); +#endif + break; + case RFID_PROTOCOL_MIFARE_CLASSIC: + rc = mfcl_set_key(ph, MIFARE_CLASSIC_KEYB_DEFAULT); + if (rc < 0) { + printf("key format error\n"); + exit(1); + } + rc = mfcl_auth(ph, RFID_CMD_MIFARE_AUTH1B, 10); + if (rc < 0) { + printf("mifare auth error\n"); + exit(1); + } else + printf("mifare authe succeeded!\n"); + mifare_classic_read(ph); + break; + } + + rfid_reader_close(rh); + + exit(0); +} -- cgit v1.2.3