From a17d12192fe74e07ab488e97d0742484f9a5ddcd Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Wed, 18 May 2016 09:55:23 +0900
Subject: Fix example-cdc more

---
 example-cdc/sample.c  |   2 +-
 example-cdc/tty.h     |   2 +
 example-cdc/usb-cdc.c | 283 ++++++++++++++++++++++++++++++--------------------
 3 files changed, 171 insertions(+), 116 deletions(-)

(limited to 'example-cdc')

diff --git a/example-cdc/sample.c b/example-cdc/sample.c
index 699c854..d29d13c 100644
--- a/example-cdc/sample.c
+++ b/example-cdc/sample.c
@@ -114,7 +114,7 @@ main (int argc, const char *argv[])
   m = 50;
   while (1)
     {
-      uint8_t s[128];
+      uint8_t s[LINEBUFSIZE];
 
       u = 1;
       tty_wait_connection (tty);
diff --git a/example-cdc/tty.h b/example-cdc/tty.h
index a2cee4e..bd0f070 100644
--- a/example-cdc/tty.h
+++ b/example-cdc/tty.h
@@ -1,3 +1,5 @@
+#define LINEBUFSIZE 128
+
 struct tty;
 
 struct tty *tty_open (void);
diff --git a/example-cdc/usb-cdc.c b/example-cdc/usb-cdc.c
index c095482..cdec2f0 100644
--- a/example-cdc/usb-cdc.c
+++ b/example-cdc/usb-cdc.c
@@ -5,14 +5,44 @@
 #include "usb_lld.h"
 #include "tty.h"
 
-#define BUFSIZE 128
+static chopstx_intr_t usb_intr;
+
+struct line_coding
+{
+  uint32_t bitrate;
+  uint8_t format;
+  uint8_t paritytype;
+  uint8_t datatype;
+}  __attribute__((packed));
+
+static const struct line_coding line_coding0 = {
+  115200, /* baud rate: 115200    */
+  0x00,   /* stop bits: 1         */
+  0x00,   /* parity:    none      */
+  0x08    /* bits:      8         */
+};
+
+/*
+ * Currently, we only support a single TTY.
+ *
+ * It is possible to extend to support multiple TTYs, for multiple
+ * interfaces.
+ *
+ * In that case, add argument to TTY_OPEN function and
+ * modify TTY_GET function to get the TTY structure.  Functions which
+ * directy accesses TTY0 (usb_cb_device_reset and usb_cb_handle_event)
+ * should be modified, too.
+ *
+ * Modification of TTY_MAIN thread will be also needed to echo back
+ * input for each TTY, and the thread should run if one of TTY is
+ * opened.
+ */
 
 struct tty {
   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 */
+  uint8_t inputline[LINEBUFSIZE];   /* Line editing is supported */
+  uint8_t send_buf[LINEBUFSIZE];    /* Sending ring buffer for echo back */
   uint32_t inputline_len    : 8;
   uint32_t send_head        : 8;
   uint32_t send_tail        : 8;
@@ -21,9 +51,34 @@ struct tty {
   uint32_t flag_input_avail : 1;
   uint32_t                  : 2;
   uint32_t device_state     : 3;     /* USB device status */
+  struct line_coding line_coding;
 };
 
-static struct tty tty;
+static struct tty tty0;
+
+/*
+ * Locate TTY structure from interface number or endpoint number.
+ * Currently, it always returns tty0, because we only have the one.
+ */
+static struct tty *
+tty_get (int interface, uint8_t ep_num)
+{
+  struct tty *t = &tty0;
+
+  if (interface >= 0)
+    {
+      if (interface == 0)
+	t = &tty0;
+    }
+  else
+    {
+      if (ep_num == ENDP1 || ep_num == ENDP2 || ep_num == ENDP3)
+	t = &tty0;
+    }
+
+  return t;
+}
+
 
 #define ENDP0_RXADDR        (0x40)
 #define ENDP0_TXADDR        (0x80)
@@ -187,14 +242,15 @@ usb_cb_device_reset (void)
   /* Initialize Endpoint 0 */
   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
 
-  chopstx_mutex_lock (&tty.mtx);
-  tty.inputline_len = 0;
-  tty.send_head = tty.send_tail = 0;
-  tty.flag_connected = 0;
-  tty.flag_send_ready = 1;
-  tty.flag_input_avail = 0;
-  tty.device_state = ATTACHED;
-  chopstx_mutex_unlock (&tty.mtx);
+  chopstx_mutex_lock (&tty0.mtx);
+  tty0.inputline_len = 0;
+  tty0.send_head = tty0.send_tail = 0;
+  tty0.flag_connected = 0;
+  tty0.flag_send_ready = 1;
+  tty0.flag_input_avail = 0;
+  tty0.device_state = ATTACHED;
+  memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
+  chopstx_mutex_unlock (&tty0.mtx);
 }
 
 
@@ -205,31 +261,19 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
 {
   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
 
-  if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
+  if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0
       && USB_SETUP_SET (req) && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
     {
+      struct tty *t = tty_get (arg->index, 0);
+
       /* Open/close the connection.  */
-      chopstx_mutex_lock (&tty.mtx);
-      tty.flag_connected = ((arg->value & CDC_CTRL_DTR) != 0);
-      chopstx_cond_signal (&tty.cnd);
-      chopstx_mutex_unlock (&tty.mtx);
+      chopstx_mutex_lock (&t->mtx);
+      t->flag_connected = ((arg->value & CDC_CTRL_DTR) != 0);
+      chopstx_cond_signal (&t->cnd);
+      chopstx_mutex_unlock (&t->mtx);
     }
 }
 
-struct line_coding
-{
-  uint32_t bitrate;
-  uint8_t format;
-  uint8_t paritytype;
-  uint8_t datatype;
-}  __attribute__((packed));
-
-static struct line_coding line_coding = {
-  115200, /* baud rate: 115200    */
-  0x00,   /* stop bits: 1         */
-  0x00,   /* parity:    none      */
-  0x08    /* bits:      8         */
-};
 
 
 static int
@@ -237,15 +281,21 @@ vcom_port_data_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
 {
   if (USB_SETUP_GET (req))
     {
+      struct tty *t = tty_get (arg->index, 0);
+
       if (req_no == USB_CDC_REQ_GET_LINE_CODING)
-	return usb_lld_reply_request (&line_coding, sizeof(line_coding), arg);
+	return usb_lld_reply_request (&t->line_coding,
+				      sizeof (struct line_coding), arg);
     }
   else  /* USB_SETUP_SET (req) */
     {
       if (req_no == USB_CDC_REQ_SET_LINE_CODING
-	  && arg->len == sizeof (line_coding))
+	  && arg->len == sizeof (struct line_coding))
 	{
-	  usb_lld_set_data_to_recv (&line_coding, sizeof (line_coding));
+	  struct tty *t = tty_get (arg->index, 0);
+
+	  usb_lld_set_data_to_recv (&t->line_coding,
+				    sizeof (struct line_coding));
 	  return USB_SUCCESS;
 	}
       else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
@@ -348,9 +398,9 @@ usb_cb_handle_event (uint8_t event_type, uint16_t value)
   switch (event_type)
     {
     case USB_EVENT_ADDRESS:
-      chopstx_mutex_lock (&tty.mtx);
-      tty.device_state = ADDRESSED;
-      chopstx_mutex_unlock (&tty.mtx);
+      chopstx_mutex_lock (&tty0.mtx);
+      tty0.device_state = ADDRESSED;
+      chopstx_mutex_unlock (&tty0.mtx);
       return USB_SUCCESS;
     case USB_EVENT_CONFIG:
       current_conf = usb_lld_current_configuration ();
@@ -362,9 +412,9 @@ usb_cb_handle_event (uint8_t event_type, uint16_t value)
 	  usb_lld_set_configuration (1);
 	  for (i = 0; i < NUM_INTERFACES; i++)
 	    vcom_setup_endpoints_for_interface (i, 0);
-	  chopstx_mutex_lock (&tty.mtx);
-	  tty.device_state = CONFIGURED;
-	  chopstx_mutex_unlock (&tty.mtx);
+	  chopstx_mutex_lock (&tty0.mtx);
+	  tty0.device_state = CONFIGURED;
+	  chopstx_mutex_unlock (&tty0.mtx);
 	}
       else if (current_conf != value)
 	{
@@ -374,9 +424,9 @@ usb_cb_handle_event (uint8_t event_type, uint16_t value)
 	  usb_lld_set_configuration (0);
 	  for (i = 0; i < NUM_INTERFACES; i++)
 	    vcom_setup_endpoints_for_interface (i, 1);
-	  chopstx_mutex_lock (&tty.mtx);
-	  tty.device_state = ADDRESSED;
-	  chopstx_mutex_unlock (&tty.mtx);
+	  chopstx_mutex_lock (&tty0.mtx);
+	  tty0.device_state = ADDRESSED;
+	  chopstx_mutex_unlock (&tty0.mtx);
 	}
       /* Do nothing when current_conf == value */
       return USB_SUCCESS;
@@ -423,61 +473,63 @@ usb_cb_interface (uint8_t cmd, struct req_args *arg)
  * Put a character into the ring buffer to be send back.
  */
 static void
-put_char_to_ringbuffer (int c)
+put_char_to_ringbuffer (struct tty *t, int c)
 {
-  uint32_t next = (tty.send_tail + 1) % BUFSIZE;
+  uint32_t next = (t->send_tail + 1) % LINEBUFSIZE;
 
-  if (tty.send_head == next)
+  if (t->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;
+  t->send_buf[t->send_tail] = c;
+  t->send_tail = next;
 }
 
 /*
  * Get characters from ring buffer into S.
  */
 static int
-get_chars_from_ringbuffer (uint8_t *s, int len)
+get_chars_from_ringbuffer (struct tty *t, uint8_t *s, int len)
 {
   int i = 0;
 
-  if (tty.send_head == tty.send_tail)
+  if (t->send_head == t->send_tail)
     /* Empty */
     return i;
 
   do
     {
-      s[i++] = tty.send_buf[tty.send_head];
-      tty.send_head = (tty.send_head + 1) % BUFSIZE;
+      s[i++] = t->send_buf[t->send_head];
+      t->send_head = (t->send_head + 1) % LINEBUFSIZE;
     }
-  while (tty.send_head != tty.send_tail && i < len);
+  while (t->send_head != t->send_tail && i < len);
 
   return i;
 }
 
 
 static void
-tty_echo_char (int c)
+tty_echo_char (struct tty *t, int c)
 {
-  put_char_to_ringbuffer (c);
+  put_char_to_ringbuffer (t, c);
 }
 
 
 void
 usb_cb_tx_done (uint8_t ep_num)
 {
+  struct tty *t = tty_get (-1, ep_num);
+
   if (ep_num == ENDP1)
     {
-      chopstx_mutex_lock (&tty.mtx);
-      if (tty.flag_send_ready == 0)
+      chopstx_mutex_lock (&t->mtx);
+      if (t->flag_send_ready == 0)
 	{
-	  tty.flag_send_ready = 1;
-	  chopstx_cond_signal (&tty.cnd);
+	  t->flag_send_ready = 1;
+	  chopstx_cond_signal (&t->cnd);
 	}
-      chopstx_mutex_unlock (&tty.mtx);
+      chopstx_mutex_unlock (&t->mtx);
     }
   else if (ep_num == ENDP2)
     {
@@ -487,60 +539,60 @@ usb_cb_tx_done (uint8_t ep_num)
 
 
 static int
-tty_input_char (int c)
+tty_input_char (struct tty *t, int c)
 {
   unsigned int i;
   int r = 0;
 
   /* Process DEL, C-U, C-R, and RET as editing command. */
-  chopstx_mutex_lock (&tty.mtx);
+  chopstx_mutex_lock (&t->mtx);
   switch (c)
     {
     case 0x0d: /* Control-M */
-      tty_echo_char (0x0d);
-      tty_echo_char (0x0a);
-      tty.flag_input_avail = 1;
+      tty_echo_char (t, 0x0d);
+      tty_echo_char (t, 0x0a);
+      t->flag_input_avail = 1;
       r = 1;
-      chopstx_cond_signal (&tty.cnd);
+      chopstx_cond_signal (&t->cnd);
       break;
     case 0x12: /* Control-R */
-      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]);
+      tty_echo_char (t, '^');
+      tty_echo_char (t, 'R');
+      tty_echo_char (t, 0x0d);
+      tty_echo_char (t, 0x0a);
+      for (i = 0; i < t->inputline_len; i++)
+	tty_echo_char (t, t->inputline[i]);
       break;
     case 0x15: /* Control-U */
-      for (i = 0; i < tty.inputline_len; i++)
+      for (i = 0; i < t->inputline_len; i++)
 	{
-	  tty_echo_char (0x08);
-	  tty_echo_char (0x20);
-	  tty_echo_char (0x08);
+	  tty_echo_char (t, 0x08);
+	  tty_echo_char (t, 0x20);
+	  tty_echo_char (t, 0x08);
 	}
-      tty.inputline_len = 0;
+      t->inputline_len = 0;
       break;
     case 0x7f: /* DEL    */
-      if (tty.inputline_len > 0)
+      if (t->inputline_len > 0)
 	{
-	  tty_echo_char (0x08);
-	  tty_echo_char (0x20);
-	  tty_echo_char (0x08);
-	  tty.inputline_len--;
+	  tty_echo_char (t, 0x08);
+	  tty_echo_char (t, 0x20);
+	  tty_echo_char (t, 0x08);
+	  t->inputline_len--;
 	}
       break;
     default:
-      if (tty.inputline_len < sizeof (tty.inputline))
+      if (t->inputline_len < sizeof (t->inputline))
 	{
-	  tty_echo_char (c);
-	  tty.inputline[tty.inputline_len++] = c;
+	  tty_echo_char (t, c);
+	  t->inputline[t->inputline_len++] = c;
 	}
       else
 	/* Beep */
-	tty_echo_char (0x0a);
+	tty_echo_char (t, 0x0a);
       break;
     }
-  chopstx_mutex_unlock (&tty.mtx);
+  chopstx_mutex_unlock (&t->mtx);
   return r;
 }
 
@@ -548,6 +600,7 @@ void
 usb_cb_rx_ready (uint8_t ep_num)
 {
   uint8_t recv_buf[64];
+  struct tty *t = tty_get (-1, ep_num);
 
   if (ep_num == ENDP3)
     {
@@ -556,13 +609,13 @@ 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++)
-	if (tty_input_char (recv_buf[i]))
+	if (tty_input_char (t, recv_buf[i]))
 	  break;
 
-      chopstx_mutex_lock (&tty.mtx);
-      if (tty.flag_input_avail == 0)
+      chopstx_mutex_lock (&t->mtx);
+      if (t->flag_input_avail == 0)
 	usb_lld_rx_enable (ENDP3);
-      chopstx_mutex_unlock (&tty.mtx);
+      chopstx_mutex_unlock (&t->mtx);
     }
 }
 
@@ -578,25 +631,25 @@ const size_t __stacksize_tty = (size_t)&__process3_stack_size__;
 struct tty *
 tty_open (void)
 {
-  chopstx_mutex_init (&tty.mtx);
-  chopstx_cond_init (&tty.cnd);
-  tty.inputline_len = 0;
-  tty.send_head = tty.send_tail = 0;
-  tty.flag_connected = 0;
-  tty.flag_send_ready = 1;
-  tty.flag_input_avail = 0;
-  tty.device_state = UNCONNECTED;
-
-  chopstx_create (PRIO_TTY, __stackaddr_tty, __stacksize_tty,
-		  tty_main, NULL);
-  return &tty;
+  chopstx_mutex_init (&tty0.mtx);
+  chopstx_cond_init (&tty0.cnd);
+  tty0.inputline_len = 0;
+  tty0.send_head = tty0.send_tail = 0;
+  tty0.flag_connected = 0;
+  tty0.flag_send_ready = 1;
+  tty0.flag_input_avail = 0;
+  tty0.device_state = UNCONNECTED;
+  memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
+
+  chopstx_create (PRIO_TTY, __stackaddr_tty, __stacksize_tty, tty_main, &tty0);
+  return &tty0;
 }
 
 
 static void *
 tty_main (void *arg)
 {
-  (void)arg;
+  struct tty *t = arg;
 
 #if defined(OLDER_SYS_H)
   /*
@@ -617,34 +670,34 @@ tty_main (void *arg)
    *
    */
   usb_lld_init (VCOM_FEATURE_BUS_POWERED);
-  chopstx_claim_irq (&tty.intr, INTR_REQ_USB);
+  chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
   usb_interrupt_handler ();
 #else
-  chopstx_claim_irq (&tty.intr, INTR_REQ_USB);
+  chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
   usb_lld_init (VCOM_FEATURE_BUS_POWERED);
 #endif
 
   while (1)
     {
-      chopstx_poll (NULL, 1, &tty.intr);
-      if (tty.intr.ready)
+      chopstx_poll (NULL, 1, &usb_intr);
+      if (usb_intr.ready)
 	usb_interrupt_handler ();
 
-      chopstx_mutex_lock (&tty.mtx);
-      if (tty.device_state == CONFIGURED && tty.flag_connected
-	  && tty.flag_send_ready)
+      chopstx_mutex_lock (&t->mtx);
+      if (t->device_state == CONFIGURED && t->flag_connected
+	  && t->flag_send_ready)
 	{
 	  uint8_t line[32];
-	  int len = get_chars_from_ringbuffer (line, sizeof (len));
+	  int len = get_chars_from_ringbuffer (t, line, sizeof (len));
 
 	  if (len)
 	    {
 	      usb_lld_txcpy (line, ENDP1, 0, len);
 	      usb_lld_tx_enable (ENDP1, len);
-	      tty.flag_send_ready = 0;
+	      t->flag_send_ready = 0;
 	    }
 	}
-      chopstx_mutex_unlock (&tty.mtx);
+      chopstx_mutex_unlock (&t->mtx);
     }
 
   return NULL;
-- 
cgit v1.2.3