summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/g/usb-stream.c47
-rw-r--r--chip/g/usb-stream.h14
2 files changed, 36 insertions, 25 deletions
diff --git a/chip/g/usb-stream.c b/chip/g/usb-stream.c
index 8241eaf43c..7ab28c37a6 100644
--- a/chip/g/usb-stream.c
+++ b/chip/g/usb-stream.c
@@ -120,7 +120,7 @@ static inline int tx_fifo_is_ready(struct usb_stream_config const *config)
uint32_t status;
struct g_usb_desc *in_desc = config->in_desc;
- if (!(in_desc->flags & DOEPDMA_LAST))
+ if (!(in_desc->flags & DIEPDMA_LAST))
++in_desc;
status = in_desc->flags & DIEPDMA_BS_MASK;
@@ -133,12 +133,6 @@ void tx_stream_handler(struct usb_stream_config const *config)
size_t count;
struct queue const *tx_q = config->consumer.queue;
- if (!*config->is_reset)
- return;
-
- if (!tx_fifo_is_ready(config))
- return;
-
/* handle the completion of the previous transfer, if there was any. */
count = *(config->tx_handled);
if (count > 0) {
@@ -194,21 +188,30 @@ void tx_stream_handler(struct usb_stream_config const *config)
* descriptor as well if it is needed.
*/
usb_enable_tx(config, len);
+ } else {
+ /* USB TX transfer is not active. */
+ *config->tx_in_progress = 0;
}
}
/* Tx/IN interrupt handler */
void usb_stream_tx(struct usb_stream_config const *config)
{
- /* Wake up the Tx FIFO handler */
- hook_call_deferred(config->deferred_tx, 0);
-
- /* clear the Tx/IN interrupts */
+ /* Clear the Tx/IN interrupts */
GR_USB_DIEPINT(config->endpoint) = 0xffffffff;
+
+ /* Call the Tx FIFO handler */
+ tx_stream_handler(config);
}
void usb_stream_reset(struct usb_stream_config const *config)
{
+ /*
+ * Mark USB TX transfer is in progress, because it shall be so at
+ * the end of this function to flush any queued data.
+ */
+ *config->tx_in_progress = 1;
+
config->out_desc->flags = DOEPDMA_RXBYTES(config->rx_size) |
DOEPDMA_LAST | DOEPDMA_BS_HOST_RDY |
DOEPDMA_IOC;
@@ -235,10 +238,8 @@ void usb_stream_reset(struct usb_stream_config const *config)
GR_USB_DAINTMSK |= DAINT_INEP(config->endpoint) |
DAINT_OUTEP(config->endpoint);
- *config->is_reset = 1;
-
/* Flush any queued data */
- hook_call_deferred(config->deferred_tx, 0);
+ tx_stream_handler(config);
hook_call_deferred(config->deferred_rx, 0);
}
@@ -250,12 +251,28 @@ static void usb_read(struct producer const *producer, size_t count)
hook_call_deferred(config->deferred_rx, 0);
}
+/*
+ * NOTE: usb_written() should be called by IRQ handlers, so that
+ * it can be non-preemptive.
+ */
static void usb_written(struct consumer const *consumer, size_t count)
{
struct usb_stream_config const *config =
DOWNCAST(consumer, struct usb_stream_config, consumer);
- hook_call_deferred(config->deferred_tx, 0);
+ /* USB TX transfer is active. No need to activate it. */
+ if (*config->tx_in_progress)
+ return;
+
+ /*
+ * if USB Endpoint has not been initialized nor in ready status,
+ * then return.
+ */
+ if (!tx_fifo_is_ready(config))
+ return;
+
+ *config->tx_in_progress = 1;
+ tx_stream_handler(config);
}
struct producer_ops const usb_stream_producer_ops = {
diff --git a/chip/g/usb-stream.h b/chip/g/usb-stream.h
index 020f6995c5..a0c580acea 100644
--- a/chip/g/usb-stream.h
+++ b/chip/g/usb-stream.h
@@ -29,12 +29,12 @@ struct usb_stream_config {
*/
int endpoint;
- int *is_reset;
+ /* USB TX transfer is in progress */
+ uint8_t *tx_in_progress;
/*
* Deferred function to call to handle USB and Queue request.
*/
- const struct deferred_data *deferred_tx;
const struct deferred_data *deferred_rx;
int tx_size;
@@ -114,19 +114,16 @@ extern struct producer_ops const usb_stream_producer_ops;
static struct g_usb_desc CONCAT2(NAME, _out_desc_); \
static struct g_usb_desc CONCAT2(NAME, _in_desc_)[MAX_IN_DESC]; \
static uint8_t CONCAT2(NAME, _buf_rx_)[RX_SIZE]; \
- static int CONCAT2(NAME, _is_reset_); \
- static void CONCAT2(NAME, _deferred_tx_)(void); \
- DECLARE_DEFERRED(CONCAT2(NAME, _deferred_tx_)); \
+ static uint8_t CONCAT2(NAME, _tx_in_progress_); \
static void CONCAT2(NAME, _deferred_rx_)(void); \
DECLARE_DEFERRED(CONCAT2(NAME, _deferred_rx_)); \
static int CONCAT2(NAME, _rx_handled); \
static size_t CONCAT2(NAME, _tx_handled); \
struct usb_stream_config const NAME = { \
.endpoint = ENDPOINT, \
- .is_reset = &CONCAT2(NAME, _is_reset_), \
+ .tx_in_progress = &CONCAT2(NAME, _tx_in_progress_), \
.in_desc = &CONCAT2(NAME, _in_desc_)[0], \
.out_desc = &CONCAT2(NAME, _out_desc_), \
- .deferred_tx = &CONCAT2(NAME, _deferred_tx__data), \
.deferred_rx = &CONCAT2(NAME, _deferred_rx__data), \
.tx_size = TX_SIZE, \
.rx_size = RX_SIZE, \
@@ -172,8 +169,6 @@ extern struct producer_ops const usb_stream_producer_ops;
.wMaxPacketSize = RX_SIZE, \
.bInterval = 0, \
}; \
- static void CONCAT2(NAME, _deferred_tx_)(void) \
- { tx_stream_handler(&NAME); } \
static void CONCAT2(NAME, _deferred_rx_)(void) \
{ rx_stream_handler(&NAME); } \
static void CONCAT2(NAME, _ep_tx)(void) \
@@ -218,7 +213,6 @@ extern struct producer_ops const usb_stream_producer_ops;
* Handle USB and Queue request in a deferred callback.
*/
void rx_stream_handler(struct usb_stream_config const *config);
-void tx_stream_handler(struct usb_stream_config const *config);
/*
* These functions are used by the trampoline functions defined above to