1 /*
2 * Copyright (c) 2018 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_l2_openthread, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
9
10 #include <zephyr/net/net_core.h>
11 #include <zephyr/net/net_pkt.h>
12 #include <zephyr/net/net_mgmt.h>
13 #include <zephyr/net/openthread.h>
14
15 #include <net_private.h>
16
17 #include <zephyr/init.h>
18 #include <zephyr/sys/check.h>
19 #include <zephyr/sys/slist.h>
20 #include <zephyr/sys/util.h>
21 #include <zephyr/sys/__assert.h>
22 #include <zephyr/version.h>
23
24 #include <openthread/child_supervision.h>
25 #include <openthread/cli.h>
26 #include <openthread/ip6.h>
27 #include <openthread/link.h>
28 #include <openthread/link_raw.h>
29 #include <openthread/ncp.h>
30 #include <openthread/message.h>
31 #include <openthread/platform/diag.h>
32 #include <openthread/tasklet.h>
33 #include <openthread/thread.h>
34 #include <openthread/dataset.h>
35 #include <openthread/joiner.h>
36 #include <openthread-system.h>
37 #include <utils/uart.h>
38
39 #include <platform-zephyr.h>
40
41 #include "openthread_utils.h"
42
43 #if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
44 #include <openthread/nat64.h>
45 #endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
46
47 #define PKT_IS_IPv4(_p) ((NET_IPV6_HDR(_p)->vtc & 0xf0) == 0x40)
48
49 #define OT_STACK_SIZE (CONFIG_OPENTHREAD_THREAD_STACK_SIZE)
50
51 #if defined(CONFIG_OPENTHREAD_THREAD_PREEMPTIVE)
52 #define OT_PRIORITY K_PRIO_PREEMPT(CONFIG_OPENTHREAD_THREAD_PRIORITY)
53 #else
54 #define OT_PRIORITY K_PRIO_COOP(CONFIG_OPENTHREAD_THREAD_PRIORITY)
55 #endif
56
57 #if defined(CONFIG_OPENTHREAD_NETWORK_NAME)
58 #define OT_NETWORK_NAME CONFIG_OPENTHREAD_NETWORK_NAME
59 #else
60 #define OT_NETWORK_NAME ""
61 #endif
62
63 #if defined(CONFIG_OPENTHREAD_CHANNEL)
64 #define OT_CHANNEL CONFIG_OPENTHREAD_CHANNEL
65 #else
66 #define OT_CHANNEL 0
67 #endif
68
69 #if defined(CONFIG_OPENTHREAD_PANID)
70 #define OT_PANID CONFIG_OPENTHREAD_PANID
71 #else
72 #define OT_PANID 0
73 #endif
74
75 #if defined(CONFIG_OPENTHREAD_XPANID)
76 #define OT_XPANID CONFIG_OPENTHREAD_XPANID
77 #else
78 #define OT_XPANID ""
79 #endif
80
81 #if defined(CONFIG_OPENTHREAD_NETWORKKEY)
82 #define OT_NETWORKKEY CONFIG_OPENTHREAD_NETWORKKEY
83 #else
84 #define OT_NETWORKKEY ""
85 #endif
86
87 #if defined(CONFIG_OPENTHREAD_JOINER_PSKD)
88 #define OT_JOINER_PSKD CONFIG_OPENTHREAD_JOINER_PSKD
89 #else
90 #define OT_JOINER_PSKD ""
91 #endif
92
93 #if defined(CONFIG_OPENTHREAD_PLATFORM_INFO)
94 #define OT_PLATFORM_INFO CONFIG_OPENTHREAD_PLATFORM_INFO
95 #else
96 #define OT_PLATFORM_INFO ""
97 #endif
98
99 #if defined(CONFIG_OPENTHREAD_POLL_PERIOD)
100 #define OT_POLL_PERIOD CONFIG_OPENTHREAD_POLL_PERIOD
101 #else
102 #define OT_POLL_PERIOD 0
103 #endif
104
105 #define ZEPHYR_PACKAGE_NAME "Zephyr"
106 #define PACKAGE_VERSION KERNEL_VERSION_STRING
107
108 extern void platformShellInit(otInstance *aInstance);
109
110 K_KERNEL_STACK_DEFINE(ot_stack_area, OT_STACK_SIZE);
111
112 static struct net_linkaddr *ll_addr;
113 static otStateChangedCallback state_changed_cb;
114
openthread_thread_id_get(void)115 k_tid_t openthread_thread_id_get(void)
116 {
117 struct openthread_context *ot_context = openthread_get_default_context();
118
119 return ot_context ? (k_tid_t)&ot_context->work_q.thread : 0;
120 }
121
122 #ifdef CONFIG_NET_MGMT_EVENT
123 static struct net_mgmt_event_callback ip6_addr_cb;
124
ipv6_addr_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)125 static void ipv6_addr_event_handler(struct net_mgmt_event_callback *cb,
126 uint32_t mgmt_event, struct net_if *iface)
127 {
128 if (net_if_l2(iface) != &NET_L2_GET_NAME(OPENTHREAD)) {
129 return;
130 }
131
132 #ifdef CONFIG_NET_MGMT_EVENT_INFO
133 struct openthread_context *ot_context = net_if_l2_data(iface);
134
135 if (cb->info == NULL || cb->info_length != sizeof(struct in6_addr)) {
136 return;
137 }
138
139 if (mgmt_event == NET_EVENT_IPV6_ADDR_ADD) {
140 add_ipv6_addr_to_ot(ot_context, (const struct in6_addr *)cb->info);
141 } else if (mgmt_event == NET_EVENT_IPV6_MADDR_ADD) {
142 add_ipv6_maddr_to_ot(ot_context, (const struct in6_addr *)cb->info);
143 }
144 #else
145 NET_WARN("No address info provided with event, "
146 "please enable CONFIG_NET_MGMT_EVENT_INFO");
147 #endif /* CONFIG_NET_MGMT_EVENT_INFO */
148 }
149 #endif /* CONFIG_NET_MGMT_EVENT */
150
ncp_hdlc_send(const uint8_t * buf,uint16_t len)151 static int ncp_hdlc_send(const uint8_t *buf, uint16_t len)
152 {
153 otError err;
154
155 err = otPlatUartSend(buf, len);
156 if (err != OT_ERROR_NONE) {
157 return 0;
158 }
159
160 return len;
161 }
162
163 #ifndef CONFIG_HDLC_RCP_IF
otPlatRadioGetIeeeEui64(otInstance * instance,uint8_t * ieee_eui64)164 void otPlatRadioGetIeeeEui64(otInstance *instance, uint8_t *ieee_eui64)
165 {
166 ARG_UNUSED(instance);
167
168 memcpy(ieee_eui64, ll_addr->addr, ll_addr->len);
169 }
170 #endif /* CONFIG_HDLC_RCP_IF */
171
otTaskletsSignalPending(otInstance * instance)172 void otTaskletsSignalPending(otInstance *instance)
173 {
174 struct openthread_context *ot_context = openthread_get_default_context();
175
176 if (ot_context) {
177 k_work_submit_to_queue(&ot_context->work_q, &ot_context->api_work);
178 }
179 }
180
otSysEventSignalPending(void)181 void otSysEventSignalPending(void)
182 {
183 otTaskletsSignalPending(NULL);
184 }
185
ot_state_changed_handler(uint32_t flags,void * context)186 static void ot_state_changed_handler(uint32_t flags, void *context)
187 {
188 struct openthread_state_changed_cb *entry, *next;
189 struct openthread_context *ot_context = context;
190
191 NET_INFO("State changed! Flags: 0x%08" PRIx32 " Current role: %s",
192 flags,
193 otThreadDeviceRoleToString(otThreadGetDeviceRole(ot_context->instance))
194 );
195
196 if (flags & OT_CHANGED_THREAD_ROLE) {
197 switch (otThreadGetDeviceRole(ot_context->instance)) {
198 case OT_DEVICE_ROLE_CHILD:
199 case OT_DEVICE_ROLE_ROUTER:
200 case OT_DEVICE_ROLE_LEADER:
201 net_if_dormant_off(ot_context->iface);
202 break;
203
204 case OT_DEVICE_ROLE_DISABLED:
205 case OT_DEVICE_ROLE_DETACHED:
206 default:
207 net_if_dormant_on(ot_context->iface);
208 break;
209 }
210 }
211
212 if (flags & OT_CHANGED_IP6_ADDRESS_REMOVED) {
213 NET_DBG("Ipv6 address removed");
214 rm_ipv6_addr_from_zephyr(ot_context);
215 }
216
217 if (flags & OT_CHANGED_IP6_ADDRESS_ADDED) {
218 NET_DBG("Ipv6 address added");
219 add_ipv6_addr_to_zephyr(ot_context);
220 }
221
222 if (flags & OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED) {
223 NET_DBG("Ipv6 multicast address removed");
224 rm_ipv6_maddr_from_zephyr(ot_context);
225 }
226
227 if (flags & OT_CHANGED_IP6_MULTICAST_SUBSCRIBED) {
228 NET_DBG("Ipv6 multicast address added");
229 add_ipv6_maddr_to_zephyr(ot_context);
230 }
231
232 #if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
233
234 if (flags & OT_CHANGED_NAT64_TRANSLATOR_STATE) {
235 NET_DBG("Nat64 translator state changed to %x",
236 otNat64GetTranslatorState(ot_context->instance));
237 }
238
239 #endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
240
241 if (state_changed_cb) {
242 state_changed_cb(flags, context);
243 }
244
245 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ot_context->state_change_cbs, entry, next, node) {
246 if (entry->state_changed_cb != NULL) {
247 entry->state_changed_cb(flags, ot_context, entry->user_data);
248 }
249 }
250 }
251
ot_receive_handler(otMessage * aMessage,void * context)252 static void ot_receive_handler(otMessage *aMessage, void *context)
253 {
254 struct openthread_context *ot_context = context;
255
256 uint16_t offset = 0U;
257 uint16_t read_len;
258 struct net_pkt *pkt;
259 struct net_buf *pkt_buf;
260
261 pkt = net_pkt_rx_alloc_with_buffer(ot_context->iface,
262 otMessageGetLength(aMessage),
263 AF_UNSPEC, 0, K_NO_WAIT);
264 if (!pkt) {
265 NET_ERR("Failed to reserve net pkt");
266 goto out;
267 }
268
269 pkt_buf = pkt->buffer;
270
271 while (1) {
272 read_len = otMessageRead(aMessage, offset, pkt_buf->data,
273 net_buf_tailroom(pkt_buf));
274 if (!read_len) {
275 break;
276 }
277
278 net_buf_add(pkt_buf, read_len);
279
280 offset += read_len;
281
282 if (!net_buf_tailroom(pkt_buf)) {
283 pkt_buf = pkt_buf->frags;
284 if (!pkt_buf) {
285 break;
286 }
287 }
288 }
289
290 NET_DBG("Injecting %s packet to Zephyr net stack",
291 PKT_IS_IPv4(pkt) ? "translated IPv4" : "Ip6");
292
293 if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
294 if (IS_ENABLED(CONFIG_OPENTHREAD_NAT64_TRANSLATOR) && PKT_IS_IPv4(pkt)) {
295 net_pkt_hexdump(pkt, "Received NAT64 IPv4 packet");
296 } else {
297 net_pkt_hexdump(pkt, "Received IPv6 packet");
298 }
299 }
300
301 if (!pkt_list_is_full(ot_context)) {
302 if (pkt_list_add(ot_context, pkt) != 0) {
303 NET_ERR("pkt_list_add failed");
304 goto out;
305 }
306
307 if (net_recv_data(ot_context->iface, pkt) < 0) {
308 NET_ERR("net_recv_data failed");
309 pkt_list_remove_first(ot_context);
310 goto out;
311 }
312
313 pkt = NULL;
314 } else {
315 NET_INFO("Packet list is full");
316 }
317 out:
318 if (pkt) {
319 net_pkt_unref(pkt);
320 }
321
322 otMessageFree(aMessage);
323 }
324
ot_joiner_start_handler(otError error,void * context)325 static void ot_joiner_start_handler(otError error, void *context)
326 {
327 struct openthread_context *ot_context = context;
328
329 switch (error) {
330 case OT_ERROR_NONE:
331 NET_INFO("Join success");
332 otThreadSetEnabled(ot_context->instance, true);
333 break;
334 default:
335 NET_ERR("Join failed [%d]", error);
336 break;
337 }
338 }
339
openthread_process(struct k_work * work)340 static void openthread_process(struct k_work *work)
341 {
342 struct openthread_context *ot_context
343 = CONTAINER_OF(work, struct openthread_context, api_work);
344
345 openthread_api_mutex_lock(ot_context);
346
347 while (otTaskletsArePending(ot_context->instance)) {
348 otTaskletsProcess(ot_context->instance);
349 }
350
351 otSysProcessDrivers(ot_context->instance);
352
353 openthread_api_mutex_unlock(ot_context);
354 }
355
is_ipv6_frag(struct net_pkt * pkt)356 static bool is_ipv6_frag(struct net_pkt *pkt)
357 {
358 NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
359 struct net_ipv6_hdr *hdr;
360
361 hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
362 if (!hdr) {
363 return false;
364 }
365
366 return hdr->nexthdr == NET_IPV6_NEXTHDR_FRAG ? true : false;
367 }
368
openthread_recv(struct net_if * iface,struct net_pkt * pkt)369 static enum net_verdict openthread_recv(struct net_if *iface, struct net_pkt *pkt)
370 {
371 struct openthread_context *ot_context = net_if_l2_data(iface);
372
373 if (pkt_list_peek(ot_context) == pkt) {
374 pkt_list_remove_last(ot_context);
375 NET_DBG("Got injected Ip6 packet, sending to upper layers");
376
377 if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
378 net_pkt_hexdump(pkt, "Injected IPv6 packet");
379 }
380
381 if (IS_ENABLED(CONFIG_OPENTHREAD_IP6_FRAGM) && is_ipv6_frag(pkt)) {
382 return NET_DROP;
383 }
384
385 return NET_CONTINUE;
386 }
387
388 NET_DBG("Got 802.15.4 packet, sending to OT");
389
390 if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
391 net_pkt_hexdump(pkt, "Received 802.15.4 frame");
392 }
393
394 if (notify_new_rx_frame(pkt) != 0) {
395 NET_ERR("Failed to queue RX packet for OpenThread");
396 return NET_DROP;
397 }
398
399 return NET_OK;
400 }
401
openthread_send(struct net_if * iface,struct net_pkt * pkt)402 int openthread_send(struct net_if *iface, struct net_pkt *pkt)
403 {
404 int len = net_pkt_get_len(pkt);
405
406 if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
407 net_pkt_hexdump(pkt, "IPv6 packet to send");
408 }
409
410 net_capture_pkt(iface, pkt);
411
412 if (notify_new_tx_frame(pkt) != 0) {
413 net_pkt_unref(pkt);
414 }
415
416 return len;
417 }
418
openthread_start(struct openthread_context * ot_context)419 int openthread_start(struct openthread_context *ot_context)
420 {
421 otInstance *ot_instance = ot_context->instance;
422 otError error = OT_ERROR_NONE;
423
424 openthread_api_mutex_lock(ot_context);
425
426 NET_INFO("OpenThread version: %s", otGetVersionString());
427
428 if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
429 NET_DBG("OpenThread co-processor.");
430 goto exit;
431 }
432
433 otIp6SetEnabled(ot_context->instance, true);
434
435 /* Sleepy End Device specific configuration. */
436 if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) {
437 otLinkModeConfig ot_mode = otThreadGetLinkMode(ot_instance);
438
439 /* A SED should always attach the network as a SED to indicate
440 * increased buffer requirement to a parent.
441 */
442 ot_mode.mRxOnWhenIdle = false;
443
444 otThreadSetLinkMode(ot_context->instance, ot_mode);
445 otLinkSetPollPeriod(ot_context->instance, OT_POLL_PERIOD);
446 }
447
448 /* Configure Child Supervision and MLE Child timeouts. */
449 otChildSupervisionSetInterval(ot_context->instance,
450 CONFIG_OPENTHREAD_CHILD_SUPERVISION_INTERVAL);
451 otChildSupervisionSetCheckTimeout(ot_context->instance,
452 CONFIG_OPENTHREAD_CHILD_SUPERVISION_CHECK_TIMEOUT);
453 otThreadSetChildTimeout(ot_context->instance, CONFIG_OPENTHREAD_MLE_CHILD_TIMEOUT);
454
455 if (otDatasetIsCommissioned(ot_instance)) {
456 /* OpenThread already has dataset stored - skip the
457 * configuration.
458 */
459 NET_DBG("OpenThread already commissioned.");
460 } else if (IS_ENABLED(CONFIG_OPENTHREAD_JOINER_AUTOSTART)) {
461 /* No dataset - initiate network join procedure. */
462 NET_DBG("Starting OpenThread join procedure.");
463
464 error = otJoinerStart(ot_instance, OT_JOINER_PSKD, NULL, ZEPHYR_PACKAGE_NAME,
465 OT_PLATFORM_INFO, PACKAGE_VERSION, NULL,
466 &ot_joiner_start_handler, ot_context);
467
468 if (error != OT_ERROR_NONE) {
469 NET_ERR("Failed to start joiner [%d]", error);
470 }
471
472 goto exit;
473 } else {
474 /* No dataset - load the default configuration. */
475 NET_DBG("Loading OpenThread default configuration.");
476
477 otExtendedPanId xpanid;
478 otNetworkKey networkKey;
479
480 otThreadSetNetworkName(ot_instance, OT_NETWORK_NAME);
481 otLinkSetChannel(ot_instance, OT_CHANNEL);
482 otLinkSetPanId(ot_instance, OT_PANID);
483 net_bytes_from_str(xpanid.m8, 8, (char *)OT_XPANID);
484 otThreadSetExtendedPanId(ot_instance, &xpanid);
485
486 if (strlen(OT_NETWORKKEY)) {
487 net_bytes_from_str(networkKey.m8, OT_NETWORK_KEY_SIZE,
488 (char *)OT_NETWORKKEY);
489 otThreadSetNetworkKey(ot_instance, &networkKey);
490 }
491 }
492
493 NET_INFO("Network name: %s",
494 otThreadGetNetworkName(ot_instance));
495
496 /* Start the network. */
497 error = otThreadSetEnabled(ot_instance, true);
498 if (error != OT_ERROR_NONE) {
499 NET_ERR("Failed to start the OpenThread network [%d]", error);
500 }
501
502 exit:
503
504 openthread_api_mutex_unlock(ot_context);
505
506 return error == OT_ERROR_NONE ? 0 : -EIO;
507 }
508
openthread_stop(struct openthread_context * ot_context)509 int openthread_stop(struct openthread_context *ot_context)
510 {
511 otError error;
512
513 if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
514 return 0;
515 }
516
517 openthread_api_mutex_lock(ot_context);
518
519 error = otThreadSetEnabled(ot_context->instance, false);
520 if (error == OT_ERROR_INVALID_STATE) {
521 NET_DBG("Openthread interface was not up [%d]", error);
522 }
523
524 openthread_api_mutex_unlock(ot_context);
525
526 return 0;
527 }
528
openthread_init(struct net_if * iface)529 static int openthread_init(struct net_if *iface)
530 {
531 struct openthread_context *ot_context = net_if_l2_data(iface);
532 struct k_work_queue_config q_cfg = {
533 .name = "openthread",
534 .no_yield = true,
535 };
536 otError err;
537
538 NET_DBG("openthread_init");
539
540 k_mutex_init(&ot_context->api_lock);
541 k_work_init(&ot_context->api_work, openthread_process);
542
543 ll_addr = net_if_get_link_addr(iface);
544
545 openthread_api_mutex_lock(ot_context);
546
547 otSysInit(0, NULL);
548
549 ot_context->instance = otInstanceInitSingle();
550 ot_context->iface = iface;
551
552 __ASSERT(ot_context->instance, "OT instance is NULL");
553
554 if (IS_ENABLED(CONFIG_OPENTHREAD_SHELL)) {
555 platformShellInit(ot_context->instance);
556 }
557
558 if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
559 otPlatUartEnable();
560 otNcpHdlcInit(ot_context->instance, ncp_hdlc_send);
561 } else {
562 otIp6SetReceiveFilterEnabled(ot_context->instance, true);
563 otIp6SetReceiveCallback(ot_context->instance,
564 ot_receive_handler, ot_context);
565
566 #if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
567
568 otIp4Cidr nat64_cidr;
569
570 if (otIp4CidrFromString(CONFIG_OPENTHREAD_NAT64_CIDR, &nat64_cidr) ==
571 OT_ERROR_NONE) {
572 if (otNat64SetIp4Cidr(openthread_get_default_instance(), &nat64_cidr) !=
573 OT_ERROR_NONE) {
574 NET_ERR("Incorrect NAT64 CIDR");
575 }
576 } else {
577 NET_ERR("Failed to parse NAT64 CIDR");
578 }
579 otNat64SetReceiveIp4Callback(ot_context->instance, ot_receive_handler, ot_context);
580
581 #endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
582
583 sys_slist_init(&ot_context->state_change_cbs);
584 err = otSetStateChangedCallback(ot_context->instance,
585 &ot_state_changed_handler,
586 ot_context);
587 if (err != OT_ERROR_NONE) {
588 NET_ERR("Could not set state changed callback: %d", err);
589 }
590
591 net_mgmt_init_event_callback(
592 &ip6_addr_cb, ipv6_addr_event_handler,
593 NET_EVENT_IPV6_ADDR_ADD | NET_EVENT_IPV6_MADDR_ADD);
594 net_mgmt_add_event_callback(&ip6_addr_cb);
595
596 net_if_dormant_on(iface);
597 }
598
599 openthread_api_mutex_unlock(ot_context);
600
601 k_work_queue_start(&ot_context->work_q, ot_stack_area,
602 K_KERNEL_STACK_SIZEOF(ot_stack_area),
603 OT_PRIORITY, &q_cfg);
604
605 (void)k_work_submit_to_queue(&ot_context->work_q, &ot_context->api_work);
606
607 return 0;
608 }
609
ieee802154_init(struct net_if * iface)610 void ieee802154_init(struct net_if *iface)
611 {
612 if (IS_ENABLED(CONFIG_IEEE802154_NET_IF_NO_AUTO_START)) {
613 LOG_DBG("Interface auto start disabled.");
614 net_if_flag_set(iface, NET_IF_NO_AUTO_START);
615 }
616
617 net_if_flag_set(iface, NET_IF_IPV6_NO_ND);
618 net_if_flag_set(iface, NET_IF_IPV6_NO_MLD);
619
620 openthread_init(iface);
621 }
622
openthread_flags(struct net_if * iface)623 static enum net_l2_flags openthread_flags(struct net_if *iface)
624 {
625 /* TODO: Should report NET_L2_PROMISC_MODE if the radio driver
626 * reports the IEEE802154_HW_PROMISC capability.
627 */
628 return NET_L2_MULTICAST | NET_L2_MULTICAST_SKIP_JOIN_SOLICIT_NODE;
629 }
630
openthread_enable(struct net_if * iface,bool state)631 static int openthread_enable(struct net_if *iface, bool state)
632 {
633 struct openthread_context *ot_context = net_if_l2_data(iface);
634
635 NET_DBG("iface %p %s", iface, state ? "up" : "down");
636
637 if (state) {
638 if (IS_ENABLED(CONFIG_OPENTHREAD_MANUAL_START)) {
639 NET_DBG("OpenThread manual start.");
640 return 0;
641 }
642
643 return openthread_start(ot_context);
644 }
645
646 return openthread_stop(ot_context);
647 }
648
openthread_get_default_context(void)649 struct openthread_context *openthread_get_default_context(void)
650 {
651 struct net_if *iface;
652 struct openthread_context *ot_context = NULL;
653
654 iface = net_if_get_first_by_type(&NET_L2_GET_NAME(OPENTHREAD));
655 if (!iface) {
656 NET_ERR("There is no net interface for OpenThread");
657 goto exit;
658 }
659
660 ot_context = net_if_l2_data(iface);
661 if (!ot_context) {
662 NET_ERR("There is no Openthread context in net interface data");
663 goto exit;
664 }
665
666 exit:
667 return ot_context;
668 }
669
openthread_get_default_instance(void)670 struct otInstance *openthread_get_default_instance(void)
671 {
672 struct openthread_context *ot_context =
673 openthread_get_default_context();
674
675 return ot_context ? ot_context->instance : NULL;
676 }
677
openthread_state_changed_cb_register(struct openthread_context * ot_context,struct openthread_state_changed_cb * cb)678 int openthread_state_changed_cb_register(struct openthread_context *ot_context,
679 struct openthread_state_changed_cb *cb)
680 {
681 CHECKIF(cb == NULL || cb->state_changed_cb == NULL) {
682 return -EINVAL;
683 }
684
685 openthread_api_mutex_lock(ot_context);
686 sys_slist_append(&ot_context->state_change_cbs, &cb->node);
687 openthread_api_mutex_unlock(ot_context);
688
689 return 0;
690 }
691
openthread_state_changed_cb_unregister(struct openthread_context * ot_context,struct openthread_state_changed_cb * cb)692 int openthread_state_changed_cb_unregister(struct openthread_context *ot_context,
693 struct openthread_state_changed_cb *cb)
694 {
695 bool removed;
696
697 CHECKIF(cb == NULL) {
698 return -EINVAL;
699 }
700
701 openthread_api_mutex_lock(ot_context);
702 removed = sys_slist_find_and_remove(&ot_context->state_change_cbs, &cb->node);
703 openthread_api_mutex_unlock(ot_context);
704
705 if (!removed) {
706 return -EALREADY;
707 }
708
709 return 0;
710 }
711
openthread_set_state_changed_cb(otStateChangedCallback cb)712 void openthread_set_state_changed_cb(otStateChangedCallback cb)
713 {
714 state_changed_cb = cb;
715 }
716
openthread_api_mutex_lock(struct openthread_context * ot_context)717 void openthread_api_mutex_lock(struct openthread_context *ot_context)
718 {
719 (void)k_mutex_lock(&ot_context->api_lock, K_FOREVER);
720 }
721
openthread_api_mutex_try_lock(struct openthread_context * ot_context)722 int openthread_api_mutex_try_lock(struct openthread_context *ot_context)
723 {
724 return k_mutex_lock(&ot_context->api_lock, K_NO_WAIT);
725 }
726
openthread_api_mutex_unlock(struct openthread_context * ot_context)727 void openthread_api_mutex_unlock(struct openthread_context *ot_context)
728 {
729 (void)k_mutex_unlock(&ot_context->api_lock);
730 }
731
732 NET_L2_INIT(OPENTHREAD_L2, openthread_recv, openthread_send, openthread_enable,
733 openthread_flags);
734