summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2019-11-27 23:20:48 +0700
committerhathach <[email protected]>2019-11-27 23:20:48 +0700
commit40b454cf28e5a86dac8d261f1276ace108446ffe (patch)
tree32fa8ef83f18d9ccda49f76682334dac53634136
parent6225d5bcfdf3b416d2dd109e88b67bc4fcefe249 (diff)
get passed first get device descriptor
-rw-r--r--src/common/tusb_common.h6
-rw-r--r--src/device/usbd.c25
-rw-r--r--src/portable/microchip/samg/dcd_samg.c122
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:
- osal_queue_send(_usbd_q, event, in_isr);
- break;
-
- case DCD_EVENT_XFER_COMPLETE:
+ default:
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; i<xact_len; i++) UDP->UDP_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);
}
}
}