Skip to content

Commit 9bba8aa

Browse files
committed
shared/tinyusb: Add support for USB Network (NCM) interface.
This provides a network interface over the USB connection which is connected to the existing LWIP network stack. Signed-off-by: Andrew Leech <[email protected]>
1 parent d137189 commit 9bba8aa

File tree

6 files changed

+112
-12
lines changed

6 files changed

+112
-12
lines changed

extmod/lwip-include/lwipopts_common.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
#define LWIP_DNS_SUPPORT_MDNS_QUERIES 1
5757
#define LWIP_MDNS_RESPONDER 1
5858
#define LWIP_IGMP 1
59+
#define LWIP_UDP 1
60+
#define LWIP_MULTICAST_TX_OPTIONS 1
5961

6062
#if MICROPY_PY_LWIP_PPP
6163
#define PPP_SUPPORT 1
@@ -108,4 +110,8 @@
108110

109111
typedef uint32_t sys_prot_t;
110112

113+
// #define LWIP_DEBUG
114+
// #define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
115+
// #define LWIP_DBG_TYPES_ON LWIP_DBG_ON
116+
111117
#endif // MICROPY_INCLUDED_LWIPOPTS_COMMON_H

extmod/network_usbd_ncm.c

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@
4646
#include "shared/netutils/netutils.h"
4747
#include "shared/netutils/dhcpserver.h"
4848

49+
#if LWIP_IPV6
50+
#define IP(x) ((x).u_addr.ip4)
51+
#else
52+
#define IP(x) (x)
53+
#endif
4954

5055
typedef struct _usbnet_obj_t {
5156
mp_obj_base_t base;
@@ -62,6 +67,7 @@ typedef struct _usbnet_obj_t {
6267
ip_addr_t ipaddr;
6368
ip_addr_t netmask;
6469
ip_addr_t gateway;
70+
ip_addr_t dns;
6571

6672
} usbnet_obj_t;
6773

@@ -115,7 +121,7 @@ static err_t ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t
115121
static err_t netif_init_cb(struct netif *netif) {
116122
LWIP_ASSERT("netif != NULL", (netif != NULL));
117123
netif->mtu = CFG_TUD_NET_MTU;
118-
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
124+
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
119125
netif->state = NULL;
120126
netif->name[0] = 'E';
121127
netif->name[1] = 'X';
@@ -124,29 +130,78 @@ static err_t netif_init_cb(struct netif *netif) {
124130
#if LWIP_IPV6
125131
netif->output_ip6 = ip6_output_fn;
126132
#endif
133+
#if LWIP_IGMP
134+
// netif_set_igmp_mac_filter(netif, cyw43_netif_update_igmp_mac_filter);
135+
#endif
127136
return ERR_OK;
128137
}
129138

139+
#if MICROPY_HW_NETWORK_USBNET_DHCP_SERVER
140+
void dhcp_client_connected(uint8_t ciaddr[4], uint8_t chaddr[16]) {
141+
// When a host pc connects and is assigned an ip address, use that host
142+
// as the default gateway. This means the host could optionally be configured
143+
// to forward internet to the usb network adaptor and this device will be able to use it.
144+
ip4_addr_t gw4;
145+
IP4_ADDR(&gw4, ciaddr[0], ciaddr[1], ciaddr[2], ciaddr[3]);
146+
netif_set_gw(&(usbnet_obj.netif), &gw4);
147+
}
148+
#endif
149+
150+
// #if LWIP_IGMP
151+
// static err_t cyw43_netif_update_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, enum netif_mac_filter_action action) {
152+
// cyw43_t *self = netif->state;
153+
// uint8_t mac[] = { 0x01, 0x00, 0x5e, ip4_addr2(group) & 0x7F, ip4_addr3(group), ip4_addr4(group) };
154+
155+
// if (action != IGMP_ADD_MAC_FILTER && action != IGMP_DEL_MAC_FILTER) {
156+
// return ERR_VAL;
157+
// }
158+
159+
// // if (cyw43_wifi_update_multicast_filter(self, mac, action == IGMP_ADD_MAC_FILTER)) {
160+
// // return ERR_IF;
161+
// // }
162+
163+
// return ERR_OK;
164+
// }
165+
// #endif
166+
167+
// #if LWIP_IPV6
168+
// static err_t cyw43_macfilter(struct netif *netif, const ip6_addr_t *group, enum netif_mac_filter_action action) {
169+
// uint8_t address[6] = { 0x33, 0x33 };
170+
// memcpy(address + 2, group->addr + 3, 4);
171+
// if (action != NETIF_ADD_MAC_FILTER && action != NETIF_DEL_MAC_FILTER) {
172+
// return ERR_VAL;
173+
// }
174+
// if (cyw43_wifi_update_multicast_filter(netif->state, address, action == NETIF_ADD_MAC_FILTER)) {
175+
// return ERR_IF;
176+
// }
177+
// return ERR_OK;
178+
// }
179+
// #endif
180+
130181
void usbnet_init(void) {
131182
struct netif *netif = &(usbnet_obj.netif);
132183

133184
MICROPY_PY_LWIP_ENTER
134185

135186
mp_hal_get_mac(MP_HAL_MAC_ETH0, tud_network_mac_address);
187+
tud_network_mac_address[0] = 0x02;
188+
// tud_network_mac_address[1] = 0x00;
189+
// tud_network_mac_address[2] = 0x5E;
190+
// tud_network_mac_address[5] ^= 0x1;
136191

137192
netif->hwaddr_len = sizeof(tud_network_mac_address);
138193
memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address));
139-
netif->hwaddr[5] ^= 0x01;
140194

141-
#if LWIP_IPV6
142-
#define IP(x) ((x).u_addr.ip4)
143-
#else
144-
#define IP(x) (x)
145-
#endif
195+
// This USB Network essentially creates a link with two interfaces, one for the
196+
// host and another for the micropython/lwip end of the connection.
197+
// The MAC configured above is use for one end of the link, flip a bit for the
198+
// MAC on the other end of the link.
199+
netif->hwaddr[5] ^= 0x01;
146200

147201
IP(usbnet_obj.ipaddr).addr = PP_HTONL(MICROPY_HW_NETWORK_USBNET_IPADDRESS);
148202
IP(usbnet_obj.netmask).addr = PP_HTONL(MICROPY_HW_NETWORK_USBNET_SUBNET);
149203
IP(usbnet_obj.gateway).addr = PP_HTONL(MICROPY_HW_NETWORK_USBNET_GATEWAY);
204+
IP(usbnet_obj.dns).addr = PP_HTONL(MICROPY_HW_NETWORK_USBNET_DNS);
150205

151206
netif = netif_add(
152207
netif,
@@ -160,15 +215,28 @@ void usbnet_init(void) {
160215
#if LWIP_IPV6
161216
netif_create_ip6_linklocal_address(netif, 1);
162217
#endif
218+
#if LWIP_NETIF_HOSTNAME
219+
netif_set_hostname(netif, mod_network_hostname_data);
220+
#endif
163221
netif_set_default(netif);
222+
netif_set_up(netif);
223+
netif_set_link_up(netif);
224+
225+
#if LWIP_MDNS_RESPONDER
226+
mdns_resp_add_netif(netif, mod_network_hostname_data);
227+
#endif
228+
229+
#if LWIP_DNS
230+
dns_setserver(0, &usbnet_obj.dns);
231+
#endif
164232

165233
#if MICROPY_HW_NETWORK_USBNET_DHCP_SERVER
166234
dhcp_server_init(&usbnet_obj.dhcp_server, &usbnet_obj.ipaddr, &usbnet_obj.netmask);
235+
dhcp_server_register_connect_cb(&usbnet_obj.dhcp_server, &dhcp_client_connected);
167236
#endif
168237

169-
#if LWIP_MDNS_RESPONDER
170-
mdns_resp_add_netif(netif, mod_network_hostname_data);
171-
#endif
238+
// register with network module
239+
mod_network_register_nic(&usbnet_obj);
172240

173241
MICROPY_PY_LWIP_EXIT
174242
}

extmod/network_usbd_ncm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@
3838
#define MICROPY_HW_NETWORK_USBNET_IPADDRESS LWIP_MAKEU32(192, 168, 7, 1)
3939
#define MICROPY_HW_NETWORK_USBNET_SUBNET LWIP_MAKEU32(255, 255, 255, 0)
4040
#define MICROPY_HW_NETWORK_USBNET_GATEWAY LWIP_MAKEU32(0, 0, 0, 0)
41+
#define MICROPY_HW_NETWORK_USBNET_DNS LWIP_MAKEU32(192, 168, 7, 1)
42+
43+
// #define MICROPY_HW_NETWORK_USBNET_IPADDRESS LWIP_MAKEU32(169, 254, 128, 1)
44+
// #define MICROPY_HW_NETWORK_USBNET_SUBNET LWIP_MAKEU32(255, 255, 0, 0)
45+
// #define MICROPY_HW_NETWORK_USBNET_GATEWAY LWIP_MAKEU32(0, 0, 0, 0)
46+
4147
#endif
4248

4349
// Start dhcp server on this interface by default as this allows the host computer

ports/rp2/lwip_inc/arch/cc.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22
#define MICROPY_INCLUDED_RP2_LWIP_ARCH_CC_H
33

44
#include <assert.h>
5-
#define LWIP_PLATFORM_DIAG(x)
5+
// #define UDP_DEBUG LWIP_DBG_ON
6+
#define MDNS_DEBUG LWIP_DBG_ON
7+
#include "py/runtime.h"
8+
9+
#define printf_wrap(...) {mp_printf(&mp_plat_print, __VA_ARGS__);}
10+
11+
// #define LWIP_PLATFORM_DIAG(x) mp_printf(&mp_plat_print, x)
12+
#define LWIP_PLATFORM_DIAG(x) do {printf_wrap x;} while (0)
13+
614
#define LWIP_PLATFORM_ASSERT(x) { assert(1); }
715

816
#define LWIP_NO_CTYPE_H 1

shared/netutils/dhcpserver.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
#define PORT_DHCP_SERVER (67)
6666
#define PORT_DHCP_CLIENT (68)
6767

68-
#define DEFAULT_DNS MAKE_IP4(192, 168, 4, 1)
68+
#define DEFAULT_DNS MAKE_IP4(192, 168, 7, 1)
6969
#define DEFAULT_LEASE_TIME_S (24 * 60 * 60) // in seconds
7070

7171
#define MAC_LEN (6)
@@ -273,6 +273,9 @@ static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p,
273273
printf("DHCPS: client connected: MAC=%02x:%02x:%02x:%02x:%02x:%02x IP=%u.%u.%u.%u\n",
274274
dhcp_msg.chaddr[0], dhcp_msg.chaddr[1], dhcp_msg.chaddr[2], dhcp_msg.chaddr[3], dhcp_msg.chaddr[4], dhcp_msg.chaddr[5],
275275
dhcp_msg.yiaddr[0], dhcp_msg.yiaddr[1], dhcp_msg.yiaddr[2], dhcp_msg.yiaddr[3]);
276+
if (d->on_client_connect != NULL) {
277+
d->on_client_connect(dhcp_msg.yiaddr, dhcp_msg.chaddr);
278+
}
276279
break;
277280
}
278281

@@ -297,6 +300,7 @@ void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm) {
297300
ip_addr_copy(d->ip, *ip);
298301
ip_addr_copy(d->nm, *nm);
299302
memset(d->lease, 0, sizeof(d->lease));
303+
d->on_client_connect = NULL;
300304
if (dhcp_socket_new_dgram(&d->udp, d, dhcp_server_process) != 0) {
301305
return;
302306
}
@@ -307,4 +311,8 @@ void dhcp_server_deinit(dhcp_server_t *d) {
307311
dhcp_socket_free(&d->udp);
308312
}
309313

314+
void dhcp_server_register_connect_cb(dhcp_server_t *d, dhcp_client_callback_t on_client_connect) {
315+
d->on_client_connect = on_client_connect;
316+
}
317+
310318
#endif // MICROPY_PY_LWIP

shared/netutils/dhcpserver.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,18 @@ typedef struct _dhcp_server_lease_t {
3636
uint16_t expiry;
3737
} dhcp_server_lease_t;
3838

39+
typedef void (*dhcp_client_callback_t)(uint8_t[4], uint8_t[16]);
40+
3941
typedef struct _dhcp_server_t {
4042
ip_addr_t ip;
4143
ip_addr_t nm;
4244
dhcp_server_lease_t lease[DHCPS_MAX_IP];
4345
struct udp_pcb *udp;
46+
dhcp_client_callback_t on_client_connect;
4447
} dhcp_server_t;
4548

4649
void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm);
4750
void dhcp_server_deinit(dhcp_server_t *d);
51+
void dhcp_server_register_connect_cb(dhcp_server_t *d, dhcp_client_callback_t on_client_connect);
4852

4953
#endif // MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H

0 commit comments

Comments
 (0)