From fd8aee3cb0f9243f600b9576863ad5c8457529b6 Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Thu, 5 Nov 2015 13:54:49 +0900
Subject: CDC to be echo service.

---
 example-cdc/sample.c  |  58 ++++++++++++------------
 example-cdc/stream.h  |  24 ++++++++++
 example-cdc/usb-cdc.c | 119 ++++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 152 insertions(+), 49 deletions(-)
 create mode 100644 example-cdc/stream.h

(limited to 'example-cdc')

diff --git a/example-cdc/sample.c b/example-cdc/sample.c
index c95680f..4e61980 100644
--- a/example-cdc/sample.c
+++ b/example-cdc/sample.c
@@ -3,14 +3,13 @@
 #include <string.h>
 #include <chopstx.h>
 #include "sys.h" /* for set_led */
-#include "usb_lld.h" /* for set_led */
+#include "usb_lld.h"
+#include "stream.h"
 
 static chopstx_mutex_t mtx;
 static chopstx_cond_t cnd0;
 static chopstx_cond_t cnd1;
 
-chopstx_mutex_t usb_mtx;
-chopstx_cond_t cnd_usb;
 
 static uint8_t u, v;
 static uint8_t m;		/* 0..100 */
@@ -128,6 +127,7 @@ static char hexchar (uint8_t x)
 int
 main (int argc, const char *argv[])
 {
+  struct stream *st;
   uint8_t count;
 
   (void)argc;
@@ -137,8 +137,7 @@ main (int argc, const char *argv[])
   chopstx_cond_init (&cnd0);
   chopstx_cond_init (&cnd1);
 
-  chopstx_mutex_init (&usb_mtx);
-  chopstx_cond_init (&cnd_usb);
+  st = stream_open ();
 
   m = 10;
 
@@ -154,41 +153,38 @@ main (int argc, const char *argv[])
   chopstx_cond_signal (&cnd1);
   chopstx_mutex_unlock (&mtx);
 
+  count= 0;
   while (1)
     {
-      extern uint8_t connected;
-
-      count= 0;
+      uint8_t s[64];
       u = 1;
-      /* waiting USB connection */
-      chopstx_mutex_lock (&usb_mtx);
-      if (!connected)
-	chopstx_cond_wait (&cnd_usb, &usb_mtx);
-      chopstx_mutex_unlock (&usb_mtx);
+
+      if (stream_wait_connection (st) < 0)
+	{
+	  chopstx_usec_wait (1000*1000);
+	  continue;
+	}
+
+      memcpy (s, "xx: Hello, World with Chopstx!\r\n\000", 32);
+      s[0] = hexchar (count >> 4);
+      s[1] = hexchar (count & 0x0f);
+      count++;
+
+      if (stream_send (st, s, 32) < 0)
+	continue;
 
       while (1)
 	{
-	  char s[32];
+	  int size = stream_recv (st, s);
 
-	  u ^= 1;
-	  chopstx_usec_wait (200*1000*6);
-
-	  memcpy (s, "xx: Hello, World with Chopstx!\r\n", 32);
-	  s[0] = hexchar (count >> 4);
-	  s[1] = hexchar (count & 0x0f);
-	  count++;
-
-	  chopstx_mutex_lock (&usb_mtx);
-	  if (connected)
-	    {
-	      usb_lld_write (ENDP1, s, 32);
-	      chopstx_cond_wait (&cnd_usb, &usb_mtx);
-	    }
-	  else
+	  if (size < 0)
+	    break;
+
+	  if (stream_send (st, s, size) < 0)
 	    break;
-	  chopstx_mutex_unlock (&usb_mtx);
+
+	  u ^= 1;
 	}
-      chopstx_mutex_unlock (&usb_mtx);
     }
 
   return 0;
diff --git a/example-cdc/stream.h b/example-cdc/stream.h
new file mode 100644
index 0000000..15cbe63
--- /dev/null
+++ b/example-cdc/stream.h
@@ -0,0 +1,24 @@
+#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;
+  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. */
+  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/usb-cdc.c b/example-cdc/usb-cdc.c
index 52871c2..7bb768a 100644
--- a/example-cdc/usb-cdc.c
+++ b/example-cdc/usb-cdc.c
@@ -2,9 +2,9 @@
 #include <stdlib.h>
 #include <chopstx.h>
 #include "usb_lld.h"
+#include "stream.h"
 
-extern chopstx_mutex_t usb_mtx;
-extern chopstx_cond_t cnd_usb;
+static struct stream stream;
 
 #define ENDP0_RXADDR        (0x40)
 #define ENDP0_TXADDR        (0x80)
@@ -157,8 +157,8 @@ static const uint8_t vcom_string3[28] = {
 
 #define NUM_INTERFACES 2
 
-uint32_t bDeviceState = UNCONNECTED; /* USB device status */
-uint8_t connected;
+static uint32_t bDeviceState = UNCONNECTED; /* USB device status */
+
 
 void
 usb_cb_device_reset (void)
@@ -174,11 +174,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 (&usb_mtx);
-  connected = 0;
+  chopstx_mutex_lock (&stream.mtx);
+  stream.flags = 0;
   bDeviceState = ATTACHED;
-  chopstx_cond_signal (&cnd_usb);
-  chopstx_mutex_unlock (&usb_mtx);
+  chopstx_mutex_unlock (&stream.mtx);
 }
 
 
@@ -193,10 +192,11 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value)
       && USB_SETUP_SET (req) && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
     {
       /* Open/close the connection.  */
-      chopstx_mutex_lock (&usb_mtx);
-      connected = ((value & CDC_CTRL_DTR) != 0)? 1 : 0;
-      chopstx_cond_signal (&cnd_usb);
-      chopstx_mutex_unlock (&usb_mtx);
+      chopstx_mutex_lock (&stream.mtx);
+      stream.flags &= ~FLAG_CONNECTED;
+      stream.flags |= ((value & CDC_CTRL_DTR) != 0)? FLAG_CONNECTED : 0;
+      chopstx_cond_signal (&stream.cnd);
+      chopstx_mutex_unlock (&stream.mtx);
     }
 }
 
@@ -312,6 +312,8 @@ vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
 	{
 	  usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
 	  usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
+	  /* Start with no data receiving */
+	  usb_lld_stall_rx (ENDP3);
 	}
       else
 	{
@@ -321,7 +323,8 @@ vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
     }
 }
 
-int usb_cb_handle_event (uint8_t event_type, uint16_t value)
+int
+usb_cb_handle_event (uint8_t event_type, uint16_t value)
 {
   int i;
   uint8_t current_conf;
@@ -365,7 +368,8 @@ int usb_cb_handle_event (uint8_t event_type, uint16_t value)
 }
 
 
-int usb_cb_interface (uint8_t cmd, struct control_info *detail)
+int
+usb_cb_interface (uint8_t cmd, struct control_info *detail)
 {
   const uint8_t zero = 0;
   uint16_t interface = detail->index;
@@ -394,12 +398,17 @@ int usb_cb_interface (uint8_t cmd, struct control_info *detail)
     }
 }
 
+
 void
 EP1_IN_Callback (void)
 {
-  chopstx_mutex_lock (&usb_mtx);
-  chopstx_cond_signal (&cnd_usb);
-  chopstx_mutex_unlock (&usb_mtx);
+  chopstx_mutex_lock (&stream.mtx);
+  if ((stream.flags & FLAG_SEND_AVAIL))
+    {
+      stream.flags &= ~FLAG_SEND_AVAIL;
+      chopstx_cond_signal (&stream.cnd);
+    }
+  chopstx_mutex_unlock (&stream.mtx);
 }
 
 void
@@ -410,5 +419,79 @@ EP2_IN_Callback (void)
 void
 EP3_OUT_Callback (void)
 {
-  usb_lld_rx_enable (ENDP3);
+  chopstx_mutex_lock (&stream.mtx);
+  if ((stream.flags & FLAG_RECV_AVAIL) == 0)
+    {
+      stream.flags |= FLAG_RECV_AVAIL;
+      chopstx_cond_signal (&stream.cnd);
+    }
+  chopstx_mutex_unlock (&stream.mtx);
+}
+
+
+struct stream *
+stream_open (void)
+{
+  chopstx_mutex_init (&stream.mtx);
+  chopstx_cond_init (&stream.cnd);
+  return &stream;
+}
+
+int
+stream_wait_connection (struct stream *st)
+{
+  chopstx_mutex_lock (&st->mtx);
+  if ((stream.flags & FLAG_CONNECTED) == 0)
+    chopstx_cond_wait (&st->cnd, &st->mtx);
+  chopstx_mutex_unlock (&st->mtx);
+  stream.flags &= ~FLAG_SEND_AVAIL;
+  return 0;
+}
+
+
+int
+stream_send (struct stream *st, uint8_t *buf, uint8_t count)
+{
+  chopstx_mutex_lock (&st->mtx);
+  if ((stream.flags & FLAG_CONNECTED) == 0)
+    {
+      chopstx_mutex_unlock (&st->mtx);
+      return -1;
+    }
+  else
+    {
+      usb_lld_write (ENDP1, buf, count);
+      stream.flags |= FLAG_SEND_AVAIL;
+      while ((stream.flags & FLAG_SEND_AVAIL))
+	chopstx_cond_wait (&st->cnd, &st->mtx);
+    }
+  chopstx_mutex_unlock (&st->mtx);
+  return 0;
+}
+
+
+int
+stream_recv (struct stream *st, uint8_t *buf)
+{
+  int recv_size;
+
+  chopstx_mutex_lock (&st->mtx);
+  if ((stream.flags & FLAG_CONNECTED) == 0)
+    {
+      chopstx_mutex_unlock (&st->mtx);
+      return -1;
+    }
+  else
+    {
+      usb_lld_rx_enable (ENDP3);
+      stream.flags &= ~FLAG_RECV_AVAIL;
+      while ((stream.flags & FLAG_RECV_AVAIL) == 0)
+	chopstx_cond_wait (&st->cnd, &st->mtx);
+
+      recv_size = usb_lld_rx_data_len (ENDP3);
+      usb_lld_rxcpy (buf, ENDP3, 0, recv_size);
+    }
+  chopstx_mutex_unlock (&st->mtx);
+
+  return recv_size;
 }
-- 
cgit v1.2.3