diff options
21 files changed, 758 insertions, 71 deletions
diff --git a/openpcd/firmware/Makefile b/openpcd/firmware/Makefile index 681e522..c9c793e 100644 --- a/openpcd/firmware/Makefile +++ b/openpcd/firmware/Makefile @@ -77,6 +77,8 @@ SRCARM = lib/lib_AT91SAM7.c src/pcd_enumerate.c src/fifo.c src/dbgu.c \ src/trigger.c src/main.c src/syscalls.c \ src/$(TARGET).c src/start/Cstartup_SAM7.c +SRCARM += src/rfid_layer2_iso14443a.c + # List C++ source files here. # use file-extension cpp for C++-files (use extension .cpp) CPPSRC = @@ -141,8 +143,10 @@ AT91LIBNOWARN = yes CSTANDARD = -std=gnu99 # Place -D or -U options for C here -CDEFS = -D$(RUN_MODE) -D__MS_types__ -DDEBUG -#CDEFS += -DOLIMEX +CDEFS = -D$(RUN_MODE) -D__MS_types__ -D__LIBRFID__ -DDEBUG +ifdef OLIMEX +CDEFS += -DOLIMEX +endif # Place -I options here CINCS = -Iinclude -Isrc diff --git a/openpcd/firmware/include/rfid.h b/openpcd/firmware/include/librfid/rfid.h index 5684884..eb96378 100644 --- a/openpcd/firmware/include/rfid.h +++ b/openpcd/firmware/include/librfid/rfid.h @@ -1,6 +1,16 @@ #ifndef _RFID_H #define _RFID_H +#include "dbgu.h" + +#define rfid_hexdump hexdump + +enum rfid_frametype { + RFID_14443A_FRAME_REGULAR, + RFID_14443B_FRAME_REGULAR, + RFID_MIFARE_FRAME, +}; + struct rfid_asic_handle { }; diff --git a/openpcd/firmware/include/librfid/rfid_layer2.h b/openpcd/firmware/include/librfid/rfid_layer2.h new file mode 100644 index 0000000..3dd54a2 --- /dev/null +++ b/openpcd/firmware/include/librfid/rfid_layer2.h @@ -0,0 +1,76 @@ +#ifndef _RFID_LAYER2_H +#define _RFID_LAYER2_H + +#include <sys/types.h> +#include <librfid/rfid.h> + +struct rfid_layer2_handle; +struct rfid_reader_handle; + +enum rfid_layer2_id { + RFID_LAYER2_NONE, + RFID_LAYER2_ISO14443A, + RFID_LAYER2_ISO14443B, + RFID_LAYER2_ISO15693, +}; + +struct rfid_layer2_handle *rfid_layer2_init(struct rfid_reader_handle *rh, + unsigned int id); +int rfid_layer2_open(struct rfid_layer2_handle *l2h); +int rfid_layer2_transceive(struct rfid_layer2_handle *l2h, + 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); +int rfid_layer2_close(struct rfid_layer2_handle *l2h); +int rfid_layer2_fini(struct rfid_layer2_handle *l2h); +int rfid_layer2_getopt(struct rfid_layer2_handle *ph, int optname, + void *optval, unsigned int *optlen); +int rfid_layer2_setopt(struct rfid_layer2_handle *ph, int optname, + const void *optval, unsigned int optlen); + +#ifdef __LIBRFID__ + +#include <librfid/rfid_layer2_iso14443a.h> +#include <librfid/rfid_layer2_iso14443b.h> +#include <librfid/rfid_layer2_iso15693.h> + +struct rfid_layer2 { + unsigned int id; + char *name; + + struct { + struct rfid_layer2_handle *(*init)(struct rfid_reader_handle *h); + int (*open)(struct rfid_layer2_handle *h); + int (*transceive)(struct rfid_layer2_handle *h, + 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); + int (*close)(struct rfid_layer2_handle *h); + int (*fini)(struct rfid_layer2_handle *h); + int (*getopt)(struct rfid_layer2_handle *h, + int optname, void *optval, unsigned int *optlen); + int (*setopt)(struct rfid_layer2_handle *h, + int optname, const void *optval, + unsigned int optlen); + } fn; + struct rfid_layer2 *next; +}; + +struct rfid_layer2_handle { + struct rfid_reader_handle *rh; + unsigned char uid[10]; /* triple size 14443a id is 10 bytes */ + unsigned int uid_len; + union { + struct iso14443a_handle iso14443a; + struct iso14443b_handle iso14443b; + struct iso15693_handle iso15693; + } priv; + struct rfid_layer2 *l2; +}; + +#endif /* __LIBRFID__ */ + +#endif diff --git a/openpcd/firmware/include/rfid_layer2_iso14443a.h b/openpcd/firmware/include/librfid/rfid_layer2_iso14443a.h index 936d902..e1ecd36 100644 --- a/openpcd/firmware/include/rfid_layer2_iso14443a.h +++ b/openpcd/firmware/include/librfid/rfid_layer2_iso14443a.h @@ -1,12 +1,6 @@ #ifndef _RFID_ISO14443A_H #define _RFID_ISO14443A_H -enum rfid_frametype { - RFID_14443A_FRAME_REGULAR, - RFID_14443B_FRAME_REGULAR, - RFID_MIFARE_FRAME, -}; - enum rfid_14443a_opt { RFID_OPT_14443A_SPEED_RX = 0x00000001, @@ -38,7 +32,7 @@ struct iso14443a_atqa { uid_size:2; u_int8_t proprietary:4, rfu2:4; -}; +} __attribute__ ((packed)); #define ISO14443A_HLTA 0x5000 @@ -47,7 +41,7 @@ struct iso14443a_anticol_cmd { unsigned char sel_code; unsigned char nvb; unsigned char uid_bits[5]; -}; +} __attribute__ ((packed)); enum iso14443a_anticol_sel_code { ISO14443A_AC_SEL_CODE_CL1 = 0x93, @@ -57,6 +51,11 @@ enum iso14443a_anticol_sel_code { #define ISO14443A_BITOFCOL_NONE 0xffffffff +struct iso14443a_handle { + unsigned int state; + unsigned int level; + unsigned int tcl_capable; +}; enum iso14443a_level { ISO14443A_LEVEL_NONE, @@ -82,5 +81,7 @@ enum iso14443a_state { #define ISO14443_CARRIER_FREQ 13560000 #define ISO14443A_FDT_OTHER_LAST1(n) (((n*128+84)*1000000)/ISO14443_CARRIER_FREQ) +#include <librfid/rfid_layer2.h> +struct rfid_layer2 rfid_layer2_iso14443a; #endif /* _ISO14443A_H */ diff --git a/openpcd/firmware/include/librfid/rfid_layer2_iso14443b.h b/openpcd/firmware/include/librfid/rfid_layer2_iso14443b.h new file mode 100644 index 0000000..5d6d979 --- /dev/null +++ b/openpcd/firmware/include/librfid/rfid_layer2_iso14443b.h @@ -0,0 +1,85 @@ +#ifndef _RFID_LAYER2_ISO14443B_H +#define _RFID_LAYER2_ISO14443B_H + +#ifdef __LIBRFID__ + +struct iso14443b_atqb { + unsigned char fifty; + unsigned char pupi[4]; + unsigned char app_data[4]; + struct { + unsigned char bit_rate_capability; + unsigned char protocol_type:4, + max_frame_size:4; + unsigned char fo:2, + adc:2, + fwi:4; + } protocol_info; +}; + +struct iso14443b_attrib_hdr { + unsigned char one_d; + unsigned char identifier[4]; + struct { + unsigned char rfu:2, + sof:1, + eof:1, + min_tr1:2, + min_tr0:2; + } param1; + struct { + unsigned char fsdi:4, + spd_out:2, + spd_in:2; + } param2; + struct { + unsigned char protocol_type:4, + rfu:4; + } param3; + struct { + unsigned char cid:4, + rfu:4; + } param4; +}; + +struct iso14443b_handle { + unsigned int tcl_capable; /* do we support T=CL */ + + unsigned int cid; /* Card ID */ + + unsigned int fsc; /* max. frame size card */ + unsigned int fsd; /* max. frame size reader */ + + unsigned int fwt; /* frame waiting time (in usec) */ + + unsigned int mbl; /* maximum buffer length */ + + unsigned int tr0; /* pcd-eof to picc-subcarrier-on */ + unsigned int tr1; /* picc-subcarrier-on to picc-sof */ + + unsigned int flags; + unsigned int state; +}; + +enum { + ISO14443B_CID_SUPPORTED = 0x01, + ISO14443B_NAD_SUPPORTED = 0x02, +}; + +enum { + ISO14443B_STATE_ERROR, + ISO14443B_STATE_NONE, + ISO14443B_STATE_REQB_SENT, + ISO14443B_STATE_ATQB_RCVD, + ISO14443B_STATE_ATTRIB_SENT, + ISO14443B_STATE_SELECTED, + ISO14443B_STATE_HLTB_SENT, + ISO14443B_STATE_HALTED, +}; + +#include <librfid/rfid_layer2.h> +struct rfid_layer2 rfid_layer2_iso14443b; + +#endif /* __LIBRFID__ */ + +#endif diff --git a/openpcd/firmware/include/librfid/rfid_layer2_iso15693.h b/openpcd/firmware/include/librfid/rfid_layer2_iso15693.h new file mode 100644 index 0000000..d91b4ec --- /dev/null +++ b/openpcd/firmware/include/librfid/rfid_layer2_iso15693.h @@ -0,0 +1,55 @@ +#ifndef _RFID_ISO15693_H +#define _RFID_ISO15693_H + +#include <sys/types.h> + +/* +07h = TagIt +04h = I.CODE +05h = Infineon +02h = ST +*/ + +/* protocol definitions */ + +struct iso15693_handle; + +struct iso15693_transport { + unsigned char *name; + + struct { + int (*init)(struct iso15693_handle *handle); + int (*fini)(struct iso15693_handle *handle); + +#if 0 + int (*transceive_sf)(struct iso14443a_handle *handle, + unsigned char cmd, + struct iso14443a_atqa *atqa); + int (*transceive_acf)(struct iso14443a_handle *handle, + struct iso14443a_anticol_cmd *acf, + unsigned int *bit_of_col); +#endif + int (*transceive)(struct iso15693_handle *handle, + const unsigned char *tx_buf, + unsigned int tx_len, + unsigned char *rx_buf, + unsigned int *rx_len); + } fn; + + union { + } priv; +}; + +struct iso15693_handle { + unsigned int state; +}; + +enum iso15693_state { + ISO15693_STATE_ERROR, + ISO15693_STATE_NONE, +}; + +#include <librfid/rfid_layer2.h> +extern struct rfid_layer2 rfid_layer2_iso15693; + +#endif /* _ISO15693_H */ diff --git a/openpcd/firmware/include/rfid_protocol_mifare_classic.h b/openpcd/firmware/include/librfid/rfid_protocol_mifare_classic.h index e6b2400..e6b2400 100644 --- a/openpcd/firmware/include/rfid_protocol_mifare_classic.h +++ b/openpcd/firmware/include/librfid/rfid_protocol_mifare_classic.h diff --git a/openpcd/firmware/src/dbgu.c b/openpcd/firmware/src/dbgu.c index 1b0ede0..a754f9e 100644 --- a/openpcd/firmware/src/dbgu.c +++ b/openpcd/firmware/src/dbgu.c @@ -15,10 +15,30 @@ // Include Standard files #include <board.h> +#include <interrupt_utils.h> #include "dbgu.h" #include "rc632.h" #include "openpcd.h" #include "led.h" +#include "main.h" + +const char * +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; +} + #define USART_SYS_LEVEL 4 /*---------------------------- Global Variable ------------------------------*/ //*--------------------------1-------------------------------------------------- @@ -53,7 +73,7 @@ static void Send_reset(void) //*---------------------------------------------------------------------------- static void DBGU_irq_handler(void) { - char value; + static char value; AT91F_DBGU_Get(&value); switch (value) { @@ -96,8 +116,11 @@ static void DBGU_irq_handler(void) case '7': rc632_dump(); break; + case '8': + break; default: - AT91F_DBGU_Printk("\n\r"); + if (_main_dbgu(value) < 0) + AT91F_DBGU_Printk("\n\r"); break; } // end switch } diff --git a/openpcd/firmware/src/dbgu.h b/openpcd/firmware/src/dbgu.h index 383e26d..8dd34be 100644 --- a/openpcd/firmware/src/dbgu.h +++ b/openpcd/firmware/src/dbgu.h @@ -21,6 +21,7 @@ //* ----------------------- External Function Prototype -----------------------
+extern const char *hexdump(const void *data, unsigned int len);
void AT91F_DBGU_Init(void);
void AT91F_DBGU_Printk( char *buffer);
void AT91F_DBGU_Frame( char *buffer);
diff --git a/openpcd/firmware/src/main.c b/openpcd/firmware/src/main.c index 384bad9..182964f 100644 --- a/openpcd/firmware/src/main.c +++ b/openpcd/firmware/src/main.c @@ -5,8 +5,6 @@ #include "led.h" #include "openpcd.h" -#define DEBUG_TOGGLE_LED - int main(void) { /* initialize LED and debug unit */ @@ -30,12 +28,6 @@ int main(void) DEBUGPCRF("entering main (idle) loop"); while (1) { -#ifdef DEBUG_TOGGLE_LED - /* toggle LEDs */ - led_toggle(1); - led_toggle(2); -#endif - /* Call application specific main idle function */ _main_func(); } diff --git a/openpcd/firmware/src/main.h b/openpcd/firmware/src/main.h new file mode 100644 index 0000000..1adc8f6 --- /dev/null +++ b/openpcd/firmware/src/main.h @@ -0,0 +1,8 @@ +#ifndef _MAIN_H +#define _MAIN_H + +extern void _init_func(void); +extern int _main_dbgu(char key); +extern void _main_func(void); + +#endif diff --git a/openpcd/firmware/src/main_analog.c b/openpcd/firmware/src/main_analog.c new file mode 100644 index 0000000..676e9fc --- /dev/null +++ b/openpcd/firmware/src/main_analog.c @@ -0,0 +1,77 @@ +/* main_reqa - OpenPCD firmware for generating an endless loop of + * ISO 14443-A REQA packets. + * + * If a response is received from the PICC, LED1 (Red) will be switched + * on. If no valid response has been received within the timeout of the + * receiver, LED1 (Red) will be switched off. + * + */ + +#include <errno.h> +#include <string.h> +#include <librfid/rfid_layer2_iso14443a.h> +#include "rc632.h" +#include "dbgu.h" +#include "led.h" +#include "trigger.h" +#include "pcd_enumerate.h" +#include "main.h" + +void _init_func(void) +{ + //udp_init(); + trigger_init(); + rc632_init(); + DEBUGPCRF("turning on RF"); + rc632_turn_on_rf(RAH); + /* FIXME: do we need this? */ + DEBUGPCRF("initializing 14443A operation"); + rc632_iso14443a_init(RAH); + /* Switch to 848kBps (1subcp / bit) */ + rc632_clear_bits(RAH, RC632_REG_RX_CONTROL1, RC632_RXCTRL1_SUBCP_MASK); +} + +int _main_dbgu(char key) +{ + static char ana_out_sel; + int ret = -EINVAL; + + switch (key) { + case 'q': + ana_out_sel--; + ret = 1; + break; + case 'w': + ana_out_sel++; + ret = 1; + break; + } + + if (ret == 1) { + ana_out_sel &= 0x0f; + DEBUGPCR("switching to analog output mode 0x%x\n", ana_out_sel); + rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel); + } + + return ret; +} + +void _main_func(void) +{ +#if 1 + struct iso14443a_atqa atqa; + + memset(&atqa, 0, sizeof(atqa)); + + trigger_pulse(); + + if (rc632_iso14443a_transceive_sf(RAH, ISO14443A_SF_CMD_WUPA, &atqa) < 0) { + DEBUGPCRF("error during transceive_sf"); + led_switch(1, 0); + } else { + DEBUGPCRF("received ATQA: %s\n", hexdump((char *)&atqa, sizeof(atqa))); + led_switch(1, 1); + } +#endif + led_toggle(2); +} diff --git a/openpcd/firmware/src/main_dumbreader.c b/openpcd/firmware/src/main_dumbreader.c index c165182..e59b4b6 100644 --- a/openpcd/firmware/src/main_dumbreader.c +++ b/openpcd/firmware/src/main_dumbreader.c @@ -7,6 +7,7 @@ #include "led.h" #include "pcd_enumerate.h" #include "openpcd.h" +#include "main.h" static int usb_in(struct req_ctx *rctx) { @@ -80,6 +81,11 @@ void _init_func(void) udp_init(); } +int _main_dbgu(char key) +{ + return -EINVAL; +} + void _main_func(void) { struct req_ctx *rctx; diff --git a/openpcd/firmware/src/main_reqa.c b/openpcd/firmware/src/main_reqa.c index 1c375c3..cd1f162 100644 --- a/openpcd/firmware/src/main_reqa.c +++ b/openpcd/firmware/src/main_reqa.c @@ -7,13 +7,14 @@ * */ +#include <errno.h> +#include <string.h> +#include <librfid/rfid_layer2_iso14443a.h> #include "rc632.h" #include "dbgu.h" #include "led.h" #include "trigger.h" #include "pcd_enumerate.h" -#include <rfid_layer2_iso14443a.h> -#include <string.h> void _init_func(void) { @@ -26,6 +27,10 @@ void _init_func(void) rc632_iso14443a_init(RAH); } +int _main_dbgu(char key) +{ + return -EINVAL; +} void _main_func(void) { @@ -38,8 +43,10 @@ void _main_func(void) if (rc632_iso14443a_transceive_sf(RAH, ISO14443A_SF_CMD_WUPA, &atqa) < 0) { DEBUGPCRF("error during transceive_sf"); led_switch(1, 0); - } else + } else { + DEBUGPCRF("received ATQA: %s\n", hexdump((char *)&atqa, sizeof(atqa))); led_switch(1, 1); + } led_toggle(2); } diff --git a/openpcd/firmware/src/pcd_enumerate.c b/openpcd/firmware/src/pcd_enumerate.c index 372ffa9..4dc096f 100644 --- a/openpcd/firmware/src/pcd_enumerate.c +++ b/openpcd/firmware/src/pcd_enumerate.c @@ -22,6 +22,7 @@ #include <usb_ch9.h> #include <lib_AT91SAM7.h> #include <openpcd.h> +#include <interrupt_utils.h> #include "pcd_enumerate.h" #include "openpcd.h" @@ -137,8 +138,6 @@ static void udp_irq(void) DEBUGP("udp_irq(imr=0x%04x, isr=0x%04x): ", pUDP->UDP_IMR, isr); - AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_UDP); - if (isr & AT91C_UDP_ENDBUSRES) { DEBUGP("ENDBUSRES "); pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES; @@ -229,6 +228,7 @@ static void udp_irq(void) } DEBUGP("END\r\n"); + AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_UDP); } /* Open USB Device Port */ diff --git a/openpcd/firmware/src/pio_irq.c b/openpcd/firmware/src/pio_irq.c index 3f73001..3e65561 100644 --- a/openpcd/firmware/src/pio_irq.c +++ b/openpcd/firmware/src/pio_irq.c @@ -1,4 +1,5 @@ +#include <interrupt_helper.h> #define NR_PIO 32 static u_int8_t ffs(u_int32_t in) diff --git a/openpcd/firmware/src/rc632.c b/openpcd/firmware/src/rc632.c index b2b434e..29cd622 100644 --- a/openpcd/firmware/src/rc632.c +++ b/openpcd/firmware/src/rc632.c @@ -10,9 +10,10 @@ #include <string.h> -#include <include/lib_AT91SAM7.h> -#include <include/cl_rc632.h> -#include <include/openpcd.h> +#include <lib_AT91SAM7.h> +#include <cl_rc632.h> +#include <openpcd.h> +#include <interrupt_utils.h> #include "openpcd.h" #include "fifo.h" #include "dbgu.h" @@ -22,13 +23,19 @@ #if 1 #define DEBUGPSPI DEBUGP #else -#define DEBUGPSPI(x, args ...) DEBUGP("") +#define DEBUGPSPI(x, args ...) #endif /* SPI driver */ -//#define SPI_DEBUG_LOOPBACK -//#define SPI_USES_DMA +#ifdef OLIMEX +#define SPI_DEBUG_LOOPBACK +#endif + +#define SPI_USES_DMA +#define SPI_DEBUG_LOOPBACK + +#define SPI_MAX_XFER_LEN 65 static AT91PS_SPI pSPI = AT91C_BASE_SPI; @@ -39,8 +46,6 @@ static void spi_irq(void) DEBUGPSPI("spi_irq: 0x%08x ", status); - AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SPI); - if (status & AT91C_SPI_OVRES) DEBUGPSPI("Overrun "); if (status & AT91C_SPI_MODF) @@ -55,30 +60,43 @@ static void spi_irq(void) } DEBUGPSPI("\r\n"); + + AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SPI); } #ifdef SPI_USES_DMA -int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, - u_int8_t *rx_data, u_int16_t *rx_len) +static int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, + u_int8_t *rx_data, u_int16_t *rx_len) { - DEBUGPSPI("spi_transcieve: Starting DMA Xfer: "); - AT91F_SPI_ReceiveFrame(pSPI, rx_data, *rx_len, NULL, 0); + //tx_len = *rx_len = 65; + DEBUGPSPI("DMA Xfer tx=%s\r\n", hexdump(tx_data, tx_len)); + if (*rx_len < tx_len) { + DEBUGPCRF("rx_len=%u smaller tx_len=%u\n", *rx_len, tx_len); + return -1; + } + //AT91F_SPI_Disable(pSPI); + + AT91F_SPI_ReceiveFrame(pSPI, rx_data, tx_len, NULL, 0); AT91F_SPI_SendFrame(pSPI, tx_data, tx_len, NULL, 0); + AT91F_PDC_EnableRx(AT91C_BASE_PDC_SPI); AT91F_PDC_EnableTx(AT91C_BASE_PDC_SPI); + pSPI->SPI_IER = AT91C_SPI_ENDTX|AT91C_SPI_ENDRX; - AT91F_SPI_Enable(pSPI); + //pSPI->SPI_IDR = AT91C_SPI_ENDTX|AT91C_SPI_ENDRX; - while (!(pSPI->SPI_SR & (AT91C_SPI_ENDRX|AT91C_SPI_ENDTX))) ; - DEBUGPSPI("DMA Xfer finished\r\n"); - AT91F_SPI_Disable(pSPI); + while (! (pSPI->SPI_SR & AT91C_SPI_ENDRX)) ; + + DEBUGPSPI("DMA Xfer finished rx=%s\r\n", hexdump(rx_data, tx_len)); + + *rx_len = tx_len; return 0; } #else /* stupid polling transceiver routine */ -int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, +static int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, u_int8_t *rx_data, u_int16_t *rx_len) { u_int16_t tx_cur = 0; @@ -95,7 +113,7 @@ int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, *rx_len = 0; } - AT91F_SPI_Enable(pSPI); + //AT91F_SPI_Enable(pSPI); while (1) { u_int32_t sr = pSPI->SPI_SR; u_int8_t tmp; @@ -112,7 +130,7 @@ int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, if (tx_cur >= tx_len && rx_cnt >= tx_len) break; } - AT91F_SPI_Disable(pSPI); + //AT91F_SPI_Disable(pSPI); if (rx_data) DEBUGPSPI("leave(%02x %02x)\r\n", rx_data[0], rx_data[1]); else @@ -130,8 +148,8 @@ int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, /* static buffers used by RC632 access primitives below. * Since we only have one */ -static u_int8_t spi_outbuf[64+1]; -static u_int8_t spi_inbuf[64+1]; +static u_int8_t spi_outbuf[SPI_MAX_XFER_LEN]; +static u_int8_t spi_inbuf[SPI_MAX_XFER_LEN]; #define FIFO_ADDR (RC632_REG_FIFO_DATA << 1) @@ -301,12 +319,14 @@ void rc632_power(u_int8_t up) void rc632_reset(void) { - int i; + volatile int i; rc632_power(0); for (i = 0; i < 0xfffff; i++) {} rc632_power(1); + for (i = 0; i < 0xfffff; i++) + {} /* turn off register paging */ rc632_reg_write(RAH, RC632_REG_PAGE0, 0x00); @@ -335,14 +355,17 @@ void rc632_init(void) #endif #ifdef SPI_DEBUG_LOOPBACK - AT91F_SPI_CfgMode(pSPI, AT91C_SPI_MSTR|AT91C_SPI_PS_FIXED|AT91C_SPI_LLB); + AT91F_SPI_CfgMode(pSPI, AT91C_SPI_MSTR|AT91C_SPI_PS_FIXED| + AT91C_SPI_MODFDIS|AT91C_SPI_LLB); #else - AT91F_SPI_CfgMode(pSPI, AT91C_SPI_MSTR|AT91C_SPI_PS_FIXED); + AT91F_SPI_CfgMode(pSPI, AT91C_SPI_MSTR|AT91C_SPI_PS_FIXED| + AT91C_SPI_MODFDIS); #endif /* CPOL = 0, NCPHA = 1, CSAAT = 0, BITS = 0000, SCBR = 10 (4.8MHz), * DLYBS = 0, DLYBCT = 0 */ //AT91F_SPI_CfgCs(pSPI, 0, AT91C_SPI_BITS_8|AT91C_SPI_NCPHA|(10<<8)); AT91F_SPI_CfgCs(pSPI, 0, AT91C_SPI_BITS_8|AT91C_SPI_NCPHA|(0x7f<<8)); + AT91F_SPI_Enable(pSPI); //AT91F_SPI_Reset(pSPI); @@ -350,9 +373,10 @@ void rc632_init(void) AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632, OPENPCD_IRQ_PRIO_RC632, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &rc632_irq); - AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_IRQ1); + AT91F_AIC_EnableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632); AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_RC632_RESET); + AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_MFIN); AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPCD_PIO_MFOUT); @@ -363,15 +387,19 @@ void rc632_init(void) irq_opcdh.len = 0x00; rc632_reset(); + + /* configure AUX to test signal four */ + rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, 0x04); }; +#if 0 void rc632_exit(void) { - AT91F_AIC_DisableIt(AT91C_BASE_AIC, AT91C_ID_IRQ1); + AT91F_AIC_DisableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632); AT91F_AIC_DisableIt(AT91C_BASE_AIC, AT91C_ID_SPI); AT91F_SPI_Disable(pSPI); } - +#endif #ifdef DEBUG static int rc632_reg_write_verify(struct rfid_asic_handle *hdl, @@ -387,30 +415,27 @@ static int rc632_reg_write_verify(struct rfid_asic_handle *hdl, return (val == tmp); } -static u_int8_t tx_buf[0x40+1]; -static u_int8_t rx_buf[0x40+1]; - int rc632_dump(void) { u_int8_t i; - u_int16_t rx_len = sizeof(rx_buf); + u_int16_t rx_len = sizeof(spi_inbuf); for (i = 0; i <= 0x3f; i++) { - tx_buf[i] = i << 1; - rx_buf[i] = 0x00; + spi_outbuf[i] = i << 1; + spi_inbuf[i] = 0x00; } /* MSB of first byte of read spi transfer is high */ - tx_buf[0] |= 0x80; + spi_outbuf[0] |= 0x80; /* last byte of read spi transfer is 0x00 */ - tx_buf[0x40] = 0x00; - rx_buf[0x40] = 0x00; + spi_outbuf[0x40] = 0x00; + spi_inbuf[0x40] = 0x00; - spi_transceive(tx_buf, 0x41, rx_buf, &rx_len); + spi_transceive(spi_outbuf, 0x41, spi_inbuf, &rx_len); for (i = 0; i < 0x3f; i++) - DEBUGPCR("REG 0x%02x = 0x%02x", i, rx_buf[i+1]); + DEBUGPCR("REG 0x%02x = 0x%02x", i, spi_inbuf[i+1]); return 0; } diff --git a/openpcd/firmware/src/rc632.h b/openpcd/firmware/src/rc632.h index ef5dfa7..7571012 100644 --- a/openpcd/firmware/src/rc632.h +++ b/openpcd/firmware/src/rc632.h @@ -3,7 +3,7 @@ #include <sys/types.h> #include <cl_rc632.h> -#include <rfid.h> +#include <librfid/rfid.h> extern int rc632_reg_write(struct rfid_asic_handle *hdl, u_int8_t addr, u_int8_t data); diff --git a/openpcd/firmware/src/rc632_highlevel.c b/openpcd/firmware/src/rc632_highlevel.c index 136447e..dbb638b 100644 --- a/openpcd/firmware/src/rc632_highlevel.c +++ b/openpcd/firmware/src/rc632_highlevel.c @@ -25,8 +25,8 @@ #include <cl_rc632.h> #include "rc632.h" #include "dbgu.h" -#include <rfid_layer2_iso14443a.h> -#include <rfid_protocol_mifare_classic.h> +#include <librfid/rfid_layer2_iso14443a.h> +#include <librfid/rfid_protocol_mifare_classic.h> /* initially we use the same values as cm5121 */ #define OPENPCD_CW_CONDUCTANCE 0x3f @@ -274,7 +274,7 @@ tcl_toggle_pcb(struct rfid_asic_handle *handle) return 0; } -static int +int rc632_transceive(struct rfid_asic_handle *handle, const u_int8_t *tx_buf, u_int8_t tx_len, @@ -861,9 +861,9 @@ static struct tx_config tx_configs[] = { }, }; -static int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle, - unsigned int tx, - u_int8_t rate) +int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle, + unsigned int tx, + u_int8_t rate) { int rc; u_int8_t reg; diff --git a/openpcd/firmware/src/rfid_layer2_iso14443a.c b/openpcd/firmware/src/rfid_layer2_iso14443a.c new file mode 100644 index 0000000..7d99dc9 --- /dev/null +++ b/openpcd/firmware/src/rfid_layer2_iso14443a.c @@ -0,0 +1,316 @@ +/* ISO 14443-3 A anticollision implementation + * + * (C) 2005 by Harald Welte <laforge@gnumonks.org> + * + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <librfid/rfid.h> +#include <librfid/rfid_layer2.h> +//#include <librfid/rfid_reader.h> +#include <librfid/rfid_layer2_iso14443a.h> + +#define TIMEOUT 1236 + +/* Transceive a 7-bit short frame */ +static int +iso14443a_transceive_sf(struct rfid_layer2_handle *handle, + unsigned char cmd, + struct iso14443a_atqa *atqa) +{ + //struct rfid_reader *rdr = handle->rh->reader; + + return rc632_iso14443a_transceive_sf(handle->rh, cmd, atqa); +} + +/* Transmit an anticollission bit frame */ +static int +iso14443a_transceive_acf(struct rfid_layer2_handle *handle, + struct iso14443a_anticol_cmd *acf, + unsigned int *bit_of_col) +{ + //struct rfid_reader *rdr = handle->rh->reader; + + return rc632_iso14443a_transceive_acf(handle->rh, acf, bit_of_col); +} + +/* Transmit a regular frame */ +static int +iso14443a_transceive(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 rc632_transceive(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_transceive_sf(handle, ISO14443A_SF_CMD_REQA, &atqa); + if (ret < 0) { + h->state = ISO14443A_STATE_REQA_SENT; + DEBUGP("error during transceive_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_transceive_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_transceive_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_transceive(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_transceive(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 int +iso14443a_setopt(struct rfid_layer2_handle *handle, int optname, + const void *optval, unsigned int optlen) +{ + int ret = -EINVAL; + unsigned int speed; + + switch (optname) { + case RFID_OPT_14443A_SPEED_RX: + speed = *(unsigned int *)optval; + ret = rc632_iso14443a_set_speed(handle->rh, 0, speed); + break; + case RFID_OPT_14443A_SPEED_TX: + speed = *(unsigned int *)optval; + ret = rc632_iso14443a_set_speed(handle->rh, 1, speed); + break; + }; + + return ret; +} + + +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 = rc632_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, + .transceive = &iso14443a_transceive, + .close = &iso14443a_hlta, + .fini = &iso14443a_fini, + .setopt = &iso14443a_setopt, + }, +}; diff --git a/openpcd/firmware/src/start/Cstartup.S b/openpcd/firmware/src/start/Cstartup.S index d13dbd8..785a18c 100644 --- a/openpcd/firmware/src/start/Cstartup.S +++ b/openpcd/firmware/src/start/Cstartup.S @@ -16,7 +16,7 @@ //*- 1.1 01/Apr/05 JPP : save SPSR //*-----------------------------------------------------------------------------*/ - .equ IRQ_Stack_Size, 0x00000060 + .equ IRQ_Stack_Size, 0x00000400 /* #include "AT91SAM7S64_inc.h" */ |