From fabd271196710655a508b8b2727945ddc581d2ae Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Thu, 12 May 2016 18:14:47 +0900
Subject: Update example-cdc

---
 example-cdc/sample.c  |  54 +++++++++++++++----
 example-cdc/sample.ld |   8 +--
 example-cdc/stream.h  |   4 +-
 example-cdc/usb-cdc.c | 140 +++++++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 178 insertions(+), 28 deletions(-)

(limited to 'example-cdc')

diff --git a/example-cdc/sample.c b/example-cdc/sample.c
index 7a6b99f..17b7cd5 100644
--- a/example-cdc/sample.c
+++ b/example-cdc/sample.c
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <chopstx.h>
+
 #include "sys.h" /* for set_led */
 #include "usb_lld.h"
 #include "stream.h"
@@ -10,7 +11,6 @@ static chopstx_mutex_t mtx;
 static chopstx_cond_t cnd0;
 static chopstx_cond_t cnd1;
 
-
 static uint8_t u, v;
 static uint8_t m;		/* 0..100 */
 
@@ -113,8 +113,10 @@ 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)
 {
+  x &= 0x0f;
   if (x <= 0x09)
     return '0' + x;
   else if (x <= 0x0f)
@@ -124,6 +126,18 @@ 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[])
 {
@@ -163,6 +177,7 @@ main (int argc, const char *argv[])
     {
       uint8_t s[64];
 
+      u = 1;
       if (stream_wait_connection (st) < 0)
 	{
 	  chopstx_usec_wait (1000*1000);
@@ -174,7 +189,7 @@ main (int argc, const char *argv[])
       /* Send ZLP at the beginning.  */
       stream_send (st, s, 0);
 
-      memcpy (s, "xx: Hello, World with Chopstx!\r\n\000", 32);
+      memcpy (s, "xx: Hello, World with Chopstx!\r\n", 32);
       s[0] = hexchar (count >> 4);
       s[1] = hexchar (count & 0x0f);
       count++;
@@ -184,15 +199,36 @@ main (int argc, const char *argv[])
 
       while (1)
 	{
-	  int size = stream_recv (st, s);
-
-	  if (size < 0)
-	    break;
-
-	  if (size >= 0)
+	  int size;
+	  uint32_t usec;
+	  struct chx_poll_desc poll_desc;
+
+	  poll_desc.type = CHOPSTX_POLL_COND;
+	  poll_desc.c.cond = &st->cnd;
+	  poll_desc.c.mutex = &st->mtx;
+	  poll_desc.c.check = check_recv;
+	  poll_desc.c.arg = st;
+
+	  /* With chopstx_poll, we can do timed cond_wait */
+	  usec = 3000000;	/* 3.0 seconds */
+	  if (chopstx_poll (&usec, 1, &poll_desc))
 	    {
-	      if (stream_send (st, s, size) < 0)
+	      size = stream_recv (st, s + 4);
+
+	      if (size < 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/sample.ld b/example-cdc/sample.ld
index dd53a0e..9b7eca3 100644
--- a/example-cdc/sample.ld
+++ b/example-cdc/sample.ld
@@ -2,10 +2,10 @@
  * ST32F103 memory setup.
  */
 __main_stack_size__     = 0x0100;  /* Exception handlers     */
-__process0_stack_size__  = 0x0200;  /* Main program           */
-__process1_stack_size__  = 0x0200; /* first thread program */
-__process2_stack_size__  = 0x0200; /* second thread program */
-__process3_stack_size__  = 0x0200; /* third thread program */
+__process0_stack_size__  = 0x0400; /* Main program           */
+__process1_stack_size__  = 0x0200; /* first thread program   */
+__process2_stack_size__  = 0x0200; /* second thread program  */
+__process3_stack_size__  = 0x0200; /* third thread program   */
 
 MEMORY
 {
diff --git a/example-cdc/stream.h b/example-cdc/stream.h
index 15cbe63..dbbfb5f 100644
--- a/example-cdc/stream.h
+++ b/example-cdc/stream.h
@@ -9,8 +9,10 @@
 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 buf_recv[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. */
diff --git a/example-cdc/usb-cdc.c b/example-cdc/usb-cdc.c
index 6af47a8..eadeb6e 100644
--- a/example-cdc/usb-cdc.c
+++ b/example-cdc/usb-cdc.c
@@ -1,9 +1,18 @@
 #include <stdint.h>
 #include <stdlib.h>
 #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;
+
 static struct stream stream;
 
 #define ENDP0_RXADDR        (0x40)
@@ -190,6 +199,8 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
       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);
     }
 }
@@ -393,36 +404,136 @@ usb_cb_interface (uint8_t cmd, struct req_args *arg)
 }
 
 
+static void
+stream_echo_char (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.  */
+      ;
+    }
+
+  if (stream.sending == 0)
+    {
+      usb_lld_txcpy (send_buf, ENDP1, 0, send_len);
+      usb_lld_tx_enable (ENDP1, send_len);
+      send_len = 0;
+      stream.sending = 1;
+    }
+  chopstx_mutex_unlock (&stream.mtx);
+}
+
+
 void
 usb_cb_tx_done (uint8_t ep_num)
 {
   if (ep_num == ENDP1)
     {
       chopstx_mutex_lock (&stream.mtx);
-      if ((stream.flags & FLAG_SEND_AVAIL))
+      stream.sending = 0;
+      if (send_len)
 	{
-	  stream.flags &= ~FLAG_SEND_AVAIL;
-	  chopstx_cond_signal (&stream.cnd);
+	  stream.sending = 1;
+	  usb_lld_txcpy (send_buf, ENDP1, 0, send_len);
+	  usb_lld_tx_enable (ENDP1, send_len);
+	  send_len = 0;
+	}
+      else
+	{
+	  if ((stream.flags & FLAG_SEND_AVAIL))
+	    {
+	      stream.flags &= ~FLAG_SEND_AVAIL;
+	      chopstx_cond_signal (&stream.cnd);
+	    }
 	}
       chopstx_mutex_unlock (&stream.mtx);
     }
   else if (ep_num == ENDP2)
     {
+      /* Nothing */
     }
 }
 
-void
-usb_cb_rx_ready (uint8_t ep_num)
+
+static void
+stream_input_char (int c)
 {
-  if (ep_num == ENDP3)
+  unsigned int i;
+
+  /* Process DEL, C-U, C-R, and RET as editing command. */
+  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;
+      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]);
+      break;
+    case 0x15: /* Control-U */
+      for (i = 0; i < inputline_len; i++)
+	{
+	  stream_echo_char (0x08);
+	  stream_echo_char (0x20);
+	  stream_echo_char (0x08);
+	}
+      inputline_len = 0;
+      break;
+    case 0x7f: /* DEL    */
+      if (inputline_len > 0)
+	{
+	  stream_echo_char (0x08);
+	  stream_echo_char (0x20);
+	  stream_echo_char (0x08);
+	  inputline_len--;
+	}
+      break;
+    default:
+      if (inputline_len < sizeof (inputline))
+	{
+	  stream_echo_char (c);
+	  inputline[inputline_len++] = c;
+	}
+      else
+	/* Beep */
+	stream_echo_char (0x0a);
+      break;
+    }
+}
+
+void
+usb_cb_rx_ready (uint8_t ep_num)
+{
+  uint8_t recv_buf[64];
+
+  if (ep_num == ENDP3)
+    {
+      int i, r;
+
+      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]);
+
+      usb_lld_rx_enable (ENDP3);
     }
 }
 
@@ -456,7 +567,9 @@ stream_send (struct stream *st, uint8_t *buf, uint8_t count)
     r = -1;
   else
     {
-      usb_lld_write (ENDP1, buf, count);
+      stream.sending = 1;
+      usb_lld_txcpy (buf, ENDP1, 0, count);
+      usb_lld_tx_enable (ENDP1, count);
       stream.flags |= FLAG_SEND_AVAIL;
       do
 	{
@@ -471,6 +584,7 @@ stream_send (struct stream *st, uint8_t *buf, uint8_t count)
 	}
       while (1);
     }
+  stream.sending = 0;
   chopstx_mutex_unlock (&st->mtx);
   return r;
 }
@@ -486,15 +600,13 @@ stream_recv (struct stream *st, uint8_t *buf)
     r = -1;
   else
     {
-      usb_lld_rx_enable (ENDP3);
-      stream.flags &= ~FLAG_RECV_AVAIL;
-      do
+      while (1)
 	{
-	  chopstx_cond_wait (&st->cnd, &st->mtx);
 	  if ((stream.flags & FLAG_RECV_AVAIL))
 	    {
-	      r = usb_lld_rx_data_len (ENDP3);
-	      usb_lld_rxcpy (buf, ENDP3, 0, r);
+	      r = stream.recv_len;
+	      memcpy (buf, stream.recv_buf, r);
+	      stream.flags &= ~FLAG_RECV_AVAIL;
 	      break;
 	    }
 	  else if ((stream.flags & FLAG_CONNECTED) == 0)
@@ -502,8 +614,8 @@ stream_recv (struct stream *st, uint8_t *buf)
 	      r = -1;
 	      break;
 	    }
+	  chopstx_cond_wait (&st->cnd, &st->mtx);
 	}
-      while (1);
     }
   chopstx_mutex_unlock (&st->mtx);
 
-- 
cgit v1.2.3