diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4538604..b827e22 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,18 +2,18 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.2.0 + rev: v4.6.0 hooks: - id: trailing-whitespace - id: check-yaml - id: check-added-large-files - id: check-merge-conflict - repo: https://github.com/hhatto/autopep8 - rev: v2.0.4 + rev: v2.3.1 hooks: - id: autopep8 - repo: https://github.com/pylint-dev/pylint - rev: v3.0.2 + rev: v3.2.5 hooks: - id: pylint - repo: https://github.com/pre-commit/mirrors-clang-format diff --git a/BUILD.md b/BUILD.md index d976b05..5253ca9 100644 --- a/BUILD.md +++ b/BUILD.md @@ -90,9 +90,13 @@ Currently, you need two HydraUSB3 boards connected together via HSPI. You just n To be able to access the HydraDancer boards and flash them, root privileges may be required, or you can provide them to your regular user, e.g. with the creation of a file `/etc/udev/rules.d/99-hydrausb3.rules` with ``` -# UDEV Rules for HydraUSB3 boards, https://github.com/hydrausb3 +# UDEV Rules for HydraUSB3 boards https://github.com/hydrausb3, Hydradancer https://github.com/HydraDancer/hydradancer_fw and Facedancer https://github.com/greatscottgadgets/Facedancer # WinChipHead CH569W Bootloader SUBSYSTEMS=="usb", ATTRS{idVendor}=="4348", ATTRS{idProduct}=="55e0", MODE="0664", GROUP="plugdev" +# Hydradancer test +SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="27d8", MODE="0664", GROUP="plugdev" +# Facedancer stress test +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="0001", MODE="0664", GROUP="plugdev" ``` and having your user as member of the group `plugdev`. diff --git a/README.md b/README.md index 3d42fcf..cd53527 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This library was built alongside [Hydradancer](https://github.com/HydraDancer/hydradancer_fw), a new backend for the Facedancer USB emulation library based on the WCH569 chip. -Reliable drivers were needed for this project and many features were missing from the WCH examples, or untested. +Reliable drivers were needed for this project and many features were missing from the WCH examples or untested. This library provides USB3, USB2, HSPI and SerDes drivers that have been tested using the benchmark/integrity tests in `tests/`. It is based on `wch-ch56x-bsp` but its goal is to provide a higher level library. As Hydradancer was using several peripherals at a time (USB3/HSPI, USB2/HSPI), an interrupt queue was implemented to avoid missing interrupts for use with `HSPIDeviceScheduled` along with a static memory pool. While the tests in this repository are simple enough to do the processing inside the interrupt handlers, Hydradancer was missing interrupts and deferring interrupts to user mode was required. @@ -18,49 +18,16 @@ Available options * POOL_BLOCK_SIZE, POOL_BLOCK_NUM * INTERRUPT_QUEUE_SIZE -# Building the tests +# Building the tests and compilation details To build and flash the firmware, see [the build tutorial](BUILD.md). +More information on compilation options can also be found there. + # More details on compilation This project uses one or two HydraUSB3 boards, which are based on the WCH569 RISCV MCU. -## Build options - -Those options can be set the following way - -```shell -cmake --toolchain ../cmake/wch-ch56x-toolchain.cmake -DCMAKE_BUILD_TYPE=release -DOPTION_1=1 -DOPTION_2=1 -B build . -``` - -- `-DCMAKE_BUILD_TYPE=Debug` use debug optimization -- `-DBUILD_TESTS=1` build the tests - -Most warnings will be considered as errors. - -## More options - -You can set different options to activate more flags, static analysis or the logging system. - -Those flags can either be set as build options (but they will apply to all projects) by passing a `-DOPTION=value` to CMake, or by adding a `set(option_name value)` in the project `CMakeLists.txt`. - -- `STATIC_ANALYSIS` : activate GCC's built-in static analysers -- `EXTRACFLAGS` : activate -Wconversion and -Wsign-compare - -## Logging options - -Several logging options can get you infos on different parts of the library/firmwares. By default, no logs are activated so there is no impact on performances. - -- Log methods - - `LOG_OUTPUT=printf`. Logs are written directly to the UART - - `LOG_OUTPUT=buffer`. Logs are stored in a buffer, and flushed to the UART when calling `LOG_DUMP()` - - `LOG_OUTPUT=serdes`. Logs are directly sent using Serdes. Might be used to share logs from one board to the other. -- Log levels - - `LOG_OUTPUT=x LOG_LEVEL=y`. With y=1(LOG_LEVEL_CRITICAL), y=2(LOG_LEVEL_ERROR), y=3(LOG_LEVEL_WARNING), y=4(LOG_LEVEL_INFO), y=5(LOG_LEVEL_DEBUG). All levels <=y will be displayed. -- Log filters - - `LOG_OUTPUT=x LOG_FILTER_IDS=a,b,c, ...` You can set any number of filters from the following list 1(LOG_ID_USER), 2(LOG_ID_USB2), 3(LOG_ID_USB3), 4(LOG_ID_HSPI), 5(LOG_ID_SERDES), 6(LOG_ID_INTERRUPT_QUEUE), 7(LOG_ID_RAMX_ALLOC). If `LOG_LEVEL` is also defined, the logs with IDs will only be displayed if they have the right level. - # Structure of the project ``` @@ -74,11 +41,7 @@ wch-ch56x-lib/ # Tests -There are no automated tests for now, but that doesn't mean tests are not required. - -For now, the tests in hydradancer/tests consist in loop-back devices, to test for integrity and benchmark the speed of the device in different scenarios. - -More information about the different scenarios can be found in [docs/Testing.md](docs/Testing.md). +More information about the different tests and how to use them can be found in [docs/Testing.md](docs/Testing.md) # How to contribute diff --git a/docs/Testing.md b/docs/Testing.md index 2034e3c..fbca1b5 100644 --- a/docs/Testing.md +++ b/docs/Testing.md @@ -44,7 +44,7 @@ Below are the different test cases and how to test them: ### Unittests * Compile : compile the tests with `-DBUILD_TESTS=1` -* Run : flash to one board, and read its UART. +* Run : flash `test_firmware_unittests.bin` to one board, and read its UART. The firmware will simply execute a list of functions returning either `true` or `false`, to check if the test has passed. @@ -55,21 +55,21 @@ Those "unittests" are a way to get some certainty about edge cases of some parts ### HSPI * Compile : compile the tests with `-DBUILD_TESTS=1` -* Run : flash to both boards, the jumper is used to differentiate the boards. Run `test_hspi_serdes.py`. +* Run : flash `test_firmware_hspi.bin` to both boards, the jumper is used to differentiate the boards. Run `test_hspi_serdes.py`. The test simply sends data from one board to the other using HSPI, then exports it to the host to check integrity. ### SerDes * Compile : compile the tests with `-DBUILD_TESTS=1` -* Run : flash to both boards, the jumper is used to differentiate the boards. Run `test_hspi_serdes.py`. +* Run : flash `test_firmware_serdes.bin` to both boards, the jumper is used to differentiate the boards. Run `test_hspi_serdes.py`. The test simply sends data from one board to the other using SerDes, then exports it to the host to check integrity. ### Loopback * Compile : compile the tests with `-DBUILD_TESTS=1` -* Run : flash to both boards, the jumper is used to differentiate the boards. Run `test_loopback.py` or `test_loopback_randomize.py`. +* Run : flash `test_firmware_loopback.bin` to both boards, the jumper is used to differentiate the boards. Run `test_loopback.py` or `test_loopback_randomize.py`. `test_loopback.py` will send data to the first board via USB, which will transmit it to the second board using HSPI, then receive it back with SerDes, and back to the host via USB. The script will then check for integrity. @@ -77,14 +77,28 @@ Run `test_loopback_randomize.py` to send packets with variable sizes, to check i The goal here is to check that all parts of the data loop works, although it does not use HSPI as half-duplex and does not use the interrupt_queue. +### USB stress +* Compile : compile the tests with `-DBUILD_TESTS=1` +* Run : flash `test_firmware_usb_stress_test.bin` to one board. Run `test_stress.py`. + +Sends packets of random size using bulk, control or interrupt (for low-speed) requests and checks if data has been correctly sent or received. + +Based on Facedancer's stress test. + ### USB loopack +NOTE : the above USB stress test should replace this loopback test in most cases. +NOTE : `test_firmware_usb_loopback.bin` allows testing all 16 endpoint numbers in both directions (not simultaneously because of incompatibilities) by uncommenting the dedicated code in `main.c`. * Compile : compile the tests with `-DBUILD_TESTS=1` -* Run : flash to one board. Run `test_loopback.py` or `test_loopback_randomize.py`. +* Run : flash `test_firmware_usb_loopback.bin` or `test_firmware_usb_loopback_separate_usb_stacks.bin` to one board. Run `test_loopback.py` or `test_loopback_randomize_packetsize.py`. `test_loopback.py` will send data to the board via USB, which will send it back. The test will then check the integrity of the transmission. The test is repeated for all 7 IN/OUT endpoints pairs. -Run `test_loopback_randomize.py` to send packets with variable sizes, to check if the board can handle various packet sizes. +Run `test_loopback_randomize_packetsize.py` to send packets with variable sizes, to check if the board can handle various packet sizes. + +`test_loopback.py --zlp` sends packets without data (ZLP, Zero-length packets) to test if the device can handle these properly. + +The `test_firmware_usb_loopback_separate_usb_stacks.bin` firmware will create one USB3 device using the USB3 lines of the connector and one USB2 device using the USB2 lines of the connector. You can then run the scripts at the same time for both device. The goal is to test if the USB3 and USB2 peripherals are working correctly. @@ -93,7 +107,7 @@ By default, the USB3 peripheral is active but you can switch to USB2 by maintain ### USB speedtest * Compile : compile the tests with `-DBUILD_TESTS=1` -* Run : flash to one board. Run `test_speedtest.py` or `test_speedtest_one_by_one.py`. +* Run : flash `test_firmware_usb_speedtest.bin` to one board. Run `test_speedtest.py` or `test_speedtest_one_by_one.py`. `test_speedtest.py` will first send data to the board in one go (one call to libusb), then read data from the board in one go (one call to libusb). diff --git a/src/wch-ch56x-lib/USBDevice/usb20.c b/src/wch-ch56x-lib/USBDevice/usb20.c index 628b1c9..b82eb12 100644 --- a/src/wch-ch56x-lib/USBDevice/usb20.c +++ b/src/wch-ch56x-lib/USBDevice/usb20.c @@ -26,7 +26,6 @@ limitations under the License. ENDPOINT_10_TX | ENDPOINT_10_RX | ENDPOINT_11_TX | ENDPOINT_11_RX | \ ENDPOINT_12_TX | ENDPOINT_12_RX | ENDPOINT_13_TX | ENDPOINT_13_RX | \ ENDPOINT_14_TX | ENDPOINT_14_RX | ENDPOINT_15_TX | ENDPOINT_15_RX)) -#define USB2_ENDP0_MAX_PACKET_SIZE ((uint8_t)(64)) #define USB2_EP_MAX_PACKET_SIZE ((uint16_t)(1024)) // the default device is a regular USB3 with the mandatory USB2 compatibility. @@ -36,16 +35,38 @@ usb_device_t* usb2_backend_current_device = &usb_device_0; static volatile puint8_t desc_head = NULL; static volatile uint16_t endp0_current_transfer_size = 0; static volatile uint16_t endp0_remaining_bytes = 0; -static volatile uint16_t endp_tx_remaining_bytes[8]; -static volatile USB_SETUP usb_setup_req; - static volatile bool ep0_passthrough_enabled = false; +volatile uint16_t endp_tx_remaining_bytes[16]; +volatile USB_SETUP usb_setup_req; +volatile uint16_t usb_setup_req_data_size; +uint16_t usb2_endp0_max_packet_size = 0; + +static uint32_t usb2_incompatibles_endpoints[18] = { + ENDPOINT_1_TX | ENDPOINT_9_TX, + ENDPOINT_2_TX | ENDPOINT_10_TX, + ENDPOINT_3_TX | ENDPOINT_11_TX, + ENDPOINT_4_TX | ENDPOINT_12_TX, + ENDPOINT_5_TX | ENDPOINT_13_TX, + ENDPOINT_6_TX | ENDPOINT_14_TX, + ENDPOINT_7_TX | ENDPOINT_15_TX, + ENDPOINT_1_RX | ENDPOINT_9_RX, + ENDPOINT_2_RX | ENDPOINT_10_RX, + ENDPOINT_3_RX | ENDPOINT_11_RX, + ENDPOINT_4_RX | ENDPOINT_12_RX, + ENDPOINT_5_RX | ENDPOINT_13_RX, + ENDPOINT_6_RX | ENDPOINT_14_RX, + ENDPOINT_7_RX | ENDPOINT_15_RX, + ENDPOINT_8_RX | ENDPOINT_4_RX, + ENDPOINT_8_TX | ENDPOINT_4_TX, + ENDPOINT_8_RX | ENDPOINT_12_RX, + ENDPOINT_8_TX | ENDPOINT_12_TX, +}; void _default_usb2_device_handle_bus_reset(void); void _default_usb2_device_handle_bus_reset(void) {} usb2_user_handled_t usb2_user_handled = { - .usb2_device_handle_bus_reset = _default_usb2_device_handle_bus_reset + .usb2_device_handle_bus_reset = _default_usb2_device_handle_bus_reset, }; usb2_endpoints_backend_handled_t usb2_endpoints_backend_handled = { @@ -78,11 +99,12 @@ void usb2_device_init() } R8_USB_CTRL |= RB_DEV_PU_EN | RB_USB_INT_BUSY | RB_USB_DMA_EN; R8_USB_INT_EN = RB_USB_IE_SETUPACT | RB_USB_IE_TRANS | RB_USB_IE_SUSPEND | - RB_USB_IE_BUSRST; + RB_USB_IE_BUSRST | RB_USB_IE_FIFOOV; // init device's state usb2_backend_current_device->addr = 0; usb2_backend_current_device->state = POWERED; + usb2_endp0_max_packet_size = usb2_backend_current_device->usb_descriptors.usb2_device_descr->bMaxPacketSize0; usb2_setup_endpoints(); } @@ -94,21 +116,18 @@ void usb2_device_deinit(void) R8_USB_CTRL = RB_USB_CLR_ALL | RB_USB_RESET_SIE; } -void usb2_setup_endpoints(void) +void usb2_setup_endpoints_in_mask(uint32_t mask) { - R32_UEP0_RT_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[0].buffer; - R16_UEP0_MAX_LEN = 64; // configure EP0 max buffer length - R16_UEP0_T_LEN = 0; - R8_UEP0_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; - R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; - - if (usb2_backend_current_device->endpoint_mask & (USB2_UNSUPPORTED_ENDPOINTS)) + for (size_t i = 0; i < sizeof(usb2_incompatibles_endpoints) / sizeof(usb2_incompatibles_endpoints[0]); ++i) { - LOG_IF(LOG_LEVEL_DEBUG, LOG_ID_USB2, "Unsupported endpoints \r\n"); - return; + if ((mask & usb2_incompatibles_endpoints[i]) == usb2_incompatibles_endpoints[i]) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "Incompatible endpoints, mask %x \r\n", usb2_incompatibles_endpoints[i]); + return; + } } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_1_TX) + if (mask & ENDPOINT_1_TX) { R8_UEP4_1_MOD |= RB_UEP1_TX_EN; R32_UEP1_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[1].buffer; @@ -116,7 +135,17 @@ void usb2_setup_endpoints(void) R8_UEP1_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; usb2_backend_current_device->endpoints.tx[1].state = ENDP_STATE_NAK; } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_1_RX) + + if (mask & ENDPOINT_9_TX) + { + R8_UEP4_1_MOD |= RB_UEP1_TX_EN; + R32_UEP1_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[9].buffer; + R16_UEP1_T_LEN = 0; + R8_UEP1_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + usb2_backend_current_device->endpoints.tx[9].state = ENDP_STATE_NAK; + } + + if (mask & ENDPOINT_1_RX) { if (usb2_backend_current_device->endpoints.rx[1].max_packet_size > USB2_EP_MAX_PACKET_SIZE) { @@ -130,7 +159,21 @@ void usb2_setup_endpoints(void) usb2_backend_current_device->endpoints.rx[1].state = ENDP_STATE_ACK; } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_2_TX) + if (mask & ENDPOINT_9_RX) + { + if (usb2_backend_current_device->endpoints.rx[9].max_packet_size > USB2_EP_MAX_PACKET_SIZE) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "ep %d rx max_packet_size exceeds the %d bytes limit \r\n", 9, USB2_EP_MAX_PACKET_SIZE); + return; + } + R8_UEP4_1_MOD |= RB_UEP1_RX_EN; + R32_UEP1_RX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[9].buffer; + R16_UEP1_MAX_LEN = usb2_backend_current_device->endpoints.rx[9].max_packet_size; + R8_UEP1_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + usb2_backend_current_device->endpoints.rx[9].state = ENDP_STATE_ACK; + } + + if (mask & ENDPOINT_2_TX) { R8_UEP2_3_MOD |= RB_UEP2_TX_EN; R32_UEP2_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[2].buffer; @@ -138,7 +181,17 @@ void usb2_setup_endpoints(void) R8_UEP2_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; usb2_backend_current_device->endpoints.tx[2].state = ENDP_STATE_NAK; } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_2_RX) + + if (mask & ENDPOINT_10_TX) + { + R8_UEP2_3_MOD |= RB_UEP2_TX_EN; + R32_UEP2_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[10].buffer; + R16_UEP2_T_LEN = 0; + R8_UEP2_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + usb2_backend_current_device->endpoints.tx[10].state = ENDP_STATE_NAK; + } + + if (mask & ENDPOINT_2_RX) { if (usb2_backend_current_device->endpoints.rx[2].max_packet_size > USB2_EP_MAX_PACKET_SIZE) { @@ -152,7 +205,21 @@ void usb2_setup_endpoints(void) usb2_backend_current_device->endpoints.rx[2].state = ENDP_STATE_ACK; } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_3_TX) + if (mask & ENDPOINT_10_RX) + { + if (usb2_backend_current_device->endpoints.rx[10].max_packet_size > USB2_EP_MAX_PACKET_SIZE) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "ep %d rx max_packet_size exceeds the %d bytes limit \r\n", 10, USB2_EP_MAX_PACKET_SIZE); + return; + } + R8_UEP2_3_MOD |= RB_UEP2_RX_EN; + R32_UEP2_RX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[10].buffer; + R16_UEP2_MAX_LEN = usb2_backend_current_device->endpoints.rx[10].max_packet_size; + R8_UEP2_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + usb2_backend_current_device->endpoints.rx[10].state = ENDP_STATE_ACK; + } + + if (mask & ENDPOINT_3_TX) { R8_UEP2_3_MOD |= RB_UEP3_TX_EN; R32_UEP3_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[3].buffer; @@ -160,7 +227,15 @@ void usb2_setup_endpoints(void) R8_UEP3_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; usb2_backend_current_device->endpoints.tx[3].state = ENDP_STATE_NAK; } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_3_RX) + if (mask & ENDPOINT_11_TX) + { + R8_UEP2_3_MOD |= RB_UEP3_TX_EN; + R32_UEP3_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[11].buffer; + R16_UEP3_T_LEN = 0; + R8_UEP3_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + usb2_backend_current_device->endpoints.tx[11].state = ENDP_STATE_NAK; + } + if (mask & ENDPOINT_3_RX) { if (usb2_backend_current_device->endpoints.rx[3].max_packet_size > USB2_EP_MAX_PACKET_SIZE) { @@ -173,8 +248,21 @@ void usb2_setup_endpoints(void) R8_UEP3_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; usb2_backend_current_device->endpoints.rx[3].state = ENDP_STATE_ACK; } + if (mask & ENDPOINT_11_RX) + { + if (usb2_backend_current_device->endpoints.rx[11].max_packet_size > USB2_EP_MAX_PACKET_SIZE) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "ep %d rx max_packet_size exceeds the %d bytes limit \r\n", 11, USB2_EP_MAX_PACKET_SIZE); + return; + } + R8_UEP2_3_MOD |= RB_UEP3_RX_EN; + R32_UEP3_RX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[11].buffer; + R16_UEP3_MAX_LEN = usb2_backend_current_device->endpoints.rx[11].max_packet_size; + R8_UEP3_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + usb2_backend_current_device->endpoints.rx[11].state = ENDP_STATE_ACK; + } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_4_TX) + if (mask & ENDPOINT_4_TX) { R8_UEP4_1_MOD |= RB_UEP4_TX_EN; R32_UEP4_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[4].buffer; @@ -182,7 +270,23 @@ void usb2_setup_endpoints(void) R8_UEP4_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; usb2_backend_current_device->endpoints.tx[4].state = ENDP_STATE_NAK; } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_4_RX) + if (mask & ENDPOINT_8_TX) + { + R8_UEP4_1_MOD |= RB_UEP4_TX_EN; + R32_UEP4_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[8].buffer; + R16_UEP4_T_LEN = 0; + R8_UEP4_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + usb2_backend_current_device->endpoints.tx[8].state = ENDP_STATE_NAK; + } + if (mask & ENDPOINT_12_TX) + { + R8_UEP4_1_MOD |= RB_UEP4_TX_EN; + R32_UEP4_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[12].buffer; + R16_UEP4_T_LEN = 0; + R8_UEP4_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + usb2_backend_current_device->endpoints.tx[12].state = ENDP_STATE_NAK; + } + if (mask & ENDPOINT_4_RX) { if (usb2_backend_current_device->endpoints.rx[4].max_packet_size > USB2_EP_MAX_PACKET_SIZE) { @@ -195,8 +299,34 @@ void usb2_setup_endpoints(void) R8_UEP4_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; usb2_backend_current_device->endpoints.rx[4].state = ENDP_STATE_ACK; } + if (mask & ENDPOINT_8_RX) + { + if (usb2_backend_current_device->endpoints.rx[8].max_packet_size > USB2_EP_MAX_PACKET_SIZE) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "ep %d rx max_packet_size exceeds the %d bytes limit \r\n", 8, USB2_EP_MAX_PACKET_SIZE); + return; + } + R8_UEP4_1_MOD |= RB_UEP4_RX_EN; + R32_UEP4_RX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[8].buffer; + R16_UEP4_MAX_LEN = usb2_backend_current_device->endpoints.rx[8].max_packet_size; + R8_UEP4_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + usb2_backend_current_device->endpoints.rx[8].state = ENDP_STATE_ACK; + } + if (mask & ENDPOINT_12_RX) + { + if (usb2_backend_current_device->endpoints.rx[12].max_packet_size > USB2_EP_MAX_PACKET_SIZE) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "ep %d rx max_packet_size exceeds the %d bytes limit \r\n", 12, USB2_EP_MAX_PACKET_SIZE); + return; + } + R8_UEP4_1_MOD |= RB_UEP4_RX_EN; + R32_UEP4_RX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[12].buffer; + R16_UEP4_MAX_LEN = usb2_backend_current_device->endpoints.rx[12].max_packet_size; + R8_UEP4_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + usb2_backend_current_device->endpoints.rx[12].state = ENDP_STATE_ACK; + } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_5_TX) + if (mask & ENDPOINT_5_TX) { R8_UEP5_6_MOD |= RB_UEP5_TX_EN; R32_UEP5_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[5].buffer; @@ -204,7 +334,15 @@ void usb2_setup_endpoints(void) R8_UEP5_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; usb2_backend_current_device->endpoints.tx[5].state = ENDP_STATE_NAK; } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_5_RX) + if (mask & ENDPOINT_13_TX) + { + R8_UEP5_6_MOD |= RB_UEP5_TX_EN; + R32_UEP5_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[13].buffer; + R16_UEP5_T_LEN = 0; + R8_UEP5_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + usb2_backend_current_device->endpoints.tx[13].state = ENDP_STATE_NAK; + } + if (mask & ENDPOINT_5_RX) { if (usb2_backend_current_device->endpoints.rx[5].max_packet_size > USB2_EP_MAX_PACKET_SIZE) { @@ -217,8 +355,21 @@ void usb2_setup_endpoints(void) R8_UEP5_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; usb2_backend_current_device->endpoints.rx[5].state = ENDP_STATE_ACK; } + if (mask & ENDPOINT_13_RX) + { + if (usb2_backend_current_device->endpoints.rx[13].max_packet_size > USB2_EP_MAX_PACKET_SIZE) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "ep %d rx max_packet_size exceeds the %d bytes limit \r\n", 13, USB2_EP_MAX_PACKET_SIZE); + return; + } + R8_UEP5_6_MOD |= RB_UEP5_RX_EN; + R32_UEP5_RX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[13].buffer; + R16_UEP5_MAX_LEN = usb2_backend_current_device->endpoints.rx[13].max_packet_size; + R8_UEP5_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + usb2_backend_current_device->endpoints.rx[13].state = ENDP_STATE_ACK; + } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_6_TX) + if (mask & ENDPOINT_6_TX) { R8_UEP5_6_MOD |= RB_UEP6_TX_EN; R32_UEP6_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[6].buffer; @@ -226,7 +377,15 @@ void usb2_setup_endpoints(void) R8_UEP6_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; usb2_backend_current_device->endpoints.tx[6].state = ENDP_STATE_NAK; } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_6_RX) + if (mask & ENDPOINT_14_TX) + { + R8_UEP5_6_MOD |= RB_UEP6_TX_EN; + R32_UEP6_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[14].buffer; + R16_UEP6_T_LEN = 0; + R8_UEP6_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + usb2_backend_current_device->endpoints.tx[14].state = ENDP_STATE_NAK; + } + if (mask & ENDPOINT_6_RX) { if (usb2_backend_current_device->endpoints.rx[6].max_packet_size > USB2_EP_MAX_PACKET_SIZE) { @@ -239,8 +398,21 @@ void usb2_setup_endpoints(void) R8_UEP6_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; usb2_backend_current_device->endpoints.rx[6].state = ENDP_STATE_ACK; } + if (mask & ENDPOINT_14_RX) + { + if (usb2_backend_current_device->endpoints.rx[14].max_packet_size > USB2_EP_MAX_PACKET_SIZE) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "ep %d rx max_packet_size exceeds the %d bytes limit \r\n", 14, USB2_EP_MAX_PACKET_SIZE); + return; + } + R8_UEP5_6_MOD |= RB_UEP6_RX_EN; + R32_UEP6_RX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[14].buffer; + R16_UEP6_MAX_LEN = usb2_backend_current_device->endpoints.rx[14].max_packet_size; + R8_UEP6_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + usb2_backend_current_device->endpoints.rx[14].state = ENDP_STATE_ACK; + } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_7_TX) + if (mask & ENDPOINT_7_TX) { R8_UEP7_MOD |= RB_UEP7_TX_EN; R32_UEP7_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[7].buffer; @@ -248,7 +420,15 @@ void usb2_setup_endpoints(void) R8_UEP7_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; usb2_backend_current_device->endpoints.tx[7].state = ENDP_STATE_NAK; } - if (usb2_backend_current_device->endpoint_mask & ENDPOINT_7_RX) + if (mask & ENDPOINT_15_TX) + { + R8_UEP7_MOD |= RB_UEP7_TX_EN; + R32_UEP7_TX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.tx[15].buffer; + R16_UEP7_T_LEN = 0; + R8_UEP7_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + usb2_backend_current_device->endpoints.tx[15].state = ENDP_STATE_NAK; + } + if (mask & ENDPOINT_7_RX) { if (usb2_backend_current_device->endpoints.rx[7].max_packet_size > USB2_EP_MAX_PACKET_SIZE) { @@ -261,13 +441,32 @@ void usb2_setup_endpoints(void) R8_UEP7_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; usb2_backend_current_device->endpoints.rx[7].state = ENDP_STATE_ACK; } - - if (usb2_backend_current_device->endpoint_mask & (USB2_UNSUPPORTED_ENDPOINTS)) + if (mask & ENDPOINT_15_RX) { - LOG_IF(LOG_LEVEL_DEBUG, LOG_ID_USB2, "Unsupported endpoints, mask %x \r\n", usb2_backend_current_device->endpoint_mask & (USB2_UNSUPPORTED_ENDPOINTS)); + if (usb2_backend_current_device->endpoints.rx[15].max_packet_size > USB2_EP_MAX_PACKET_SIZE) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "ep %d rx max_packet_size exceeds the %d bytes limit \r\n", 15, USB2_EP_MAX_PACKET_SIZE); + return; + } + R8_UEP7_MOD |= RB_UEP7_RX_EN; + R32_UEP7_RX_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[15].buffer; + R16_UEP7_MAX_LEN = usb2_backend_current_device->endpoints.rx[15].max_packet_size; + R8_UEP7_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + usb2_backend_current_device->endpoints.rx[15].state = ENDP_STATE_ACK; } } +void usb2_setup_endpoints(void) +{ + R32_UEP0_RT_DMA = (uint32_t)(uint8_t*)usb2_backend_current_device->endpoints.rx[0].buffer; + R16_UEP0_MAX_LEN = 64; // configure EP0 max buffer length + R16_UEP0_T_LEN = 0; + R8_UEP0_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + + usb2_setup_endpoints_in_mask(usb2_backend_current_device->endpoint_mask); +} + void usb2_reset_endpoints(void) { usb2_setup_endpoints(); } void usb2_ep0_passthrough_enabled(bool enable) @@ -300,9 +499,7 @@ usb2_ep0_set_configuration_callback(void) __attribute__((always_inline)) static inline uint16_t usb2_ep0_next_data_packet_size(void) { - return endp0_remaining_bytes >= USB2_ENDP0_MAX_PACKET_SIZE - ? USB2_ENDP0_MAX_PACKET_SIZE - : endp0_remaining_bytes; + return min(endp0_remaining_bytes, usb2_endp0_max_packet_size); } /** @@ -508,7 +705,7 @@ __attribute__((always_inline)) static inline void usb2_ep0_in_handler(void) { // Do not forget ZLP in case we only send full-sized packets : the host knows when the transfer is finished // either by receiving a short packet (why would the device send a short packet if it has more to send ?) or a ZLP (zero-length packet) - if ((endp0_current_transfer_size % USB2_ENDP0_MAX_PACKET_SIZE) == 0 && len != 0) + if ((endp0_current_transfer_size % usb2_endp0_max_packet_size) == 0 && len != 0) { R16_UEP0_T_LEN = 0; R8_UEP0_TX_CTRL = (R8_UEP0_TX_CTRL & ~(uint8_t)RB_UEP_TRES_MASK) | (uint8_t)UEP_T_RES_ACK; @@ -622,43 +819,51 @@ usb2_in_transfer_handler(uint8_t endp_num) vuint16_t* T_Len = usb2_get_tx_endpoint_len_reg(endp_num); vuint16_t* tx_remaining_bytes = &endp_tx_remaining_bytes[endp_num]; -#ifdef DEBUG - if (endp == NULL || TX_CTRL == NULL || T_Len == NULL || - tx_remaining_bytes == NULL) - return; -#endif - if (*usb2_get_tx_endpoint_addr_reg(endp_num) != 0) { uint16_t len = *tx_remaining_bytes > endp->max_packet_size ? endp->max_packet_size : *tx_remaining_bytes; + usb_setup_req_data_size += len; *tx_remaining_bytes -= len; if (*tx_remaining_bytes == 0) { *T_Len = 0; - if (endp_num != 0) + if (endp_num == 0 && !(usb_setup_req.bRequestType & USB_REQ_TYP_IN)) { - *usb2_get_tx_endpoint_addr_reg(endp_num) = (uint32_t)endp->buffer; + R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + R8_UEP0_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + } + else if (endp_num == 0 && (usb_setup_req.bRequestType & USB_REQ_TYP_IN) && ((usb_setup_req_data_size >= usb_setup_req.wLength || (len < endp->max_packet_size)))) + { + // prepare STATUS + R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_1; + R8_UEP0_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_1; } else { - *usb2_get_rx_endpoint_addr_reg(0) = (uint32_t)usb2_backend_current_device->endpoints.rx[0].buffer; + *TX_CTRL ^= RB_UEP_T_TOG_1; // switch between DATA0/DATA1 toggle } + *TX_CTRL = (*TX_CTRL & ~RB_UEP_TRES_MASK) | UEP_T_RES_NAK; usb2_backend_current_device->endpoints.tx_complete[endp_num](Ack); + if (endp_num != 0) + { + *usb2_get_tx_endpoint_addr_reg(endp_num) = (uint32_t)endp->buffer; + } } else { + *usb2_get_tx_endpoint_addr_reg(endp_num) += len; *TX_CTRL = (*TX_CTRL & ~RB_UEP_TRES_MASK) | UEP_T_RES_ACK; + *TX_CTRL ^= RB_UEP_T_TOG_1; // switch between DATA0/DATA1 toggle } } else { *TX_CTRL = (*TX_CTRL & ~RB_UEP_TRES_MASK) | UEP_T_RES_NAK; } - *TX_CTRL ^= RB_UEP_T_TOG_1; // switch between DATA0/DATA1 toggle } /** @@ -673,22 +878,38 @@ usb2_out_transfer_handler(uint8_t endp_num) volatile USB_ENDPOINT* endp = &usb2_backend_current_device->endpoints.rx[endp_num]; vuint8_t* RX_CTRL = usb2_get_rx_endpoint_ctrl_reg(endp_num); -#ifdef DEBUG - if (endp == NULL || RX_CTRL == NULL) - return; -#endif - if (endp->buffer != NULL) { + if (endp_num == 0) + { + usb_setup_req_data_size += num_bytes_received; + } + endp->state = usb2_backend_current_device->endpoints.rx_callback[endp_num](endp->buffer, num_bytes_received); *usb2_get_rx_endpoint_addr_reg(endp_num) = (uint32_t)endp->buffer; - *RX_CTRL = (*RX_CTRL & ~RB_UEP_TRES_MASK) | endp->state; + + if (endp_num == 0 && (usb_setup_req.bRequestType & USB_REQ_TYP_IN)) + { + // prepare SETUP + R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0; + R8_UEP0_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0; + } + else if (endp_num == 0 && !(usb_setup_req.bRequestType & USB_REQ_TYP_IN) && (usb_setup_req_data_size >= usb_setup_req.wLength)) + { + // prepare STATUS + R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_1; + R8_UEP0_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_1; + } + else + { + *RX_CTRL = (*RX_CTRL & ~RB_UEP_RRES_MASK) | endp->state; + *RX_CTRL ^= RB_UEP_T_TOG_1; // switch between DATA0/DATA1 toggle + } } else { - *RX_CTRL = (*RX_CTRL & ~RB_UEP_TRES_MASK) | UEP_T_RES_NAK; + *RX_CTRL = (*RX_CTRL & ~RB_UEP_RRES_MASK) | UEP_T_RES_NAK; } - *RX_CTRL ^= RB_UEP_T_TOG_1; // switch between DATA0/DATA1 toggle } void usb2_endp_rx_set_state_callback(uint8_t endp_num) @@ -748,29 +969,26 @@ void usb2_endp_tx_ready(uint8_t endp_num, uint16_t size) __attribute__((interrupt("WCH-Interrupt-fast"))) void USBHS_IRQHandler(void) { - uint8_t usb_dev_endp = (R8_USB_INT_ST & RB_DEV_ENDP_MASK) & 0xf; - uint8_t usb_pid = (R8_USB_INT_ST & RB_DEV_TOKEN_MASK) >> 4; - + volatile uint8_t usb_dev_endp = (R8_USB_INT_ST & RB_DEV_ENDP_MASK) & 0xf; + volatile uint8_t usb_pid = (R8_USB_INT_ST & RB_DEV_TOKEN_MASK) >> 4; + volatile uint8_t usb_event = R8_USB_INT_FG; + volatile bool togok = (R8_USB_INT_ST & RB_USB_ST_TOGOK) != 0; LOG_IF(LOG_LEVEL_TRACE, LOG_ID_TRACE, "USBHS_IRQHandler-start\r\n"); - - if (!(R8_USB_INT_FG & RB_USB_IF_SETUOACT) && (R8_USB_INT_ST & RB_USB_ST_NAK)) + if (!(usb_event & RB_USB_IF_SETUOACT) && (R8_USB_INT_ST & RB_USB_ST_NAK)) { usb2_backend_current_device->endpoints.nak_callback(usb_dev_endp); R8_USB_INT_FG = R8_USB_INT_FG; return; } - - if (R8_USB_INT_FG & RB_USB_IF_SETUOACT && usb2_backend_current_device->state != POWERED) + else if (usb_event & RB_USB_IF_SETUOACT && usb2_backend_current_device->state != POWERED) { - usb_setup_req = *(USB_SETUP*)usb2_backend_current_device->endpoints.rx[0].buffer; - + volatile USB_ENDPOINT* endp0 = &usb2_backend_current_device->endpoints.rx[0]; + usb_setup_req = *(USB_SETUP*)endp0->buffer; + usb_setup_req_data_size = 0; if (ep0_passthrough_enabled) { - volatile USB_ENDPOINT* endp0 = &usb2_backend_current_device->endpoints.rx[0]; - endp0->state = usb2_backend_current_device->endpoints.endp0_passthrough_setup_callback( usb2_backend_current_device->endpoints.rx[0].buffer, sizeof(USB_SETUP)); - *usb2_get_rx_endpoint_addr_reg(0) = (uint32_t)endp0->buffer; R8_UEP0_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_1; R8_UEP0_RX_CTRL = endp0->state | RB_UEP_T_TOG_1; } @@ -778,44 +996,38 @@ __attribute__((interrupt("WCH-Interrupt-fast"))) void USBHS_IRQHandler(void) { usb2_ep0_setup_stage_handler(); } - - R8_USB_INT_FG = RB_USB_IF_SETUOACT; // Clear interrupt flag + R8_USB_INT_FG = R8_USB_INT_FG; // Clear interrupt flag } - else if ((R8_USB_INT_FG & RB_USB_IF_TRANSFER) && + else if ((usb_event & RB_USB_IF_TRANSFER) && usb2_backend_current_device->state != POWERED) { - if (!(R8_USB_INT_ST & RB_USB_ST_TOGOK)) + if (usb_pid == PID_IN) { - LOG_IF_LEVEL(LOG_LEVEL_DEBUG, " TOG MATCH FAIL : ENDP %x pid %x \n", usb_dev_endp, usb_pid); - // what to do here ? - // R8_USB_INT_FG = RB_USB_IF_TRANSFER; // Clear interrupt flag - // return; + if (usb_dev_endp != 0 || ep0_passthrough_enabled) + { + usb2_in_transfer_handler(usb_dev_endp); + } + else + { + usb2_ep0_in_handler(); + } } - - switch (usb_dev_endp) + else if (usb_pid == PID_OUT) { - case 0: - if (usb_pid == PID_IN) + vuint8_t* RX_CTRL = usb2_get_rx_endpoint_ctrl_reg(usb_dev_endp); + if (!togok) { - if (ep0_passthrough_enabled) - { - usb2_in_transfer_handler(usb_dev_endp); - } - else - { - usb2_ep0_in_handler(); - } + *RX_CTRL = (*RX_CTRL & ~RB_UEP_RRES_MASK) | usb2_backend_current_device->endpoints.rx[usb_dev_endp].state; + R8_USB_INT_FG = RB_USB_IF_TRANSFER; // Clear interrupt flag + return; } - else if (usb_pid == PID_OUT) + + // WCH569 will trigger an interrupt for a DATA packet, even if RX_CTRL was set to NAK + // discard this packet, as even though data has been received it shouldn't be taken into account + if (!(*RX_CTRL & (UEP_R_RES_NAK | UEP_R_RES_STALL))) { - if (ep0_passthrough_enabled) + if (usb_dev_endp != 0 || ep0_passthrough_enabled) { - // WCH569 will trigger an interrupt for a DATA packet, even if RX_CTRL was set to NAK - // discard this packet, as even though data has been received it shouldn't be taken into account - if (R8_UEP0_RX_CTRL & (UEP_R_RES_NAK | UEP_R_RES_STALL)) - { - break; - } usb2_out_transfer_handler(usb_dev_endp); } else @@ -823,41 +1035,22 @@ __attribute__((interrupt("WCH-Interrupt-fast"))) void USBHS_IRQHandler(void) usb2_ep0_out_handler(); } } - break; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - - if (usb_pid == PID_IN) + else { - usb2_in_transfer_handler(usb_dev_endp); + *RX_CTRL = (*RX_CTRL & ~RB_UEP_RRES_MASK) | usb2_backend_current_device->endpoints.rx[usb_dev_endp].state; } - else if (usb_pid == PID_OUT) - { - // WCH569 will trigger an interrupt for a DATA packet, even if RX_CTRL was set to NAK - // discard this packet, as even though data has been received it shouldn't be taken into account - if (*usb2_get_rx_endpoint_ctrl_reg(usb_dev_endp) & (UEP_R_RES_NAK | UEP_R_RES_STALL)) - { - break; - } - usb2_out_transfer_handler(usb_dev_endp); - } - break; - default: - break; } - R8_USB_INT_FG = RB_USB_IF_TRANSFER; // Clear interrupt flag } - else if (R8_USB_INT_FG & RB_USB_IF_SUSPEND) // wakeup event or bus suspend + else if (usb_event & RB_USB_IF_SUSPEND) // wakeup event or bus suspend { R8_USB_INT_FG = RB_USB_IF_SUSPEND; } - else if (R8_USB_INT_FG & RB_USB_IF_BUSRST) + else if (usb_event & RB_USB_IF_FIFOOV) + { + LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "USB2 FIFO Overflow\r\n"); + } + else if (usb_event & RB_USB_IF_BUSRST) { usb2_user_handled.usb2_device_handle_bus_reset(); usb2_set_device_address(0); diff --git a/src/wch-ch56x-lib/USBDevice/usb20.h b/src/wch-ch56x-lib/USBDevice/usb20.h index 1db6ef3..4c567ea 100644 --- a/src/wch-ch56x-lib/USBDevice/usb20.h +++ b/src/wch-ch56x-lib/USBDevice/usb20.h @@ -61,6 +61,10 @@ typedef struct usb2_user_handled_t } usb2_user_handled_t; extern usb2_user_handled_t usb2_user_handled; +extern volatile uint16_t endp_tx_remaining_bytes[16]; +extern volatile USB_SETUP current_req; +extern volatile uint16_t current_req_size; +extern uint16_t usb2_endp0_max_packet_size; /** * @fn usb2_device_init @@ -78,6 +82,13 @@ void usb2_device_init(void); */ void usb2_device_deinit(void); +/** + * @fn usb2_setup_endpoints_in_mask + * @brief Setup endpoints set in bitmask mask + * @param mask Bitmask, endpoints to activate + **/ +void usb2_setup_endpoints_in_mask(uint32_t mask); + /** * @fn usb2_setup_endpoints * @brief Setup the registers containing the address of the endpoint buffers. diff --git a/src/wch-ch56x-lib/USBDevice/usb2_utils.h b/src/wch-ch56x-lib/USBDevice/usb2_utils.h index 20ccf99..f75a3e1 100644 --- a/src/wch-ch56x-lib/USBDevice/usb2_utils.h +++ b/src/wch-ch56x-lib/USBDevice/usb2_utils.h @@ -73,24 +73,32 @@ usb2_get_rx_endpoint_ctrl_reg(uint8_t endp_num) return &R8_UEP0_RX_CTRL; break; case ENDP_1: + case ENDP_9: return &R8_UEP1_RX_CTRL; break; case ENDP_2: + case ENDP_10: return &R8_UEP2_RX_CTRL; break; case ENDP_3: + case ENDP_11: return &R8_UEP3_RX_CTRL; break; case ENDP_4: + case ENDP_8: + case ENDP_12: return &R8_UEP4_RX_CTRL; break; case ENDP_5: + case ENDP_13: return &R8_UEP5_RX_CTRL; break; case ENDP_6: + case ENDP_14: return &R8_UEP6_RX_CTRL; break; case ENDP_7: + case ENDP_15: return &R8_UEP7_RX_CTRL; break; default: @@ -114,24 +122,32 @@ usb2_get_tx_endpoint_ctrl_reg(uint8_t endp_num) return &R8_UEP0_TX_CTRL; break; case ENDP_1: + case ENDP_9: return &R8_UEP1_TX_CTRL; break; case ENDP_2: + case ENDP_10: return &R8_UEP2_TX_CTRL; break; case ENDP_3: + case ENDP_11: return &R8_UEP3_TX_CTRL; break; case ENDP_4: + case ENDP_8: + case ENDP_12: return &R8_UEP4_TX_CTRL; break; case ENDP_5: + case ENDP_13: return &R8_UEP5_TX_CTRL; break; case ENDP_6: + case ENDP_14: return &R8_UEP6_TX_CTRL; break; case ENDP_7: + case ENDP_15: return &R8_UEP7_TX_CTRL; break; default: @@ -155,24 +171,32 @@ usb2_get_tx_endpoint_addr_reg(uint8_t endp_num) return &R32_UEP0_RT_DMA; break; case ENDP_1: + case ENDP_9: return &R32_UEP1_TX_DMA; break; case ENDP_2: + case ENDP_10: return &R32_UEP2_TX_DMA; break; case ENDP_3: + case ENDP_11: return &R32_UEP3_TX_DMA; break; case ENDP_4: + case ENDP_8: + case ENDP_12: return &R32_UEP4_TX_DMA; break; case ENDP_5: + case ENDP_13: return &R32_UEP5_TX_DMA; break; case ENDP_6: + case ENDP_14: return &R32_UEP6_TX_DMA; break; case ENDP_7: + case ENDP_15: return &R32_UEP7_TX_DMA; break; default: @@ -196,24 +220,32 @@ usb2_get_rx_endpoint_addr_reg(uint8_t endp_num) return &R32_UEP0_RT_DMA; break; case ENDP_1: + case ENDP_9: return &R32_UEP1_RX_DMA; break; case ENDP_2: + case ENDP_10: return &R32_UEP2_RX_DMA; break; case ENDP_3: + case ENDP_11: return &R32_UEP3_RX_DMA; break; case ENDP_4: + case ENDP_8: + case ENDP_12: return &R32_UEP4_RX_DMA; break; case ENDP_5: + case ENDP_13: return &R32_UEP5_RX_DMA; break; case ENDP_6: + case ENDP_14: return &R32_UEP6_RX_DMA; break; case ENDP_7: + case ENDP_15: return &R32_UEP7_RX_DMA; break; default: @@ -238,24 +270,32 @@ usb2_get_tx_endpoint_len_reg(uint8_t endp_num) return &R16_UEP0_T_LEN; break; case ENDP_1: + case ENDP_9: return &R16_UEP1_T_LEN; break; case ENDP_2: + case ENDP_10: return &R16_UEP2_T_LEN; break; case ENDP_3: + case ENDP_11: return &R16_UEP3_T_LEN; break; case ENDP_4: + case ENDP_8: + case ENDP_12: return &R16_UEP4_T_LEN; break; case ENDP_5: + case ENDP_13: return &R16_UEP5_T_LEN; break; case ENDP_6: + case ENDP_14: return &R16_UEP6_T_LEN; break; case ENDP_7: + case ENDP_15: return &R16_UEP7_T_LEN; break; default: diff --git a/src/wch-ch56x-lib/USBDevice/usb30.c b/src/wch-ch56x-lib/USBDevice/usb30.c index 607b718..92d035f 100644 --- a/src/wch-ch56x-lib/USBDevice/usb30.c +++ b/src/wch-ch56x-lib/USBDevice/usb30.c @@ -37,43 +37,43 @@ usb_device_t* usb3_backend_current_device = &usb_device_0; /* Global Variable */ static volatile uint8_t tx_lmp_port = 0; static volatile uint8_t link_sta = 0; -static volatile uint16_t SetupLen = 0; -static volatile uint8_t SetupReqCode = 0; -static uint8_t* volatile pDescr; +volatile uint16_t SetupLen = 0; +volatile uint8_t SetupReqCode = 0; +uint8_t* volatile pDescr; static volatile bool usb2_fallback_enabled = false; // total length received -static volatile uint16_t ep1_rx_total_length = 0; -static volatile uint16_t ep2_rx_total_length = 0; -static volatile uint16_t ep3_rx_total_length = 0; -static volatile uint16_t ep4_rx_total_length = 0; -static volatile uint16_t ep5_rx_total_length = 0; -static volatile uint16_t ep6_rx_total_length = 0; -static volatile uint16_t ep7_rx_total_length = 0; +volatile uint16_t ep1_rx_total_length = 0; +volatile uint16_t ep2_rx_total_length = 0; +volatile uint16_t ep3_rx_total_length = 0; +volatile uint16_t ep4_rx_total_length = 0; +volatile uint16_t ep5_rx_total_length = 0; +volatile uint16_t ep6_rx_total_length = 0; +volatile uint16_t ep7_rx_total_length = 0; // how many burst the host was told it could send at most -static volatile uint8_t ep1_rx_previously_set_max_burst = 0; -static volatile uint8_t ep2_rx_previously_set_max_burst = 0; -static volatile uint8_t ep3_rx_previously_set_max_burst = 0; -static volatile uint8_t ep4_rx_previously_set_max_burst = 0; -static volatile uint8_t ep5_rx_previously_set_max_burst = 0; -static volatile uint8_t ep6_rx_previously_set_max_burst = 0; -static volatile uint8_t ep7_rx_previously_set_max_burst = 0; - -static volatile uint16_t ep1_tx_remaining_length = 0; -static volatile uint16_t ep2_tx_remaining_length = 0; -static volatile uint16_t ep3_tx_remaining_length = 0; -static volatile uint16_t ep4_tx_remaining_length = 0; -static volatile uint16_t ep5_tx_remaining_length = 0; -static volatile uint16_t ep6_tx_remaining_length = 0; -static volatile uint16_t ep7_tx_remaining_length = 0; -static volatile uint8_t ep1_tx_total_bursts = 0; -static volatile uint8_t ep2_tx_total_bursts = 0; -static volatile uint8_t ep3_tx_total_bursts = 0; -static volatile uint8_t ep4_tx_total_bursts = 0; -static volatile uint8_t ep5_tx_total_bursts = 0; -static volatile uint8_t ep6_tx_total_bursts = 0; -static volatile uint8_t ep7_tx_total_bursts = 0; +volatile uint8_t ep1_rx_previously_set_max_burst = 0; +volatile uint8_t ep2_rx_previously_set_max_burst = 0; +volatile uint8_t ep3_rx_previously_set_max_burst = 0; +volatile uint8_t ep4_rx_previously_set_max_burst = 0; +volatile uint8_t ep5_rx_previously_set_max_burst = 0; +volatile uint8_t ep6_rx_previously_set_max_burst = 0; +volatile uint8_t ep7_rx_previously_set_max_burst = 0; + +volatile uint16_t ep1_tx_remaining_length = 0; +volatile uint16_t ep2_tx_remaining_length = 0; +volatile uint16_t ep3_tx_remaining_length = 0; +volatile uint16_t ep4_tx_remaining_length = 0; +volatile uint16_t ep5_tx_remaining_length = 0; +volatile uint16_t ep6_tx_remaining_length = 0; +volatile uint16_t ep7_tx_remaining_length = 0; +volatile uint8_t ep1_tx_total_bursts = 0; +volatile uint8_t ep2_tx_total_bursts = 0; +volatile uint8_t ep3_tx_total_bursts = 0; +volatile uint8_t ep4_tx_total_bursts = 0; +volatile uint8_t ep5_tx_total_bursts = 0; +volatile uint8_t ep6_tx_total_bursts = 0; +volatile uint8_t ep7_tx_total_bursts = 0; /*************************************************************************** * @fn USB3_force @@ -302,154 +302,6 @@ void usb30_reinit_endpoints(void) usb30_init_endpoints(); } -/** - * @brief Get the current number of bytes received on endpoint - * @param endp endpoint number - * @return - */ -__attribute__((always_inline)) static inline volatile uint16_t* -usb30_get_rx_endpoint_total_length(uint8_t endp) -{ - switch (endp) - { - case ENDP_1: - return &ep1_rx_total_length; - break; - case ENDP_2: - return &ep2_rx_total_length; - break; - case ENDP_3: - return &ep3_rx_total_length; - break; - case ENDP_4: - return &ep4_rx_total_length; - break; - case ENDP_5: - return &ep5_rx_total_length; - break; - case ENDP_6: - return &ep6_rx_total_length; - break; - case ENDP_7: - return &ep7_rx_total_length; - break; - default: - return NULL; - } -} - -/** - * @brief In an OUT transfer, the device doesn't know what size data from the - * host will be. Since the device sets the max number of bursts it can receive, - * by having the max number of bursts, the number of actually received bursts - * can be computed. The host can send any number of packets between 1 and - * prev_set_max_burst, and we only get the number of remaining bursts, and the - * size of the last packet, so we need prev_set_max_burst to compute the number - * of full packets actually received. num_packets_received = prev_set_max_burst - * - remaining_number_of_packets - * @param endp endpoint number - */ -__attribute__((always_inline)) static inline volatile uint8_t* -usb30_get_rx_endpoint_prev_set_max_burst(uint8_t endp) -{ - switch (endp) - { - case ENDP_1: - return &ep1_rx_previously_set_max_burst; - break; - case ENDP_2: - return &ep2_rx_previously_set_max_burst; - break; - case ENDP_3: - return &ep3_rx_previously_set_max_burst; - break; - case ENDP_4: - return &ep4_rx_previously_set_max_burst; - break; - case ENDP_5: - return &ep5_rx_previously_set_max_burst; - break; - case ENDP_6: - return &ep6_rx_previously_set_max_burst; - break; - case ENDP_7: - return &ep7_rx_previously_set_max_burst; - break; - default: - return NULL; - } -} - -/** - * @brief Get the remaining bytes to be sent for endp - * @param endp endpoint number - */ -__attribute__((always_inline)) static inline volatile uint16_t* -usb30_get_tx_endpoint_remaining_length(uint8_t endp) -{ - switch (endp) - { - case ENDP_1: - return &ep1_tx_remaining_length; - break; - case ENDP_2: - return &ep2_tx_remaining_length; - break; - case ENDP_3: - return &ep3_tx_remaining_length; - break; - case ENDP_4: - return &ep4_tx_remaining_length; - break; - case ENDP_5: - return &ep5_tx_remaining_length; - break; - case ENDP_6: - return &ep6_tx_remaining_length; - break; - case ENDP_7: - return &ep7_tx_remaining_length; - break; - default: - return NULL; - } -} - -/** - * @brief Get the number of remaining packets to be sent for endp (including a - * packet of size less than max_packet_size) - */ -__attribute__((always_inline)) static inline volatile uint8_t* -usb30_get_tx_endpoint_total_bursts(uint8_t endp) -{ - switch (endp) - { - case ENDP_1: - return &ep1_tx_total_bursts; - break; - case ENDP_2: - return &ep2_tx_total_bursts; - break; - case ENDP_3: - return &ep3_tx_total_bursts; - break; - case ENDP_4: - return &ep4_tx_total_bursts; - break; - case ENDP_5: - return &ep5_tx_total_bursts; - break; - case ENDP_6: - return &ep6_tx_total_bursts; - break; - case ENDP_7: - return &ep7_tx_total_bursts; - break; - default: - return NULL; - } -} - /** * @fn usb30_standard_req_handler * @brief USB Device Mode Standard Request Command Handling @@ -1123,7 +975,7 @@ __attribute__((interrupt("WCH-Interrupt-fast"))) void USBSS_IRQHandler(void) uint32_t ep_in = (usb_status >> 0xc) & 1; if (ep != 0) { - if (ep_in != 0) + if (ep_in == 0) { switch (ep) { @@ -1134,7 +986,7 @@ __attribute__((interrupt("WCH-Interrupt-fast"))) void USBSS_IRQHandler(void) case 5: case 6: case 7: - usb30_ep_in_handler(ep); + usb30_ep_out_handler(ep); break; } return; @@ -1148,7 +1000,7 @@ __attribute__((interrupt("WCH-Interrupt-fast"))) void USBSS_IRQHandler(void) case 5: case 6: case 7: - usb30_ep_out_handler(ep); + usb30_ep_in_handler(ep); break; } return; diff --git a/src/wch-ch56x-lib/USBDevice/usb30.h b/src/wch-ch56x-lib/USBDevice/usb30.h index 389757c..e55e824 100644 --- a/src/wch-ch56x-lib/USBDevice/usb30.h +++ b/src/wch-ch56x-lib/USBDevice/usb30.h @@ -147,6 +147,190 @@ extern "C" { ENDPOINT_14_TX | ENDPOINT_14_RX | ENDPOINT_15_TX | ENDPOINT_15_RX)) extern usb_device_t* usb3_backend_current_device; +extern volatile uint16_t SetupLen; +extern volatile uint8_t SetupReqCode; +extern uint8_t* volatile pDescr; + +// total length received +extern volatile uint16_t ep1_rx_total_length; +extern volatile uint16_t ep2_rx_total_length; +extern volatile uint16_t ep3_rx_total_length; +extern volatile uint16_t ep4_rx_total_length; +extern volatile uint16_t ep5_rx_total_length; +extern volatile uint16_t ep6_rx_total_length; +extern volatile uint16_t ep7_rx_total_length; + +// how many burst the host was told it could send at most +extern volatile uint8_t ep1_rx_previously_set_max_burst; +extern volatile uint8_t ep2_rx_previously_set_max_burst; +extern volatile uint8_t ep3_rx_previously_set_max_burst; +extern volatile uint8_t ep4_rx_previously_set_max_burst; +extern volatile uint8_t ep5_rx_previously_set_max_burst; +extern volatile uint8_t ep6_rx_previously_set_max_burst; +extern volatile uint8_t ep7_rx_previously_set_max_burst; + +extern volatile uint16_t ep1_tx_remaining_length; +extern volatile uint16_t ep2_tx_remaining_length; +extern volatile uint16_t ep3_tx_remaining_length; +extern volatile uint16_t ep4_tx_remaining_length; +extern volatile uint16_t ep5_tx_remaining_length; +extern volatile uint16_t ep6_tx_remaining_length; +extern volatile uint16_t ep7_tx_remaining_length; +extern volatile uint8_t ep1_tx_total_bursts; +extern volatile uint8_t ep2_tx_total_bursts; +extern volatile uint8_t ep3_tx_total_bursts; +extern volatile uint8_t ep4_tx_total_bursts; +extern volatile uint8_t ep5_tx_total_bursts; +extern volatile uint8_t ep6_tx_total_bursts; +extern volatile uint8_t ep7_tx_total_bursts; + +/** + * @brief Get the current number of bytes received on endpoint + * @param endp endpoint number + * @return + */ +__attribute__((always_inline)) static inline volatile uint16_t* +usb30_get_rx_endpoint_total_length(uint8_t endp) +{ + switch (endp) + { + case ENDP_1: + return &ep1_rx_total_length; + break; + case ENDP_2: + return &ep2_rx_total_length; + break; + case ENDP_3: + return &ep3_rx_total_length; + break; + case ENDP_4: + return &ep4_rx_total_length; + break; + case ENDP_5: + return &ep5_rx_total_length; + break; + case ENDP_6: + return &ep6_rx_total_length; + break; + case ENDP_7: + return &ep7_rx_total_length; + break; + default: + return NULL; + } +} + +/** + * @brief In an OUT transfer, the device doesn't know what size data from the + * host will be. Since the device sets the max number of bursts it can receive, + * by having the max number of bursts, the number of actually received bursts + * can be computed. The host can send any number of packets between 1 and + * prev_set_max_burst, and we only get the number of remaining bursts, and the + * size of the last packet, so we need prev_set_max_burst to compute the number + * of full packets actually received. num_packets_received = prev_set_max_burst + * - remaining_number_of_packets + * @param endp endpoint number + */ +__attribute__((always_inline)) static inline volatile uint8_t* +usb30_get_rx_endpoint_prev_set_max_burst(uint8_t endp) +{ + switch (endp) + { + case ENDP_1: + return &ep1_rx_previously_set_max_burst; + break; + case ENDP_2: + return &ep2_rx_previously_set_max_burst; + break; + case ENDP_3: + return &ep3_rx_previously_set_max_burst; + break; + case ENDP_4: + return &ep4_rx_previously_set_max_burst; + break; + case ENDP_5: + return &ep5_rx_previously_set_max_burst; + break; + case ENDP_6: + return &ep6_rx_previously_set_max_burst; + break; + case ENDP_7: + return &ep7_rx_previously_set_max_burst; + break; + default: + return NULL; + } +} + +/** + * @brief Get the remaining bytes to be sent for endp + * @param endp endpoint number + */ +__attribute__((always_inline)) static inline volatile uint16_t* +usb30_get_tx_endpoint_remaining_length(uint8_t endp) +{ + switch (endp) + { + case ENDP_1: + return &ep1_tx_remaining_length; + break; + case ENDP_2: + return &ep2_tx_remaining_length; + break; + case ENDP_3: + return &ep3_tx_remaining_length; + break; + case ENDP_4: + return &ep4_tx_remaining_length; + break; + case ENDP_5: + return &ep5_tx_remaining_length; + break; + case ENDP_6: + return &ep6_tx_remaining_length; + break; + case ENDP_7: + return &ep7_tx_remaining_length; + break; + default: + return NULL; + } +} + +/** + * @brief Get the number of remaining packets to be sent for endp (including a + * packet of size less than max_packet_size) + */ +__attribute__((always_inline)) static inline volatile uint8_t* +usb30_get_tx_endpoint_total_bursts(uint8_t endp) +{ + switch (endp) + { + case ENDP_1: + return &ep1_tx_total_bursts; + break; + case ENDP_2: + return &ep2_tx_total_bursts; + break; + case ENDP_3: + return &ep3_tx_total_bursts; + break; + case ENDP_4: + return &ep4_tx_total_bursts; + break; + case ENDP_5: + return &ep5_tx_total_bursts; + break; + case ENDP_6: + return &ep6_tx_total_bursts; + break; + case ENDP_7: + return &ep7_tx_total_bursts; + break; + default: + return NULL; + } +} /** * @brief Enable USB30 device but without downgrade to USB2 diff --git a/src/wch-ch56x-lib/USBDevice/usb_device.c b/src/wch-ch56x-lib/USBDevice/usb_device.c index 7d16a27..6512c2d 100644 --- a/src/wch-ch56x-lib/USBDevice/usb_device.c +++ b/src/wch-ch56x-lib/USBDevice/usb_device.c @@ -44,12 +44,25 @@ void _default_nak_callback(uint8_t ep_num) {} */ usb_device_t usb_device_0 = { .speed = USB2_HIGHSPEED, + .endpoint_mask = 0, + .current_config = 0, + .current_interface = 0, + .addr = 0, + .state = DETACHED, .endpoints = { .endp0_user_handled_control_request = _default_endp0_user_handled_control_request, .endp0_passthrough_setup_callback = _default_endp0_passthrough_setup_callback, .tx_complete = { _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, _default_endp_tx_complete, _default_endp_tx_complete, _default_endp_tx_complete, @@ -58,6 +71,14 @@ usb_device_t usb_device_0 = { _default_endp_tx_complete, _default_endp_tx_complete }, .rx_callback = { _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, _default_endp_rx_callback, _default_endp_rx_callback, _default_endp_rx_callback, @@ -70,12 +91,25 @@ usb_device_t usb_device_0 = { usb_device_t usb_device_1 = { .speed = USB2_HIGHSPEED, + .endpoint_mask = 0, + .current_config = 0, + .current_interface = 0, + .addr = 0, + .state = DETACHED, .endpoints = { .endp0_user_handled_control_request = _default_endp0_user_handled_control_request, .endp0_passthrough_setup_callback = _default_endp0_passthrough_setup_callback, .tx_complete = { _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, + _default_endp_tx_complete, _default_endp_tx_complete, _default_endp_tx_complete, _default_endp_tx_complete, @@ -84,6 +118,14 @@ usb_device_t usb_device_1 = { _default_endp_tx_complete, _default_endp_tx_complete }, .rx_callback = { _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, + _default_endp_rx_callback, _default_endp_rx_callback, _default_endp_rx_callback, _default_endp_rx_callback, @@ -154,8 +196,10 @@ void endp_rx_set_state(usb_device_t* usb_device, uint8_t endp_num, uint8_t state if (usb_device->speed == USB30_SUPERSPEED) ; // not implemented // usb3_endpoints_backend_handled.usb3_endp_rx_set_state_callback(endp_num); - else + else if (usb_device->speed == USB2_HIGHSPEED) + { usb2_endpoints_backend_handled.usb2_endp_rx_set_state_callback(endp_num); + } } } diff --git a/src/wch-ch56x-lib/USBDevice/usb_endpoints.h b/src/wch-ch56x-lib/USBDevice/usb_endpoints.h index 71263e2..51dfc9c 100644 --- a/src/wch-ch56x-lib/USBDevice/usb_endpoints.h +++ b/src/wch-ch56x-lib/USBDevice/usb_endpoints.h @@ -42,8 +42,8 @@ typedef struct USB_ENDPOINT_T */ typedef struct usb_endpoints_t { - volatile USB_ENDPOINT tx[8]; - volatile USB_ENDPOINT rx[8]; + volatile USB_ENDPOINT tx[16]; + volatile USB_ENDPOINT rx[16]; /** * @brief Process requests unhandled by the backend. Must return 0xffff if it @@ -64,7 +64,7 @@ typedef struct usb_endpoints_t * @param status The status of the transaction, sent by the host (ACK if all * went well) */ - void (*tx_complete[8])(TRANSACTION_STATUS status); + void (*tx_complete[16])(TRANSACTION_STATUS status); /** * @brief rx_callback[0] is called by the USB2 backend in passthrough mode after receiving an @@ -78,7 +78,7 @@ typedef struct usb_endpoints_t * @return new state of endpoint response (ACK 0x00, NAK 0X02, STALL 0X03). * This will set the response for the next transfer (not this one). */ - uint8_t (*rx_callback[8])(uint8_t* const ptr, uint16_t size); + uint8_t (*rx_callback[16])(uint8_t* const ptr, uint16_t size); void (*nak_callback)(uint8_t ep_num); diff --git a/src/wch-ch56x-lib/USBDevice/usb_types.h b/src/wch-ch56x-lib/USBDevice/usb_types.h index 4e4edad..c7f8eef 100644 --- a/src/wch-ch56x-lib/USBDevice/usb_types.h +++ b/src/wch-ch56x-lib/USBDevice/usb_types.h @@ -94,6 +94,14 @@ typedef enum #define ENDP_5 0x05 #define ENDP_6 0x06 #define ENDP_7 0x07 +#define ENDP_8 0x08 +#define ENDP_9 0x09 +#define ENDP_10 0x0a +#define ENDP_11 0x0b +#define ENDP_12 0x0c +#define ENDP_13 0x0d +#define ENDP_14 0x0e +#define ENDP_15 0x0f #define ENDP_STATE_ACK 0x00 #define ENDP_STATE_NAK 0x02 diff --git a/tests/scripts/requirements.txt b/tests/scripts/requirements.txt index 7e2effa..20362f9 100644 --- a/tests/scripts/requirements.txt +++ b/tests/scripts/requirements.txt @@ -1 +1,2 @@ +libusb1==3.1.0 pyusb==1.2.1 diff --git a/tests/scripts/test_hspi_serdes.py b/tests/scripts/test_hspi_serdes.py index eab75d6..d5a88d7 100644 --- a/tests/scripts/test_hspi_serdes.py +++ b/tests/scripts/test_hspi_serdes.py @@ -51,8 +51,8 @@ def check(array_in): intf, find_all=True, # match the first OUT endpoint - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN)) assert ep_in is not None diff --git a/tests/scripts/test_loopback.py b/tests/scripts/test_loopback.py index 4cc0ff2..9df1a1b 100644 --- a/tests/scripts/test_loopback.py +++ b/tests/scripts/test_loopback.py @@ -21,12 +21,12 @@ def check(byte_array, packet_size, reference_array): """ Check the received buffers against what has been sent, to check for integrity """ - for i in range(len(byte_array) // packet_size): - packet_in = byte_array[i * packet_size:i*packet_size + packet_size] - packet_ref = reference_array[i * - packet_size:i*packet_size + packet_size] + for j in range(len(byte_array) // packet_size): + packet_in = byte_array[j * packet_size:j*packet_size + packet_size] + packet_ref = reference_array[j * + packet_size:j*packet_size + packet_size] if packet_in != packet_ref: - print(f"Error at {i} ") + print(f"Error at {j} ") print(packet_in) print(packet_ref) return False @@ -57,8 +57,13 @@ def send_next_packet(head, ep_in, ep_out, endp_max_packet_size, buffer_in, buffe parser = argparse.ArgumentParser() parser.add_argument("--device_num", default=0, help="In case multiple devices are found, select the index of the device that will be used.", type=int) + parser.add_argument( + "--zlp", help="Only send packets of size 0", action='store_true') args = parser.parse_args() + if args.zlp: + BUFFER_SIZE = 0 + # find our device devs = usb.core.find(idVendor=0x16c0, idProduct=0x27d8, find_all=True) @@ -87,16 +92,16 @@ def send_next_packet(head, ep_in, ep_out, endp_max_packet_size, buffer_in, buffe intf, find_all=True, # match the first OUT endpoint - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN)) ep_out = list(usb.util.find_descriptor( intf, # match the first OUT endpoint find_all=True, - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)) assert ep_in is not None @@ -109,9 +114,9 @@ def send_next_packet(head, ep_in, ep_out, endp_max_packet_size, buffer_in, buffe SUCCESS = True fails = [] - for i in range(len(ep_in)): + for i, (current_ep_in, current_ep_out) in enumerate(zip(ep_in, ep_out)): TOTAL_TIME_NS = 0 - print(f"EP {i+1}") + print(f"EP {current_ep_in.bEndpointAddress & 0x7f}") try: endp_max_packet_size = ENDP_BURST_SIZE * ep_out[i].wMaxPacketSize buffer_out = array.array( @@ -122,13 +127,19 @@ def send_next_packet(head, ep_in, ep_out, endp_max_packet_size, buffer_in, buffe head = 0 num_sent = 0 total_to_send = len(buffer_out) - while head < total_to_send: - try: - head = send_next_packet( - head, ep_in[i], ep_out[i], endp_max_packet_size, buffer_in, buffer_out) - sys.stdout.write(f"\r{100. * head/total_to_send} % sent") - except usb.core.USBTimeoutError: # HydraUSB3 tends to timeout when handling USB3 - print("error timeout, retrying ! ") + + if BUFFER_SIZE == 0: + send_next_packet( + head, current_ep_in, current_ep_out, endp_max_packet_size, buffer_in, buffer_out) + else: + while head < total_to_send: + try: + head = send_next_packet( + head, current_ep_in, current_ep_out, endp_max_packet_size, buffer_in, buffer_out) + sys.stdout.write( + f"\r{100. * head/total_to_send} % sent") + except usb.core.USBTimeoutError: # HydraUSB3 tends to timeout when handling USB3 + print("error timeout, retrying ! ") STOP = time.time_ns() sys.stdout.write("\r") @@ -139,12 +150,12 @@ def send_next_packet(head, ep_in, ep_out, endp_max_packet_size, buffer_in, buffe f"Success ! Transfer rate with only transfer {len(buffer_in) / ((TOTAL_TIME_NS) * 1e-9) * 1e-6} MB/s") else: print("Error") - fails.append(i) + fails.append(current_ep_in.bEndpointAddress & 0x7f) except: - fails.append(i) + fails.append(current_ep_in.bEndpointAddress & 0x7f) print( - f"There have been {len(fails)} fails. Endpoints {[ep + 1 for ep in fails]} failed ") + f"There have been {len(fails)} fails. Endpoints {fails} failed ") if len(fails) == 0: print("Test successful ! ") diff --git a/tests/scripts/test_loopback_randomize_packetsize.py b/tests/scripts/test_loopback_randomize_packetsize.py index 03113db..5fd49f8 100644 --- a/tests/scripts/test_loopback_randomize_packetsize.py +++ b/tests/scripts/test_loopback_randomize_packetsize.py @@ -85,16 +85,16 @@ def send_next_packet(head, ep_in, ep_out, endp_max_packet_size, buffer_in, buffe intf, find_all=True, # match the first OUT endpoint - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN)) ep_out = list(usb.util.find_descriptor( intf, # match the first OUT endpoint find_all=True, - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)) assert ep_in is not None diff --git a/tests/scripts/test_speedtest.py b/tests/scripts/test_speedtest.py index c0c9772..1f32b50 100644 --- a/tests/scripts/test_speedtest.py +++ b/tests/scripts/test_speedtest.py @@ -61,15 +61,15 @@ ep_in = usb.util.find_descriptor( intf, # match the first OUT endpoint - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN) ep_out = usb.util.find_descriptor( intf, # match the first OUT endpoint - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT) assert ep_in is not None diff --git a/tests/scripts/test_speedtest_one_by_one.py b/tests/scripts/test_speedtest_one_by_one.py index 3f54b02..7d8fb92 100644 --- a/tests/scripts/test_speedtest_one_by_one.py +++ b/tests/scripts/test_speedtest_one_by_one.py @@ -64,15 +64,15 @@ ep_in = usb.util.find_descriptor( intf, # match the first OUT endpoint - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN) ep_out = usb.util.find_descriptor( intf, # match the first OUT endpoint - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT) assert ep_in is not None diff --git a/tests/scripts/test_stress.py b/tests/scripts/test_stress.py new file mode 100644 index 0000000..ebe8415 --- /dev/null +++ b/tests/scripts/test_stress.py @@ -0,0 +1,347 @@ +# +# This file is based on Facedancer. +# +# BSD-3-Clause license +# Copyright (c) 2024 Quarkslab +# Copyright (c) 2019 Katherine J. Temkin +# Copyright (c) 2018 Dominic Spill +# Copyright (c) 2018 Travis Goodspeed + +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. + +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +import logging +import random +import unittest +import usb1 + +# How many iterations to run for stress test +ITERATIONS = 20000 + +logging.basicConfig(level=logging.DEBUG) + +# - helpers ------------------------------------------------------------------- + + +def generate_data(length): + return bytes([(byte % 256) for byte in range(length)]) + +# Transfer length for tests + + +def test_transfer_length(): + return random.randrange(1, MAX_TRANSFER_LENGTH) + + +VENDOR_ID = 0x1209 +PRODUCT_ID = 0x0001 + +OUT_ENDPOINT = 0x01 +IN_ENDPOINT = 0x82 + +# This is constrained by pygreat::comms_backends::usb1::LIBGREAT_MAX_COMMAND_SIZE +# and is board dependent. +MAX_TRANSFER_LENGTH = 768 + + +class FacedancerTestCase(unittest.TestCase): + + # - life-cycle ------------------------------------------------------------ + + @classmethod + def setUpClass(cls): + logging.basicConfig(level=logging.INFO) + cls.context = usb1.USBContext().open() + cls.device = cls.context.getByVendorIDAndProductID( + VENDOR_ID, PRODUCT_ID) + cls.device_handle = cls.device.open() + if cls.device_handle is None: + raise Exception("device not found") + cls.device_handle.claimInterface(0) + cls.device_speed = cls.device.getDeviceSpeed() + + @classmethod + def tearDownClass(cls): + cls.context.close() + + # - transfers ------------------------------------------------------------- + + def bulk_out_transfer(self, data): + logging.debug("Testing bulk OUT endpoint") + response = self.device_handle.bulkWrite( + endpoint=0x01, + data=data, + timeout=1000, + ) + logging.debug("sent %d bytes\n", response) + return response + + def bulk_in_transfer(self, length): + logging.debug("Testing bulk IN endpoint") + response = self.device_handle.bulkRead( + endpoint=0x82, + length=length, + timeout=1000, + ) + logging.debug( + "[host] received %d bytes from bulk endpoint", len(response)) + return response + + def interrupt_out_transfer(self, data): + logging.debug("Testing interrupt OUT endpoint") + response = self.device_handle.interruptWrite( + endpoint=0x01, + data=data, + timeout=0 if self.device_speed == usb1.SPEED_LOW else 1000, + ) + logging.debug("sent %d bytes\n", response) + return response + + def interrupt_in_transfer(self, length): + logging.debug("Testing interrupt IN endpoint") + response = self.device_handle.interruptRead( + endpoint=0x82, + length=length, + timeout=0 if self.device_speed == usb1.SPEED_LOW else 1000, + ) + logging.debug( + "[host] received %d bytes from interrupt endpoint", len(response)) + return response + + def control_out_transfer(self, data): + logging.debug("Testing OUT control transfer") + hi, lo = len(data).to_bytes(2, byteorder="big") + response = self.device_handle.controlWrite( + request_type=usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, + request=10, + index=hi, + value=lo, + data=data, + timeout=0 if self.device_speed == usb1.SPEED_LOW else 1000, + ) + logging.debug("sent %d bytes\n", response) + return response + + def control_in_transfer(self, length): + logging.debug("Testing IN control transfer") + hi, lo = length.to_bytes(2, byteorder="big") + response = self.device_handle.controlRead( + request_type=usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, + request=20, + index=hi, + value=lo, + length=length, + timeout=0 if self.device_speed == usb1.SPEED_LOW else 1000, + ) + logging.debug( + "[host] received %d bytes from control endpoint", len(response)) + return response + + # - device control ------------------------------------------------------------ + + def set_in_transfer_length(self, length): + hi, lo = length.to_bytes(2, byteorder="big") + logging.debug("Setting transfer length to %d bytes", length) + response = self.device_handle.controlWrite( + request_type=usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, + request=1, + index=hi, + value=lo, + data=[], + timeout=0 if self.device_speed == usb1.SPEED_LOW else 1000, + ) + return response + + def get_last_out_transfer_data(self): + logging.debug("Getting last OUT transfer data") + response = self.device_handle.controlRead( + request_type=usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, + request=2, + index=0, + value=0, + length=MAX_TRANSFER_LENGTH, + timeout=0 if self.device_speed == usb1.SPEED_LOW else 1000, + ) + logging.debug( + "[host] sent %d bytes with last out transfer", len(response)) + return response + + def reset_device_state(self): + logging.debug(f"Resetting stress test device state") + response = self.device_handle.controlWrite( + request_type=usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, + request=3, + index=0, + value=0, + data=[], + timeout=0 if self.device_speed == usb1.SPEED_LOW else 1000, + ) + return response + + +# Run tests in random order +# +# Note: if you can't reproduce a failed run check the order of the +# tests in the failed run! +unittest.TestLoader.sortTestMethodsUsing = lambda self, a, b: random.choice([ + 1, 0, -1]) + + +class TestTransfers(FacedancerTestCase): + """Transfer tests for test device""" + + # - life-cycle ------------------------------------------------------------ + + def setUp(self): + # reset test device state between tests + self.reset_device_state() + + # - transfer checks ------------------------------------------------------- + + def check_out_transfer(self, length, sent_data, bytes_sent): + # request a copy of the received data to compare against + received_data = self.get_last_out_transfer_data() + + # did we send the right amount of data? + self.assertEqual(bytes_sent, length) + + # does the length of the sent data match the length of the received data? + self.assertEqual(len(sent_data), len(received_data)) + + # does the content of the sent data match the content of the received data? + self.assertEqual(sent_data, received_data) + + def check_in_transfer(self, length, received_data): + # generate a set of data to compare against + compare_data = generate_data(length) + + # did we receive the right amount of data? + self.assertEqual(len(received_data), length) + + # does the content of the received data match the content of our comparison data? + self.assertEqual(received_data, compare_data) + + # - tests ----------------------------------------------------------------- + + def test_bulk_out_transfer(self): + # generate test data + length = test_transfer_length() + data = generate_data(length) + + # perform Bulk OUT transfer + bytes_sent = self.bulk_out_transfer(data) + + # check transfer + self.check_out_transfer(length, data, bytes_sent) + + def test_bulk_in_transfer(self): + # set desired IN transfer length + length = test_transfer_length() + self.set_in_transfer_length(length) + + # perform Bulk IN transfer + received_data = self.bulk_in_transfer(length) + + # check transfer + self.check_in_transfer(length, received_data) + + def test_interrupt_out_transfer(self): + # generate test data + length = test_transfer_length() + data = generate_data(length) + + # perform Interrupt OUT transfer + bytes_sent = self.interrupt_out_transfer(data) + + # check transfer + self.check_out_transfer(length, data, bytes_sent) + + def test_interrupt_in_transfer(self): + # set desired IN transfer length + length = test_transfer_length() + self.set_in_transfer_length(length) + + # perform Bulk IN transfer + received_data = self.interrupt_in_transfer(length) + + # check transfer + self.check_in_transfer(length, received_data) + + def test_control_out_transfer(self): + # generate test data + length = test_transfer_length() + data = generate_data(length) + + # perform Control OUT transfer + bytes_sent = self.control_out_transfer(data) + + # check transfer + self.check_out_transfer(length, data, bytes_sent) + + def test_control_in_transfer(self): + # set desired IN transfer length + length = test_transfer_length() + self.set_in_transfer_length(length) + + # perform Bulk IN transfer + received_data = self.control_in_transfer(length) + + # check transfer + self.check_in_transfer(length, received_data) + + +def highly_stressed_edition(): + available_tests = [] + with usb1.USBContext() as context: + device = context.getByVendorIDAndProductID(VENDOR_ID, PRODUCT_ID) + # No BULK endpoint in LS + if device.getDeviceSpeed() == usb1.SPEED_LOW: + available_tests = [ + "test_interrupt_out_transfer", + "test_interrupt_in_transfer", + "test_control_out_transfer", + "test_control_in_transfer", + ] + else: + available_tests = [ + "test_bulk_out_transfer", + "test_bulk_in_transfer", + "test_control_out_transfer", + "test_control_in_transfer", + ] + + tests = [random.choice(available_tests) for _ in range(ITERATIONS)] + + suite = unittest.TestSuite() + for test in tests: + suite.addTest(TestTransfers(test)) + + runner = unittest.TextTestRunner(failfast=True) + runner.run(suite) + + +if __name__ == "__main__": + highly_stressed_edition() diff --git a/tests/test_firmware_usb_loopback/User/main.c b/tests/test_firmware_usb_loopback/User/main.c index 19d8670..dad58dc 100644 --- a/tests/test_firmware_usb_loopback/User/main.c +++ b/tests/test_firmware_usb_loopback/User/main.c @@ -27,6 +27,7 @@ limitations under the License. #pragma GCC diagnostic pop #include "usb2_device_descriptors.h" +#include "usb2_device_descriptors_alt_endpoints.h" #include "usb3_device_descriptors.h" #include "usb_device.h" #include "wch-ch56x-lib/logging/logging.h" @@ -39,25 +40,13 @@ limitations under the License. /* System clock / MCU frequency in Hz (lowest possible speed 15MHz) */ #define FREQ_SYS (120000000) -void endp1_tx_complete(TRANSACTION_STATUS status); -void endp1_tx_complete(TRANSACTION_STATUS status) {} -void endp2_tx_complete(TRANSACTION_STATUS status); -void endp2_tx_complete(TRANSACTION_STATUS status) {} -void endp3_tx_complete(TRANSACTION_STATUS status); -void endp3_tx_complete(TRANSACTION_STATUS status) {} -void endp4_tx_complete(TRANSACTION_STATUS status); -void endp4_tx_complete(TRANSACTION_STATUS status) {} -void endp5_tx_complete(TRANSACTION_STATUS status); -void endp5_tx_complete(TRANSACTION_STATUS status) {} -void endp6_tx_complete(TRANSACTION_STATUS status); -void endp6_tx_complete(TRANSACTION_STATUS status) {} -void endp7_tx_complete(TRANSACTION_STATUS status); -void endp7_tx_complete(TRANSACTION_STATUS status) {} +void endp_tx_complete(TRANSACTION_STATUS status); +void endp_tx_complete(TRANSACTION_STATUS status) {} uint8_t endp1_rx_callback(uint8_t* const ptr, uint16_t size); uint8_t endp1_rx_callback(uint8_t* const ptr, uint16_t size) { - endp_tx_set_new_buffer(&usb_device_0, 1, endp1_rx_buffer, size); // loop-back + endp_tx_set_new_buffer(&usb_device_0, 1, usb_device_0.endpoints.rx[1].buffer, size); // loop-back LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp1 \r\n", size); return 0x00; @@ -66,7 +55,7 @@ uint8_t endp1_rx_callback(uint8_t* const ptr, uint16_t size) uint8_t endp2_rx_callback(uint8_t* const ptr, uint16_t size); uint8_t endp2_rx_callback(uint8_t* const ptr, uint16_t size) { - endp_tx_set_new_buffer(&usb_device_0, 2, endp2_rx_buffer, size); // loop-back + endp_tx_set_new_buffer(&usb_device_0, 2, usb_device_0.endpoints.rx[2].buffer, size); // loop-back LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp2 \r\n", size); return 0x00; @@ -75,7 +64,7 @@ uint8_t endp2_rx_callback(uint8_t* const ptr, uint16_t size) uint8_t endp3_rx_callback(uint8_t* const ptr, uint16_t size); uint8_t endp3_rx_callback(uint8_t* const ptr, uint16_t size) { - endp_tx_set_new_buffer(&usb_device_0, 3, endp3_rx_buffer, size); // loop-back + endp_tx_set_new_buffer(&usb_device_0, 3, usb_device_0.endpoints.rx[3].buffer, size); // loop-back LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp3 \r\n", size); return 0x00; @@ -84,7 +73,7 @@ uint8_t endp3_rx_callback(uint8_t* const ptr, uint16_t size) uint8_t endp4_rx_callback(uint8_t* const ptr, uint16_t size); uint8_t endp4_rx_callback(uint8_t* const ptr, uint16_t size) { - endp_tx_set_new_buffer(&usb_device_0, 4, endp4_rx_buffer, size); // loop-back + endp_tx_set_new_buffer(&usb_device_0, 4, usb_device_0.endpoints.rx[4].buffer, size); // loop-back LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp4 \r\n", size); return 0x00; @@ -93,7 +82,7 @@ uint8_t endp4_rx_callback(uint8_t* const ptr, uint16_t size) uint8_t endp5_rx_callback(uint8_t* const ptr, uint16_t size); uint8_t endp5_rx_callback(uint8_t* const ptr, uint16_t size) { - endp_tx_set_new_buffer(&usb_device_0, 5, endp5_rx_buffer, size); // loop-back + endp_tx_set_new_buffer(&usb_device_0, 5, usb_device_0.endpoints.rx[5].buffer, size); // loop-back LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp5 \r\n", size); return 0x00; @@ -102,7 +91,7 @@ uint8_t endp5_rx_callback(uint8_t* const ptr, uint16_t size) uint8_t endp6_rx_callback(uint8_t* const ptr, uint16_t size); uint8_t endp6_rx_callback(uint8_t* const ptr, uint16_t size) { - endp_tx_set_new_buffer(&usb_device_0, 6, endp6_rx_buffer, size); // loop-back + endp_tx_set_new_buffer(&usb_device_0, 6, usb_device_0.endpoints.rx[6].buffer, size); // loop-back LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp6 \r\n", size); return 0x00; @@ -111,12 +100,84 @@ uint8_t endp6_rx_callback(uint8_t* const ptr, uint16_t size) uint8_t endp7_rx_callback(uint8_t* const ptr, uint16_t size); uint8_t endp7_rx_callback(uint8_t* const ptr, uint16_t size) { - endp_tx_set_new_buffer(&usb_device_0, 7, endp7_rx_buffer, size); // loop-back + endp_tx_set_new_buffer(&usb_device_0, 7, usb_device_0.endpoints.rx[7].buffer, size); // loop-back LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp7 \r\n", size); return 0x00; } +uint8_t endp8_rx_callback(uint8_t* const ptr, uint16_t size); +uint8_t endp8_rx_callback(uint8_t* const ptr, uint16_t size) +{ + endp_tx_set_new_buffer(&usb_device_0, 8, usb_device_0.endpoints.rx[8].buffer, size); // loop-back + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp8 \r\n", + size); + return 0x00; +} + +uint8_t endp9_rx_callback(uint8_t* const ptr, uint16_t size); +uint8_t endp9_rx_callback(uint8_t* const ptr, uint16_t size) +{ + endp_tx_set_new_buffer(&usb_device_0, 9, usb_device_0.endpoints.rx[9].buffer, size); // loop-back + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp9 \r\n", + size); + return 0x00; +} + +uint8_t endp10_rx_callback(uint8_t* const ptr, uint16_t size); +uint8_t endp10_rx_callback(uint8_t* const ptr, uint16_t size) +{ + endp_tx_set_new_buffer(&usb_device_0, 10, usb_device_0.endpoints.rx[10].buffer, size); // loop-back + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp11 \r\n", + size); + return 0x00; +} + +uint8_t endp11_rx_callback(uint8_t* const ptr, uint16_t size); +uint8_t endp11_rx_callback(uint8_t* const ptr, uint16_t size) +{ + endp_tx_set_new_buffer(&usb_device_0, 11, usb_device_0.endpoints.rx[11].buffer, size); // loop-back + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp12 \r\n", + size); + return 0x00; +} + +uint8_t endp12_rx_callback(uint8_t* const ptr, uint16_t size); +uint8_t endp12_rx_callback(uint8_t* const ptr, uint16_t size) +{ + endp_tx_set_new_buffer(&usb_device_0, 12, usb_device_0.endpoints.rx[12].buffer, size); // loop-back + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp12 \r\n", + size); + return 0x00; +} + +uint8_t endp13_rx_callback(uint8_t* const ptr, uint16_t size); +uint8_t endp13_rx_callback(uint8_t* const ptr, uint16_t size) +{ + endp_tx_set_new_buffer(&usb_device_0, 13, usb_device_0.endpoints.rx[13].buffer, size); // loop-back + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp13 \r\n", + size); + return 0x00; +} + +uint8_t endp14_rx_callback(uint8_t* const ptr, uint16_t size); +uint8_t endp14_rx_callback(uint8_t* const ptr, uint16_t size) +{ + endp_tx_set_new_buffer(&usb_device_0, 14, usb_device_0.endpoints.rx[14].buffer, size); // loop-back + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp14 \r\n", + size); + return 0x00; +} + +uint8_t endp15_rx_callback(uint8_t* const ptr, uint16_t size); +uint8_t endp15_rx_callback(uint8_t* const ptr, uint16_t size) +{ + endp_tx_set_new_buffer(&usb_device_0, 15, usb_device_0.endpoints.rx[15].buffer, size); // loop-back + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "Received something of size %d on endp15 \r\n", + size); + return 0x00; +} + /* Blink time in ms */ #define BLINK_FAST (50) // Blink LED each 100ms (50*2) #define BLINK_USB3 (250) // Blink LED each 500ms (250*2) @@ -157,13 +218,20 @@ int main() usb_device_0.endpoints.endp0_user_handled_control_request = endp0_user_handled_control_request; usb_device_0.endpoints.endp0_passthrough_setup_callback = endp0_passthrough_setup_callback; - usb_device_0.endpoints.tx_complete[1] = endp1_tx_complete; - usb_device_0.endpoints.tx_complete[2] = endp2_tx_complete; - usb_device_0.endpoints.tx_complete[3] = endp3_tx_complete; - usb_device_0.endpoints.tx_complete[4] = endp4_tx_complete; - usb_device_0.endpoints.tx_complete[5] = endp5_tx_complete; - usb_device_0.endpoints.tx_complete[6] = endp6_tx_complete; - usb_device_0.endpoints.tx_complete[7] = endp7_tx_complete; + usb_device_0.endpoints.tx_complete[1] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[2] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[3] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[4] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[5] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[6] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[8] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[9] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[10] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[11] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[12] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[13] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[14] = endp_tx_complete; + usb_device_0.endpoints.tx_complete[15] = endp_tx_complete; usb_device_0.endpoints.rx_callback[1] = endp1_rx_callback; usb_device_0.endpoints.rx_callback[2] = endp2_rx_callback; usb_device_0.endpoints.rx_callback[3] = endp3_rx_callback; @@ -171,37 +239,61 @@ int main() usb_device_0.endpoints.rx_callback[5] = endp5_rx_callback; usb_device_0.endpoints.rx_callback[6] = endp6_rx_callback; usb_device_0.endpoints.rx_callback[7] = endp7_rx_callback; + usb_device_0.endpoints.rx_callback[8] = endp8_rx_callback; + usb_device_0.endpoints.rx_callback[9] = endp9_rx_callback; + usb_device_0.endpoints.rx_callback[10] = endp10_rx_callback; + usb_device_0.endpoints.rx_callback[11] = endp11_rx_callback; + usb_device_0.endpoints.rx_callback[13] = endp13_rx_callback; + usb_device_0.endpoints.rx_callback[14] = endp14_rx_callback; + usb_device_0.endpoints.rx_callback[15] = endp15_rx_callback; usb2_user_handled.usb2_device_handle_bus_reset = &usb2_device_handle_bus_reset; // Finish initializing the descriptor parameters - init_usb3_descriptors(); - init_usb2_descriptors(); + init_string_descriptors(); // Set the USB device parameters - usb_device_set_usb3_device_descriptor(&usb_device_0, &usb3_descriptors.usb_device_descr); - usb_device_set_usb2_device_descriptor(&usb_device_0, &usb2_descriptors.usb_device_descr); - usb_device_set_usb3_config_descriptors(&usb_device_0, usb3_device_configs); - usb_device_set_usb2_config_descriptors(&usb_device_0, usb2_device_configs); - usb_device_set_bos_descriptor(&usb_device_0, &usb3_descriptors.capabilities.usb_bos_descr); + usb_device_set_string_descriptors(&usb_device_0, device_string_descriptors); - usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_1_RX | ENDPOINT_1_TX | ENDPOINT_2_RX | - ENDPOINT_2_TX | ENDPOINT_3_RX | ENDPOINT_3_TX | - ENDPOINT_4_RX | ENDPOINT_4_TX | ENDPOINT_5_RX | - ENDPOINT_5_TX | ENDPOINT_6_RX | ENDPOINT_6_TX | - ENDPOINT_7_RX | ENDPOINT_7_TX); init_endpoints(); if (!bsp_ubtn()) { + init_usb3_descriptors(); + usb_device_set_usb3_device_descriptor(&usb_device_0, &usb3_descriptors.usb_device_descr); + usb_device_set_usb3_config_descriptors(&usb_device_0, usb3_device_configs); + usb_device_set_bos_descriptor(&usb_device_0, &usb3_descriptors.capabilities.usb_bos_descr); + usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_1_RX | ENDPOINT_1_TX | ENDPOINT_2_RX | + ENDPOINT_2_TX | ENDPOINT_3_RX | ENDPOINT_3_TX | + ENDPOINT_4_RX | ENDPOINT_4_TX | ENDPOINT_5_RX | + ENDPOINT_5_TX | ENDPOINT_6_RX | ENDPOINT_6_TX | + ENDPOINT_7_RX | ENDPOINT_7_TX); usb_device_0.speed = USB30_SUPERSPEED; usb30_device_init(false); } else { + // // uncomment to test other supported endpoint numbers + // // NOTE : some endpoints numbers are incompatible and can't be used at the same time + // init_usb2_descriptors_alt_endpoints(); + // usb_device_set_usb2_device_descriptor(&usb_device_0, &usb2_descriptors_alt_endpoints.usb_device_descr); + // usb_device_set_usb2_config_descriptors(&usb_device_0, usb2_device_configs_alt_endpoints); + // usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_9_RX | ENDPOINT_9_TX | ENDPOINT_10_RX | + // ENDPOINT_10_TX | ENDPOINT_11_RX | ENDPOINT_11_TX | + // ENDPOINT_12_RX | ENDPOINT_12_TX | ENDPOINT_13_RX | + // ENDPOINT_13_TX | ENDPOINT_14_RX | ENDPOINT_14_TX | + // ENDPOINT_15_RX | ENDPOINT_15_TX); + init_usb2_descriptors(); + usb_device_set_usb2_device_descriptor(&usb_device_0, &usb2_descriptors.usb_device_descr); + usb_device_set_usb2_config_descriptors(&usb_device_0, usb2_device_configs); + usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_1_RX | ENDPOINT_1_TX | ENDPOINT_2_RX | + ENDPOINT_2_TX | ENDPOINT_3_RX | ENDPOINT_3_TX | + ENDPOINT_4_RX | ENDPOINT_4_TX | ENDPOINT_5_RX | + ENDPOINT_5_TX | ENDPOINT_6_RX | ENDPOINT_6_TX | + ENDPOINT_7_RX | ENDPOINT_7_TX); usb_device_0.speed = USB2_HIGHSPEED; usb2_device_init(); } diff --git a/tests/test_firmware_usb_loopback/User/usb2_device_descriptors_alt_endpoints.h b/tests/test_firmware_usb_loopback/User/usb2_device_descriptors_alt_endpoints.h new file mode 100644 index 0000000..07e7d30 --- /dev/null +++ b/tests/test_firmware_usb_loopback/User/usb2_device_descriptors_alt_endpoints.h @@ -0,0 +1,251 @@ +/********************************** (C) COPYRIGHT ******************************* +Copyright (c) 2023 Quarkslab + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*******************************************************************************/ + +#ifndef USB2_DEVICE_DESCRIPTOR_ALT_ENDPOINTS_H +#define USB2_DEVICE_DESCRIPTOR_ALT_ENDPOINTS_H + +#include "definitions.h" +#include "wch-ch56x-lib/USBDevice/usb_descriptors.h" + +const uint8_t* usb2_device_configs_alt_endpoints[1]; + +struct usb2_descriptors_alt_endpoints +{ + USB_DEV_DESCR usb_device_descr; + struct __PACKED + { + USB_CFG_DESCR usb_cfg_descr; + USB_ITF_DESCR usb_itf_descr; + USB_ENDP_DESCR usb_endp_descr_9; + USB_ENDP_DESCR usb_endp_descr_9_tx; + USB_ENDP_DESCR usb_endp_descr_10; + USB_ENDP_DESCR usb_endp_descr_10_tx; + USB_ENDP_DESCR usb_endp_descr_11; + USB_ENDP_DESCR usb_endp_descr_11_tx; + USB_ENDP_DESCR usb_endp_descr_12; + USB_ENDP_DESCR usb_endp_descr_12_tx; + USB_ENDP_DESCR usb_endp_descr_13; + USB_ENDP_DESCR usb_endp_descr_13_tx; + USB_ENDP_DESCR usb_endp_descr_14; + USB_ENDP_DESCR usb_endp_descr_14_tx; + USB_ENDP_DESCR usb_endp_descr_15; + USB_ENDP_DESCR usb_endp_descr_15_tx; + } other_descr; +} usb2_descriptors_alt_endpoints; + +void init_usb2_descriptors_alt_endpoints(void); + +void init_usb2_descriptors_alt_endpoints(void) +{ + usb2_descriptors_alt_endpoints.usb_device_descr = (USB_DEV_DESCR){ + .bLength = 0x12, + .bDescriptorType = 0x01, // device descriptor type + .bcdUSB = 0x0200, // usb2.0 + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = 64, + .bcdDevice = 0x0001, + .idVendor = + 0x16c0, // https://github.com/obdev/v-usb/blob/master/usbdrv/usb-ids-for-free.txt + .idProduct = 0x27d8, + .iProduct = 0x01, + .iManufacturer = 0x00, + .iSerialNumber = 0x00, + .bNumConfigurations = 0x01 + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_cfg_descr = (USB_CFG_DESCR){ + .bLength = 0x09, + .bDescriptorType = 0x02, + .wTotalLength = sizeof(usb2_descriptors_alt_endpoints.other_descr), + .bNumInterfaces = 0x01, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = 0xa0, // supports remote wake-up + .MaxPower = 0x64 // 200ma + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_itf_descr = + (USB_ITF_DESCR){ .bLength = 0x09, + .bDescriptorType = 0x04, + .bInterfaceNumber = 0x00, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x0e, + .bInterfaceClass = 0xff, // vendor-specific + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .iInterface = 0x00 }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_9 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x09) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 255 // max NAK rate + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_9_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x09) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 0 + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_10 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x0a) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 255 // max NAK rate + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_10_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x0a) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 0 + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_11 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x0b) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 255 // max NAK rate + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_11_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x0b) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 0 + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_12 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x0c) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 255 // max NAK rate + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_12_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x0c) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 0 + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_13 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x0d) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 255 // max NAK rate + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_13_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x0d) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 0 + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_14 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x0e) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 255 // max NAK rate + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_14_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x0e) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 0 + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_15 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x0f) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 255 // max NAK rate + }; + + usb2_descriptors_alt_endpoints.other_descr.usb_endp_descr_15_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x0f) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x02, // 512 bytes + .bInterval = 0 + }; + + usb2_device_configs_alt_endpoints[0] = (uint8_t*)&usb2_descriptors_alt_endpoints.other_descr; +} + +#endif diff --git a/tests/test_firmware_usb_loopback/User/usb_device.h b/tests/test_firmware_usb_loopback/User/usb_device.h index cae4705..3cd6c17 100644 --- a/tests/test_firmware_usb_loopback/User/usb_device.h +++ b/tests/test_firmware_usb_loopback/User/usb_device.h @@ -304,6 +304,76 @@ void init_endpoints(void) usb_device_0.endpoints.tx[7].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; usb_device_0.endpoints.tx[7].max_burst = DEF_ENDP_OUT_BURST_LEVEL; usb_device_0.endpoints.tx[7].max_packet_size_with_burst = sizeof(endp7_rx_buffer); + + usb_device_0.endpoints.rx[9].buffer = endp1_rx_buffer; + usb_device_0.endpoints.rx[9].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.rx[9].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.rx[9].max_packet_size_with_burst = sizeof(endp1_rx_buffer); + + usb_device_0.endpoints.tx[9].buffer = NULL; + usb_device_0.endpoints.tx[9].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.tx[9].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.tx[9].max_packet_size_with_burst = sizeof(endp1_rx_buffer); + + usb_device_0.endpoints.rx[10].buffer = endp2_rx_buffer; + usb_device_0.endpoints.rx[10].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.rx[10].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.rx[10].max_packet_size_with_burst = sizeof(endp2_rx_buffer); + + usb_device_0.endpoints.tx[10].buffer = NULL; + usb_device_0.endpoints.tx[10].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.tx[10].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.tx[10].max_packet_size_with_burst = sizeof(endp2_rx_buffer); + + usb_device_0.endpoints.rx[11].buffer = endp3_rx_buffer; + usb_device_0.endpoints.rx[11].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.rx[11].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.rx[11].max_packet_size_with_burst = sizeof(endp3_rx_buffer); + + usb_device_0.endpoints.tx[11].buffer = NULL; + usb_device_0.endpoints.tx[11].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.tx[11].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.tx[11].max_packet_size_with_burst = sizeof(endp3_rx_buffer); + + usb_device_0.endpoints.rx[12].buffer = endp4_rx_buffer; + usb_device_0.endpoints.rx[12].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.rx[12].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.rx[12].max_packet_size_with_burst = sizeof(endp4_rx_buffer); + + usb_device_0.endpoints.tx[12].buffer = NULL; + usb_device_0.endpoints.tx[12].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.tx[12].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.tx[12].max_packet_size_with_burst = sizeof(endp4_rx_buffer); + + usb_device_0.endpoints.rx[13].buffer = endp5_rx_buffer; + usb_device_0.endpoints.rx[13].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.rx[13].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.rx[13].max_packet_size_with_burst = sizeof(endp5_rx_buffer); + + usb_device_0.endpoints.tx[13].buffer = NULL; + usb_device_0.endpoints.tx[13].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.tx[13].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.tx[13].max_packet_size_with_burst = sizeof(endp5_rx_buffer); + + usb_device_0.endpoints.rx[14].buffer = endp6_rx_buffer; + usb_device_0.endpoints.rx[14].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.rx[14].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.rx[14].max_packet_size_with_burst = sizeof(endp6_rx_buffer); + + usb_device_0.endpoints.tx[14].buffer = NULL; + usb_device_0.endpoints.tx[14].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.tx[14].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.tx[14].max_packet_size_with_burst = sizeof(endp6_rx_buffer); + + usb_device_0.endpoints.rx[15].buffer = endp7_rx_buffer; + usb_device_0.endpoints.rx[15].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.rx[15].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.rx[15].max_packet_size_with_burst = sizeof(endp7_rx_buffer); + + usb_device_0.endpoints.tx[15].buffer = NULL; + usb_device_0.endpoints.tx[15].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.tx[15].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.tx[15].max_packet_size_with_burst = sizeof(endp7_rx_buffer); } #endif diff --git a/tests/test_firmware_usb_stress_test/User/main.c b/tests/test_firmware_usb_stress_test/User/main.c index 6b27dd8..39acc9b 100644 --- a/tests/test_firmware_usb_stress_test/User/main.c +++ b/tests/test_firmware_usb_stress_test/User/main.c @@ -26,7 +26,9 @@ limitations under the License. #pragma GCC diagnostic pop #pragma GCC diagnostic pop -#include "usb2_device_descriptors.h" +#include "usb2_fs_device_descriptors.h" +#include "usb2_hs_device_descriptors.h" +#include "usb2_ls_device_descriptors.h" #include "usb_device.h" #include "wch-ch56x-lib/logging/logging.h" #include "wch-ch56x-lib/USBDevice/usb20.h" @@ -72,7 +74,6 @@ void endp2_tx_complete(TRANSACTION_STATUS status) uint8_t endp1_rx_callback(uint8_t* const ptr, uint16_t size); uint8_t endp1_rx_callback(uint8_t* const ptr, uint16_t size) { - LOG("writing %d bytes %x %x %x %x \r\n", size, endp0_buffer[0], endp0_buffer[1], endp0_buffer[2], endp0_buffer[3]); memcpy(last_out_buffer + out_total_sent, ptr, size); out_total_sent += size; last_out_total_sent = out_total_sent; //because no ZLP is sent for bulk OUT ... meaning we can't detect the end of the transfer @@ -171,7 +172,7 @@ int main() bsp_init(FREQ_SYS); LOG_INIT(FREQ_SYS); - LOG("USB stress test azeaez\r\n"); + LOG("USB stress test\r\n"); usb_device_0.endpoints.endp0_user_handled_control_request = endp0_user_handled_control_request; usb_device_0.endpoints.tx_complete[2] = endp2_tx_complete; @@ -181,21 +182,66 @@ int main() usb2_user_handled.usb2_device_handle_bus_reset = &usb2_device_handle_bus_reset; - // Finish initializing the descriptor parameters - init_usb2_descriptors(); - init_string_descriptors(); + if (bsp_ubtn()) + { + usb_device_0.speed = USB2_FULLSPEED; + } + else + { + usb_device_0.speed = USB2_HIGHSPEED; + } - // Set the USB device parameters - usb_device_set_usb2_device_descriptor(&usb_device_0, &usb2_descriptors.usb_device_descr); - usb_device_set_usb2_config_descriptors(&usb_device_0, usb2_device_configs); - usb_device_set_string_descriptors(&usb_device_0, device_string_descriptors); - usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_1_RX | ENDPOINT_2_TX); + if (usb_device_0.speed == USB2_LOWSPEED) + { + // Finish initializing the descriptor parameters + init_usb2_ls_descriptors(); + init_string_descriptors(); - init_endpoints(); + // Set the USB device parameters + usb_device_set_usb2_device_descriptor(&usb_device_0, &usb2_ls_descriptors.usb_device_descr); + usb_device_set_usb2_config_descriptors(&usb_device_0, usb2_ls_device_configs); + usb_device_set_string_descriptors(&usb_device_0, device_string_descriptors); + usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_1_RX | ENDPOINT_2_TX); + + init_endpoints_ls(); + + usb2_device_init(); + usb2_enable_nak(true); + } + else if (usb_device_0.speed == USB2_FULLSPEED) + { + // Finish initializing the descriptor parameters + init_usb2_fs_descriptors(); + init_string_descriptors(); - usb_device_0.speed = USB2_HIGHSPEED; - usb2_device_init(); - usb2_enable_nak(true); + // Set the USB device parameters + usb_device_set_usb2_device_descriptor(&usb_device_0, &usb2_fs_descriptors.usb_device_descr); + usb_device_set_usb2_config_descriptors(&usb_device_0, usb2_fs_device_configs); + usb_device_set_string_descriptors(&usb_device_0, device_string_descriptors); + usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_1_RX | ENDPOINT_2_TX); + + init_endpoints_fs(); + + usb2_device_init(); + usb2_enable_nak(true); + } + else if (usb_device_0.speed == USB2_HIGHSPEED) + { + // Finish initializing the descriptor parameters + init_usb2_hs_descriptors(); + init_string_descriptors(); + + // Set the USB device parameters + usb_device_set_usb2_device_descriptor(&usb_device_0, &usb2_hs_descriptors.usb_device_descr); + usb_device_set_usb2_config_descriptors(&usb_device_0, usb2_hs_device_configs); + usb_device_set_string_descriptors(&usb_device_0, device_string_descriptors); + usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_1_RX | ENDPOINT_2_TX); + + init_endpoints_hs(); + + usb2_device_init(); + usb2_enable_nak(true); + } // Infinite loop USB2/USB3 managed with Interrupt while (1) diff --git a/tests/test_firmware_usb_stress_test/User/usb2_fs_device_descriptors.h b/tests/test_firmware_usb_stress_test/User/usb2_fs_device_descriptors.h new file mode 100644 index 0000000..bb8286e --- /dev/null +++ b/tests/test_firmware_usb_stress_test/User/usb2_fs_device_descriptors.h @@ -0,0 +1,106 @@ +/********************************** (C) COPYRIGHT ******************************* +Copyright (c) 2023 Quarkslab + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*******************************************************************************/ + +#ifndef USB2_FS_DEVICE_DESCRIPTOR_H +#define USB2_FS_DEVICE_DESCRIPTOR_H + +#include "definitions.h" +#include "wch-ch56x-lib/USBDevice/usb_descriptors.h" + +const uint8_t* usb2_fs_device_configs[1]; + +struct usb2_fs_descriptors +{ + USB_DEV_DESCR usb_device_descr; + struct __PACKED + { + USB_CFG_DESCR usb_cfg_descr; + USB_ITF_DESCR usb_itf_descr; + USB_ENDP_DESCR usb_endp_descr_1; + USB_ENDP_DESCR usb_endp_descr_2_tx; + } other_descr; +} usb2_fs_descriptors; + +void init_usb2_fs_descriptors(void); +void init_usb2_fs_descriptors(void) +{ + usb2_fs_descriptors.usb_device_descr = (USB_DEV_DESCR){ + .bLength = 0x12, + .bDescriptorType = 0x01, // device descriptor type + .bcdUSB = 0x0200, // usb2.0 + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = 64, + .bcdDevice = 0x0001, + .idVendor = + 0x1209, // https://github.com/obdev/v-usb/blob/master/usbdrv/usb-ids-for-free.txt + .idProduct = 0x0001, + .iProduct = 0x01, + .iManufacturer = 0x00, + .iSerialNumber = 0x00, + .bNumConfigurations = 0x01 + }; + + usb2_fs_descriptors.other_descr.usb_cfg_descr = (USB_CFG_DESCR){ + .bLength = 0x09, + .bDescriptorType = 0x02, + .wTotalLength = sizeof(usb2_fs_descriptors.other_descr), + .bNumInterfaces = 0x01, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = 0xa0, // supports remote wake-up + .MaxPower = 0x64 // 200ma + }; + + usb2_fs_descriptors.other_descr.usb_itf_descr = + (USB_ITF_DESCR){ .bLength = 0x09, + .bDescriptorType = 0x04, + .bInterfaceNumber = 0x00, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = 0xff, // vendor-specific + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .iInterface = 0x00 }; + + usb2_fs_descriptors.other_descr.usb_endp_descr_1 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x01) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x40, + .wMaxPacketSizeH = 0x00, // 64 bytes + .bInterval = 255 // max NAK rate + }; + + usb2_fs_descriptors.other_descr.usb_endp_descr_2_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x02) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x40, + .wMaxPacketSizeH = 0x00, // 64 bytes + .bInterval = 0 + }; + + usb2_fs_device_configs[0] = (uint8_t*)&usb2_fs_descriptors.other_descr; +} + +#endif diff --git a/tests/test_firmware_usb_stress_test/User/usb2_device_descriptors.h b/tests/test_firmware_usb_stress_test/User/usb2_hs_device_descriptors.h similarity index 79% rename from tests/test_firmware_usb_stress_test/User/usb2_device_descriptors.h rename to tests/test_firmware_usb_stress_test/User/usb2_hs_device_descriptors.h index 140f204..4af7d75 100644 --- a/tests/test_firmware_usb_stress_test/User/usb2_device_descriptors.h +++ b/tests/test_firmware_usb_stress_test/User/usb2_hs_device_descriptors.h @@ -15,15 +15,15 @@ limitations under the License. *******************************************************************************/ -#ifndef USB2_DEVICE_DESCRIPTOR_H -#define USB2_DEVICE_DESCRIPTOR_H +#ifndef USB2_HS_DEVICE_DESCRIPTOR_H +#define USB2_HS_DEVICE_DESCRIPTOR_H #include "definitions.h" #include "wch-ch56x-lib/USBDevice/usb_descriptors.h" -const uint8_t* usb2_device_configs[1]; +const uint8_t* usb2_hs_device_configs[1]; -struct usb2_descriptors +struct usb2_hs_descriptors { USB_DEV_DESCR usb_device_descr; struct __PACKED @@ -33,13 +33,12 @@ struct usb2_descriptors USB_ENDP_DESCR usb_endp_descr_1; USB_ENDP_DESCR usb_endp_descr_2_tx; } other_descr; -} usb2_descriptors; +} usb2_hs_descriptors; -void init_usb2_descriptors(void); - -void init_usb2_descriptors(void) +void init_usb2_hs_descriptors(void); +void init_usb2_hs_descriptors(void) { - usb2_descriptors.usb_device_descr = (USB_DEV_DESCR){ + usb2_hs_descriptors.usb_device_descr = (USB_DEV_DESCR){ .bLength = 0x12, .bDescriptorType = 0x01, // device descriptor type .bcdUSB = 0x0200, // usb2.0 @@ -57,10 +56,10 @@ void init_usb2_descriptors(void) .bNumConfigurations = 0x01 }; - usb2_descriptors.other_descr.usb_cfg_descr = (USB_CFG_DESCR){ + usb2_hs_descriptors.other_descr.usb_cfg_descr = (USB_CFG_DESCR){ .bLength = 0x09, .bDescriptorType = 0x02, - .wTotalLength = sizeof(usb2_descriptors.other_descr), + .wTotalLength = sizeof(usb2_hs_descriptors.other_descr), .bNumInterfaces = 0x01, .bConfigurationValue = 0x01, .iConfiguration = 0x00, @@ -68,7 +67,7 @@ void init_usb2_descriptors(void) .MaxPower = 0x64 // 200ma }; - usb2_descriptors.other_descr.usb_itf_descr = + usb2_hs_descriptors.other_descr.usb_itf_descr = (USB_ITF_DESCR){ .bLength = 0x09, .bDescriptorType = 0x04, .bInterfaceNumber = 0x00, @@ -79,7 +78,7 @@ void init_usb2_descriptors(void) .bInterfaceProtocol = 0xff, .iInterface = 0x00 }; - usb2_descriptors.other_descr.usb_endp_descr_1 = (USB_ENDP_DESCR){ + usb2_hs_descriptors.other_descr.usb_endp_descr_1 = (USB_ENDP_DESCR){ .bLength = 0x07, .bDescriptorType = 0x05, .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x01) & @@ -90,7 +89,7 @@ void init_usb2_descriptors(void) .bInterval = 255 // max NAK rate }; - usb2_descriptors.other_descr.usb_endp_descr_2_tx = (USB_ENDP_DESCR){ + usb2_hs_descriptors.other_descr.usb_endp_descr_2_tx = (USB_ENDP_DESCR){ .bLength = 0x07, .bDescriptorType = 0x05, .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x02) & @@ -101,7 +100,7 @@ void init_usb2_descriptors(void) .bInterval = 0 }; - usb2_device_configs[0] = (uint8_t*)&usb2_descriptors.other_descr; + usb2_hs_device_configs[0] = (uint8_t*)&usb2_hs_descriptors.other_descr; } #endif diff --git a/tests/test_firmware_usb_stress_test/User/usb2_ls_device_descriptors.h b/tests/test_firmware_usb_stress_test/User/usb2_ls_device_descriptors.h new file mode 100644 index 0000000..29f2593 --- /dev/null +++ b/tests/test_firmware_usb_stress_test/User/usb2_ls_device_descriptors.h @@ -0,0 +1,106 @@ +/********************************** (C) COPYRIGHT ******************************* +Copyright (c) 2023 Quarkslab + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*******************************************************************************/ + +#ifndef USB2_LS_DEVICE_DESCRIPTOR_H +#define USB2_LS_DEVICE_DESCRIPTOR_H + +#include "definitions.h" +#include "wch-ch56x-lib/USBDevice/usb_descriptors.h" + +const uint8_t* usb2_ls_device_configs[1]; + +struct usb2_ls_descriptors +{ + USB_DEV_DESCR usb_device_descr; + struct __PACKED + { + USB_CFG_DESCR usb_cfg_descr; + USB_ITF_DESCR usb_itf_descr; + USB_ENDP_DESCR usb_endp_descr_1; + USB_ENDP_DESCR usb_endp_descr_2_tx; + } other_descr; +} usb2_ls_descriptors; + +void init_usb2_ls_descriptors(void); +void init_usb2_ls_descriptors(void) +{ + usb2_ls_descriptors.usb_device_descr = (USB_DEV_DESCR){ + .bLength = 0x12, + .bDescriptorType = 0x01, // device descriptor type + .bcdUSB = 0x0100, // usb2.0 + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = 8, + .bcdDevice = 0x0001, + .idVendor = + 0x1209, // https://github.com/obdev/v-usb/blob/master/usbdrv/usb-ids-for-free.txt + .idProduct = 0x0001, + .iProduct = 0x01, + .iManufacturer = 0x00, + .iSerialNumber = 0x00, + .bNumConfigurations = 0x01 + }; + + usb2_ls_descriptors.other_descr.usb_cfg_descr = (USB_CFG_DESCR){ + .bLength = 0x09, + .bDescriptorType = 0x02, + .wTotalLength = sizeof(usb2_ls_descriptors.other_descr), + .bNumInterfaces = 0x01, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = 0xa0, // supports remote wake-up + .MaxPower = 0x64 // 200ma + }; + + usb2_ls_descriptors.other_descr.usb_itf_descr = + (USB_ITF_DESCR){ .bLength = 0x09, + .bDescriptorType = 0x04, + .bInterfaceNumber = 0x00, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = 0xff, // vendor-specific + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .iInterface = 0x00 }; + + usb2_ls_descriptors.other_descr.usb_endp_descr_1 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x01) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_INTERRUPT_TRANSFER, + .wMaxPacketSizeL = 0x08, + .wMaxPacketSizeH = 0x00, // 8 bytes + .bInterval = 255 // max NAK rate + }; + + usb2_ls_descriptors.other_descr.usb_endp_descr_2_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x02) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_INTERRUPT_TRANSFER, + .wMaxPacketSizeL = 0x08, + .wMaxPacketSizeH = 0x00, // 8 bytes + .bInterval = 0 + }; + + usb2_ls_device_configs[0] = (uint8_t*)&usb2_ls_descriptors.other_descr; +} + +#endif diff --git a/tests/test_firmware_usb_stress_test/User/usb_device.h b/tests/test_firmware_usb_stress_test/User/usb_device.h index 2d9efce..9042c4d 100644 --- a/tests/test_firmware_usb_stress_test/User/usb_device.h +++ b/tests/test_firmware_usb_stress_test/User/usb_device.h @@ -187,13 +187,13 @@ void init_string_descriptors(void) &usb_string_descriptors.product_string_descriptor; } -void init_endpoints(void); -void init_endpoints(void) +void init_endpoints_hs(void); +void init_endpoints_hs(void) { usb_device_0.endpoints.rx[0].buffer = endp0_buffer; - usb_device_0.endpoints.rx[0].max_packet_size = 512; + usb_device_0.endpoints.rx[0].max_packet_size = 64; usb_device_0.endpoints.rx[0].max_burst = 1; - usb_device_0.endpoints.rx[0].max_packet_size_with_burst = 512; + usb_device_0.endpoints.rx[0].max_packet_size_with_burst = 64; usb_device_0.endpoints.rx[1].buffer = endp1_rx_buffer; usb_device_0.endpoints.rx[1].max_packet_size = 512; @@ -206,4 +206,42 @@ void init_endpoints(void) usb_device_0.endpoints.tx[2].max_packet_size_with_burst = 512; } +void init_endpoints_fs(void); +void init_endpoints_fs(void) +{ + usb_device_0.endpoints.rx[0].buffer = endp0_buffer; + usb_device_0.endpoints.rx[0].max_packet_size = 64; + usb_device_0.endpoints.rx[0].max_burst = 1; + usb_device_0.endpoints.rx[0].max_packet_size_with_burst = 64; + + usb_device_0.endpoints.rx[1].buffer = endp1_rx_buffer; + usb_device_0.endpoints.rx[1].max_packet_size = 64; + usb_device_0.endpoints.rx[1].max_burst = 1; + usb_device_0.endpoints.rx[1].max_packet_size_with_burst = 64; + + usb_device_0.endpoints.tx[2].buffer = NULL; + usb_device_0.endpoints.tx[2].max_packet_size = 64; + usb_device_0.endpoints.tx[2].max_burst = 1; + usb_device_0.endpoints.tx[2].max_packet_size_with_burst = 64; +} + +void init_endpoints_ls(void); +void init_endpoints_ls(void) +{ + usb_device_0.endpoints.rx[0].buffer = endp0_buffer; + usb_device_0.endpoints.rx[0].max_packet_size = 8; + usb_device_0.endpoints.rx[0].max_burst = 1; + usb_device_0.endpoints.rx[0].max_packet_size_with_burst = 8; + + usb_device_0.endpoints.rx[1].buffer = endp1_rx_buffer; + usb_device_0.endpoints.rx[1].max_packet_size = 8; + usb_device_0.endpoints.rx[1].max_burst = 1; + usb_device_0.endpoints.rx[1].max_packet_size_with_burst = 8; + + usb_device_0.endpoints.tx[2].buffer = NULL; + usb_device_0.endpoints.tx[2].max_packet_size = 8; + usb_device_0.endpoints.tx[2].max_burst = 1; + usb_device_0.endpoints.tx[2].max_packet_size_with_burst = 8; +} + #endif diff --git a/tools/scripts/print_logs.py b/tools/scripts/print_logs.py index 67491fb..7e4671b 100755 --- a/tools/scripts/print_logs.py +++ b/tools/scripts/print_logs.py @@ -39,16 +39,16 @@ intf, find_all=True, # match the first OUT endpoint - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN)) ep_out = list(usb.util.find_descriptor( intf, # match the first OUT endpoint find_all=True, - custom_match=lambda e: \ - usb.util.endpoint_direction(e.bEndpointAddress) == \ + custom_match=lambda e: + usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)) assert ep_in is not None