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"	  */ | 
