host_communication/card_emu: adapt to nwe req_ctx / queuing paradignm
diff --git a/firmware/src_simtrace/card_emu.c b/firmware/src_simtrace/card_emu.c
index 5c57ddf..fa028a1 100644
--- a/firmware/src_simtrace/card_emu.c
+++ b/firmware/src_simtrace/card_emu.c
@@ -30,6 +30,7 @@
#include "card_emu.h"
#include "req_ctx.h"
#include "cardemu_prot.h"
+#include "linuxlist.h"
#define NUM_SLOTS 2
@@ -135,6 +136,9 @@
struct req_ctx *uart_rx_ctx; /* UART RX -> USB TX */
struct req_ctx *uart_tx_ctx; /* USB RX -> UART TX */
+ struct llist_head usb_tx_queue;
+ struct llist_head uart_tx_queue;
+
struct {
uint32_t tx_bytes;
uint32_t rx_bytes;
@@ -142,6 +146,16 @@
} stats;
};
+struct llist_head *card_emu_get_usb_tx_queue(struct card_handle *ch)
+{
+ return &ch->usb_tx_queue;
+}
+
+struct llist_head *card_emu_get_uart_tx_queue(struct card_handle *ch)
+{
+ return &ch->uart_tx_queue;
+}
+
static void set_tpdu_state(struct card_handle *ch, enum tpdu_state new_ts);
static void set_pts_state(struct card_handle *ch, enum pts_state new_ptss);
@@ -154,12 +168,14 @@
if (!rctx)
return;
- rd = (struct cardemu_usb_msg_rx_data *) ch->uart_rx_ctx->data;
+ ch->uart_rx_ctx = NULL;
/* store length of data payload fild in header */
+ rd = (struct cardemu_usb_msg_rx_data *) ch->uart_rx_ctx->data;
rd->hdr.data_len = rctx->idx;
+
+ llist_add_tail(&rctx->list, &ch->usb_tx_queue);
req_ctx_set_state(rctx, RCTX_S_USB_TX_PENDING);
- ch->uart_rx_ctx = NULL;
/* FIXME: call into USB code to see if this buffer can
* be transmitted now */
@@ -214,6 +230,7 @@
ptsi->hdr.data_len = serialize_pts(ptsi->req, ch->pts.req);
serialize_pts(ptsi->resp, ch->pts.resp);
+ llist_add_tail(&rctx->list, &ch->usb_tx_queue);
req_ctx_set_state(rctx, RCTX_S_USB_TX_PENDING);
/* FIXME: call into USB code to see if this buffer can
@@ -637,11 +654,15 @@
/* ensure we are aware of any data that might be pending for
* transmit */
if (!ch->uart_tx_ctx) {
- ch->uart_tx_ctx = req_ctx_find_get(0, RCTX_S_UART_TX_PENDING,
- RCTX_S_UART_TX_BUSY);
- if (!ch->uart_tx_ctx)
+ if (llist_empty(&ch->uart_tx_queue))
return 0;
+ /* dequeue first at head */
+ ch->uart_tx_ctx = llist_entry(ch->uart_tx_queue.next,
+ struct req_ctx, list);
+ llist_del(&ch->uart_tx_ctx->list);
+ req_ctx_set_state(ch->uart_tx_ctx, RCTX_S_UART_TX_BUSY);
+
/* start with index zero */
ch->uart_tx_ctx->idx = 0;
@@ -855,6 +876,9 @@
memset(ch, 0, sizeof(*ch));
+ INIT_LLIST_HEAD(&ch->usb_tx_queue);
+ INIT_LLIST_HEAD(&ch->uart_tx_queue);
+
/* initialize the card_handle with reasonabe defaults */
ch->state = ISO_S_WAIT_POWER;
ch->vcc_active = 0;
diff --git a/firmware/src_simtrace/card_emu.h b/firmware/src_simtrace/card_emu.h
index 225c307..eea3478 100644
--- a/firmware/src_simtrace/card_emu.h
+++ b/firmware/src_simtrace/card_emu.h
@@ -24,6 +24,8 @@
/* User sets a new ATR to be returned during next card reset */
int card_emu_set_atr(struct card_handle *ch, const uint8_t *atr, uint8_t len);
+struct llist_head *card_emu_get_uart_tx_queue(struct card_handle *ch);
+struct llist_head *card_emu_get_usb_tx_queue(struct card_handle *ch);
#define ENABLE_TX 0x01
#define ENABLE_RX 0x02
diff --git a/firmware/src_simtrace/host_communication.c b/firmware/src_simtrace/host_communication.c
index 10561c4..6834c4a 100644
--- a/firmware/src_simtrace/host_communication.c
+++ b/firmware/src_simtrace/host_communication.c
@@ -1,5 +1,8 @@
#include "board.h"
#include "req_ctx.h"
+#include "linuxlist.h"
+
+static volatile uint32_t usbep_in_progress[BOARD_USB_NUMENDPOINTS];
/* call-back after (successful?) transfer of a buffer */
static void usb_write_cb(uint8_t *arg, uint8_t status, uint32_t transferred,
@@ -7,6 +10,8 @@
{
struct req_ctx *rctx = (struct req_ctx *) arg;
+ usbep_in_progress[rctx->ep] = 0;
+
if (status != USBD_STATUS_SUCCESS)
TRACE_ERROR("%s error, status=%d\n", __func__, status);
@@ -14,15 +19,24 @@
req_ctx_set_state(rctx, RCTX_S_FREE);
}
-int usb_to_host(void)
+int usb_refill_to_host(struct llist_head *queue, uint32_t ep)
{
struct req_ctx *rctx;
int rc;
- rctx = req_ctx_find_get(0, RCTX_S_USB_TX_PENDING, RCTX_S_USB_TX_BUSY);
+ if (usbep_in_progress[ep])
+ return 0;
- /* FIXME: obtain endpoint number from req_ctx! */
- rc = USBD_Write(PHONE_DATAIN, rctx->data, rctx->tot_len,
+ if (llist_empty(queue))
+ return 0;
+
+ rctx = llist_entry(queue->next, struct req_ctx, list);
+ llist_del(&rctx->list);
+
+ req_ctx_set_state(rctx, RCTX_S_USB_TX_BUSY);
+ rctx->ep = ep;
+
+ rc = USBD_Write(ep, rctx->data, rctx->tot_len,
(TransferCallback) &usb_write_cb, rctx);
if (rc != USBD_STATUS_SUCCESS) {
TRACE_ERROR("%s error %x\n", __func__, rc);
@@ -30,6 +44,8 @@
return 0;
}
+ usbep_in_progress[ep] = 1;
+
return 1;
}
@@ -37,6 +53,9 @@
uint32_t remaining)
{
struct req_ctx *rctx = (struct req_ctx *) arg;
+ struct llist_head *queue = (struct llist_head *) usbep_in_progress[rctx->ep];
+
+ usbep_in_progress[rctx->ep] = 0;
if (status != USBD_STATUS_SUCCESS) {
TRACE_ERROR("%s error, status=%d\n", __func__, status);
@@ -45,14 +64,19 @@
return;
}
req_ctx_set_state(rctx, RCTX_S_UART_TX_PENDING);
+ llist_add_tail(&rctx->list, queue);
}
-int usb_from_host(int ep)
+int usb_refill_from_host(struct llist_head *queue, int ep)
{
struct req_ctx *rctx;
int rc;
+ if (usbep_in_progress[ep])
+ return 0;
+
rctx = req_ctx_find_get(0, RCTX_S_FREE, RCTX_S_USB_RX_BUSY);
+ rctx->ep = ep;
rc = USBD_Read(ep, rctx->data, rctx->size,
(TransferCallback) &usb_read_cb, rctx);
@@ -60,7 +84,10 @@
if (rc != USBD_STATUS_SUCCESS) {
TRACE_ERROR("%s error %x\n", __func__, rc);
req_ctx_put(rctx);
+ return 0;
}
- return 0;
+ usbep_in_progress[ep] = (uint32_t) queue;
+
+ return 1;
}
diff --git a/firmware/src_simtrace/main.c b/firmware/src_simtrace/main.c
index 36d86ee..95adb7e 100644
--- a/firmware/src_simtrace/main.c
+++ b/firmware/src_simtrace/main.c
@@ -140,7 +140,6 @@
last_simtrace_config = simtrace_config;
} else {
config_func_ptrs[simtrace_config].run();
- usb_to_host();
}
}
}
diff --git a/firmware/src_simtrace/mode_cardemu.c b/firmware/src_simtrace/mode_cardemu.c
index 21f3735..f1bbaf7 100644
--- a/firmware/src_simtrace/mode_cardemu.c
+++ b/firmware/src_simtrace/mode_cardemu.c
@@ -1,6 +1,7 @@
#include "board.h"
#include "card_emu.h"
#include "iso7816_fidi.h"
+#include "utils.h"
#define TRACE_ENTRY() TRACE_DEBUG("%s entering\n", __func__)
@@ -204,10 +205,8 @@
/* main loop function, called repeatedly */
void mode_cardemu_run(void)
{
-
- /* usb_to_host() is handled by main() */
-
if (ch1) {
+ /* drain the ring buffer from UART into card_emu */
while (1) {
__disable_irq();
if (rbuf_is_empty(&ch1_rb)) {
@@ -218,8 +217,9 @@
__enable_irq();
card_emu_process_rx_byte(ch1, byte);
}
+ usb_refill_to_host(card_emu_get_usb_tx_queue(ch1), PHONE_DATAIN);
+ usb_refill_from_host(card_emu_get_uart_tx_queue(ch1), PHONE_DATAOUT);
}
- usb_from_host(PHONE_DATAOUT);
#ifdef CARDEMU_SECOND_UART
if (ch2) {
diff --git a/firmware/src_simtrace/simtrace.h b/firmware/src_simtrace/simtrace.h
index 687d219..c116346 100644
--- a/firmware/src_simtrace/simtrace.h
+++ b/firmware/src_simtrace/simtrace.h
@@ -92,7 +92,8 @@
void Timer_Init( void );
void TC0_Counter_Reset( void );
-int usb_to_host(void);
-int usb_from_host(int ep);
+struct llist_head;
+int usb_refill_to_host(struct llist_head *queue, uint32_t ep);
+int usb_refill_from_host(struct llist_head *queue, int ep);
#endif /* SIMTRACE_H */