summaryrefslogtreecommitdiff
path: root/openpicc
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc')
-rw-r--r--openpicc/Makefile1
-rw-r--r--openpicc/application/cmd.c7
-rw-r--r--openpicc/application/main.c10
-rw-r--r--openpicc/application/ssc.c3
-rw-r--r--openpicc/application/tc_sniffer.c143
-rw-r--r--openpicc/application/tc_sniffer.h7
-rw-r--r--openpicc/application/usb_print.c11
-rw-r--r--openpicc/application/usb_print.h1
-rw-r--r--openpicc/os/boot/boot.s150
-rw-r--r--openpicc/os/usb/USB-CDC.c13
-rw-r--r--openpicc/os/usb/USB-CDC.h1
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
personal git repositories of Harald Welte. Your mileage may vary