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