/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection. This example code is in the Public Domain (or CC0 licensed, at your option.) Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ #include #include "protocol_examples_common.h" #include "sdkconfig.h" #include "esp_event.h" #include "esp_wifi.h" #include "esp_wifi_default.h" #if CONFIG_EXAMPLE_CONNECT_ETHERNET #include "esp_eth.h" #endif #include "esp_log.h" #include "esp_netif.h" #include "driver/gpio.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "lwip/err.h" #include "lwip/sys.h" #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 #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 #elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_GLOBAL) #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_GLOBAL #elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL) #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_SITE_LOCAL #elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL) #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_UNIQUE_LOCAL #endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_... #else #define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces) #endif static int s_active_interfaces = 0; static xSemaphoreHandle s_semph_get_ip_addrs; static esp_ip4_addr_t s_ip_addr; static esp_netif_t *s_example_esp_netif = NULL; #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 static esp_ip6_addr_t s_ipv6_addr; /* types of ipv6 addresses to be displayed on ipv6 events */ static const char *s_ipv6_addr_types[] = { "ESP_IP6_ADDR_IS_UNKNOWN", "ESP_IP6_ADDR_IS_GLOBAL", "ESP_IP6_ADDR_IS_LINK_LOCAL", "ESP_IP6_ADDR_IS_SITE_LOCAL", "ESP_IP6_ADDR_IS_UNIQUE_LOCAL", "ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6" }; #endif static const char *TAG = "example_connect"; #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) { #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) { 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)); xSemaphoreGive(s_semph_get_ip_addrs); } #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 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 (!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 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)); xSemaphoreGive(s_semph_get_ip_addrs); } } #endif // CONFIG_EXAMPLE_CONNECT_IPV6 esp_err_t example_connect(void) { if (s_semph_get_ip_addrs != NULL) { return ESP_ERR_INVALID_STATE; } start(); ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop)); 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(eth_netif); s_example_esp_netif = NULL; } #endif // CONFIG_EXAMPLE_CONNECT_ETHERNET 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; }