summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/device/net_lwip_webserver/src/lwipopts.h1
-rw-r--r--examples/device/net_lwip_webserver/src/main.c73
-rw-r--r--examples/device/net_lwip_webserver/src/tusb_config.h2
3 files changed, 67 insertions, 9 deletions
diff --git a/examples/device/net_lwip_webserver/src/lwipopts.h b/examples/device/net_lwip_webserver/src/lwipopts.h
index 41e8f0d67..04949cef9 100644
--- a/examples/device/net_lwip_webserver/src/lwipopts.h
+++ b/examples/device/net_lwip_webserver/src/lwipopts.h
@@ -58,6 +58,7 @@
#define LWIP_HTTPD_SSI_INCLUDE_TAG 0
#define LWIP_SINGLE_NETIF 1
+#define LWIP_NETIF_LINK_CALLBACK 1
#define PBUF_POOL_SIZE 4
diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c
index 36f402332..41f02576f 100644
--- a/examples/device/net_lwip_webserver/src/main.c
+++ b/examples/device/net_lwip_webserver/src/main.c
@@ -31,6 +31,12 @@ this appears as either a RNDIS or CDC-ECM USB virtual network adapter; the OS pi
RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and macOS hosts
The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server.
+
+Link State Control:
+- Press the user button to toggle the network link state (UP/DOWN)
+- This simulates "ethernet cable unplugged/plugged" events
+- The host OS will see the network interface as disconnected/connected accordingly
+- Use this to test network error handling and recovery in host applications
*/
/*
Some smartphones *may* work with this implementation as well, but likely have limited (broken) drivers,
@@ -137,6 +143,12 @@ static err_t netif_init_cb(struct netif *netif) {
return ERR_OK;
}
+/* notifies the USB host about the link state change. */
+static void usbnet_netif_link_callback(struct netif *netif) {
+ bool link_up = netif_is_link_up(netif);
+ tud_network_link_state(BOARD_TUD_RHPORT, link_up);
+}
+
static void init_lwip(void) {
struct netif *netif = &netif_data;
@@ -147,11 +159,19 @@ static void init_lwip(void) {
memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address));
netif->hwaddr[5] ^= 0x01;
- netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input);
+ netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ethernet_input);
#if LWIP_IPV6
netif_create_ip6_linklocal_address(netif, 1);
#endif
netif_set_default(netif);
+
+#if LWIP_NETIF_LINK_CALLBACK
+ // Set the link callback to notify USB host about link state changes
+ netif_set_link_callback(netif, usbnet_netif_link_callback);
+ netif_set_link_up(netif);
+#else
+ tud_network_link_state(BOARD_TUD_RHPORT, true);
+#endif
}
/* handle any DNS requests from dns-server */
@@ -171,13 +191,16 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) {
if (size) {
struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL);
- if (p) {
- /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */
- memcpy(p->payload, src, size);
-
- /* store away the pointer for service_traffic() to later handle */
- received_frame = p;
+ if (p == NULL) {
+ printf("ERROR: Failed to allocate pbuf of size %d\n", size);
+ return false;
}
+
+ /* Copy buf to pbuf */
+ pbuf_take(p, src, size);
+
+ /* store away the pointer for service_traffic() to later handle */
+ received_frame = p;
}
return true;
@@ -194,12 +217,14 @@ uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) {
static void service_traffic(void) {
/* handle any packet received by tud_network_recv_cb() */
if (received_frame) {
+ struct netif *netif = &netif_data;
// Surrender ownership of our pbuf unless there was an error
// Only call pbuf_free if not Ok else it will panic with "pbuf_free: p->ref > 0"
// or steal it from whatever took ownership of it with undefined consequences.
// See: https://savannah.nongnu.org/patch/index.php?10121
- if (ethernet_input(received_frame, &netif_data)!=ERR_OK) {
- pbuf_free(received_frame);
+ if (netif->input(received_frame, netif) != ERR_OK) {
+ printf("ERROR: netif input failed\n");
+ pbuf_free(received_frame);
}
received_frame = NULL;
tud_network_recv_renew();
@@ -216,6 +241,28 @@ void tud_network_init_cb(void) {
}
}
+static void handle_link_state_switch(void) {
+ /* Check for button press to toggle link state */
+ static bool last_link_state = true;
+ static bool last_button_state = false;
+ bool current_button_state = board_button_read();
+
+ if (current_button_state && !last_button_state) {
+ /* Button pressed - toggle link state */
+ last_link_state = !last_link_state;
+ if (last_link_state) {
+ printf("Link state: UP\n");
+ netif_set_link_up(&netif_data);
+ } else {
+ printf("Link state: DOWN\n");
+ netif_set_link_down(&netif_data);
+ }
+ /* LWIP callback will notify USB host about the change */
+ }
+ last_button_state = current_button_state;
+
+}
+
int main(void) {
/* initialize TinyUSB */
board_init();
@@ -243,15 +290,23 @@ int main(void) {
lwiperf_start_tcp_server_default(NULL, NULL);
#endif
+#if CFG_TUD_NCM
+ printf("USB NCM network interface initialized\n");
+#elif CFG_TUD_ECM_RNDIS
+ printf("USB RNDIS/ECM network interface initialized\n");
+#endif
+
while (1) {
tud_task();
service_traffic();
+ handle_link_state_switch();
}
return 0;
}
/* lwip has provision for using a mutex, when applicable */
+/* This implementation is for single-threaded use only */
sys_prot_t sys_arch_protect(void) {
return 0;
}
diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h
index 22082fc81..c774f59ff 100644
--- a/examples/device/net_lwip_webserver/src/tusb_config.h
+++ b/examples/device/net_lwip_webserver/src/tusb_config.h
@@ -85,6 +85,7 @@ extern "C" {
#endif
// Use different configurations to test all net devices (also due to resource limitations)
+#ifndef USE_ECM
#if TU_CHECK_MCU(OPT_MCU_LPC15XX, OPT_MCU_LPC40XX, OPT_MCU_LPC51UXX, OPT_MCU_LPC54)
#define USE_ECM 1
#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAML21, OPT_MCU_SAML22)
@@ -97,6 +98,7 @@ extern "C" {
#define USE_ECM 0
#define INCLUDE_IPERF
#endif
+#endif
//--------------------------------------------------------------------
// NCM CLASS CONFIGURATION, SEE "ncm.h" FOR PERFORMANCE TUNING