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