aboutsummaryrefslogtreecommitdiff
path: root/example-fs-bb48
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2016-05-23 13:48:24 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2016-05-23 13:48:24 +0900
commitb6603f677159b72a8165a5475dad525947889881 (patch)
tree0ebf65e409053730b9546a00d5debd3f1a7eb521 /example-fs-bb48
parentee92bb15b361b3daee816a4e930be0032be2d9e7 (diff)
Update example-fs-bb48
Diffstat (limited to 'example-fs-bb48')
-rw-r--r--example-fs-bb48/sample.c168
-rw-r--r--example-fs-bb48/tty.h31
-rw-r--r--example-fs-bb48/usb-cdc.c555
3 files changed, 453 insertions, 301 deletions
diff --git a/example-fs-bb48/sample.c b/example-fs-bb48/sample.c
index 9250700..2935709 100644
--- a/example-fs-bb48/sample.c
+++ b/example-fs-bb48/sample.c
@@ -4,7 +4,7 @@
#include <chopstx.h>
#include "usb_lld.h"
-#include "stream.h"
+#include "tty.h"
#include "board.h"
#include "crc32.h"
@@ -93,43 +93,12 @@ blk (void *arg)
return NULL;
}
-#define INTR_REQ_USB 24
-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;
- chopstx_claim_irq (&interrupt, INTR_REQ_USB);
- usb_lld_init (0x80); /* Bus powered. */
-
- while (1)
- {
- chopstx_intr_wait (&interrupt);
-
- /* Process interrupt. */
- usb_interrupt_handler ();
- }
-
- return NULL;
-}
-
-#if defined(BUSY_LOOP)
-#define PRIO_PWM (CHOPSTX_SCHED_RR|1)
-#define PRIO_BLK (CHOPSTX_SCHED_RR|1)
-#else
#define PRIO_PWM 3
#define PRIO_BLK 2
-#endif
-#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__;
@@ -137,9 +106,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)
{
@@ -153,24 +119,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;
@@ -182,14 +135,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);
@@ -199,81 +148,80 @@ 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[LINEBUFSIZE];
u = 1;
- if (stream_wait_connection (st) < 0)
- {
- chopstx_usec_wait (1000*1000);
- continue;
- }
+ tty_wait_connection (tty);
- chopstx_usec_wait (500*1000);
+ chopstx_usec_wait (50*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;
- if (chopstx_poll (&usec, 1, &poll_desc))
+
+ usec = 3000000; /* 3.0 seconds */
+ size = tty_recv (tty, s + 4, &usec);
+ if (size < 0)
+ break;
+
+ if (usec)
{
- size = stream_recv (st, s + 4);
+ unsigned int value;
- if (size < 0)
- break;
+ if (s[4] == 't')
+ {
+ s[0] = 'T';
+ s[1] = 'M';
+
+ adc_start_conversion (0, 1);
+ adc_wait_completion (NULL);
+ value = adc_buf[0];
- if (size >= 0)
+ s[4] = hexchar (value >> 28);
+ s[5] = hexchar (value >> 24);
+ s[6] = hexchar (value >> 20);
+ s[7] = hexchar (value >> 16);
+ s[8] = hexchar (value >> 12);
+ s[9] = hexchar (value >> 8);
+ s[10] = hexchar (value >> 4);
+ s[11] = hexchar (value);
+ s[12] = '\r';
+ s[13] = '\n';
+
+ if (tty_send (tty, s, 14) < 0)
+ break;
+ }
+ else if (s[4] == 'c')
{
- unsigned int value;
-
- if (s[4] == 't')
- {
- s[0] = 'T';
- s[1] = 'M';
-
- adc_start_conversion (0, 1);
- adc_wait_completion (NULL);
- value = adc_buf[0];
- }
- else
- {
- int i;
-
- crc32_init ();
- s[0] = hexchar (size >> 4);
- s[1] = hexchar (size & 0x0f);
-
- for (i = 0; i < size; i++)
- crc32_u8 (s[4 + i]);
- value = crc32_value () ^ 0xffffffff;
- }
+ int i;
+
+ crc32_init ();
+ s[0] = hexchar (size >> 4);
+ s[1] = hexchar (size & 0x0f);
+
+ for (i = 0; i < size; i++)
+ crc32_u8 (s[4 + i]);
+ value = crc32_value () ^ 0xffffffff;
s[4] = hexchar (value >> 28);
s[5] = hexchar (value >> 24);
@@ -285,7 +233,19 @@ main (int argc, const char *argv[])
s[11] = hexchar (value);
s[12] = '\r';
s[13] = '\n';
- if (stream_send (st, s, 14) < 0)
+
+ if (tty_send (tty, s, 14) < 0)
+ break;
+ }
+ else
+ {
+ 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;
}
}
diff --git a/example-fs-bb48/tty.h b/example-fs-bb48/tty.h
index 77b7014..bd0f070 100644
--- a/example-fs-bb48/tty.h
+++ b/example-fs-bb48/tty.h
@@ -1,26 +1,9 @@
-#define BUFSIZE 128
-#define FLAG_CONNECTED (1 << 0)
-#define FLAG_SEND_AVAIL (1 << 1)
-#define FLAG_RECV_AVAIL (1 << 2)
+#define LINEBUFSIZE 128
-/*
- * 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];
- 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 tty;
-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);
+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-fs-bb48/usb-cdc.c b/example-fs-bb48/usb-cdc.c
index 58588c8..b412cf1 100644
--- a/example-fs-bb48/usb-cdc.c
+++ b/example-fs-bb48/usb-cdc.c
@@ -3,19 +3,84 @@
#include <chopstx.h>
#include <string.h>
#include "usb_lld.h"
-#include "stream.h"
+#include "tty.h"
-static uint8_t send_buf[64];
-static unsigned int send_len;
-static uint8_t send_buf1[64];
+static chopstx_intr_t usb_intr;
-static uint8_t recv_buf[64];
-static unsigned int recv_len;
+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 */
+};
-static uint8_t inputline[64];
-static unsigned int inputline_len;
+/*
+ * 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;
+ uint8_t inputline[LINEBUFSIZE]; /* Line editing is supported */
+ uint8_t send_buf[LINEBUFSIZE]; /* Sending ring buffer for echo back */
+ uint8_t send_buf0[64];
+ uint8_t recv_buf0[64];
+ uint32_t inputline_len : 8;
+ uint32_t send_head : 8;
+ uint32_t send_tail : 8;
+ uint32_t flag_connected : 1;
+ uint32_t flag_send_ready : 1;
+ 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 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;
+}
-static struct stream stream;
#define USB_CDC_REQ_SET_LINE_CODING 0x20
#define USB_CDC_REQ_GET_LINE_CODING 0x21
@@ -40,6 +105,8 @@ static const uint8_t vcom_device_desc[18] = {
1 /* bNumConfigurations. */
};
+#define VCOM_FEATURE_BUS_POWERED 0x80
+
/* Configuration Descriptor tree for a CDC.*/
static const uint8_t vcom_config_desc[67] = {
9,
@@ -49,7 +116,7 @@ static const uint8_t vcom_config_desc[67] = {
0x02, /* bNumInterfaces. */
0x01, /* bConfigurationValue. */
0, /* iConfiguration. */
- 0x80, /* bmAttributes (bus powered). */
+ VCOM_FEATURE_BUS_POWERED, /* bmAttributes. */
50, /* bMaxPower (100mA). */
/* Interface Descriptor.*/
9,
@@ -162,21 +229,24 @@ static const uint8_t vcom_string3[28] = {
#define NUM_INTERFACES 2
-uint32_t bDeviceState = UNCONNECTED; /* USB device status */
-
void
usb_cb_device_reset (void)
{
- usb_lld_reset (vcom_config_desc[7]);
+ usb_lld_reset (VCOM_FEATURE_BUS_POWERED);
/* Initialize Endpoint 0 */
usb_lld_setup_endpoint (ENDP0, 1, 1);
- chopstx_mutex_lock (&stream.mtx);
- stream.flags = 0;
- bDeviceState = ATTACHED;
- chopstx_mutex_unlock (&stream.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);
}
@@ -187,34 +257,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 (&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, recv_buf, 64);
- chopstx_mutex_unlock (&stream.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
@@ -222,15 +277,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)
@@ -313,10 +374,7 @@ vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
{
usb_lld_setup_endpoint (ENDP1, 0, 1);
usb_lld_setup_endpoint (ENDP3, 1, 0);
-#if 0
- /* Start with no data receiving */
- usb_lld_stall (ENDP3);
-#endif
+ /* Start with no data receiving (ENDP3 not enabled)*/
}
else
{
@@ -335,7 +393,9 @@ usb_cb_handle_event (uint8_t event_type, uint16_t value)
switch (event_type)
{
case USB_EVENT_ADDRESS:
- bDeviceState = ADDRESSED;
+ 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 ();
@@ -347,7 +407,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);
- bDeviceState = CONFIGURED;
+ chopstx_mutex_lock (&tty0.mtx);
+ tty0.device_state = CONFIGURED;
+ chopstx_mutex_unlock (&tty0.mtx);
}
else if (current_conf != value)
{
@@ -357,12 +419,12 @@ 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);
- bDeviceState = ADDRESSED;
+ chopstx_mutex_lock (&tty0.mtx);
+ tty0.device_state = ADDRESSED;
+ chopstx_mutex_unlock (&tty0.mtx);
}
/* Do nothing when current_conf == value */
return USB_SUCCESS;
-
- return USB_SUCCESS;
default:
break;
}
@@ -402,52 +464,67 @@ 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 (struct tty *t, 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 = (t->send_tail + 1) % LINEBUFSIZE;
+
+ if (t->send_head == next)
+ /* full */
+ /* All that we can do is ignore this char. */
+ return;
+
+ t->send_buf[t->send_tail] = c;
+ t->send_tail = next;
+}
- if (stream.sending == 0)
+/*
+ * Get characters from ring buffer into S.
+ */
+static int
+get_chars_from_ringbuffer (struct tty *t, uint8_t *s, int len)
+{
+ int i = 0;
+
+ if (t->send_head == t->send_tail)
+ /* Empty */
+ return i;
+
+ do
{
- memcpy (send_buf1, send_buf, send_len);
- usb_lld_tx_enable (ENDP1, send_buf1, send_len);
- send_len = 0;
- stream.sending = 1;
+ s[i++] = t->send_buf[t->send_head];
+ t->send_head = (t->send_head + 1) % LINEBUFSIZE;
}
- chopstx_mutex_unlock (&stream.mtx);
+ while (t->send_head != t->send_tail && i < len);
+
+ return i;
+}
+
+
+static void
+tty_echo_char (struct tty *t, int 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 (&stream.mtx);
- stream.sending = 0;
- if (send_len)
+ chopstx_mutex_lock (&t->mtx);
+ if (t->flag_send_ready == 0)
{
- stream.sending = 1;
- memcpy (send_buf1, send_buf, send_len);
- usb_lld_tx_enable (ENDP1, send_buf1, send_len);
- send_len = 0;
+ t->flag_send_ready = 1;
+ chopstx_cond_signal (&t->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 (&t->mtx);
}
else if (ep_num == ENDP2)
{
@@ -456,162 +533,294 @@ usb_cb_tx_done (uint8_t ep_num)
}
-static void
-stream_input_char (int c)
+static int
+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 (&t->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 (t, 0x0d);
+ tty_echo_char (t, 0x0a);
+ t->flag_input_avail = 1;
+ r = 1;
+ chopstx_cond_signal (&t->cnd);
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 (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 < inputline_len; i++)
+ for (i = 0; i < t->inputline_len; i++)
{
- stream_echo_char (0x08);
- stream_echo_char (0x20);
- stream_echo_char (0x08);
+ tty_echo_char (t, 0x08);
+ tty_echo_char (t, 0x20);
+ tty_echo_char (t, 0x08);
}
- inputline_len = 0;
+ t->inputline_len = 0;
break;
case 0x7f: /* DEL */
- if (inputline_len > 0)
+ if (t->inputline_len > 0)
{
- stream_echo_char (0x08);
- stream_echo_char (0x20);
- stream_echo_char (0x08);
- inputline_len--;
+ tty_echo_char (t, 0x08);
+ tty_echo_char (t, 0x20);
+ tty_echo_char (t, 0x08);
+ t->inputline_len--;
}
break;
default:
- if (inputline_len < sizeof (inputline))
+ if (t->inputline_len < sizeof (t->inputline))
{
- stream_echo_char (c);
- inputline[inputline_len++] = c;
+ tty_echo_char (t, c);
+ t->inputline[t->inputline_len++] = c;
}
else
/* Beep */
- stream_echo_char (0x0a);
+ tty_echo_char (t, 0x0a);
break;
}
+ chopstx_mutex_unlock (&t->mtx);
+ return r;
}
void
usb_cb_rx_ready (uint8_t ep_num)
{
+ struct tty *t = tty_get (-1, 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]);
+ if (tty_input_char (t, t->recv_buf0[i]))
+ break;
- usb_lld_rx_enable (ENDP3, recv_buf, 64);
+ chopstx_mutex_lock (&t->mtx);
+ if (t->flag_input_avail == 0)
+ usb_lld_rx_enable (ENDP3, t->recv_buf0, 64);
+ chopstx_mutex_unlock (&t->mtx);
}
}
-struct stream *
-stream_open (void)
+static void *tty_main (void *arg);
+
+#define INTR_REQ_USB 24
+#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 (&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;
}
-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;
+ struct tty *t = 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 (VCOM_FEATURE_BUS_POWERED);
+ chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
+ usb_interrupt_handler ();
+#else
+ chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
+ usb_lld_init (VCOM_FEATURE_BUS_POWERED);
+#endif
+
+ while (1)
+ {
+ chopstx_poll (NULL, 1, &usb_intr);
+ if (usb_intr.ready)
+ usb_interrupt_handler ();
+
+ 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 (t, line, sizeof (len));
+
+ if (len)
+ {
+ memcpy (t->send_buf0, line, len);
+ usb_lld_tx_enable (ENDP1, t->send_buf0, len);
+ t->flag_send_ready = 0;
+ }
+ }
+ chopstx_mutex_unlock (&t->mtx);
+ }
+
+ return NULL;
+}
+
+
+void
+tty_wait_configured (struct tty *t)
+{
+ chopstx_mutex_lock (&t->mtx);
+ while (t->device_state != 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->flag_connected == 0)
+ chopstx_cond_wait (&t->cnd, &t->mtx);
+ t->flag_send_ready = 1;
+ t->flag_input_avail = 0;
+ t->send_head = t->send_tail = 0;
+ t->inputline_len = 0;
+ usb_lld_rx_enable (ENDP3, t->recv_buf0, 64); /* Accept input for line */
+ chopstx_mutex_unlock (&t->mtx);
+}
+
+static int
+check_tx (struct tty *t)
+{
+ if (t->flag_send_ready)
+ /* TX done */
+ return 1;
+ if (t->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_tx_enable (ENDP1, buf, 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_tx_enable (ENDP1, p, count);
+ t->flag_send_ready = 0;
}
- 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->flag_input_avail)
+ /* RX */
+ return 1;
+ if (t->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;
+
+ 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->flag_connected == 0)
r = -1;
- else
+ else if (t->flag_input_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->flag_input_avail = 0;
+ usb_lld_rx_enable (ENDP3, t->recv_buf0, 64);
+ t->inputline_len = 0;
}
- chopstx_mutex_unlock (&st->mtx);
+ else
+ r = 0;
+ chopstx_mutex_unlock (&t->mtx);
return r;
}