openthread: Move OpenThread implementation from net to modules

Move OpenThread-related code from
zephyr/subsys/net/l2/openthread/openthread.c to
zephyr/modules/openthread/platform/openthread.c.

The primary goal of this refactor is to enable the use
of OpenThread as an independent module, without the necessity
of Zephyr's networking layer.

This change is particularly beneficial for simple applications
that have their own implementation of the IEEE802.15.4 driver
and do not require a networking layer. These applications can
now disable Zephyr's L2 and IEEE802.15.4 shim layers and
directly use the OpenThread module, saving valuable kilobytes
of memory.

In this approach if the CONFIG_NET_L2_OPENTHREAD
Kconfig option is set, Zephyr's L2 and IEEE802.15.4 layers
will be used, and everything will function as before.
The main difference is the Zephyr's L2 layer now uses
the OpenThread module, no longer implementing it.

While most of the functions in include/net/openthread.h
have been deprecated, they are still available for use to
maintain backwards compatibility.

Signed-off-by: Arkadiusz Balys <arkadiusz.balys@nordicsemi.no>
This commit is contained in:
Arkadiusz Balys 2025-04-18 16:07:55 +02:00 committed by Benjamin Cabé
commit 596844a2cb
7 changed files with 759 additions and 467 deletions

View file

@ -5,15 +5,15 @@
*/
/** @file
* @brief OpenThread L2 stack public header
* @brief OpenThread stack public header
*/
#ifndef ZEPHYR_INCLUDE_NET_OPENTHREAD_H_
#define ZEPHYR_INCLUDE_NET_OPENTHREAD_H_
/**
* @brief OpenThread Layer 2 abstraction layer
* @defgroup openthread OpenThread L2 abstraction layer
* @brief OpenThread stack public header
* @defgroup openthread OpenThread stack
* @since 1.11
* @version 0.8.0
* @ingroup ieee802154
@ -21,10 +21,11 @@
*/
#include <zephyr/kernel.h>
#include <zephyr/net/net_if.h>
#include <zephyr/kernel/thread.h>
#include <openthread/instance.h>
#include <openthread/message.h>
#ifdef __cplusplus
extern "C" {
@ -44,8 +45,10 @@ struct pkt_list_elem {
* @brief OpenThread l2 private data.
*/
struct openthread_context {
/** Pointer to OpenThread stack instance */
otInstance *instance;
/** @deprecated Pointer to OpenThread stack instance. This is deprecated and will be removed
* in a future release. This field must not be used anymore.
*/
__deprecated otInstance *instance;
/** Pointer to OpenThread network interface */
struct net_if *iface;
@ -62,25 +65,74 @@ struct openthread_context {
/** Array for storing net_pkt for OpenThread internal usage */
struct pkt_list_elem pkt_list[CONFIG_OPENTHREAD_PKT_LIST_SIZE];
/** A mutex to protect API calls from being preempted. */
struct k_mutex api_lock;
/** @deprecated A mutex to protect API calls from being preempted. This is deprecated and
* will be removed in a future release. This field must not be used anymore.
*/
__deprecated struct k_mutex api_lock;
/** A work queue for all OpenThread activity */
struct k_work_q work_q;
/** @deprecated A work queue for all OpenThread activity. This is deprecated and will be
* removed in a future release. This field must not be used anymore.
*/
__deprecated struct k_work_q work_q;
/** Work object for OpenThread internal usage */
struct k_work api_work;
/** @deprecated Work object for OpenThread internal usage. This is deprecated and will be
* removed in a future release. This field must not be used anymore.
*/
__deprecated struct k_work api_work;
/** A list for state change callbacks */
/** @deprecated A list for state change callbacks. This is deprecated and will be removed in
* a future release.
*/
sys_slist_t state_change_cbs;
};
/**
* INTERNAL_HIDDEN @endcond
*/
/**
* @brief The common callback type for receiving IPv4 (translated by NAT64) and IPv6 datagrams.
*
* This callback is called when a datagram is received.
*
* @param message The message to receive.
* @param context The context to pass to the callback.
*/
typedef void (*openthread_receive_cb)(otMessage *message, void *context);
/** OpenThread state change callback */
/**
* @brief OpenThread state change callback structure
*
* Used to register a callback in the callback list. As many
* callbacks as needed can be added as long as each of them
* are unique pointers of struct openthread_state_changed_cb.
*
* @note You may destroy the object only after it is unregistered from the callback list.
*/
struct openthread_state_changed_callback {
/**
* @brief Callback for notifying configuration or state changes.
*
* @param otCallback OpenThread callback to register.
* See https://openthread.io/reference/group/api-instance#otstatechangedcallback for
* details.
*/
otStateChangedCallback otCallback;
/** User data if required */
void *user_data;
/**
* Internally used field for list handling
* - user must not directly modify
*/
sys_snode_t node;
};
/**
* @deprecated use @ref openthread_state_changed_callback instead.
*
* @brief OpenThread state change callback structure
*
* Used to register a callback in the callback list. As many
@ -111,23 +163,42 @@ struct openthread_state_changed_cb {
};
/**
* @brief Register callbacks that will be called when a certain configuration
* or state changes occur within OpenThread.
*
* @param cb Callback struct to register.
*/
int openthread_state_changed_callback_register(struct openthread_state_changed_callback *cb);
/**
* @brief Unregister OpenThread configuration or state changed callbacks.
*
* @param cb Callback struct to unregister.
*/
int openthread_state_changed_callback_unregister(struct openthread_state_changed_callback *cb);
/**
* @deprecated use @ref openthread_state_changed_callback_register instead.
*
* @brief Registers callbacks which will be called when certain configuration
* or state changes occur within OpenThread.
*
* @param ot_context the OpenThread context to register the callback with.
* @param cb callback struct to register.
*/
int openthread_state_changed_cb_register(struct openthread_context *ot_context,
struct openthread_state_changed_cb *cb);
__deprecated int openthread_state_changed_cb_register(struct openthread_context *ot_context,
struct openthread_state_changed_cb *cb);
/**
* @deprecated use @ref openthread_state_changed_callback_unregister instead.
*
* @brief Unregisters OpenThread configuration or state changed callbacks.
*
* @param ot_context the OpenThread context to unregister the callback from.
* @param cb callback struct to unregister.
*/
int openthread_state_changed_cb_unregister(struct openthread_context *ot_context,
struct openthread_state_changed_cb *cb);
__deprecated int openthread_state_changed_cb_unregister(struct openthread_context *ot_context,
struct openthread_state_changed_cb *cb);
/**
* @brief Get OpenThread thread identification.
@ -151,6 +222,44 @@ struct openthread_context *openthread_get_default_context(void);
struct otInstance *openthread_get_default_instance(void);
/**
* @brief Initialize the OpenThread module.
*
* This function:
* - Initializes the OpenThread module.
* - Creates an OpenThread single instance.
* - Starts the shell.
* - Enables the UART and NCP HDLC for coprocessor purposes.
* - Initializes the NAT64 translator.
* - Creates a work queue for the OpenThread module.
*
* @note This function is automatically called by Zephyr's networking layer.
* If you want to initialize the OpenThread independently, call this function
* in your application init code.
*
* @retval 0 On success.
* @retval -EIO On failure.
*/
int openthread_init(void);
/**
* @brief Run the OpenThread network.
*
* @details Prepares the OpenThread network and enables it.
* Depends on active settings: it uses the stored network configuration,
* starts the joining procedure or uses the default network configuration.
* Additionally, when the device is MTD, it sets the SED mode to properly
* attach the network.
*/
int openthread_run(void);
/**
* @brief Disable the OpenThread network.
*/
int openthread_stop(void);
/**
* @deprecated use @ref openthread_run instead.
*
* @brief Starts the OpenThread network.
*
* @details Depends on active settings: it uses stored network configuration,
@ -159,9 +268,46 @@ struct otInstance *openthread_get_default_instance(void);
*
* @param ot_context
*/
int openthread_start(struct openthread_context *ot_context);
__deprecated int openthread_start(struct openthread_context *ot_context);
/**
* @brief Set the additional callback for receiving packets.
*
* @details This callback is called once a packet is received and can be
* used to inject packets into the Zephyr networking stack.
* Setting this callback is optional.
*
* @param cb Callback to set.
* @param context Context to pass to the callback.
*/
void openthread_set_receive_cb(openthread_receive_cb cb, void *context);
/**
* @brief Lock internal mutex before accessing OpenThread API.
*
* @details OpenThread API is not thread-safe. Therefore, before accessing any
* API function, you need to lock the internal mutex, to prevent the
* OpenThread thread from pre-empting the API call.
*/
void openthread_mutex_lock(void);
/**
* @brief Try to lock internal mutex before accessing OpenThread API.
*
* @details This function behaves like openthread_mutex_lock(), provided that
* the internal mutex is unlocked. Otherwise, it returns a negative value without
* waiting.
*/
int openthread_mutex_try_lock(void);
/**
* @brief Unlock internal mutex after accessing OpenThread API.
*/
void openthread_mutex_unlock(void);
/**
* @deprecated use @ref openthread_mutex_lock.
*
* @brief Lock internal mutex before accessing OT API.
*
* @details OpenThread API is not thread-safe, therefore before accessing any
@ -170,9 +316,11 @@ int openthread_start(struct openthread_context *ot_context);
*
* @param ot_context Context to lock.
*/
void openthread_api_mutex_lock(struct openthread_context *ot_context);
__deprecated void openthread_api_mutex_lock(struct openthread_context *ot_context);
/**
* @deprecated use @ref openthread_mutex_try_lock instead.
*
* @brief Try to lock internal mutex before accessing OT API.
*
* @details This function behaves like openthread_api_mutex_lock() provided that
@ -183,14 +331,16 @@ void openthread_api_mutex_lock(struct openthread_context *ot_context);
* @retval 0 On success.
* @retval <0 On failure.
*/
int openthread_api_mutex_try_lock(struct openthread_context *ot_context);
__deprecated int openthread_api_mutex_try_lock(struct openthread_context *ot_context);
/**
* @deprecated use @ref openthread_mutex_unlock instead.
*
* @brief Unlock internal mutex after accessing OT API.
*
* @param ot_context Context to unlock.
*/
void openthread_api_mutex_unlock(struct openthread_context *ot_context);
__deprecated void openthread_api_mutex_unlock(struct openthread_context *ot_context);
/** @cond INTERNAL_HIDDEN */

View file

@ -273,6 +273,13 @@ zephyr_link_libraries(${ot_libs})
endif()
# Create a library for the OpenThread Zephyr utils
zephyr_library_named(openthread_utils)
zephyr_library_sources(
openthread.c
)
zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_SHELL shell.c)
add_subdirectory(platform)
endif()

View file

@ -0,0 +1,484 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* This file implements the OpenThread module initialization and state change handling.
*
*/
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_openthread_platform, CONFIG_OPENTHREAD_PLATFORM_LOG_LEVEL);
#include <zephyr/kernel.h>
#include <zephyr/init.h>
#include <zephyr/version.h>
#include <zephyr/sys/check.h>
#include <zephyr/net/openthread.h>
#include "platform/platform-zephyr.h"
#include <openthread/child_supervision.h>
#include <openthread/cli.h>
#include <openthread/ip6.h>
#include <openthread/link.h>
#include <openthread/link_raw.h>
#include <openthread/ncp.h>
#include <openthread/message.h>
#include <openthread/platform/diag.h>
#include <openthread/tasklet.h>
#include <openthread/thread.h>
#include <openthread/dataset.h>
#include <openthread/joiner.h>
#include <openthread-system.h>
#include <utils/uart.h>
#if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
#include <openthread/nat64.h>
#endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
#define OT_STACK_SIZE (CONFIG_OPENTHREAD_THREAD_STACK_SIZE)
#if defined(CONFIG_OPENTHREAD_THREAD_PREEMPTIVE)
#define OT_PRIORITY K_PRIO_PREEMPT(CONFIG_OPENTHREAD_THREAD_PRIORITY)
#else
#define OT_PRIORITY K_PRIO_COOP(CONFIG_OPENTHREAD_THREAD_PRIORITY)
#endif
#if defined(CONFIG_OPENTHREAD_NETWORK_NAME)
#define OT_NETWORK_NAME CONFIG_OPENTHREAD_NETWORK_NAME
#else
#define OT_NETWORK_NAME ""
#endif
#if defined(CONFIG_OPENTHREAD_CHANNEL)
#define OT_CHANNEL CONFIG_OPENTHREAD_CHANNEL
#else
#define OT_CHANNEL 0
#endif
#if defined(CONFIG_OPENTHREAD_PANID)
#define OT_PANID CONFIG_OPENTHREAD_PANID
#else
#define OT_PANID 0
#endif
#if defined(CONFIG_OPENTHREAD_XPANID)
#define OT_XPANID CONFIG_OPENTHREAD_XPANID
#else
#define OT_XPANID ""
#endif
#if defined(CONFIG_OPENTHREAD_NETWORKKEY)
#define OT_NETWORKKEY CONFIG_OPENTHREAD_NETWORKKEY
#else
#define OT_NETWORKKEY ""
#endif
#if defined(CONFIG_OPENTHREAD_JOINER_PSKD)
#define OT_JOINER_PSKD CONFIG_OPENTHREAD_JOINER_PSKD
#else
#define OT_JOINER_PSKD ""
#endif
#if defined(CONFIG_OPENTHREAD_PLATFORM_INFO)
#define OT_PLATFORM_INFO CONFIG_OPENTHREAD_PLATFORM_INFO
#else
#define OT_PLATFORM_INFO ""
#endif
#if defined(CONFIG_OPENTHREAD_POLL_PERIOD)
#define OT_POLL_PERIOD CONFIG_OPENTHREAD_POLL_PERIOD
#else
#define OT_POLL_PERIOD 0
#endif
#define ZEPHYR_PACKAGE_NAME "Zephyr"
#define PACKAGE_VERSION KERNEL_VERSION_STRING
static void openthread_process(struct k_work *work);
/* Global variables to store the OpenThread module context */
static otInstance *openthread_instance;
static sys_slist_t openthread_state_change_cbs = SYS_SLIST_STATIC_INIT(openthread_state_change_cbs);
static struct k_work_q openthread_work_q;
static K_WORK_DEFINE(openthread_work, openthread_process);
static K_MUTEX_DEFINE(openthread_lock);
K_KERNEL_STACK_DEFINE(ot_stack_area, OT_STACK_SIZE);
k_tid_t openthread_thread_id_get(void)
{
return (k_tid_t)&openthread_work_q.thread;
}
static int ncp_hdlc_send(const uint8_t *buf, uint16_t len)
{
otError err = OT_ERROR_NONE;
err = otPlatUartSend(buf, len);
if (err != OT_ERROR_NONE) {
return 0;
}
return len;
}
static void openthread_process(struct k_work *work)
{
ARG_UNUSED(work);
openthread_mutex_lock();
while (otTaskletsArePending(openthread_instance)) {
otTaskletsProcess(openthread_instance);
}
otSysProcessDrivers(openthread_instance);
openthread_mutex_unlock();
}
static void ot_joiner_start_handler(otError error, void *context)
{
ARG_UNUSED(context);
if (error != OT_ERROR_NONE) {
LOG_ERR("Join failed [%d]", error);
} else {
LOG_INF("Join success");
error = otThreadSetEnabled(openthread_instance, true);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to start the OpenThread network [%d]", error);
}
}
}
static bool ot_setup_default_configuration(void)
{
otExtendedPanId xpanid = {0};
otNetworkKey networkKey = {0};
otError error = OT_ERROR_NONE;
error = otThreadSetNetworkName(openthread_instance, OT_NETWORK_NAME);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to set %s [%d]", "network name", error);
return false;
}
error = otLinkSetChannel(openthread_instance, OT_CHANNEL);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to set %s [%d]", "channel", error);
return false;
}
error = otLinkSetPanId(openthread_instance, OT_PANID);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to set %s [%d]", "PAN ID", error);
return false;
}
net_bytes_from_str(xpanid.m8, 8, (char *)OT_XPANID);
error = otThreadSetExtendedPanId(openthread_instance, &xpanid);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to set %s [%d]", "ext PAN ID", error);
return false;
}
if (strlen(OT_NETWORKKEY)) {
net_bytes_from_str(networkKey.m8, OT_NETWORK_KEY_SIZE, (char *)OT_NETWORKKEY);
error = otThreadSetNetworkKey(openthread_instance, &networkKey);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to set %s [%d]", "network key", error);
return false;
}
}
return true;
}
static void ot_state_changed_handler(uint32_t flags, void *context)
{
ARG_UNUSED(context);
struct openthread_state_changed_callback *entry, *next;
bool is_up = otIp6IsEnabled(openthread_instance);
LOG_INF("State changed! Flags: 0x%08" PRIx32 " Current role: %s Ip6: %s", flags,
otThreadDeviceRoleToString(otThreadGetDeviceRole(openthread_instance)),
(is_up ? "up" : "down"));
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&openthread_state_change_cbs, entry, next, node) {
if (entry->otCallback != NULL) {
entry->otCallback(flags, entry->user_data);
}
}
}
void otTaskletsSignalPending(otInstance *instance)
{
ARG_UNUSED(instance);
int error = k_work_submit_to_queue(&openthread_work_q, &openthread_work);
if (error < 0) {
LOG_ERR("Failed to submit work to queue, error: %d", error);
}
}
void otSysEventSignalPending(void)
{
otTaskletsSignalPending(NULL);
}
int openthread_state_changed_callback_register(struct openthread_state_changed_callback *cb)
{
CHECKIF(cb == NULL || cb->otCallback == NULL) {
return -EINVAL;
}
openthread_mutex_lock();
sys_slist_append(&openthread_state_change_cbs, &cb->node);
openthread_mutex_unlock();
return 0;
}
int openthread_state_changed_callback_unregister(struct openthread_state_changed_callback *cb)
{
bool removed = false;
CHECKIF(cb == NULL) {
return -EINVAL;
}
openthread_mutex_lock();
removed = sys_slist_find_and_remove(&openthread_state_change_cbs, &cb->node);
openthread_mutex_unlock();
if (!removed) {
return -EALREADY;
}
return 0;
}
struct otInstance *openthread_get_default_instance(void)
{
__ASSERT(openthread_instance, "OT instance is not initialized");
return openthread_instance;
}
int openthread_init(void)
{
struct k_work_queue_config q_cfg = {
.name = "openthread",
.no_yield = true,
};
otError error = OT_ERROR_NONE;
/* Prevent multiple initializations */
if (openthread_instance) {
return 0;
}
openthread_mutex_lock();
otSysInit(0, NULL);
openthread_instance = otInstanceInitSingle();
__ASSERT(openthread_instance, "OT instance initialization failed");
if (IS_ENABLED(CONFIG_OPENTHREAD_SHELL)) {
platformShellInit(openthread_instance);
}
if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
error = otPlatUartEnable();
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to enable UART: [%d]", error);
}
otNcpHdlcInit(openthread_instance, ncp_hdlc_send);
} else {
otIp6SetReceiveFilterEnabled(openthread_instance, true);
#if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
otIp4Cidr nat64_cidr;
if (otIp4CidrFromString(CONFIG_OPENTHREAD_NAT64_CIDR, &nat64_cidr) ==
OT_ERROR_NONE) {
if (otNat64SetIp4Cidr(openthread_instance, &nat64_cidr) != OT_ERROR_NONE) {
LOG_ERR("Incorrect NAT64 CIDR");
return -EIO;
}
} else {
LOG_ERR("Failed to parse NAT64 CIDR");
return -EIO;
}
#endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
error = otSetStateChangedCallback(openthread_instance, &ot_state_changed_handler,
NULL);
if (error != OT_ERROR_NONE) {
LOG_ERR("Could not set state changed callback: %d", error);
return -EIO;
}
}
openthread_mutex_unlock();
/* Start work queue for the OpenThread module */
k_work_queue_start(&openthread_work_q, ot_stack_area, K_KERNEL_STACK_SIZEOF(ot_stack_area),
OT_PRIORITY, &q_cfg);
(void)k_work_submit_to_queue(&openthread_work_q, &openthread_work);
return error == OT_ERROR_NONE ? 0 : -EIO;
}
int openthread_run(void)
{
openthread_mutex_lock();
otError error = OT_ERROR_NONE;
LOG_INF("OpenThread version: %s", otGetVersionString());
if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
LOG_DBG("OpenThread co-processor.");
goto exit;
}
error = otIp6SetEnabled(openthread_instance, true);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to set %s [%d]", "IPv6 support", error);
goto exit;
}
/* Sleepy End Device specific configuration. */
if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) {
otLinkModeConfig ot_mode = otThreadGetLinkMode(openthread_instance);
/* A SED should always attach the network as a SED to indicate
* increased buffer requirement to a parent.
*/
ot_mode.mRxOnWhenIdle = false;
error = otThreadSetLinkMode(openthread_instance, ot_mode);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to set %s [%d]", "link mode", error);
goto exit;
}
error = otLinkSetPollPeriod(openthread_instance, OT_POLL_PERIOD);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to set %s [%d]", "poll period", error);
goto exit;
}
}
/* Configure Child Supervision and MLE Child timeouts. */
otChildSupervisionSetInterval(openthread_instance,
CONFIG_OPENTHREAD_CHILD_SUPERVISION_INTERVAL);
otChildSupervisionSetCheckTimeout(openthread_instance,
CONFIG_OPENTHREAD_CHILD_SUPERVISION_CHECK_TIMEOUT);
otThreadSetChildTimeout(openthread_instance, CONFIG_OPENTHREAD_MLE_CHILD_TIMEOUT);
if (otDatasetIsCommissioned(openthread_instance)) {
/* OpenThread already has dataset stored - skip the
* configuration.
*/
LOG_DBG("OpenThread already commissioned.");
} else if (IS_ENABLED(CONFIG_OPENTHREAD_JOINER_AUTOSTART)) {
/* No dataset - initiate network join procedure. */
LOG_DBG("Starting OpenThread join procedure.");
error = otJoinerStart(openthread_instance, OT_JOINER_PSKD, NULL,
ZEPHYR_PACKAGE_NAME, OT_PLATFORM_INFO, PACKAGE_VERSION, NULL,
&ot_joiner_start_handler, NULL);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to start joiner [%d]", error);
}
goto exit;
} else {
/* No dataset - load the default configuration. */
LOG_DBG("Loading OpenThread default configuration.");
if (!ot_setup_default_configuration()) {
goto exit;
}
}
LOG_INF("Network name: %s", otThreadGetNetworkName(openthread_instance));
/* Start the network. */
error = otThreadSetEnabled(openthread_instance, true);
if (error != OT_ERROR_NONE) {
LOG_ERR("Failed to start the OpenThread network [%d]", error);
}
exit:
openthread_mutex_unlock();
return error == OT_ERROR_NONE ? 0 : -EIO;
}
int openthread_stop(void)
{
otError error = OT_ERROR_NONE;
if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
return 0;
}
openthread_mutex_lock();
error = otThreadSetEnabled(openthread_instance, false);
if (error == OT_ERROR_INVALID_STATE) {
LOG_DBG("Openthread interface was not up [%d]", error);
}
openthread_mutex_unlock();
return 0;
}
void openthread_set_receive_cb(openthread_receive_cb cb, void *context)
{
__ASSERT(cb != NULL, "Receive callback is not set");
__ASSERT(openthread_instance != NULL, "OpenThread instance is not initialized");
if (!IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
openthread_mutex_lock();
otIp6SetReceiveCallback(openthread_instance, cb, context);
#if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
otNat64SetReceiveIp4Callback(openthread_instance, cb, context);
#endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
openthread_mutex_unlock();
}
}
void openthread_mutex_lock(void)
{
(void)k_mutex_lock(&openthread_lock, K_FOREVER);
}
int openthread_mutex_try_lock(void)
{
return k_mutex_lock(&openthread_lock, K_NO_WAIT);
}
void openthread_mutex_unlock(void)
{
(void)k_mutex_unlock(&openthread_lock);
}

View file

@ -22,7 +22,6 @@ zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_BLE_TCAT ble.c)
zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_DIAG diag.c)
zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_COPROCESSOR uart.c)
zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_CRYPTO_PSA crypto_psa.c)
zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_SHELL shell.c)
zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_EXTERNAL_HEAP memory.c)
zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_PLATFORM_MESSAGE_MANAGEMENT messagepool.c)
zephyr_library_sources_ifdef(CONFIG_SETTINGS settings.c)

View file

@ -74,9 +74,9 @@ static int ot_cmd(const struct shell *sh, size_t argc, char *argv[])
shell_p = sh;
openthread_api_mutex_lock(openthread_get_default_context());
openthread_mutex_lock();
otCliInputLine(rx_buffer);
openthread_api_mutex_unlock(openthread_get_default_context());
openthread_mutex_unlock();
return 0;
}

View file

@ -19,111 +19,23 @@ LOG_MODULE_REGISTER(net_l2_openthread, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
#include <zephyr/sys/slist.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/version.h>
#include <openthread/child_supervision.h>
#include <openthread/cli.h>
#include <openthread/ip6.h>
#include <openthread/link.h>
#include <openthread/link_raw.h>
#include <openthread/ncp.h>
#include <openthread/message.h>
#include <openthread/platform/diag.h>
#include <openthread/tasklet.h>
#include <openthread/thread.h>
#include <openthread/dataset.h>
#include <openthread/joiner.h>
#include <openthread-system.h>
#include <utils/uart.h>
#include <platform-zephyr.h>
#include "openthread_utils.h"
#if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
#include <openthread/nat64.h>
#endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
static struct net_linkaddr *ll_addr;
static struct openthread_state_changed_callback ot_l2_state_changed_cb;
#define PKT_IS_IPv4(_p) ((NET_IPV6_HDR(_p)->vtc & 0xf0) == 0x40)
#define OT_STACK_SIZE (CONFIG_OPENTHREAD_THREAD_STACK_SIZE)
#if defined(CONFIG_OPENTHREAD_THREAD_PREEMPTIVE)
#define OT_PRIORITY K_PRIO_PREEMPT(CONFIG_OPENTHREAD_THREAD_PRIORITY)
#else
#define OT_PRIORITY K_PRIO_COOP(CONFIG_OPENTHREAD_THREAD_PRIORITY)
#endif
#if defined(CONFIG_OPENTHREAD_NETWORK_NAME)
#define OT_NETWORK_NAME CONFIG_OPENTHREAD_NETWORK_NAME
#else
#define OT_NETWORK_NAME ""
#endif
#if defined(CONFIG_OPENTHREAD_CHANNEL)
#define OT_CHANNEL CONFIG_OPENTHREAD_CHANNEL
#else
#define OT_CHANNEL 0
#endif
#if defined(CONFIG_OPENTHREAD_PANID)
#define OT_PANID CONFIG_OPENTHREAD_PANID
#else
#define OT_PANID 0
#endif
#if defined(CONFIG_OPENTHREAD_XPANID)
#define OT_XPANID CONFIG_OPENTHREAD_XPANID
#else
#define OT_XPANID ""
#endif
#if defined(CONFIG_OPENTHREAD_NETWORKKEY)
#define OT_NETWORKKEY CONFIG_OPENTHREAD_NETWORKKEY
#else
#define OT_NETWORKKEY ""
#endif
#if defined(CONFIG_OPENTHREAD_JOINER_PSKD)
#define OT_JOINER_PSKD CONFIG_OPENTHREAD_JOINER_PSKD
#else
#define OT_JOINER_PSKD ""
#endif
#if defined(CONFIG_OPENTHREAD_PLATFORM_INFO)
#define OT_PLATFORM_INFO CONFIG_OPENTHREAD_PLATFORM_INFO
#else
#define OT_PLATFORM_INFO ""
#endif
#if defined(CONFIG_OPENTHREAD_POLL_PERIOD)
#define OT_POLL_PERIOD CONFIG_OPENTHREAD_POLL_PERIOD
#else
#define OT_POLL_PERIOD 0
#endif
#define ZEPHYR_PACKAGE_NAME "Zephyr"
#define PACKAGE_VERSION KERNEL_VERSION_STRING
extern void platformShellInit(otInstance *aInstance);
K_KERNEL_STACK_DEFINE(ot_stack_area, OT_STACK_SIZE);
static struct net_linkaddr *ll_addr;
static otStateChangedCallback state_changed_cb;
k_tid_t openthread_thread_id_get(void)
{
struct openthread_context *ot_context = openthread_get_default_context();
return ot_context ? (k_tid_t)&ot_context->work_q.thread : 0;
}
#ifdef CONFIG_NET_MGMT_EVENT
static struct net_mgmt_event_callback ip6_addr_cb;
static void ipv6_addr_event_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event, struct net_if *iface)
static void ipv6_addr_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
struct net_if *iface)
{
if (net_if_l2(iface) != &NET_L2_GET_NAME(OPENTHREAD)) {
return;
@ -148,18 +60,6 @@ static void ipv6_addr_event_handler(struct net_mgmt_event_callback *cb,
}
#endif /* CONFIG_NET_MGMT_EVENT */
static int ncp_hdlc_send(const uint8_t *buf, uint16_t len)
{
otError err;
err = otPlatUartSend(buf, len);
if (err != OT_ERROR_NONE) {
return 0;
}
return len;
}
#ifndef CONFIG_HDLC_RCP_IF
void otPlatRadioGetIeeeEui64(otInstance *instance, uint8_t *ieee_eui64)
{
@ -169,30 +69,10 @@ void otPlatRadioGetIeeeEui64(otInstance *instance, uint8_t *ieee_eui64)
}
#endif /* CONFIG_HDLC_RCP_IF */
void otTaskletsSignalPending(otInstance *instance)
static void ot_l2_state_changed_handler(uint32_t flags, void *context)
{
struct openthread_context *ot_context = openthread_get_default_context();
if (ot_context) {
k_work_submit_to_queue(&ot_context->work_q, &ot_context->api_work);
}
}
void otSysEventSignalPending(void)
{
otTaskletsSignalPending(NULL);
}
static void ot_state_changed_handler(uint32_t flags, void *context)
{
struct openthread_state_changed_cb *entry, *next;
struct openthread_context *ot_context = context;
bool is_up = otIp6IsEnabled(ot_context->instance);
NET_INFO("State changed! Flags: 0x%08" PRIx32 " Current role: %s Ip6: %s",
flags,
otThreadDeviceRoleToString(otThreadGetDeviceRole(ot_context->instance)),
(is_up ? "up" : "down"));
struct openthread_state_changed_cb *entry, *next;
#if defined(CONFIG_OPENTHREAD_INTERFACE_EARLY_UP)
if (is_up) {
@ -202,7 +82,7 @@ static void ot_state_changed_handler(uint32_t flags, void *context)
}
#else
if (flags & OT_CHANGED_THREAD_ROLE) {
switch (otThreadGetDeviceRole(ot_context->instance)) {
switch (otThreadGetDeviceRole(openthread_get_default_instance())) {
case OT_DEVICE_ROLE_CHILD:
case OT_DEVICE_ROLE_ROUTER:
case OT_DEVICE_ROLE_LEADER:
@ -219,38 +99,34 @@ static void ot_state_changed_handler(uint32_t flags, void *context)
#endif
if (flags & OT_CHANGED_IP6_ADDRESS_REMOVED) {
NET_DBG("Ipv6 address removed");
rm_ipv6_addr_from_zephyr(ot_context);
NET_DBG("Ipv6 address removed");
}
if (flags & OT_CHANGED_IP6_ADDRESS_ADDED) {
NET_DBG("Ipv6 address added");
add_ipv6_addr_to_zephyr(ot_context);
NET_DBG("Ipv6 address added");
}
if (flags & OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED) {
NET_DBG("Ipv6 multicast address removed");
rm_ipv6_maddr_from_zephyr(ot_context);
NET_DBG("Ipv6 multicast address removed");
}
if (flags & OT_CHANGED_IP6_MULTICAST_SUBSCRIBED) {
NET_DBG("Ipv6 multicast address added");
add_ipv6_maddr_to_zephyr(ot_context);
NET_DBG("Ipv6 multicast address added");
}
#if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
if (flags & OT_CHANGED_NAT64_TRANSLATOR_STATE) {
NET_DBG("Nat64 translator state changed to %x",
otNat64GetTranslatorState(ot_context->instance));
otNat64GetTranslatorState(openthread_get_default_instance()));
}
#endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
if (state_changed_cb) {
state_changed_cb(flags, context);
}
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ot_context->state_change_cbs, entry, next, node) {
if (entry->state_changed_cb != NULL) {
entry->state_changed_cb(flags, ot_context, entry->user_data);
@ -258,7 +134,7 @@ static void ot_state_changed_handler(uint32_t flags, void *context)
}
}
static void ot_receive_handler(otMessage *aMessage, void *context)
static void ot_receive_handler(otMessage *message, void *context)
{
struct openthread_context *ot_context = context;
@ -267,8 +143,7 @@ static void ot_receive_handler(otMessage *aMessage, void *context)
struct net_pkt *pkt;
struct net_buf *pkt_buf;
pkt = net_pkt_rx_alloc_with_buffer(ot_context->iface,
otMessageGetLength(aMessage),
pkt = net_pkt_rx_alloc_with_buffer(ot_context->iface, otMessageGetLength(message),
AF_UNSPEC, 0, K_NO_WAIT);
if (!pkt) {
NET_ERR("Failed to reserve net pkt");
@ -278,8 +153,7 @@ static void ot_receive_handler(otMessage *aMessage, void *context)
pkt_buf = pkt->buffer;
while (1) {
read_len = otMessageRead(aMessage, offset, pkt_buf->data,
net_buf_tailroom(pkt_buf));
read_len = otMessageRead(message, offset, pkt_buf->data, net_buf_tailroom(pkt_buf));
if (!read_len) {
break;
}
@ -328,42 +202,7 @@ out:
net_pkt_unref(pkt);
}
otMessageFree(aMessage);
}
static void ot_joiner_start_handler(otError error, void *context)
{
struct openthread_context *ot_context = context;
switch (error) {
case OT_ERROR_NONE:
NET_INFO("Join success");
error = otThreadSetEnabled(ot_context->instance, true);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to start the OpenThread network [%d]", error);
}
break;
default:
NET_ERR("Join failed [%d]", error);
break;
}
}
static void openthread_process(struct k_work *work)
{
struct openthread_context *ot_context
= CONTAINER_OF(work, struct openthread_context, api_work);
openthread_api_mutex_lock(ot_context);
while (otTaskletsArePending(ot_context->instance)) {
otTaskletsProcess(ot_context->instance);
}
otSysProcessDrivers(ot_context->instance);
openthread_api_mutex_unlock(ot_context);
otMessageFree(message);
}
static bool is_ipv6_frag(struct net_pkt *pkt)
@ -429,248 +268,55 @@ int openthread_send(struct net_if *iface, struct net_pkt *pkt)
return len;
}
int openthread_start(struct openthread_context *ot_context)
static int openthread_l2_init(struct net_if *iface)
{
otInstance *ot_instance = ot_context->instance;
otError error = OT_ERROR_NONE;
struct openthread_context *ot_l2_context = net_if_l2_data(iface);
int error = 0;
openthread_api_mutex_lock(ot_context);
NET_INFO("OpenThread version: %s", otGetVersionString());
if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
NET_DBG("OpenThread co-processor.");
goto exit;
}
error = otIp6SetEnabled(ot_context->instance, true);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to set %s [%d]", "IPv6 support", error);
goto exit;
}
/* Sleepy End Device specific configuration. */
if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) {
otLinkModeConfig ot_mode = otThreadGetLinkMode(ot_instance);
/* A SED should always attach the network as a SED to indicate
* increased buffer requirement to a parent.
*/
ot_mode.mRxOnWhenIdle = false;
error = otThreadSetLinkMode(ot_context->instance, ot_mode);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to set %s [%d]", "link mode", error);
goto exit;
}
error = otLinkSetPollPeriod(ot_context->instance, OT_POLL_PERIOD);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to set %s [%d]", "poll period", error);
goto exit;
}
}
/* Configure Child Supervision and MLE Child timeouts. */
otChildSupervisionSetInterval(ot_context->instance,
CONFIG_OPENTHREAD_CHILD_SUPERVISION_INTERVAL);
otChildSupervisionSetCheckTimeout(ot_context->instance,
CONFIG_OPENTHREAD_CHILD_SUPERVISION_CHECK_TIMEOUT);
otThreadSetChildTimeout(ot_context->instance, CONFIG_OPENTHREAD_MLE_CHILD_TIMEOUT);
if (otDatasetIsCommissioned(ot_instance)) {
/* OpenThread already has dataset stored - skip the
* configuration.
*/
NET_DBG("OpenThread already commissioned.");
} else if (IS_ENABLED(CONFIG_OPENTHREAD_JOINER_AUTOSTART)) {
/* No dataset - initiate network join procedure. */
NET_DBG("Starting OpenThread join procedure.");
error = otJoinerStart(ot_instance, OT_JOINER_PSKD, NULL, ZEPHYR_PACKAGE_NAME,
OT_PLATFORM_INFO, PACKAGE_VERSION, NULL,
&ot_joiner_start_handler, ot_context);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to start joiner [%d]", error);
}
goto exit;
} else {
/* No dataset - load the default configuration. */
NET_DBG("Loading OpenThread default configuration.");
otExtendedPanId xpanid;
otNetworkKey networkKey;
error = otThreadSetNetworkName(ot_instance, OT_NETWORK_NAME);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to set %s [%d]", "network name", error);
goto exit;
}
error = otLinkSetChannel(ot_instance, OT_CHANNEL);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to set %s [%d]", "channel", error);
goto exit;
}
error = otLinkSetPanId(ot_instance, OT_PANID);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to set %s [%d]", "PAN ID", error);
goto exit;
}
net_bytes_from_str(xpanid.m8, 8, (char *)OT_XPANID);
error = otThreadSetExtendedPanId(ot_instance, &xpanid);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to set %s [%d]", "ext PAN ID", error);
goto exit;
}
if (strlen(OT_NETWORKKEY)) {
net_bytes_from_str(networkKey.m8, OT_NETWORK_KEY_SIZE,
(char *)OT_NETWORKKEY);
error = otThreadSetNetworkKey(ot_instance, &networkKey);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to set %s [%d]", "network key", error);
goto exit;
}
}
}
NET_INFO("Network name: %s",
otThreadGetNetworkName(ot_instance));
/* Start the network. */
error = otThreadSetEnabled(ot_instance, true);
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to start the OpenThread network [%d]", error);
}
exit:
openthread_api_mutex_unlock(ot_context);
return error == OT_ERROR_NONE ? 0 : -EIO;
}
int openthread_stop(struct openthread_context *ot_context)
{
otError error;
if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
return 0;
}
openthread_api_mutex_lock(ot_context);
error = otThreadSetEnabled(ot_context->instance, false);
if (error == OT_ERROR_INVALID_STATE) {
NET_DBG("Openthread interface was not up [%d]", error);
}
openthread_api_mutex_unlock(ot_context);
return 0;
}
static int openthread_init(struct net_if *iface)
{
struct openthread_context *ot_context = net_if_l2_data(iface);
struct k_work_queue_config q_cfg = {
.name = "openthread",
.no_yield = true,
};
otError err = OT_ERROR_NONE;
NET_DBG("openthread_init");
k_mutex_init(&ot_context->api_lock);
k_work_init(&ot_context->api_work, openthread_process);
ot_l2_state_changed_cb.otCallback = ot_l2_state_changed_handler;
ot_l2_state_changed_cb.user_data = (void *)ot_l2_context;
ll_addr = net_if_get_link_addr(iface);
openthread_api_mutex_lock(ot_context);
otSysInit(0, NULL);
ot_context->instance = otInstanceInitSingle();
ot_context->iface = iface;
__ASSERT(ot_context->instance, "OT instance is NULL");
if (IS_ENABLED(CONFIG_OPENTHREAD_SHELL)) {
platformShellInit(ot_context->instance);
error = openthread_init();
if (error) {
return error;
}
if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
err = otPlatUartEnable();
if (err != OT_ERROR_NONE) {
NET_ERR("Failed to enable UART: [%d]", err);
}
ot_l2_context->iface = iface;
otNcpHdlcInit(ot_context->instance, ncp_hdlc_send);
} else {
otIp6SetReceiveFilterEnabled(ot_context->instance, true);
otIp6SetReceiveCallback(ot_context->instance,
ot_receive_handler, ot_context);
#if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
otIp4Cidr nat64_cidr;
if (otIp4CidrFromString(CONFIG_OPENTHREAD_NAT64_CIDR, &nat64_cidr) ==
OT_ERROR_NONE) {
if (otNat64SetIp4Cidr(openthread_get_default_instance(), &nat64_cidr) !=
OT_ERROR_NONE) {
NET_ERR("Incorrect NAT64 CIDR");
}
} else {
NET_ERR("Failed to parse NAT64 CIDR");
}
otNat64SetReceiveIp4Callback(ot_context->instance, ot_receive_handler, ot_context);
#endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
sys_slist_init(&ot_context->state_change_cbs);
err = otSetStateChangedCallback(ot_context->instance,
&ot_state_changed_handler,
ot_context);
if (err != OT_ERROR_NONE) {
NET_ERR("Could not set state changed callback: %d", err);
}
net_mgmt_init_event_callback(
&ip6_addr_cb, ipv6_addr_event_handler,
NET_EVENT_IPV6_ADDR_ADD | NET_EVENT_IPV6_MADDR_ADD);
if (!IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
net_mgmt_init_event_callback(&ip6_addr_cb, ipv6_addr_event_handler,
NET_EVENT_IPV6_ADDR_ADD | NET_EVENT_IPV6_MADDR_ADD);
net_mgmt_add_event_callback(&ip6_addr_cb);
net_if_dormant_on(iface);
openthread_set_receive_cb(ot_receive_handler, (void *)ot_l2_context);
/* To keep backward compatibility use the additional state change callback list from
* the ot l2 context and register the callback to the openthread module.
*/
sys_slist_init(&ot_l2_context->state_change_cbs);
openthread_state_changed_callback_register(&ot_l2_state_changed_cb);
}
openthread_api_mutex_unlock(ot_context);
k_work_queue_start(&ot_context->work_q, ot_stack_area,
K_KERNEL_STACK_SIZEOF(ot_stack_area),
OT_PRIORITY, &q_cfg);
(void)k_work_submit_to_queue(&ot_context->work_q, &ot_context->api_work);
return (err == OT_ERROR_NONE) ? 0 : -EIO;
return error;
}
void ieee802154_init(struct net_if *iface)
{
if (IS_ENABLED(CONFIG_IEEE802154_NET_IF_NO_AUTO_START)) {
LOG_DBG("Interface auto start disabled.");
net_if_flag_set(iface, NET_IF_NO_AUTO_START);
}
net_if_flag_set(iface, NET_IF_IPV6_NO_ND);
net_if_flag_set(iface, NET_IF_IPV6_NO_MLD);
openthread_init(iface);
int error = openthread_l2_init(iface);
if (error) {
NET_ERR("Failed to initialize OpenThread L2");
}
}
static enum net_l2_flags openthread_flags(struct net_if *iface)
@ -683,20 +329,17 @@ static enum net_l2_flags openthread_flags(struct net_if *iface)
static int openthread_enable(struct net_if *iface, bool state)
{
struct openthread_context *ot_context = net_if_l2_data(iface);
NET_DBG("iface %p %s", iface, state ? "up" : "down");
LOG_DBG("iface %p %s", iface, state ? "up" : "down");
if (state) {
if (IS_ENABLED(CONFIG_OPENTHREAD_MANUAL_START)) {
NET_DBG("OpenThread manual start.");
return 0;
}
return openthread_start(ot_context);
return openthread_run();
}
return openthread_stop(ot_context);
return openthread_stop();
}
struct openthread_context *openthread_get_default_context(void)
@ -720,14 +363,44 @@ exit:
return ot_context;
}
struct otInstance *openthread_get_default_instance(void)
/* Keep deprecated functions and forward them to the OpenThread platform module */
int openthread_start(struct openthread_context *ot_context)
{
struct openthread_context *ot_context =
openthread_get_default_context();
ARG_UNUSED(ot_context);
return ot_context ? ot_context->instance : NULL;
return openthread_run();
}
void openthread_api_mutex_lock(struct openthread_context *ot_context)
{
/* The mutex is managed internally by the OpenThread module */
ARG_UNUSED(ot_context);
openthread_mutex_lock();
}
int openthread_api_mutex_try_lock(struct openthread_context *ot_context)
{
/* The mutex is managed internally by the OpenThread module */
ARG_UNUSED(ot_context);
return openthread_mutex_try_lock();
}
void openthread_api_mutex_unlock(struct openthread_context *ot_context)
{
/* The mutex is managed internally by the OpenThread module */
ARG_UNUSED(ot_context);
openthread_mutex_unlock();
}
/* Keep deprecated state change callback registration functions to keep backward compatibility.
* The callbacks that are registered using these functions are run by the OpenThread module
* as one of the platform callback. However, they will be not supported in the future after
* deprecation period, so it is recommended to switch to
* openthread_state_change_callback_register() instead.
*/
int openthread_state_changed_cb_register(struct openthread_context *ot_context,
struct openthread_state_changed_cb *cb)
{
@ -735,9 +408,9 @@ int openthread_state_changed_cb_register(struct openthread_context *ot_context,
return -EINVAL;
}
openthread_api_mutex_lock(ot_context);
openthread_mutex_lock();
sys_slist_append(&ot_context->state_change_cbs, &cb->node);
openthread_api_mutex_unlock(ot_context);
openthread_mutex_unlock();
return 0;
}
@ -751,9 +424,9 @@ int openthread_state_changed_cb_unregister(struct openthread_context *ot_context
return -EINVAL;
}
openthread_api_mutex_lock(ot_context);
openthread_mutex_lock();
removed = sys_slist_find_and_remove(&ot_context->state_change_cbs, &cb->node);
openthread_api_mutex_unlock(ot_context);
openthread_mutex_unlock();
if (!removed) {
return -EALREADY;
@ -762,25 +435,4 @@ int openthread_state_changed_cb_unregister(struct openthread_context *ot_context
return 0;
}
void openthread_set_state_changed_cb(otStateChangedCallback cb)
{
state_changed_cb = cb;
}
void openthread_api_mutex_lock(struct openthread_context *ot_context)
{
(void)k_mutex_lock(&ot_context->api_lock, K_FOREVER);
}
int openthread_api_mutex_try_lock(struct openthread_context *ot_context)
{
return k_mutex_lock(&ot_context->api_lock, K_NO_WAIT);
}
void openthread_api_mutex_unlock(struct openthread_context *ot_context)
{
(void)k_mutex_unlock(&ot_context->api_lock);
}
NET_L2_INIT(OPENTHREAD_L2, openthread_recv, openthread_send, openthread_enable,
openthread_flags);
NET_L2_INIT(OPENTHREAD_L2, openthread_recv, openthread_send, openthread_enable, openthread_flags);

View file

@ -31,7 +31,7 @@ static bool is_mesh_local(struct openthread_context *context,
const uint8_t *address)
{
const otMeshLocalPrefix *ml_prefix =
otThreadGetMeshLocalPrefix(context->instance);
otThreadGetMeshLocalPrefix(openthread_get_default_instance());
return (memcmp(address, ml_prefix->m8, sizeof(ml_prefix->m8)) == 0);
}
@ -106,7 +106,7 @@ void add_ipv6_addr_to_zephyr(struct openthread_context *context)
const otNetifAddress *address;
struct net_if_addr *if_addr;
for (address = otIp6GetUnicastAddresses(context->instance);
for (address = otIp6GetUnicastAddresses(openthread_get_default_instance());
address; address = address->mNext) {
if (address->mRloc || is_anycast_locator(address)) {
@ -215,9 +215,9 @@ void add_ipv6_addr_to_ot(struct openthread_context *context,
return;
}
openthread_api_mutex_lock(context);
error = otIp6AddUnicastAddress(context->instance, &addr);
openthread_api_mutex_unlock(context);
openthread_mutex_lock();
error = otIp6AddUnicastAddress(openthread_get_default_instance(), &addr);
openthread_mutex_unlock();
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to add IPv6 unicast address %s [%d]",
@ -235,9 +235,9 @@ void add_ipv6_maddr_to_ot(struct openthread_context *context,
memcpy(&addr, addr6, sizeof(addr));
openthread_api_mutex_lock(context);
error = otIp6SubscribeMulticastAddress(context->instance, &addr);
openthread_api_mutex_unlock(context);
openthread_mutex_lock();
error = otIp6SubscribeMulticastAddress(openthread_get_default_instance(), &addr);
openthread_mutex_unlock();
if (error != OT_ERROR_NONE) {
NET_ERR("Failed to add IPv6 multicast address %s [%d]",
@ -252,7 +252,7 @@ void add_ipv6_maddr_to_zephyr(struct openthread_context *context)
const otNetifMulticastAddress *maddress;
struct net_if_mcast_addr *zmaddr;
for (maddress = otIp6GetMulticastAddresses(context->instance);
for (maddress = otIp6GetMulticastAddresses(openthread_get_default_instance());
maddress; maddress = maddress->mNext) {
if (net_if_ipv6_maddr_lookup(
(struct in6_addr *)(&maddress->mAddress),
@ -306,7 +306,7 @@ void rm_ipv6_addr_from_zephyr(struct openthread_context *context)
continue;
}
for (address = otIp6GetUnicastAddresses(context->instance);
for (address = otIp6GetUnicastAddresses(openthread_get_default_instance());
address; address = address->mNext) {
ot_addr = (struct in6_addr *)(&address->mAddress);
@ -354,7 +354,7 @@ void rm_ipv6_maddr_from_zephyr(struct openthread_context *context)
continue;
}
for (maddress = otIp6GetMulticastAddresses(context->instance);
for (maddress = otIp6GetMulticastAddresses(openthread_get_default_instance());
maddress; maddress = maddress->mNext) {
ot_addr = (struct in6_addr *)(&maddress->mAddress);