1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  *   This file implements the OpenThread platform abstraction
10  *   for radio communication.
11  *
12  */
13 
14 #include <openthread/error.h>
15 #define LOG_MODULE_NAME net_otPlat_radio
16 
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_PLATFORM_LOG_LEVEL);
19 
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 #include <string.h>
24 
25 #include <zephyr/kernel.h>
26 #include <zephyr/device.h>
27 #include <zephyr/net/ieee802154_radio.h>
28 #include <zephyr/net/net_pkt.h>
29 #include <zephyr/net/net_time.h>
30 #include <zephyr/sys/__assert.h>
31 
32 #include <openthread/ip6.h>
33 #include <openthread-system.h>
34 #include <openthread/instance.h>
35 #include <openthread/platform/radio.h>
36 #include <openthread/platform/diag.h>
37 #include <openthread/platform/time.h>
38 #include <openthread/message.h>
39 
40 #include "platform-zephyr.h"
41 
42 #if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
43 #include <openthread/nat64.h>
44 #endif
45 
46 #define PKT_IS_IPv6(_p) ((NET_IPV6_HDR(_p)->vtc & 0xf0) == 0x60)
47 
48 #define SHORT_ADDRESS_SIZE 2
49 
50 #define FCS_SIZE     2
51 #if defined(CONFIG_OPENTHREAD_THREAD_VERSION_1_1)
52 #define ACK_PKT_LENGTH 5
53 #else
54 #define ACK_PKT_LENGTH 127
55 #endif
56 
57 #define FRAME_TYPE_MASK 0x07
58 #define FRAME_TYPE_ACK 0x02
59 
60 #if defined(CONFIG_NET_TC_THREAD_COOPERATIVE)
61 #define OT_WORKER_PRIORITY K_PRIO_COOP(CONFIG_OPENTHREAD_RADIO_WORKQUEUE_PRIORITY)
62 #else
63 #define OT_WORKER_PRIORITY K_PRIO_PREEMPT(CONFIG_OPENTHREAD_RADIO_WORKQUEUE_PRIORITY)
64 #endif
65 
66 #define CHANNEL_COUNT OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN + 1
67 
68 /* PHY header duration in us (i.e. 2 symbol periods @ 62.5k symbol rate), see
69  * IEEE 802.15.4, sections 12.1.3.1, 12.2.5 and 12.3.3.
70  */
71 #define PHR_DURATION_US 32U
72 
73 enum pending_events {
74 	PENDING_EVENT_FRAME_TO_SEND, /* There is a tx frame to send  */
75 	PENDING_EVENT_FRAME_RECEIVED, /* Radio has received new frame */
76 	PENDING_EVENT_RX_FAILED, /* The RX failed */
77 	PENDING_EVENT_TX_STARTED, /* Radio has started transmitting */
78 	PENDING_EVENT_TX_DONE, /* Radio transmission finished */
79 	PENDING_EVENT_DETECT_ENERGY, /* Requested to start Energy Detection procedure */
80 	PENDING_EVENT_DETECT_ENERGY_DONE, /* Energy Detection finished */
81 	PENDING_EVENT_SLEEP, /* Sleep if idle */
82 	PENDING_EVENT_COUNT /* Keep last */
83 };
84 
85 K_SEM_DEFINE(radio_sem, 0, 1);
86 
87 static otRadioState sState = OT_RADIO_STATE_DISABLED;
88 
89 static otRadioFrame sTransmitFrame;
90 static otRadioFrame ack_frame;
91 static uint8_t ack_psdu[ACK_PKT_LENGTH];
92 
93 #if defined(CONFIG_OPENTHREAD_TIME_SYNC)
94 static otRadioIeInfo tx_ie_info;
95 #endif
96 
97 static struct net_pkt *tx_pkt;
98 static struct net_buf *tx_payload;
99 
100 static const struct device *const radio_dev =
101 	DEVICE_DT_GET(DT_CHOSEN(zephyr_ieee802154));
102 static struct ieee802154_radio_api *radio_api;
103 
104 /* Get the default tx output power from Kconfig */
105 static int8_t tx_power = CONFIG_OPENTHREAD_DEFAULT_TX_POWER;
106 static uint16_t channel;
107 static bool promiscuous;
108 
109 static uint16_t energy_detection_time;
110 static uint8_t energy_detection_channel;
111 static int16_t energy_detected_value;
112 
113 static int8_t max_tx_power_table[CHANNEL_COUNT];
114 
115 ATOMIC_DEFINE(pending_events, PENDING_EVENT_COUNT);
116 K_KERNEL_STACK_DEFINE(ot_task_stack,
117 		      CONFIG_OPENTHREAD_RADIO_WORKQUEUE_STACK_SIZE);
118 static struct k_work_q ot_work_q;
119 static otError rx_result;
120 static otError tx_result;
121 
122 K_FIFO_DEFINE(rx_pkt_fifo);
123 K_FIFO_DEFINE(tx_pkt_fifo);
124 
get_transmit_power_for_channel(uint8_t aChannel)125 static int8_t get_transmit_power_for_channel(uint8_t aChannel)
126 {
127 	int8_t channel_max_power = OT_RADIO_POWER_INVALID;
128 	int8_t power = 0; /* 0 dbm as default value */
129 
130 	if (aChannel >= OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN &&
131 	    aChannel <= OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX) {
132 		channel_max_power =
133 			max_tx_power_table[aChannel - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN];
134 	}
135 
136 	if (tx_power != OT_RADIO_POWER_INVALID) {
137 		power = (channel_max_power < tx_power) ? channel_max_power : tx_power;
138 	} else if (channel_max_power != OT_RADIO_POWER_INVALID) {
139 		power = channel_max_power;
140 	}
141 
142 	return power;
143 }
144 
is_pending_event_set(enum pending_events event)145 static inline bool is_pending_event_set(enum pending_events event)
146 {
147 	return atomic_test_bit(pending_events, event);
148 }
149 
set_pending_event(enum pending_events event)150 static void set_pending_event(enum pending_events event)
151 {
152 	atomic_set_bit(pending_events, event);
153 	otSysEventSignalPending();
154 }
155 
reset_pending_event(enum pending_events event)156 static void reset_pending_event(enum pending_events event)
157 {
158 	atomic_clear_bit(pending_events, event);
159 }
160 
energy_detected(const struct device * dev,int16_t max_ed)161 void energy_detected(const struct device *dev, int16_t max_ed)
162 {
163 	if (dev == radio_dev) {
164 		energy_detected_value = max_ed;
165 		set_pending_event(PENDING_EVENT_DETECT_ENERGY_DONE);
166 	}
167 }
168 
ieee802154_handle_ack(struct net_if * iface,struct net_pkt * pkt)169 enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt)
170 {
171 	ARG_UNUSED(iface);
172 
173 	size_t ack_len = net_pkt_get_len(pkt);
174 
175 	if (ack_len > ACK_PKT_LENGTH) {
176 		return NET_CONTINUE;
177 	}
178 
179 	if ((*net_pkt_data(pkt) & FRAME_TYPE_MASK) != FRAME_TYPE_ACK) {
180 		return NET_CONTINUE;
181 	}
182 
183 	if (ack_frame.mLength != 0) {
184 		LOG_ERR("Overwriting unhandled ACK frame.");
185 	}
186 
187 	if (net_pkt_read(pkt, ack_psdu, ack_len) < 0) {
188 		LOG_ERR("Failed to read ACK frame.");
189 		return NET_CONTINUE;
190 	}
191 
192 	ack_frame.mPsdu = ack_psdu;
193 	ack_frame.mLength = ack_len;
194 	ack_frame.mInfo.mRxInfo.mLqi = net_pkt_ieee802154_lqi(pkt);
195 	ack_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi_dbm(pkt);
196 
197 #if defined(CONFIG_NET_PKT_TIMESTAMP)
198 	ack_frame.mInfo.mRxInfo.mTimestamp = net_pkt_timestamp_ns(pkt) / NSEC_PER_USEC;
199 #endif
200 
201 	return NET_OK;
202 }
203 
handle_radio_event(const struct device * dev,enum ieee802154_event evt,void * event_params)204 void handle_radio_event(const struct device *dev, enum ieee802154_event evt,
205 			void *event_params)
206 {
207 	ARG_UNUSED(event_params);
208 
209 	switch (evt) {
210 	case IEEE802154_EVENT_TX_STARTED:
211 		if (sState == OT_RADIO_STATE_TRANSMIT) {
212 			set_pending_event(PENDING_EVENT_TX_STARTED);
213 		}
214 		break;
215 	case IEEE802154_EVENT_RX_FAILED:
216 		if (sState == OT_RADIO_STATE_RECEIVE) {
217 			switch (*(enum ieee802154_rx_fail_reason *) event_params) {
218 			case IEEE802154_RX_FAIL_NOT_RECEIVED:
219 				rx_result = OT_ERROR_NO_FRAME_RECEIVED;
220 				break;
221 
222 			case IEEE802154_RX_FAIL_INVALID_FCS:
223 				rx_result = OT_ERROR_FCS;
224 				break;
225 
226 			case IEEE802154_RX_FAIL_ADDR_FILTERED:
227 				rx_result = OT_ERROR_DESTINATION_ADDRESS_FILTERED;
228 				break;
229 
230 			case IEEE802154_RX_FAIL_OTHER:
231 			default:
232 				rx_result = OT_ERROR_FAILED;
233 				break;
234 			}
235 			set_pending_event(PENDING_EVENT_RX_FAILED);
236 		}
237 		break;
238 	case IEEE802154_EVENT_RX_OFF:
239 		set_pending_event(PENDING_EVENT_SLEEP);
240 		break;
241 	default:
242 		/* do nothing - ignore event */
243 		break;
244 	}
245 }
246 
247 #if defined(CONFIG_OPENTHREAD_PLATFORM_PKT_TXTIME) || defined(CONFIG_OPENTHREAD_CSL_RECEIVER)
248 /**
249  * @brief Convert 32-bit (potentially wrapped) OpenThread microsecond timestamps
250  * to 64-bit Zephyr network subsystem nanosecond timestamps.
251  *
252  * This is a workaround until OpenThread is able to schedule 64-bit RX/TX time.
253  *
254  * @param target_time_ns_wrapped time in nanoseconds referred to the radio clock
255  * modulo UINT32_MAX.
256  *
257  * @return 64-bit nanosecond timestamp
258  */
convert_32bit_us_wrapped_to_64bit_ns(uint32_t target_time_us_wrapped)259 static net_time_t convert_32bit_us_wrapped_to_64bit_ns(uint32_t target_time_us_wrapped)
260 {
261 	/**
262 	 * OpenThread provides target time as a (potentially wrapped) 32-bit
263 	 * integer defining a moment in time in the microsecond domain.
264 	 *
265 	 * The target time can point to a moment in the future, but can be
266 	 * overdue as well. In order to determine what's the case and correctly
267 	 * set the absolute (non-wrapped) target time, it's necessary to compare
268 	 * the least significant 32 bits of the current 64-bit network subsystem
269 	 * time with the provided 32-bit target time. Let's assume that half of
270 	 * the 32-bit range can be used for specifying target times in the
271 	 * future, and the other half - in the past.
272 	 */
273 	uint64_t now_us = otPlatTimeGet();
274 	uint32_t now_us_wrapped = (uint32_t)now_us;
275 	uint32_t time_diff = target_time_us_wrapped - now_us_wrapped;
276 	uint64_t result = UINT64_C(0);
277 
278 	if (time_diff < 0x80000000) {
279 		/**
280 		 * Target time is assumed to be in the future. Check if a 32-bit overflow
281 		 * occurs between the current time and the target time.
282 		 */
283 		if (now_us_wrapped > target_time_us_wrapped) {
284 			/**
285 			 * Add a 32-bit overflow and replace the least significant 32 bits
286 			 * with the provided target time.
287 			 */
288 			result = now_us + UINT32_MAX + 1;
289 			result &= ~(uint64_t)UINT32_MAX;
290 			result |= target_time_us_wrapped;
291 		} else {
292 			/**
293 			 * Leave the most significant 32 bits and replace the least significant
294 			 * 32 bits with the provided target time.
295 			 */
296 			result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time_us_wrapped;
297 		}
298 	} else {
299 		/**
300 		 * Target time is assumed to be in the past. Check if a 32-bit overflow
301 		 * occurs between the target time and the current time.
302 		 */
303 		if (now_us_wrapped > target_time_us_wrapped) {
304 			/**
305 			 * Leave the most significant 32 bits and replace the least significant
306 			 * 32 bits with the provided target time.
307 			 */
308 			result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time_us_wrapped;
309 		} else {
310 			/**
311 			 * Subtract a 32-bit overflow and replace the least significant
312 			 * 32 bits with the provided target time.
313 			 */
314 			result = now_us - UINT32_MAX - 1;
315 			result &= ~(uint64_t)UINT32_MAX;
316 			result |= target_time_us_wrapped;
317 		}
318 	}
319 
320 	__ASSERT_NO_MSG(result <= INT64_MAX / NSEC_PER_USEC);
321 	return (net_time_t)result * NSEC_PER_USEC;
322 }
323 #endif /* CONFIG_OPENTHREAD_PLATFORM_PKT_TXTIME || CONFIG_OPENTHREAD_CSL_RECEIVER */
324 
dataInit(void)325 static void dataInit(void)
326 {
327 	tx_pkt = net_pkt_alloc(K_NO_WAIT);
328 	__ASSERT_NO_MSG(tx_pkt != NULL);
329 
330 	tx_payload = net_pkt_get_reserve_tx_data(IEEE802154_MAX_PHY_PACKET_SIZE,
331 						 K_NO_WAIT);
332 	__ASSERT_NO_MSG(tx_payload != NULL);
333 
334 	net_pkt_append_buffer(tx_pkt, tx_payload);
335 
336 	sTransmitFrame.mPsdu = tx_payload->data;
337 
338 	for (size_t i = 0; i < CHANNEL_COUNT; i++) {
339 		max_tx_power_table[i] = OT_RADIO_POWER_INVALID;
340 	}
341 
342 #if defined(CONFIG_OPENTHREAD_TIME_SYNC)
343 	sTransmitFrame.mInfo.mTxInfo.mIeInfo = &tx_ie_info;
344 #endif
345 }
346 
platformRadioInit(void)347 void platformRadioInit(void)
348 {
349 	struct ieee802154_config cfg;
350 
351 	dataInit();
352 
353 	__ASSERT_NO_MSG(device_is_ready(radio_dev));
354 
355 	radio_api = (struct ieee802154_radio_api *)radio_dev->api;
356 	if (!radio_api) {
357 		return;
358 	}
359 
360 	k_work_queue_start(&ot_work_q, ot_task_stack,
361 			   K_KERNEL_STACK_SIZEOF(ot_task_stack),
362 			   OT_WORKER_PRIORITY, NULL);
363 	k_thread_name_set(&ot_work_q.thread, "ot_radio_workq");
364 
365 	if ((radio_api->get_capabilities(radio_dev) &
366 	     IEEE802154_HW_TX_RX_ACK) != IEEE802154_HW_TX_RX_ACK) {
367 		LOG_ERR("Only radios with automatic ack handling "
368 			"are currently supported");
369 		k_panic();
370 	}
371 
372 	cfg.event_handler = handle_radio_event;
373 	radio_api->configure(radio_dev, IEEE802154_CONFIG_EVENT_HANDLER, &cfg);
374 }
375 
radio_set_channel(uint16_t ch)376 static void radio_set_channel(uint16_t ch)
377 {
378 	channel = ch;
379 	radio_api->set_channel(radio_dev, ch);
380 }
381 
transmit_message(struct k_work * tx_job)382 void transmit_message(struct k_work *tx_job)
383 {
384 	int tx_err;
385 
386 	ARG_UNUSED(tx_job);
387 
388 	enum ieee802154_hw_caps radio_caps = radio_api->get_capabilities(radio_dev);
389 
390 	/*
391 	 * The payload is already in tx_payload->data,
392 	 * but we need to set the length field
393 	 * according to sTransmitFrame.length.
394 	 * We subtract the FCS size as radio driver
395 	 * adds CRC and increases frame length on its own.
396 	 */
397 	tx_payload->len = sTransmitFrame.mLength - FCS_SIZE;
398 
399 	radio_api->set_txpower(radio_dev, get_transmit_power_for_channel(sTransmitFrame.mChannel));
400 
401 #if defined(CONFIG_OPENTHREAD_TIME_SYNC)
402 	if (sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0) {
403 		uint8_t *time_ie =
404 			sTransmitFrame.mPsdu + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
405 		uint64_t offset_plat_time =
406 			otPlatTimeGet() + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset;
407 
408 		*(time_ie++) = sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
409 		sys_put_le64(offset_plat_time, time_ie);
410 	}
411 #endif
412 
413 	net_pkt_set_ieee802154_frame_secured(tx_pkt,
414 					     sTransmitFrame.mInfo.mTxInfo.mIsSecurityProcessed);
415 	net_pkt_set_ieee802154_mac_hdr_rdy(tx_pkt, sTransmitFrame.mInfo.mTxInfo.mIsHeaderUpdated);
416 
417 	if ((radio_caps & IEEE802154_HW_TXTIME) &&
418 	    (sTransmitFrame.mInfo.mTxInfo.mTxDelay != 0)) {
419 #if defined(CONFIG_OPENTHREAD_PLATFORM_PKT_TXTIME)
420 		uint32_t tx_at = sTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime +
421 				 sTransmitFrame.mInfo.mTxInfo.mTxDelay;
422 		net_pkt_set_timestamp_ns(tx_pkt, convert_32bit_us_wrapped_to_64bit_ns(tx_at));
423 #endif
424 #if defined(CONFIG_IEEE802154_SELECTIVE_TXCHANNEL)
425 		if (radio_caps & IEEE802154_HW_SELECTIVE_TXCHANNEL) {
426 			net_pkt_set_ieee802154_txchannel(tx_pkt, sTransmitFrame.mChannel);
427 		} else {
428 			radio_set_channel(sTransmitFrame.mChannel);
429 		}
430 #else
431 		radio_set_channel(sTransmitFrame.mChannel);
432 #endif
433 		tx_err =
434 			radio_api->tx(radio_dev, IEEE802154_TX_MODE_TXTIME_CCA, tx_pkt, tx_payload);
435 	} else if (sTransmitFrame.mInfo.mTxInfo.mCsmaCaEnabled) {
436 		radio_set_channel(sTransmitFrame.mChannel);
437 		if (radio_caps & IEEE802154_HW_CSMA) {
438 			tx_err = radio_api->tx(radio_dev, IEEE802154_TX_MODE_CSMA_CA, tx_pkt,
439 					       tx_payload);
440 		} else {
441 			tx_err = radio_api->cca(radio_dev);
442 			if (tx_err == 0) {
443 				tx_err = radio_api->tx(radio_dev, IEEE802154_TX_MODE_DIRECT, tx_pkt,
444 						       tx_payload);
445 			}
446 		}
447 	} else {
448 		radio_set_channel(sTransmitFrame.mChannel);
449 		tx_err = radio_api->tx(radio_dev, IEEE802154_TX_MODE_DIRECT, tx_pkt, tx_payload);
450 	}
451 
452 	/*
453 	 * OpenThread handles the following errors:
454 	 * - OT_ERROR_NONE
455 	 * - OT_ERROR_NO_ACK
456 	 * - OT_ERROR_CHANNEL_ACCESS_FAILURE
457 	 * - OT_ERROR_ABORT
458 	 * Any other error passed to `otPlatRadioTxDone` will result in assertion.
459 	 */
460 	switch (tx_err) {
461 	case 0:
462 		tx_result = OT_ERROR_NONE;
463 		break;
464 	case -ENOMSG:
465 		tx_result = OT_ERROR_NO_ACK;
466 		break;
467 	case -EBUSY:
468 		tx_result = OT_ERROR_CHANNEL_ACCESS_FAILURE;
469 		break;
470 	case -EIO:
471 		tx_result = OT_ERROR_ABORT;
472 		break;
473 	default:
474 		tx_result = OT_ERROR_CHANNEL_ACCESS_FAILURE;
475 		break;
476 	}
477 
478 	set_pending_event(PENDING_EVENT_TX_DONE);
479 }
480 
handle_tx_done(otInstance * aInstance)481 static inline void handle_tx_done(otInstance *aInstance)
482 {
483 	sTransmitFrame.mInfo.mTxInfo.mIsSecurityProcessed =
484 		net_pkt_ieee802154_frame_secured(tx_pkt);
485 	sTransmitFrame.mInfo.mTxInfo.mIsHeaderUpdated = net_pkt_ieee802154_mac_hdr_rdy(tx_pkt);
486 
487 	if (IS_ENABLED(CONFIG_OPENTHREAD_DIAG) && otPlatDiagModeGet()) {
488 		otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, tx_result);
489 	} else {
490 		otPlatRadioTxDone(aInstance, &sTransmitFrame, ack_frame.mLength ? &ack_frame : NULL,
491 				  tx_result);
492 		ack_frame.mLength = 0;
493 	}
494 }
495 
openthread_handle_received_frame(otInstance * instance,struct net_pkt * pkt)496 static void openthread_handle_received_frame(otInstance *instance,
497 					     struct net_pkt *pkt)
498 {
499 	otRadioFrame recv_frame;
500 	memset(&recv_frame, 0, sizeof(otRadioFrame));
501 
502 	recv_frame.mPsdu = net_buf_frag_last(pkt->buffer)->data;
503 	/* Length inc. CRC. */
504 	recv_frame.mLength = net_buf_frags_len(pkt->buffer);
505 	recv_frame.mChannel = platformRadioChannelGet(instance);
506 	recv_frame.mInfo.mRxInfo.mLqi = net_pkt_ieee802154_lqi(pkt);
507 	recv_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi_dbm(pkt);
508 	recv_frame.mInfo.mRxInfo.mAckedWithFramePending = net_pkt_ieee802154_ack_fpb(pkt);
509 
510 #if defined(CONFIG_NET_PKT_TIMESTAMP)
511 	recv_frame.mInfo.mRxInfo.mTimestamp = net_pkt_timestamp_ns(pkt) / NSEC_PER_USEC;
512 #endif
513 
514 	recv_frame.mInfo.mRxInfo.mAckedWithSecEnhAck = net_pkt_ieee802154_ack_seb(pkt);
515 	recv_frame.mInfo.mRxInfo.mAckFrameCounter = net_pkt_ieee802154_ack_fc(pkt);
516 	recv_frame.mInfo.mRxInfo.mAckKeyId = net_pkt_ieee802154_ack_keyid(pkt);
517 
518 	if (IS_ENABLED(CONFIG_OPENTHREAD_DIAG) && otPlatDiagModeGet()) {
519 		otPlatDiagRadioReceiveDone(instance, &recv_frame, OT_ERROR_NONE);
520 	} else {
521 		otPlatRadioReceiveDone(instance, &recv_frame, OT_ERROR_NONE);
522 	}
523 
524 	net_pkt_unref(pkt);
525 }
526 
527 #if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
528 
openthread_ip4_new_msg(otInstance * instance,otMessageSettings * settings)529 static otMessage *openthread_ip4_new_msg(otInstance *instance, otMessageSettings *settings)
530 {
531 	return otIp4NewMessage(instance, settings);
532 }
533 
openthread_nat64_send(otInstance * instance,otMessage * message)534 static otError openthread_nat64_send(otInstance *instance, otMessage *message)
535 {
536 	return otNat64Send(instance, message);
537 }
538 
539 #else /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
540 
openthread_ip4_new_msg(otInstance * instance,otMessageSettings * settings)541 static otMessage *openthread_ip4_new_msg(otInstance *instance, otMessageSettings *settings)
542 {
543 	return NULL;
544 }
545 
openthread_nat64_send(otInstance * instance,otMessage * message)546 static otError openthread_nat64_send(otInstance *instance, otMessage *message)
547 {
548 	return OT_ERROR_DROP;
549 }
550 
551 #endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
552 
openthread_handle_frame_to_send(otInstance * instance,struct net_pkt * pkt)553 static void openthread_handle_frame_to_send(otInstance *instance, struct net_pkt *pkt)
554 {
555 	otError error;
556 	struct net_buf *buf;
557 	otMessage *message;
558 	otMessageSettings settings;
559 	bool is_ip6 = PKT_IS_IPv6(pkt);
560 
561 	NET_DBG("Sending %s packet to ot stack", is_ip6 ? "IPv6" : "IPv4");
562 
563 	settings.mPriority = OT_MESSAGE_PRIORITY_NORMAL;
564 	settings.mLinkSecurityEnabled = true;
565 
566 	message = is_ip6 ? otIp6NewMessage(instance, &settings)
567 			 : openthread_ip4_new_msg(instance, &settings);
568 	if (!message) {
569 		NET_ERR("Cannot allocate new message buffer");
570 		goto exit;
571 	}
572 
573 	if (IS_ENABLED(CONFIG_OPENTHREAD)) {
574 		/* Set multicast loop so the stack can process multicast packets for
575 		 * subscribed addresses.
576 		 */
577 		otMessageSetMulticastLoopEnabled(message, true);
578 	}
579 
580 	for (buf = pkt->buffer; buf; buf = buf->frags) {
581 		if (otMessageAppend(message, buf->data, buf->len) != OT_ERROR_NONE) {
582 			NET_ERR("Error while appending to otMessage");
583 			otMessageFree(message);
584 			goto exit;
585 		}
586 	}
587 
588 	error = is_ip6 ? otIp6Send(instance, message) : openthread_nat64_send(instance, message);
589 
590 	if (error != OT_ERROR_NONE) {
591 		NET_ERR("Error while calling %s [error: %d]",
592 			is_ip6 ? "otIp6Send" : "openthread_nat64_send", error);
593 	}
594 
595 exit:
596 	net_pkt_unref(pkt);
597 }
598 
notify_new_rx_frame(struct net_pkt * pkt)599 int notify_new_rx_frame(struct net_pkt *pkt)
600 {
601 	k_fifo_put(&rx_pkt_fifo, pkt);
602 	set_pending_event(PENDING_EVENT_FRAME_RECEIVED);
603 
604 	return 0;
605 }
606 
notify_new_tx_frame(struct net_pkt * pkt)607 int notify_new_tx_frame(struct net_pkt *pkt)
608 {
609 	k_fifo_put(&tx_pkt_fifo, pkt);
610 	set_pending_event(PENDING_EVENT_FRAME_TO_SEND);
611 
612 	return 0;
613 }
614 
run_tx_task(otInstance * aInstance)615 static int run_tx_task(otInstance *aInstance)
616 {
617 	static K_WORK_DEFINE(tx_job, transmit_message);
618 
619 	ARG_UNUSED(aInstance);
620 
621 	if (!k_work_is_pending(&tx_job)) {
622 		sState = OT_RADIO_STATE_TRANSMIT;
623 
624 		k_work_submit_to_queue(&ot_work_q, &tx_job);
625 		k_yield();
626 
627 		return 0;
628 	} else {
629 		return -EBUSY;
630 	}
631 }
632 
platformRadioProcess(otInstance * aInstance)633 void platformRadioProcess(otInstance *aInstance)
634 {
635 	bool event_pending = false;
636 
637 	if (is_pending_event_set(PENDING_EVENT_FRAME_TO_SEND)) {
638 		struct net_pkt *evt_pkt;
639 
640 		reset_pending_event(PENDING_EVENT_FRAME_TO_SEND);
641 		while ((evt_pkt = (struct net_pkt *) k_fifo_get(&tx_pkt_fifo, K_NO_WAIT)) != NULL) {
642 			if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR_RCP)) {
643 				net_pkt_unref(evt_pkt);
644 			} else {
645 				openthread_handle_frame_to_send(aInstance, evt_pkt);
646 			}
647 		}
648 	}
649 
650 	if (is_pending_event_set(PENDING_EVENT_FRAME_RECEIVED)) {
651 		struct net_pkt *rx_pkt;
652 
653 		reset_pending_event(PENDING_EVENT_FRAME_RECEIVED);
654 		while ((rx_pkt = (struct net_pkt *) k_fifo_get(&rx_pkt_fifo, K_NO_WAIT)) != NULL) {
655 			openthread_handle_received_frame(aInstance, rx_pkt);
656 		}
657 	}
658 
659 	if (is_pending_event_set(PENDING_EVENT_RX_FAILED)) {
660 		reset_pending_event(PENDING_EVENT_RX_FAILED);
661 		if (IS_ENABLED(CONFIG_OPENTHREAD_DIAG) && otPlatDiagModeGet()) {
662 			otPlatDiagRadioReceiveDone(aInstance, NULL, rx_result);
663 		} else {
664 			otPlatRadioReceiveDone(aInstance, NULL, rx_result);
665 		}
666 	}
667 
668 	if (is_pending_event_set(PENDING_EVENT_TX_STARTED)) {
669 		reset_pending_event(PENDING_EVENT_TX_STARTED);
670 		otPlatRadioTxStarted(aInstance, &sTransmitFrame);
671 	}
672 
673 	if (is_pending_event_set(PENDING_EVENT_TX_DONE)) {
674 		reset_pending_event(PENDING_EVENT_TX_DONE);
675 
676 		if (sState == OT_RADIO_STATE_TRANSMIT ||
677 		    radio_api->get_capabilities(radio_dev) & IEEE802154_HW_SLEEP_TO_TX) {
678 			sState = OT_RADIO_STATE_RECEIVE;
679 			handle_tx_done(aInstance);
680 		}
681 	}
682 
683 	if (is_pending_event_set(PENDING_EVENT_SLEEP)) {
684 		reset_pending_event(PENDING_EVENT_SLEEP);
685 		ARG_UNUSED(otPlatRadioSleep(aInstance));
686 	}
687 
688 	/* handle events that can't run during transmission */
689 	if (sState != OT_RADIO_STATE_TRANSMIT) {
690 		if (is_pending_event_set(PENDING_EVENT_DETECT_ENERGY)) {
691 			radio_api->set_channel(radio_dev,
692 					       energy_detection_channel);
693 
694 			if (!radio_api->ed_scan(radio_dev,
695 						energy_detection_time,
696 						energy_detected)) {
697 				reset_pending_event(
698 					PENDING_EVENT_DETECT_ENERGY);
699 			} else {
700 				event_pending = true;
701 			}
702 		}
703 
704 		if (is_pending_event_set(PENDING_EVENT_DETECT_ENERGY_DONE)) {
705 			otPlatRadioEnergyScanDone(aInstance, (int8_t) energy_detected_value);
706 			reset_pending_event(PENDING_EVENT_DETECT_ENERGY_DONE);
707 		}
708 	}
709 
710 	if (event_pending) {
711 		otSysEventSignalPending();
712 	}
713 }
714 
platformRadioChannelGet(otInstance * aInstance)715 uint16_t platformRadioChannelGet(otInstance *aInstance)
716 {
717 	ARG_UNUSED(aInstance);
718 
719 	return channel;
720 }
721 
722 #if defined(CONFIG_OPENTHREAD_DIAG)
platformRadioChannelSet(uint8_t aChannel)723 void platformRadioChannelSet(uint8_t aChannel)
724 {
725 	channel = aChannel;
726 }
727 #endif
728 
otPlatRadioSetPanId(otInstance * aInstance,uint16_t aPanId)729 void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId)
730 {
731 	ARG_UNUSED(aInstance);
732 
733 	radio_api->filter(radio_dev, true, IEEE802154_FILTER_TYPE_PAN_ID,
734 			  (struct ieee802154_filter *) &aPanId);
735 }
736 
otPlatRadioSetExtendedAddress(otInstance * aInstance,const otExtAddress * aExtAddress)737 void otPlatRadioSetExtendedAddress(otInstance *aInstance,
738 				   const otExtAddress *aExtAddress)
739 {
740 	ARG_UNUSED(aInstance);
741 
742 	radio_api->filter(radio_dev, true, IEEE802154_FILTER_TYPE_IEEE_ADDR,
743 			  (struct ieee802154_filter *) &aExtAddress);
744 }
745 
otPlatRadioSetShortAddress(otInstance * aInstance,uint16_t aShortAddress)746 void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddress)
747 {
748 	ARG_UNUSED(aInstance);
749 
750 	radio_api->filter(radio_dev, true, IEEE802154_FILTER_TYPE_SHORT_ADDR,
751 			  (struct ieee802154_filter *) &aShortAddress);
752 }
753 
otPlatRadioIsEnabled(otInstance * aInstance)754 bool otPlatRadioIsEnabled(otInstance *aInstance)
755 {
756 	ARG_UNUSED(aInstance);
757 
758 	return (sState != OT_RADIO_STATE_DISABLED) ? true : false;
759 }
760 
otPlatRadioEnable(otInstance * aInstance)761 otError otPlatRadioEnable(otInstance *aInstance)
762 {
763 	ARG_UNUSED(aInstance);
764 
765 	if (sState != OT_RADIO_STATE_DISABLED && sState != OT_RADIO_STATE_SLEEP) {
766 		return OT_ERROR_INVALID_STATE;
767 	}
768 
769 	sState = OT_RADIO_STATE_SLEEP;
770 	return OT_ERROR_NONE;
771 }
772 
otPlatRadioDisable(otInstance * aInstance)773 otError otPlatRadioDisable(otInstance *aInstance)
774 {
775 	ARG_UNUSED(aInstance);
776 
777 	if (sState != OT_RADIO_STATE_DISABLED && sState != OT_RADIO_STATE_SLEEP) {
778 		return OT_ERROR_INVALID_STATE;
779 	}
780 
781 	sState = OT_RADIO_STATE_DISABLED;
782 	return OT_ERROR_NONE;
783 }
784 
otPlatRadioSleep(otInstance * aInstance)785 otError otPlatRadioSleep(otInstance *aInstance)
786 {
787 	ARG_UNUSED(aInstance);
788 
789 	if (sState != OT_RADIO_STATE_SLEEP && sState != OT_RADIO_STATE_RECEIVE) {
790 		return OT_ERROR_INVALID_STATE;
791 	}
792 
793 	radio_api->stop(radio_dev);
794 	sState = OT_RADIO_STATE_SLEEP;
795 
796 	return OT_ERROR_NONE;
797 }
798 
otPlatRadioReceive(otInstance * aInstance,uint8_t aChannel)799 otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
800 {
801 	ARG_UNUSED(aInstance);
802 
803 	if (sState == OT_RADIO_STATE_DISABLED) {
804 		return OT_ERROR_INVALID_STATE;
805 	}
806 
807 	channel = aChannel;
808 
809 	radio_api->set_channel(radio_dev, aChannel);
810 	radio_api->set_txpower(radio_dev, get_transmit_power_for_channel(channel));
811 	radio_api->start(radio_dev);
812 	sState = OT_RADIO_STATE_RECEIVE;
813 
814 	return OT_ERROR_NONE;
815 }
816 
817 #if defined(CONFIG_OPENTHREAD_CSL_RECEIVER) || defined(CONFIG_OPENTHREAD_WAKEUP_END_DEVICE)
otPlatRadioReceiveAt(otInstance * aInstance,uint8_t aChannel,uint32_t aStart,uint32_t aDuration)818 otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel,
819 			     uint32_t aStart, uint32_t aDuration)
820 {
821 	int result;
822 
823 	ARG_UNUSED(aInstance);
824 
825 	struct ieee802154_config config = {
826 		.rx_slot.channel = aChannel,
827 		.rx_slot.start = convert_32bit_us_wrapped_to_64bit_ns(aStart),
828 		.rx_slot.duration = (net_time_t)aDuration * NSEC_PER_USEC,
829 	};
830 
831 	result = radio_api->configure(radio_dev, IEEE802154_CONFIG_RX_SLOT,
832 				      &config);
833 
834 	return result ? OT_ERROR_FAILED : OT_ERROR_NONE;
835 }
836 #endif
837 
838 #if defined(CONFIG_OPENTHREAD_PLATFORM_CARRIER_FUNCTIONS)
platformRadioTransmitCarrier(otInstance * aInstance,bool aEnable)839 otError platformRadioTransmitCarrier(otInstance *aInstance, bool aEnable)
840 {
841 	if (radio_api->continuous_carrier == NULL) {
842 		return OT_ERROR_NOT_IMPLEMENTED;
843 	}
844 
845 	if ((aEnable) && (sState == OT_RADIO_STATE_RECEIVE)) {
846 		radio_api->set_txpower(radio_dev, get_transmit_power_for_channel(channel));
847 
848 		if (radio_api->continuous_carrier(radio_dev) != 0) {
849 			return OT_ERROR_FAILED;
850 		}
851 
852 		sState = OT_RADIO_STATE_TRANSMIT;
853 	} else if ((!aEnable) && (sState == OT_RADIO_STATE_TRANSMIT)) {
854 		return otPlatRadioReceive(aInstance, channel);
855 	} else {
856 		return OT_ERROR_INVALID_STATE;
857 	}
858 
859 	return OT_ERROR_NONE;
860 }
861 
platformRadioTransmitModulatedCarrier(otInstance * aInstance,bool aEnable,const uint8_t * aData)862 otError platformRadioTransmitModulatedCarrier(otInstance *aInstance, bool aEnable,
863 					      const uint8_t *aData)
864 {
865 	if (radio_api->modulated_carrier == NULL) {
866 		return OT_ERROR_NOT_IMPLEMENTED;
867 	}
868 
869 	if (aEnable && sState == OT_RADIO_STATE_RECEIVE) {
870 		if (aData == NULL) {
871 			return OT_ERROR_INVALID_ARGS;
872 		}
873 
874 		radio_api->set_txpower(radio_dev, get_transmit_power_for_channel(channel));
875 
876 		if (radio_api->modulated_carrier(radio_dev, aData) != 0) {
877 			return OT_ERROR_FAILED;
878 		}
879 		sState = OT_RADIO_STATE_TRANSMIT;
880 	} else if ((!aEnable) && sState == OT_RADIO_STATE_TRANSMIT) {
881 		return otPlatRadioReceive(aInstance, channel);
882 	} else {
883 		return OT_ERROR_INVALID_STATE;
884 	}
885 
886 	return OT_ERROR_NONE;
887 }
888 
889 #endif /* CONFIG_OPENTHREAD_PLATFORM_CARRIER_FUNCTIONS */
890 
otPlatRadioGetState(otInstance * aInstance)891 otRadioState otPlatRadioGetState(otInstance *aInstance)
892 {
893 	ARG_UNUSED(aInstance);
894 
895 	return sState;
896 }
897 
otPlatRadioTransmit(otInstance * aInstance,otRadioFrame * aPacket)898 otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aPacket)
899 {
900 	otError error = OT_ERROR_INVALID_STATE;
901 
902 	ARG_UNUSED(aInstance);
903 	ARG_UNUSED(aPacket);
904 
905 	__ASSERT_NO_MSG(aPacket == &sTransmitFrame);
906 
907 	enum ieee802154_hw_caps radio_caps;
908 
909 	radio_caps = radio_api->get_capabilities(radio_dev);
910 
911 	if (sState == OT_RADIO_STATE_RECEIVE ||
912 	    (sState == OT_RADIO_STATE_SLEEP &&
913 	     radio_caps & IEEE802154_HW_SLEEP_TO_TX)) {
914 		if (run_tx_task(aInstance) == 0) {
915 			error = OT_ERROR_NONE;
916 		}
917 	}
918 
919 	return error;
920 }
921 
otPlatRadioGetTransmitBuffer(otInstance * aInstance)922 otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
923 {
924 	ARG_UNUSED(aInstance);
925 
926 	return &sTransmitFrame;
927 }
928 
get_rssi_energy_detected(const struct device * dev,int16_t max_ed)929 static void get_rssi_energy_detected(const struct device *dev, int16_t max_ed)
930 {
931 	ARG_UNUSED(dev);
932 	energy_detected_value = max_ed;
933 	k_sem_give(&radio_sem);
934 }
935 
otPlatRadioGetRssi(otInstance * aInstance)936 int8_t otPlatRadioGetRssi(otInstance *aInstance)
937 {
938 	int8_t ret_rssi = INT8_MAX;
939 	int error = 0;
940 	const uint16_t detection_time = 1;
941 	enum ieee802154_hw_caps radio_caps;
942 	ARG_UNUSED(aInstance);
943 
944 	radio_caps = radio_api->get_capabilities(radio_dev);
945 
946 	if (!(radio_caps & IEEE802154_HW_ENERGY_SCAN)) {
947 		/*
948 		 * TODO: No API in Zephyr to get the RSSI
949 		 * when IEEE802154_HW_ENERGY_SCAN is not available
950 		 */
951 		ret_rssi = 0;
952 	} else {
953 		/*
954 		 * Blocking implementation of get RSSI
955 		 * using no-blocking ed_scan
956 		 */
957 		error = radio_api->ed_scan(radio_dev, detection_time,
958 					   get_rssi_energy_detected);
959 
960 		if (error == 0) {
961 			k_sem_take(&radio_sem, K_FOREVER);
962 
963 			ret_rssi = (int8_t)energy_detected_value;
964 		}
965 	}
966 
967 	return ret_rssi;
968 }
969 
otPlatRadioGetCaps(otInstance * aInstance)970 otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
971 {
972 	otRadioCaps caps = OT_RADIO_CAPS_NONE;
973 
974 	enum ieee802154_hw_caps radio_caps;
975 	ARG_UNUSED(aInstance);
976 	__ASSERT(radio_api,
977 	    "platformRadioInit needs to be called prior to otPlatRadioGetCaps");
978 
979 	radio_caps = radio_api->get_capabilities(radio_dev);
980 
981 	if (radio_caps & IEEE802154_HW_ENERGY_SCAN) {
982 		caps |= OT_RADIO_CAPS_ENERGY_SCAN;
983 	}
984 
985 	if (radio_caps & IEEE802154_HW_CSMA) {
986 		caps |= OT_RADIO_CAPS_CSMA_BACKOFF;
987 	}
988 
989 	if (radio_caps & IEEE802154_HW_TX_RX_ACK) {
990 		caps |= OT_RADIO_CAPS_ACK_TIMEOUT;
991 	}
992 
993 	if (radio_caps & IEEE802154_HW_SLEEP_TO_TX) {
994 		caps |= OT_RADIO_CAPS_SLEEP_TO_TX;
995 	}
996 
997 #if !defined(CONFIG_OPENTHREAD_THREAD_VERSION_1_1)
998 	if (radio_caps & IEEE802154_HW_TX_SEC) {
999 		caps |= OT_RADIO_CAPS_TRANSMIT_SEC;
1000 	}
1001 #endif
1002 
1003 #if defined(CONFIG_OPENTHREAD_PLATFORM_PKT_TXTIME)
1004 	if (radio_caps & IEEE802154_HW_TXTIME) {
1005 		caps |= OT_RADIO_CAPS_TRANSMIT_TIMING;
1006 	}
1007 #endif
1008 
1009 	if (radio_caps & IEEE802154_HW_RXTIME) {
1010 		caps |= OT_RADIO_CAPS_RECEIVE_TIMING;
1011 	}
1012 
1013 	if (radio_caps & IEEE802154_RX_ON_WHEN_IDLE) {
1014 		caps |= OT_RADIO_CAPS_RX_ON_WHEN_IDLE;
1015 	}
1016 
1017 	return caps;
1018 }
1019 
otPlatRadioSetRxOnWhenIdle(otInstance * aInstance,bool aRxOnWhenIdle)1020 void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aRxOnWhenIdle)
1021 {
1022 	struct ieee802154_config config = {
1023 		.rx_on_when_idle = aRxOnWhenIdle
1024 	};
1025 
1026 	ARG_UNUSED(aInstance);
1027 
1028 	LOG_DBG("RxOnWhenIdle=%d", aRxOnWhenIdle ? 1 : 0);
1029 
1030 	radio_api->configure(radio_dev, IEEE802154_CONFIG_RX_ON_WHEN_IDLE, &config);
1031 }
1032 
otPlatRadioGetPromiscuous(otInstance * aInstance)1033 bool otPlatRadioGetPromiscuous(otInstance *aInstance)
1034 {
1035 	ARG_UNUSED(aInstance);
1036 
1037 	LOG_DBG("PromiscuousMode=%d", promiscuous ? 1 : 0);
1038 
1039 	return promiscuous;
1040 }
1041 
otPlatRadioSetPromiscuous(otInstance * aInstance,bool aEnable)1042 void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
1043 {
1044 	struct ieee802154_config config = {
1045 		.promiscuous = aEnable
1046 	};
1047 
1048 	ARG_UNUSED(aInstance);
1049 
1050 	LOG_DBG("PromiscuousMode=%d", aEnable ? 1 : 0);
1051 
1052 	promiscuous = aEnable;
1053 	/* TODO: Should check whether the radio driver actually supports
1054 	 *       promiscuous mode, see net_if_l2(iface)->get_flags() and
1055 	 *       ieee802154_radio_get_hw_capabilities(iface).
1056 	 */
1057 	radio_api->configure(radio_dev, IEEE802154_CONFIG_PROMISCUOUS, &config);
1058 }
1059 
otPlatRadioEnergyScan(otInstance * aInstance,uint8_t aScanChannel,uint16_t aScanDuration)1060 otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel,
1061 			      uint16_t aScanDuration)
1062 {
1063 	energy_detection_time    = aScanDuration;
1064 	energy_detection_channel = aScanChannel;
1065 
1066 	if (radio_api->ed_scan == NULL) {
1067 		return OT_ERROR_NOT_IMPLEMENTED;
1068 	}
1069 
1070 	reset_pending_event(PENDING_EVENT_DETECT_ENERGY);
1071 	reset_pending_event(PENDING_EVENT_DETECT_ENERGY_DONE);
1072 
1073 	radio_api->set_channel(radio_dev, aScanChannel);
1074 
1075 	if (radio_api->ed_scan(radio_dev, energy_detection_time, energy_detected) != 0) {
1076 		/*
1077 		 * OpenThread API does not accept failure of this function,
1078 		 * it can return 'No Error' or 'Not Implemented' error only.
1079 		 * If ed_scan start failed event is set to schedule the scan at
1080 		 * later time.
1081 		 */
1082 		LOG_ERR("Failed do start energy scan, scheduling for later");
1083 		set_pending_event(PENDING_EVENT_DETECT_ENERGY);
1084 	}
1085 
1086 	return OT_ERROR_NONE;
1087 }
1088 
otPlatRadioGetCcaEnergyDetectThreshold(otInstance * aInstance,int8_t * aThreshold)1089 otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance,
1090 					       int8_t *aThreshold)
1091 {
1092 	OT_UNUSED_VARIABLE(aInstance);
1093 	OT_UNUSED_VARIABLE(aThreshold);
1094 
1095 	return OT_ERROR_NOT_IMPLEMENTED;
1096 }
1097 
otPlatRadioSetCcaEnergyDetectThreshold(otInstance * aInstance,int8_t aThreshold)1098 otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance,
1099 					       int8_t aThreshold)
1100 {
1101 	OT_UNUSED_VARIABLE(aInstance);
1102 	OT_UNUSED_VARIABLE(aThreshold);
1103 
1104 	return OT_ERROR_NOT_IMPLEMENTED;
1105 }
1106 
otPlatRadioEnableSrcMatch(otInstance * aInstance,bool aEnable)1107 void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
1108 {
1109 	ARG_UNUSED(aInstance);
1110 
1111 	struct ieee802154_config config = {
1112 		.auto_ack_fpb.enabled = aEnable,
1113 		.auto_ack_fpb.mode = IEEE802154_FPB_ADDR_MATCH_THREAD,
1114 	};
1115 
1116 	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_AUTO_ACK_FPB,
1117 				   &config);
1118 }
1119 
otPlatRadioAddSrcMatchShortEntry(otInstance * aInstance,const uint16_t aShortAddress)1120 otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance,
1121 					 const uint16_t aShortAddress)
1122 {
1123 	ARG_UNUSED(aInstance);
1124 
1125 	uint8_t short_address[SHORT_ADDRESS_SIZE];
1126 	struct ieee802154_config config = {
1127 		.ack_fpb.enabled = true,
1128 		.ack_fpb.addr = short_address,
1129 		.ack_fpb.extended = false
1130 	};
1131 
1132 	sys_put_le16(aShortAddress, short_address);
1133 
1134 	if (radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
1135 				 &config) != 0) {
1136 		return OT_ERROR_NO_BUFS;
1137 	}
1138 
1139 	return OT_ERROR_NONE;
1140 }
1141 
otPlatRadioAddSrcMatchExtEntry(otInstance * aInstance,const otExtAddress * aExtAddress)1142 otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance,
1143 				       const otExtAddress *aExtAddress)
1144 {
1145 	ARG_UNUSED(aInstance);
1146 
1147 	struct ieee802154_config config = {
1148 		.ack_fpb.enabled = true,
1149 		.ack_fpb.addr = (uint8_t *)aExtAddress->m8,
1150 		.ack_fpb.extended = true
1151 	};
1152 
1153 	if (radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
1154 				 &config) != 0) {
1155 		return OT_ERROR_NO_BUFS;
1156 	}
1157 
1158 	return OT_ERROR_NONE;
1159 }
1160 
otPlatRadioClearSrcMatchShortEntry(otInstance * aInstance,const uint16_t aShortAddress)1161 otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance,
1162 					   const uint16_t aShortAddress)
1163 {
1164 	ARG_UNUSED(aInstance);
1165 
1166 	uint8_t short_address[SHORT_ADDRESS_SIZE];
1167 	struct ieee802154_config config = {
1168 		.ack_fpb.enabled = false,
1169 		.ack_fpb.addr = short_address,
1170 		.ack_fpb.extended = false
1171 	};
1172 
1173 	sys_put_le16(aShortAddress, short_address);
1174 
1175 	if (radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
1176 				 &config) != 0) {
1177 		return OT_ERROR_NO_ADDRESS;
1178 	}
1179 
1180 	return OT_ERROR_NONE;
1181 }
1182 
otPlatRadioClearSrcMatchExtEntry(otInstance * aInstance,const otExtAddress * aExtAddress)1183 otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance,
1184 					 const otExtAddress *aExtAddress)
1185 {
1186 	ARG_UNUSED(aInstance);
1187 
1188 	struct ieee802154_config config = {
1189 		.ack_fpb.enabled = false,
1190 		.ack_fpb.addr = (uint8_t *)aExtAddress->m8,
1191 		.ack_fpb.extended = true
1192 	};
1193 
1194 	if (radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
1195 				 &config) != 0) {
1196 		return OT_ERROR_NO_ADDRESS;
1197 	}
1198 
1199 	return OT_ERROR_NONE;
1200 }
1201 
otPlatRadioClearSrcMatchShortEntries(otInstance * aInstance)1202 void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance)
1203 {
1204 	ARG_UNUSED(aInstance);
1205 
1206 	struct ieee802154_config config = {
1207 		.ack_fpb.enabled = false,
1208 		.ack_fpb.addr = NULL,
1209 		.ack_fpb.extended = false
1210 	};
1211 
1212 	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
1213 				   &config);
1214 }
1215 
otPlatRadioClearSrcMatchExtEntries(otInstance * aInstance)1216 void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance)
1217 {
1218 	ARG_UNUSED(aInstance);
1219 
1220 	struct ieee802154_config config = {
1221 		.ack_fpb.enabled = false,
1222 		.ack_fpb.addr = NULL,
1223 		.ack_fpb.extended = true
1224 	};
1225 
1226 	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
1227 				   &config);
1228 }
1229 
otPlatRadioGetReceiveSensitivity(otInstance * aInstance)1230 int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
1231 {
1232 	ARG_UNUSED(aInstance);
1233 
1234 	return CONFIG_OPENTHREAD_DEFAULT_RX_SENSITIVITY;
1235 }
1236 
otPlatRadioGetTransmitPower(otInstance * aInstance,int8_t * aPower)1237 otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
1238 {
1239 	ARG_UNUSED(aInstance);
1240 
1241 	if (aPower == NULL) {
1242 		return OT_ERROR_INVALID_ARGS;
1243 	}
1244 
1245 	*aPower = tx_power;
1246 
1247 	return OT_ERROR_NONE;
1248 }
1249 
otPlatRadioSetTransmitPower(otInstance * aInstance,int8_t aPower)1250 otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
1251 {
1252 	ARG_UNUSED(aInstance);
1253 
1254 	tx_power = aPower;
1255 
1256 	return OT_ERROR_NONE;
1257 }
1258 
otPlatTimeGet(void)1259 uint64_t otPlatTimeGet(void)
1260 {
1261 	if (radio_api == NULL || radio_api->get_time == NULL) {
1262 		return k_ticks_to_us_floor64(k_uptime_ticks());
1263 	} else {
1264 		return radio_api->get_time(radio_dev) / NSEC_PER_USEC;
1265 	}
1266 }
1267 
1268 #if defined(CONFIG_OPENTHREAD_PLATFORM_PKT_TXTIME)
otPlatRadioGetNow(otInstance * aInstance)1269 uint64_t otPlatRadioGetNow(otInstance *aInstance)
1270 {
1271 	ARG_UNUSED(aInstance);
1272 
1273 	return otPlatTimeGet();
1274 }
1275 #endif
1276 
1277 #if !defined(CONFIG_OPENTHREAD_THREAD_VERSION_1_1)
otPlatRadioSetMacKey(otInstance * aInstance,uint8_t aKeyIdMode,uint8_t aKeyId,const otMacKeyMaterial * aPrevKey,const otMacKeyMaterial * aCurrKey,const otMacKeyMaterial * aNextKey,otRadioKeyType aKeyType)1278 void otPlatRadioSetMacKey(otInstance *aInstance, uint8_t aKeyIdMode, uint8_t aKeyId,
1279 			  const otMacKeyMaterial *aPrevKey, const otMacKeyMaterial *aCurrKey,
1280 			  const otMacKeyMaterial *aNextKey, otRadioKeyType aKeyType)
1281 {
1282 	ARG_UNUSED(aInstance);
1283 	__ASSERT_NO_MSG(aPrevKey != NULL && aCurrKey != NULL && aNextKey != NULL);
1284 
1285 #if defined(CONFIG_OPENTHREAD_PLATFORM_KEYS_EXPORTABLE_ENABLE)
1286 	__ASSERT_NO_MSG(aKeyType == OT_KEY_TYPE_KEY_REF);
1287 	size_t keyLen;
1288 	otError error;
1289 
1290 	error = otPlatCryptoExportKey(aPrevKey->mKeyMaterial.mKeyRef,
1291 				      (uint8_t *)aPrevKey->mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE,
1292 				      &keyLen);
1293 	__ASSERT_NO_MSG(error == OT_ERROR_NONE);
1294 	error = otPlatCryptoExportKey(aCurrKey->mKeyMaterial.mKeyRef,
1295 				      (uint8_t *)aCurrKey->mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE,
1296 				      &keyLen);
1297 	__ASSERT_NO_MSG(error == OT_ERROR_NONE);
1298 	error = otPlatCryptoExportKey(aNextKey->mKeyMaterial.mKeyRef,
1299 				      (uint8_t *)aNextKey->mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE,
1300 				      &keyLen);
1301 	__ASSERT_NO_MSG(error == OT_ERROR_NONE);
1302 #else
1303 	__ASSERT_NO_MSG(aKeyType == OT_KEY_TYPE_LITERAL_KEY);
1304 #endif
1305 
1306 	uint8_t key_id_mode = aKeyIdMode >> 3;
1307 
1308 	struct ieee802154_key keys[] = {
1309 		{
1310 			.key_id_mode = key_id_mode,
1311 			.frame_counter_per_key = false,
1312 		},
1313 		{
1314 			.key_id_mode = key_id_mode,
1315 			.frame_counter_per_key = false,
1316 		},
1317 		{
1318 			.key_id_mode = key_id_mode,
1319 			.frame_counter_per_key = false,
1320 		},
1321 		{
1322 			.key_value = NULL,
1323 		},
1324 	};
1325 
1326 	struct ieee802154_key clear_keys[] = {
1327 		{
1328 			.key_value = NULL,
1329 		},
1330 	};
1331 
1332 	if (key_id_mode == 1) {
1333 		/* aKeyId in range: (1, 0x80) means valid keys */
1334 		uint8_t prev_key_id = aKeyId == 1 ? 0x80 : aKeyId - 1;
1335 		uint8_t next_key_id = aKeyId == 0x80 ? 1 : aKeyId + 1;
1336 
1337 		keys[0].key_id = &prev_key_id;
1338 		keys[0].key_value = (uint8_t *)aPrevKey->mKeyMaterial.mKey.m8;
1339 
1340 		keys[1].key_id = &aKeyId;
1341 		keys[1].key_value = (uint8_t *)aCurrKey->mKeyMaterial.mKey.m8;
1342 
1343 		keys[2].key_id = &next_key_id;
1344 		keys[2].key_value = (uint8_t *)aNextKey->mKeyMaterial.mKey.m8;
1345 	} else {
1346 		/* aKeyId == 0 is used only to clear keys for stack reset in RCP */
1347 		__ASSERT_NO_MSG((key_id_mode == 0) && (aKeyId == 0));
1348 	}
1349 
1350 	struct ieee802154_config config = {
1351 		.mac_keys = aKeyId == 0 ? clear_keys : keys,
1352 	};
1353 
1354 	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_MAC_KEYS,
1355 				   &config);
1356 }
1357 
otPlatRadioSetMacFrameCounter(otInstance * aInstance,uint32_t aMacFrameCounter)1358 void otPlatRadioSetMacFrameCounter(otInstance *aInstance,
1359 				   uint32_t aMacFrameCounter)
1360 {
1361 	ARG_UNUSED(aInstance);
1362 
1363 	struct ieee802154_config config = { .frame_counter = aMacFrameCounter };
1364 
1365 	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_FRAME_COUNTER,
1366 				   &config);
1367 }
1368 
otPlatRadioSetMacFrameCounterIfLarger(otInstance * aInstance,uint32_t aMacFrameCounter)1369 void otPlatRadioSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacFrameCounter)
1370 {
1371 	ARG_UNUSED(aInstance);
1372 
1373 	struct ieee802154_config config = { .frame_counter = aMacFrameCounter };
1374 	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_FRAME_COUNTER_IF_LARGER,
1375 				   &config);
1376 }
1377 #endif
1378 
1379 #if defined(CONFIG_OPENTHREAD_CSL_RECEIVER)
otPlatRadioEnableCsl(otInstance * aInstance,uint32_t aCslPeriod,otShortAddress aShortAddr,const otExtAddress * aExtAddr)1380 otError otPlatRadioEnableCsl(otInstance *aInstance, uint32_t aCslPeriod, otShortAddress aShortAddr,
1381 			     const otExtAddress *aExtAddr)
1382 {
1383 	struct ieee802154_config config;
1384 	/* CSL phase will be injected on-the-fly by the driver. */
1385 	struct ieee802154_header_ie header_ie =
1386 		IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(/* phase */ 0, aCslPeriod);
1387 	int result;
1388 
1389 	ARG_UNUSED(aInstance);
1390 
1391 	/* Configure the CSL period first to give drivers a chance to validate
1392 	 * the IE for consistency if they wish to.
1393 	 */
1394 	config.csl_period = aCslPeriod;
1395 	result = radio_api->configure(radio_dev, IEEE802154_CONFIG_CSL_PERIOD, &config);
1396 	if (result) {
1397 		return OT_ERROR_FAILED;
1398 	}
1399 
1400 	/* Configure the CSL IE. */
1401 	config.ack_ie.header_ie = aCslPeriod > 0 ? &header_ie : NULL;
1402 	config.ack_ie.short_addr = aShortAddr;
1403 	config.ack_ie.ext_addr = aExtAddr != NULL ? aExtAddr->m8 : NULL;
1404 	config.ack_ie.purge_ie = false;
1405 
1406 	result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config);
1407 
1408 	return result ? OT_ERROR_FAILED : OT_ERROR_NONE;
1409 }
1410 
otPlatRadioResetCsl(otInstance * aInstance)1411 otError otPlatRadioResetCsl(otInstance *aInstance)
1412 {
1413 	struct ieee802154_config config = { 0 };
1414 	int result;
1415 
1416 	result = radio_api->configure(radio_dev, IEEE802154_CONFIG_CSL_PERIOD, &config);
1417 	if (result) {
1418 		return OT_ERROR_FAILED;
1419 	}
1420 
1421 	config.ack_ie.purge_ie = true;
1422 	result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config);
1423 
1424 	return result ? OT_ERROR_FAILED : OT_ERROR_NONE;
1425 }
1426 
otPlatRadioUpdateCslSampleTime(otInstance * aInstance,uint32_t aCslSampleTime)1427 void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTime)
1428 {
1429 	ARG_UNUSED(aInstance);
1430 
1431 	/* CSL sample time points to "start of MAC" while the expected RX time
1432 	 * refers to "end of SFD".
1433 	 */
1434 	struct ieee802154_config config = {
1435 		.expected_rx_time =
1436 			convert_32bit_us_wrapped_to_64bit_ns(aCslSampleTime - PHR_DURATION_US),
1437 	};
1438 
1439 	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_EXPECTED_RX_TIME, &config);
1440 }
1441 #endif /* CONFIG_OPENTHREAD_CSL_RECEIVER */
1442 
1443 #if defined(CONFIG_OPENTHREAD_WAKEUP_COORDINATOR)
otPlatRadioEnableCst(otInstance * aInstance,uint32_t aCstPeriod,otShortAddress aShortAddr,const otExtAddress * aExtAddr)1444 otError otPlatRadioEnableCst(otInstance *aInstance, uint32_t aCstPeriod, otShortAddress aShortAddr,
1445 			     const otExtAddress *aExtAddr)
1446 {
1447 	struct ieee802154_config config;
1448 	int result;
1449 	uint8_t header_ie[OT_IE_HEADER_SIZE + OT_THREAD_IE_SIZE + OT_CST_IE_SIZE] = { 0 };
1450 	size_t index = 0;
1451 
1452 	ARG_UNUSED(aInstance);
1453 
1454 	/* Configure the CST period first to give drivers a chance to validate
1455 	 * the IE for consistency if they wish to.
1456 	 */
1457 	config.cst_period = aCstPeriod;
1458 	result = radio_api->configure(radio_dev, IEEE802154_OPENTHREAD_CONFIG_CST_PERIOD, &config);
1459 	if (result) {
1460 		return OT_ERROR_FAILED;
1461 	}
1462 
1463 	/* Configure the CST IE. */
1464 	header_ie[index++] = OT_THREAD_IE_SIZE + OT_CST_IE_SIZE;
1465 	header_ie[index++] = 0;
1466 	sys_put_le24(THREAD_IE_VENDOR_OUI, &header_ie[index]);
1467 	index += 3;
1468 	header_ie[index++] = THREAD_IE_SUBTYPE_CST;
1469 	/* Leave CST Phase empty intentionally */
1470 	index += 2;
1471 	sys_put_le16(aCstPeriod, &header_ie[index]);
1472 	index += 2;
1473 
1474 	config.ack_ie.header_ie = aCstPeriod > 0 ? (struct ieee802154_header_ie *)header_ie : NULL;
1475 	config.ack_ie.short_addr = aShortAddr;
1476 	config.ack_ie.ext_addr = aExtAddr != NULL ? aExtAddr->m8 : NULL;
1477 	config.ack_ie.purge_ie = false;
1478 
1479 	result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config);
1480 
1481 	return result ? OT_ERROR_FAILED : OT_ERROR_NONE;
1482 }
1483 
otPlatRadioUpdateCstSampleTime(otInstance * aInstance,uint32_t aCstSampleTime)1484 void otPlatRadioUpdateCstSampleTime(otInstance *aInstance, uint32_t aCstSampleTime)
1485 {
1486 	int result;
1487 
1488 	ARG_UNUSED(aInstance);
1489 
1490 	struct ieee802154_config config = {
1491 		.expected_tx_time = convert_32bit_us_wrapped_to_64bit_ns(
1492 			aCstSampleTime - PHR_DURATION_US),
1493 	};
1494 
1495 	result = radio_api->configure(radio_dev, IEEE802154_OPENTHREAD_CONFIG_EXPECTED_TX_TIME,
1496 					&config);
1497 	__ASSERT_NO_MSG(result == 0);
1498 	(void)result;
1499 }
1500 #endif /* CONFIG_OPENTHREAD_WAKEUP_COORDINATOR */
1501 
otPlatRadioGetCslAccuracy(otInstance * aInstance)1502 uint8_t otPlatRadioGetCslAccuracy(otInstance *aInstance)
1503 {
1504 	ARG_UNUSED(aInstance);
1505 
1506 	return radio_api->get_sch_acc(radio_dev);
1507 }
1508 
1509 #if defined(CONFIG_OPENTHREAD_PLATFORM_CSL_UNCERT)
otPlatRadioGetCslUncertainty(otInstance * aInstance)1510 uint8_t otPlatRadioGetCslUncertainty(otInstance *aInstance)
1511 {
1512 	ARG_UNUSED(aInstance);
1513 
1514 	return CONFIG_OPENTHREAD_PLATFORM_CSL_UNCERT;
1515 }
1516 #endif
1517 
1518 #if defined(CONFIG_OPENTHREAD_LINK_METRICS_SUBJECT)
1519 /**
1520  * Header IE format - IEEE Std. 802.15.4-2015, 7.4.2.1 && 7.4.2.2
1521  *
1522  * +---------------------------------+----------------------+
1523  * | Length    | Element ID | Type=0 |      Vendor OUI      |
1524  * +-----------+------------+--------+----------------------+
1525  * |           Bytes: 0-1            |          2-4         |
1526  * +-----------+---------------------+----------------------+
1527  * | Bits: 0-6 |    7-14    |   15   | IE_VENDOR_THREAD_OUI |
1528  * +-----------+------------+--------+----------------------|
1529  *
1530  * Thread v1.2.1 Spec., 4.11.3.4.4.6
1531  * +---------------------------------+-------------------+------------------+
1532  * |                  Vendor Specific Information                           |
1533  * +---------------------------------+-------------------+------------------+
1534  * |                5                |         6         |   7 (optional)   |
1535  * +---------------------------------+-------------------+------------------+
1536  * | IE_VENDOR_THREAD_ACK_PROBING_ID | LINK_METRIC_TOKEN | LINK_METRIC_TOKEN|
1537  * |---------------------------------|-------------------|------------------|
1538  */
set_vendor_ie_header_lm(bool lqi,bool link_margin,bool rssi,uint8_t * ie_header)1539 static void set_vendor_ie_header_lm(bool lqi, bool link_margin, bool rssi, uint8_t *ie_header)
1540 {
1541 	/* Vendor-specific IE identifier */
1542 	const uint8_t ie_vendor_id = 0x00;
1543 	/* Thread Vendor-specific ACK Probing IE subtype ID */
1544 	const uint8_t ie_vendor_thread_ack_probing_id = 0x00;
1545 	/* Thread Vendor-specific IE OUI */
1546 	const uint32_t ie_vendor_thread_oui = 0xeab89b;
1547 	/* Thread Vendor-specific ACK Probing IE RSSI value placeholder */
1548 	const uint8_t ie_vendor_thread_rssi_token = 0x01;
1549 	/* Thread Vendor-specific ACK Probing IE Link margin value placeholder */
1550 	const uint8_t ie_vendor_thread_margin_token = 0x02;
1551 	/* Thread Vendor-specific ACK Probing IE LQI value placeholder */
1552 	const uint8_t ie_vendor_thread_lqi_token = 0x03;
1553 	const uint8_t oui_size = 3;
1554 	const uint8_t sub_type = 1;
1555 	const uint8_t id_offset = 7;
1556 	const uint16_t id_mask = 0x00ff << id_offset;
1557 	const uint8_t type = 0x00;
1558 	const uint8_t type_offset = 7;
1559 	const uint8_t type_mask = 0x01 << type_offset;
1560 	const uint8_t length_mask = 0x7f;
1561 	uint8_t content_len;
1562 	uint16_t element_id = 0x0000;
1563 	uint8_t link_metrics_idx = 6;
1564 	uint8_t link_metrics_data_len = (uint8_t)lqi + (uint8_t)link_margin + (uint8_t)rssi;
1565 
1566 	__ASSERT(link_metrics_data_len <= 2, "Thread limits to 2 metrics at most");
1567 	__ASSERT(ie_header, "Invalid argument");
1568 
1569 	if (link_metrics_data_len == 0) {
1570 		ie_header[0] = 0;
1571 		return;
1572 	}
1573 
1574 	/* Set Element ID */
1575 	element_id = (((uint16_t)ie_vendor_id) << id_offset) & id_mask;
1576 	sys_put_le16(element_id, &ie_header[0]);
1577 
1578 	/* Set Length - number of octets in content field. */
1579 	content_len = oui_size + sub_type + link_metrics_data_len;
1580 	ie_header[0] = (ie_header[0] & ~length_mask) | (content_len & length_mask);
1581 
1582 	/* Set Type */
1583 	ie_header[1] = (ie_header[1] & ~type_mask) | (type & type_mask);
1584 
1585 	/* Set Vendor Oui */
1586 	sys_put_le24(ie_vendor_thread_oui, &ie_header[2]);
1587 
1588 	/* Set SubType */
1589 	ie_header[5] = ie_vendor_thread_ack_probing_id;
1590 
1591 	/* Set Link Metrics Tokens
1592 	 * TODO: Thread requires the order of requested metrics by the Link Metrics Initiator
1593 	 *       to be kept by the Link Metrics Subject in the ACKs.
1594 	 */
1595 	if (lqi) {
1596 		ie_header[link_metrics_idx++] = ie_vendor_thread_lqi_token;
1597 	}
1598 
1599 	if (link_margin) {
1600 		ie_header[link_metrics_idx++] = ie_vendor_thread_margin_token;
1601 	}
1602 
1603 	if (rssi) {
1604 		ie_header[link_metrics_idx++] = ie_vendor_thread_rssi_token;
1605 	}
1606 }
1607 
otPlatRadioConfigureEnhAckProbing(otInstance * aInstance,otLinkMetrics aLinkMetrics,const otShortAddress aShortAddress,const otExtAddress * aExtAddress)1608 otError otPlatRadioConfigureEnhAckProbing(otInstance *aInstance, otLinkMetrics aLinkMetrics,
1609 					  const otShortAddress aShortAddress,
1610 					  const otExtAddress *aExtAddress)
1611 {
1612 	struct ieee802154_config config = {
1613 		.ack_ie.short_addr = aShortAddress,
1614 		.ack_ie.ext_addr = aExtAddress->m8,
1615 	};
1616 	uint8_t header_ie_buf[OT_ACK_IE_MAX_SIZE];
1617 	int result;
1618 
1619 	ARG_UNUSED(aInstance);
1620 
1621 	set_vendor_ie_header_lm(aLinkMetrics.mLqi, aLinkMetrics.mLinkMargin,
1622 				aLinkMetrics.mRssi, header_ie_buf);
1623 	config.ack_ie.header_ie = (struct ieee802154_header_ie *)header_ie_buf;
1624 	result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config);
1625 
1626 	return result ? OT_ERROR_FAILED : OT_ERROR_NONE;
1627 }
1628 
1629 #endif /* CONFIG_OPENTHREAD_LINK_METRICS_SUBJECT */
1630 
otPlatRadioSetChannelMaxTransmitPower(otInstance * aInstance,uint8_t aChannel,int8_t aMaxPower)1631 otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aChannel,
1632 					      int8_t aMaxPower)
1633 {
1634 	ARG_UNUSED(aInstance);
1635 
1636 	if (aChannel < OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN ||
1637 	    aChannel > OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX) {
1638 		return OT_ERROR_INVALID_ARGS;
1639 	}
1640 
1641 	max_tx_power_table[aChannel - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN] = aMaxPower;
1642 
1643 	if (aChannel == channel) {
1644 		radio_api->set_txpower(radio_dev, get_transmit_power_for_channel(aChannel));
1645 	}
1646 
1647 	return OT_ERROR_NONE;
1648 }
1649