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