From cdeb194c7ac3c6bd3af21a228d3f9f3d73e21994 Mon Sep 17 00:00:00 2001 From: Arti Zirk Date: Fri, 1 Oct 2021 18:48:38 +0300 Subject: [PATCH] RDNIS skeleton --- CMakeLists.txt | 2 +- openocd/stlink.cfg | 2 +- src/cdcacm.c | 53 +++------------ src/cdcacm.h | 2 +- src/main.c | 42 +++++++++++- src/rndis.c | 158 +++++++++++++++++++++++++++++++++++++++++++++ src/rndis.h | 7 ++ src/util.c | 10 +++ src/util.h | 1 + 9 files changed, 230 insertions(+), 47 deletions(-) create mode 100644 src/rndis.c create mode 100644 src/rndis.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 542e530..11304fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ add_compile_definitions( DEBUG TARGETS=stm32/f1 ) -add_executable(usbtest src/main.c src/util.c src/cdcacm.c) +add_executable(usbtest src/main.c src/util.c src/cdcacm.c src/rndis.c src/rndis.h) set_target_properties(usbtest PROPERTIES SUFFIX .elf) diff --git a/openocd/stlink.cfg b/openocd/stlink.cfg index 00761b9..c7fdf89 100644 --- a/openocd/stlink.cfg +++ b/openocd/stlink.cfg @@ -2,7 +2,7 @@ source [find interface/stlink.cfg] source [find target/stm32f1x.cfg] -#reset_config srst_only +reset_config combined # Search for RTT string from start of RAM rtt setup 0x20000000 8192 "SEGGER RTT" diff --git a/src/cdcacm.c b/src/cdcacm.c index c741a2c..3ead9af 100644 --- a/src/cdcacm.c +++ b/src/cdcacm.c @@ -18,8 +18,6 @@ */ #include -#include -#include #include #include @@ -168,16 +166,16 @@ static const char *usb_strings[] = { }; /* Buffer to be used for control requests. */ -uint8_t usbd_control_buffer[128]; +static uint8_t usbd_control_buffer[128]; static enum usbd_request_return_codes cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req)) { - (void)complete; - (void)buf; - (void)usbd_dev; + (void)complete; + (void)buf; + (void)usbd_dev; - switch (req->bRequest) { + switch (req->bRequest) { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { /* * This Linux cdc_acm driver requires this to be implemented @@ -202,8 +200,8 @@ static enum usbd_request_return_codes cdcacm_control_request(usbd_device *usbd_d if (*len < sizeof(struct usb_cdc_line_coding)) return USBD_REQ_NOTSUPP; return USBD_REQ_HANDLED; - } - return USBD_REQ_NOTSUPP; + } + return USBD_REQ_NOTSUPP; } static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep) @@ -238,46 +236,15 @@ static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue) cdcacm_control_request); } -void start_cdcacm(void) { - int i; - +usbd_device *start_cdcacm(void) { usbd_device *usbd_dev; - //SCB_VTOR = (uint32_t) 0x08005000; + SEGGER_RTT_printf(0, "Configuring USB CDC-ACM device\n"); - rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); - - rcc_periph_clock_enable(RCC_GPIOB); - - - /* Setup GPIOB Pin 9 to pull up the D+ high, so autodect works - * with the bootloader. The circuit is active high. */ - gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_OPENDRAIN, GPIO9); - gpio_set(GPIOB, GPIO9); - - /* Setup GPIOB Pin 1 for the LED */ - gpio_set(GPIOB, GPIO1); - gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO1); - - SEGGER_RTT_printf(0, "Starting USB\n"); - - rcc_periph_clock_enable(RCC_AFIO); - rcc_periph_clock_enable(RCC_OTGFS); usbd_dev = usbd_init(&st_usbfs_v1_usb_driver, &dev, &config, usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer)); usbd_register_set_config_callback(usbd_dev, cdcacm_set_config); - for (i = 0; i < 0x800000; i++) - __asm__("nop"); - gpio_clear(GPIOB, GPIO9); - - SEGGER_RTT_printf(0, "Main loop\n"); - - while (1) { - usbd_poll(usbd_dev); - gpio_toggle(GPIOB, GPIO1); - } + return usbd_dev; } diff --git a/src/cdcacm.h b/src/cdcacm.h index 5fb5a6c..e9cbf3d 100644 --- a/src/cdcacm.h +++ b/src/cdcacm.h @@ -1,6 +1,6 @@ #ifndef USBTEST_CDCACM_H -void start_cdcacm(void); +usbd_device *start_cdcacm(void); #define USBTEST_CDCACM_H diff --git a/src/main.c b/src/main.c index e65de1d..9e13bec 100644 --- a/src/main.c +++ b/src/main.c @@ -1,8 +1,48 @@ +#include +#include +#include + #include #include "cdcacm.h" +#include "rndis.h" int main(void) { + usbd_device *usbd_dev; + + SEGGER_RTT_printf(0, "Hello World\n"); - start_cdcacm(); + + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + + rcc_periph_clock_enable(RCC_GPIOB); + + + /* Setup GPIOB Pin 9 to pull up the D+ high, so autodect works + * with the bootloader. The circuit is active high. */ + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, GPIO9); + + /* Setup GPIOB Pin 1 for the LED */ + gpio_set(GPIOB, GPIO1); + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO1); + + SEGGER_RTT_printf(0, "Starting USB\n"); + + rcc_periph_clock_enable(RCC_AFIO); + rcc_periph_clock_enable(RCC_OTGFS); + + + usbd_dev = start_rdnis(); + + + SEGGER_RTT_printf(0, "Main loop\n"); + + while (1) { + usbd_poll(usbd_dev); + gpio_toggle(GPIOB, GPIO1); + } + + return 0; } diff --git a/src/rndis.c b/src/rndis.c new file mode 100644 index 0000000..392bd8d --- /dev/null +++ b/src/rndis.c @@ -0,0 +1,158 @@ +#include +#include +#include + +#include + +#include "rndis.h" + +/* Buffer to be used for control requests. */ +static uint8_t usbd_control_buffer[128]; + +static const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0xE0, // Wireless Controller + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = 0x4E44, + .idProduct = 0x4953, + .bcdDevice = 0xffff, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +static const struct usb_endpoint_descriptor comm_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x81, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 8, + .bInterval = 255, +}}; + +static const struct { + struct usb_cdc_header_descriptor header; + struct usb_cdc_call_management_descriptor call_mgmt; + struct usb_cdc_acm_descriptor acm; + struct usb_cdc_union_descriptor cdc_union; +} __attribute__((packed)) cdcacm_functional_descriptors = { + .header = { + .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_HEADER, + .bcdCDC = 0x0110, + }, + .call_mgmt = { + .bFunctionLength = + sizeof(struct usb_cdc_call_management_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 1, + }, + .acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_ACM, + .bmCapabilities = 0, + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_UNION, + .bControlInterface = 0, + .bSubordinateInterface0 = 1, + }, +}; + +// RNDIS Communications Control +static const struct usb_interface_descriptor comm_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = 0xE0, // Wireless Controller + .bInterfaceSubClass = 0x01, + .bInterfaceProtocol = 0x03, + .iInterface = 0, + + .endpoint = comm_endp, + + .extra = &cdcacm_functional_descriptors, + .extralen = sizeof(cdcacm_functional_descriptors), +}}; + +static const struct usb_endpoint_descriptor data_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x01, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = 64, + .bInterval = 0, +}, { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x82, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = 64, + .bInterval = 0, +}}; + +static const struct usb_interface_descriptor data_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, + + .endpoint = data_endp, +}}; + +static const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .altsetting = comm_iface, +}, { + .num_altsetting = 1, + .altsetting = data_iface, +}}; + +static const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, + .bNumInterfaces = 2, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0x80, + .bMaxPower = 0x32, + + .interface = ifaces, +}; + +static const char *usb_strings[] = { + "Arti Zirk", // iManufacturer + "STM32-RNDIS", // iProduct + "lrndis demo", // iSerialNumber +}; + +usbd_device *start_rdnis(void) { + usbd_device *usb_dev; + + usb_dev = usbd_init( + &st_usbfs_v1_usb_driver, &dev, &config, + usb_strings, 3, + usbd_control_buffer, sizeof(usbd_control_buffer) + ); + + return usb_dev; +} diff --git a/src/rndis.h b/src/rndis.h new file mode 100644 index 0000000..ac4e6ab --- /dev/null +++ b/src/rndis.h @@ -0,0 +1,7 @@ +#ifndef USBTEST_RNDIS_H +#define USBTEST_RNDIS_H + +usbd_device *start_rdnis(void); + + +#endif //USBTEST_RNDIS_H diff --git a/src/util.c b/src/util.c index 5104b97..bfbade3 100644 --- a/src/util.c +++ b/src/util.c @@ -1,4 +1,7 @@ +#include + #include +#include "delay.h" #include "util.h" void hexdump(char *buf, size_t size, uint32_t width) { @@ -15,3 +18,10 @@ void hexdump(char *buf, size_t size, uint32_t width) { SEGGER_RTT_printf(0,"\n"); SEGGER_RTT_SetFlagsUpBuffer(0, SEGGER_RTT_MODE_DEFAULT); } + + +void reset_usb_bus(void) { + gpio_set(GPIOB, GPIO9); + delay_ms(10); + gpio_clear(GPIOB, GPIO9); +} diff --git a/src/util.h b/src/util.h index ee83190..7f8f66d 100644 --- a/src/util.h +++ b/src/util.h @@ -4,5 +4,6 @@ #include void hexdump(char *buf, size_t size, uint32_t width); +void reset_usb_bus(void); #endif //DHT_TEST_UTIL_H