summaryrefslogtreecommitdiff
path: root/openpicc/application/iso14443a_pretender.c
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc/application/iso14443a_pretender.c')
-rw-r--r--openpicc/application/iso14443a_pretender.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/openpicc/application/iso14443a_pretender.c b/openpicc/application/iso14443a_pretender.c
new file mode 100644
index 0000000..6f62330
--- /dev/null
+++ b/openpicc/application/iso14443a_pretender.c
@@ -0,0 +1,227 @@
+/***************************************************************
+ *
+ * OpenPICC - ISO 14443 Layer 3 response pretender,
+ * proof of concept
+ *
+ * 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 <board.h>
+#include <task.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "openpicc.h"
+#include "ssc_buffer.h"
+#include "iso14443.h"
+#include "iso14443_layer2a.h"
+#include "iso14443a_pretender.h"
+#include "iso14443a_manchester.h"
+#include "usb_print.h"
+#include "cmd.h"
+#include "led.h"
+
+static const iso14443_frame ATQA_FRAME = {
+ TYPE_A,
+ {{STANDARD_FRAME, PARITY, ISO14443A_LAST_BIT_NONE}},
+ 2,
+ 0, 0,
+ {4, 0},
+ {}
+};
+
+static ssc_dma_tx_buffer_t tx_buffer;
+
+static void fast_receive_callback(ssc_dma_rx_buffer_t *buffer, u_int8_t in_irq)
+{
+ (void)buffer; (void)in_irq;
+ unsigned int buffy=0;
+ u_int32_t cv = *AT91C_TC2_CV;
+
+ const iso14443_frame *tx_frame = NULL;
+ int fdt = 0;
+
+ switch(buffer->len_transfers) {
+ case 3: case 4: /* REQA (7 bits) */
+ tx_frame = &ATQA_FRAME;
+ fdt = 1172;
+ break;
+ case 6: case 7: /* ANTICOL (2 bytes) */
+ case 22: /* SELECT (9 bytes) */
+
+ break;
+ case 577:
+ usb_print_string_f("f", 0);
+ buffy=(unsigned int)buffer;
+ break;
+ }
+
+ /* Add some extra room to the fdt for testing */
+ fdt += 3*128;
+
+ int ret = 0;
+ if(tx_frame != NULL) {
+ tx_buffer.source = (void*)tx_frame;
+ tx_buffer.len = sizeof(tx_buffer.data);
+ ret = manchester_encode(tx_buffer.data,
+ tx_buffer.len,
+ tx_frame);
+ if(ret >= 0) {
+ tx_buffer.state = FULL;
+ tx_buffer.len = ret;
+ if( iso14443_transmit(&tx_buffer, fdt, 1, 0) < 0) {
+ tx_buffer.state = FREE;
+ usb_print_string_f("Tx failed ", 0);
+ }
+ } else tx_buffer.state = FREE;
+
+ }
+
+ u_int32_t cv2 = *AT91C_TC2_CV;
+ int old=usb_print_set_default_flush(0);
+ DumpUIntToUSB(cv);
+ DumpStringToUSB(":");
+ DumpUIntToUSB(cv2);
+ if(ret<0) {
+ DumpStringToUSB("!");
+ DumpUIntToUSB(-ret);
+ }
+ if(buffy!=0) {
+ DumpStringToUSB("§");
+ DumpUIntToUSB(buffy);
+ }
+ usb_print_set_default_flush(old);
+ usb_print_string_f("%", 0);
+}
+
+void iso14443a_pretender (void *pvParameters)
+{
+ (void)pvParameters;
+ int res;
+
+ /* Delay until USB print etc. are ready */
+ int i;
+ for(i=0; i<=1000; i++) {
+ vLedSetBrightness(LED_RED, i);
+ vLedSetBrightness(LED_GREEN, i);
+ vTaskDelay(1*portTICK_RATE_MS);
+ }
+
+ for(i=0; i<=1000; i+=4) {
+ vLedSetBrightness(LED_GREEN, 1000-i);
+ vTaskDelay(1*portTICK_RATE_MS);
+ }
+
+ do {
+ res = iso14443_layer2a_init(1);
+ if(res < 0) {
+ usb_print_string("Pretender: Initialization failed\n\r");
+ for(i=0; i<=10000; i++) {
+ vLedSetBrightness(LED_RED, abs(1000-(i%2000)));
+ vTaskDelay(1*portTICK_RATE_MS);
+ }
+ }
+ } while(res < 0);
+
+
+ usb_print_string("Waiting for carrier. ");
+ while(iso14443_wait_for_carrier(1000 * portTICK_RATE_MS) != 0) {
+ }
+ usb_print_string("Carrier detected.\n\r");
+
+ for(i=0; i<=1000; i+=4) {
+ vLedSetBrightness(LED_RED, 1000-i);
+ vTaskDelay(1*portTICK_RATE_MS);
+ }
+
+ vTaskDelay(250*portTICK_RATE_MS);
+ vLedSetGreen(0);
+ vLedSetRed(0);
+
+ int current_detected = 0, last_detected = 0;
+ portTickType last_switched = 0;
+#define DETECTED_14443A_3 1
+#define DETECTED_14443A_4 2
+#define DETECTED_MIFARE 4
+
+ while(true) {
+ ssc_dma_rx_buffer_t *buffer = 0;
+ res = iso14443_receive(fast_receive_callback, &buffer, 1000 * portTICK_RATE_MS);
+ if(res >= 0) {
+ DumpUIntToUSB(buffer->len_transfers);
+ DumpStringToUSB("\n\r");
+
+ switch(buffer->len_transfers) {
+ case 3: case 4: /* REQA (7 bits) */
+ current_detected |= DETECTED_14443A_3;
+ break;
+ case 6: case 7: /* ANTICOL (2 bytes) */
+ case 22: /* SELECT (9 bytes) */
+ current_detected |= DETECTED_14443A_3;
+ break;
+ case 10: case 11: /* AUTH1A (or any other four byte frame) */
+ case 19: case 20: /* AUTH2 (8 bytes) */
+ current_detected |= DETECTED_MIFARE;
+ break;
+ }
+
+ portENTER_CRITICAL();
+ buffer->state = FREE;
+ portEXIT_CRITICAL();
+ } else {
+ if(res != -ETIMEDOUT) {
+ usb_print_string("Receive error: ");
+ switch(res) {
+ case -ENETDOWN: usb_print_string("PLL is not locked or PLL lock lost\n\r"); break;
+ case -EBUSY: usb_print_string("A Tx is currently running or pending, can't receive\n\r"); break;
+ case -EALREADY: usb_print_string("There's already an iso14443_receive() invocation running\n\r"); break;
+ }
+ vTaskDelay(1000 * portTICK_RATE_MS); // FIXME Proper error handling, e.g. wait for Tx end in case of EBUSY
+ } else if(0) {
+ DumpStringToUSB("\n\r");
+ DumpTimeToUSB(xTaskGetTickCount());
+ usb_print_string(": -- Mark --");
+ }
+ }
+
+ if( last_switched < xTaskGetTickCount()-(1000*portTICK_RATE_MS) ) {
+ last_detected = current_detected;
+ current_detected = 0;
+ last_switched = xTaskGetTickCount();
+ }
+
+ if(last_detected & (DETECTED_14443A_3 | DETECTED_14443A_4 | DETECTED_MIFARE)) {
+ if(last_detected & DETECTED_MIFARE) {
+ vLedSetGreen(0);
+ vLedSetRed(1);
+ } else if(last_detected & DETECTED_14443A_4) {
+ vLedSetGreen(1);
+ vLedSetRed(0);
+ } else {
+ vLedSetGreen(1);
+ vLedSetRed(1);
+ }
+ } else {
+ vLedSetGreen(0);
+ vLedSetRed(0);
+ }
+
+ }
+}
personal git repositories of Harald Welte. Your mileage may vary