summaryrefslogtreecommitdiff
path: root/openpicc/application/iso14443_layer2a.c
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc/application/iso14443_layer2a.c')
-rw-r--r--openpicc/application/iso14443_layer2a.c92
1 files changed, 84 insertions, 8 deletions
diff --git a/openpicc/application/iso14443_layer2a.c b/openpicc/application/iso14443_layer2a.c
index 57754f8..d5e89cf 100644
--- a/openpicc/application/iso14443_layer2a.c
+++ b/openpicc/application/iso14443_layer2a.c
@@ -39,6 +39,7 @@
#include "openpicc.h"
#include "iso14443_layer2a.h"
#include "ssc.h"
+#include "ssc_buffer.h"
#include "pll.h"
#include "tc_fdt.h"
#include "tc_cdiv.h"
@@ -51,6 +52,9 @@
#define PRINT_DEBUG 0
static u_int8_t fast_receive;
+static u_int8_t tx_pending=0;
+static u_int8_t rx_pending=0;
+static iso14443_receive_callback_t callback=NULL;
static ssc_handle_t *ssc;
#ifdef FOUR_TIMES_OVERSAMPLING
@@ -59,16 +63,23 @@ static ssc_handle_t *ssc;
#define RX_DIVIDER 64
#endif
-int iso14443_receive(iso14443_receive_callback_t callback, ssc_dma_rx_buffer_t **buffer, unsigned int timeout)
+int iso14443_receive(iso14443_receive_callback_t _callback, ssc_dma_rx_buffer_t **buffer, unsigned int timeout)
{
- (void)callback; (void)timeout;
ssc_dma_rx_buffer_t* _buffer = NULL;
int len;
+ if(rx_pending) {
+ return -EALREADY;
+ }
+ rx_pending=1;
+ callback=_callback;
+
if(ssc_recv(ssc, &_buffer, timeout) == 0) {
if(_buffer == NULL) {
/* Can this happen? */
+ rx_pending=0;
+ callback=NULL;
return -ETIMEDOUT;
}
@@ -78,6 +89,10 @@ int iso14443_receive(iso14443_receive_callback_t callback, ssc_dma_rx_buffer_t *
len = _buffer->len_transfers;
+ if(callback != NULL && !fast_receive) {
+ callback(_buffer, 0);
+ }
+
if(buffer != NULL) *buffer = _buffer;
else {
portENTER_CRITICAL();
@@ -85,13 +100,59 @@ int iso14443_receive(iso14443_receive_callback_t callback, ssc_dma_rx_buffer_t *
portEXIT_CRITICAL();
}
+ rx_pending=0;
+ callback=NULL;
return len;
}
- if(AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, OPENPICC_PIO_FRAME)) tc_cdiv_sync_reset();
+ /* Note: There is the remote chance of a race condition probability here if
+ * a frame start was received right before the timeout for this function
+ * expired. In the future one might want to replace this with some safer code
+ * (hmm, maybe check TC2_CV?) but for now it's an essential safeguard to prevent
+ * a hung receiver when no proper frame end is signalled to iso14443_ssc_callback
+ * and therefore the callback never resets the flipflop */
+ if(!tx_pending) {
+ if(AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, OPENPICC_PIO_FRAME)) tc_cdiv_sync_reset();
+ }
+
+ rx_pending=0;
+ callback=NULL;
return -ETIMEDOUT;
}
+int iso14443_transmit(ssc_dma_tx_buffer_t *buffer, unsigned int fdt, u_int8_t async, unsigned int timeout)
+{
+ if(tx_pending)
+ return -EBUSY;
+
+ tx_pending = 1;
+
+ /* Immediately set up FDT and clock */
+ ssc_select_clock(CLOCK_SELECT_CARRIER);
+ ssc_set_gate(0);
+ tc_fdt_set(fdt);
+ tc_cdiv_set_divider(8); // FIXME Magic hardcoded number
+
+ if(!async) {
+ /* FIXME Implement */
+ (void)timeout;
+ tx_pending = 0;
+ return -EINVAL;
+ }
+
+ int ret = ssc_send(ssc, buffer);
+ if(ret < 0) {
+ tx_pending = 0;
+ return ret;
+ }
+
+ if(!async) {
+ /* FIXME Wait for completion, timeout or abort */
+ }
+
+ return 0;
+}
+
int iso14443_wait_for_carrier(unsigned int timeout)
{
(void)timeout;
@@ -112,7 +173,6 @@ u_int8_t iso14443_get_fast_receive(void)
static void iso14443_ssc_callback(ssc_callback_reason reason, void *data)
{
- (void) data;
if(reason == CALLBACK_RX_FRAME_BEGIN) {
/* Busy loop for the frame end */
int *end_asserted = data, i=0;
@@ -124,11 +184,28 @@ static void iso14443_ssc_callback(ssc_callback_reason reason, void *data)
}
return;
}
- if( reason == CALLBACK_RX_FRAME_ENDED || reason == CALLBACK_RX_STARTED ) {
+
+ if(reason == CALLBACK_TX_FRAME_ENDED) {
+ tx_pending = 0;
+ }
+
+ if( reason == CALLBACK_RX_FRAME_ENDED && fast_receive ) {
+ ssc_select_clock(CLOCK_SELECT_CARRIER); /* A Tx might be coming up */
+
+ ssc_dma_rx_buffer_t *buffer = data;
+ if(callback != NULL)
+ callback(buffer, 1);
+ }
+
+ if( (reason == CALLBACK_RX_FRAME_ENDED && !tx_pending) || reason == CALLBACK_RX_STARTING
+ || reason == CALLBACK_TX_FRAME_ENDED ) {
+ ssc_select_clock(CLOCK_SELECT_PLL);
+ ssc_set_gate(1);
tc_fdt_set(0xff00);
tc_cdiv_set_divider(RX_DIVIDER);
tc_cdiv_sync_reset();
}
+
}
static void iso14443_rx_FRAME_cb(u_int32_t pio)
@@ -155,12 +232,11 @@ int iso14443_layer2a_init(u_int8_t enable_fast_receive)
if(PRINT_DEBUG) usb_print_string("FRAME irq registered\n\r"); // DEBUG OUTPUT
}
- ssc = ssc_open(1, 0, SSC_MODE_14443A, iso14443_ssc_callback);
+ ssc = ssc_open(1, 1, SSC_MODE_14443A, iso14443_ssc_callback);
if(ssc == NULL)
return -EIO;
- // FIXME should be 3 for production, when tx code is implemented
- load_mod_level(0);
+ load_mod_level(3);
return 0;
}
personal git repositories of Harald Welte. Your mileage may vary