connect.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include <string.h>
  8. #include "protocol_examples_common.h"
  9. #include "sdkconfig.h"
  10. #include "esp_event.h"
  11. #include "esp_wifi.h"
  12. #include "esp_wifi_default.h"
  13. #if CONFIG_EXAMPLE_CONNECT_ETHERNET
  14. #include "esp_eth.h"
  15. #endif
  16. #include "esp_log.h"
  17. #include "esp_netif.h"
  18. #include "driver/gpio.h"
  19. #include "freertos/FreeRTOS.h"
  20. #include "freertos/task.h"
  21. #include "freertos/event_groups.h"
  22. #include "lwip/err.h"
  23. #include "lwip/sys.h"
  24. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  25. #define MAX_IP6_ADDRS_PER_NETIF (5)
  26. #define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces*2)
  27. #if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK)
  28. #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL
  29. #elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_GLOBAL)
  30. #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_GLOBAL
  31. #elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL)
  32. #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_SITE_LOCAL
  33. #elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL)
  34. #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_UNIQUE_LOCAL
  35. #endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_...
  36. #else
  37. #define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces)
  38. #endif
  39. static int s_active_interfaces = 0;
  40. static xSemaphoreHandle s_semph_get_ip_addrs;
  41. static esp_ip4_addr_t s_ip_addr;
  42. static esp_netif_t *s_example_esp_netif = NULL;
  43. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  44. static esp_ip6_addr_t s_ipv6_addr;
  45. /* types of ipv6 addresses to be displayed on ipv6 events */
  46. static const char *s_ipv6_addr_types[] = {
  47. "ESP_IP6_ADDR_IS_UNKNOWN",
  48. "ESP_IP6_ADDR_IS_GLOBAL",
  49. "ESP_IP6_ADDR_IS_LINK_LOCAL",
  50. "ESP_IP6_ADDR_IS_SITE_LOCAL",
  51. "ESP_IP6_ADDR_IS_UNIQUE_LOCAL",
  52. "ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6"
  53. };
  54. #endif
  55. static const char *TAG = "example_connect";
  56. #if CONFIG_EXAMPLE_CONNECT_WIFI
  57. static esp_netif_t* wifi_start(void);
  58. static void wifi_stop(void);
  59. #endif
  60. #if CONFIG_EXAMPLE_CONNECT_ETHERNET
  61. static esp_netif_t* eth_start(void);
  62. static void eth_stop(void);
  63. #endif
  64. /**
  65. * @brief Checks the netif description if it contains specified prefix.
  66. * All netifs created withing common connect component are prefixed with the module TAG,
  67. * so it returns true if the specified netif is owned by this module
  68. */
  69. static bool is_our_netif(const char *prefix, esp_netif_t *netif)
  70. {
  71. return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix)-1) == 0;
  72. }
  73. /* set up connection, Wi-Fi and/or Ethernet */
  74. static void start(void)
  75. {
  76. #if CONFIG_EXAMPLE_CONNECT_WIFI
  77. s_example_esp_netif = wifi_start();
  78. s_active_interfaces++;
  79. #endif
  80. #if CONFIG_EXAMPLE_CONNECT_ETHERNET
  81. s_example_esp_netif = eth_start();
  82. s_active_interfaces++;
  83. #endif
  84. #if CONFIG_EXAMPLE_CONNECT_WIFI && CONFIG_EXAMPLE_CONNECT_ETHERNET
  85. /* if both intefaces at once, clear out to indicate that multiple netifs are active */
  86. s_example_esp_netif = NULL;
  87. #endif
  88. s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0);
  89. }
  90. /* tear down connection, release resources */
  91. static void stop(void)
  92. {
  93. #if CONFIG_EXAMPLE_CONNECT_WIFI
  94. wifi_stop();
  95. s_active_interfaces--;
  96. #endif
  97. #if CONFIG_EXAMPLE_CONNECT_ETHERNET
  98. eth_stop();
  99. s_active_interfaces--;
  100. #endif
  101. }
  102. static void on_got_ip(void *arg, esp_event_base_t event_base,
  103. int32_t event_id, void *event_data)
  104. {
  105. ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
  106. if (!is_our_netif(TAG, event->esp_netif)) {
  107. ESP_LOGW(TAG, "Got IPv4 from another interface \"%s\": ignored", esp_netif_get_desc(event->esp_netif));
  108. return;
  109. }
  110. ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
  111. memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr));
  112. xSemaphoreGive(s_semph_get_ip_addrs);
  113. }
  114. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  115. static void on_got_ipv6(void *arg, esp_event_base_t event_base,
  116. int32_t event_id, void *event_data)
  117. {
  118. ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
  119. if (!is_our_netif(TAG, event->esp_netif)) {
  120. ESP_LOGW(TAG, "Got IPv6 from another netif: ignored");
  121. return;
  122. }
  123. esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
  124. ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
  125. IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]);
  126. if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
  127. memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr));
  128. xSemaphoreGive(s_semph_get_ip_addrs);
  129. }
  130. }
  131. #endif // CONFIG_EXAMPLE_CONNECT_IPV6
  132. esp_err_t example_connect(void)
  133. {
  134. if (s_semph_get_ip_addrs != NULL) {
  135. return ESP_ERR_INVALID_STATE;
  136. }
  137. start();
  138. ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop));
  139. ESP_LOGI(TAG, "Waiting for IP(s)");
  140. for (int i=0; i<NR_OF_IP_ADDRESSES_TO_WAIT_FOR; ++i) {
  141. xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
  142. }
  143. // iterate over active interfaces, and print out IPs of "our" netifs
  144. esp_netif_t *netif = NULL;
  145. esp_netif_ip_info_t ip;
  146. for (int i=0; i<esp_netif_get_nr_of_ifs(); ++i) {
  147. netif = esp_netif_next(netif);
  148. if (is_our_netif(TAG, netif)) {
  149. ESP_LOGI(TAG, "Connected to %s", esp_netif_get_desc(netif));
  150. ESP_ERROR_CHECK(esp_netif_get_ip_info(netif, &ip));
  151. ESP_LOGI(TAG, "- IPv4 address: " IPSTR, IP2STR(&ip.ip));
  152. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  153. esp_ip6_addr_t ip6[MAX_IP6_ADDRS_PER_NETIF];
  154. int ip6_addrs = esp_netif_get_all_ip6(netif, ip6);
  155. for (int j=0; j< ip6_addrs; ++j) {
  156. esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j]));
  157. ESP_LOGI(TAG, "- IPv6 address: " IPV6STR ", type: %s", IPV62STR(ip6[j]), s_ipv6_addr_types[ipv6_type]);
  158. }
  159. #endif
  160. }
  161. }
  162. return ESP_OK;
  163. }
  164. esp_err_t example_disconnect(void)
  165. {
  166. if (s_semph_get_ip_addrs == NULL) {
  167. return ESP_ERR_INVALID_STATE;
  168. }
  169. vSemaphoreDelete(s_semph_get_ip_addrs);
  170. s_semph_get_ip_addrs = NULL;
  171. stop();
  172. ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&stop));
  173. return ESP_OK;
  174. }
  175. #ifdef CONFIG_EXAMPLE_CONNECT_WIFI
  176. static void on_wifi_disconnect(void *arg, esp_event_base_t event_base,
  177. int32_t event_id, void *event_data)
  178. {
  179. ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect...");
  180. esp_err_t err = esp_wifi_connect();
  181. if (err == ESP_ERR_WIFI_NOT_STARTED) {
  182. return;
  183. }
  184. ESP_ERROR_CHECK(err);
  185. }
  186. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  187. static void on_wifi_connect(void *esp_netif, esp_event_base_t event_base,
  188. int32_t event_id, void *event_data)
  189. {
  190. esp_netif_create_ip6_linklocal(esp_netif);
  191. }
  192. #endif // CONFIG_EXAMPLE_CONNECT_IPV6
  193. static esp_netif_t* wifi_start(void)
  194. {
  195. char *desc;
  196. wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  197. ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  198. esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
  199. // Prefix the interface description with the module TAG
  200. // Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
  201. asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc);
  202. esp_netif_config.if_desc = desc;
  203. esp_netif_config.route_prio = 128;
  204. esp_netif_t *netif = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
  205. free(desc);
  206. esp_wifi_set_default_wifi_sta_handlers();
  207. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL));
  208. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL));
  209. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  210. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect, netif));
  211. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
  212. #endif
  213. ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
  214. wifi_config_t wifi_config = {
  215. .sta = {
  216. .ssid = CONFIG_EXAMPLE_WIFI_SSID,
  217. .password = CONFIG_EXAMPLE_WIFI_PASSWORD,
  218. },
  219. };
  220. ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid);
  221. ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
  222. ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
  223. ESP_ERROR_CHECK(esp_wifi_start());
  224. esp_wifi_connect();
  225. return netif;
  226. }
  227. static void wifi_stop(void)
  228. {
  229. esp_netif_t *wifi_netif = get_example_netif_from_desc("sta");
  230. ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect));
  231. ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip));
  232. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  233. ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6));
  234. ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect));
  235. #endif
  236. esp_err_t err = esp_wifi_stop();
  237. if (err == ESP_ERR_WIFI_NOT_INIT) {
  238. return;
  239. }
  240. ESP_ERROR_CHECK(err);
  241. ESP_ERROR_CHECK(esp_wifi_deinit());
  242. ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(wifi_netif));
  243. esp_netif_destroy(wifi_netif);
  244. s_example_esp_netif = NULL;
  245. }
  246. #endif // CONFIG_EXAMPLE_CONNECT_WIFI
  247. #ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
  248. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  249. /** Event handler for Ethernet events */
  250. static void on_eth_event(void *esp_netif, esp_event_base_t event_base,
  251. int32_t event_id, void *event_data)
  252. {
  253. switch (event_id) {
  254. case ETHERNET_EVENT_CONNECTED:
  255. ESP_LOGI(TAG, "Ethernet Link Up");
  256. esp_netif_create_ip6_linklocal(esp_netif);
  257. break;
  258. default:
  259. break;
  260. }
  261. }
  262. #endif // CONFIG_EXAMPLE_CONNECT_IPV6
  263. static esp_eth_handle_t s_eth_handle = NULL;
  264. static esp_eth_mac_t *s_mac = NULL;
  265. static esp_eth_phy_t *s_phy = NULL;
  266. static void *s_eth_glue = NULL;
  267. static esp_netif_t* eth_start(void)
  268. {
  269. char *desc;
  270. esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
  271. // Prefix the interface description with the module TAG
  272. // Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
  273. asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc);
  274. esp_netif_config.if_desc = desc;
  275. esp_netif_config.route_prio = 64;
  276. esp_netif_config_t netif_config = {
  277. .base = &esp_netif_config,
  278. .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
  279. };
  280. esp_netif_t *netif = esp_netif_new(&netif_config);
  281. assert(netif);
  282. free(desc);
  283. // Set default handlers to process TCP/IP stuffs
  284. ESP_ERROR_CHECK(esp_eth_set_default_handlers(netif));
  285. // Register user defined event handers
  286. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL));
  287. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  288. ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
  289. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
  290. #endif
  291. eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
  292. eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
  293. phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
  294. phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
  295. #if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
  296. mac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
  297. mac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
  298. s_mac = esp_eth_mac_new_esp32(&mac_config);
  299. #if CONFIG_EXAMPLE_ETH_PHY_IP101
  300. s_phy = esp_eth_phy_new_ip101(&phy_config);
  301. #elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
  302. s_phy = esp_eth_phy_new_rtl8201(&phy_config);
  303. #elif CONFIG_EXAMPLE_ETH_PHY_LAN8720
  304. s_phy = esp_eth_phy_new_lan8720(&phy_config);
  305. #elif CONFIG_EXAMPLE_ETH_PHY_DP83848
  306. s_phy = esp_eth_phy_new_dp83848(&phy_config);
  307. #endif
  308. #elif CONFIG_EXAMPLE_USE_DM9051
  309. gpio_install_isr_service(0);
  310. spi_device_handle_t spi_handle = NULL;
  311. spi_bus_config_t buscfg = {
  312. .miso_io_num = CONFIG_EXAMPLE_DM9051_MISO_GPIO,
  313. .mosi_io_num = CONFIG_EXAMPLE_DM9051_MOSI_GPIO,
  314. .sclk_io_num = CONFIG_EXAMPLE_DM9051_SCLK_GPIO,
  315. .quadwp_io_num = -1,
  316. .quadhd_io_num = -1,
  317. };
  318. ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_DM9051_SPI_HOST, &buscfg, 1));
  319. spi_device_interface_config_t devcfg = {
  320. .command_bits = 1,
  321. .address_bits = 7,
  322. .mode = 0,
  323. .clock_speed_hz = CONFIG_EXAMPLE_DM9051_SPI_CLOCK_MHZ * 1000 * 1000,
  324. .spics_io_num = CONFIG_EXAMPLE_DM9051_CS_GPIO,
  325. .queue_size = 20
  326. };
  327. ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_DM9051_SPI_HOST, &devcfg, &spi_handle));
  328. /* dm9051 ethernet driver is based on spi driver */
  329. eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
  330. dm9051_config.int_gpio_num = CONFIG_EXAMPLE_DM9051_INT_GPIO;
  331. s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
  332. s_phy = esp_eth_phy_new_dm9051(&phy_config);
  333. #elif CONFIG_EXAMPLE_USE_OPENETH
  334. phy_config.autonego_timeout_ms = 100;
  335. s_mac = esp_eth_mac_new_openeth(&mac_config);
  336. s_phy = esp_eth_phy_new_dp83848(&phy_config);
  337. #endif
  338. // Install Ethernet driver
  339. esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
  340. ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
  341. // combine driver with netif
  342. s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
  343. esp_netif_attach(netif, s_eth_glue);
  344. esp_eth_start(s_eth_handle);
  345. return netif;
  346. }
  347. static void eth_stop(void)
  348. {
  349. esp_netif_t *eth_netif = get_example_netif_from_desc("eth");
  350. ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip));
  351. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  352. ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6));
  353. ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event));
  354. #endif
  355. ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle));
  356. ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue));
  357. ESP_ERROR_CHECK(esp_eth_clear_default_handlers(eth_netif));
  358. ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle));
  359. ESP_ERROR_CHECK(s_phy->del(s_phy));
  360. ESP_ERROR_CHECK(s_mac->del(s_mac));
  361. esp_netif_destroy(eth_netif);
  362. s_example_esp_netif = NULL;
  363. }
  364. #endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
  365. esp_netif_t *get_example_netif(void)
  366. {
  367. return s_example_esp_netif;
  368. }
  369. esp_netif_t *get_example_netif_from_desc(const char *desc)
  370. {
  371. esp_netif_t *netif = NULL;
  372. char *expected_desc;
  373. asprintf(&expected_desc, "%s: %s", TAG, desc);
  374. while ((netif = esp_netif_next(netif)) != NULL) {
  375. if (strcmp(esp_netif_get_desc(netif), expected_desc) == 0) {
  376. free(expected_desc);
  377. return netif;
  378. }
  379. }
  380. free(expected_desc);
  381. return netif;
  382. }