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