diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index f47b8a6af..eccf77889 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -1,18 +1,11 @@ menu "Example Connection Configuration" - choice EXAMPLE_CONNECT_INTERFACE - prompt "Connect using" - default EXAMPLE_CONNECT_WIFI + + config EXAMPLE_CONNECT_WIFI + bool "connect using WiFi interface" + default y help - Protocol examples can use Wi-Fi or Ethernet to connect to the network. - Choose which interface to use. - - config EXAMPLE_CONNECT_WIFI - bool "Wi-Fi" - - config EXAMPLE_CONNECT_ETHERNET - bool "Ethernet" - - endchoice + Protocol examples can use Wi-Fi and/or Ethernet to connect to the network. + Choose this option to connect with WiFi if EXAMPLE_CONNECT_WIFI config EXAMPLE_WIFI_SSID @@ -29,6 +22,13 @@ menu "Example Connection Configuration" Can be left blank if the network has no security set. endif + config EXAMPLE_CONNECT_ETHERNET + bool "connect using Ethernet interface" + default n + help + Protocol examples can use Wi-Fi and/or Ethernet to connect to the network. + Choose this option to connect with Ethernet + if EXAMPLE_CONNECT_ETHERNET choice EXAMPLE_USE_ETHERNET prompt "Ethernet Type" diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index e845837cb..653a43ea0 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -25,11 +25,9 @@ #include "lwip/err.h" #include "lwip/sys.h" -#define GOT_IPV4_BIT BIT(0) -#define GOT_IPV6_BIT BIT(1) - #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 -#define CONNECTED_BITS (GOT_IPV4_BIT | GOT_IPV6_BIT) +#define MAX_IP6_ADDRS_PER_NETIF (5) +#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces*2) #if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK) #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL @@ -42,12 +40,12 @@ #endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_... #else -#define CONNECTED_BITS (GOT_IPV4_BIT) +#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces) #endif -static EventGroupHandle_t s_connect_event_group; +static int s_active_interfaces = 0; +static xSemaphoreHandle s_semph_get_ip_addrs; static esp_ip4_addr_t s_ip_addr; -static const char *s_connection_name; static esp_netif_t *s_example_esp_netif = NULL; #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 @@ -66,19 +64,72 @@ static const char *s_ipv6_addr_types[] = { static const char *TAG = "example_connect"; -/* set up connection, Wi-Fi or Ethernet */ -static void start(void); +#if CONFIG_EXAMPLE_CONNECT_WIFI +static esp_netif_t* wifi_start(void); +static void wifi_stop(void); +#endif +#if CONFIG_EXAMPLE_CONNECT_ETHERNET +static esp_netif_t* eth_start(void); +static void eth_stop(void); +#endif + +/** + * @brief Checks the netif description if it contains specified prefix. + * All netifs created withing common connect component are prefixed with the module TAG, + * so it returns true if the specified netif is owned by this module + */ +static bool is_our_netif(const char *prefix, esp_netif_t *netif) +{ + return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix)-1) == 0; +} + +/* set up connection, Wi-Fi and/or Ethernet */ +static void start(void) +{ + +#if CONFIG_EXAMPLE_CONNECT_WIFI + s_example_esp_netif = wifi_start(); + s_active_interfaces++; +#endif + +#if CONFIG_EXAMPLE_CONNECT_ETHERNET + s_example_esp_netif = eth_start(); + s_active_interfaces++; +#endif + +#if CONFIG_EXAMPLE_CONNECT_WIFI && CONFIG_EXAMPLE_CONNECT_ETHERNET + /* if both intefaces at once, clear out to indicate that multiple netifs are active */ + s_example_esp_netif = NULL; +#endif + + s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0); +} /* tear down connection, release resources */ -static void stop(void); +static void stop(void) +{ +#if CONFIG_EXAMPLE_CONNECT_WIFI + wifi_stop(); + s_active_interfaces--; +#endif + +#if CONFIG_EXAMPLE_CONNECT_ETHERNET + eth_stop(); + s_active_interfaces--; +#endif +} static void on_got_ip(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { - ESP_LOGI(TAG, "Got IP event!"); ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + if (!is_our_netif(TAG, event->esp_netif)) { + ESP_LOGW(TAG, "Got IPv4 from another interface \"%s\": ignored", esp_netif_get_desc(event->esp_netif)); + return; + } + ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip)); memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr)); - xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT); + xSemaphoreGive(s_semph_get_ip_addrs); } #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 @@ -87,15 +138,16 @@ static void on_got_ipv6(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; - if (event->esp_netif != s_example_esp_netif) { - ESP_LOGD(TAG, "Got IPv6 from another netif: ignored"); + if (!is_our_netif(TAG, event->esp_netif)) { + ESP_LOGW(TAG, "Got IPv6 from another netif: ignored"); return; } esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip); - ESP_LOGI(TAG, "Got IPv6 address: " IPV6STR ", type: %s", IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]); + ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif), + IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]); if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) { memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); - xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); + xSemaphoreGive(s_semph_get_ip_addrs); } } @@ -103,32 +155,47 @@ static void on_got_ipv6(void *arg, esp_event_base_t event_base, esp_err_t example_connect(void) { - if (s_connect_event_group != NULL) { + if (s_semph_get_ip_addrs != NULL) { return ESP_ERR_INVALID_STATE; } - s_connect_event_group = xEventGroupCreate(); start(); ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop)); - ESP_LOGI(TAG, "Waiting for IP"); - xEventGroupWaitBits(s_connect_event_group, CONNECTED_BITS, true, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to %s", s_connection_name); - ESP_LOGI(TAG, "IPv4 address: " IPSTR, IP2STR(&s_ip_addr)); + ESP_LOGI(TAG, "Waiting for IP(s)"); + for (int i=0; idel(s_phy)); ESP_ERROR_CHECK(s_mac->del(s_mac)); - esp_netif_destroy(s_example_esp_netif); + esp_netif_destroy(eth_netif); s_example_esp_netif = NULL; } @@ -334,3 +413,18 @@ esp_netif_t *get_example_netif(void) { return s_example_esp_netif; } + +esp_netif_t *get_example_netif_from_desc(const char *desc) +{ + esp_netif_t *netif = NULL; + char *expected_desc; + asprintf(&expected_desc, "%s: %s", TAG, desc); + while ((netif = esp_netif_next(netif)) != NULL) { + if (strcmp(esp_netif_get_desc(netif), expected_desc) == 0) { + free(expected_desc); + return netif; + } + } + free(expected_desc); + return netif; +} diff --git a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h index 98f67e348..859264df0 100644 --- a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h +++ b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h @@ -57,8 +57,22 @@ esp_err_t example_configure_stdin_stdout(void); /** * @brief Returns esp-netif pointer created by example_connect() * + * @note If multiple interfaces active at once, this API return NULL + * In that case the get_example_netif_from_desc() should be used + * to get esp-netif pointer based on interface description */ esp_netif_t *get_example_netif(void); + +/** + * @brief Returns esp-netif pointer created by example_connect() described by + * the supplied desc field + * + * @param desc Textual interface of created network interface, for example "sta" + * indicate default WiFi station, "eth" default Ethernet interface. + * + */ +esp_netif_t *get_example_netif_from_desc(const char *desc); + #ifdef __cplusplus } #endif