summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2017-10-18 11:51:13 -0700
committerDan Halbert <halbert@halwitz.org>2017-10-18 15:46:26 -0400
commitf31a7b70e81dd352f9301a842685ff4d136125f6 (patch)
tree5d0b85cc51a390eedd4e0317a6089ebe0a814198
parent51cd4da76edd1941edf4a933e7d6d7628c3feec2 (diff)
atmel-samd: Fix CDC now that its clear its async.
-rw-r--r--atmel-samd/usb.c62
1 files changed, 36 insertions, 26 deletions
diff --git a/atmel-samd/usb.c b/atmel-samd/usb.c
index 5aee96767..641bdd457 100644
--- a/atmel-samd/usb.c
+++ b/atmel-samd/usb.c
@@ -74,7 +74,7 @@ static uint8_t multi_desc_bytes[] = {
static struct usbd_descriptors multi_desc = {multi_desc_bytes, multi_desc_bytes + sizeof(multi_desc_bytes)};
/** Ctrl endpoint buffer */
-static uint8_t ctrl_buffer[64];
+COMPILER_ALIGNED(4) static uint8_t ctrl_buffer[64];
static void init_hardware(void) {
#ifdef SAMD21
@@ -107,12 +107,19 @@ static void init_hardware(void) {
#endif
}
-extern uint32_t *_usb_ep1_cache;
-static bool usb_device_cb_bulk_out(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
-{
- if (rc == USB_XFER_RESET) {
- return false;
+COMPILER_ALIGNED(4) uint8_t cdc_packet_buffer[64];
+static volatile bool pending_read;
+
+static int32_t start_read(void) {
+ pending_read = true;
+ return cdcdf_acm_read(cdc_packet_buffer, 64);
+}
+
+static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count) {
+ if (rc != USB_XFER_DONE) {
+ return false; // No errors.
}
+ pending_read = false;
volatile hal_atomic_t flags;
atomic_enter_critical(&flags);
// If our buffer can't fit the data received, then error out.
@@ -121,24 +128,12 @@ static bool usb_device_cb_bulk_out(const uint8_t ep, const enum usb_xfer_code rc
return true;
}
- // We read the data but ignore it later. The data itself isn't correct but
- // it does mark it as read so further data is received ok.
- // TODO(tannewt): Get ASF4 fixed so the data is correct and then stop using
- // _usb_ep1_cache directly below.
- uint8_t buf[count];
- int32_t result = cdcdf_acm_read(buf, count);
- if (result != ERR_NONE) {
- atomic_leave_critical(&flags);
- return true;
- }
-
for (uint16_t i = 0; i < count; i++) {
- uint8_t c = ((uint8_t*) &_usb_ep1_cache)[i];
+ uint8_t c = cdc_packet_buffer[i];
if (c == mp_interrupt_char) {
- atomic_leave_critical(&flags);
mp_keyboard_interrupt();
// Don't put the interrupt into the buffer, just continue.
- return false;
+ continue;
} else {
// The count of characters present in receive buffer is
// incremented.
@@ -154,12 +149,21 @@ static bool usb_device_cb_bulk_out(const uint8_t ep, const enum usb_xfer_code rc
}
atomic_leave_critical(&flags);
+ // Trigger a follow up read if we have space.
+ if (usb_rx_count < USB_RX_BUF_SIZE) {
+ int32_t result = start_read();
+ if (result != ERR_NONE) {
+ return true;
+ }
+ }
+
/* No error. */
return false;
}
-static bool usb_device_cb_bulk_in(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
+static bool write_complete(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
{
+ // This is called after writed are finished.
/* No error. */
return false;
}
@@ -193,6 +197,7 @@ void init_usb(void) {
/* usbdc_register_funcion inside */
cdcdf_acm_init();
+ pending_read = false;
mscdf_init(1);
// hiddf_mouse_init();
@@ -218,19 +223,19 @@ static inline bool cdc_enabled(void) {
if (!cdcdf_acm_is_enabled()) {
return false;
}
- cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)usb_device_cb_bulk_out);
- cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)usb_device_cb_bulk_in);
+ cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)read_complete);
+ cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)write_complete);
cdcdf_acm_register_callback(CDCDF_ACM_CB_STATE_C, (FUNC_PTR)usb_device_cb_state_c);
cdcdf_acm_register_callback(CDCDF_ACM_CB_LINE_CODING_C, (FUNC_PTR)usb_device_cb_line_coding_c);
mp_cdc_enabled = true;
- // Ignored read.
- uint8_t buf[64];
- cdcdf_acm_read(buf, 64);
return true;
}
bool usb_bytes_available(void) {
+ if (!pending_read) {
+ start_read();
+ }
if (usb_rx_count == 0) {
cdc_enabled();
return false;
@@ -254,6 +259,11 @@ int usb_read(void) {
}
CRITICAL_SECTION_LEAVE();
+ // Trigger a new read because we just cleared some space.
+ if (!pending_read && usb_rx_count == USB_RX_BUF_SIZE - 1) {
+ start_read();
+ }
+
return data;
}