summaryrefslogtreecommitdiff
path: root/components/drivers
diff options
context:
space:
mode:
authoruestczyh222 <[email protected]>2017-11-21 22:37:22 +0800
committeruestczyh222 <[email protected]>2017-11-21 22:44:13 +0800
commitbd566e6a37a99f311e95e5bd2a0b8aac265aca4d (patch)
tree2c03a77253926b74f33cbb37c25b8df193f60bf2 /components/drivers
parent334da974c37f2dbec5e5cdc5c59074f3425cd808 (diff)
[Components][Drivers][USB] Add CDC-ECM class (LWIP on USB)
Windows下没驱动 linux和mac下免驱
Diffstat (limited to 'components/drivers')
-rw-r--r--components/drivers/KConfig8
-rw-r--r--components/drivers/usb/usbdevice/SConscript3
-rw-r--r--components/drivers/usb/usbdevice/class/cdc.h64
-rw-r--r--components/drivers/usb/usbdevice/class/ecm.c602
-rw-r--r--components/drivers/usb/usbdevice/core/usbdevice.c11
5 files changed, 686 insertions, 2 deletions
diff --git a/components/drivers/KConfig b/components/drivers/KConfig
index d968f7837f..6770a7815d 100644
--- a/components/drivers/KConfig
+++ b/components/drivers/KConfig
@@ -132,6 +132,10 @@ menu "Using USB"
config _RT_USB_DEVICE_HID
bool "Enable to use device as HID device"
select RT_USB_DEVICE_HID
+ config _RT_USB_DEVICE_ECM
+ bool "Enable to use device as ecm device"
+ select RT_USB_DEVICE_ECM
+ depends on RT_USING_LWIP
endchoice
if RT_USB_DEVICE_COMPOSITE
config RT_USB_DEVICE_CDC
@@ -143,6 +147,10 @@ menu "Using USB"
config RT_USB_DEVICE_HID
bool "Enable to use device as HID device"
default n
+ config RT_USB_DEVICE_ECM
+ bool "Enable to use device as ecm device"
+ default n
+ depends on RT_USING_LWIP
endif
if RT_USB_DEVICE_HID
diff --git a/components/drivers/usb/usbdevice/SConscript b/components/drivers/usb/usbdevice/SConscript
index 760000a887..29914333fc 100644
--- a/components/drivers/usb/usbdevice/SConscript
+++ b/components/drivers/usb/usbdevice/SConscript
@@ -16,6 +16,9 @@ if GetDepend('RT_USB_DEVICE_HID'):
if GetDepend('RT_USB_DEVICE_MSTORAGE'):
src += Glob('class/mstorage.c')
+if GetDepend('RT_USB_DEVICE_ECM'):
+ src += Glob('class/ecm.c')
+
CPPPATH = [cwd]
group = DefineGroup('rt_usbd', src, depend = ['RT_USING_USB_DEVICE'], CPPPATH = CPPPATH)
diff --git a/components/drivers/usb/usbdevice/class/cdc.h b/components/drivers/usb/usbdevice/class/cdc.h
index 66b4c602a0..dd919f51fe 100644
--- a/components/drivers/usb/usbdevice/class/cdc.h
+++ b/components/drivers/usb/usbdevice/class/cdc.h
@@ -31,6 +31,7 @@
#define USB_CDC_CLASS_COMM 0x02
#define USB_CDC_CLASS_DATA 0x0A
+#define USB_CDC_SUBCLASS_NONE 0x00
#define USB_CDC_SUBCLASS_DLCM 0x01
#define USB_CDC_SUBCLASS_ACM 0x02
#define USB_CDC_SUBCLASS_TCM 0x03
@@ -38,9 +39,10 @@
#define USB_CDC_SUBCLASS_CCM 0x05
#define USB_CDC_SUBCLASS_ETH 0x06
#define USB_CDC_SUBCLASS_ATM 0x07
+#define USB_CDC_SUBCLASS_EEM 0x0C
+#define USB_CDC_PROTOCOL_NONE 0x00
#define USB_CDC_PROTOCOL_V25TER 0x01
-
#define USB_CDC_PROTOCOL_I430 0x30
#define USB_CDC_PROTOCOL_HDLC 0x31
#define USB_CDC_PROTOCOL_TRANS 0x32
@@ -54,6 +56,7 @@
#define USB_CDC_PROTOCOL_HOST 0xFD
#define USB_CDC_PROTOCOL_PUFD 0xFE
#define USB_CDC_PROTOCOL_VENDOR 0xFF
+#define USB_CDC_PROTOCOL_EEM 0x07
#define USB_CDC_CS_INTERFACE 0x24
#define USB_CDC_CS_ENDPOINT 0x25
@@ -62,6 +65,7 @@
#define USB_CDC_SCS_CALL_MGMT 0x01
#define USB_CDC_SCS_ACM 0x02
#define USB_CDC_SCS_UNION 0x06
+#define USB_CDC_SCS_ETH 0x0F
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
@@ -153,6 +157,30 @@ struct ucdc_comm_descriptor
};
typedef struct ucdc_comm_descriptor* ucdc_comm_desc_t;
+struct ucdc_enet_descriptor
+{
+ rt_uint8_t bFunctionLength;
+ rt_uint8_t bDescriptorType;
+ rt_uint8_t bDescriptorSubtype;
+ rt_uint8_t iMACAddress;
+ rt_uint8_t bmEthernetStatistics[4];
+ rt_uint16_t wMaxSegmentSize;
+ rt_uint16_t wMCFilters;
+ rt_uint8_t bNumberPowerFilters;
+};
+struct ucdc_eth_descriptor
+{
+#ifdef RT_USB_DEVICE_COMPOSITE
+ struct uiad_descriptor iad_desc;
+#endif
+ struct uinterface_descriptor intf_desc;
+ struct ucdc_header_descriptor hdr_desc;
+ struct ucdc_union_descriptor union_desc;
+ struct ucdc_enet_descriptor enet_desc;
+ struct uendpoint_descriptor ep_desc;
+};
+typedef struct ucdc_eth_descriptor* ucdc_eth_desc_t;
+
struct ucdc_data_descriptor
{
struct uinterface_descriptor intf_desc;
@@ -177,7 +205,39 @@ struct cdc_eps
uep_t ep_cmd;
};
typedef struct cdc_eps* cdc_eps_t;
-
+
+
+
+struct ucdc_management_element_notifications
+{
+ rt_uint8_t bmRequestType;
+ rt_uint8_t bNotificatinCode;
+ rt_uint16_t wValue;
+ rt_uint16_t wIndex;
+ rt_uint16_t wLength;
+};
+typedef struct ucdc_management_element_notifications * ucdc_mg_notifications_t;
+
+struct ucdc_connection_speed_change_data
+{
+ rt_uint32_t down_bit_rate;
+ rt_uint32_t up_bit_rate;
+};
+typedef struct connection_speed_change_data * connect_speed_data_t;
+
+enum ucdc_notification_code
+{
+ UCDC_NOTIFI_NETWORK_CONNECTION = 0x00,
+ UCDC_NOTIFI_RESPONSE_AVAILABLE = 0x01,
+ UCDC_NOTIFI_AUX_JACK_HOOK_STATE = 0x08,
+ UCDC_NOTIFI_RING_DETECT = 0x09,
+ UCDC_NOTIFI_SERIAL_STATE = 0x20,
+ UCDC_NOTIFI_CALL_STATE_CHANGE = 0x28,
+ UCDC_NOTIFI_LINE_STATE_CHANGE = 0x29,
+ UCDC_NOTIFI_CONNECTION_SPEED_CHANGE = 0x2A,
+};
+typedef enum ucdc_notification_code ucdc_notification_code_t;
+
#pragma pack()
#endif
diff --git a/components/drivers/usb/usbdevice/class/ecm.c b/components/drivers/usb/usbdevice/class/ecm.c
new file mode 100644
index 0000000000..4a45bc0939
--- /dev/null
+++ b/components/drivers/usb/usbdevice/class/ecm.c
@@ -0,0 +1,602 @@
+/*
+ * File : ecm.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006-2013, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-11-19 ZYH first version
+ */
+
+#include <rtdevice.h>
+#include "cdc.h"
+
+
+#ifdef ECM_DEBUG
+#define ECM_PRINTF rt_kprintf("[ECM] "); rt_kprintf
+#else
+#define ECM_PRINTF(...)
+#endif /* ECM_DEBUG */
+
+/* RT-Thread LWIP ethernet interface */
+#include <netif/ethernetif.h>
+
+#ifndef USB_ETH_MTU
+#define USB_ETH_MTU 1514
+#endif
+#define MAX_ADDR_LEN 6
+
+struct rt_ecm_eth
+{
+ /* inherit from ethernet device */
+ struct eth_device parent;
+ struct ufunction * func;
+ struct cdc_eps eps;
+ /* interface address info */
+ rt_uint8_t host_addr[MAX_ADDR_LEN];
+ rt_uint8_t dev_addr[MAX_ADDR_LEN];
+
+ ALIGN(4)
+ rt_uint8_t rx_pool[64];
+ ALIGN(4)
+ rt_size_t rx_size;
+ ALIGN(4)
+ rt_size_t rx_offset;
+ ALIGN(4)
+ char rx_buffer[USB_ETH_MTU];
+ char tx_buffer[USB_ETH_MTU];
+
+ struct rt_semaphore tx_buffer_free;
+
+};
+typedef struct rt_ecm_eth * rt_ecm_eth_t;
+
+ALIGN(4)
+static struct udevice_descriptor _dev_desc =
+{
+ USB_DESC_LENGTH_DEVICE, /* bLength */
+ USB_DESC_TYPE_DEVICE, /* type */
+ USB_BCD_VERSION, /* bcdUSB */
+ USB_CLASS_CDC, /* bDeviceClass */
+ USB_CDC_SUBCLASS_ETH, /* bDeviceSubClass */
+ USB_CDC_PROTOCOL_NONE, /* bDeviceProtocol */
+ 0x40, /* bMaxPacketSize0 */
+ _VENDOR_ID, /* idVendor */
+ _PRODUCT_ID, /* idProduct */
+ USB_BCD_DEVICE, /* bcdDevice */
+ USB_STRING_MANU_INDEX, /* iManufacturer */
+ USB_STRING_PRODUCT_INDEX, /* iProduct */
+ USB_STRING_SERIAL_INDEX, /* iSerialNumber */
+ USB_DYNAMIC /* bNumConfigurations */
+};
+
+/* communcation interface descriptor */
+ALIGN(4)
+const static struct ucdc_eth_descriptor _comm_desc =
+{
+#ifdef RT_USB_DEVICE_COMPOSITE
+ /* Interface Association Descriptor */
+ USB_DESC_LENGTH_IAD,
+ USB_DESC_TYPE_IAD,
+ USB_DYNAMIC,
+ 0x02,
+ USB_CDC_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETH,
+ USB_CDC_PROTOCOL_NONE,
+ 0x00,
+#endif
+ /* Interface Descriptor */
+ USB_DESC_LENGTH_INTERFACE,
+ USB_DESC_TYPE_INTERFACE,
+ USB_DYNAMIC,
+ 0x00,
+ 0x01,
+ USB_CDC_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETH,
+ USB_CDC_PROTOCOL_NONE,
+ 0x00,
+ /* Header Functional Descriptor */
+ sizeof(struct ucdc_header_descriptor),
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_HEADER,
+ 0x0110,
+ /* Union Functional Descriptor */
+ sizeof(struct ucdc_union_descriptor),
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_UNION,
+ USB_DYNAMIC,
+ USB_DYNAMIC,
+ /* Abstract Control Management Functional Descriptor */
+ sizeof(struct ucdc_enet_descriptor),
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_ETH,
+ USB_STRING_SERIAL_INDEX,
+ {0,0,0,0},
+ USB_ETH_MTU,
+ 0x00,
+ 0x00,
+ /* Endpoint Descriptor */
+ USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_TYPE_ENDPOINT,
+ USB_DIR_IN | USB_DYNAMIC,
+ USB_EP_ATTR_INT,
+ 0x08,
+ 0xFF,
+};
+
+/* data interface descriptor */
+ALIGN(4)
+const static struct ucdc_data_descriptor _data_desc =
+{
+ /* interface descriptor */
+ USB_DESC_LENGTH_INTERFACE,
+ USB_DESC_TYPE_INTERFACE,
+ USB_DYNAMIC,
+ 0x00,
+ 0x02,
+ USB_CDC_CLASS_DATA,
+ USB_CDC_SUBCLASS_ETH,
+ 0x00,
+ 0x00,
+ /* endpoint, bulk out */
+ USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_TYPE_ENDPOINT,
+ USB_DIR_OUT | USB_DYNAMIC,
+ USB_EP_ATTR_BULK,
+ USB_CDC_BUFSIZE,
+ 0x00,
+ /* endpoint, bulk in */
+ USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_TYPE_ENDPOINT,
+ USB_DYNAMIC | USB_DIR_IN,
+ USB_EP_ATTR_BULK,
+ USB_CDC_BUFSIZE,
+ 0x00,
+};
+
+ALIGN(4)
+const static char* _ustring[] =
+{
+ "Language", /* LANGID */
+ "RT-Thread Team.", /* MANU */
+ "RT-Thread ECM device", /* PRODUCT */
+ "3497F694ECAB", /* SERIAL (MAC)*/
+ "Configuration", /* CONFIG */
+ "Interface", /* INTERFACE */
+};
+
+ALIGN(4)
+static struct usb_qualifier_descriptor dev_qualifier =
+{
+ sizeof(dev_qualifier),
+ USB_DESC_TYPE_DEVICEQUALIFIER,
+ 0x0200,
+ USB_CLASS_CDC,
+ 0x00,
+ 64,
+ 0x01,
+ 0,
+};
+static rt_err_t _cdc_send_notifi(ufunction_t func,ucdc_notification_code_t notifi,rt_uint16_t wValue,rt_uint16_t wLength)
+{
+ static struct ucdc_management_element_notifications _notifi;
+ cdc_eps_t eps;
+ RT_ASSERT(func!=RT_NULL)
+ eps = &((rt_ecm_eth_t)func->user_data)->eps;
+ _notifi.bmRequestType = 0xA1;
+ _notifi.bNotificatinCode = notifi;
+ _notifi.wValue = wValue;
+ _notifi.wLength = wLength;
+
+ eps->ep_cmd->request.buffer = (void *)&_notifi;
+ eps->ep_cmd->request.size = 8;
+ eps->ep_cmd->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, eps->ep_cmd, &eps->ep_cmd->request);
+ return RT_EOK;
+}
+
+static rt_err_t _ecm_set_eth_packet_filter(ufunction_t func, ureq_t setup)
+{
+ rt_ecm_eth_t _ecm_eth = (rt_ecm_eth_t)func->user_data;
+ dcd_ep0_send_status(func->device->dcd);
+
+
+ /* send link up. */
+ eth_device_linkchange(&_ecm_eth->parent, RT_TRUE);
+ _cdc_send_notifi(func,UCDC_NOTIFI_NETWORK_CONNECTION,1,0);
+ return RT_EOK;
+}
+/**
+ * This function will handle rndis interface request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
+{
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ switch(setup->bRequest)
+ {
+ case CDC_SET_ETH_PACKET_FILTER:
+ _ecm_set_eth_packet_filter(func, setup);
+ break;
+ default:
+ rt_kprintf("setup->bRequest:0x%02X",setup->bRequest);
+ break;
+ }
+ return RT_EOK;
+}
+
+/**
+ * This function will handle rndis bulk in endpoint request.
+ *
+ * @param device the usb device object.
+ * @param size request size.
+ *
+ * @return RT_EOK.
+ */
+
+static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
+{
+ rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data;
+ rt_sem_release(&ecm_device->tx_buffer_free);
+ return RT_EOK;
+}
+
+/**
+ * This function will handle RNDIS bulk out endpoint request.
+ *
+ * @param device the usb device object.
+ * @param size request size.
+ *
+ * @return RT_EOK.
+ */
+static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
+{
+ rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data;
+ rt_memcpy((void *)(ecm_device->rx_buffer + ecm_device->rx_offset),ecm_device->rx_pool,size);
+ ecm_device->rx_offset += size;
+ if(size < EP_MAXPACKET(ecm_device->eps.ep_out))
+ {
+ ecm_device->rx_size = ecm_device->rx_offset;
+ ecm_device->rx_offset = 0;
+ eth_device_ready(&ecm_device->parent);
+
+ }else
+ {
+ ecm_device->eps.ep_out->request.buffer = ecm_device->eps.ep_out->buffer;
+ ecm_device->eps.ep_out->request.size = EP_MAXPACKET(ecm_device->eps.ep_out);
+ ecm_device->eps.ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(ecm_device->func->device, ecm_device->eps.ep_out, &ecm_device->eps.ep_out->request);
+ }
+
+
+ return RT_EOK;
+}
+static rt_err_t rt_ecm_eth_init(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_err_t rt_ecm_eth_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ return RT_EOK;
+}
+
+static rt_err_t rt_ecm_eth_close(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_size_t rt_ecm_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+
+static rt_size_t rt_ecm_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+static rt_err_t rt_ecm_eth_control(rt_device_t dev, int cmd, void *args)
+{
+ rt_ecm_eth_t ecm_eth_dev = (rt_ecm_eth_t)dev;
+ switch(cmd)
+ {
+ case NIOCTL_GADDR:
+ /* get mac address */
+ if(args) rt_memcpy(args, ecm_eth_dev->dev_addr, MAX_ADDR_LEN);
+ else return -RT_ERROR;
+ break;
+
+ default :
+ break;
+ }
+
+ return RT_EOK;
+}
+struct pbuf *rt_ecm_eth_rx(rt_device_t dev)
+{
+ struct pbuf* p = RT_NULL;
+ rt_uint32_t offset = 0;
+ rt_ecm_eth_t ecm_eth_dev = (rt_ecm_eth_t)dev;
+ if(ecm_eth_dev->rx_size != 0)
+ {
+ /* allocate buffer */
+ p = pbuf_alloc(PBUF_RAW, ecm_eth_dev->rx_size, PBUF_RAM);
+ if (p != RT_NULL)
+ {
+ struct pbuf* q;
+
+ for (q = p; q != RT_NULL; q= q->next)
+ {
+ /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */
+ rt_memcpy(q->payload,
+ (rt_uint8_t *)((ecm_eth_dev->rx_buffer) + offset),
+ q->len);
+ offset += q->len;
+ }
+ }
+ }
+
+ {
+ if(ecm_eth_dev->func->device->state == USB_STATE_CONFIGURED)
+ {
+ ecm_eth_dev->rx_size = 0;
+ ecm_eth_dev->rx_offset = 0;
+ ecm_eth_dev->eps.ep_out->request.buffer = ecm_eth_dev->eps.ep_out->buffer;
+ ecm_eth_dev->eps.ep_out->request.size = EP_MAXPACKET(ecm_eth_dev->eps.ep_out);
+ ecm_eth_dev->eps.ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(ecm_eth_dev->func->device, ecm_eth_dev->eps.ep_out, &ecm_eth_dev->eps.ep_out->request);
+ }
+ }
+
+ return p;
+}
+
+rt_err_t rt_ecm_eth_tx(rt_device_t dev, struct pbuf* p)
+{
+ struct pbuf* q;
+ char * pbuffer;
+ rt_err_t result = RT_EOK;
+ rt_ecm_eth_t ecm_eth_dev = (rt_ecm_eth_t)dev;
+
+ if(!ecm_eth_dev->parent.link_status)
+ {
+ ECM_PRINTF("linkdown, drop pkg\r\n");
+ return RT_EOK;
+ }
+
+ // RT_ASSERT(p->tot_len < USB_ETH_MTU);
+ if(p->tot_len > USB_ETH_MTU)
+ {
+ ECM_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n",
+ USB_ETH_MTU, p->tot_len);
+ p->tot_len = USB_ETH_MTU;
+ }
+ result = rt_sem_take(&ecm_eth_dev->tx_buffer_free, RT_WAITING_FOREVER);
+ if(result != RT_EOK)
+ {
+ return result;
+ }
+ pbuffer = (char *)&ecm_eth_dev->tx_buffer;
+ for (q = p; q != NULL; q = q->next)
+ {
+ rt_memcpy(pbuffer, q->payload, q->len);
+ pbuffer += q->len;
+ }
+
+ {
+ if(ecm_eth_dev->func->device->state == USB_STATE_CONFIGURED)
+ {
+ ecm_eth_dev->eps.ep_in->request.buffer = (void *)&ecm_eth_dev->tx_buffer;
+ ecm_eth_dev->eps.ep_in->request.size = p->tot_len;
+ ecm_eth_dev->eps.ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(ecm_eth_dev->func->device, ecm_eth_dev->eps.ep_in, &ecm_eth_dev->eps.ep_in->request);
+ }
+ }
+
+ return result;
+}
+/**
+ * This function will handle RNDIS interrupt in endpoint request.
+ *
+ * @param device the usb device object.
+ * @param size request size.
+ *
+ * @return RT_EOK.
+ */
+static rt_err_t _ep_cmd_handler(ufunction_t func, rt_size_t size)
+{
+ return RT_EOK;
+}
+
+/**
+ * This function will run cdc class, it will be called on handle set configuration request.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _function_enable(ufunction_t func)
+{
+ cdc_eps_t eps;
+ rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data;
+ eps = (cdc_eps_t)&ecm_device->eps;
+ eps->ep_out->buffer = ecm_device->rx_pool;
+ ecm_device->rx_size = 0;
+ ecm_device->rx_offset = 0;
+
+ eps->ep_out->request.buffer = (void *)eps->ep_out->buffer;
+ eps->ep_out->request.size = EP_MAXPACKET(eps->ep_out);
+ eps->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(func->device, eps->ep_out, &eps->ep_out->request);
+ return RT_EOK;
+}
+
+/**
+ * This function will stop cdc class, it will be called on handle set configuration request.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _function_disable(ufunction_t func)
+{
+ eth_device_linkchange(&((rt_ecm_eth_t)func->user_data)->parent, RT_FALSE);
+ return RT_EOK;
+}
+
+
+static struct ufunction_ops ops =
+{
+ _function_enable,
+ _function_disable,
+ RT_NULL,
+};
+
+/**
+ * This function will configure cdc descriptor.
+ *
+ * @param comm the communication interface number.
+ * @param data the data interface number.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr)
+{
+ comm->call_mgmt_desc.data_interface = dintf_nr;
+ comm->union_desc.master_interface = cintf_nr;
+ comm->union_desc.slave_interface0 = dintf_nr;
+#ifdef RT_USB_DEVICE_COMPOSITE
+ comm->iad_desc.bFirstInterface = cintf_nr;
+#endif
+
+ return RT_EOK;
+}
+
+
+
+/**
+ * This function will create a cdc ecm class instance.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+ufunction_t rt_usbd_function_ecm_create(udevice_t device)
+{
+ ufunction_t cdc;
+ rt_ecm_eth_t _ecm_eth;
+ cdc_eps_t eps;
+ uintf_t intf_comm, intf_data;
+ ualtsetting_t comm_setting, data_setting;
+ ucdc_data_desc_t data_desc;
+ ucdc_eth_desc_t comm_desc;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+
+ /* set usb device string description */
+ rt_usbd_device_set_string(device, _ustring);
+
+ /* create a cdc class */
+ cdc = rt_usbd_function_new(device, &_dev_desc, &ops);
+ rt_usbd_device_set_qualifier(device, &dev_qualifier);
+ _ecm_eth= rt_malloc(sizeof(struct rt_ecm_eth));
+ rt_memset(_ecm_eth, 0, sizeof(struct rt_ecm_eth));
+ cdc->user_data = _ecm_eth;
+
+ _ecm_eth->func = cdc;
+ /* create a cdc class endpoints collection */
+ eps = &_ecm_eth->eps;
+ /* create a cdc communication interface and a cdc data interface */
+ intf_comm = rt_usbd_interface_new(device, _interface_handler);
+ intf_data = rt_usbd_interface_new(device, _interface_handler);
+
+ /* create a communication alternate setting and a data alternate setting */
+ comm_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_eth_descriptor));
+ data_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_data_descriptor));
+
+ /* config desc in alternate setting */
+ rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
+ (rt_off_t)&((ucdc_eth_desc_t)0)->intf_desc);
+ rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0);
+ /* configure the cdc interface descriptor */
+ _cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num);
+
+ /* create a command endpoint */
+ comm_desc = (ucdc_eth_desc_t)comm_setting->desc;
+ eps->ep_cmd = rt_usbd_endpoint_new(&comm_desc->ep_desc, _ep_cmd_handler);
+ /* add the command endpoint to the cdc communication interface */
+ rt_usbd_altsetting_add_endpoint(comm_setting, eps->ep_cmd);
+
+ /* add the communication alternate setting to the communication interface,
+ then set default setting of the interface */
+ rt_usbd_interface_add_altsetting(intf_comm, comm_setting);
+ rt_usbd_set_altsetting(intf_comm, 0);
+ /* add the communication interface to the cdc class */
+ rt_usbd_function_add_interface(cdc, intf_comm);
+
+ /* create a bulk in and a bulk out endpoint */
+ data_desc = (ucdc_data_desc_t)data_setting->desc;
+ eps->ep_out = rt_usbd_endpoint_new(&data_desc->ep_out_desc, _ep_out_handler);
+ eps->ep_in = rt_usbd_endpoint_new(&data_desc->ep_in_desc, _ep_in_handler);
+
+ /* add the bulk out and bulk in endpoints to the data alternate setting */
+ rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_in);
+ rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_out);
+
+ /* add the data alternate setting to the data interface
+ then set default setting of the interface */
+ rt_usbd_interface_add_altsetting(intf_data, data_setting);
+ rt_usbd_set_altsetting(intf_data, 0);
+
+ /* add the cdc data interface to cdc class */
+ rt_usbd_function_add_interface(cdc, intf_data);
+
+ rt_sem_init(&_ecm_eth->tx_buffer_free, "ue_tx", 1, RT_IPC_FLAG_FIFO);
+ /* OUI 00-00-00, only for test. */
+ _ecm_eth->dev_addr[0] = 0x34;
+ _ecm_eth->dev_addr[1] = 0x97;
+ _ecm_eth->dev_addr[2] = 0xF6;
+ /* generate random MAC. */
+ _ecm_eth->dev_addr[3] = 0x94;//*(const rt_uint8_t *)(0x1fff7a10);
+ _ecm_eth->dev_addr[4] = 0xEC;//*(const rt_uint8_t *)(0x1fff7a14);
+ _ecm_eth->dev_addr[5] = 0xAC;//(const rt_uint8_t *)(0x1fff7a18);
+ /* OUI 00-00-00, only for test. */
+ _ecm_eth->host_addr[0] = 0x34;
+ _ecm_eth->host_addr[1] = 0x97;
+ _ecm_eth->host_addr[2] = 0xF6;
+ /* generate random MAC. */
+ _ecm_eth->host_addr[3] = 0x94;//*(const rt_uint8_t *)(0x1fff7a10);
+ _ecm_eth->host_addr[4] = 0xEC;//*(const rt_uint8_t *)(0x1fff7a14);
+ _ecm_eth->host_addr[5] = 0xAB;//*(const rt_uint8_t *)(0x1fff7a18);
+
+ _ecm_eth->parent.parent.init = rt_ecm_eth_init;
+ _ecm_eth->parent.parent.open = rt_ecm_eth_open;
+ _ecm_eth->parent.parent.close = rt_ecm_eth_close;
+ _ecm_eth->parent.parent.read = rt_ecm_eth_read;
+ _ecm_eth->parent.parent.write = rt_ecm_eth_write;
+ _ecm_eth->parent.parent.control = rt_ecm_eth_control;
+ _ecm_eth->parent.parent.user_data = device;
+
+ _ecm_eth->parent.eth_rx = rt_ecm_eth_rx;
+ _ecm_eth->parent.eth_tx = rt_ecm_eth_tx;
+ /* register eth device */
+ eth_device_init(&_ecm_eth->parent, "u0");
+
+ /* send link up. */
+ eth_device_linkchange(&_ecm_eth->parent, RT_FALSE);
+
+ return cdc;
+}
diff --git a/components/drivers/usb/usbdevice/core/usbdevice.c b/components/drivers/usb/usbdevice/core/usbdevice.c
index 2c7bd39e16..57a15da648 100644
--- a/components/drivers/usb/usbdevice/core/usbdevice.c
+++ b/components/drivers/usb/usbdevice/core/usbdevice.c
@@ -132,6 +132,17 @@ rt_err_t rt_usb_device_init(void)
}
#endif
+#ifdef RT_USB_DEVICE_ECM
+ {
+ extern ufunction_t rt_usbd_function_ecm_create(udevice_t device);
+ /* create a rndis function object */
+ func = rt_usbd_function_ecm_create(udevice);
+
+ /* add the function to the configuration */
+ rt_usbd_config_add_function(cfg, func);
+ }
+#endif
+
/* set device descriptor to the device */
#ifdef RT_USB_DEVICE_COMPOSITE
rt_usbd_device_set_descriptor(udevice, &compsit_desc);