aboutsummaryrefslogtreecommitdiff
path: root/example-cdc
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2016-05-17 17:51:41 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2016-05-17 17:51:41 +0900
commitdce6c70ffc2fdee9dd37fe68413babf618bb12b0 (patch)
treeabf78e743f16e278c8b325b9f2959e276f2552b9 /example-cdc
parent3651aa64b48d46fa8572a94b23c291d81e9d84ea (diff)
more fix for chopstx_poll
Diffstat (limited to 'example-cdc')
-rw-r--r--example-cdc/sample.c128
-rw-r--r--example-cdc/stream.h26
-rw-r--r--example-cdc/tty.h7
-rw-r--r--example-cdc/usb-cdc.c440
4 files changed, 325 insertions, 276 deletions
diff --git a/example-cdc/sample.c b/example-cdc/sample.c
index 9b9a4a6..699c854 100644
--- a/example-cdc/sample.c
+++ b/example-cdc/sample.c
@@ -5,7 +5,7 @@
#include "sys.h" /* for set_led */
#include "usb_lld.h"
-#include "stream.h"
+#include "tty.h"
static chopstx_mutex_t mtx;
static chopstx_cond_t cnd0;
@@ -54,61 +54,12 @@ blk (void *arg)
return NULL;
}
-#define INTR_REQ_USB 20
-
-static void *
-usb_intr (void *arg)
-{
- extern void usb_lld_init (uint8_t feature);
- extern void usb_interrupt_handler (void);
-
- chopstx_intr_t interrupt;
-
- (void)arg;
-#if defined(OLDER_SYS_H)
- /*
- * Historically (before sys < 3.0), NVIC priority setting for USB
- * interrupt was done in usb_lld_sys_init. Thus this code.
- *
- * When USB interrupt occurs between usb_lld_init (which assumes
- * ISR) and chopstx_claim_irq (which clears pending interrupt),
- * invocation of usb_interrupt_handler won't occur.
- *
- * Calling usb_interrupt_handler is no harm even if there were no
- * interrupts, thus, we call it unconditionally here, just in case
- * if there is a request.
- *
- * We can't call usb_lld_init after chopstx_claim_irq, as
- * usb_lld_init does its own setting for NVIC. Calling
- * chopstx_claim_irq after usb_lld_init overrides that.
- *
- */
- usb_lld_init (0x80); /* Bus powered. */
- chopstx_claim_irq (&interrupt, INTR_REQ_USB);
- usb_interrupt_handler ();
-#else
- chopstx_claim_irq (&interrupt, INTR_REQ_USB);
- usb_lld_init (0x80); /* Bus powered. */
-#endif
-
- while (1)
- {
- chopstx_intr_wait (&interrupt);
-
- /* Process interrupt. */
- usb_interrupt_handler ();
- }
-
- return NULL;
-}
#define PRIO_PWM 3
#define PRIO_BLK 2
-#define PRIO_INTR 4
extern uint8_t __process1_stack_base__, __process1_stack_size__;
extern uint8_t __process2_stack_base__, __process2_stack_size__;
-extern uint8_t __process3_stack_base__, __process3_stack_size__;
const uint32_t __stackaddr_pwm = (uint32_t)&__process1_stack_base__;
const size_t __stacksize_pwm = (size_t)&__process1_stack_size__;
@@ -116,9 +67,6 @@ const size_t __stacksize_pwm = (size_t)&__process1_stack_size__;
const uint32_t __stackaddr_blk = (uint32_t)&__process2_stack_base__;
const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
-const uint32_t __stackaddr_intr = (uint32_t)&__process3_stack_base__;
-const size_t __stacksize_intr = (size_t)&__process3_stack_size__;
-
static char hexchar (uint8_t x)
{
@@ -132,24 +80,11 @@ static char hexchar (uint8_t x)
}
-static int
-check_recv (void *arg)
-{
- struct stream *s = arg;
- if ((s->flags & FLAG_CONNECTED) == 0)
- return 1;
- if ((s->flags & FLAG_RECV_AVAIL))
- return 1;
- return 0;
-}
-
-
int
main (int argc, const char *argv[])
{
- struct stream *st;
+ struct tty *tty;
uint8_t count;
- extern uint32_t bDeviceState;
(void)argc;
(void)argv;
@@ -158,14 +93,10 @@ main (int argc, const char *argv[])
chopstx_cond_init (&cnd0);
chopstx_cond_init (&cnd1);
- st = stream_open ();
-
m = 10;
chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL);
chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL);
- chopstx_create (PRIO_INTR, __stackaddr_intr, __stacksize_intr,
- usb_intr, NULL);
chopstx_usec_wait (200*1000);
@@ -175,67 +106,52 @@ main (int argc, const char *argv[])
chopstx_mutex_unlock (&mtx);
u = 1;
- while (bDeviceState != CONFIGURED)
- chopstx_usec_wait (500*1000);
+
+ tty = tty_open ();
+ tty_wait_configured (tty);
count = 0;
+ m = 50;
while (1)
{
- uint8_t s[64];
+ uint8_t s[128];
u = 1;
- if (stream_wait_connection (st) < 0)
- {
- chopstx_usec_wait (1000*1000);
- continue;
- }
+ tty_wait_connection (tty);
chopstx_usec_wait (500*1000);
/* Send ZLP at the beginning. */
- stream_send (st, s, 0);
+ tty_send (tty, s, 0);
memcpy (s, "xx: Hello, World with Chopstx!\r\n", 32);
s[0] = hexchar (count >> 4);
s[1] = hexchar (count & 0x0f);
count++;
- if (stream_send (st, s, 32) < 0)
+ if (tty_send (tty, s, 32) < 0)
continue;
while (1)
{
int size;
uint32_t usec;
- struct chx_poll_cond poll_desc;
-
- poll_desc.type = CHOPSTX_POLL_COND;
- poll_desc.ready = 0;
- poll_desc.cond = &st->cnd;
- poll_desc.mutex = &st->mtx;
- poll_desc.check = check_recv;
- poll_desc.arg = st;
- /* With chopstx_poll, we can do timed cond_wait */
usec = 3000000; /* 3.0 seconds */
- if (chopstx_poll (&usec, 1, &poll_desc))
- {
- size = stream_recv (st, s + 4);
+ size = tty_recv (tty, s + 4, &usec);
+ if (size < 0)
+ break;
- if (size < 0)
+ if (usec)
+ {
+ s[0] = hexchar (size >> 4);
+ s[1] = hexchar (size & 0x0f);
+ s[2] = ':';
+ s[3] = ' ';
+ s[size + 4] = '\r';
+ s[size + 5] = '\n';
+ if (tty_send (tty, s, size + 6) < 0)
break;
-
- if (size >= 0)
- {
- s[0] = hexchar (size >> 4);
- s[1] = hexchar (size & 0x0f);
- s[2] = ':';
- s[3] = ' ';
- s[size + 4] = '\r';
- s[size + 5] = '\n';
- if (stream_send (st, s, size + 6) < 0)
- break;
- }
}
u ^= 1;
diff --git a/example-cdc/stream.h b/example-cdc/stream.h
deleted file mode 100644
index dbbfb5f..0000000
--- a/example-cdc/stream.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#define BUFSIZE 128
-#define FLAG_CONNECTED (1 << 0)
-#define FLAG_SEND_AVAIL (1 << 1)
-#define FLAG_RECV_AVAIL (1 << 2)
-
-/*
- * Current implementation is synchronous and buffers are not yet used.
- */
-struct stream {
- chopstx_mutex_t mtx;
- chopstx_cond_t cnd;
- int sending;
- unsigned int recv_len;
- uint8_t recv_buf[BUFSIZE]; /* Not yet used. */
- uint8_t buf_send[BUFSIZE]; /* Not yet used. */
- uint8_t cnt_send_head; /* Not yet used. */
- uint8_t cnt_send_tail; /* Not yet used. */
- uint8_t cnt_recv_head; /* Not yet used. */
- uint8_t cnt_recv_tail; /* Not yet used. */
- uint32_t flags;
-};
-
-struct stream *stream_open (void);
-int stream_wait_connection (struct stream *st);
-int stream_send (struct stream *st, uint8_t *buf, uint8_t count);
-int stream_recv (struct stream *st, uint8_t *buf);
diff --git a/example-cdc/tty.h b/example-cdc/tty.h
new file mode 100644
index 0000000..a2cee4e
--- /dev/null
+++ b/example-cdc/tty.h
@@ -0,0 +1,7 @@
+struct tty;
+
+struct tty *tty_open (void);
+void tty_wait_configured (struct tty *tty);
+void tty_wait_connection (struct tty *tty);
+int tty_send (struct tty *tty, uint8_t *buf, int count);
+int tty_recv (struct tty *tty, uint8_t *buf, uint32_t *timeout);
diff --git a/example-cdc/usb-cdc.c b/example-cdc/usb-cdc.c
index eadeb6e..adf2773 100644
--- a/example-cdc/usb-cdc.c
+++ b/example-cdc/usb-cdc.c
@@ -3,17 +3,26 @@
#include <chopstx.h>
#include <string.h>
#include "usb_lld.h"
-#include "stream.h"
-
-static uint8_t send_buf[64];
-static unsigned int send_len;
-
-static unsigned int recv_len;
-
-static uint8_t inputline[64];
-static unsigned int inputline_len;
+#include "tty.h"
+
+#define BUFSIZE 128
+#define FLAG_CONNECTED (1 << 0)
+#define FLAG_SEND_READY (1 << 1)
+#define FLAG_RECV_AVAIL (1 << 2)
+
+struct tty {
+ uint32_t flags;
+ chopstx_mutex_t mtx;
+ chopstx_cond_t cnd;
+ chopstx_intr_t intr;
+ uint8_t inputline[BUFSIZE]; /* Line editing is supported */
+ uint8_t send_buf[BUFSIZE]; /* Sending ring buffer for echo back */
+ uint32_t inputline_len : 16;
+ uint32_t send_head : 8;
+ uint32_t send_tail : 8;
+};
-static struct stream stream;
+static struct tty tty;
#define ENDP0_RXADDR (0x40)
#define ENDP0_TXADDR (0x80)
@@ -166,7 +175,7 @@ static const uint8_t vcom_string3[28] = {
#define NUM_INTERFACES 2
-uint32_t bDeviceState = UNCONNECTED; /* USB device status */
+static uint32_t bDeviceState = UNCONNECTED; /* USB device status */
void
@@ -177,10 +186,10 @@ usb_cb_device_reset (void)
/* Initialize Endpoint 0 */
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
- chopstx_mutex_lock (&stream.mtx);
- stream.flags = 0;
+ chopstx_mutex_lock (&tty.mtx);
+ tty.flags = 0;
bDeviceState = ATTACHED;
- chopstx_mutex_unlock (&stream.mtx);
+ chopstx_mutex_unlock (&tty.mtx);
}
@@ -195,13 +204,11 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
&& USB_SETUP_SET (req) && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
{
/* Open/close the connection. */
- chopstx_mutex_lock (&stream.mtx);
- stream.flags &= ~FLAG_CONNECTED;
- stream.flags |= ((arg->value & CDC_CTRL_DTR) != 0)? FLAG_CONNECTED : 0;
- chopstx_cond_signal (&stream.cnd);
- recv_len = 0;
- usb_lld_rx_enable (ENDP3);
- chopstx_mutex_unlock (&stream.mtx);
+ chopstx_mutex_lock (&tty.mtx);
+ tty.flags &= ~FLAG_CONNECTED;
+ tty.flags |= ((arg->value & CDC_CTRL_DTR) != 0)? FLAG_CONNECTED : 0;
+ chopstx_cond_signal (&tty.cnd);
+ chopstx_mutex_unlock (&tty.mtx);
}
}
@@ -404,26 +411,50 @@ usb_cb_interface (uint8_t cmd, struct req_args *arg)
}
+/*
+ * Put a character into the ring buffer to be send back.
+ */
static void
-stream_echo_char (int c)
+put_char_to_ringbuffer (int c)
{
- chopstx_mutex_lock (&stream.mtx);
- if (send_len < sizeof (send_buf))
- send_buf[send_len++] = c;
- else
- {
- /* All that we can is ignoring the output. */
- ;
- }
+ uint32_t next = (tty.send_tail + 1) % BUFSIZE;
+
+ if (tty.send_head == next)
+ /* full */
+ /* All that we can do is ignore this char. */
+ return;
+
+ tty.send_buf[tty.send_tail] = c;
+ tty.send_tail = next;
+}
- if (stream.sending == 0)
+/*
+ * Get characters from ring buffer into S.
+ */
+static int
+get_chars_from_ringbuffer (uint8_t *s, int len)
+{
+ int i = 0;
+
+ if (tty.send_head == tty.send_tail)
+ /* Empty */
+ return i;
+
+ do
{
- usb_lld_txcpy (send_buf, ENDP1, 0, send_len);
- usb_lld_tx_enable (ENDP1, send_len);
- send_len = 0;
- stream.sending = 1;
+ s[i++] = tty.send_buf[tty.send_head];
+ tty.send_head = (tty.send_head + 1) % BUFSIZE;
}
- chopstx_mutex_unlock (&stream.mtx);
+ while (tty.send_head != tty.send_tail && i < len);
+
+ return i;
+}
+
+
+static void
+tty_echo_char (int c)
+{
+ put_char_to_ringbuffer (c);
}
@@ -432,24 +463,13 @@ usb_cb_tx_done (uint8_t ep_num)
{
if (ep_num == ENDP1)
{
- chopstx_mutex_lock (&stream.mtx);
- stream.sending = 0;
- if (send_len)
+ chopstx_mutex_lock (&tty.mtx);
+ if ((tty.flags & FLAG_SEND_READY) == 0)
{
- stream.sending = 1;
- usb_lld_txcpy (send_buf, ENDP1, 0, send_len);
- usb_lld_tx_enable (ENDP1, send_len);
- send_len = 0;
+ tty.flags |= FLAG_SEND_READY;
+ chopstx_cond_signal (&tty.cnd);
}
- else
- {
- if ((stream.flags & FLAG_SEND_AVAIL))
- {
- stream.flags &= ~FLAG_SEND_AVAIL;
- chopstx_cond_signal (&stream.cnd);
- }
- }
- chopstx_mutex_unlock (&stream.mtx);
+ chopstx_mutex_unlock (&tty.mtx);
}
else if (ep_num == ENDP2)
{
@@ -458,65 +478,62 @@ usb_cb_tx_done (uint8_t ep_num)
}
-static void
-stream_input_char (int c)
+static int
+tty_input_char (int c)
{
unsigned int i;
+ int r = 0;
/* Process DEL, C-U, C-R, and RET as editing command. */
+ chopstx_mutex_lock (&tty.mtx);
switch (c)
{
case 0x0d: /* Control-M */
- stream_echo_char (0x0d);
- stream_echo_char (0x0a);
- chopstx_mutex_lock (&stream.mtx);
- if ((stream.flags & FLAG_RECV_AVAIL) == 0)
- {
- memcpy (stream.recv_buf, inputline, inputline_len);
- stream.recv_len = inputline_len;
- stream.flags |= FLAG_RECV_AVAIL;
- chopstx_cond_signal (&stream.cnd);
- }
- chopstx_mutex_unlock (&stream.mtx);
- inputline_len = 0;
+ tty_echo_char (0x0d);
+ tty_echo_char (0x0a);
+ tty.flags |= FLAG_RECV_AVAIL;
+ chopstx_cond_signal (&tty.cnd);
+ r = 1;
break;
case 0x12: /* Control-R */
- stream_echo_char ('^');
- stream_echo_char ('R');
- stream_echo_char (0x0d);
- stream_echo_char (0x0a);
- for (i = 0; i < inputline_len; i++)
- stream_echo_char (inputline[i]);
+ tty_echo_char ('^');
+ tty_echo_char ('R');
+ tty_echo_char (0x0d);
+ tty_echo_char (0x0a);
+ for (i = 0; i < tty.inputline_len; i++)
+ tty_echo_char (tty.inputline[i]);
break;
case 0x15: /* Control-U */
- for (i = 0; i < inputline_len; i++)
+ for (i = 0; i < tty.inputline_len; i++)
{
- stream_echo_char (0x08);
- stream_echo_char (0x20);
- stream_echo_char (0x08);
+ tty_echo_char (0x08);
+ tty_echo_char (0x20);
+ tty_echo_char (0x08);
}
- inputline_len = 0;
+ tty.inputline_len = 0;
break;
case 0x7f: /* DEL */
- if (inputline_len > 0)
+ if (tty.inputline_len > 0)
{
- stream_echo_char (0x08);
- stream_echo_char (0x20);
- stream_echo_char (0x08);
- inputline_len--;
+ tty_echo_char (0x08);
+ tty_echo_char (0x20);
+ tty_echo_char (0x08);
+ tty.inputline_len--;
}
break;
default:
- if (inputline_len < sizeof (inputline))
+ if (tty.inputline_len < sizeof (tty.inputline))
{
- stream_echo_char (c);
- inputline[inputline_len++] = c;
+ tty_echo_char (c);
+ tty.inputline[tty.inputline_len++] = c;
}
else
/* Beep */
- stream_echo_char (0x0a);
+ tty_echo_char (0x0a);
break;
}
+ chopstx_mutex_unlock (&tty.mtx);
+ return r;
}
void
@@ -531,93 +548,228 @@ usb_cb_rx_ready (uint8_t ep_num)
r = usb_lld_rx_data_len (ENDP3);
usb_lld_rxcpy (recv_buf, ep_num, 0, r);
for (i = 0; i < r; i++)
- stream_input_char (recv_buf[i]);
+ if (tty_input_char (recv_buf[i]))
+ break;
- usb_lld_rx_enable (ENDP3);
+ chopstx_mutex_lock (&tty.mtx);
+ if ((tty.flags & FLAG_RECV_AVAIL) == 0)
+ usb_lld_rx_enable (ENDP3);
+ chopstx_mutex_unlock (&tty.mtx);
}
}
-struct stream *
-stream_open (void)
+static void *tty_main (void *arg);
+
+#define INTR_REQ_USB 20
+#define PRIO_TTY 4
+
+extern uint8_t __process3_stack_base__, __process3_stack_size__;
+const uint32_t __stackaddr_tty = (uint32_t)&__process3_stack_base__;
+const size_t __stacksize_tty = (size_t)&__process3_stack_size__;
+
+struct tty *
+tty_open (void)
{
- chopstx_mutex_init (&stream.mtx);
- chopstx_cond_init (&stream.cnd);
- return &stream;
+ chopstx_mutex_init (&tty.mtx);
+ chopstx_cond_init (&tty.cnd);
+ tty.flags = 0;
+ tty.send_head = tty.send_tail = 0;
+ tty.inputline_len = 0;
+
+ chopstx_create (PRIO_TTY, __stackaddr_tty, __stacksize_tty,
+ tty_main, NULL);
+ return &tty;
}
-int
-stream_wait_connection (struct stream *st)
+
+static void *
+tty_main (void *arg)
{
- chopstx_mutex_lock (&st->mtx);
- while ((stream.flags & FLAG_CONNECTED) == 0)
- chopstx_cond_wait (&st->cnd, &st->mtx);
- chopstx_mutex_unlock (&st->mtx);
- stream.flags &= ~FLAG_SEND_AVAIL;
- return 0;
+ (void)arg;
+
+#if defined(OLDER_SYS_H)
+ /*
+ * Historically (before sys < 3.0), NVIC priority setting for USB
+ * interrupt was done in usb_lld_sys_init. Thus this code.
+ *
+ * When USB interrupt occurs between usb_lld_init (which assumes
+ * ISR) and chopstx_claim_irq (which clears pending interrupt),
+ * invocation of usb_interrupt_handler won't occur.
+ *
+ * Calling usb_interrupt_handler is no harm even if there were no
+ * interrupts, thus, we call it unconditionally here, just in case
+ * if there is a request.
+ *
+ * We can't call usb_lld_init after chopstx_claim_irq, as
+ * usb_lld_init does its own setting for NVIC. Calling
+ * chopstx_claim_irq after usb_lld_init overrides that.
+ *
+ */
+ usb_lld_init (0x80); /* Bus powered. */
+ chopstx_claim_irq (&tty.intr, INTR_REQ_USB);
+ usb_interrupt_handler ();
+#else
+ chopstx_claim_irq (&tty.intr, INTR_REQ_USB);
+ usb_lld_init (0x80); /* Bus powered. */
+#endif
+
+ while (1)
+ {
+ chopstx_poll (NULL, 1, &tty.intr);
+ if (tty.intr.ready)
+ usb_interrupt_handler ();
+
+ chopstx_mutex_lock (&tty.mtx);
+ if (bDeviceState == CONFIGURED
+ && (tty.flags & FLAG_CONNECTED)
+ && (tty.flags & FLAG_SEND_READY))
+ {
+ uint8_t line[32];
+ int len = get_chars_from_ringbuffer (line, sizeof (len));
+
+ if (len)
+ {
+ usb_lld_txcpy (line, ENDP1, 0, len);
+ usb_lld_tx_enable (ENDP1, len);
+ tty.flags &= ~FLAG_SEND_READY;
+ }
+ }
+ chopstx_mutex_unlock (&tty.mtx);
+ }
+
+ return NULL;
+}
+
+
+void
+tty_wait_configured (struct tty *t)
+{
+ chopstx_mutex_lock (&t->mtx);
+ while (bDeviceState != CONFIGURED)
+ chopstx_cond_wait (&t->cnd, &t->mtx);
+ chopstx_mutex_unlock (&t->mtx);
}
+void
+tty_wait_connection (struct tty *t)
+{
+ chopstx_mutex_lock (&t->mtx);
+ while ((t->flags & FLAG_CONNECTED) == 0)
+ chopstx_cond_wait (&t->cnd, &t->mtx);
+ t->flags |= FLAG_SEND_READY;
+ t->flags &= ~FLAG_RECV_AVAIL;
+ t->send_head = t->send_tail = 0;
+ t->inputline_len = 0;
+ chopstx_mutex_unlock (&t->mtx);
+}
+
+static int
+check_tx (struct tty *t)
+{
+ if ((t->flags & FLAG_SEND_READY))
+ /* TX done */
+ return 1;
+ if ((t->flags & FLAG_CONNECTED) == 0)
+ /* Disconnected */
+ return -1;
+ return 0;
+}
+
int
-stream_send (struct stream *st, uint8_t *buf, uint8_t count)
+tty_send (struct tty *t, uint8_t *buf, int len)
{
- int r = 0;
+ int r;
+ uint8_t *p;
+ int count;
- chopstx_mutex_lock (&st->mtx);
- if ((stream.flags & FLAG_CONNECTED) == 0)
- r = -1;
- else
+ p = buf;
+ count = len >= 64 ? 64 : len;
+
+ while (1)
{
- stream.sending = 1;
- usb_lld_txcpy (buf, ENDP1, 0, count);
- usb_lld_tx_enable (ENDP1, count);
- stream.flags |= FLAG_SEND_AVAIL;
- do
+ chopstx_mutex_lock (&t->mtx);
+ while ((r = check_tx (t)) == 0)
+ chopstx_cond_wait (&t->cnd, &t->mtx);
+ if (r > 0)
{
- chopstx_cond_wait (&st->cnd, &st->mtx);
- if ((stream.flags & FLAG_SEND_AVAIL) == 0)
- break;
- else if ((stream.flags & FLAG_CONNECTED) == 0)
- {
- r = -1;
- break;
- }
+ usb_lld_txcpy (p, ENDP1, 0, count);
+ usb_lld_tx_enable (ENDP1, count);
+ t->flags &= ~FLAG_SEND_READY;
}
- while (1);
+ chopstx_mutex_unlock (&t->mtx);
+
+ len -= count;
+ p += count;
+ if (len == 0 && count != 64)
+ /*
+ * The size of the last packet should be != 0
+ * If 64, send ZLP (zelo length packet)
+ */
+ break;
+ count = len >= 64 ? 64 : len;
}
- stream.sending = 0;
- chopstx_mutex_unlock (&st->mtx);
+
return r;
}
+static int
+check_rx (void *arg)
+{
+ struct tty *t = arg;
+
+ if ((t->flags & FLAG_RECV_AVAIL))
+ /* RX */
+ return 1;
+ if ((t->flags & FLAG_CONNECTED) == 0)
+ /* Disconnected */
+ return 1;
+ return 0;
+}
+
int
-stream_recv (struct stream *st, uint8_t *buf)
+tty_recv (struct tty *t, uint8_t *buf, uint32_t *timeout)
{
int r;
+ chopstx_poll_cond_t poll_desc;
+
+ chopstx_mutex_unlock (&t->mtx);
+ if ((t->flags & FLAG_RECV_AVAIL) == 0)
+ usb_lld_rx_enable (ENDP3);
+ chopstx_mutex_unlock (&t->mtx);
+
+ poll_desc.type = CHOPSTX_POLL_COND;
+ poll_desc.ready = 0;
+ poll_desc.cond = &t->cnd;
+ poll_desc.mutex = &t->mtx;
+ poll_desc.check = check_rx;
+ poll_desc.arg = t;
+
+ while (1)
+ {
+ chopstx_poll (timeout, 1, &poll_desc);
+ chopstx_mutex_lock (&t->mtx);
+ r = check_rx (t);
+ chopstx_mutex_unlock (&t->mtx);
+ if (r || (timeout != NULL && *timeout == 0))
+ break;
+ }
- chopstx_mutex_lock (&st->mtx);
- if ((stream.flags & FLAG_CONNECTED) == 0)
+ chopstx_mutex_lock (&t->mtx);
+ if ((t->flags & FLAG_CONNECTED) == 0)
r = -1;
- else
+ else if ((t->flags & FLAG_RECV_AVAIL))
{
- while (1)
- {
- if ((stream.flags & FLAG_RECV_AVAIL))
- {
- r = stream.recv_len;
- memcpy (buf, stream.recv_buf, r);
- stream.flags &= ~FLAG_RECV_AVAIL;
- break;
- }
- else if ((stream.flags & FLAG_CONNECTED) == 0)
- {
- r = -1;
- break;
- }
- chopstx_cond_wait (&st->cnd, &st->mtx);
- }
+ r = t->inputline_len;
+ memcpy (buf, t->inputline, r);
+ t->flags &= ~FLAG_RECV_AVAIL;
+ usb_lld_rx_enable (ENDP3);
+ t->inputline_len = 0;
}
- chopstx_mutex_unlock (&st->mtx);
+ else
+ r = 0;
+ chopstx_mutex_unlock (&t->mtx);
return r;
}