From 59e85cf921f3a282df344513e1ae26fb0f756732 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 19:39:12 +0200 Subject: [PATCH 01/10] usbdev: Refactor to xmit API This API change refactors the usbdev API to supply buffers via the usbdev_ep_xmit function. This changes from the usbdev_ep_ready call to allow separate buffers per call. An usbdev_ep_buf_t pseudotype is available and must be used when defining buffers used for endpoints to adhere to the DMA alignment restrictions often required with usb peripherals. Main advantage is that the usbdev peripherals no longer have to allocate oversized buffers for the endpoint data, potentially saving multiple KiB of unused buffer space. These allocations are now the responsibility of the individual USB interfaces in the firmware --- drivers/include/periph/usbdev.h | 102 +++++++++++++++++++++----------- sys/include/usb/usbopt.h | 5 -- 2 files changed, 67 insertions(+), 40 deletions(-) diff --git a/drivers/include/periph/usbdev.h b/drivers/include/periph/usbdev.h index 1845b5e69a..1ba20a9f89 100644 --- a/drivers/include/periph/usbdev.h +++ b/drivers/include/periph/usbdev.h @@ -37,22 +37,26 @@ * it's endpoint number. It can simply request an available endpoint from the * usb device with the @ref usbdev_new_ep function. * - * Data transmission is done by requesting the endpoint with a max packet size. - * Memory for this buffer is allocated from dedicated memory of the MCU USB - * peripheral or from a buffer allocated by the peripheral specific usbdev - * struct. Received data from the host ends up at this buffer automatically - * by the low level drivers. Signalling that the data at the specified address - * is ready to be reused is done with the @ref usbdev_ep_ready function by - * supplying a size of 0 for the @p len argument. + * Each interface handler can request multiple endpoints from the usbdev device. + * It must supply the expected maximum endpoint transfer size and other + * properties of the endpoint. A pointer to an usbdev endpoint is returned if + * an endpoint fitting the requirements is available. + * + * Data transmission is done via the @ref usbdev_ep_xmit function. A buffer and + * length must be supplied. Received data from the host ends up at this buffer + * automatically by the low level drivers after reception. For reception the + * maximum expected transfer length must be supplied, equal to the maximum + * endpoint transfer size. The data received can be less than this. * * For transmitting data back to the host, a similar approach is used. The data - * to be transmitted is written to the specified address and the - * @ref usbdev_ep_ready function is called with the size of the data as @p len - * argument. + * to be transmitted is supplied as buffer and the @ref usbdev_ep_xmit function + * is called with the buffer and the size of the data. * - * This approach of setting the address and only indicating new data available - * is done to allow the low level USB peripheral to use DMA to transfer the data - * from and to the MCU memory. + * To ensure that the data buffers adhere to the restrictions of the low level + * USB peripheral memory interface, the specific @ref usbdev_ep_buf_t data type + * must be used. It behaves as a regular `uint8_t` byte buffer, but is + * instantiated with the attributes to ensure that the low level DMA interface + * can use it. * * A callback function is required for signalling events from the driver. The * @ref USBDEV_EVENT_ESR is special in that it indicates that the USB peripheral @@ -75,6 +79,7 @@ #include #include "assert.h" +#include "periph_cpu.h" #include "usb.h" #include "usb/usbopt.h" @@ -93,16 +98,31 @@ typedef struct usbdev usbdev_t; typedef struct usbdev_ep usbdev_ep_t; /** - * @brief Statically allocated buffer space for endpoints. + * @brief USBDEV endpoint buffer CPU-specific requirements * - * When the device doesn't have dedicated memory for endpoint buffers, a - * buffer of this size is allocated to contain the endpoint buffers. Only - * needs to be as big as the total buffer space required by all endpoints + * Can be overridden by periph_cpu if needed by the USB peripheral DMA. */ -#ifndef USBDEV_EP_BUF_SPACE -#define USBDEV_EP_BUF_SPACE 1024 +#ifndef USBDEV_CPU_DMA_REQUIREMENTS +#define USBDEV_CPU_DMA_REQUIREMENTS #endif +/** + * @brief Instantiation type for usbdev endpoint buffers + * + * Functions passing around pointers to these buffers can still use `uint8_t` + * for the argument type. + * + * Example usage: + * + * ``` + * usbdev_ep_buf_t buffer[64]; + * ``` + * + * @note This is a define and not a typedef so that the above works. With a + * typedef it would + */ +#define usbdev_ep_buf_t USBDEV_CPU_DMA_REQUIREMENTS uint8_t + /** * @brief Number of USB IN and OUT endpoints allocated * @@ -232,8 +252,7 @@ struct usbdev { */ struct usbdev_ep { usbdev_t *dev; /**< USB device this endpoint belongs to */ - uint8_t *buf; /**< Ptr to the data buffer */ - size_t len; /**< Size of the data buffer in bytes */ + size_t len; /**< Endpoint configured max transfer size in bytes */ usb_ep_dir_t dir; /**< Endpoint direction */ usb_ep_type_t type; /**< Endpoint type */ uint8_t num; /**< Endpoint number */ @@ -265,12 +284,12 @@ typedef struct usbdev_driver { * @param[in] dev USB device descriptor * @param[in] type USB endpoint type * @param[in] dir USB endpoint direction - * @param[in] buf_len optimal USB endpoint buffer size + * @param[in] size USB endpoint buffer size * * @return ptr to the new USB endpoint descriptor * @return NULL on error */ - usbdev_ep_t *(*new_ep)(usbdev_t *dev, usb_ep_type_t type, usb_ep_dir_t dir, size_t buf_len); + usbdev_ep_t *(*new_ep)(usbdev_t *dev, usb_ep_type_t type, usb_ep_dir_t dir, size_t size); /** * @brief Get an option value from a given usb device @@ -359,14 +378,22 @@ typedef struct usbdev_driver { void (*ep_esr)(usbdev_ep_t *ep); /** - * @brief Signal data buffer ready for data transmission + * @brief Transmit a data buffer + * + * Ownership of the @p buf is transferred to the usbdev device after calling + * this. Do not modify (or unallocate) the buffer between calling this and + * when it is released via the @ref USBDEV_EVENT_TR_COMPLETE event. * * This clears the stall setting in the endpoint if that is enabled. * + * @note The @p buf passed here must have been declared as + * @ref usbdev_ep_buf_t before so that DMA restrictions are applied to it + * * @param[in] ep USB endpoint descriptor - * @param[in] len length of the data to be transmitted + * @param[inout] buf Buffer with the data to transfer + * @param[in] len (Max) Length of the data to transfer */ - int (*ready)(usbdev_ep_t *ep, size_t len); + int (*xmit)(usbdev_ep_t *ep, uint8_t *buf, size_t len); } usbdev_driver_t; /** @@ -410,16 +437,16 @@ static inline void usbdev_init(usbdev_t *dev) * @param[in] dev USB device descriptor * @param[in] type USB endpoint type * @param[in] dir USB endpoint direction - * @param[in] buf_len optimal USB endpoint buffer size + * @param[in] size Maximum USB endpoint buffer size used * * @return ptr to the new USB endpoint descriptor * @return NULL on error */ static inline usbdev_ep_t * usbdev_new_ep(usbdev_t *dev, usb_ep_type_t type, - usb_ep_dir_t dir, size_t buf_len) + usb_ep_dir_t dir, size_t size) { assert(dev); - return dev->driver->new_ep(dev, type, dir, buf_len); + return dev->driver->new_ep(dev, type, dir, size); } /** @@ -564,21 +591,26 @@ static inline void usbdev_ep_esr(usbdev_ep_t *ep) } /** - * @brief Signal data buffer ready for data transmission + * @brief Submit a buffer for a USB endpoint transmission * - * @see @ref usbdev_driver_t::ready + * When dealing with an OUT type endpoint, @p len must be the maximum allowed + * transfer size for the endpoint. The host is allowed to transfer fewer bytes + * than @p len. + * + * @see @ref usbdev_driver_t::xmit * * @pre `(ep != NULL)` * @pre `(ep->dev != NULL)` * - * @param[in] ep USB endpoint descriptor - * @param[in] len length of the data to be transmitted + * @param[in] ep USB endpoint descriptor + * @param[inout] buf Buffer to submit for transmission + * @param[in] len length of the buffer in bytes to be transmitted or received */ -static inline int usbdev_ep_ready(usbdev_ep_t *ep, size_t len) +static inline int usbdev_ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len) { assert(ep); assert(ep->dev); - return ep->dev->driver->ready(ep, len); + return ep->dev->driver->xmit(ep, buf, len); } #ifdef __cplusplus diff --git a/sys/include/usb/usbopt.h b/sys/include/usb/usbopt.h index 900f28273f..db684ebb97 100644 --- a/sys/include/usb/usbopt.h +++ b/sys/include/usb/usbopt.h @@ -91,11 +91,6 @@ typedef enum { */ USBOPT_EP_STALL, - /** - * @brief (usbopt_enable_t) Signal data ready or not ready anymore - */ - USBOPT_EP_READY, - /** * @brief (size_t) Retrieve number of bytes available on endpoint. */ From 597f1d19aaeac01326c41c2142e028e66d25569f Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 22:05:23 +0200 Subject: [PATCH 02/10] usbdev: Refactor to xmit API This API change refactors the usbdev API to supply buffers via the usbdev_ep_xmit function. This changes from the usbdev_ep_ready call to allow separate buffers per call. An usbdev_ep_buf_t pseudotype is available and must be used when defining buffers used for endpoints to adhere to the DMA alignment restrictions often required with usb peripherals. Main advantage is that the usbdev peripherals no longer have to allocate oversized buffers for the endpoint data, potentially saving multiple KiB of unused buffer space. These allocations are now the responsibility of the individual USB interfaces in the firmware --- drivers/include/periph/usbdev.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/include/periph/usbdev.h b/drivers/include/periph/usbdev.h index 1ba20a9f89..0d947ea9f2 100644 --- a/drivers/include/periph/usbdev.h +++ b/drivers/include/periph/usbdev.h @@ -119,7 +119,8 @@ typedef struct usbdev_ep usbdev_ep_t; * ``` * * @note This is a define and not a typedef so that the above works. With a - * typedef it would + * typedef it would instantiate an array of aligned uint8_t and not an aligned + * array of uint8_t (assuming the requirement is alignment). */ #define usbdev_ep_buf_t USBDEV_CPU_DMA_REQUIREMENTS uint8_t From f8e7e2f55754260fa705f5cd571782be752332c1 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 19:41:38 +0200 Subject: [PATCH 03/10] usbdev_mock: Adapt to xmit API Includes the adaptations needed in the test application --- drivers/include/usbdev_mock.h | 9 +++++---- drivers/usbdev_mock/usbdev_mock.c | 21 ++++++++++++--------- tests/usbus/main.c | 12 +++++------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/include/usbdev_mock.h b/drivers/include/usbdev_mock.h index 324dea8c83..d502a02a4d 100644 --- a/drivers/include/usbdev_mock.h +++ b/drivers/include/usbdev_mock.h @@ -40,10 +40,11 @@ typedef enum { * @brief usbdev mock device endpoint */ typedef struct { - usbdev_ep_t ep; /**< Generic endpoint struct */ - usbdev_mock_ep_state_t state; /**< Endpoint state */ - size_t available; /**< Bytes available in the buffer */ - uint8_t *buf_start; /**< Start location of the buffer */ + usbdev_ep_t ep; /**< Generic endpoint struct */ + usbdev_mock_ep_state_t state; /**< Endpoint state */ + size_t available; /**< Bytes available in the buffer */ + uint8_t *target_buf; /**< Buffer as passed by @ref usbdev_ep_xmit */ + uint8_t *buf; /**< Internal mock buffer pointer */ } usbdev_mock_ep_t; /** diff --git a/drivers/usbdev_mock/usbdev_mock.c b/drivers/usbdev_mock/usbdev_mock.c index a3c9a9d3bf..944cef9381 100644 --- a/drivers/usbdev_mock/usbdev_mock.c +++ b/drivers/usbdev_mock/usbdev_mock.c @@ -75,16 +75,15 @@ usbdev_ep_t *_new_ep(usbdev_t *dev, usb_ep_type_t type, usb_ep_dir_t dir, res = &testdev->out[0]; res->ep.num = 0; - res->ep.buf = _out_buf; + res->buf = _out_buf; } else { res = &testdev->in[0]; res->ep.num = 0; - res->ep.buf = _in_buf; + res->buf = _in_buf; } } if (res) { - res->buf_start = res->ep.buf; res->state = EP_STATE_READY; res->available = 0; res->ep.len = buf_len; @@ -190,26 +189,30 @@ void _ep_esr(usbdev_ep_t *ep) ep->num, ep->dir == USB_EP_DIR_OUT ? "out" : "in"); usbdev_mock_ep_t *mock_ep = (usbdev_mock_ep_t *)ep; + if (mock_ep->ep.dir == USB_EP_DIR_OUT) { + memcpy(mock_ep->target_buf, mock_ep->buf, mock_ep->available); + } if (mock_ep->state == EP_STATE_DATA_AVAILABLE) { dev->ep_esr_cb(dev, mock_ep); mock_ep->state = EP_STATE_READY; } } -int _ready(usbdev_ep_t *ep, size_t len) +int _xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len) { DEBUG("[mock]: Readying EP %u, dir %s, len %u\n", ep->num, ep->dir == USB_EP_DIR_OUT ? "out" : "in", (unsigned)len); if (ep->num == 0) { usbdev_mock_t *usbdev_mock = _ep2dev(ep); usbdev_mock_ep_t *mock_ep = (usbdev_mock_ep_t *)ep; - - mock_ep->available = len; - mock_ep->ep.buf += len; + mock_ep->target_buf = buf; + if (ep->dir == USB_EP_DIR_IN) { + memcpy(mock_ep->buf + mock_ep->available, mock_ep->target_buf, len); + mock_ep->available = len; + } mock_ep->state = EP_STATE_DATA_AVAILABLE; usbdev_mock->ready_cb(usbdev_mock, (usbdev_mock_ep_t *)ep, len); - } return 0; } @@ -224,5 +227,5 @@ static const usbdev_driver_t testdriver = { .ep_get = _ep_get, .ep_set = _ep_set, .ep_esr = _ep_esr, - .ready = _ready, + .xmit = _xmit, }; diff --git a/tests/usbus/main.c b/tests/usbus/main.c index a2ba8b4f8f..3ca6bf32dc 100644 --- a/tests/usbus/main.c +++ b/tests/usbus/main.c @@ -146,7 +146,7 @@ static void _test_sequence(usbdev_mock_t *dev) case TESTPHASE_RESET: next_phase = TESTPHASE_REQ_DEV_INIT; DEBUG("[test]: Requesting device descriptor\n"); - _build_conf_req(dev->out[0].ep.buf, 8); /* initial config request */ + _build_conf_req(dev->out[0].buf, 8); /* initial config request */ dev->req_len = 8; dev->out[0].state = EP_STATE_DATA_AVAILABLE; dev->out[0].available = 8; @@ -157,7 +157,7 @@ static void _test_sequence(usbdev_mock_t *dev) DEBUG("[test]: validating device descriptor\n"); TEST_ASSERT_EQUAL_INT(dev->in[0].available, 8); _validate_device_desc_init( - (usb_descriptor_device_t *)dev->in[0].buf_start); + (usb_descriptor_device_t *)dev->in[0].buf); /* Reset device */ DEBUG("[test]: Signalling second USB reset condition\n"); dev->usbdev.cb(&dev->usbdev, USBDEV_EVENT_RESET); @@ -166,7 +166,7 @@ static void _test_sequence(usbdev_mock_t *dev) case TESTPHASE_RESET2: next_phase = TESTPHASE_SET_ADDRESS; DEBUG("[test]: Set USB address\n"); - _build_set_addr(dev->out[0].ep.buf); + _build_set_addr(dev->out[0].buf); dev->req_len = 0; dev->out[0].state = EP_STATE_DATA_AVAILABLE; dev->out[0].available = 8; @@ -175,7 +175,7 @@ static void _test_sequence(usbdev_mock_t *dev) case TESTPHASE_SET_ADDRESS: next_phase = TESTPHASE_REQ_DEV_FULL; DEBUG("[test]: Requesting full device descriptor\n"); - _build_conf_req(dev->out[0].ep.buf, + _build_conf_req(dev->out[0].buf, sizeof(usb_descriptor_device_t)); dev->req_len = sizeof(usb_descriptor_device_t); dev->out[0].state = EP_STATE_DATA_AVAILABLE; @@ -187,7 +187,7 @@ static void _test_sequence(usbdev_mock_t *dev) sizeof(usb_descriptor_device_t)); DEBUG("[test]: Validating full descriptor\n"); _validate_device_desc_init( - (usb_descriptor_device_t *)dev->in[0].buf_start); + (usb_descriptor_device_t *)dev->in[0].buf); next_phase = TESTPHASE_FINAL; dev->usbdev.cb(&dev->usbdev, USBDEV_EVENT_ESR); @@ -261,8 +261,6 @@ static void _handle_data(usbdev_mock_t *dev, usbdev_mock_ep_t *ep, size_t len) if (ep->available == dev->req_len) { DEBUG("[data]: Full data received from stack\n"); req_phase = TEST_REQ_PHASE_OUTACK; - /* Reset buffer ptr to the start */ - ep->ep.buf = ep->buf_start; } else { DEBUG("[data]: Expecting more data from stack: %u/%u\n", From 617027ab5cd83fac3af6197a4f99d7deb1692a34 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 19:44:17 +0200 Subject: [PATCH 04/10] nrf52/usb: Adapt to xmit API --- cpu/nrf52/include/nrfusb.h | 8 ---- cpu/nrf52/include/periph_cpu.h | 11 +++++ cpu/nrf52/periph/usbdev.c | 87 ++++++++++------------------------ 3 files changed, 35 insertions(+), 71 deletions(-) diff --git a/cpu/nrf52/include/nrfusb.h b/cpu/nrf52/include/nrfusb.h index d69967ff4b..07239fc021 100644 --- a/cpu/nrf52/include/nrfusb.h +++ b/cpu/nrf52/include/nrfusb.h @@ -36,11 +36,6 @@ extern "C" { */ #define NRF_USB_NUM_PERIPH 1 -/** - * USB endpoint buffer space - */ -#define NRF_USB_BUF_SPACE USBDEV_EP_BUF_SPACE - /** * Number of USB IN and OUT endpoints */ @@ -65,9 +60,6 @@ typedef struct { usbdev_ep_t ep_ins[NRF_USB_NUM_EP]; /**< IN type endpoints */ usbdev_ep_t ep_outs[ NRF_USB_NUM_EP]; /**< OUT type endpoints */ NRF_USBD_Type *device; /**< Ptr to the device registers */ - size_t used; /**< Number of bytes from the - buffer that are used */ - uint8_t buffer[NRF_USB_BUF_SPACE]; /**< Buffer space for endpoint data */ nrfusb_setup_state_t sstate; /**< Setup request state machine */ } nrfusb_t; diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h index 25283d6b18..7f3bef6051 100644 --- a/cpu/nrf52/include/periph_cpu.h +++ b/cpu/nrf52/include/periph_cpu.h @@ -263,6 +263,17 @@ void spi_twi_irq_register_spi(NRF_SPIM_Type *bus, */ void spi_twi_irq_register_i2c(NRF_TWIM_Type *bus, spi_twi_irq_cb_t cb, void *arg); + +/** + * @brief USBDEV buffers must be word aligned because of DMA restrictions + */ +#define USBDEV_CPU_DMA_ALIGNMENT (4) + +/** + * @brief USBDEV buffer instantiation requirement + */ +#define USBDEV_CPU_DMA_REQUIREMENTS __attribute__((aligned(USBDEV_CPU_DMA_ALIGNMENT))) + #ifdef __cplusplus } #endif diff --git a/cpu/nrf52/periph/usbdev.c b/cpu/nrf52/periph/usbdev.c index 26d8ef4ff8..c639e2f50f 100644 --- a/cpu/nrf52/periph/usbdev.c +++ b/cpu/nrf52/periph/usbdev.c @@ -27,6 +27,7 @@ #include #include +#include "architecture.h" #include "cpu.h" #include "nrfusb.h" #include "periph/usbdev.h" @@ -42,12 +43,12 @@ static nrfusb_t _usbdevs[NRF_USB_NUM_PERIPH]; static void _init(usbdev_t *usbdev); static int _get(usbdev_t *usbdev, usbopt_t opt, void *value, size_t max_len); static int _set(usbdev_t *usbdev, usbopt_t opt, const void *value, size_t value_len); -static usbdev_ep_t *_new_ep(usbdev_t *dev, usb_ep_type_t type, usb_ep_dir_t dir, size_t buf_len); +static usbdev_ep_t *_new_ep(usbdev_t *dev, usb_ep_type_t type, usb_ep_dir_t dir, size_t len); static void _esr(usbdev_t *usbdev); static void _ep_init(usbdev_ep_t *ep); static int _ep_get(usbdev_ep_t *ep, usbopt_ep_t opt, void *value, size_t max_len); static int _ep_set(usbdev_ep_t *ep, usbopt_ep_t opt, const void *value, size_t value_len); -static int _ep_ready(usbdev_ep_t *ep, size_t len); +static int _ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len); static void _ep_esr(usbdev_ep_t *ep); static const usbdev_driver_t _driver = { @@ -60,7 +61,7 @@ static const usbdev_driver_t _driver = { .ep_get = _ep_get, .ep_set = _ep_set, .ep_esr = _ep_esr, - .ready = _ep_ready, + .xmit = _ep_xmit, }; static inline usbdev_ep_t *_get_ep_in(nrfusb_t *usbdev, unsigned num) @@ -129,22 +130,10 @@ static void usb_detach(nrfusb_t *usbdev) usbdev->device->USBPULLUP = 0x00; } -static void _ep_set_address(usbdev_ep_t *ep) -{ - nrfusb_t *usbdev = (nrfusb_t *)ep->dev; - - if (ep->dir == USB_EP_DIR_OUT) { - usbdev->device->EPOUT[ep->num].PTR = (uint32_t)ep->buf; - } - else { - usbdev->device->EPIN[ep->num].PTR = (uint32_t)ep->buf; - } -} - static void _copy_setup(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t *)ep->dev; - usb_setup_t *setup = (usb_setup_t *)ep->buf; + nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + usb_setup_t *setup = (usb_setup_t*)(intptr_t)usbdev->device->EPOUT[0].PTR; setup->type = usbdev->device->BMREQUESTTYPE; setup->request = usbdev->device->BREQUEST; @@ -159,17 +148,6 @@ static void _copy_setup(usbdev_ep_t *ep) } } -static int _ep_set_size(usbdev_ep_t *ep) -{ - /* TODO: validate size */ - nrfusb_t *usbdev = (nrfusb_t *)ep->dev; - - if (ep->dir == USB_EP_DIR_OUT) { - usbdev->device->EPOUT[ep->num].MAXCNT = (uint32_t)ep->len; - } - return 1; -} - static void _ep_enable(usbdev_ep_t *ep) { DEBUG("Enabling endpoint %u dir %s\n", ep->num, ep->dir == USB_EP_DIR_OUT ? "OUT" : "IN"); @@ -287,7 +265,6 @@ static void _init(usbdev_t *dev) nrfusb_t *usbdev = (nrfusb_t *)dev; poweron(usbdev); - usbdev->used = 0; usbdev->sstate = NRFUSB_SETUP_READY; /* Enable a set of interrupts */ @@ -350,9 +327,9 @@ static int _set(usbdev_t *dev, usbopt_t opt, static usbdev_ep_t *_new_ep(usbdev_t *dev, usb_ep_type_t type, usb_ep_dir_t dir, - size_t buf_len) + size_t len) { - nrfusb_t *usbdev = (nrfusb_t *)dev; + nrfusb_t *usbdev = (nrfusb_t*)dev; /* The IP supports all types for all endpoints */ usbdev_ep_t *res = NULL; @@ -374,23 +351,9 @@ static usbdev_ep_t *_new_ep(usbdev_t *dev, if (res) { res->dev = dev; res->dir = dir; - DEBUG("nrfusb: Allocated new ep (%d %s)\n", - res->num, - res->dir == USB_EP_DIR_OUT ? "OUT" : "IN"); - if (usbdev->used + buf_len < NRF_USB_BUF_SPACE) { - res->buf = usbdev->buffer + usbdev->used; - res->len = buf_len; - if (_ep_set_size(res) < 0) { - return NULL; - } - usbdev->used += buf_len; - _ep_set_address(res); - res->type = type; - res->dev = dev; - } - else { - DEBUG("nrfusb: error allocating buffer space\n"); - } + res->type = type; + res->len = len; + DEBUG("nrfusb: Allocated new ep (%d %s)\n", res->num, res->dir == USB_EP_DIR_OUT ? "OUT" : "IN"); } return res; } @@ -429,10 +392,8 @@ static void _ep_disable_irq(usbdev_ep_t *ep) static void _ep_init(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + nrfusb_t *usbdev = (nrfusb_t*)ep->dev; - _ep_set_size(ep); - _ep_set_address(ep); if (ep->num == 0) { usbdev->device->EVENTS_EP0SETUP = 0; } @@ -493,13 +454,6 @@ static int _ep_set(usbdev_ep_t *ep, usbopt_ep_t opt, _ep_set_stall(ep, *(usbopt_enable_t *)value); res = sizeof(usbopt_enable_t); break; - case USBOPT_EP_READY: - assert(value_len == sizeof(usbopt_enable_t)); - if (*((usbopt_enable_t *)value)) { - _ep_ready(ep, 0); - res = sizeof(usbopt_enable_t); - } - break; default: DEBUG("Unhandled set call: 0x%x\n", opt); break; @@ -507,9 +461,11 @@ static int _ep_set(usbdev_ep_t *ep, usbopt_ep_t opt, return res; } -static int _ep0_ready(usbdev_ep_t *ep, size_t len) +static int _ep0_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len) { nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + /* Assert the alignment required for the buffers */ + assert(HAS_ALIGNMENT_OF(buf, USBDEV_CPU_DMA_ALIGNMENT)); if (ep->dir == USB_EP_DIR_IN) { if (len == 0 && usbdev->sstate == NRFUSB_SETUP_WRITE) { @@ -518,12 +474,14 @@ static int _ep0_ready(usbdev_ep_t *ep, size_t len) usbdev->sstate = NRFUSB_SETUP_ACKIN; } else { - usbdev->device->EPIN[0].PTR = (uint32_t)ep->buf; + usbdev->device->EPIN[0].PTR = (uint32_t)(intptr_t)buf; usbdev->device->EPIN[0].MAXCNT = (uint32_t)len; usbdev->device->TASKS_STARTEPIN[0] = 1; } } else { + usbdev->device->EPOUT[0].PTR = (uint32_t)(intptr_t)buf; + usbdev->device->EPOUT[0].MAXCNT = (uint32_t)len; /* USB_EP_DIR_OUT */ if (usbdev->sstate == NRFUSB_SETUP_READ) { usbdev->device->TASKS_EP0STATUS = 1; @@ -537,20 +495,23 @@ static int _ep0_ready(usbdev_ep_t *ep, size_t len) return len; } -static int _ep_ready(usbdev_ep_t *ep, size_t len) +static int _ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len) { nrfusb_t *usbdev = (nrfusb_t *)ep->dev; if (ep->num == 0) { /* Endpoint 0 requires special handling as per datasheet sec 6.35.9 */ - return _ep0_ready(ep, len); + return _ep0_xmit(ep, buf, len); } if (ep->dir == USB_EP_DIR_IN) { - usbdev->device->EPIN[ep->num].PTR = (uint32_t)ep->buf; + usbdev->device->EPIN[ep->num].PTR = (uint32_t)(intptr_t)buf; usbdev->device->EPIN[ep->num].MAXCNT = (uint32_t)len; _ep_dma_in(ep); } else { + /* Pre-Setup the EasyDMA settings */ + usbdev->device->EPOUT[ep->num].PTR = (uint32_t)(intptr_t)buf; + usbdev->device->EPOUT[ep->num].MAXCNT = (uint32_t)(intptr_t)len; /* Write nonzero value to EPOUT to indicate ready */ usbdev->device->SIZE.EPOUT[ep->num] = 1; } From c81df904ea5c56a3a4b2133ebd36edd57c2eef01 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 19:44:34 +0200 Subject: [PATCH 05/10] stm32/usbdev: Adapt to xmit API --- cpu/stm32/include/periph_cpu.h | 10 +++++ cpu/stm32/include/usbdev_stm32.h | 23 ++++------ cpu/stm32/periph/usbdev.c | 73 ++++++++++++++------------------ 3 files changed, 51 insertions(+), 55 deletions(-) diff --git a/cpu/stm32/include/periph_cpu.h b/cpu/stm32/include/periph_cpu.h index f84be15b77..c73e045d11 100644 --- a/cpu/stm32/include/periph_cpu.h +++ b/cpu/stm32/include/periph_cpu.h @@ -782,6 +782,16 @@ typedef struct { } i2c_timing_param_t; #endif +/** + * @brief USBDEV buffers must be word aligned because of DMA restrictions + */ +#define USBDEV_CPU_DMA_ALIGNMENT (4) + +/** + * @brief USBDEV buffer instantiation requirement + */ +#define USBDEV_CPU_DMA_REQUIREMENTS __attribute__((aligned(USBDEV_CPU_DMA_ALIGNMENT))) + /** * @brief USB OTG peripheral type. * diff --git a/cpu/stm32/include/usbdev_stm32.h b/cpu/stm32/include/usbdev_stm32.h index 6f60c3be34..337692f165 100644 --- a/cpu/stm32/include/usbdev_stm32.h +++ b/cpu/stm32/include/usbdev_stm32.h @@ -56,17 +56,6 @@ extern "C" { #error Unknown USB peripheral version #endif -/** - * @brief Buffer space available for endpoint TX/RX data - */ -#ifndef STM32_USB_OTG_BUF_SPACE -#define STM32_USB_OTG_BUF_SPACE USBDEV_EP_BUF_SPACE -#endif - -#if (STM32_USB_OTG_BUF_SPACE % 4) != 0 -#error "STM32_USB_OTG_BUF_SPACE needs to be a multiple of 4" -#endif - /** * @brief Number of endpoints available with the OTG FS peripheral * including the control endpoint @@ -121,17 +110,23 @@ extern "C" { #endif #endif +/** + * @brief stm32 USB OTG peripheral device out endpoint struct + */ +typedef struct { + usbdev_ep_t ep; /**< Inherited usbdev endpoint struct */ + uint8_t *out_buf; /**< Requested data output buffer */ +} stm32_usb_otg_fshs_out_ep_t; + /** * @brief stm32 USB OTG peripheral device context */ typedef struct { usbdev_t usbdev; /**< Inherited usbdev struct */ const stm32_usb_otg_fshs_config_t *config; /**< USB peripheral config */ - uint8_t buffer[STM32_USB_OTG_BUF_SPACE]; /**< Buffer space for endpoints */ - size_t occupied; /**< Buffer space occupied */ size_t fifo_pos; /**< FIFO space occupied */ usbdev_ep_t *in; /**< In endpoints */ - usbdev_ep_t *out; /**< Out endpoints */ + stm32_usb_otg_fshs_out_ep_t *out; /**< Out endpoints */ bool suspend; /**< Suspend status */ } stm32_usb_otg_fshs_t; diff --git a/cpu/stm32/periph/usbdev.c b/cpu/stm32/periph/usbdev.c index dae27c1902..740413ae4b 100644 --- a/cpu/stm32/periph/usbdev.c +++ b/cpu/stm32/periph/usbdev.c @@ -23,6 +23,7 @@ #include #include +#include "architecture.h" #include "bitarithm.h" #include "ztimer.h" #include "cpu.h" @@ -101,7 +102,7 @@ /* List of instantiated USB peripherals */ static stm32_usb_otg_fshs_t _usbdevs[USBDEV_NUMOF] = { 0 }; -static usbdev_ep_t _out[_TOTAL_NUM_ENDPOINTS]; +static stm32_usb_otg_fshs_out_ep_t _out[_TOTAL_NUM_ENDPOINTS]; static usbdev_ep_t _in[_TOTAL_NUM_ENDPOINTS]; /* Forward declaration for the usb device driver */ @@ -418,7 +419,7 @@ static usbdev_ep_t *_get_ep(stm32_usb_otg_fshs_t *usbdev, unsigned num, if (num >= STM32_USB_OTG_FS_NUM_EP) { return NULL; } - return dir == USB_EP_DIR_IN ? &usbdev->in[num] : &usbdev->out[num]; + return dir == USB_EP_DIR_IN ? &usbdev->in[num] : &usbdev->out[num].ep; } #if defined(DEVELHELP) && !defined(NDEBUG) @@ -479,18 +480,8 @@ static void _configure_fifo(stm32_usb_otg_fshs_t *usbdev) usbdev->fifo_pos = (rx_size + STM32_USB_OTG_FIFO_MIN_WORD_SIZE); } -size_t _round_up_to_multiple_of_four(size_t unaligned) -{ - size_t misalignment = unaligned & 0x03; - if (misalignment) { - unaligned += 4 - misalignment; - } - - return unaligned; -} - static usbdev_ep_t *_usbdev_new_ep(usbdev_t *dev, usb_ep_type_t type, - usb_ep_dir_t dir, size_t buf_len) + usb_ep_dir_t dir, size_t len) { stm32_usb_otg_fshs_t *usbdev = (stm32_usb_otg_fshs_t *)dev; usbdev_ep_t *ep = NULL; @@ -500,7 +491,7 @@ static usbdev_ep_t *_usbdev_new_ep(usbdev_t *dev, usb_ep_type_t type, ep = &usbdev->in[0]; } else { - ep = &usbdev->out[0]; + ep = &usbdev->out[0].ep; } ep->num = 0; } @@ -516,17 +507,12 @@ static usbdev_ep_t *_usbdev_new_ep(usbdev_t *dev, usb_ep_type_t type, } if (ep && ep->type == USB_EP_TYPE_NONE) { - if (usbdev->occupied + buf_len < STM32_USB_OTG_BUF_SPACE) { - ep->buf = usbdev->buffer + usbdev->occupied; - ep->dir = dir; - ep->type = type; - ep->dev = dev; - ep->len = buf_len; - usbdev->occupied += buf_len; - usbdev->occupied = _round_up_to_multiple_of_four(usbdev->occupied); - if (ep->dir == USB_EP_DIR_IN && ep->num != 0) { - _configure_tx_fifo(usbdev, ep->num, ep->len); - } + ep->dir = dir; + ep->type = type; + ep->dev = dev; + ep->len = len; + if (ep->dir == USB_EP_DIR_IN && ep->num != 0) { + _configure_tx_fifo(usbdev, ep->num, ep->len); } } return ep; @@ -922,10 +908,12 @@ static int _usbdev_ep_set(usbdev_ep_t *ep, usbopt_ep_t opt, return res; } -static int _usbdev_ep_ready(usbdev_ep_t *ep, size_t len) +static int _usbdev_ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len) { stm32_usb_otg_fshs_t *usbdev = (stm32_usb_otg_fshs_t *)ep->dev; const stm32_usb_otg_fshs_config_t *conf = usbdev->config; + /* Assert the alignment required for the buffers */ + assert(HAS_ALIGNMENT_OF(buf, USBDEV_CPU_DMA_ALIGNMENT)); if (ep->dir == USB_EP_DIR_IN) { /* Abort when the endpoint is not active, prevents hangs, @@ -935,7 +923,7 @@ static int _usbdev_ep_ready(usbdev_ep_t *ep, size_t len) } if (_uses_dma(conf)) { - _in_regs(conf, ep->num)->DIEPDMA = (uint32_t)ep->buf; + _in_regs(conf, ep->num)->DIEPDMA = (uint32_t)(intptr_t)buf; } /* The order here is crucial (AFAIK), it is required to first set the @@ -966,9 +954,10 @@ static int _usbdev_ep_ready(usbdev_ep_t *ep, size_t len) if (len > 0 && !_uses_dma(conf)) { /* The FIFO requires 32 bit word reads/writes */ size_t words = (len + 3) / 4; - /* buffer is gets aligned in _usbdev_new_ep(). Use intermediate + + /* buffer alignment is asserted above. Use intermediate * cast to uintptr_t to silence -Wcast-align*/ - uint32_t *ep_buf = (uint32_t *)(uintptr_t)ep->buf; + uint32_t *ep_buf = (uint32_t *)(uintptr_t)buf; __O uint32_t *fifo = _tx_fifo(conf, ep->num); for (size_t i = 0; i < words; i++) { fifo[i] = ep_buf[i]; @@ -983,7 +972,10 @@ static int _usbdev_ep_ready(usbdev_ep_t *ep, size_t len) } if (_uses_dma(conf)) { - _out_regs(conf, ep->num)->DOEPDMA = (uint32_t)ep->buf; + _out_regs(conf, ep->num)->DOEPDMA = (uint32_t)(intptr_t)buf; + } + else { + container_of(ep, stm32_usb_otg_fshs_out_ep_t, ep)->out_buf = buf; } /* Configure to receive one packet with ep->len as max length */ @@ -1012,9 +1004,9 @@ static void _copy_rxfifo(stm32_usb_otg_fshs_t *usbdev, uint8_t *buf, size_t len) } } -static void _read_packet(usbdev_ep_t *ep) +static void _read_packet(stm32_usb_otg_fshs_out_ep_t *st_ep) { - stm32_usb_otg_fshs_t *usbdev = (stm32_usb_otg_fshs_t *)ep->dev; + stm32_usb_otg_fshs_t *usbdev = (stm32_usb_otg_fshs_t *)st_ep->ep.dev; const stm32_usb_otg_fshs_config_t *conf = usbdev->config; /* Pop status from the receive fifo status register */ uint32_t status = _global_regs(conf)->GRXSTSP; @@ -1029,13 +1021,12 @@ static void _read_packet(usbdev_ep_t *ep) * complete status*/ if (pkt_status == STM32_PKTSTS_DATA_UPDT || pkt_status == STM32_PKTSTS_SETUP_UPDT) { - _copy_rxfifo(usbdev, ep->buf, len); + _copy_rxfifo(usbdev, st_ep->out_buf, len); #ifdef STM32_USB_OTG_CID_2x /* CID 2x doesn't signal SETUP_COMP on non-zero length packets, signal * the TR_COMPLETE event immediately */ - if (ep->num == 0 && len) { - usbdev->usbdev.epcb(&usbdev->out[ep->num], - USBDEV_EVENT_TR_COMPLETE); + if (st_ep->ep.num == 0 && len) { + usbdev->usbdev.epcb(&st_ep->ep, USBDEV_EVENT_TR_COMPLETE); } #endif /* STM32_USB_OTG_CID_2x */ } @@ -1043,7 +1034,7 @@ static void _read_packet(usbdev_ep_t *ep) * status is skipped */ else if (pkt_status == STM32_PKTSTS_XFER_COMP || pkt_status == STM32_PKTSTS_SETUP_COMP) { - usbdev->usbdev.epcb(&usbdev->out[ep->num], USBDEV_EVENT_TR_COMPLETE); + usbdev->usbdev.epcb(&st_ep->ep, USBDEV_EVENT_TR_COMPLETE); } } @@ -1078,7 +1069,7 @@ static void _usbdev_ep_esr(usbdev_ep_t *ep) if ((_global_regs(conf)->GINTSTS & USB_OTG_GINTSTS_RXFLVL) && (_global_regs(conf)->GRXSTSR & USB_OTG_GRXSTSP_EPNUM_Msk) == ep->num && !_uses_dma(conf)) { - _read_packet(ep); + _read_packet(container_of(ep, stm32_usb_otg_fshs_out_ep_t, ep)); } /* Transfer complete seems only reliable when used with DMA */ else if (_out_regs(conf, ep->num)->DOEPINT & USB_OTG_DOEPINT_XFRC) { @@ -1102,7 +1093,7 @@ static void _isr_ep(stm32_usb_otg_fshs_t *usbdev) if (active_ep) { unsigned epnum = bitarithm_lsb(active_ep); if (epnum >= STM32_USB_OTG_REG_EP_OUT_OFFSET) { - usbdev->usbdev.epcb(&usbdev->out[epnum - STM32_USB_OTG_REG_EP_OUT_OFFSET], + usbdev->usbdev.epcb(&usbdev->out[epnum - STM32_USB_OTG_REG_EP_OUT_OFFSET].ep, USBDEV_EVENT_ESR); } else { @@ -1121,7 +1112,7 @@ void _isr_common(stm32_usb_otg_fshs_t *usbdev) if (status & USB_OTG_GINTSTS_RXFLVL) { unsigned epnum = _global_regs(conf)->GRXSTSR & USB_OTG_GRXSTSP_EPNUM_Msk; - usbdev->usbdev.epcb(&usbdev->out[epnum], USBDEV_EVENT_ESR); + usbdev->usbdev.epcb(&usbdev->out[epnum].ep, USBDEV_EVENT_ESR); } else if (_global_regs(conf)->GINTSTS & (USB_OTG_GINTSTS_OEPINT | USB_OTG_GINTSTS_IEPINT)) { @@ -1166,5 +1157,5 @@ const usbdev_driver_t driver = { .ep_get = _usbdev_ep_get, .ep_set = _usbdev_ep_set, .ep_esr = _usbdev_ep_esr, - .ready = _usbdev_ep_ready, + .xmit = _usbdev_ep_xmit, }; From a6b6f43ce24fc829d24a4f8cedb38cb083d35f89 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 19:44:54 +0200 Subject: [PATCH 06/10] sam0_common/usbdev: Adapt to xmit API --- cpu/sam0_common/include/periph_cpu_common.h | 10 ++++ cpu/sam0_common/include/sam_usb.h | 10 ---- cpu/sam0_common/periph/usbdev.c | 60 +++++---------------- 3 files changed, 22 insertions(+), 58 deletions(-) diff --git a/cpu/sam0_common/include/periph_cpu_common.h b/cpu/sam0_common/include/periph_cpu_common.h index eb10d8c63b..6138e18002 100644 --- a/cpu/sam0_common/include/periph_cpu_common.h +++ b/cpu/sam0_common/include/periph_cpu_common.h @@ -813,6 +813,16 @@ typedef struct { } sam0_common_gmac_config_t; #endif +/** + * @brief USBDEV buffers must be word aligned because of DMA restrictions + */ +#define USBDEV_CPU_DMA_ALIGNMENT (4) + +/** + * @brief USBDEV buffer instantiation requirement + */ +#define USBDEV_CPU_DMA_REQUIREMENTS __attribute__((aligned(USBDEV_CPU_DMA_ALIGNMENT))) + /** * @brief USB peripheral parameters */ diff --git a/cpu/sam0_common/include/sam_usb.h b/cpu/sam0_common/include/sam_usb.h index 9b6800b349..f11d9f9075 100644 --- a/cpu/sam0_common/include/sam_usb.h +++ b/cpu/sam0_common/include/sam_usb.h @@ -31,11 +31,6 @@ extern "C" { #endif -/** - * USB endpoint buffer space - */ -#define SAM_USB_BUF_SPACE USBDEV_EP_BUF_SPACE - /** * Number of USB IN and OUT endpoints */ @@ -49,11 +44,6 @@ typedef struct { const sam0_common_usb_config_t *config; /**< USB peripheral config */ UsbDeviceDescBank banks[2 * SAM_USB_NUM_EP]; /**< Device descriptor banks */ usbdev_ep_t endpoints[2 * SAM_USB_NUM_EP]; /**< Endpoints */ - size_t used; /**< Number of bytes from the - buffer that are used */ - __attribute__ ((aligned(4))) - uint8_t buffer[SAM_USB_BUF_SPACE]; /**< Buffer space, must be - 32-bit aligned */ bool suspended; /**< Suspend active */ } sam0_common_usb_t; diff --git a/cpu/sam0_common/periph/usbdev.c b/cpu/sam0_common/periph/usbdev.c index f392640e4d..4a54511846 100644 --- a/cpu/sam0_common/periph/usbdev.c +++ b/cpu/sam0_common/periph/usbdev.c @@ -22,6 +22,7 @@ #include #include #include +#include "architecture.h" #include "cpu.h" #include "cpu_conf.h" #include "periph/gpio.h" @@ -46,12 +47,11 @@ static sam0_common_usb_t _usbdevs[USB_INST_NUM]; const usbdev_driver_t driver; static void _usbdev_ep_init(usbdev_ep_t *ep); -static int _usbdev_ep_ready(usbdev_ep_t *ep, size_t len); +static int _usbdev_ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len); static usbdev_ep_t *_usbdev_new_ep(usbdev_t *dev, usb_ep_type_t type, - usb_ep_dir_t dir, size_t buf_len); + usb_ep_dir_t dir, size_t len); static int _bank_set_size(usbdev_ep_t *ep); -static int _ep_unready(usbdev_ep_t *ep); static inline unsigned _ep_num(unsigned num, usb_ep_dir_t dir) { @@ -144,13 +144,6 @@ static void _disable_ep_irq_in(UsbDeviceEndpoint *ep_reg) USB_DEVICE_EPINTENCLR_STALL1; } -static void _bank_set_address(usbdev_ep_t *ep) -{ - UsbDeviceDescBank *bank = _bank_from_ep(ep); - - bank->ADDR.reg = (uint32_t)ep->buf; -} - static int _bank_set_size(usbdev_ep_t *ep) { UsbDeviceDescBank *bank = _bank_from_ep(ep); @@ -255,7 +248,7 @@ static inline void _poweron(sam0_common_usb_t *dev) } static usbdev_ep_t *_usbdev_new_ep(usbdev_t *dev, usb_ep_type_t type, - usb_ep_dir_t dir, size_t buf_len) + usb_ep_dir_t dir, size_t size) { sam0_common_usb_t *usbdev = (sam0_common_usb_t *)dev; /* The IP supports all types for all endpoints */ @@ -279,17 +272,9 @@ static usbdev_ep_t *_usbdev_new_ep(usbdev_t *dev, usb_ep_type_t type, if (res) { res->dev = dev; res->dir = dir; - if (usbdev->used + buf_len < SAM_USB_BUF_SPACE) { - res->buf = usbdev->buffer + usbdev->used; - res->len = buf_len; - if (_bank_set_size(res) < 0) { - return NULL; - } - usbdev->used += buf_len; - _bank_set_address(res); - res->type = type; - res->dev = dev; - } + res->type = type; + res->len = size; + _bank_set_size(res); } return res; } @@ -334,7 +319,6 @@ static void _usbdev_init(usbdev_t *dev) /* Only one usb device on this board */ sam0_common_usb_t *usbdev = (sam0_common_usb_t *)dev; - usbdev->used = 0; /* Set GPIO */ gpio_init(usbdev->config->dp, GPIO_IN); gpio_init(usbdev->config->dm, GPIO_IN); @@ -688,16 +672,6 @@ static int _usbdev_ep_set(usbdev_ep_t *ep, usbopt_ep_t opt, _ep_set_stall(ep, *(usbopt_enable_t *)value); res = sizeof(usbopt_enable_t); break; - case USBOPT_EP_READY: - assert(value_len == sizeof(usbopt_enable_t)); - if (*((usbopt_enable_t *)value)) { - _ep_unready(ep); - } - else { - _usbdev_ep_ready(ep, 0); - } - res = sizeof(usbopt_enable_t); - break; default: DEBUG("sam_usb: Unhandled set call: 0x%x\n", opt); break; @@ -705,23 +679,13 @@ static int _usbdev_ep_set(usbdev_ep_t *ep, usbopt_ep_t opt, return res; } -static int _ep_unready(usbdev_ep_t *ep) -{ - UsbDeviceEndpoint *ep_reg = _ep_reg_from_ep(ep); - - if (ep->dir == USB_EP_DIR_IN) { - ep_reg->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY; - } - else { - ep_reg->EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY; - } - return 0; -} - -static int _usbdev_ep_ready(usbdev_ep_t *ep, size_t len) +static int _usbdev_ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len) { UsbDeviceEndpoint *ep_reg = _ep_reg_from_ep(ep); + /* Assert the alignment required for the buffers */ + assert(HAS_ALIGNMENT_OF(buf, USBDEV_CPU_DMA_ALIGNMENT)); + _bank_from_ep(ep)->ADDR.reg = (uint32_t)(intptr_t)buf; if (ep->dir == USB_EP_DIR_IN) { _disable_ep_stall_in(ep_reg); _bank_from_ep(ep)->PCKSIZE.bit.BYTE_COUNT = len; @@ -803,5 +767,5 @@ const usbdev_driver_t driver = { .ep_get = _usbdev_ep_get, .ep_set = _usbdev_ep_set, .ep_esr = _usbdev_ep_esr, - .ready = _usbdev_ep_ready, + .xmit = _usbdev_ep_xmit, }; From 7d9a177f25f7eb244dbd8663699e37b0f4eba3b3 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 19:45:53 +0200 Subject: [PATCH 07/10] USBUS: Adapt to xmit API Converts the control endpoint to xmit API --- sys/include/usb/usbus/control.h | 14 ++++++++++++-- sys/usb/usbus/usbus.c | 3 ++- sys/usb/usbus/usbus_control.c | 19 +++++++++---------- sys/usb/usbus/usbus_control_slicer.c | 6 +++--- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/sys/include/usb/usbus/control.h b/sys/include/usb/usbus/control.h index 068e85766f..69e8028111 100644 --- a/sys/include/usb/usbus/control.h +++ b/sys/include/usb/usbus/control.h @@ -69,14 +69,24 @@ typedef struct { size_t received_len; /** - * @brief EP0 OUT endpoint + * @brief EP0 OUT endpoint reference */ usbdev_ep_t *out; /** - * @brief EP0 IN endpoint + * @brief EP0 IN endpoint reference */ usbdev_ep_t *in; + + /** + * @brief Host to device control request buffer + */ + usbdev_ep_buf_t out_buf[CONFIG_USBUS_EP0_SIZE]; + + /** + * @brief Device to host control request buffer + */ + usbdev_ep_buf_t in_buf[CONFIG_USBUS_EP0_SIZE]; } usbus_control_handler_t; /** diff --git a/sys/usb/usbus/usbus.c b/sys/usb/usbus/usbus.c index 94f344cbdc..a58453aab2 100644 --- a/sys/usb/usbus/usbus.c +++ b/sys/usb/usbus/usbus.c @@ -166,7 +166,7 @@ usbus_endpoint_t *usbus_add_endpoint(usbus_t *usbus, usbus_interface_t *iface, if (usbdev_ep) { ep = dir == USB_EP_DIR_IN ? &usbus->ep_in[usbdev_ep->num] : &usbus->ep_out[usbdev_ep->num]; - ep->maxpacketsize = usbdev_ep->len; + ep->maxpacketsize = len; ep->ep = usbdev_ep; if (iface) { ep->next = iface->ep; @@ -325,6 +325,7 @@ static void _event_cb(usbdev_t *usbdev, usbdev_event_t event) sizeof(uint8_t)); flag = USBUS_HANDLER_FLAG_RESET; msg = USBUS_EVENT_USB_RESET; + DEBUG("usbus: USB reset detected\n"); break; case USBDEV_EVENT_SUSPEND: DEBUG("usbus: USB suspend detected\n"); diff --git a/sys/usb/usbus/usbus_control.c b/sys/usb/usbus/usbus_control.c index de1e1a1a76..e083fa919e 100644 --- a/sys/usb/usbus/usbus_control.c +++ b/sys/usb/usbus/usbus_control.c @@ -286,11 +286,11 @@ static void _recv_setup(usbus_t *usbus, usbus_control_handler_t *handler) /* Signal ready for new data in case there is more */ if (handler->received_len < pkt->length) { handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_OUTDATA; - usbdev_ep_ready(handler->out, 1); + usbdev_ep_xmit(handler->out, handler->out_buf, CONFIG_USBUS_EP0_SIZE); } else { handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_INACK; - usbdev_ep_ready(handler->in, 0); + usbdev_ep_xmit(handler->in, handler->in_buf, 0); } } @@ -307,7 +307,7 @@ static void _usbus_config_ep0(usbus_control_handler_t *ep0_handler) sizeof(usbopt_enable_t)); usbdev_ep_set(ep0_handler->out, USBOPT_EP_ENABLE, &enable, sizeof(usbopt_enable_t)); - usbdev_ep_ready(ep0_handler->out, 0); + usbdev_ep_xmit(ep0_handler->out, ep0_handler->out_buf, CONFIG_USBUS_EP0_SIZE); } uint8_t *usbus_control_get_out_data(usbus_t *usbus, size_t *len) @@ -317,10 +317,9 @@ uint8_t *usbus_control_get_out_data(usbus_t *usbus, size_t *len) assert(len); assert(handler->control_request_state == USBUS_CONTROL_REQUEST_STATE_OUTDATA); - usbdev_ep_t *ep_out = handler->out; - usbdev_ep_get(ep_out, USBOPT_EP_AVAILABLE, + usbdev_ep_get(handler->out, USBOPT_EP_AVAILABLE, len, sizeof(size_t)); - return ep_out->buf; + return handler->out_buf; } static void _init(usbus_t *usbus, usbus_handler_t *handler) @@ -351,14 +350,14 @@ static int _handle_tr_complete(usbus_t *usbus, } ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY; /* Ready for new control request */ - usbdev_ep_ready(ep0_handler->out, 0); + usbdev_ep_xmit(ep0_handler->out, ep0_handler->out_buf, CONFIG_USBUS_EP0_SIZE); } break; case USBUS_CONTROL_REQUEST_STATE_OUTACK: if (ep->dir == USB_EP_DIR_OUT) { ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY; /* Ready for new control request */ - usbdev_ep_ready(ep0_handler->out, 0); + usbdev_ep_xmit(ep0_handler->out, ep0_handler->out_buf, CONFIG_USBUS_EP0_SIZE); } break; case USBUS_CONTROL_REQUEST_STATE_INDATA: @@ -369,7 +368,7 @@ static int _handle_tr_complete(usbus_t *usbus, } else { /* Ready out ZLP */ - usbdev_ep_ready(ep0_handler->out, 0); + usbdev_ep_xmit(ep0_handler->out, ep0_handler->out_buf, CONFIG_USBUS_EP0_SIZE); ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_OUTACK; } } @@ -389,7 +388,7 @@ static int _handle_tr_complete(usbus_t *usbus, case USBUS_CONTROL_REQUEST_STATE_READY: if (ep->dir == USB_EP_DIR_OUT) { memset(&ep0_handler->slicer, 0, sizeof(usbus_control_slicer_t)); - memcpy(&ep0_handler->setup, ep0_handler->out->buf, + memcpy(&ep0_handler->setup, ep0_handler->out_buf, sizeof(usb_setup_t)); ep0_handler->received_len = 0; ep0_handler->slicer.reqlen = ep0_handler->setup.length; diff --git a/sys/usb/usbus/usbus_control_slicer.c b/sys/usb/usbus/usbus_control_slicer.c index 567ee511aa..865c1972c1 100644 --- a/sys/usb/usbus/usbus_control_slicer.c +++ b/sys/usb/usbus/usbus_control_slicer.c @@ -69,7 +69,7 @@ size_t usbus_control_slicer_put_bytes(usbus_t *usbus, const uint8_t *buf, size_t start_offset = bldr->cur - bldr->start + byte_offset; bldr->cur += len; bldr->len += byte_len; - memcpy(ep0->in->buf + start_offset, buf + byte_offset, byte_len); + memcpy(ep0->in_buf + start_offset, buf + byte_offset, byte_len); return byte_len; } @@ -81,7 +81,7 @@ size_t usbus_control_slicer_put_char(usbus_t *usbus, char c) /* Only copy the char if it is within the window */ if ((bldr->start <= bldr->cur) && (bldr->cur < end)) { - uint8_t *pos = ep0->in->buf + bldr->cur - bldr->start; + uint8_t *pos = ep0->in_buf + bldr->cur - bldr->start; *pos = c; bldr->cur++; bldr->len++; @@ -99,5 +99,5 @@ void usbus_control_slicer_ready(usbus_t *usbus) len = len < bldr->reqlen - bldr->start ? len : bldr->reqlen - bldr->start; bldr->transferred += len; - usbdev_ep_ready(ep0->in, len); + usbdev_ep_xmit(ep0->in, ep0->in_buf, len); } From 1a0bc3d8bc9de7c1b6d41c3dde9eefd711c34dd4 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 19:46:41 +0200 Subject: [PATCH 08/10] USBUS/cdc_acm: Adapt to xmit API --- sys/include/usb/usbus/cdc/acm.h | 10 ++++++++++ sys/usb/usbus/cdc/acm/cdc_acm.c | 11 ++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/sys/include/usb/usbus/cdc/acm.h b/sys/include/usb/usbus/cdc/acm.h index 6eba372af3..ca8901228b 100644 --- a/sys/include/usb/usbus/cdc/acm.h +++ b/sys/include/usb/usbus/cdc/acm.h @@ -142,6 +142,16 @@ struct usbus_cdcacm_device { usbus_cdcacm_line_state_t state; /**< Current line state */ event_t flush; /**< device2host forced flush event */ usb_req_cdcacm_coding_t coding; /**< Current coding configuration */ + + /** + * @brief Host to device data buffer + */ + usbdev_ep_buf_t out_buf[CONFIG_USBUS_CDC_ACM_BULK_EP_SIZE]; + + /** + * @brief Device to host data buffer + */ + usbdev_ep_buf_t in_buf[CONFIG_USBUS_CDC_ACM_STDIO_BUF_SIZE]; }; /** diff --git a/sys/usb/usbus/cdc/acm/cdc_acm.c b/sys/usb/usbus/cdc/acm/cdc_acm.c index 2badc70580..6e542bc239 100644 --- a/sys/usb/usbus/cdc/acm/cdc_acm.c +++ b/sys/usb/usbus/cdc/acm/cdc_acm.c @@ -303,7 +303,8 @@ static int _control_handler(usbus_t *usbus, usbus_handler_t *handler, usbus_endpoint_t *data_out = usbus_interface_find_endpoint( &cdcacm->iface_data, USB_EP_TYPE_BULK, USB_EP_DIR_OUT); assert(data_out); - usbdev_ep_ready(data_out->ep, 0); + usbdev_ep_xmit(data_out->ep, cdcacm->out_buf, + CONFIG_USBUS_CDC_ACM_BULK_EP_SIZE); usbus_cdc_acm_flush(cdcacm); } else { @@ -329,13 +330,13 @@ static void _handle_in(usbus_cdcacm_device_t *cdcacm, unsigned old = irq_disable(); while (!tsrb_empty(&cdcacm->tsrb)) { int c = tsrb_get_one(&cdcacm->tsrb); - ep->buf[cdcacm->occupied++] = (uint8_t)c; + cdcacm->in_buf[cdcacm->occupied++] = (uint8_t)c; if (cdcacm->occupied >= CONFIG_USBUS_CDC_ACM_BULK_EP_SIZE) { break; } } irq_restore(old); - usbdev_ep_ready(ep, cdcacm->occupied); + usbdev_ep_xmit(ep, cdcacm->in_buf, cdcacm->occupied); } static void _transfer_handler(usbus_t *usbus, usbus_handler_t *handler, @@ -349,9 +350,9 @@ static void _transfer_handler(usbus_t *usbus, usbus_handler_t *handler, /* Retrieve incoming data */ usbdev_ep_get(ep, USBOPT_EP_AVAILABLE, &len, sizeof(size_t)); if (len > 0) { - cdcacm->cb(cdcacm, ep->buf, len); + cdcacm->cb(cdcacm, cdcacm->out_buf, len); } - usbdev_ep_ready(ep, 0); + usbdev_ep_xmit(ep, cdcacm->out_buf, CONFIG_USBUS_CDC_ACM_BULK_EP_SIZE); } if ((ep->dir == USB_EP_DIR_IN) && (ep->type == USB_EP_TYPE_BULK)) { cdcacm->occupied = 0; From 5455c40c7aeedd3c2f92177cda5b3ee1206679ac Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 19:47:09 +0200 Subject: [PATCH 09/10] USBUS/cdc_ecm: Adapt to xmit API --- sys/include/usb/usbus/cdc/ecm.h | 24 ++++++++++--- sys/usb/usbus/cdc/ecm/cdc_ecm.c | 49 +++++++++----------------- sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c | 4 +-- 3 files changed, 38 insertions(+), 39 deletions(-) diff --git a/sys/include/usb/usbus/cdc/ecm.h b/sys/include/usb/usbus/cdc/ecm.h index 6f13514126..254d402782 100644 --- a/sys/include/usb/usbus/cdc/ecm.h +++ b/sys/include/usb/usbus/cdc/ecm.h @@ -106,12 +106,26 @@ typedef struct usbus_cdcecm_device { char mac_host[13]; /**< host side's MAC address as string */ usbus_string_t mac_str; /**< String context for the host side mac address */ usbus_t *usbus; /**< Ptr to the USBUS context */ - mutex_t out_lock; /**< mutex used for locking netif/USBUS send */ - size_t tx_len; /**< Length of the current tx frame */ - uint8_t in_buf[ETHERNET_FRAME_LEN]; /**< Buffer for the received frames */ + mutex_t out_lock; /**< mutex used for locking netif/USBUS send */ + size_t tx_len; /**< Length of the current tx frame */ size_t len; /**< Length of the current rx frame */ - usbus_cdcecm_notif_t notif; /**< Startup message notification tracker */ - unsigned active_iface; /**< Current active data interface */ + usbus_cdcecm_notif_t notif; /**< Startup message notification tracker */ + unsigned active_iface; /**< Current active data interface */ + + /** + * @brief Buffer for received frames + */ + usbdev_ep_buf_t data_out[ETHERNET_FRAME_LEN]; + + /** + * @brief Host in device out data buffer + */ + usbdev_ep_buf_t data_in[USBUS_CDCECM_EP_DATA_SIZE]; + + /** + * @brief Host out device in control buffer + */ + usbdev_ep_buf_t control_in[USBUS_CDCECM_EP_CTRL_SIZE]; } usbus_cdcecm_device_t; /** diff --git a/sys/usb/usbus/cdc/ecm/cdc_ecm.c b/sys/usb/usbus/cdc/ecm/cdc_ecm.c index 376ce45087..d9504ba27a 100644 --- a/sys/usb/usbus/cdc/ecm/cdc_ecm.c +++ b/sys/usb/usbus/cdc/ecm/cdc_ecm.c @@ -115,7 +115,7 @@ static void _notify_link_speed(usbus_cdcecm_device_t *cdcecm) { DEBUG("CDC ECM: sending link speed indication\n"); usb_desc_cdcecm_speed_t *notification = - (usb_desc_cdcecm_speed_t *)cdcecm->ep_ctrl->ep->buf; + (usb_desc_cdcecm_speed_t *)cdcecm->control_in; notification->setup.type = USB_SETUP_REQUEST_DEVICE2HOST | USB_SETUP_REQUEST_TYPE_CLASS | USB_SETUP_REQUEST_RECIPIENT_INTERFACE; @@ -126,7 +126,7 @@ static void _notify_link_speed(usbus_cdcecm_device_t *cdcecm) notification->down = CONFIG_USBUS_CDC_ECM_CONFIG_SPEED_DOWNSTREAM; notification->up = CONFIG_USBUS_CDC_ECM_CONFIG_SPEED_UPSTREAM; - usbdev_ep_ready(cdcecm->ep_ctrl->ep, + usbdev_ep_xmit(cdcecm->ep_ctrl->ep, cdcecm->control_in, sizeof(usb_desc_cdcecm_speed_t)); cdcecm->notif = USBUS_CDCECM_NOTIF_SPEED; } @@ -134,7 +134,7 @@ static void _notify_link_speed(usbus_cdcecm_device_t *cdcecm) static void _notify_link_up(usbus_cdcecm_device_t *cdcecm) { DEBUG("CDC ECM: sending link up indication\n"); - usb_setup_t *notification = (usb_setup_t *)cdcecm->ep_ctrl->ep->buf; + usb_setup_t *notification = (usb_setup_t *)cdcecm->control_in; notification->type = USB_SETUP_REQUEST_DEVICE2HOST | USB_SETUP_REQUEST_TYPE_CLASS | USB_SETUP_REQUEST_RECIPIENT_INTERFACE; @@ -142,7 +142,7 @@ static void _notify_link_up(usbus_cdcecm_device_t *cdcecm) notification->value = 1; notification->index = cdcecm->iface_ctrl.idx; notification->length = 0; - usbdev_ep_ready(cdcecm->ep_ctrl->ep, sizeof(usb_setup_t)); + usbdev_ep_xmit(cdcecm->ep_ctrl->ep, cdcecm->control_in, sizeof(usb_setup_t)); cdcecm->notif = USBUS_CDCECM_NOTIF_LINK_UP; } @@ -251,7 +251,8 @@ static int _control_handler(usbus_t *usbus, usbus_handler_t *handler, setup->value); cdcecm->active_iface = (uint8_t)setup->value; if (cdcecm->active_iface == 1) { - usbdev_ep_ready(cdcecm->ep_out->ep, 0); + usbdev_ep_xmit(cdcecm->ep_out->ep, cdcecm->data_out, + USBUS_CDCECM_EP_DATA_SIZE); _notify_link_up(cdcecm); } break; @@ -290,36 +291,15 @@ static void _handle_tx_xmit(event_t *ev) mutex_unlock(&cdcecm->out_lock); } /* Data prepared by netdev_send, signal ready to usbus */ - usbdev_ep_ready(cdcecm->ep_in->ep, cdcecm->tx_len); -} - -static void _handle_rx_flush(usbus_cdcecm_device_t *cdcecm) -{ - cdcecm->len = 0; + usbdev_ep_xmit(cdcecm->ep_in->ep, cdcecm->data_in, cdcecm->tx_len); } static void _handle_rx_flush_ev(event_t *ev) { usbus_cdcecm_device_t *cdcecm = container_of(ev, usbus_cdcecm_device_t, rx_flush); - - usbdev_ep_ready(cdcecm->ep_out->ep, 0); - _handle_rx_flush(cdcecm); -} - -static void _store_frame_chunk(usbus_cdcecm_device_t *cdcecm, size_t len) -{ - uint8_t *buf = cdcecm->ep_out->ep->buf; - - /* Truncate if it exceeds the expected MTU size. */ - /* TODO: Should be converted to an endpoint halt after #17090 is merged */ - if (cdcecm->len + len < ETHERNET_FRAME_LEN) { - memcpy(cdcecm->in_buf + cdcecm->len, buf, len); - cdcecm->len += len; - } - if (len < USBUS_CDCECM_EP_DATA_SIZE) { - netdev_trigger_event_isr(&cdcecm->netdev); - } + cdcecm->len = 0; /* Flush packet */ + usbdev_ep_xmit(cdcecm->ep_out->ep, cdcecm->data_out, USBUS_CDCECM_EP_DATA_SIZE); } static void _transfer_handler(usbus_t *usbus, usbus_handler_t *handler, @@ -335,9 +315,14 @@ static void _transfer_handler(usbus_t *usbus, usbus_handler_t *handler, } size_t len = 0; usbdev_ep_get(ep, USBOPT_EP_AVAILABLE, &len, sizeof(size_t)); - _store_frame_chunk(cdcecm, len); + cdcecm->len += len; if (len == USBUS_CDCECM_EP_DATA_SIZE) { - usbdev_ep_ready(ep, 0); + /* ready next chunk */ + usbdev_ep_xmit(ep, cdcecm->data_out + cdcecm->len, + USBUS_CDCECM_EP_DATA_SIZE); + } + else { + netdev_trigger_event_isr(&cdcecm->netdev); } } else if (ep == cdcecm->ep_in->ep) { @@ -354,9 +339,9 @@ static void _handle_reset(usbus_t *usbus, usbus_handler_t *handler) usbus_cdcecm_device_t *cdcecm = (usbus_cdcecm_device_t *)handler; DEBUG("CDC ECM: Reset\n"); - _handle_rx_flush(cdcecm); _handle_in_complete(usbus, handler); cdcecm->notif = USBUS_CDCECM_NOTIF_NONE; + cdcecm->len = 0; /* Flush received data */ cdcecm->active_iface = 0; mutex_unlock(&cdcecm->out_lock); } diff --git a/sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c b/sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c index 2009569990..08b40c3d48 100644 --- a/sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c +++ b/sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c @@ -59,7 +59,7 @@ static int _send(netdev_t *netdev, const iolist_t *iolist) { assert(iolist); usbus_cdcecm_device_t *cdcecm = _netdev_to_cdcecm(netdev); - uint8_t *buf = cdcecm->ep_in->ep->buf; + uint8_t *buf = cdcecm->data_in; const iolist_t *iolist_start = iolist; size_t len = iolist_size(iolist); /* interface with alternative function ID 1 is the interface containing the @@ -142,7 +142,7 @@ static int _recv(netdev_t *netdev, void *buf, size_t max_len, void *info) return pktlen; } if (pktlen <= max_len) { - memcpy(buf, cdcecm->in_buf, pktlen); + memcpy(buf, cdcecm->data_out, pktlen); } _signal_rx_flush(cdcecm); return (pktlen <= max_len) ? (int)pktlen : -ENOBUFS; From 587d25a38e2001dc5ad137310879a079c76467c7 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 26 Oct 2021 19:47:31 +0200 Subject: [PATCH 10/10] USBUS/hid: Adapt to xmit API --- sys/include/usb/usbus/cdc/ecm.h | 2 +- sys/include/usb/usbus/hid.h | 10 ++++++++++ sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c | 1 + sys/usb/usbus/hid/hid.c | 9 +++++---- sys/usb/usbus/hid/hid_io.c | 2 +- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/sys/include/usb/usbus/cdc/ecm.h b/sys/include/usb/usbus/cdc/ecm.h index 254d402782..f117a32271 100644 --- a/sys/include/usb/usbus/cdc/ecm.h +++ b/sys/include/usb/usbus/cdc/ecm.h @@ -113,7 +113,7 @@ typedef struct usbus_cdcecm_device { unsigned active_iface; /**< Current active data interface */ /** - * @brief Buffer for received frames + * @brief Buffer for received frames from the host */ usbdev_ep_buf_t data_out[ETHERNET_FRAME_LEN]; diff --git a/sys/include/usb/usbus/hid.h b/sys/include/usb/usbus/hid.h index a7672796f4..f05191a988 100644 --- a/sys/include/usb/usbus/hid.h +++ b/sys/include/usb/usbus/hid.h @@ -77,6 +77,16 @@ struct usbus_hid_device { usbus_hid_cb_t cb; /**< Callback for data handlers */ event_t tx_ready; /**< Transmit ready event */ mutex_t in_lock; /**< mutex used for locking hid send */ + + /** + * @brief Host to device data buffer + */ + usbdev_ep_buf_t out_buf[CONFIG_USBUS_HID_INTERRUPT_EP_SIZE]; + + /** + * @brief Device to host data buffer + */ + usbdev_ep_buf_t in_buf[CONFIG_USBUS_HID_INTERRUPT_EP_SIZE]; }; /** diff --git a/sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c b/sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c index 08b40c3d48..587da8d4b6 100644 --- a/sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c +++ b/sys/usb/usbus/cdc/ecm/cdc_ecm_netdev.c @@ -142,6 +142,7 @@ static int _recv(netdev_t *netdev, void *buf, size_t max_len, void *info) return pktlen; } if (pktlen <= max_len) { + /* Copy the received data from the host to the netif buffer */ memcpy(buf, cdcecm->data_out, pktlen); } _signal_rx_flush(cdcecm); diff --git a/sys/usb/usbus/hid/hid.c b/sys/usb/usbus/hid/hid.c index d35e357014..33d95eaa6d 100644 --- a/sys/usb/usbus/hid/hid.c +++ b/sys/usb/usbus/hid/hid.c @@ -77,7 +77,7 @@ static void _handle_tx_ready(event_t *ev) { usbus_hid_device_t *hid = container_of(ev, usbus_hid_device_t, tx_ready); - usbdev_ep_ready(hid->ep_in->ep, hid->occupied); + usbdev_ep_xmit(hid->ep_in->ep, hid->in_buf, hid->occupied); } void usbus_hid_init(usbus_t *usbus, usbus_hid_device_t *hid, usbus_hid_cb_t cb, @@ -138,7 +138,8 @@ static void _init(usbus_t *usbus, usbus_handler_t *handler) usbus_enable_endpoint(hid->ep_out); /* signal that INTERRUPT OUT is ready to receive data */ - usbdev_ep_ready(hid->ep_out->ep, 0); + usbdev_ep_xmit(hid->ep_out->ep, hid->out_buf, + CONFIG_USBUS_HID_INTERRUPT_EP_SIZE); usbus_add_interface(usbus, &hid->iface); } @@ -222,8 +223,8 @@ static void _transfer_handler(usbus_t *usbus, usbus_handler_t *handler, size_t len; usbdev_ep_get(ep, USBOPT_EP_AVAILABLE, &len, sizeof(size_t)); if (len > 0) { - hid->cb(hid, ep->buf, len); + hid->cb(hid, hid->out_buf, len); } - usbdev_ep_ready(ep, 0); + usbdev_ep_xmit(ep, hid->out_buf, CONFIG_USBUS_HID_INTERRUPT_EP_SIZE); } } diff --git a/sys/usb/usbus/hid/hid_io.c b/sys/usb/usbus/hid/hid_io.c index a7b9137de5..d1267eddca 100644 --- a/sys/usb/usbus/hid/hid_io.c +++ b/sys/usb/usbus/hid/hid_io.c @@ -50,7 +50,7 @@ int usb_hid_io_read_timeout(void *buffer, size_t len, uint32_t timeout) void usb_hid_io_write(const void *buffer, size_t len) { assert(buffer); - uint8_t *buffer_ep = hid.ep_in->ep->buf; + uint8_t *buffer_ep = hid.in_buf; uint16_t max_size = hid.ep_in->maxpacketsize; size_t offset = 0;