diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2016-05-18 09:55:23 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2016-05-18 09:55:23 +0900 |
commit | a17d12192fe74e07ab488e97d0742484f9a5ddcd (patch) | |
tree | df56cbed74890e5e6c6c995eb91750e5abbc87f8 /example-cdc | |
parent | 4c1aa50f13ca6dc08be0bb243f3c885b661b0fa8 (diff) |
Fix example-cdc more
Diffstat (limited to 'example-cdc')
-rw-r--r-- | example-cdc/sample.c | 2 | ||||
-rw-r--r-- | example-cdc/tty.h | 2 | ||||
-rw-r--r-- | example-cdc/usb-cdc.c | 283 |
3 files changed, 171 insertions, 116 deletions
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; |