summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2023-11-04 16:44:02 +0800
committersakumisu <[email protected]>2023-11-04 16:44:02 +0800
commita04b1fa55122f03ad3ebbd27f089776da2f263e8 (patch)
tree8f3a395ac7311c390356ded6a4e55fd1c7111aa4
parentc37c60c7c7b07d3356a5b55a06640437662e5ef2 (diff)
add cdc ecm device
-rw-r--r--class/cdc/usb_cdc.h132
-rw-r--r--class/cdc/usbd_cdc_ecm.c237
-rw-r--r--class/cdc/usbd_cdc_ecm.h36
-rw-r--r--demo/cdc_ecm_template.c274
4 files changed, 679 insertions, 0 deletions
diff --git a/class/cdc/usb_cdc.h b/class/cdc/usb_cdc.h
index 027e08d6..de0e794f 100644
--- a/class/cdc/usb_cdc.h
+++ b/class/cdc/usb_cdc.h
@@ -212,6 +212,57 @@
#define CDC_SERIAL_STATE_RX_CARRIER_Pos (0)
#define CDC_SERIAL_STATE_RX_CARRIER_Msk (1 << CDC_SERIAL_STATE_RX_CARRIER_Pos)
+#define CDC_ECM_XMIT_OK (1 << 0)
+#define CDC_ECM_RVC_OK (1 << 1)
+#define CDC_ECM_XMIT_ERROR (1 << 2)
+#define CDC_ECM_RCV_ERROR (1 << 3)
+#define CDC_ECM_RCV_NO_BUFFER (1 << 4)
+#define CDC_ECM_DIRECTED_BYTES_XMIT (1 << 5)
+#define CDC_ECM_DIRECTED_FRAMES_XMIT (1 << 6)
+#define CDC_ECM_MULTICAST_BYTES_XMIT (1 << 7)
+#define CDC_ECM_MULTICAST_FRAMES_XMIT (1 << 8)
+#define CDC_ECM_BROADCAST_BYTES_XMIT (1 << 9)
+#define CDC_ECM_BROADCAST_FRAMES_XMIT (1 << 10)
+#define CDC_ECM_DIRECTED_BYTES_RCV (1 << 11)
+#define CDC_ECM_DIRECTED_FRAMES_RCV (1 << 12)
+#define CDC_ECM_MULTICAST_BYTES_RCV (1 << 13)
+#define CDC_ECM_MULTICAST_FRAMES_RCV (1 << 14)
+#define CDC_ECM_BROADCAST_BYTES_RCV (1 << 15)
+#define CDC_ECM_BROADCAST_FRAMES_RCV (1 << 16)
+#define CDC_ECM_RCV_CRC_ERROR (1 << 17)
+#define CDC_ECM_TRANSMIT_QUEUE_LENGTH (1 << 18)
+#define CDC_ECM_RCV_ERROR_ALIGNMENT (1 << 19)
+#define CDC_ECM_XMIT_ONE_COLLISION (1 << 20)
+#define CDC_ECM_XMIT_MORE_COLLISIONS (1 << 21)
+#define CDC_ECM_XMIT_DEFERRED (1 << 22)
+#define CDC_ECM_XMIT_MAX_COLLISIONS (1 << 23)
+#define CDC_ECM_RCV_OVERRUN (1 << 24)
+#define CDC_ECM_XMIT_UNDERRUN (1 << 25)
+#define CDC_ECM_XMIT_HEARTBEAT_FAILURE (1 << 26)
+#define CDC_ECM_XMIT_TIMES_CRS_LOST (1 << 27)
+#define CDC_ECM_XMIT_LATE_COLLISIONS (1 << 28)
+
+#define CDC_ECM_MAC_STR_DESC (uint8_t *)"010202030000"
+#define CDC_ECM_MAC_ADDR0 0x00U /* 01 */
+#define CDC_ECM_MAC_ADDR1 0x02U /* 02 */
+#define CDC_ECM_MAC_ADDR2 0x02U /* 03 */
+#define CDC_ECM_MAC_ADDR3 0x03U /* 00 */
+#define CDC_ECM_MAC_ADDR4 0x00U /* 00 */
+#define CDC_ECM_MAC_ADDR5 0x00U /* 00 */
+
+#define CDC_ECM_NET_DISCONNECTED 0x00U
+#define CDC_ECM_NET_CONNECTED 0x01U
+
+#define CDC_ECM_ETH_STATS_RESERVED 0xE0U
+#define CDC_ECM_BMREQUEST_TYPE_ECM 0xA1U
+
+#define CDC_ECM_CONNECT_SPEED_UPSTREAM 0x004C4B40U /* 5Mbps */
+#define CDC_ECM_CONNECT_SPEED_DOWNSTREAM 0x004C4B40U /* 5Mbps */
+
+#define CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION 0x00
+#define CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE 0x01
+#define CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE 0x2A
+
/*------------------------------------------------------------------------------
* Structures based on usbcdc11.pdf (www.usb.org)
*----------------------------------------------------------------------------*/
@@ -299,6 +350,15 @@ struct cdc_ecm_descriptor {
uint8_t bNumberPowerFilters;
} __PACKED;
+struct cdc_ecm_notification {
+ uint8_t bmRequestType;
+ uint8_t bNotificationType;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+ uint8_t data[8];
+} __PACKED;
+
/*Length of template descriptor: 66 bytes*/
#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
// clang-format off
@@ -437,4 +497,76 @@ struct cdc_ecm_descriptor {
0x00 /* bInterval */
// clang-format on
+#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
+
+/*Length of template descriptor: 66 bytes*/
+#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 7 + 7)
+// clang-format off
+#define CDC_ECM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
+eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) \
+ /* Interface Associate */ \
+ 0x08, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
+ bFirstInterface, /* bFirstInterface */ \
+ 0x02, /* bInterfaceCount */ \
+ USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
+ CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bFunctionSubClass */ \
+ CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
+ 0x00, /* iFunction */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bFirstInterface, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x01, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
+ CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bInterfaceSubClass */ \
+ CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
+ str_idx, /* iInterface */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
+ WBVAL(CDC_V1_10), /* bcdCDC */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
+ bFirstInterface, /* bMasterInterface */ \
+ (uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
+ /* CDC_ECM Functional Descriptor */ \
+ 0x0D, /* bFunctionLength */\
+ CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */\
+ CDC_FUNC_DESC_ETHERNET_NETWORKING, /* Ethernet Networking functional descriptor subtype */\
+ str_idx, /* Device's MAC string index */\
+ DBVAL_BE(eth_statistics), /* Ethernet statistics (bitmap) */\
+ WBVAL(wMaxPacketSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
+ WBVAL(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
+ bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ int_ep, /* bEndpointAddress */ \
+ 0x03, /* bmAttributes */ \
+ 0x10, 0x00, /* wMaxPacketSize */ \
+ 0x10, /* bInterval */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x02, /* bNumEndpoints */ \
+ CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
+ 0x00, /* bInterfaceSubClass */ \
+ 0x00, /* bInterfaceProtocol */ \
+ 0x00, /* iInterface */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ out_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
+ 0x00, /* bInterval */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ in_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
+ 0x00 /* bInterval */
+// clang-format on
+
#endif /* USB_CDC_H */
diff --git a/class/cdc/usbd_cdc_ecm.c b/class/cdc/usbd_cdc_ecm.c
new file mode 100644
index 00000000..1ebdecf6
--- /dev/null
+++ b/class/cdc/usbd_cdc_ecm.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2023, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_cdc_ecm.h"
+
+#define CDC_ECM_OUT_EP_IDX 0
+#define CDC_ECM_IN_EP_IDX 1
+#define CDC_ECM_INT_EP_IDX 2
+
+/* Describe EndPoints configuration */
+static struct usbd_endpoint cdc_ecm_ep_data[3];
+
+#ifdef CONFIG_USB_HS
+#define CDC_ECM_MAX_PACKET_SIZE 512
+#else
+#define CDC_ECM_MAX_PACKET_SIZE 64
+#endif
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
+
+volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL;
+volatile uint32_t g_cdc_ecm_rx_data_length = 0;
+volatile uint32_t g_cdc_ecm_tx_data_length = 0;
+
+static volatile uint8_t g_current_net_status = 0;
+static volatile uint8_t g_cmd_intf = 0;
+
+static uint32_t g_connect_speed_table[2] = { CDC_ECM_CONNECT_SPEED_UPSTREAM,
+ CDC_ECM_CONNECT_SPEED_DOWNSTREAM };
+
+void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed)
+{
+ struct cdc_ecm_notification *notify = (struct cdc_ecm_notification *)g_cdc_ecm_notify_buf;
+ uint8_t bytes2send = 0;
+
+ notify->bmRequestType = CDC_ECM_BMREQUEST_TYPE_ECM;
+ notify->bNotificationType = notifycode;
+
+ switch (notifycode) {
+ case CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION:
+ notify->wValue = value;
+ notify->wIndex = g_cmd_intf;
+ notify->wLength = 0U;
+
+ for (uint8_t i = 0U; i < 8U; i++) {
+ notify->data[i] = 0U;
+ }
+ bytes2send = 8U;
+ break;
+ case CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE:
+ notify->wValue = 0U;
+ notify->wIndex = g_cmd_intf;
+ notify->wLength = 0U;
+ for (uint8_t i = 0U; i < 8U; i++) {
+ notify->data[i] = 0U;
+ }
+ bytes2send = 8U;
+ break;
+ case CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE:
+ notify->wValue = 0U;
+ notify->wIndex = g_cmd_intf;
+ notify->wLength = 0x0008U;
+ bytes2send = 16U;
+
+ memcpy(notify->data, speed, 8);
+ break;
+
+ default:
+ break;
+ }
+
+ if (bytes2send) {
+ usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
+ }
+}
+
+static int cdc_ecm_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_DBG("CDC ECM Class request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
+
+ g_cmd_intf = LO_BYTE(setup->wIndex);
+
+ switch (setup->bRequest) {
+ case CDC_REQUEST_SET_ETHERNET_PACKET_FILTER:
+ /* bit0 Promiscuous
+ * bit1 ALL Multicast
+ * bit2 Directed
+ * bit3 Broadcast
+ * bit4 Multicast
+ */
+ if (g_current_net_status == 0) {
+ g_current_net_status = 1;
+ usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
+ }
+
+ break;
+ default:
+ USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+
+ return 0;
+}
+
+void cdc_ecm_notify_handler(uint8_t event, void *arg)
+{
+ switch (event) {
+ case USBD_EVENT_RESET:
+ g_current_net_status = 0;
+ g_cdc_ecm_rx_data_length = 0;
+ g_cdc_ecm_tx_data_length = 0;
+ g_cdc_ecm_rx_data_buffer = NULL;
+ break;
+ case USBD_EVENT_CONFIGURED:
+ usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void cdc_ecm_bulk_out(uint8_t ep, uint32_t nbytes)
+{
+ g_cdc_ecm_rx_data_length += nbytes;
+
+ if (nbytes < CDC_ECM_MAX_PACKET_SIZE) {
+ g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
+ usbd_cdc_ecm_data_recv_done();
+ } else {
+ usbd_ep_start_read(ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
+ }
+}
+
+void cdc_ecm_bulk_in(uint8_t ep, uint32_t nbytes)
+{
+ if ((nbytes % CDC_ECM_MAX_PACKET_SIZE) == 0 && nbytes) {
+ /* send zlp */
+ usbd_ep_start_write(ep, NULL, 0);
+ } else {
+ g_cdc_ecm_tx_data_length = 0;
+ }
+}
+
+void cdc_ecm_int_in(uint8_t ep, uint32_t nbytes)
+{
+ if (g_current_net_status == 1) {
+ g_current_net_status = 2;
+ usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
+ }
+}
+
+#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
+struct pbuf *usbd_cdc_ecm_eth_rx(void)
+{
+ struct pbuf *p;
+
+ if (g_cdc_ecm_rx_data_buffer == NULL) {
+ return NULL;
+ }
+ p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
+ if (p == NULL) {
+ return NULL;
+ }
+ memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
+ p->len = g_cdc_ecm_rx_data_length;
+
+ USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
+ g_cdc_ecm_rx_data_length = 0;
+ g_cdc_ecm_rx_data_buffer = NULL;
+ usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, CDC_ECM_MAX_PACKET_SIZE);
+
+ return p;
+}
+
+int usbd_cdc_ecm_eth_tx(struct pbuf *p)
+{
+ struct pbuf *q;
+ uint8_t *buffer;
+
+ if (g_cdc_ecm_tx_data_length > 0) {
+ return -EBUSY;
+ }
+
+ if (p->tot_len > sizeof(g_cdc_ecm_tx_buffer)) {
+ p->tot_len = sizeof(g_cdc_ecm_tx_buffer);
+ }
+
+ buffer = g_cdc_ecm_tx_buffer;
+ for (q = p; q != NULL; q = q->next) {
+ memcpy(buffer, q->payload, q->len);
+ buffer += q->len;
+ }
+
+ g_cdc_ecm_tx_data_length = p->tot_len;
+
+ USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
+ return usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, g_cdc_ecm_tx_buffer, g_cdc_ecm_tx_data_length);
+}
+#endif
+
+struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep)
+{
+ intf->class_interface_handler = cdc_ecm_class_interface_request_handler;
+ intf->class_endpoint_handler = NULL;
+ intf->vendor_handler = NULL;
+ intf->notify_handler = cdc_ecm_notify_handler;
+
+ cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr = out_ep;
+ cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_cb = cdc_ecm_bulk_out;
+ cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr = in_ep;
+ cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_cb = cdc_ecm_bulk_in;
+ cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr = int_ep;
+ cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_cb = cdc_ecm_int_in;
+
+ usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
+ usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
+ usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX]);
+
+ return intf;
+}
+
+void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
+{
+ memcpy(g_connect_speed_table, speed, 8);
+}
+
+__WEAK void usbd_cdc_ecm_data_recv_done(void)
+{
+} \ No newline at end of file
diff --git a/class/cdc/usbd_cdc_ecm.h b/class/cdc/usbd_cdc_ecm.h
new file mode 100644
index 00000000..8381b1a5
--- /dev/null
+++ b/class/cdc/usbd_cdc_ecm.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_CDC_ECM_H
+#define USBD_CDC_ECM_H
+
+#include "usb_cdc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Ethernet Maximum Segment size, typically 1514 bytes */
+#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
+#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
+
+/* Init cdc ecm interface driver */
+struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
+
+/* Setup request command callback api */
+void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
+void usbd_cdc_ecm_data_recv_done(void);
+
+#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
+#include <lwip/pbuf.h>
+struct pbuf *usbd_cdc_ecm_eth_rx(void);
+int usbd_cdc_ecm_eth_tx(struct pbuf *p);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_CDC_ECM_H */
diff --git a/demo/cdc_ecm_template.c b/demo/cdc_ecm_template.c
new file mode 100644
index 00000000..8eb6d03f
--- /dev/null
+++ b/demo/cdc_ecm_template.c
@@ -0,0 +1,274 @@
+#include "usbd_core.h"
+#include "usbd_cdc_ecm.h"
+
+/*!< endpoint address */
+#define CDC_IN_EP 0x81
+#define CDC_OUT_EP 0x02
+#define CDC_INT_EP 0x83
+
+#define USBD_VID 0xFFFF
+#define USBD_PID 0xFFFF
+#define USBD_MAX_POWER 100
+#define USBD_LANGID_STRING 1033
+
+/*!< config descriptor size */
+#define USB_CONFIG_SIZE (9 + CDC_ECM_DESCRIPTOR_LEN)
+
+#ifdef CONFIG_USB_HS
+#define CDC_MAX_MPS 512
+#else
+#define CDC_MAX_MPS 64
+#endif
+
+#define CDC_ECM_ETH_STATISTICS_BITMAP 0x00000000
+
+/* str idx = 4 is for mac address: aa:bb:cc:dd:ee:ff*/
+#define CDC_ECM_MAC_STRING_INDEX 4
+
+/*!< global descriptor */
+static const uint8_t cdc_ecm_descriptor[] = {
+ USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
+ USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+ CDC_ECM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, CDC_ECM_ETH_STATISTICS_BITMAP, CONFIG_CDC_ECM_ETH_MAX_SEGSZE, 0, 0, CDC_ECM_MAC_STRING_INDEX),
+ ///////////////////////////////////////
+ /// string0 descriptor
+ ///////////////////////////////////////
+ USB_LANGID_INIT(USBD_LANGID_STRING),
+ ///////////////////////////////////////
+ /// string1 descriptor
+ ///////////////////////////////////////
+ 0x14, /* bLength */
+ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+ 'C', 0x00, /* wcChar0 */
+ 'h', 0x00, /* wcChar1 */
+ 'e', 0x00, /* wcChar2 */
+ 'r', 0x00, /* wcChar3 */
+ 'r', 0x00, /* wcChar4 */
+ 'y', 0x00, /* wcChar5 */
+ 'U', 0x00, /* wcChar6 */
+ 'S', 0x00, /* wcChar7 */
+ 'B', 0x00, /* wcChar8 */
+ ///////////////////////////////////////
+ /// string2 descriptor
+ ///////////////////////////////////////
+ 0x2E, /* bLength */
+ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+ 'C', 0x00, /* wcChar0 */
+ 'h', 0x00, /* wcChar1 */
+ 'e', 0x00, /* wcChar2 */
+ 'r', 0x00, /* wcChar3 */
+ 'r', 0x00, /* wcChar4 */
+ 'y', 0x00, /* wcChar5 */
+ 'U', 0x00, /* wcChar6 */
+ 'S', 0x00, /* wcChar7 */
+ 'B', 0x00, /* wcChar8 */
+ ' ', 0x00, /* wcChar9 */
+ 'C', 0x00, /* wcChar10 */
+ 'D', 0x00, /* wcChar11 */
+ 'C', 0x00, /* wcChar12 */
+ ' ', 0x00, /* wcChar13 */
+ 'E', 0x00, /* wcChar14 */
+ 'C', 0x00, /* wcChar15 */
+ 'M', 0x00, /* wcChar16 */
+ ' ', 0x00, /* wcChar17 */
+ 'D', 0x00, /* wcChar18 */
+ 'E', 0x00, /* wcChar19 */
+ 'M', 0x00, /* wcChar20 */
+ 'O', 0x00, /* wcChar21 */
+ ///////////////////////////////////////
+ /// string3 descriptor
+ ///////////////////////////////////////
+ 0x16, /* bLength */
+ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+ '2', 0x00, /* wcChar0 */
+ '0', 0x00, /* wcChar1 */
+ '2', 0x00, /* wcChar2 */
+ '2', 0x00, /* wcChar3 */
+ '1', 0x00, /* wcChar4 */
+ '2', 0x00, /* wcChar5 */
+ '3', 0x00, /* wcChar6 */
+ '4', 0x00, /* wcChar7 */
+ '5', 0x00, /* wcChar8 */
+ '6', 0x00, /* wcChar9 */
+ ///////////////////////////////////////
+ /// string4 descriptor
+ ///////////////////////////////////////
+ 0x1A, /* bLength */
+ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+ 'a', 0x00, /* wcChar0 */
+ 'a', 0x00, /* wcChar1 */
+ 'b', 0x00, /* wcChar2 */
+ 'b', 0x00, /* wcChar3 */
+ 'c', 0x00, /* wcChar4 */
+ 'c', 0x00, /* wcChar5 */
+ 'd', 0x00, /* wcChar6 */
+ 'd', 0x00, /* wcChar7 */
+ 'e', 0x00, /* wcChar8 */
+ 'e', 0x00, /* wcChar9 */
+ 'f', 0x00, /* wcChar10 */
+ 'f', 0x00, /* wcChar11 */
+#ifdef CONFIG_USB_HS
+ ///////////////////////////////////////
+ /// device qualifier descriptor
+ ///////////////////////////////////////
+ 0x0a,
+ USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+ 0x00,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x01,
+ 0x40,
+ 0x01,
+ 0x00,
+#endif
+ 0x00
+};
+
+const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+
+/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
+#define IP_ADDR0 (uint8_t)192
+#define IP_ADDR1 (uint8_t)168
+#define IP_ADDR2 (uint8_t)123
+#define IP_ADDR3 (uint8_t)100
+
+/*NETMASK*/
+#define NETMASK_ADDR0 (uint8_t)255
+#define NETMASK_ADDR1 (uint8_t)255
+#define NETMASK_ADDR2 (uint8_t)255
+#define NETMASK_ADDR3 (uint8_t)0
+
+/*Gateway Address*/
+#define GW_ADDR0 (uint8_t)192
+#define GW_ADDR1 (uint8_t)168
+#define GW_ADDR2 (uint8_t)123
+#define GW_ADDR3 (uint8_t)1
+
+#include "netif/etharp.h"
+#include "lwip/init.h"
+#include "lwip/netif.h"
+#include "lwip/pbuf.h"
+
+const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
+const ip_addr_t netmask = IPADDR4_INIT_BYTES(NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
+const ip_addr_t gateway = IPADDR4_INIT_BYTES(GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+
+static struct netif cdc_ecm_netif; //network interface
+
+/* Network interface name */
+#define IFNAME0 'E'
+#define IFNAME1 'X'
+
+static err_t linkoutput_fn(struct netif *netif, struct pbuf *p)
+{
+ static int ret;
+
+ ret = usbd_cdc_ecm_eth_tx(p);
+ if (ret == 0)
+ return ERR_OK;
+ else
+ return ERR_BUF;
+}
+
+err_t cdc_ecm_if_init(struct netif *netif)
+{
+ LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+ netif->mtu = 1500;
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
+ netif->state = NULL;
+ netif->name[0] = IFNAME0;
+ netif->name[1] = IFNAME1;
+ netif->output = etharp_output;
+ netif->linkoutput = linkoutput_fn;
+ return ERR_OK;
+}
+
+err_t cdc_ecm_if_input(struct netif *netif)
+{
+ static err_t err;
+ static struct pbuf *p;
+
+ p = usbd_cdc_ecm_eth_rx();
+ if (p != NULL) {
+ err = netif->input(p, netif);
+ if (err != ERR_OK) {
+ pbuf_free(p);
+ }
+ } else {
+ return ERR_BUF;
+ }
+ return err;
+}
+
+void cdc_ecm_lwip_init(void)
+{
+ struct netif *netif = &cdc_ecm_netif;
+
+ lwip_init();
+
+ netif->hwaddr_len = 6;
+ memcpy(netif->hwaddr, mac, 6);
+
+ netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, cdc_ecm_if_init, netif_input);
+ netif_set_default(netif);
+ while (!netif_is_up(netif)) {
+ }
+
+ // while (dhserv_init(&dhcp_config)) {}
+
+ // while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
+}
+
+void usbd_cdc_ecm_data_recv_done(void)
+{
+}
+
+void cdc_ecm_input_poll(void)
+{
+ cdc_ecm_if_input(&cdc_ecm_netif);
+}
+
+void usbd_event_handler(uint8_t event)
+{
+ 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:
+ break;
+ case USBD_EVENT_SET_REMOTE_WAKEUP:
+ break;
+ case USBD_EVENT_CLR_REMOTE_WAKEUP:
+ break;
+
+ default:
+ break;
+ }
+}
+
+struct usbd_interface intf0;
+struct usbd_interface intf1;
+
+/* ecm only supports in linux, and you should input the following command
+ *
+ * sudo ifconfig enxaabbccddeeff up
+ * sudo dhcpclient enxaabbccddeeff
+*/
+void cdc_ecm_init(void)
+{
+ cdc_ecm_lwip_init();
+
+ usbd_desc_register(cdc_ecm_descriptor);
+ usbd_add_interface(usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
+ usbd_add_interface(usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
+ usbd_initialize();
+} \ No newline at end of file