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