diff options
| -rw-r--r-- | openpicc/Makefile | 1 | ||||
| -rw-r--r-- | openpicc/application/cmd.c | 7 | ||||
| -rw-r--r-- | openpicc/application/main.c | 10 | ||||
| -rw-r--r-- | openpicc/application/ssc.c | 3 | ||||
| -rw-r--r-- | openpicc/application/tc_sniffer.c | 143 | ||||
| -rw-r--r-- | openpicc/application/tc_sniffer.h | 7 | ||||
| -rw-r--r-- | openpicc/application/usb_print.c | 11 | ||||
| -rw-r--r-- | openpicc/application/usb_print.h | 1 | ||||
| -rw-r--r-- | openpicc/os/boot/boot.s | 150 | ||||
| -rw-r--r-- | openpicc/os/usb/USB-CDC.c | 13 | ||||
| -rw-r--r-- | openpicc/os/usb/USB-CDC.h | 1 | 
11 files changed, 228 insertions, 119 deletions
diff --git a/openpicc/Makefile b/openpicc/Makefile index 25ee436..d826582 100644 --- a/openpicc/Makefile +++ b/openpicc/Makefile @@ -96,6 +96,7 @@ ARM_SRC= \    application/decoder_miller.c \    application/decoder_nrzl.c \    application/decoder.c \ +  application/tc_sniffer.c \    os/boot/Cstartup_SAM7.c \    os/core/list.c \    os/core/queue.c \ diff --git a/openpicc/application/cmd.c b/openpicc/application/cmd.c index 47bbec5..50b59d3 100644 --- a/openpicc/application/cmd.c +++ b/openpicc/application/cmd.c @@ -21,6 +21,7 @@  #include "ssc.h"  #include "usb_print.h"  #include "load_modulation.h" +#include "tc_sniffer.h"  xQueueHandle xCmdQueue;  xTaskHandle xCmdTask; @@ -45,7 +46,7 @@ static const portBASE_TYPE USE_COLON_FOR_LONG_COMMANDS = 0;  /* When not USE_COLON_FOR_LONG_COMMANDS then short commands will be recognized by including   * their character in the string SHORT_COMMANDS   * */ -static const char *SHORT_COMMANDS = "!pc+-l?hq9fjka#i"; +static const char *SHORT_COMMANDS = "!prc+-l?hq9fjka#i";  /* Note that the long/short command distinction only applies to the USB serial console   * */ @@ -241,6 +242,9 @@ void prvExecCommand(u_int32_t cmd, portCHAR *args) {  		case 'P':  		    print_pio();  		    break; +		case 'R': +			start_stop_sniffing(); +			break;  		case 'C':  		    DumpStringToUSB(  			" *****************************************************\n\r" @@ -442,6 +446,7 @@ void prvExecCommand(u_int32_t cmd, portCHAR *args) {  		    " * #    - switch clock\n\r"  			" * l    - cycle LEDs\n\r"  			" * p    - print PIO pins\n\r" +		    " * r    - start/stop receiving\n\r"  			" * z 0/1- enable or disable tc_cdiv_sync\n\r"  			" * i    - inhibit/uninhibit PLL\n\r"  			" * !    - reset tc_cdiv_sync\n\r" diff --git a/openpicc/application/main.c b/openpicc/application/main.c index 2397c61..9b81aea 100644 --- a/openpicc/application/main.c +++ b/openpicc/application/main.c @@ -51,6 +51,7 @@  #include "iso14443_sniffer.h"  #include "iso14443a_pretender.h"  #include "decoder.h" +#include "tc_sniffer.h"  static inline int detect_board(void)  { @@ -210,9 +211,12 @@ int main (void)  	NULL, TASK_ISO_PRIORITY, NULL);*/      /*xTaskCreate (iso14443_sniffer, (signed portCHAR *) "ISO14443-SNIFF", TASK_ISO_STACK,  	NULL, TASK_ISO_PRIORITY, NULL);*/ -    xTaskCreate (iso14443a_pretender, (signed portCHAR *) "ISO14443A-PRETEND", TASK_ISO_STACK, -	NULL, TASK_ISO_PRIORITY, NULL); -     +    /*xTaskCreate (iso14443a_pretender, (signed portCHAR *) "ISO14443A-PRETEND", TASK_ISO_STACK, +	NULL, TASK_ISO_PRIORITY, NULL);*/ +    xTaskCreate (tc_sniffer, (signed portCHAR *) "RFID-SNIFFER", TASK_ISO_STACK, +		 	NULL, TASK_ISO_PRIORITY, NULL); + +	          xTaskCreate (vUSBCDCTask, (signed portCHAR *) "USB", TASK_USB_STACK,  	NULL, TASK_USB_PRIORITY, NULL); diff --git a/openpicc/application/ssc.c b/openpicc/application/ssc.c index 50d416b..a490d42 100644 --- a/openpicc/application/ssc.c +++ b/openpicc/application/ssc.c @@ -43,9 +43,6 @@  #define PRINT_DEBUG 0 -// BROKEN Old FIQ code -int ssc_tx_pending=0, ssc_tx_fiq_fdt_cdiv=0, ssc_tx_fiq_fdt_ssc=0; -  struct _ssc_handle {  	enum ssc_mode mode;  	const struct openpicc_hardware *openpicc; diff --git a/openpicc/application/tc_sniffer.c b/openpicc/application/tc_sniffer.c new file mode 100644 index 0000000..abf04c0 --- /dev/null +++ b/openpicc/application/tc_sniffer.c @@ -0,0 +1,143 @@ +/*************************************************************** + * + * OpenPICC - T/C based dumb sniffer + *  + * TC2 will reset its value on each falling edge of SSC_DATA, we + * will have the FIQ store the TC2 value on each rising edge of + * SSC_DATA. This will give us a count of carrier cycles between + * modulation pauses which should be enough information to decode + * the modified miller encoding. + * + * Copyright 2008 Henryk Plötz <henryk@ploetzli.ch> + * + *************************************************************** + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; version 2. + +    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., +    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +*/ + +#include <FreeRTOS.h> +#include <openpicc.h> +#include <task.h> +#include <string.h> + +#include <USB-CDC.h> + +#include "tc_sniffer.h" +#include "load_modulation.h" +#include "pll.h" +#include "tc_fdt.h" +#include "usb_print.h" +#include "cmd.h" +#include "pio_irq.h" + +/* Problem: We want to receive data from the FIQ without locking (the FIQ must not be blocked ever) + * Strategy: Double buffering. + */ + +#define BUFSIZE 1024 +#define WAIT_TICKS (20*portTICK_RATE_MS) +typedef struct { +	u_int32_t count; +	u_int32_t data[BUFSIZE]; +} fiq_buffer_t; +fiq_buffer_t fiq_buffers[2]; + +fiq_buffer_t *tc_sniffer_next_buffer_for_fiq = 0; + +portBASE_TYPE currently_sniffing = 0; +enum { NONE, REQUEST_START, REQUEST_STOP } request_change = NONE; + +#define MIN(a, b) ((a)>(b)?(b):(a)) +void flush_buffer(fiq_buffer_t *buffer) +{ +	/* Write all data from the given buffer out, then zero the count */ +	if(buffer->count > 0) { +		vUSBSendBuffer_blocking((unsigned char*)(&(buffer->data[0])), 0, MIN(buffer->count,BUFSIZE)*4, WAIT_TICKS); +		if(buffer->count >= BUFSIZE) +			vUSBSendBuffer_blocking((unsigned char*)"////", 0, 4, WAIT_TICKS); +		else +			vUSBSendBuffer_blocking((unsigned char*)"____", 0, 4, WAIT_TICKS); +		buffer->count = 0; +	} +} + +void start_stop_sniffing(void) +{ +	if(currently_sniffing) +		request_change = REQUEST_STOP; +	else +		request_change = REQUEST_START; +} + +void tc_sniffer (void *pvParameters) +{ +	(void)pvParameters; +	 +	/* Disable load modulation circuitry +	 * (Must be done explicitly, because the default state is pull-up high, leading +	 * to a constant modulation output which prevents reception. I've been bitten by +	 * this more than once.) +	 */ +	load_mod_init(); +	load_mod_level(0); +	 +	pll_init(); +	pll_inhibit(0); +	 +	tc_fdt_init(); +	 +	memset(fiq_buffers, 0, sizeof(fiq_buffers)); +	 +	/* Wait for the USB and CMD threads to start up */ +	vTaskDelay(1000 * portTICK_RATE_MS); +	 +	// The change interrupt is going to be handled by the FIQ  +	AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_SSC_DATA); +	pio_irq_enable(OPENPICC_SSC_DATA); +	 +	int current = 0; +	while(1) { +		/* Main loop of the sniffer */ +		 +		if(currently_sniffing) { +			int next = (current+1)%(sizeof(fiq_buffers)/sizeof(fiq_buffers[0])); +			flush_buffer( &fiq_buffers[next] ); +			/* The buffer designated by next is now empty, give it to the fiq, +			 * we'll just guess that this write is atomic */  +			tc_sniffer_next_buffer_for_fiq = &fiq_buffers[current=next]; + +			if(request_change == REQUEST_STOP) { +				currently_sniffing = 0; +				request_change = NONE; +				 +				tc_sniffer_next_buffer_for_fiq = 0; +				memset(fiq_buffers, 0, sizeof(fiq_buffers)); +				current = 0; +				vUSBSendBuffer_blocking((unsigned char *)"----", 0, 4, WAIT_TICKS); +				usb_print_set_force_silence(0); +			} else vTaskDelay(2* portTICK_RATE_MS); +		} else { +			// Do nothing, wait longer +			 +			if(request_change == REQUEST_START) { +				// Prevent usb_print code from barging in +				usb_print_set_force_silence(1); +				vUSBSendBuffer_blocking((unsigned char *)"----", 0, 4, WAIT_TICKS); +				currently_sniffing = 1; +				request_change = NONE; +			} else vTaskDelay(100 * portTICK_RATE_MS); +		} +	} +} diff --git a/openpicc/application/tc_sniffer.h b/openpicc/application/tc_sniffer.h new file mode 100644 index 0000000..e3a1c29 --- /dev/null +++ b/openpicc/application/tc_sniffer.h @@ -0,0 +1,7 @@ +#ifndef TC_SNIFFER_H_ +#define TC_SNIFFER_H_ + +extern void tc_sniffer (void *pvParameters); +extern void start_stop_sniffing (void); + +#endif /*TC_SNIFFER_H_*/ diff --git a/openpicc/application/usb_print.c b/openpicc/application/usb_print.c index 5ff42b8..5e4372b 100644 --- a/openpicc/application/usb_print.c +++ b/openpicc/application/usb_print.c @@ -29,7 +29,7 @@  static char ringbuffer[BUFLEN];  static int ringstart, ringstop; -static int default_flush = 1; +static int default_flush = 1, forced_silence = 0;  static xSemaphoreHandle print_semaphore;  void usb_print_buffer(const char* buffer, int start, int stop) { @@ -92,11 +92,20 @@ int usb_print_set_default_flush(int flush)  	return old_flush;  } +int usb_print_set_force_silence(int silence) +{ +	int old_silence = forced_silence; +	forced_silence = silence; +	return old_silence; +} +  /* Must NOT be called from ISR context */  void usb_print_flush(void)  {  	int oldstop, newstart; +	if(forced_silence) return; +	  	taskENTER_CRITICAL();  	if(print_semaphore == NULL)  		usb_print_init(); diff --git a/openpicc/application/usb_print.h b/openpicc/application/usb_print.h index 9186dc9..0497146 100644 --- a/openpicc/application/usb_print.h +++ b/openpicc/application/usb_print.h @@ -10,6 +10,7 @@ extern int usb_print_char_f(const char c, int flush);  extern void usb_print_flush(void);  extern int usb_print_get_default_flush(void);  extern int usb_print_set_default_flush(int flush); +extern int usb_print_set_force_silence(int silence);  extern void usb_print_init(void);  #endif /*USB_PRINT_H_*/ diff --git a/openpicc/os/boot/boot.s b/openpicc/os/boot/boot.s index d9ac156..4fca262 100644 --- a/openpicc/os/boot/boot.s +++ b/openpicc/os/boot/boot.s @@ -4,9 +4,7 @@  	.extern exit  	.extern AT91F_LowLevelInit  	.extern pio_irq_isr_value -	.extern ssc_tx_pending -	.extern ssc_tx_fiq_fdt_cdiv -	.extern ssc_tx_fiq_fdt_ssc +	.extern tc_sniffer_next_buffer_for_fiq  	.text  	.code 32 @@ -47,15 +45,14 @@  .equ AT91C_BASE_MC,   (0xFFFFFF00)  .equ AT91C_BASE_PIOA, 0xFFFFF400  .equ AT91C_BASE_TC0,  0xFFFA0000 +.equ AT91C_BASE_TC2,  0xFFFA0080  .equ AT91C_BASE_SSC,  0xFFFD4000  .equ SSC_CR,          0x0  .equ SSC_RCMR,        0x10  .equ SSC_CR_TXEN,     0x100  .equ AT91C_TC_SWTRG,  ((1 << 2)|1)  .equ AT91C_TC_CLKEN,  (1 << 0) -.equ PIO_DATA,        (1 << 27) -.equ PIO_FRAME,       (1 << 20) -.equ PIO_SSC_TF,      (1 << 15) +.equ PIO_DATA,        (1 << 18)  .equ PIOA_SODR,       0x30  .equ PIOA_CODR,       0x34  .equ PIOA_PDSR,       0x3c @@ -71,6 +68,8 @@  .equ PIO_SECONDARY_IRQ, 31  .equ PIO_SECONDARY_IRQ_BIT, (1 << PIO_SECONDARY_IRQ) +.equ BUFSIZE, 1024 +  start:  _start:  _mainCRTStartup: @@ -90,7 +89,6 @@ _mainCRTStartup:      ldr     r10, =AT91C_BASE_PIOA      ldr     r12, =AT91C_BASE_TC0      ldr     r8, =AT91C_BASE_AIC -    mov     r9, #AT91C_TC_SWTRG      /*ldr     r9, =AT91C_BASE_SSC*/      mov   sp, r0      sub   r0, r0, #FIQ_STACK_SIZE @@ -196,7 +194,7 @@ endless_loop:  my_fiq_handler:                  /* code that uses pre-initialized FIQ reg */                  /* r8   tmp -                   r9   AT91C_TC_SWTRG +                   r9   tmp                     r10  AT91C_BASE_PIOA                     r11  tmp                     r12  AT91C_BASE_TC0 @@ -215,111 +213,47 @@ my_fiq_handler:                  str   r8, [r11]                  tst     r8, #PIO_DATA           /* check for PIO_DATA change */ -                ldrne   r11, [r10, #PIOA_PDSR] -                tstne   r11, #PIO_DATA          /* check for PIO_DATA == 1 */ -                /*strne   r9, [r12, #TC_CCR]      /* software trigger */ - -                movne   r11, #PIO_DATA -                strne   r11, [r10, #PIOA_IDR]   /* disable further PIO_DATA FIQ */ -                beq .no_pio_data -/* .loop_high: -				ldr     r11, [r10, #PIOA_PDSR] -				tst     r11, #PIO_DATA -				bne     .loop_high -                str   r9, [r12, #TC_CCR]      /* software trigger */ - -.no_pio_data: -                tst     r8, #PIO_SSC_TF         /* check for SSC Transmit Frame signal */ -                ldrne   r11, [r10, #PIOA_PDSR] -                tstne   r11, #PIO_SSC_TF        /* check for SSC_TF == 1 */ -                 -                movne   r11, #PIO_SSC_TF -                strne   r11, [r10, #PIOA_IDR]   /* disable further SSC_TF FIQ */ -                 -                ldrne   r11, =ssc_tx_pending -                ldrne   r8, [r11] -                tstne   r8, #0x01              /* Check whether a TX is pending */ -                beq     .no_ssc -                b .no_ssc +                beq     .no_buffer -                mov   r8, #PIO_LED1 -                str   r8, [r10, #PIOA_SODR] /* disable LED */ +                ldr   r11, [r10, #PIOA_PDSR] +                tst   r11, #PIO_DATA          /* check for PIO_DATA == 1 */ +                beq   .no_buffer + +/*                mov     r11, #PIO_LED2 +                str     r11, [r10, #PIOA_CODR] /* enable LED */ + +                /* Load the TC2.CV into r9 */ +                ldr r9, [r12, #TC2_CV] -                mov   r8, #0x00 -                str   r8, [r11]                /* Set ssc_tx_pending to 0 */ +                ldr r11, =tc_sniffer_next_buffer_for_fiq +                ldr r11, [r11] +                /* r11 now contains the value of tc_sniffer_next_buffer_for_fiq, e.q. the address +                 * of the next buffer */ -                ldr   r11, =ssc_tx_fiq_fdt_cdiv -                ldr   r11, [r11]               /* r11 == ssc_tx_fiq_fdt_cdiv */ - -/* Problem: LDR from the timer and loop still take too long and cause us to miss the exact time. - * (One load-from-timer,compare,jump-back-if-less cycle are 7 CPU cycles, which are 2 carrier cycles.) - * Strategy: Spin on TC2 till 3 or 4 carrier cycles before the actual time. Then go into an unrolled - * 'loop' for the remaining time. (load-from-timer,compare,jump-forward-if-greater-or-equal are 5 CPU  - * cycles if the condition is not reached.) - *  - * At 47.923200 MHz 7 processor cycles are 2 carrier cycles of the 13.56MHz carrier - */ - .equ SUB_TIME, 4 /* subtract 4 carrier cycles == 14 processor cycles */ -  - 				mov r8, #SUB_TIME - 				sub r11, r11, r8              /* r11 == fdt_cdiv-SUB_TIME */ - -.wait_for_fdt_cdiv: -				ldr   r8, [r12, #TC2_CV] -				cmp   r8, r11 -				blt   .wait_for_fdt_cdiv       /* spin while TC2.CV is less fdt_cdiv-SUB_TIME */ -				 -				mov r8, #SUB_TIME -				add r11, r11, r8               /* r11 == fdt_cdiv */ - -/* Seven copies of the loop contents, covering for 35 CPU cycles, or 10 carrier cycles */ -				ldr   r8, [r12, #TC2_CV] -				cmp   r8, r11 -				bge   .fdt_expired             /* jump forward if TC2.CV is greater than or equal fdt_cdiv */ - -				ldr   r8, [r12, #TC2_CV] -				cmp   r8, r11 -				bge   .fdt_expired              - -				ldr   r8, [r12, #TC2_CV] -				cmp   r8, r11 -				bge   .fdt_expired              - -				ldr   r8, [r12, #TC2_CV] -				cmp   r8, r11 -				bge   .fdt_expired              - -				ldr   r8, [r12, #TC2_CV] -				cmp   r8, r11 -				bge   .fdt_expired              - -				ldr   r8, [r12, #TC2_CV] -				cmp   r8, r11 -				bge   .fdt_expired              - -				ldr   r8, [r12, #TC2_CV] -				cmp   r8, r11 -				bge   .fdt_expired              - -.fdt_expired:				 -				str   r9, [r12, #TC_CCR]       /* SWTRG on TC0 */ -				 -                ldr   r11, =ssc_tx_fiq_fdt_ssc -                ldr   r11, [r11]               /* r11 == ssc_tx_fiq_fdt_ssc */ - -.wait_for_fdt_ssc: -				ldr   r8, [r12, #TC2_CV] -				cmp   r8, r11 -				bmi   .wait_for_fdt_ssc        /* spin while TC2.CV is less fdt_ssc */ +                /* Jump to .no_buffer if the pointer is 0, indicating that no buffer is set */ +                cmp r11, #0 +                beq .no_buffer  -                mov   r11, #PIO_LED1 -                str   r11, [r10, #PIOA_CODR] /* enable LED */ +		/* Increment the value at the location the pointer points to */ +		ldr r8, [r11] +		add r8, r8, #1 +		str r8, [r11] +		 +		/* At this point: +		   r8  = count +		   r9  = TC2.CV +		   r11 = pointer to buffer +		 */ +		 +		cmp r8, #BUFSIZE +		bge .no_buffer +		 +		str r9, [r11, r8, LSL #2] +		 +.no_buffer: +/*                mov     r11, #PIO_LED2 +                str     r11, [r10, #PIOA_SODR] /* disable LED */ -                ldr   r11, =AT91C_BASE_SSC -                mov   r8, #SSC_CR_TXEN -                str   r8, [r11, #SSC_CR]       /* Write TXEN to SSC_CR, enables tx */  - -.no_ssc:                                 /* Trigger PIO_SECONDARY_IRQ */                  mov r11, #PIO_SECONDARY_IRQ_BIT                  ldr r8, =AT91C_BASE_AIC diff --git a/openpicc/os/usb/USB-CDC.c b/openpicc/os/usb/USB-CDC.c index 1b840c9..c005597 100644 --- a/openpicc/os/usb/USB-CDC.c +++ b/openpicc/os/usb/USB-CDC.c @@ -123,7 +123,7 @@ transmitted.  Rx queue must be larger than FIFO size. */  static xQueueHandle xRxCDC;  static xQueueHandle xTxCDC; -#define CHUNK_SIZE 8 +#define CHUNK_SIZE 9  /* Line coding - 115,200 baud, N-8-1 */  static const unsigned portCHAR pxLineCoding[] = @@ -277,7 +277,7 @@ vUSBSendByte_blocking (portCHAR cByte, portTickType xTicksToWait)  #define MIN(a,b) ((a)>(b)?(b):(a))  void -vUSBSendBuffer (unsigned char *buffer, portBASE_TYPE offset, portBASE_TYPE length) +vUSBSendBuffer_blocking (unsigned char *buffer, portBASE_TYPE offset, portBASE_TYPE length, portTickType xTicksToWait)  {  	unsigned char chunk[CHUNK_SIZE];  	while(length > 0) { @@ -285,12 +285,19 @@ vUSBSendBuffer (unsigned char *buffer, portBASE_TYPE offset, portBASE_TYPE lengt  		chunk[0] = next_size;  		memcpy(chunk+1, buffer+offset, next_size);  		/* Queue the bytes to be sent.  The USB task will send it. */ -		xQueueSend (xTxCDC, &chunk, usbNO_BLOCK); +		xQueueSend (xTxCDC, &chunk, xTicksToWait);  		length -= next_size;  		offset += next_size;  	}  } +void +vUSBSendBuffer (unsigned char *buffer, portBASE_TYPE offset, portBASE_TYPE length) +{ +	vUSBSendBuffer_blocking(buffer, offset, length, usbNO_BLOCK); +} + +  /*------------------------------------------------------------*/  portLONG diff --git a/openpicc/os/usb/USB-CDC.h b/openpicc/os/usb/USB-CDC.h index 6074956..6c0a779 100644 --- a/openpicc/os/usb/USB-CDC.h +++ b/openpicc/os/usb/USB-CDC.h @@ -84,6 +84,7 @@ sent unless the port is connected. */  void vUSBSendByte (portCHAR cByte);  void vUSBSendByte_blocking (portCHAR cByte, portTickType xTicksToWait);  void vUSBSendBuffer (unsigned char *buffer, portBASE_TYPE offset, portBASE_TYPE length); +void vUSBSendBuffer_blocking (unsigned char *buffer, portBASE_TYPE offset, portBASE_TYPE length, portTickType xTicksToWait);  portLONG vUSBRecvByte (portCHAR *cByte,portLONG size, portTickType xTicksToWait);  #endif  | 
