Project

General

Profile

Download (7.25 KB) Statistics
| Branch: | Tag: | Revision:
1
/***************************************************************
2
 *
3
 * OpenPICC - T/C based dumb sniffer
4
 * 
5
 * TC2 will reset its value on each falling edge of SSC_DATA, we
6
 * will have the FIQ store the TC2 value on each rising edge of
7
 * SSC_DATA. This will give us a count of carrier cycles between
8
 * modulation pauses which should be enough information to decode
9
 * the modified miller encoding.
10
 *
11
 * Copyright 2008 Henryk Plötz <henryk@ploetzli.ch>
12
 *
13
 ***************************************************************
14

    
15
    This program is free software; you can redistribute it and/or modify
16
    it under the terms of the GNU General Public License as published by
17
    the Free Software Foundation; version 2.
18

    
19
    This program is distributed in the hope that it will be useful,
20
    but WITHOUT ANY WARRANTY; without even the implied warranty of
21
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
    GNU General Public License for more details.
23

    
24
    You should have received a copy of the GNU General Public License along
25
    with this program; if not, write to the Free Software Foundation, Inc.,
26
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27

    
28
*/
29

    
30
#include <FreeRTOS.h>
31
#include <openpicc.h>
32
#include <task.h>
33
#include <semphr.h>
34
#include <string.h>
35

    
36
#include <USB-CDC.h>
37

    
38
#include "tc_sniffer.h"
39
#include "load_modulation.h"
40
#include "pll.h"
41
#include "tc_fdt.h"
42
#include "usb_print.h"
43
#include "cmd.h"
44
#include "pio_irq.h"
45
#include "led.h"
46
#include "clock_switch.h"
47
#include "performance.h"
48

    
49
#include "iso14443a_diffmiller.h"
50

    
51
/* Problem: We want to receive data from the FIQ without locking (the FIQ must not be blocked ever)
52
 * Strategy: Double buffering.
53
 */
54

    
55
static xSemaphoreHandle data_semaphore;
56
struct diffmiller_state *decoder;
57
iso14443_frame rx_frame;
58

    
59
#define WAIT_TICKS (20*portTICK_RATE_MS)
60

    
61
portBASE_TYPE currently_sniffing = 0;
62
enum { NONE, REQUEST_START, REQUEST_STOP } request_change = REQUEST_START;
63

    
64
//#define PRINT_TIMES
65
//#define USE_BINARY_PROTOCOL
66

    
67
#define MIN(a, b) ((a)>(b)?(b):(a))
68
static int overruns = 0; 
69
static void handle_buffer(u_int32_t data[], unsigned int count)
70
{
71
#ifdef USE_BINARY_PROTOCOL
72
		vUSBSendBuffer_blocking((unsigned char*)(&data[0]), 0, MIN(count,BUFSIZE)*4, WAIT_TICKS);
73
		if(count >= BUFSIZE)
74
			vUSBSendBuffer_blocking((unsigned char*)"////", 0, 4, WAIT_TICKS);
75
		else
76
			vUSBSendBuffer_blocking((unsigned char*)"____", 0, 4, WAIT_TICKS);
77
#elif defined(PRINT_TIMES)
78
		unsigned int i=0;
79
		for(i=0; i<count; i++) {
80
			DumpUIntToUSB(data[i]);
81
			DumpStringToUSB(" ");
82
		}
83
		DumpStringToUSB("\n\r");
84
#else
85
		unsigned int offset = 0;
86
		while(offset < count) {
87
			int ret = iso14443a_decode_diffmiller(decoder, &rx_frame, data, &offset, count);
88
			/*
89
			DumpStringToUSB("\n\r");
90
			if(ret < 0) {
91
				DumpStringToUSB("-");
92
				DumpUIntToUSB(-ret);
93
			} else {
94
				DumpUIntToUSB(ret);
95
			}
96
			DumpStringToUSB(" ");
97
			DumpUIntToUSB(offset); DumpStringToUSB(" "); DumpUIntToUSB(count); DumpStringToUSB(" "); DumpUIntToUSB(overruns);
98
			DumpStringToUSB("\n\r");
99
			if(ret >= 0) {
100
				DumpStringToUSB("Frame finished, ");
101
				DumpUIntToUSB(rx_frame.numbytes);
102
				DumpStringToUSB(" bytes, ");
103
				DumpUIntToUSB(rx_frame.numbits);
104
				DumpStringToUSB(" bits\n\r");
105
				switch(rx_frame.parameters.a.crc) {
106
				case CRC_OK: DumpStringToUSB("CRC OK\n\r"); break;
107
				case CRC_ERROR: DumpStringToUSB("CRC ERROR\n\r"); break;
108
				case CRC_UNCALCULATED: DumpStringToUSB("CRC UNCALCULATED\n\r"); break;
109
				}
110
			}*/
111
			(void)ret;
112
		}
113
#endif
114
}
115

    
116
void flush_buffer(fiq_buffer_t *buffer)
117
{
118
	/* Write all data from the given buffer out, then zero the count */
119
	if(buffer->count > 0) {
120
		if(buffer->count >= BUFSIZE) {
121
			DumpStringToUSB("Warning: Possible buffer overrun detected\n\r");
122
			overruns++;
123
		}
124
		buffer->count = MIN(buffer->count, BUFSIZE);
125
		handle_buffer(buffer->data, buffer->count);
126
		buffer->count = 0;
127
	}
128
}
129

    
130
void start_stop_sniffing(void)
131
{
132
	if(currently_sniffing)
133
		request_change = REQUEST_STOP;
134
	else
135
		request_change = REQUEST_START;
136
}
137

    
138
static portBASE_TYPE tc_sniffer_irq(u_int32_t pio, portBASE_TYPE xTaskWoken)
139
{
140
	(void)pio;
141
	usb_print_string_f("?", 0);
142
	xTaskWoken = xSemaphoreGiveFromISR(data_semaphore, xTaskWoken);
143
	return xTaskWoken;
144
}
145

    
146
static void main_loop(void)
147
{
148
	int current = 0;
149
	
150
	while(1) {
151
		/* Main loop of the sniffer */
152
		//vTaskDelay(1000 * portTICK_RATE_MS);
153
		
154
			u_int32_t start = *AT91C_TC2_CV;
155
			int next = (current+1)%(sizeof(fiq_buffers)/sizeof(fiq_buffers[0]));
156
			flush_buffer( &fiq_buffers[next] );
157
			/* The buffer designated by next is now empty, give it to the fiq,
158
			 * we'll just guess that this write is atomic */ 
159
			tc_sniffer_next_buffer_for_fiq = &fiq_buffers[current=next];
160
			u_int32_t stop = *AT91C_TC2_CV;
161
			
162
			DumpStringToUSB("{"); DumpUIntToUSB(start); DumpStringToUSB(":"); DumpUIntToUSB(stop); DumpStringToUSB("}");
163
			if(*AT91C_TC2_CV > 2*128) {
164
				u_int32_t dummybuf[1] = {*AT91C_TC2_CV};
165
				handle_buffer(dummybuf, 1);
166
				
167
				usb_print_string_f("[", 0);
168
				while(xSemaphoreTake(data_semaphore, portMAX_DELAY) == pdFALSE) ;
169
				usb_print_string_f("]", 0);
170
			}
171
	}	
172
}
173

    
174
static u_int32_t testdata[] = {65535, 75, 138, 75, 138, 139, 139, 300};
175
static u_int32_t testdata2[] = {65535, 80, 144, 208, 208, 208, 80, 80, 208, 208, 208, 208, 80, 144, 80, 144, 144, 80, 144, 208, 81, 80, 80, 81, 80, 81, 209, 209, 209, 80, 81, 145, 81, 300};
176

    
177
static void timing_loop(void)
178
{
179
	while(1) {
180
		vTaskDelay(5000*portTICK_RATE_MS);
181
		performance_start();
182
		handle_buffer(testdata, sizeof(testdata)/sizeof(testdata[0]));
183
		performance_set_checkpoint("end of first buffer");
184
		handle_buffer(testdata2, sizeof(testdata2)/sizeof(testdata2[0]));
185
		performance_stop_report();
186
		DumpStringToUSB("Produced frame of "); DumpUIntToUSB(rx_frame.numbytes);
187
		DumpStringToUSB(" bytes and "); DumpUIntToUSB(rx_frame.numbits);
188
		DumpStringToUSB(" bits: "); DumpBufferToUSB((char*)rx_frame.data, rx_frame.numbytes + (rx_frame.numbits+7)/8 );
189
		DumpStringToUSB(" CRC "); if(rx_frame.parameters.a.crc) DumpStringToUSB("OK"); else DumpStringToUSB("ERROR");
190
		DumpStringToUSB("\n\r");
191
	}
192
}
193

    
194
void tc_sniffer (void *pvParameters)
195
{
196
	(void)pvParameters;
197
	/* Disable load modulation circuitry
198
	 * (Must be done explicitly, because the default state is pull-up high, leading
199
	 * to a constant modulation output which prevents reception. I've been bitten by
200
	 * this more than once.)
201
	 */
202
	load_mod_init();
203
	load_mod_level(0);
204
	
205
	clock_switch_init();
206
	
207
	pll_init();
208
	pll_inhibit(0);
209
	
210
	tc_fdt_init();
211
	
212
	memset(fiq_buffers, 0, sizeof(fiq_buffers));
213
	
214
	/* Wait for the USB and CMD threads to start up */
215
	vTaskDelay(1000 * portTICK_RATE_MS);
216
	
217
	if(OPENPICC->features.clock_switching) {
218
		clock_switch(CLOCK_SELECT_CARRIER);
219
		decoder = iso14443a_init_diffmiller(0);
220
	} else {
221
		switch(OPENPICC->default_clock) {
222
		case CLOCK_SELECT_CARRIER:
223
			decoder = iso14443a_init_diffmiller(0);
224
			break;
225
		case CLOCK_SELECT_PLL:
226
			decoder = iso14443a_init_diffmiller(1);
227
			break;
228
		}
229
	}
230
	
231
	if(!decoder) vLedHaltBlinking(1);
232
	vSemaphoreCreateBinary(data_semaphore);
233
	if(data_semaphore == NULL) vLedHaltBlinking(3);
234
	
235
	// The change interrupt is going to be handled by the FIQ 
236
	AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_SSC_DATA);
237
	if( pio_irq_register(OPENPICC_SSC_DATA, &tc_sniffer_irq) < 0) 
238
		vLedHaltBlinking(2);
239
	pio_irq_enable(OPENPICC_SSC_DATA);
240

    
241
	//main_loop();
242
	timing_loop();
243
	
244
	(void)main_loop; (void)timing_loop;
245
}
(56-56/59)
Add picture from clipboard (Maximum size: 48.8 MB)