From 0bbb43dd3a943285ffb5462db468f7af29c4bbfb Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Mon, 18 Apr 2016 17:23:10 +0900
Subject: Fix USB driver and example

---
 example-fs-bb48/sample.c    |  11 ++--
 example-fs-bb48/stream.h    |   4 +-
 example-fs-bb48/usb-cdc.c   | 128 +++++++++++++++++++++++++++++++++++++++++---
 example-fs-bb48/usb_kl27z.c |   2 +-
 4 files changed, 132 insertions(+), 13 deletions(-)

(limited to 'example-fs-bb48')

diff --git a/example-fs-bb48/sample.c b/example-fs-bb48/sample.c
index 92ecc9b..aa69144 100644
--- a/example-fs-bb48/sample.c
+++ b/example-fs-bb48/sample.c
@@ -199,7 +199,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++;
@@ -209,14 +209,19 @@ main (int argc, const char *argv[])
 
       while (1)
 	{
-	  int size = stream_recv (st, s);
+	  int size = stream_recv (st, s + 4);
 
 	  if (size < 0)
 	    break;
 
 	  if (size >= 0)
 	    {
-	      if (stream_send (st, s, size) < 0)
+	      s[0] = hexchar (size >> 4);
+	      s[1] = hexchar (size & 0x0f);
+
+	      s[size + 4] = '\r';
+	      s[size + 5] = '\n';
+	      if (stream_send (st, s, size + 6) < 0)
 		break;
 	    }
 
diff --git a/example-fs-bb48/stream.h b/example-fs-bb48/stream.h
index 15cbe63..77b7014 100644
--- a/example-fs-bb48/stream.h
+++ b/example-fs-bb48/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];
   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-fs-bb48/usb-cdc.c b/example-fs-bb48/usb-cdc.c
index 290a4fd..30d4ccd 100644
--- a/example-fs-bb48/usb-cdc.c
+++ b/example-fs-bb48/usb-cdc.c
@@ -1,9 +1,20 @@
 #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 uint8_t send_buf1[64];
+
+static uint8_t recv_buf[64];
+static unsigned int recv_len;
+
+static uint8_t inputline[64];
+static unsigned int inputline_len;
+
 static struct stream stream;
 
 #define USB_CDC_REQ_SET_LINE_CODING             0x20
@@ -184,6 +195,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, recv_buf, 64);
       chopstx_mutex_unlock (&stream.mtx);
     }
 }
@@ -389,36 +402,133 @@ 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)
+    {
+      memcpy (send_buf1, send_buf, send_len);
+      usb_lld_tx_enable (ENDP1, send_buf1, 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;
+	  memcpy (send_buf1, send_buf, send_len);
+	  usb_lld_tx_enable (ENDP1, send_buf1, 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)
+{
+  if (ep_num == ENDP3)
+    {
+      int i, r;
+
+      r = usb_lld_rx_data_len (ENDP3);
+      for (i = 0; i < r; i++)
+	stream_input_char (recv_buf[i]);
+
+      usb_lld_rx_enable (ENDP3, recv_buf, 64);
     }
 }
 
@@ -452,6 +562,7 @@ stream_send (struct stream *st, uint8_t *buf, uint8_t count)
     r = -1;
   else
     {
+      stream.sending = 1;
       usb_lld_tx_enable (ENDP1, buf, count);
       stream.flags |= FLAG_SEND_AVAIL;
       do
@@ -467,6 +578,7 @@ stream_send (struct stream *st, uint8_t *buf, uint8_t count)
 	}
       while (1);
     }
+  stream.sending = 0;
   chopstx_mutex_unlock (&st->mtx);
   return r;
 }
@@ -482,14 +594,14 @@ stream_recv (struct stream *st, uint8_t *buf)
     r = -1;
   else
     {
-      usb_lld_rx_enable (ENDP3, buf, 64);
       stream.flags &= ~FLAG_RECV_AVAIL;
       do
 	{
 	  chopstx_cond_wait (&st->cnd, &st->mtx);
 	  if ((stream.flags & FLAG_RECV_AVAIL))
 	    {
-	      r = usb_lld_rx_data_len (ENDP3);
+	      r = stream.recv_len;
+	      memcpy (buf, stream.recv_buf, r);
 	      break;
 	    }
 	  else if ((stream.flags & FLAG_CONNECTED) == 0)
diff --git a/example-fs-bb48/usb_kl27z.c b/example-fs-bb48/usb_kl27z.c
index 09a65f7..4e35753 100644
--- a/example-fs-bb48/usb_kl27z.c
+++ b/example-fs-bb48/usb_kl27z.c
@@ -863,8 +863,8 @@ handle_transaction (uint8_t stat)
       if ((stat & 0x08) == 0)
 	{
 	  dev_p->recv++;
-	  usb_cb_rx_ready (ep_num);
 	  ep[ep_num].rx_odd ^= 1;
+	  usb_cb_rx_ready (ep_num);
 	}
       else
 	{
-- 
cgit v1.2.3