diff --git a/demo/mongoose/cdc_rndis_mongoose.c b/demo/mongoose/cdc_rndis_mongoose.c new file mode 100644 index 00000000..0f571b57 --- /dev/null +++ b/demo/mongoose/cdc_rndis_mongoose.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2025, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbd_core.h" +#include "usbd_rndis.h" +#include "rndis_protocol.h" +#include "mongoose.h" + +#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP +#error Do not define CONFIG_USBDEV_RNDIS_USING_LWIP in this demo +#endif + +/*!< endpoint address */ +#define CDC_IN_EP 0x81 +#define CDC_OUT_EP 0x02 +#define CDC_INT_EP 0x83 + +/*!< config descriptor size */ +#define USB_CONFIG_SIZE (9 + CDC_RNDIS_DESCRIPTOR_LEN) + +static const uint8_t device_descriptor[] = { + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01) +}; + +static const uint8_t config_descriptor_hs[] = { + USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_HS, 0x02), +}; + +static const uint8_t config_descriptor_fs[] = { + USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_FS, 0x02), +}; + +static const uint8_t device_quality_descriptor[] = { + USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, 0x01), +}; + +static const uint8_t other_speed_config_descriptor_hs[] = { + USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_FS, 0x02), +}; + +static const uint8_t other_speed_config_descriptor_fs[] = { + USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_HS, 0x02), +}; + +static const char *string_descriptors[] = { + (const char[]){ 0x09, 0x04 }, /* Langid */ + "CherryUSB", /* Manufacturer */ + "CherryUSB RNDIS MONGOOSE DEMO", /* Product */ + "2025123456", /* Serial Number */ +}; + +static const uint8_t *device_descriptor_callback(uint8_t speed) +{ + (void)speed; + + return device_descriptor; +} + +static const uint8_t *config_descriptor_callback(uint8_t speed) +{ + if (speed == USB_SPEED_HIGH) { + return config_descriptor_hs; + } else if (speed == USB_SPEED_FULL) { + return config_descriptor_fs; + } else { + return NULL; + } +} + +static const uint8_t *device_quality_descriptor_callback(uint8_t speed) +{ + (void)speed; + + return device_quality_descriptor; +} + +static const uint8_t *other_speed_config_descriptor_callback(uint8_t speed) +{ + if (speed == USB_SPEED_HIGH) { + return other_speed_config_descriptor_hs; + } else if (speed == USB_SPEED_FULL) { + return other_speed_config_descriptor_fs; + } else { + return NULL; + } +} + +static const char *string_descriptor_callback(uint8_t speed, uint8_t index) +{ + (void)speed; + + if (index >= (sizeof(string_descriptors) / sizeof(char *))) { + return NULL; + } + return string_descriptors[index]; +} + +const struct usb_descriptor cdc_descriptor = { + .device_descriptor_callback = device_descriptor_callback, + .config_descriptor_callback = config_descriptor_callback, + .device_quality_descriptor_callback = device_quality_descriptor_callback, + .other_speed_descriptor_callback = other_speed_config_descriptor_callback, + .string_descriptor_callback = string_descriptor_callback, +}; + +static uint8_t rndis_mac[6] = { 0x20, 0x89, 0x84, 0x6A, 0x96, 0xAA }; + +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[USB_ALIGN_UP(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE, CONFIG_USB_ALIGN_SIZE)]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[USB_ALIGN_UP(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE, CONFIG_USB_ALIGN_SIZE)]; + +volatile bool g_rndis_tx_busy_flag = false; + +static void usbd_event_handler(uint8_t busid, uint8_t event) +{ + (void)busid; + + switch (event) { + case USBD_EVENT_RESET: + break; + case USBD_EVENT_CONNECTED: + break; + case USBD_EVENT_DISCONNECTED: + break; + case USBD_EVENT_RESUME: + break; + case USBD_EVENT_SUSPEND: + break; + case USBD_EVENT_CONFIGURED: + g_rndis_tx_busy_flag = false; + usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer)); + break; + case USBD_EVENT_SET_REMOTE_WAKEUP: + break; + case USBD_EVENT_CLR_REMOTE_WAKEUP: + break; + + default: + break; + } +} + +static struct mg_tcpip_if *s_ifp; + +void usbd_rndis_data_recv_done(uint32_t len) +{ + (void)len; + + rndis_data_packet_t *hdr; + uint8_t *buf; + + hdr = (rndis_data_packet_t *)g_rndis_rx_buffer; + buf = (uint8_t *)hdr + hdr->DataOffset + sizeof(rndis_generic_msg_t); + + mg_tcpip_qwrite((void *)buf, hdr->DataLength, s_ifp); + + usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer)); +} + +void usbd_rndis_data_send_done(uint32_t len) +{ + (void)len; + + g_rndis_tx_busy_flag = false; +} + +static size_t usb_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) +{ + (void)ifp; + rndis_data_packet_t *hdr; + + if (!usb_device_is_configured(0)) + return 0; + + hdr = (rndis_data_packet_t *)g_rndis_tx_buffer; + + memset(hdr, 0, sizeof(rndis_data_packet_t)); + hdr->MessageType = REMOTE_NDIS_PACKET_MSG; + hdr->MessageLength = sizeof(rndis_data_packet_t) + len; + hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t); + hdr->DataLength = len; + + memcpy(g_rndis_tx_buffer + sizeof(rndis_data_packet_t), buf, len); + + g_rndis_tx_busy_flag = true; + usbd_rndis_start_write(g_rndis_tx_buffer, sizeof(rndis_data_packet_t) + len); + while (g_rndis_tx_busy_flag) { + } + return len; +} + +static bool usb_poll(struct mg_tcpip_if *ifp, bool s1) +{ + (void)ifp; + + return s1 ? usb_device_is_configured(0) : false; +} + +struct mg_tcpip_driver driver = { .tx = usb_tx, .poll = usb_poll }; + +struct usbd_interface intf0; +struct usbd_interface intf1; + +struct mg_mgr mgr; // Initialise Mongoose event manager + +void cdc_rndis_mongoose_init(uint8_t busid, uint32_t reg_base) +{ + mg_mgr_init(&mgr); // and attach it to the interface + + static struct mg_tcpip_if mif = { .mac = { 2, 0, 1, 2, 3, 0x77 }, + .enable_dhcp_server = true, + .driver = &driver, + .recv_queue.size = 4096 }; + s_ifp = &mif; + + mif.ip = mg_htonl(MG_U32(192, 168, 7, 1)); + mif.mask = mg_htonl(MG_U32(255, 255, 255, 0)); + mg_tcpip_init(&mgr, &mif); + + web_init(&mgr); + + usbd_desc_register(busid, &cdc_descriptor); + usbd_add_interface(busid, usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, rndis_mac)); + usbd_add_interface(busid, usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, rndis_mac)); + usbd_initialize(busid, reg_base, usbd_event_handler); +} + +// call mg_mgr_poll(&mgr, 0); in main loop \ No newline at end of file diff --git a/demo/mongoose/mongoose.png b/demo/mongoose/mongoose.png new file mode 100644 index 00000000..974ff58e Binary files /dev/null and b/demo/mongoose/mongoose.png differ diff --git a/demo/mongoose/mongoose_config.h b/demo/mongoose/mongoose_config.h new file mode 100644 index 00000000..22e957d7 --- /dev/null +++ b/demo/mongoose/mongoose_config.h @@ -0,0 +1,22 @@ +#pragma once + +// See https://mongoose.ws/documentation/#build-options +#define MG_ARCH MG_ARCH_CUSTOM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_CUSTOM_MILLIS 1 +#define MG_ENABLE_CUSTOM_RANDOM 1 +#define MG_ENABLE_PACKED_FS 1 +#define MG_IO_SIZE 1460