ppp_connect.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include <string.h>
  7. #include <stdint.h>
  8. #include "sdkconfig.h"
  9. #include "protocol_examples_common.h"
  10. #include "example_common_private.h"
  11. #if CONFIG_EXAMPLE_CONNECT_PPP
  12. #include "esp_log.h"
  13. #include "esp_netif.h"
  14. #include "esp_netif_ppp.h"
  15. #include "freertos/FreeRTOS.h"
  16. #include "freertos/task.h"
  17. #if CONFIG_EXAMPLE_CONNECT_PPP_DEVICE_USB
  18. #include "tinyusb.h"
  19. #include "tusb_cdc_acm.h"
  20. static int s_itf;
  21. static uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE];
  22. #else // DEVICE is UART
  23. #include "driver/uart.h"
  24. #define BUF_SIZE (1024)
  25. static bool s_stop_task = false;
  26. #endif // CONNECT_PPP_DEVICE
  27. static const char *TAG = "example_connect_ppp";
  28. static int s_retry_num = 0;
  29. static EventGroupHandle_t s_event_group = NULL;
  30. static esp_netif_t *s_netif;
  31. static const int GOT_IPV4 = BIT0;
  32. static const int CONNECTION_FAILED = BIT1;
  33. #if CONFIG_EXAMPLE_CONNECT_IPV6
  34. static const int GOT_IPV6 = BIT2;
  35. #define CONNECT_BITS (GOT_IPV4|GOT_IPV6|CONNECTION_FAILED)
  36. #else
  37. #define CONNECT_BITS (GOT_IPV4|CONNECTION_FAILED)
  38. #endif
  39. static esp_err_t transmit(void *h, void *buffer, size_t len)
  40. {
  41. ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_VERBOSE);
  42. #if CONFIG_EXAMPLE_CONNECT_PPP_DEVICE_USB
  43. tinyusb_cdcacm_write_queue(s_itf, buffer, len);
  44. tinyusb_cdcacm_write_flush(s_itf, 0);
  45. #else // DEVICE_UART
  46. uart_write_bytes(UART_NUM_1, buffer, len);
  47. #endif // CONNECT_PPP_DEVICE
  48. return ESP_OK;
  49. }
  50. static esp_netif_driver_ifconfig_t driver_cfg = {
  51. .handle = (void *)1, // singleton driver, just to != NULL
  52. .transmit = transmit,
  53. };
  54. const esp_netif_driver_ifconfig_t *ppp_driver_cfg = &driver_cfg;
  55. static void on_ip_event(void *arg, esp_event_base_t event_base,
  56. int32_t event_id, void *event_data)
  57. {
  58. if (event_id == IP_EVENT_PPP_GOT_IP) {
  59. ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
  60. if (!example_is_our_netif(EXAMPLE_NETIF_DESC_PPP, event->esp_netif)) {
  61. return;
  62. }
  63. esp_netif_t *netif = event->esp_netif;
  64. esp_netif_dns_info_t dns_info;
  65. ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
  66. esp_netif_get_dns_info(netif, ESP_NETIF_DNS_MAIN, &dns_info);
  67. ESP_LOGI(TAG, "Main DNS server : " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
  68. xEventGroupSetBits(s_event_group, GOT_IPV4);
  69. #if CONFIG_EXAMPLE_CONNECT_IPV6
  70. } else if (event_id == IP_EVENT_GOT_IP6) {
  71. ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
  72. if (!example_is_our_netif(EXAMPLE_NETIF_DESC_PPP, event->esp_netif)) {
  73. return;
  74. }
  75. esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
  76. ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
  77. IPV62STR(event->ip6_info.ip), example_ipv6_addr_types_to_str[ipv6_type]);
  78. if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
  79. xEventGroupSetBits(s_event_group, GOT_IPV6);
  80. }
  81. #endif
  82. } else if (event_id == IP_EVENT_PPP_LOST_IP) {
  83. ESP_LOGI(TAG, "Disconnect from PPP Server");
  84. s_retry_num++;
  85. if (s_retry_num > CONFIG_EXAMPLE_PPP_CONN_MAX_RETRY) {
  86. ESP_LOGE(TAG, "PPP Connection failed %d times, stop reconnecting.", s_retry_num);
  87. xEventGroupSetBits(s_event_group, CONNECTION_FAILED);
  88. } else {
  89. ESP_LOGI(TAG, "PPP Connection failed %d times, try to reconnect.", s_retry_num);
  90. esp_netif_action_start(s_netif, 0, 0, 0);
  91. esp_netif_action_connected(s_netif, 0, 0, 0);
  92. }
  93. }
  94. }
  95. #if CONFIG_EXAMPLE_CONNECT_PPP_DEVICE_USB
  96. static void cdc_rx_callback(int itf, cdcacm_event_t *event)
  97. {
  98. size_t rx_size = 0;
  99. if (itf != s_itf) {
  100. // Not our channel
  101. return;
  102. }
  103. esp_err_t ret = tinyusb_cdcacm_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size);
  104. if (ret == ESP_OK) {
  105. ESP_LOG_BUFFER_HEXDUMP(TAG, buf, rx_size, ESP_LOG_VERBOSE);
  106. // pass the received data to the network interface
  107. esp_netif_receive(s_netif, buf, rx_size, NULL);
  108. } else {
  109. ESP_LOGE(TAG, "Read error");
  110. }
  111. }
  112. static void line_state_changed(int itf, cdcacm_event_t *event)
  113. {
  114. s_itf = itf; // use this channel for the netif communication
  115. ESP_LOGI(TAG, "Line state changed on channel %d", itf);
  116. }
  117. #else // DEVICE is UART
  118. static void ppp_task(void *args)
  119. {
  120. uart_config_t uart_config = {};
  121. uart_config.baud_rate = CONFIG_EXAMPLE_CONNECT_UART_BAUDRATE;
  122. uart_config.data_bits = UART_DATA_8_BITS;
  123. uart_config.parity = UART_PARITY_DISABLE;
  124. uart_config.stop_bits = UART_STOP_BITS_1;
  125. uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
  126. uart_config.source_clk = UART_SCLK_DEFAULT;
  127. QueueHandle_t event_queue;
  128. ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, BUF_SIZE, 0, 16, &event_queue, 0));
  129. ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &uart_config));
  130. ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, CONFIG_EXAMPLE_CONNECT_UART_TX_PIN, CONFIG_EXAMPLE_CONNECT_UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
  131. ESP_ERROR_CHECK(uart_set_rx_timeout(UART_NUM_1, 1));
  132. char *buffer = (char*)malloc(BUF_SIZE);
  133. uart_event_t event;
  134. esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, s_netif);
  135. esp_netif_action_start(s_netif, 0, 0, 0);
  136. esp_netif_action_connected(s_netif, 0, 0, 0);
  137. while (!s_stop_task) {
  138. xQueueReceive(event_queue, &event, pdMS_TO_TICKS(1000));
  139. if (event.type == UART_DATA) {
  140. size_t len;
  141. uart_get_buffered_data_len(UART_NUM_1, &len);
  142. if (len) {
  143. len = uart_read_bytes(UART_NUM_1, buffer, BUF_SIZE, 0);
  144. ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_VERBOSE);
  145. esp_netif_receive(s_netif, buffer, len, NULL);
  146. }
  147. } else {
  148. ESP_LOGW(TAG, "Received UART event: %d", event.type);
  149. }
  150. }
  151. free(buffer);
  152. vTaskDelete(NULL);
  153. }
  154. #endif // CONNECT_PPP_DEVICE
  155. esp_err_t example_ppp_connect(void)
  156. {
  157. ESP_LOGI(TAG, "Start example_connect.");
  158. #if CONFIG_EXAMPLE_CONNECT_PPP_DEVICE_USB
  159. ESP_LOGI(TAG, "USB initialization");
  160. const tinyusb_config_t tusb_cfg = {
  161. .device_descriptor = NULL,
  162. .string_descriptor = NULL,
  163. .external_phy = false,
  164. .configuration_descriptor = NULL,
  165. };
  166. ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
  167. tinyusb_config_cdcacm_t acm_cfg = {
  168. .usb_dev = TINYUSB_USBDEV_0,
  169. .cdc_port = TINYUSB_CDC_ACM_0,
  170. .callback_rx = &cdc_rx_callback,
  171. .callback_rx_wanted_char = NULL,
  172. .callback_line_state_changed = NULL,
  173. .callback_line_coding_changed = NULL
  174. };
  175. ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg));
  176. /* the second way to register a callback */
  177. ESP_ERROR_CHECK(tinyusb_cdcacm_register_callback(
  178. TINYUSB_CDC_ACM_0,
  179. CDC_EVENT_LINE_STATE_CHANGED,
  180. &line_state_changed));
  181. #endif // CONFIG_EXAMPLE_CONNECT_PPP_DEVICE_USB
  182. s_event_group = xEventGroupCreate();
  183. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event, NULL));
  184. esp_netif_inherent_config_t base_netif_cfg = ESP_NETIF_INHERENT_DEFAULT_PPP();
  185. base_netif_cfg.if_desc = EXAMPLE_NETIF_DESC_PPP;
  186. esp_netif_config_t netif_ppp_config = { .base = &base_netif_cfg,
  187. .driver = ppp_driver_cfg,
  188. .stack = ESP_NETIF_NETSTACK_DEFAULT_PPP
  189. };
  190. s_netif = esp_netif_new(&netif_ppp_config);
  191. assert(s_netif);
  192. #if CONFIG_EXAMPLE_CONNECT_PPP_DEVICE_USB
  193. esp_netif_action_start(s_netif, 0, 0, 0);
  194. esp_netif_action_connected(s_netif, 0, 0, 0);
  195. #else // DEVICE is UART
  196. s_stop_task = false;
  197. if (xTaskCreate(ppp_task, "ppp connect", 4096, NULL, 5, NULL) != pdTRUE) {
  198. ESP_LOGE(TAG, "Failed to create a ppp connection task");
  199. return ESP_FAIL;
  200. }
  201. #endif // CONNECT_PPP_DEVICE
  202. ESP_LOGI(TAG, "Waiting for IP address");
  203. EventBits_t bits = xEventGroupWaitBits(s_event_group, CONNECT_BITS, pdFALSE, pdFALSE, portMAX_DELAY);
  204. if (bits & CONNECTION_FAILED) {
  205. ESP_LOGE(TAG, "Connection failed!");
  206. return ESP_FAIL;
  207. }
  208. ESP_LOGI(TAG, "Connected!");
  209. return ESP_OK;
  210. }
  211. void example_ppp_shutdown(void)
  212. {
  213. ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event));
  214. #if CONFIG_EXAMPLE_CONNECT_PPP_DEVICE_UART
  215. s_stop_task = true;
  216. vTaskDelay(pdMS_TO_TICKS(1000)); // wait for the ppp task to stop
  217. #endif
  218. esp_netif_action_disconnected(s_netif, 0, 0, 0);
  219. vEventGroupDelete(s_event_group);
  220. esp_netif_action_stop(s_netif, 0, 0, 0);
  221. esp_netif_destroy(s_netif);
  222. s_netif = NULL;
  223. s_event_group = NULL;
  224. }
  225. #endif // CONFIG_EXAMPLE_CONNECT_PPP