esp_openthread.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "esp_openthread.h"
  7. #include "esp_check.h"
  8. #include "esp_openthread_border_router.h"
  9. #include "esp_openthread_common_macro.h"
  10. #include "esp_openthread_dns64.h"
  11. #include "esp_openthread_lock.h"
  12. #include "esp_openthread_platform.h"
  13. #include "esp_openthread_sleep.h"
  14. #include "esp_openthread_task_queue.h"
  15. #include "esp_openthread_types.h"
  16. #include "freertos/FreeRTOS.h"
  17. #include "lwip/dns.h"
  18. #include "openthread/instance.h"
  19. #include "openthread/netdata.h"
  20. #include "openthread/tasklet.h"
  21. #include "openthread/thread.h"
  22. static int hex_digit_to_int(char hex)
  23. {
  24. if ('A' <= hex && hex <= 'F') {
  25. return 10 + hex - 'A';
  26. }
  27. if ('a' <= hex && hex <= 'f') {
  28. return 10 + hex - 'a';
  29. }
  30. if ('0' <= hex && hex <= '9') {
  31. return hex - '0';
  32. }
  33. return -1;
  34. }
  35. static size_t hex_string_to_binary(const char *hex_string, uint8_t *buf, size_t buf_size)
  36. {
  37. int num_char = strlen(hex_string);
  38. if (num_char != buf_size * 2) {
  39. return 0;
  40. }
  41. for (size_t i = 0; i < num_char; i += 2) {
  42. int digit0 = hex_digit_to_int(hex_string[i]);
  43. int digit1 = hex_digit_to_int(hex_string[i + 1]);
  44. if (digit0 < 0 || digit1 < 0) {
  45. return 0;
  46. }
  47. buf[i / 2] = (digit0 << 4) + digit1;
  48. }
  49. return buf_size;
  50. }
  51. esp_err_t esp_openthread_init(const esp_openthread_platform_config_t *config)
  52. {
  53. ESP_RETURN_ON_ERROR(esp_openthread_platform_init(config), OT_PLAT_LOG_TAG,
  54. "Failed to initialize OpenThread platform driver");
  55. #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
  56. ESP_RETURN_ON_ERROR(esp_openthread_sleep_init(), OT_PLAT_LOG_TAG,
  57. "Failed to initialize OpenThread esp pm_lock");
  58. #endif
  59. esp_openthread_lock_acquire(portMAX_DELAY);
  60. ESP_RETURN_ON_FALSE(otInstanceInitSingle() != NULL, ESP_FAIL, OT_PLAT_LOG_TAG,
  61. "Failed to initialize OpenThread instance");
  62. #if CONFIG_OPENTHREAD_DNS64_CLIENT
  63. ESP_RETURN_ON_ERROR(esp_openthread_dns64_client_init(), OT_PLAT_LOG_TAG,
  64. "Failed to initialize OpenThread dns64 client");
  65. #endif
  66. esp_openthread_lock_release();
  67. return ESP_OK;
  68. }
  69. esp_err_t esp_openthread_auto_start(otOperationalDatasetTlvs *datasetTlvs)
  70. {
  71. otInstance *instance = esp_openthread_get_instance();
  72. if (datasetTlvs) {
  73. ESP_RETURN_ON_FALSE(otDatasetSetActiveTlvs(instance, datasetTlvs) == OT_ERROR_NONE, ESP_FAIL, OT_PLAT_LOG_TAG,
  74. "Failed to set OpenThread active dataset");
  75. }
  76. else {
  77. otOperationalDataset dataset;
  78. size_t len = 0;
  79. memset(&dataset, 0, sizeof(otOperationalDataset));
  80. // Active timestamp
  81. dataset.mActiveTimestamp.mSeconds = 1;
  82. dataset.mActiveTimestamp.mTicks = 0;
  83. dataset.mActiveTimestamp.mAuthoritative = false;
  84. dataset.mComponents.mIsActiveTimestampPresent = true;
  85. // Channel, Pan ID, Network Name
  86. dataset.mChannel = CONFIG_OPENTHREAD_NETWORK_CHANNEL;
  87. dataset.mComponents.mIsChannelPresent = true;
  88. dataset.mPanId = CONFIG_OPENTHREAD_NETWORK_PANID;
  89. dataset.mComponents.mIsPanIdPresent = true;
  90. len = strlen(CONFIG_OPENTHREAD_NETWORK_NAME);
  91. assert(len <= OT_NETWORK_NAME_MAX_SIZE);
  92. memcpy(dataset.mNetworkName.m8, CONFIG_OPENTHREAD_NETWORK_NAME, len);
  93. dataset.mComponents.mIsNetworkNamePresent = true;
  94. // Extended Pan ID
  95. len = hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_EXTPANID, dataset.mExtendedPanId.m8,
  96. sizeof(dataset.mExtendedPanId.m8));
  97. ESP_RETURN_ON_FALSE(len == sizeof(dataset.mExtendedPanId.m8), ESP_FAIL, OT_PLAT_LOG_TAG,
  98. "Cannot convert OpenThread extended pan id");
  99. dataset.mComponents.mIsExtendedPanIdPresent = true;
  100. // Network Key
  101. len = hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_MASTERKEY, dataset.mNetworkKey.m8,
  102. sizeof(dataset.mNetworkKey.m8));
  103. ESP_RETURN_ON_FALSE(len == sizeof(dataset.mNetworkKey.m8), ESP_FAIL, OT_PLAT_LOG_TAG,
  104. "Cannot convert OpenThread master key");
  105. dataset.mComponents.mIsNetworkKeyPresent = true;
  106. // PSKc
  107. len = hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_PSKC, dataset.mPskc.m8, sizeof(dataset.mPskc.m8));
  108. ESP_RETURN_ON_FALSE(len == sizeof(dataset.mPskc.m8), ESP_FAIL, OT_PLAT_LOG_TAG,
  109. "Cannot convert OpenThread pre-shared commissioner key");
  110. dataset.mComponents.mIsPskcPresent = true;
  111. ESP_RETURN_ON_FALSE(otDatasetSetActive(instance, &dataset) == OT_ERROR_NONE, ESP_FAIL, OT_PLAT_LOG_TAG,
  112. "Failed to set OpenThread active dataset");
  113. }
  114. ESP_RETURN_ON_FALSE(otIp6SetEnabled(instance, true) == OT_ERROR_NONE, ESP_FAIL, OT_PLAT_LOG_TAG,
  115. "Failed to enable OpenThread IPv6 interface");
  116. ESP_RETURN_ON_FALSE(otThreadSetEnabled(instance, true) == OT_ERROR_NONE, ESP_FAIL, OT_PLAT_LOG_TAG,
  117. "Failed to enable OpenThread");
  118. return ESP_OK;
  119. }
  120. esp_err_t esp_openthread_launch_mainloop(void)
  121. {
  122. esp_openthread_mainloop_context_t mainloop;
  123. otInstance *instance = esp_openthread_get_instance();
  124. esp_err_t error = ESP_OK;
  125. while (true) {
  126. FD_ZERO(&mainloop.read_fds);
  127. FD_ZERO(&mainloop.write_fds);
  128. FD_ZERO(&mainloop.error_fds);
  129. mainloop.max_fd = -1;
  130. mainloop.timeout.tv_sec = 10;
  131. mainloop.timeout.tv_usec = 0;
  132. esp_openthread_lock_acquire(portMAX_DELAY);
  133. esp_openthread_platform_update(&mainloop);
  134. if (otTaskletsArePending(instance)) {
  135. mainloop.timeout.tv_sec = 0;
  136. mainloop.timeout.tv_usec = 0;
  137. }
  138. #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
  139. esp_openthread_sleep_process();
  140. #endif
  141. esp_openthread_lock_release();
  142. if (select(mainloop.max_fd + 1, &mainloop.read_fds, &mainloop.write_fds, &mainloop.error_fds,
  143. &mainloop.timeout) >= 0) {
  144. esp_openthread_lock_acquire(portMAX_DELAY);
  145. #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
  146. esp_openthread_wakeup_process();
  147. #endif
  148. error = esp_openthread_platform_process(instance, &mainloop);
  149. while (otTaskletsArePending(instance)) {
  150. otTaskletsProcess(instance);
  151. }
  152. esp_openthread_lock_release();
  153. if (error != ESP_OK) {
  154. ESP_LOGE(OT_PLAT_LOG_TAG, "esp_openthread_platform_process failed");
  155. break;
  156. }
  157. } else {
  158. error = ESP_FAIL;
  159. ESP_LOGE(OT_PLAT_LOG_TAG, "OpenThread system polling failed");
  160. break;
  161. }
  162. }
  163. return error;
  164. }
  165. esp_err_t esp_openthread_deinit(void)
  166. {
  167. otInstanceFinalize(esp_openthread_get_instance());
  168. return esp_openthread_platform_deinit();
  169. }
  170. static void stub_task(void *context)
  171. {
  172. // this is a empty function used for ot-task signal pending
  173. }
  174. void otTaskletsSignalPending(otInstance *aInstance)
  175. {
  176. esp_openthread_task_queue_post(stub_task, NULL);
  177. }