1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
|
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc_ecm.h"
#ifndef CONFIG_USBDEV_CDC_ECM_USING_LWIP
#error "Please enable CONFIG_USBDEV_CDC_ECM_USING_LWIP for this demo"
#endif
/*!< 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
/* str idx = 4 is for mac address: aa:bb:cc:dd:ee:ff*/
#define CDC_ECM_MAC_STRING_INDEX 4
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[] = {
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_MAC_STRING_INDEX)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB CDC ECM DEMO", /* Product */
"2022123456", /* Serial Number */
"aabbccddeeff", /* ecm mac address */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_ecm_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
volatile bool cdc_ecm_tx_done = false;
void usbd_cdc_ecm_data_send_done(uint32_t len)
{
cdc_ecm_tx_done = true; // suggest you to use semaphore in os
}
#ifdef RT_USING_LWIP
#ifndef RT_LWIP_DHCP
#error cdc_ecm must enable RT_LWIP_DHCP
#endif
#ifndef LWIP_USING_DHCPD
#error cdc_ecm must enable LWIP_USING_DHCPD
#endif
#include <rtthread.h>
#include <rtdevice.h>
#include <netif/ethernetif.h>
#include <dhcp_server.h>
struct eth_device cdc_ecm_dev;
static rt_err_t rt_usbd_cdc_ecm_control(rt_device_t dev, int cmd, void *args)
{
switch (cmd) {
case NIOCTL_GADDR:
/* get mac address */
if (args) {
uint8_t *mac_dev = (uint8_t *)args;
rt_memcpy(mac_dev, mac, 6);
mac_dev[5] = ~mac_dev[5]; /* device mac can't same as host. */
} else
return -RT_ERROR;
break;
default:
break;
}
return RT_EOK;
}
struct pbuf *rt_usbd_cdc_ecm_eth_rx(rt_device_t dev)
{
return usbd_cdc_ecm_eth_rx();
}
rt_err_t rt_usbd_cdc_ecm_eth_tx(rt_device_t dev, struct pbuf *p)
{
int ret;
cdc_ecm_tx_done = false;
ret = usbd_cdc_ecm_eth_tx(p);
if (ret == 0) {
while (!cdc_ecm_tx_done) {
}
return RT_EOK;
} else
return -RT_ERROR;
}
void cdc_ecm_lwip_init(void)
{
cdc_ecm_dev.parent.control = rt_usbd_cdc_ecm_control;
cdc_ecm_dev.eth_rx = rt_usbd_cdc_ecm_eth_rx;
cdc_ecm_dev.eth_tx = rt_usbd_cdc_ecm_eth_tx;
eth_device_init(&cdc_ecm_dev, "u0");
eth_device_linkchange(&cdc_ecm_dev, RT_TRUE);
dhcpd_start("u0");
}
void usbd_cdc_ecm_data_recv_done(uint32_t len)
{
eth_device_ready(&cdc_ecm_dev);
}
#else
#include "netif/etharp.h"
#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
#include "dhserver.h"
#include "dnserver.h"
/*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)7
#define IP_ADDR3 (uint8_t)1
/*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)0
#define GW_ADDR1 (uint8_t)0
#define GW_ADDR2 (uint8_t)0
#define GW_ADDR3 (uint8_t)0
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);
#define NUM_DHCP_ENTRY 3
static dhcp_entry_t entries[NUM_DHCP_ENTRY] = {
/* mac ip address subnet mask lease time */
{ { 0 }, { 192, 168, 7, 2 }, { 255, 255, 255, 0 }, 24 * 60 * 60 },
{ { 0 }, { 192, 168, 7, 3 }, { 255, 255, 255, 0 }, 24 * 60 * 60 },
{ { 0 }, { 192, 168, 7, 4 }, { 255, 255, 255, 0 }, 24 * 60 * 60 }
};
static dhcp_config_t dhcp_config = {
{ 192, 168, 7, 1 }, /* server address */
67, /* port */
{ 192, 168, 7, 1 }, /* dns server */
"cherry", /* dns suffix */
NUM_DHCP_ENTRY, /* num entry */
entries /* entries */
};
static bool dns_query_proc(const char *name, ip_addr_t *addr)
{
if (strcmp(name, "cdc_ecm.cherry") == 0 || strcmp(name, "www.cdc_ecm.cherry") == 0) {
addr->addr = ipaddr.addr;
return true;
}
return false;
}
static struct netif cdc_ecm_netif; //network interface
/* Network interface name */
#define IFNAME0 'E'
#define IFNAME1 'X'
err_t linkoutput_fn(struct netif *netif, struct pbuf *p)
{
int ret;
cdc_ecm_tx_done = false;
ret = usbd_cdc_ecm_eth_tx(p);
if (ret == 0) {
while (!cdc_ecm_tx_done) {
}
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)
{
err_t err;
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->hwaddr[5] = ~netif->hwaddr[5]; /* device mac can't same as host. */
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(IP_ADDR_ANY, 53, dns_query_proc)) {
}
}
void usbd_cdc_ecm_data_recv_done(uint32_t len)
{
}
void cdc_ecm_input_poll(void)
{
cdc_ecm_if_input(&cdc_ecm_netif);
}
#endif
static void usbd_event_handler(uint8_t busid, 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 dhclient enxaabbccddeeff
*/
void cdc_ecm_init(uint8_t busid, uintptr_t reg_base)
{
cdc_ecm_lwip_init();
usbd_desc_register(busid, &cdc_ecm_descriptor);
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_initialize(busid, reg_base, usbd_event_handler);
}
|