From 40b454cf28e5a86dac8d261f1276ace108446ffe Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Nov 2019 23:20:48 +0700 Subject: get passed first get device descriptor --- src/device/usbd.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'src/device') 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; } } -- cgit v1.3.1 From 6bc245cb36cd18543916516a91def1f1e3a04e66 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Nov 2019 11:46:36 +0700 Subject: add dcd_edpt0_status_complete() which is useful for several mcu port --- src/common/tusb_common.h | 12 +++++++----- src/device/dcd.h | 4 ++++ src/device/usbd_control.c | 2 ++ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 ++ 4 files changed, 15 insertions(+), 5 deletions(-) (limited to 'src/device') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index d162e4e8e..a2c40e669 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -216,17 +216,19 @@ static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value void tu_print_mem(void const *buf, uint8_t size, uint16_t count); #ifndef tu_printf - #define tu_printf printf + #define tu_printf printf #endif // Log with debug level 1 -#define TU_LOG1 tu_printf -#define TU_LOG1_MEM tu_print_mem +#define TU_LOG1 tu_printf +#define TU_LOG1_MEM tu_print_mem +#define TU_LOG1_LOCATION() tu_printf("%s: %d:\n", __PRETTY_FUNCTION__, __LINE__) // Log with debug level 2 #if CFG_TUSB_DEBUG > 1 - #define TU_LOG2 TU_LOG1 - #define TU_LOG2_MEM TU_LOG1_MEM + #define TU_LOG2 TU_LOG1 + #define TU_LOG2_MEM TU_LOG1_MEM + #define TU_LOG2_LOCATION() TU_LOG1_LOCATION() #endif #endif // CFG_TUSB_DEBUG diff --git a/src/device/dcd.h b/src/device/dcd.h index dca289e78..8ae232fa6 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -110,6 +110,10 @@ void dcd_remote_wakeup(uint8_t rhport); // Endpoint API //--------------------------------------------------------------------+ +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; + // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 7f6cf5a40..8b9b8f1cf 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -64,6 +64,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con return dcd_edpt_xfer(rhport, request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN, NULL, 0); } +// Status phase bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) { _ctrl_xfer.request = (*request); @@ -141,6 +142,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) { TU_ASSERT(0 == xferred_bytes); + if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); return true; } diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index ec182960e..7ba9481ba 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -296,6 +296,8 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void)rhport; + + // FIXME use dcd_edpt0_status_complete() // We cannot immediatly change it; it must be queued to change after the STATUS packet is sent. // (CTR handler will actually change the address once it sees that the transmission is complete) newDADDR = dev_addr; -- cgit v1.3.1 From 5dc04887e28314c1d74409939af66445ce9626ae Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Nov 2019 11:48:08 +0700 Subject: get passed set address --- src/device/usbd.c | 7 ++++- src/portable/microchip/samg/dcd_samg.c | 49 +++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 17 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 530eb09d1..01ec0e5fd 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -405,7 +405,6 @@ void tud_task (void) if ( 0 == epnum ) { - TU_LOG1(" EP Addr = 0x%02X, len = %ld\r\n", ep_addr, event.xfer_complete.len); usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } else @@ -503,7 +502,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Depending on mcu, status phase could be sent either before or after changing device address // Therefore DCD must include zero-length status response dcd_set_address(rhport, (uint8_t) p_request->wValue); + +// FIXME remove STATUS response from dcd_set_address(), +#if CFG_TUSB_MCU == OPT_MCU_SAMG // skip status for nrf5x mcu + tud_control_status(rhport, p_request); +#else return true; // skip status +#endif break; case TUSB_REQ_GET_CONFIGURATION: diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 27fd35de6..bf842eab3 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -119,6 +119,9 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { (void) rhport; (void) dev_addr; + + // SAMG can only set address after status for this request is complete + // do it at dcd_edpt0_status_complete() } // Receive Set Configure request @@ -138,6 +141,27 @@ void dcd_remote_wakeup (uint8_t rhport) // Endpoint API //--------------------------------------------------------------------+ +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bRequest == TUSB_REQ_SET_ADDRESS) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + TU_LOG2("dev address = %d", dev_addr); + + // Enable addressed state + UDP->UDP_GLB_STAT |= UDP_GLB_STAT_FADDEN_Msk; + + // Set new address & Function enable bit + UDP->UDP_FADDR |= UDP_FADDR_FADD(dev_addr); + + UDP->UDP_FADDR |= UDP_FADDR_FEN_Msk; + } +} + // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { @@ -162,19 +186,14 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // 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) { + // Clear DIR bit UDP->UDP_CSR[0] &= ~UDP_CSR_DIR_Msk; - // + }else { + // Set DIR bit if needed UDP->UDP_CSR[0] |= UDP_CSR_DIR_Msk; // Write data to fifo @@ -250,13 +269,6 @@ void dcd_isr(uint8_t rhport) setup[i] = (uint8_t) UDP->UDP_FDR[0]; } - // 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); @@ -283,7 +295,12 @@ void dcd_isr(uint8_t rhport) // Endpoint OUT if (UDP->UDP_CSR[epnum] & UDP_CSR_RX_DATA_BK0_Msk) { - dcd_event_bus_signal(rhport, DCD_EVENT_INVALID, true); + uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[0] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); + + dcd_event_xfer_complete(rhport, epnum, xact_len, XFER_RESULT_SUCCESS, true); + + // Clear DATA Bank0 bit + UDP->UDP_CSR[0] &= ~UDP_CSR_RX_DATA_BK0_Msk; } } } -- cgit v1.3.1 From d7558e8a0f12c685f2690c985e5f75df0777065b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Nov 2019 13:39:29 +0700 Subject: use dcd_edpt0_status_complete() to set address without blocking for samd21/samd51/stm32_fsdev --- src/device/usbd.c | 25 +++++++++----------- src/device/usbd_control.c | 12 ++++++++-- src/portable/microchip/samd21/dcd_samd21.c | 25 +++++++++++++++----- src/portable/microchip/samd51/dcd_samd51.c | 23 ++++++++++++++---- src/portable/microchip/samg/dcd_samg.c | 5 +++- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 34 ++++++++++++++++----------- src/portable/st/synopsys/dcd_synopsys.c | 1 - 7 files changed, 82 insertions(+), 43 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 01ec0e5fd..497281c2d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -202,9 +202,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); -void usbd_control_reset (uint8_t rhport); -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void usbd_control_reset(void); +void usbd_control_set_request(tusb_control_request_t const *request); void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); +bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); //--------------------------------------------------------------------+ @@ -321,7 +322,7 @@ static void usbd_reset(uint8_t rhport) memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping - usbd_control_reset(rhport); + usbd_control_reset(); for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) { @@ -376,7 +377,7 @@ void tud_task (void) case DCD_EVENT_SETUP_RECEIVED: TU_LOG2(" "); - TU_LOG1_MEM(&event.setup_received, 1, 8); + TU_LOG2_MEM(&event.setup_received, 1, 8); // Mark as connected after receiving 1st setup packet. // But it is easier to set it every time instead of wasting time to check then set @@ -385,7 +386,7 @@ void tud_task (void) // Process control request if ( !process_control_request(event.rhport, &event.setup_received) ) { - TU_LOG1(" Stall EP0\r\n"); + TU_LOG2(" Stall EP0\r\n"); // Failed -> stall both control endpoint IN and OUT dcd_edpt_stall(event.rhport, 0); dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK); @@ -499,16 +500,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const switch ( p_request->bRequest ) { case TUSB_REQ_SET_ADDRESS: - // Depending on mcu, status phase could be sent either before or after changing device address - // Therefore DCD must include zero-length status response + // Depending on mcu, status phase could be sent either before or after changing device address, + // or even require stack to not response with status at all + // Therefore DCD must take full responsibility to response and include zlp status packet if needed. + usbd_control_set_request(p_request); // set request since DCD has no access to tud_control_status() API dcd_set_address(rhport, (uint8_t) p_request->wValue); - -// FIXME remove STATUS response from dcd_set_address(), -#if CFG_TUSB_MCU == OPT_MCU_SAMG // skip status for nrf5x mcu - tud_control_status(rhport, p_request); -#else - return true; // skip status -#endif + // skip tud_control_status() break; case TUSB_REQ_GET_CONFIGURATION: diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 8b9b8f1cf..e6d1caf4b 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -119,9 +119,8 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // USBD API //--------------------------------------------------------------------+ -void usbd_control_reset (uint8_t rhport) +void usbd_control_reset(void) { - (void) rhport; tu_varclr(&_ctrl_xfer); } @@ -131,6 +130,15 @@ void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_reque _ctrl_xfer.complete_cb = fp; } +// useful for dcd_set_address where DCD is responsible for status response +void usbd_control_set_request(tusb_control_request_t const *request) +{ + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = NULL; + _ctrl_xfer.total_xferred = 0; + _ctrl_xfer.data_len = 0; +} + // callback when a transaction complete on // - DATA stage of control endpoint or // - Status stage diff --git a/src/portable/microchip/samd21/dcd_samd21.c b/src/portable/microchip/samd21/dcd_samd21.c index 231abc7d0..3ffaabf09 100644 --- a/src/portable/microchip/samd21/dcd_samd21.c +++ b/src/portable/microchip/samd21/dcd_samd21.c @@ -98,13 +98,13 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { - // Response with status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + (void) dev_addr; - // Wait for EP0 to finish before switching the address. - while (USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK1RDY == 1) {} + // Response with zlp status + dcd_edpt_xfer(rhport, 0x80, NULL, 0); - USB->DEVICE.DADD.reg = USB_DEVICE_DADD_DADD(dev_addr) | USB_DEVICE_DADD_ADDEN; + // DCD can only set address after status for this request is complete + // do it at dcd_edpt0_status_complete() // Enable SUSPEND interrupt since the bus signal D+/D- are stable now. USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTENCLR_SUSPEND; // clear pending @@ -116,7 +116,6 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num) (void) rhport; (void) config_num; // Nothing to do - } void dcd_remote_wakeup(uint8_t rhport) @@ -130,6 +129,20 @@ void dcd_remote_wakeup(uint8_t rhport) /* DCD Endpoint port *------------------------------------------------------------------*/ +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bRequest == TUSB_REQ_SET_ADDRESS) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + USB->DEVICE.DADD.reg = USB_DEVICE_DADD_DADD(dev_addr) | USB_DEVICE_DADD_ADDEN; + } +} + + bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { (void) rhport; diff --git a/src/portable/microchip/samd51/dcd_samd51.c b/src/portable/microchip/samd51/dcd_samd51.c index f58e7cbc7..1af247702 100644 --- a/src/portable/microchip/samd51/dcd_samd51.c +++ b/src/portable/microchip/samd51/dcd_samd51.c @@ -104,13 +104,13 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { - // Response with status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + (void) dev_addr; - // Wait for EP0 to finish before switching the address. - while (USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK1RDY == 1) {} + // Response with zlp status + dcd_edpt_xfer(rhport, 0x80, NULL, 0); - USB->DEVICE.DADD.reg = USB_DEVICE_DADD_DADD(dev_addr) | USB_DEVICE_DADD_ADDEN; + // DCD can only set address after status for this request is complete + // do it at dcd_edpt0_status_complete() // Enable SUSPEND interrupt since the bus signal D+/D- are stable now. USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTENCLR_SUSPEND; // clear pending @@ -135,6 +135,19 @@ void dcd_remote_wakeup(uint8_t rhport) /* DCD Endpoint port *------------------------------------------------------------------*/ +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bRequest == TUSB_REQ_SET_ADDRESS) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + USB->DEVICE.DADD.reg = USB_DEVICE_DADD_DADD(dev_addr) | USB_DEVICE_DADD_ADDEN; + } +} + bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { (void) rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index c38621e00..122dc04b7 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -120,7 +120,10 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) rhport; (void) dev_addr; - // SAMG can only set address after status for this request is complete + // Response with zlp status + dcd_edpt_xfer(rhport, 0x80, NULL, 0); + + // DCD can only set address after status for this request is complete. // do it at dcd_edpt0_status_complete() } diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 7ba9481ba..f52e113b7 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -172,7 +172,6 @@ static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t epnum, uint32_t dir) static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; -static uint8_t newDADDR; // Used to set the new device address during the CTR IRQ handler static uint8_t remoteWakeCountdown; // When wake is requested // EP Buffers assigned from end of memory location, to minimize their chance of crashing @@ -297,14 +296,11 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void)rhport; - // FIXME use dcd_edpt0_status_complete() - // We cannot immediatly change it; it must be queued to change after the STATUS packet is sent. - // (CTR handler will actually change the address once it sees that the transmission is complete) - newDADDR = dev_addr; - // Respond with status dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + // DCD can only set address after status for this request is complete. + // do it at dcd_edpt0_status_complete() } // Receive Set Config request @@ -361,7 +357,7 @@ static void dcd_handle_bus_reset(void) ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each) dcd_edpt_open (0, &ep0OUT_desc); dcd_edpt_open (0, &ep0IN_desc); - newDADDR = 0u; + USB->DADDR = USB_DADDR_EF; // Set enable flag, and leaving the device address as zero. } @@ -397,13 +393,7 @@ static uint16_t dcd_ep_ctr_handler(void) if((xfer->total_len == xfer->queued_len)) { dcd_event_xfer_complete(0u, (uint8_t)(0x80 + EPindex), xfer->total_len, XFER_RESULT_SUCCESS, true); - if((newDADDR != 0) && ( xfer->total_len == 0U)) - { - // Delayed setting of the DADDR after the 0-len DATA packet acking the request is sent. - reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD); - USB->DADDR = (uint16_t)(USB->DADDR | newDADDR); // leave the enable bit set - newDADDR = 0; - } + if(xfer->total_len == 0) // Probably a status message? { pcd_clear_rx_dtog(USB,EPindex); @@ -601,6 +591,22 @@ static void dcd_fs_irqHandler(void) { // Endpoint API //--------------------------------------------------------------------+ +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bRequest == TUSB_REQ_SET_ADDRESS) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + + // Setting new address after the whole request is complete + reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD); + USB->DADDR = (uint16_t)(USB->DADDR | dev_addr); // leave the enable bit set + } +} + // The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers, // so I'm using the #define from HAL here, instead. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 7929b6916..e02580e4f 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -236,7 +236,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) rhport; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; - dev->DCFG |= (dev_addr << USB_OTG_DCFG_DAD_Pos) & USB_OTG_DCFG_DAD_Msk; // Response with status after changing device address -- cgit v1.3.1 From 050fa2fd394912775994d4171774adb475eaf531 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 21 Dec 2019 19:33:41 +0700 Subject: able to response to scsi inquiry, but failed to response to test unit ready --- src/class/msc/msc_device.c | 9 ++ src/common/tusb_common.h | 2 +- src/device/usbd.c | 5 +- src/portable/microchip/samg/dcd_samg.c | 158 ++++++++++++++++++++++----------- src/tusb.c | 6 +- 5 files changed, 125 insertions(+), 55 deletions(-) (limited to 'src/device') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index bf2b5bb8c..190252265 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -378,6 +378,9 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); + TU_LOG2(" Command Block Wrapper\n"); + TU_LOG2_MEM(p_cbw, xferred_bytes, 2); + p_csw->signature = MSC_CSW_SIGNATURE; p_csw->tag = p_cbw->tag; p_csw->data_residue = 0; @@ -448,6 +451,9 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; case MSC_STAGE_DATA: + //TU_LOG2(" SCSI Data\n"); + //TU_LOG2_MEM(_mscd_buf, xferred_bytes, 2); + // OUT transfer, invoke callback if needed if ( !tu_bit_test(p_cbw->dir, 7) ) { @@ -538,6 +544,9 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the command status wrapper complete event if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) { + TU_LOG2(" Command Status Wrapper\n"); + TU_LOG2_MEM(p_csw, xferred_bytes, 2); + // Move to default CMD stage p_msc->stage = MSC_STAGE_CMD; diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index a2c40e669..f76abca88 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -213,7 +213,7 @@ static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value // 2 : print out log #if CFG_TUSB_DEBUG -void tu_print_mem(void const *buf, uint8_t size, uint16_t count); +void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); #ifndef tu_printf #define tu_printf printf diff --git a/src/device/usbd.c b/src/device/usbd.c index 497281c2d..5832f2353 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -376,8 +376,7 @@ void tud_task (void) break; case DCD_EVENT_SETUP_RECEIVED: - TU_LOG2(" "); - TU_LOG2_MEM(&event.setup_received, 1, 8); + TU_LOG2_MEM(&event.setup_received, 8, 2); // Mark as connected after receiving 1st setup packet. // But it is easier to set it every time instead of wasting time to check then set @@ -949,6 +948,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ); _usbd_dev.ep_status[epnum][dir].busy = true; + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, total_bytes); + return true; } diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index f05763e38..96cd775c4 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -51,6 +51,11 @@ typedef struct // Endpoint 0-5, each can only be either OUT or In xfer_desc_t _dcd_xfer[EP_COUNT]; +void xfer_epsize_set(xfer_desc_t* xfer, uint16_t epsize) +{ + xfer->epsize = epsize; +} + void xfer_begin(xfer_desc_t* xfer, uint8_t * buffer, uint16_t total_bytes) { xfer->buffer = buffer; @@ -73,14 +78,23 @@ void xfer_packet_done(xfer_desc_t* xfer) } //------------- Transaction helpers -------------// -static uint16_t xact_in(uint8_t epnum, xfer_desc_t* xfer) -{ - uint16_t const xact_len = xfer_packet_len(xfer); - // Write data to fifo - for(uint16_t i=0; iUDP_FDR[epnum] = (uint32_t) xfer->buffer[i]; +// Write data to EP FIFO, return number of written bytes +static void xact_ep_write(uint8_t epnum, uint8_t* buffer, uint16_t xact_len) +{ + for(uint16_t i=0; iUDP_FDR[epnum] = (uint32_t) buffer[i]; + } +} - return xact_len; +// Read data from EP FIFO +static void xact_ep_read(uint8_t epnum, uint8_t* buffer, uint16_t xact_len) +{ + for(uint16_t i=0; iUDP_FDR[epnum]; + } } /*------------------------------------------------------------------*/ @@ -92,7 +106,7 @@ static void bus_reset(void) { tu_memclr(_dcd_xfer, sizeof(_dcd_xfer)); - _dcd_xfer[0].epsize = CFG_TUD_ENDPOINT0_SIZE; + xfer_epsize_set(&_dcd_xfer[0], CFG_TUD_ENDPOINT0_SIZE); // Enable EP0 control UDP->UDP_CSR[0] = UDP_CSR_EPEDS_Msk; @@ -205,11 +219,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) // Must not already enabled TU_ASSERT((UDP->UDP_CSR[epnum] & UDP_CSR_EPEDS_Msk) == 0); + xfer_epsize_set(&_dcd_xfer[epnum], ep_desc->wMaxPacketSize.size); + // Configure type and eanble EP UDP->UDP_CSR[epnum] = UDP_CSR_EPEDS_Msk | UDP_CSR_EPTYPE(ep_desc->bmAttributes.xfer + 4*dir); - // Enable EP Interrupt - UDP->UDP_IER |= (1 << epnum); + // Enable EP Interrupt for IN + if (dir == TUSB_DIR_IN) UDP->UDP_IER |= (1 << epnum); return true; } @@ -225,27 +241,47 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_desc_t* xfer = &_dcd_xfer[epnum]; xfer_begin(xfer, buffer, total_bytes); - // Configure DIR bit for control endpoint - if ( epnum == 0 ) - { - if (dir == TUSB_DIR_OUT) - { - // Clear DIR bit - UDP->UDP_CSR[0] &= ~UDP_CSR_DIR_Msk; - }else - { - // Set DIR bit - UDP->UDP_CSR[0] |= UDP_CSR_DIR_Msk; - } - } - if (dir == TUSB_DIR_IN) { - xact_in(epnum, xfer); + // Set DIR bit for EP0 + if ( epnum == 0 ) UDP->UDP_CSR[epnum] |= UDP_CSR_DIR_Msk; + + xact_ep_write(epnum, xfer->buffer, xfer_packet_len(xfer)); // TX ready for transfer UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; } + else + { + // Clear DIR bit for EP0 + if ( epnum == 0 ) UDP->UDP_CSR[epnum] &= ~UDP_CSR_DIR_Msk; + + // OUT Data may already received and acked by hardware + // Read it as 1st packet then continue with transfer if needed +// uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); +// +// if ( xact_len ) +// { +// // Read from EP fifo +// xact_ep_read(epnum, xfer->buffer, xact_len); +// xfer_packet_done(xfer); +// +// // Clear DATA Bank0 bit +// UDP->UDP_CSR[epnum] &= ~UDP_CSR_RX_DATA_BK0_Msk; +// +// if ( 0 == xfer_packet_len(xfer) ) +// { +// // Disable OUT EP interrupt when transfer is complete +// UDP->UDP_IER &= ~(1 << epnum); +// +// dcd_event_xfer_complete(rhport, epnum, xact_len, XFER_RESULT_SUCCESS, false); +// return true; // complete +// } +// } + + // Enable interrupt when starting OUT transfer + UDP->UDP_IER |= (1 << epnum); + } return true; } @@ -325,47 +361,67 @@ void dcd_isr(uint8_t rhport) // Clear Setup bit UDP->UDP_CSR[0] &= ~UDP_CSR_RXSETUP_Msk; + + return; } } for(uint8_t epnum = 0; epnum < EP_COUNT; epnum++) { - xfer_desc_t* xfer = &_dcd_xfer[epnum]; - - // Endpoint IN - if (UDP->UDP_CSR[epnum] & UDP_CSR_TXCOMP_Msk) + if ( intr_status & TU_BIT(epnum) ) { - xfer_packet_done(xfer); + xfer_desc_t* xfer = &_dcd_xfer[epnum]; - if ( xact_in(epnum, xfer) ) + // Endpoint IN + if (UDP->UDP_CSR[epnum] & UDP_CSR_TXCOMP_Msk) { - // TX ready for transfer - UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; - }else - { - // xfer is complete - dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + xfer_packet_done(xfer); + + uint16_t const xact_len = xfer_packet_len(xfer); + + if (xact_len) + { + // write to EP fifo + xact_ep_write(epnum, xfer->buffer, xact_len); + + // TX ready for transfer + UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; + }else + { + // xfer is complete + dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + } + + // Clear TX Complete bit + UDP->UDP_CSR[epnum] &= ~UDP_CSR_TXCOMP_Msk; } - // Clear TX Complete bit - UDP->UDP_CSR[epnum] &= ~UDP_CSR_TXCOMP_Msk; - } + // Endpoint OUT + if (UDP->UDP_CSR[epnum] & UDP_CSR_RX_DATA_BK0_Msk) + { + uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); - // Endpoint OUT - if (UDP->UDP_CSR[epnum] & UDP_CSR_RX_DATA_BK0_Msk) - { - uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); + // Read from EP fifo + xact_ep_read(epnum, xfer->buffer, xact_len); + xfer_packet_done(xfer); - dcd_event_xfer_complete(rhport, epnum, xact_len, XFER_RESULT_SUCCESS, true); + if ( 0 == xfer_packet_len(xfer) ) + { + // Disable OUT EP interrupt when transfer is complete + UDP->UDP_IER &= ~(1 << epnum); - // Clear DATA Bank0 bit - UDP->UDP_CSR[epnum] &= ~UDP_CSR_RX_DATA_BK0_Msk; - } + dcd_event_xfer_complete(rhport, epnum, xact_len, XFER_RESULT_SUCCESS, true); + } - // Stall sent to host - if (UDP->UDP_CSR[epnum] & UDP_CSR_STALLSENT_Msk) - { - UDP->UDP_CSR[epnum] &= ~UDP_CSR_STALLSENT_Msk; + // Clear DATA Bank0 bit + UDP->UDP_CSR[epnum] &= ~UDP_CSR_RX_DATA_BK0_Msk; + } + + // Stall sent to host + if (UDP->UDP_CSR[epnum] & UDP_CSR_STALLSENT_Msk) + { + UDP->UDP_CSR[epnum] &= ~UDP_CSR_STALLSENT_Msk; + } } } } diff --git a/src/tusb.c b/src/tusb.c index 7a1e73ec7..f68387450 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -81,8 +81,10 @@ static void dump_str_line(uint8_t const* buf, uint16_t count) // size : item size in bytes // count : number of item // print offet or not (handfy for dumping large memory) -void tu_print_mem(void const *buf, uint8_t size, uint16_t count) +void tu_print_mem(void const *buf, uint16_t count, uint8_t indent) { + uint8_t const size = 1; // fixed 1 byte for now + if ( !buf || !count ) { tu_printf("NULL\r\n"); @@ -110,6 +112,8 @@ void tu_print_mem(void const *buf, uint8_t size, uint16_t count) tu_printf("\r\n"); } + for(uint8_t s=0; s < indent; s++) tu_printf(" "); + // print offset or absolute address tu_printf("%03lX: ", 16*i/item_per_line); } -- cgit v1.3.1 From bbada1d3e6dba5b339c7cd4129e5df7b3203c11b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Dec 2019 18:54:06 +0700 Subject: adding lookup table for debugging add msc scsi command list --- src/class/msc/msc_device.c | 32 ++++++++++++++++++++++++++++++-- src/common/tusb_common.h | 23 +++++++++++++++++++++++ src/device/usbd.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 5 +++-- 4 files changed, 57 insertions(+), 5 deletions(-) (limited to 'src/device') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 84fe5a194..93167bc6d 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -97,6 +97,34 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) return tu_ntohs(block_count); } +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static lookup_entry_t const _msc_scsi_cmd_lookup[] = +{ + { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, + { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, + { .key = SCSI_CMD_MODE_SELECT_6 , .data = "Mode_Select 6" }, + { .key = SCSI_CMD_MODE_SENSE_6 , .data = "Mode_Sense 6" }, + { .key = SCSI_CMD_START_STOP_UNIT , .data = "Start Stop Unit" }, + { .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent Allow Medium Removal" }, + { .key = SCSI_CMD_READ_CAPACITY_10 , .data = "Read Capacity10" }, + { .key = SCSI_CMD_REQUEST_SENSE , .data = "Request Sense" }, + { .key = SCSI_CMD_READ_FORMAT_CAPACITY , .data = "Read Format Capacity" }, + { .key = SCSI_CMD_READ_10 , .data = "Read10" }, + { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } +}; + +static lookup_table_t const _msc_scsi_cmd_table = +{ + .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), + .items = _msc_scsi_cmd_lookup +}; + +#endif + //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ @@ -378,7 +406,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); - TU_LOG2(" Command Block Wrapper\n"); + TU_LOG2(" SCSI Command: %s\n", lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); // TU_LOG2_MEM(p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; @@ -544,7 +572,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the command status wrapper complete event if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) { - TU_LOG2(" Command Status Wrapper\n"); + TU_LOG2(" SCSI Status: %u\n", p_csw->status); // TU_LOG2_MEM(p_csw, xferred_bytes, 2); // Move to default CMD stage diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index f76abca88..5700c1282 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -231,6 +231,29 @@ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); #define TU_LOG2_LOCATION() TU_LOG1_LOCATION() #endif + +typedef struct +{ + uint32_t key; + char const * data; +}lookup_entry_t; + +typedef struct +{ + uint16_t count; + lookup_entry_t const* items; +} lookup_table_t; + +static inline char const* lookup_find(lookup_table_t const* p_table, uint32_t key) +{ + for(uint16_t i=0; icount; i++) + { + if (p_table->items[i].key == key) return p_table->items[i].data; + } + + return NULL; +} + #endif // CFG_TUSB_DEBUG #ifndef TU_LOG1 diff --git a/src/device/usbd.c b/src/device/usbd.c index 5832f2353..949e14096 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -211,7 +211,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, //--------------------------------------------------------------------+ // Debugging //--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG > 1 +#if CFG_TUSB_DEBUG >= 2 static char const* const _usbd_event_str[DCD_EVENT_COUNT] = { "INVALID" , diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index fd50237dc..a93b26caa 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -267,9 +267,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // Read it as 1st packet then continue with transfer if needed if ( UDP->UDP_CSR[epnum] & (UDP_CSR_RX_DATA_BK0_Msk | UDP_CSR_RX_DATA_BK1_Msk) ) { - uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); +// uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); - TU_LOG2("xact_len = %d\r", xact_len); +// TU_LOG2("xact_len = %d\r", xact_len); // // Read from EP fifo // xact_ep_read(epnum, xfer->buffer, xact_len); @@ -406,6 +406,7 @@ void dcd_isr(uint8_t rhport) } // Endpoint OUT + // Ping-Pong is a must for Bulk/Iso // When both Bank0 and Bank1 are both set, there is not way to know which one comes first if (UDP->UDP_CSR[epnum] & (UDP_CSR_RX_DATA_BK0_Msk | UDP_CSR_RX_DATA_BK1_Msk)) { -- cgit v1.3.1