2 #include "usb_serial.h"
3 #include <Lib/USBLib.h>
5 // defined by usb_dev.h -> usb_desc.h
6 #if defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE)
8 uint8_t usb_cdc_line_coding[7];
9 volatile uint8_t usb_cdc_line_rtsdtr=0;
10 volatile uint8_t usb_cdc_transmit_flush_timer=0;
12 static usb_packet_t *rx_packet=NULL;
13 static usb_packet_t *tx_packet=NULL;
14 static volatile uint8_t tx_noautoflush=0;
16 #define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */
18 static void usb_serial_receive(void)
20 if (!usb_configuration) return;
21 if (rx_packet) return;
23 rx_packet = usb_rx(CDC_RX_ENDPOINT);
24 if (rx_packet == NULL) return;
25 if (rx_packet->len > 0) return;
31 // get the next character, or -1 if nothing received
32 int usb_serial_getchar(void)
38 if (!rx_packet) return -1;
40 c = rx_packet->buf[i++];
41 if (i >= rx_packet->len) {
50 // peek at the next character, or -1 if nothing received
51 int usb_serial_peekchar(void)
54 if (!rx_packet) return -1;
55 return rx_packet->buf[rx_packet->index];
58 // number of bytes available in the receive buffer
59 int usb_serial_available(void)
63 if (usb_configuration) {
64 count = usb_rx_byte_count(CDC_RX_ENDPOINT);
66 if (rx_packet) count += rx_packet->len - rx_packet->index;
70 // discard any buffered input
71 void usb_serial_flush_input(void)
75 if (!usb_configuration) return;
81 rx = usb_rx(CDC_RX_ENDPOINT);
87 // Maximum number of transmit packets to queue so we don't starve other endpoints for memory
88 #define TX_PACKET_LIMIT 8
90 // When the PC isn't listening, how long do we wait before discarding data? If this is
91 // too short, we risk losing data during the stalls that are common with ordinary desktop
92 // software. If it's too long, we stall the user's program when no software is running.
93 #define TX_TIMEOUT_MSEC 70
96 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
97 #elif F_CPU == 48000000
98 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
99 #elif F_CPU == 24000000
100 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
103 // When we've suffered the transmit timeout, don't wait again until the computer
104 // begins accepting data. If no software is running to receive, we'll just discard
105 // data as rapidly as Serial.print() can generate it, until there's something to
106 // actually receive it.
107 static uint8_t transmit_previous_timeout=0;
110 // transmit a character. 0 returned on success, -1 on error
111 int usb_serial_putchar(uint8_t c)
114 return usb_serial_write(&c, 1);
123 if (!usb_configuration) {
127 if (usb_tx_packet_count(CDC_TX_ENDPOINT) < TX_PACKET_LIMIT) {
129 tx_packet = usb_malloc();
130 if (tx_packet) break;
133 if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
134 transmit_previous_timeout = 1;
139 transmit_previous_timeout = 0;
140 tx_packet->buf[tx_packet->index++] = c;
141 if (tx_packet->index < CDC_TX_SIZE) {
142 usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
144 tx_packet->len = CDC_TX_SIZE;
145 usb_cdc_transmit_flush_timer = 0;
146 usb_tx(CDC_TX_ENDPOINT, tx_packet);
155 int usb_serial_write(const void *buffer, uint32_t size)
160 const uint8_t *src = (const uint8_t *)buffer;
168 if (!usb_configuration) {
172 if (usb_tx_packet_count(CDC_TX_ENDPOINT) < TX_PACKET_LIMIT) {
174 tx_packet = usb_malloc();
175 if (tx_packet) break;
178 if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
179 transmit_previous_timeout = 1;
185 transmit_previous_timeout = 0;
186 len = CDC_TX_SIZE - tx_packet->index;
187 if (len > size) len = size;
188 dest = tx_packet->buf + tx_packet->index;
189 tx_packet->index += len;
191 while (len-- > 0) *dest++ = *src++;
192 if (tx_packet->index < CDC_TX_SIZE) {
193 usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
195 tx_packet->len = CDC_TX_SIZE;
196 usb_cdc_transmit_flush_timer = 0;
197 usb_tx(CDC_TX_ENDPOINT, tx_packet);
205 const uint8_t *p = (const uint8_t *)buffer;
209 r = usb_serial_putchar(*p++);
210 if (r < 0) return -1;
217 void usb_serial_flush_output(void)
219 if (!usb_configuration) return;
220 //serial_print("usb_serial_flush_output\n");
221 if (tx_packet && tx_packet->index > 0) {
222 usb_cdc_transmit_flush_timer = 0;
223 tx_packet->len = tx_packet->index;
224 usb_tx(CDC_TX_ENDPOINT, tx_packet);
227 // while (usb_tx_byte_count(CDC_TX_ENDPOINT) > 0) ; // wait
230 void usb_serial_flush_callback(void)
232 if (tx_noautoflush) return;
233 //serial_print("usb_flush_callback \n");
234 tx_packet->len = tx_packet->index;
235 usb_tx(CDC_TX_ENDPOINT, tx_packet);
237 //serial_print("usb_flush_callback end\n");
240 #endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE