1 /*
2  * Copyright (c) 2025 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_MODULES_OPENTHREAD_OPENTHREAD_H_
8 #define ZEPHYR_MODULES_OPENTHREAD_OPENTHREAD_H_
9 
10 #include <zephyr/kernel.h>
11 
12 #include <openthread/instance.h>
13 #include <openthread/message.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /**
20  * @brief The common callback type for receiving IPv4 (translated by NAT64) and IPv6 datagrams.
21  *
22  * This callback is called when a datagram is received.
23  *
24  * @param message The message to receive.
25  * @param context The context to pass to the callback.
26  */
27 typedef void (*openthread_receive_cb)(struct otMessage *message, void *context);
28 
29 /** OpenThread state change callback  */
30 
31 /**
32  * @brief OpenThread state change callback structure
33  *
34  * Used to register a callback in the callback list. As many
35  * callbacks as needed can be added as long as each of them
36  * are unique pointers of struct openthread_state_changed_callback.
37  *
38  * @note You may destroy the object only after it is unregistered from the callback list.
39  */
40 struct openthread_state_changed_callback {
41 	/**
42 	 * @brief Callback for notifying configuration or state changes.
43 	 *
44 	 * @param otCallback OpenThread callback to register.
45 	 * See https://openthread.io/reference/group/api-instance#otstatechangedcallback for
46 	 * details.
47 	 */
48 	otStateChangedCallback otCallback;
49 
50 	/** User data if required */
51 	void *user_data;
52 
53 	/**
54 	 * Internally used field for list handling
55 	 *  - user must not directly modify
56 	 */
57 	sys_snode_t node;
58 };
59 
60 /**
61  * @brief Register callbacks that will be called when a certain configuration
62  * or state changes occur within OpenThread.
63  *
64  * @param cb Callback struct to register.
65  */
66 int openthread_state_changed_callback_register(struct openthread_state_changed_callback *cb);
67 
68 /**
69  * @brief Unregister OpenThread configuration or state changed callbacks.
70  *
71  * @param cb Callback struct to unregister.
72  */
73 int openthread_state_changed_callback_unregister(struct openthread_state_changed_callback *cb);
74 
75 /**
76  * @brief Get OpenThread thread identification.
77  */
78 k_tid_t openthread_thread_id_get(void);
79 
80 /**
81  * @brief Get pointer to default OpenThread instance.
82  *
83  * @retval !NULL On success.
84  * @retval NULL  On failure.
85  */
86 struct otInstance *openthread_get_default_instance(void);
87 
88 /**
89  * @brief Initialize the OpenThread module.
90  *
91  * This function:
92  * - Initializes the OpenThread module.
93  * - Creates an OpenThread single instance.
94  * - Starts the shell.
95  * - Enables the UART and NCP HDLC for coprocessor purposes.
96  * - Initializes the NAT64 translator.
97  * - Creates a work queue for the OpenThread module.
98  *
99  * @note This function is automatically called by Zephyr's networking layer.
100  * If you want to initialize the OpenThread independently, call this function
101  * in your application init code.
102  *
103  * @retval 0 On success.
104  * @retval -EIO On failure.
105  */
106 int openthread_init(void);
107 
108 /**
109  * @brief Run the OpenThread network.
110  *
111  * @details Prepares the OpenThread network and enables it.
112  * Depends on active settings: it uses the stored network configuration,
113  * starts the joining procedure or uses the default network configuration.
114  * Additionally, when the device is MTD, it sets the SED mode to properly
115  * attach the network.
116  */
117 int openthread_run(void);
118 
119 /**
120  * @brief Disable the OpenThread network.
121  */
122 int openthread_stop(void);
123 
124 /**
125  * @brief Set the additional callback for receiving packets.
126  *
127  * @details This callback is called once a packet is received and can be
128  * used to inject packets into the Zephyr networking stack.
129  * Setting this callback is optional.
130  *
131  * @param cb Callback to set.
132  * @param context Context to pass to the callback.
133  */
134 void openthread_set_receive_cb(openthread_receive_cb cb, void *context);
135 
136 #if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR) || defined(__DOXYGEN__)
137 /**
138  * @brief Set the additional callback for receiving NAT64 translated packets.
139  *
140  * @details This callback is called once a packet from OpenThread NAT64 translator
141  * is received and can be used to inject packets into the Zephyr networking stack.
142  * Setting this callback is optional.
143  *
144  * @kconfig_dep{CONFIG_OPENTHREAD_NAT64_TRANSLATOR}
145  *
146  * @param cb Callback to set.
147  * @param context Context to pass to the callback.
148  */
149 void openthread_set_nat64_receive_cb(openthread_receive_cb cb, void *context);
150 #endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
151 
152 /**
153  * @brief Lock internal mutex before accessing OpenThread API.
154  *
155  * @details OpenThread API is not thread-safe. Therefore, before accessing any
156  * API function, you need to lock the internal mutex, to prevent the
157  * OpenThread thread from pre-empting the API call.
158  */
159 void openthread_mutex_lock(void);
160 
161 /**
162  * @brief Try to lock internal mutex before accessing OpenThread API.
163  *
164  * @details This function behaves like openthread_mutex_lock(), provided that
165  * the internal mutex is unlocked. Otherwise, it returns a negative value without
166  * waiting.
167  */
168 int openthread_mutex_try_lock(void);
169 
170 /**
171  * @brief Unlock internal mutex after accessing OpenThread API.
172  */
173 void openthread_mutex_unlock(void);
174 
175 #if defined(CONFIG_OPENTHREAD_ZEPHYR_BORDER_ROUTER)
176 /**
177  * @brief Notify OpenThread task about Border Router pending work.
178  */
179 void openthread_notify_border_router_work(void);
180 #endif /* CONFIG_OPENTHREAD_ZEPHYR_BORDER_ROUTER */
181 
182 #ifdef __cplusplus
183 }
184 #endif
185 
186 #endif /* ZEPHYR_MODULES_OPENTHREAD_OPENTHREAD_H_ */
187