From 40b454cf28e5a86dac8d261f1276ace108446ffe Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Nov 2019 23:20:48 +0700 Subject: [PATCH] get passed first get device descriptor --- src/common/tusb_common.h | 6 +- src/device/usbd.c | 25 +---- src/portable/microchip/samg/dcd_samg.c | 122 ++++++++++++++++++++++--- 3 files changed, 119 insertions(+), 34 deletions(-) diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 59e1fe7fd..d162e4e8e 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -139,9 +139,9 @@ static inline uint8_t tu_log2(uint32_t value) } // Bit -static inline uint32_t tu_bit_set (uint32_t value, uint8_t n) { return value | TU_BIT(n); } -static inline uint32_t tu_bit_clear(uint32_t value, uint8_t n) { return value & (~TU_BIT(n)); } -static inline bool tu_bit_test (uint32_t value, uint8_t n) { return (value & TU_BIT(n)) ? true : false; } +static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } +static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); } +static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value & TU_BIT(pos)) ? true : false; } /*------------------------------------------------------------------*/ /* Count number of arguments of __VA_ARGS__ diff --git a/src/device/usbd.c b/src/device/usbd.c index 1797dfafa..530eb09d1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -830,19 +830,15 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) { switch (event->event_id) { - case DCD_EVENT_BUS_RESET: - osal_queue_send(_usbd_q, event, in_isr); - break; - case DCD_EVENT_UNPLUGGED: - _usbd_dev.connected = 0; + _usbd_dev.connected = 0; _usbd_dev.configured = 0; - _usbd_dev.suspended = 0; + _usbd_dev.suspended = 0; osal_queue_send(_usbd_q, event, in_isr); break; case DCD_EVENT_SOF: - // nothing to do now + return; // skip SOF event for now break; case DCD_EVENT_SUSPEND: @@ -857,6 +853,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) break; case DCD_EVENT_RESUME: + // skip event if not connected (especially required for SAMD) if ( _usbd_dev.connected ) { _usbd_dev.suspended = 0; @@ -864,21 +861,9 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) } break; - case DCD_EVENT_SETUP_RECEIVED: + default: osal_queue_send(_usbd_q, event, in_isr); break; - - case DCD_EVENT_XFER_COMPLETE: - osal_queue_send(_usbd_q, event, in_isr); - TU_ASSERT(event->xfer_complete.result == XFER_RESULT_SUCCESS,); - break; - - // Not an DCD event, just a convenient way to defer ISR function should we need to - case USBD_EVENT_FUNC_CALL: - osal_queue_send(_usbd_q, event, in_isr); - break; - - default: break; } } diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 899d054c6..27fd35de6 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -35,6 +35,38 @@ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ +// Transfer descriptor +typedef struct +{ + uint8_t* buffer; + uint16_t total_len; + volatile uint16_t actual_len; + uint16_t epsize; +} xfer_desc_t; + +// Endpoint 0-5 with OUT & IN +xfer_desc_t _dcd_xfer[6][2]; + +void xfer_begin(xfer_desc_t* xfer, uint8_t * buffer, uint16_t total_bytes) +{ + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->actual_len = 0; +} + +uint16_t xfer_packet_len(xfer_desc_t* xfer) +{ + // also cover zero-length packet + return tu_min16(xfer->total_len - xfer->actual_len, xfer->epsize); +} + +void xfer_packet_done(xfer_desc_t* xfer) +{ + uint16_t const xact_len = xfer_packet_len(xfer); + + xfer->buffer += xact_len; + xfer->actual_len += xact_len; +} /*------------------------------------------------------------------*/ /* Device API @@ -43,6 +75,10 @@ // Set up endpoint 0, clear all other endpoints static void bus_reset(void) { + tu_memclr(_dcd_xfer, sizeof(_dcd_xfer)); + + _dcd_xfer[0][0].epsize = _dcd_xfer[0][1].epsize = CFG_TUD_ENDPOINT0_SIZE; + // Enable EP0 control UDP->UDP_CSR[0] = UDP_CSR_EPEDS_Msk; @@ -58,8 +94,7 @@ void dcd_init (uint8_t rhport) { (void) rhport; - - + tu_memclr(_dcd_xfer, sizeof(_dcd_xfer)); // Enable pull-up, disable transceiver UDP->UDP_TXVC = UDP_TXVC_PUON | UDP_TXVC_TXVDIS_Msk; @@ -115,10 +150,46 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { (void) rhport; - (void) ep_addr; - (void) buffer; - (void) total_bytes; - return false; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_desc_t* xfer = &_dcd_xfer[epnum][dir]; + xfer_begin(xfer, buffer, total_bytes); + + uint16_t const xact_len = xfer_packet_len(xfer); + + // control endpoint + if ( epnum == 0 ) + { + // opposite to DIR bit --> status phase + // switch the DIR bit +// if ( dir != tu_bit_test(UDP->UDP_CSR[0], UDP_CSR_DIR_Pos) ) +// { +// +// } + + if (dir == TUSB_DIR_OUT) + { + UDP->UDP_CSR[0] &= ~UDP_CSR_DIR_Msk; + // + }else + { + UDP->UDP_CSR[0] |= UDP_CSR_DIR_Msk; + + // Write data to fifo + for(uint16_t i=0; iUDP_FDR[0] = (uint32_t) buffer[i]; + + // TX ready for transfer + UDP->UDP_CSR[0] |= UDP_CSR_TXPKTRDY_Msk; + } + + }else + { + return false; + } + + return true; } // Stall endpoint @@ -154,13 +225,13 @@ void dcd_isr(uint8_t rhport) } // SOF - if (intr_status & UDP_ISR_SOFINT_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); +// if (intr_status & UDP_ISR_SOFINT_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); // Suspend - if (intr_status & UDP_ISR_RXSUSP_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); +// if (intr_status & UDP_ISR_RXSUSP_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); // Resume - if (intr_status & UDP_ISR_RXRSM_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); +// if (intr_status & UDP_ISR_RXRSM_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); // Wakeup // if (intr_status & UDP_ISR_WAKEUP_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); @@ -179,11 +250,40 @@ void dcd_isr(uint8_t rhport) setup[i] = (uint8_t) UDP->UDP_FDR[0]; } - // clear setup bit - UDP->UDP_CSR[0] &= ~UDP_CSR_RXSETUP_Msk; + // Set EP0 Dir bit & Clear setup bit +// uint32_t csr = UDP->UDP_CSR[0]; +// csr &= ~(UDP_CSR_RXSETUP_Msk | UDP_CSR_DIR_Msk); +// if ( setup[0] & TUSB_DIR_IN_MASK ) csr |= UDP_CSR_DIR_Msk; +// +// UDP->UDP_CSR[0] = csr; // notify usbd dcd_event_setup_received(rhport, setup, true); + + // Clear Setup bit + UDP->UDP_CSR[0] &= ~UDP_CSR_RXSETUP_Msk; + } + } + + for(uint8_t epnum = 0; epnum < 6; epnum++) + { + // Endpoint IN + if (UDP->UDP_CSR[epnum] & UDP_CSR_TXCOMP_Msk) + { + xfer_desc_t* xfer = &_dcd_xfer[epnum][1]; + uint16_t xact_len = xfer_packet_len(xfer); + xfer_packet_done(xfer); + + dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xact_len, XFER_RESULT_SUCCESS, true); + + // Clear TX Complete bit + UDP->UDP_CSR[0] &= ~UDP_CSR_TXCOMP_Msk; + } + + // Endpoint OUT + if (UDP->UDP_CSR[epnum] & UDP_CSR_RX_DATA_BK0_Msk) + { + dcd_event_bus_signal(rhport, DCD_EVENT_INVALID, true); } } }