summaryrefslogtreecommitdiff
path: root/openpicc/application
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc/application')
-rw-r--r--openpicc/application/decoder.c81
-rw-r--r--openpicc/application/decoder.h32
-rw-r--r--openpicc/application/decoder_miller.c130
-rw-r--r--openpicc/application/decoder_nrzl.c111
-rw-r--r--openpicc/application/iso14443_layer3a.c15
-rw-r--r--openpicc/application/iso14443a_manchester.c134
-rw-r--r--openpicc/application/load_modulation.c49
-rw-r--r--openpicc/application/load_modulation.h7
-rw-r--r--openpicc/application/main.c2
9 files changed, 558 insertions, 3 deletions
diff --git a/openpicc/application/decoder.c b/openpicc/application/decoder.c
new file mode 100644
index 0000000..a4287fd
--- /dev/null
+++ b/openpicc/application/decoder.c
@@ -0,0 +1,81 @@
+/* Decoder Core for OpenPICC
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <errno.h>
+#include <sys/types.h>
+
+#include "openpicc.h"
+#include "dbgu.h"
+#include "decoder.h"
+
+static struct decoder_algo *decoder_algo[DECODER_NUM_ALGOS];
+
+static int get_next_data(struct decoder_state *st, u_int8_t *data)
+{
+ u_int8_t parity_sample;
+ u_int32_t bytesample;
+
+ bytesample = st->algo->get_next_bytesample(st, &parity_sample);
+
+ return st->algo->decode_sample(bytesample, data);
+}
+
+/* iterate over sample buffer (size N bytes) and decode data */
+int decoder_decode(u_int8_t algo, const char *sample_buf,
+ int sample_buf_size, unsigned char *data_buf)
+{
+ int i, ret;
+ struct decoder_state st;
+
+ if (algo >= DECODER_NUM_ALGOS)
+ return -EINVAL;
+
+ st.buf = sample_buf;
+ st.buf32 = (u_int32_t *) st.buf;
+ st.bit_ofs = 0;
+ st.algo = decoder_algo[algo];
+
+ for (i = 0; i < (sample_buf_size*8)/st.algo->bits_per_sampled_char;
+ i++) {
+ ret = get_next_data(&st, &data_buf[i]);
+ if (ret < 0) {
+ DEBUGPCR("decoder error %d at data byte %u",
+ ret, i);
+ return ret;
+ }
+ }
+
+ return i+1;
+}
+
+int decoder_register(int algnum, struct decoder_algo *algo)
+{
+ if (algnum >= DECODER_NUM_ALGOS)
+ return -EINVAL;
+
+ decoder_algo[algnum] = algo;
+
+ return 0;
+}
+
+void decoder_init(void)
+{
+ decoder_register(DECODER_MILLER, &miller_decoder);
+ decoder_register(DECODER_NRZL, &nrzl_decoder);
+}
diff --git a/openpicc/application/decoder.h b/openpicc/application/decoder.h
new file mode 100644
index 0000000..bd25777
--- /dev/null
+++ b/openpicc/application/decoder.h
@@ -0,0 +1,32 @@
+#ifndef _DECODER_H
+#define _DECODER_H
+
+struct decoder_state;
+
+struct decoder_algo {
+ u_int8_t oversampling_rate;
+ u_int8_t bits_per_sampled_char;
+ u_int32_t bytesample_mask;
+ int (*decode_sample)(const u_int32_t sample, u_int8_t *data);
+ u_int32_t (*get_next_bytesample)(struct decoder_state *st, u_int8_t *parity_sample);
+};
+
+struct decoder_state {
+ struct decoder_algo *algo;
+ u_int8_t bit_ofs;
+ const char *buf;
+ const u_int32_t *buf32;
+};
+
+extern int decoder_register(int algnum, struct decoder_algo *algo);
+extern int decoder_decode(u_int8_t algo, const char *sample_buf,
+ int sample_buf_size, unsigned char *data_buf);
+
+#define DECODER_MILLER 0
+#define DECODER_NRZL 1
+#define DECODER_NUM_ALGOS 2
+
+extern struct decoder_algo nrzl_decoder;
+extern struct decoder_algo miller_decoder;
+
+#endif
diff --git a/openpicc/application/decoder_miller.c b/openpicc/application/decoder_miller.c
new file mode 100644
index 0000000..aa3a669
--- /dev/null
+++ b/openpicc/application/decoder_miller.c
@@ -0,0 +1,130 @@
+/*
+ * ISO14443A modified Miller decoder for OpenPICC
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ */
+
+/*
+ * LSB First LSB hex
+ * Sequence X 0010 0100 0x4
+ * Sequence Y 0000 0000 0x0
+ * Sequence Z 1000 0001 0x1
+ *
+ * Logic 1 Sequence X
+ * Logic 0 Sequence Y with two exceptions:
+ * - if there are more contiguous 0, Z used from second one
+ * - if the first bit after SOF is 0, sequence Z used for all contig 0's
+ * SOF Sequence Z
+ * EOF Logic 0 followed by Sequence Y
+ *
+ * cmd hex bits symbols hex (quad-sampled)
+ *
+ * REQA 0x26 S 0110010 E Z ZXXYZXY ZY 0x10410441
+ * WUPA 0x52 S 0100101 E Z ZXYZXYX YY 0x04041041
+ *
+ * SOF is 'eaten' by SSC start condition (Compare 0). Remaining bits are
+ * mirrored, e.g. samples for LSB of first byte are & 0xf
+ *
+ */
+
+#include <sys/types.h>
+
+#include "openpicc.h"
+#include "dbgu.h"
+#include "decoder.h"
+
+
+#define OVERSAMPLING_RATE 4
+
+/* definitions for four-times oversampling */
+#define SEQ_X 0x4
+#define SEQ_Y 0x0
+#define SEQ_Z 0x1
+
+/* decode a single sampled bit */
+static u_int8_t miller_decode_sampled_bit(u_int32_t sampled_bit)
+{
+ switch (sampled_bit) {
+ case SEQ_X:
+ return 1;
+ break;
+ case SEQ_Z:
+ case SEQ_Y:
+ return 0;
+ break;
+ default:
+ DEBUGP("unknown sequence sample `%x' ", sampled_bit);
+ return 2;
+ break;
+ }
+}
+
+/* decode a single 32bit data sample of an 8bit miller encoded word */
+static int miller_decode_sample(u_int32_t sample, u_int8_t *data)
+{
+ u_int8_t ret = 0;
+ unsigned int i;
+
+ for (i = 0; i < sizeof(sample)/OVERSAMPLING_RATE; i++) {
+ u_int8_t bit = miller_decode_sampled_bit(sample & 0xf);
+
+ if (bit == 1)
+ ret |= 1;
+ /* else do nothing since ret was initialized with 0 */
+
+ /* skip shifting in case of last data bit */
+ if (i == sizeof(sample)/OVERSAMPLING_RATE)
+ break;
+
+ sample = sample >> OVERSAMPLING_RATE;
+ ret = ret << 1;
+ }
+
+ *data = ret;
+
+ return ret;
+}
+
+static u_int32_t get_next_bytesample(struct decoder_state *ms,
+ u_int8_t *parity_sample)
+{
+ u_int32_t ret = 0;
+
+ /* get remaining bits from the current word */
+ ret = *(ms->buf32) >> ms->bit_ofs;
+ /* move to next word */
+ ms->buf32++;
+
+ /* if required, get remaining bits from next word */
+ if (ms->bit_ofs)
+ ret |= *(ms->buf32) << (32 - ms->bit_ofs);
+
+ *parity_sample = (*(ms->buf32) >> ms->bit_ofs & 0xf);
+
+ /* increment bit offset (modulo 32) */
+ ms->bit_ofs = (ms->bit_ofs + OVERSAMPLING_RATE) % 32;
+
+ return ret;
+}
+
+struct decoder_algo miller_decoder = {
+ .oversampling_rate = OVERSAMPLING_RATE,
+ .bits_per_sampled_char = 9 * OVERSAMPLING_RATE,
+ .bytesample_mask = 0xffffffff,
+ .decode_sample = &miller_decode_sample,
+ .get_next_bytesample = &get_next_bytesample,
+};
diff --git a/openpicc/application/decoder_nrzl.c b/openpicc/application/decoder_nrzl.c
new file mode 100644
index 0000000..6ffbb45
--- /dev/null
+++ b/openpicc/application/decoder_nrzl.c
@@ -0,0 +1,111 @@
+/* NRZ-L decoder implementation for OpenPICC
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ */
+
+/*
+ * speed(kbps) 106 212 424 848
+ * etu 128/fc 64/fc 32/fc 16/fc
+ * etu(usec) 9.4 4.7 2.35 1.18
+ *
+ * NRZ-L coding with logic level
+ *
+ * logic 1: carrier high field amplitude (no modulation)
+ * logic 0: carrier low field amplitude
+ *
+ * Character transmission format:
+ * start bit: logic 0
+ * data: eight bits, lsb first
+ * stop bit logic 1
+ *
+ * Frame Format:
+ *
+ * SOF char [EGT char, ...] EOF
+ *
+ * SOF: falling edge, 10..11 etu '0', rising edge in 1etu, 2..3etu '1'
+ * EGT: between 0 and 57uS
+ * EOF: falling edge, 10..11 etu '0', rising edge in 1etu
+ *
+ *
+ * Sampling
+ * - sample once per bit clock, exactly in the middle of it
+ * - synchronize CARRIER_DIV TC0 to first falling edge
+ * - Configure CARRIER_DIV RA compare (rising edge) to be at
+ * etu/2 carrier clocks.
+ * - problem: SOF 12..14etu length, therefore we cannot specify
+ * SOF as full start condition and then sample with 10bit
+ * frames :(
+ *
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+
+#include "openpicc.h"
+#include "dbgu.h"
+#include "decoder.h"
+
+/* currently this code will only work with oversampling_rate == 1 */
+#define OVERSAMPLING_RATE 1
+
+static u_int32_t get_next_bytesample(struct decoder_state *st,
+ u_int8_t *parity_sample)
+{
+ u_int32_t ret = 0;
+ u_int8_t bits_per_sampled_char = st->algo->bits_per_sampled_char;
+ u_int8_t bytesample_mask = st->algo->bytesample_mask;
+
+ /* FIXME: shift start and stop bit into parity_sample and just
+ * return plain 8-bit data word */
+ (void)parity_sample;
+
+ /* first part of 10-databit bytesample */
+ ret = (*(st->buf32) >> st->bit_ofs) & bytesample_mask;
+
+ if (st->bit_ofs > 32 - bits_per_sampled_char) {
+ /* second half of 10-databit bytesample */
+ st->buf32++;
+ ret |= (*(st->buf32) << (32 - st->bit_ofs));
+ }
+ st->bit_ofs = (st->bit_ofs + bits_per_sampled_char) % 32;
+
+ return ret & bytesample_mask;
+}
+
+static int nrzl_decode_sample(const u_int32_t sample, u_int8_t *data)
+{
+ *data = (sample >> 1) & 0xff;
+
+ if (!(sample & 0x01)) {
+ DEBUGPCRF("invalid start bit 0!");
+ return -EIO;
+ }
+ if (sample & 0x20) {
+ DEBUGPCRF("invalid stop bit 1!");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+struct decoder_algo nrzl_decoder = {
+ .oversampling_rate = OVERSAMPLING_RATE,
+ .bits_per_sampled_char = 10 * OVERSAMPLING_RATE,
+ .bytesample_mask = 0x3ff,
+ .decode_sample = &nrzl_decode_sample,
+ .get_next_bytesample = &get_next_bytesample,
+};
diff --git a/openpicc/application/iso14443_layer3a.c b/openpicc/application/iso14443_layer3a.c
index 8dd9cd2..841ad14 100644
--- a/openpicc/application/iso14443_layer3a.c
+++ b/openpicc/application/iso14443_layer3a.c
@@ -130,17 +130,26 @@ void iso14443_layer3a_state_machine (void *pvParameters)
portENTER_CRITICAL();
buffer->state = PROCESSING;
portEXIT_CRITICAL();
+ u_int32_t first_sample = *(u_int32_t*)buffer->data;
DumpStringToUSB("Frame: ");
- DumpUIntToUSB(*(u_int32_t*)buffer->data);
+ DumpUIntToUSB(first_sample);
DumpStringToUSB(" ");
main_help_print_buffer(buffer, &pktcount);
switch(state) {
case IDLE:
case HALT:
- ssc_rx_mode_set(SSC_MODE_14443A_SHORT);
- ssc_rx_start();
+ if(first_sample == WUPA || (state==IDLE && first_sample==REQA)) {
+ /* Need to transmit ATQA */
+ LAYER3_DEBUG("Received ");
+ LAYER3_DEBUG(first_sample == WUPA ? "WUPA" : "REQA");
+ LAYER3_DEBUG(" waking up to send ATQA\n\r");
+ } else {
+ /* Wait for another frame */
+ ssc_rx_mode_set(SSC_MODE_14443A_SHORT);
+ ssc_rx_start();
+ }
break;
default:
break;
diff --git a/openpicc/application/iso14443a_manchester.c b/openpicc/application/iso14443a_manchester.c
new file mode 100644
index 0000000..efc4baf
--- /dev/null
+++ b/openpicc/application/iso14443a_manchester.c
@@ -0,0 +1,134 @@
+/* ISO14443A Manchester encoder for OpenPICC
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ */
+
+
+/*
+ * Definitions for 106kBps, at sampling clock 1695kHz
+ *
+ * bit sample pattern for one bit cycle
+ * MSB first LSB first hex LSB first
+ * Sequence D 1010101000000000 0000000001010101 0x0055
+ * Sequence E 0000000010101010 0101010100000000 0x5500
+ * Sequence F 1010101010101010 0101010101010101 0x5555
+ *
+ * Logic 1 Sequence D
+ * Logic 0 Sequence E
+ * SOF Sequence D
+ * EOF Sequence F
+ *
+ * 212/424/848kBps: BPSK.
+ *
+ * SOF: 32 subcarrier clocks + bit '0'
+ *
+ * SOF: hex LSB first: 0x55555555 55555555 + bit '0'
+ *
+ * EOF: even parity of last byte (!)
+ *
+ */
+
+#define MANCHESTER_SEQ_D 0x0055
+#define MANCHESTER_SEQ_E 0x5500
+#define MANCHESTER_SEQ_F 0x5555
+
+#include <errno.h>
+#include <string.h>
+#include "openpicc.h"
+
+static u_int32_t manchester_sample_size(u_int8_t frame_bytelen) __attribute__((unused));
+static u_int32_t manchester_sample_size(u_int8_t frame_bytelen)
+{
+ /* 16 bits (2 bytes) per bit => 16 bytes samples per data byte,
+ * plus 16bit (2 bytes) parity per data byte
+ * plus 16bit (2 bytes) SOF plus 16bit (2 bytes) EOF */
+ return (frame_bytelen*18) + 2 + 2;
+
+ /* this results in a maximum samples-per-frame size of 4612 bytes
+ * for a 256byte frame */
+}
+
+struct manch_enc_state {
+ const char *data;
+ char *samples;
+ u_int16_t *samples16;
+};
+
+static void manchester_enc_byte(struct manch_enc_state *mencs, u_int8_t data) __attribute__((unused));
+static void manchester_enc_byte(struct manch_enc_state *mencs, u_int8_t data)
+{
+ int i;
+ u_int8_t sum_1 = 0;
+
+ /* append 8 sample blobs, one for each bit */
+ for (i = 0; i < 8; i++) {
+ if (data & (1 << i)) {
+ *(mencs->samples16) = MANCHESTER_SEQ_D;
+ sum_1++;
+ } else {
+ *(mencs->samples16) = MANCHESTER_SEQ_E;
+ }
+ mencs->samples16++;
+ }
+ /* append odd parity */
+ if (sum_1 & 0x01)
+ *(mencs->samples16) = MANCHESTER_SEQ_E;
+ else
+ *(mencs->samples16) = MANCHESTER_SEQ_D;
+ mencs->samples16++;
+}
+
+#if 0
+/* Broken? */
+int manchester_encode(char *sample_buf, u_int16_t sample_buf_len,
+ const char *data, u_int8_t data_len)
+{
+ int i, enc_size;
+ struct manch_enc_state mencs;
+
+ enc_size = manchester_sample_size(data_len);
+
+ if (sample_buf_len < enc_size)
+ return -EINVAL;
+
+ /* SOF */
+ *(mencs.samples16++) = MANCHESTER_SEQ_D;
+
+ for (i = 0; i < data_len; i++)
+ manchester_enc_byte(&mencs, data[i]);
+
+ /* EOF */
+ *(mencs.samples16++) = MANCHESTER_SEQ_F;
+
+ return enc_size;
+}
+#endif
+#if 0
+/* Broken? */
+#define BPSK_SPEED_212
+
+
+static u_int32_t bpsk_sample_size(u_int8_t frame_bytelen);
+
+int bpsk_encode(char *sample_buf, u_int16_t sample_buf_len,
+ const char *data, u_int8_t data_len)
+{
+ /* burst of 32 sub carrier cycles */
+ memset(sample_buf, 0x55, 8);
+
+}
+#endif
diff --git a/openpicc/application/load_modulation.c b/openpicc/application/load_modulation.c
new file mode 100644
index 0000000..976d57f
--- /dev/null
+++ b/openpicc/application/load_modulation.c
@@ -0,0 +1,49 @@
+/* AT91SAM7 PWM routines for OpenPICC
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <sys/types.h>
+#include <lib_AT91SAM7.h>
+
+#include "openpicc.h"
+
+void load_mod_level(u_int8_t level)
+{
+ if (level > 3)
+ level = 3;
+
+ if (level & 0x1)
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD1);
+ else
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD1);
+
+ if (level & 0x2)
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD2);
+ else
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD2);
+}
+
+void load_mod_init(void)
+{
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD1);
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD2);
+
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD1);
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD2);
+}
diff --git a/openpicc/application/load_modulation.h b/openpicc/application/load_modulation.h
new file mode 100644
index 0000000..71f9d6f
--- /dev/null
+++ b/openpicc/application/load_modulation.h
@@ -0,0 +1,7 @@
+#ifndef _LOAD_MODULATION_H
+#define _LOAD_MODULATION_H
+
+extern void load_mod_level(u_int8_t level);
+extern void load_mod_init(void);
+
+#endif
diff --git a/openpicc/application/main.c b/openpicc/application/main.c
index 37cc24a..48e9ab2 100644
--- a/openpicc/application/main.c
+++ b/openpicc/application/main.c
@@ -102,6 +102,8 @@ void main_help_print_buffer(ssc_dma_buffer_t *buffer, int *pktcount)
DumpStringToUSB(" ");
}
dumped = 1;
+ DumpUIntToUSB(i);
+ DumpStringToUSB(": ");
for(j=0; j<sizeof(*tmp)*8; j++) {
usb_print_char_f( (((*tmp) >> j) & 0x1) ? '1' : '_' , 0);
}
personal git repositories of Harald Welte. Your mileage may vary