1 /*
2  * Copyright (c) 2020 - 2023, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 #include <assert.h>
36 #include <stddef.h>
37 #include <string.h>
38 
39 #ifndef TEST
40 #include <nrfx.h>
41 #endif
42 
43 #include "../spinel_base/spinel.h"
44 #include "nrf_802154_spinel.h"
45 #include "nrf_802154_spinel_datatypes.h"
46 #include "nrf_802154_spinel_dec.h"
47 #include "nrf_802154_spinel_response_notifier.h"
48 #include "nrf_802154_spinel_log.h"
49 #include "nrf_802154_serialization_error.h"
50 #include "nrf_802154_buffer_mgr_dst.h"
51 #include "nrf_802154_buffer_mgr_src.h"
52 
53 #include "nrf_802154.h"
54 #include "nrf_802154_config.h"
55 
56 /**
57  * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_DONE.
58  *
59  * @param[in]  p_property_data    Pointer to a buffer that contains data to be decoded.
60  * @param[in]  property_data_len  Size of the @ref p_data buffer.
61  */
spinel_decode_prop_nrf_802154_cca_done(const void * p_property_data,size_t property_data_len)62 static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_cca_done(
63     const void * p_property_data,
64     size_t       property_data_len)
65 {
66     bool channel_free = false;
67 
68     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
69                                                 property_data_len,
70                                                 SPINEL_DATATYPE_NRF_802154_CCA_DONE,
71                                                 &channel_free);
72 
73     if (siz < 0)
74     {
75         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
76     }
77 
78     nrf_802154_cca_done(channel_free);
79 
80     return NRF_802154_SERIALIZATION_ERROR_OK;
81 }
82 
83 /**
84  * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_FAILED.
85  *
86  * @param[in]  p_property_data    Pointer to a buffer that contains data to be decoded.
87  * @param[in]  property_data_len  Size of the @ref p_data buffer.
88  */
spinel_decode_prop_nrf_802154_cca_failed(const void * p_property_data,size_t property_data_len)89 static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_cca_failed(
90     const void * p_property_data,
91     size_t       property_data_len)
92 {
93     nrf_802154_cca_error_t err = NRF_802154_CCA_ERROR_ABORTED;
94 
95     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
96                                                 property_data_len,
97                                                 SPINEL_DATATYPE_NRF_802154_CCA_FAILED,
98                                                 &err);
99 
100     if (siz < 0)
101     {
102         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
103     }
104 
105     nrf_802154_cca_failed(err);
106 
107     return NRF_802154_SERIALIZATION_ERROR_OK;
108 }
109 
110 /**
111  * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ENERGY_DETECTED.
112  *
113  * @param[in]  p_property_data    Pointer to a buffer that contains data to be decoded.
114  * @param[in]  property_data_len  Size of the @ref p_data buffer.
115  */
spinel_decode_prop_nrf_802154_energy_detected(const void * p_property_data,size_t property_data_len)116 static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_energy_detected(
117     const void * p_property_data,
118     size_t       property_data_len)
119 {
120     uint8_t result;
121 
122     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
123                                                 property_data_len,
124                                                 SPINEL_DATATYPE_NRF_802154_ENERGY_DETECTED,
125                                                 &result);
126 
127     if (siz < 0)
128     {
129         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
130     }
131 
132     nrf_802154_energy_detected(result);
133 
134     return NRF_802154_SERIALIZATION_ERROR_OK;
135 }
136 
137 /**
138  * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ENERGY_DETECTION_FAILED.
139  *
140  * @param[in]  p_property_data    Pointer to a buffer that contains data to be decoded.
141  * @param[in]  property_data_len  Size of the @ref p_data buffer.
142  */
spinel_decode_prop_nrf_802154_energy_detection_failed(const void * p_property_data,size_t property_data_len)143 static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_energy_detection_failed(
144     const void * p_property_data,
145     size_t       property_data_len)
146 {
147     nrf_802154_ed_error_t err = NRF_802154_CCA_ERROR_ABORTED;
148 
149     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
150                                                 property_data_len,
151                                                 SPINEL_DATATYPE_NRF_802154_ENERGY_DETECTION_FAILED,
152                                                 &err);
153 
154     if (siz < 0)
155     {
156         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
157     }
158 
159     nrf_802154_energy_detection_failed(err);
160 
161     return NRF_802154_SERIALIZATION_ERROR_OK;
162 }
163 
164 /**
165  * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVED_TIMESTAMP_RAW.
166  *
167  * @param[in]  p_property_data    Pointer to a buffer that contains data to be decoded.
168  * @param[in]  property_data_len  Size of the @ref p_data buffer.
169  */
spinel_decode_prop_nrf_802154_received_timestamp_raw(const void * p_property_data,size_t property_data_len)170 static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_received_timestamp_raw(
171     const void * p_property_data,
172     size_t       property_data_len)
173 {
174     uint32_t remote_frame_handle;
175     void   * p_frame;
176     size_t   frame_hdata_len;
177     int8_t   power;
178     uint8_t  lqi;
179     uint64_t timestamp;
180     void   * p_local_ptr;
181 
182     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
183                                                 property_data_len,
184                                                 SPINEL_DATATYPE_NRF_802154_RECEIVED_TIMESTAMP_RAW,
185                                                 NRF_802154_HDATA_DECODE(remote_frame_handle,
186                                                                         p_frame,
187                                                                         frame_hdata_len),
188                                                 &power,
189                                                 &lqi,
190                                                 &timestamp);
191 
192     if (siz < 0)
193     {
194         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
195     }
196 
197     // Associate the remote frame handle with a local pointer
198     // and copy the buffer content there
199     bool frame_added = nrf_802154_buffer_mgr_dst_add(
200         nrf_802154_spinel_dst_buffer_mgr_get(),
201         remote_frame_handle,
202         p_frame,
203         NRF_802154_DATA_LEN_FROM_HDATA_LEN(frame_hdata_len),
204         &p_local_ptr);
205 
206     if (!frame_added)
207     {
208         return NRF_802154_SERIALIZATION_ERROR_NO_MEMORY;
209     }
210 
211     nrf_802154_received_timestamp_raw(p_local_ptr, power, lqi, timestamp);
212 
213     return NRF_802154_SERIALIZATION_ERROR_OK;
214 }
215 
216 /**
217  * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_FAILED
218  *
219  * @param[in]  p_property_data    Pointer to a buffer that contains data to be decoded.
220  * @param[in]  property_data_len  Size of the @ref p_data buffer.
221  */
spinel_decode_prop_nrf_802154_receive_failed(const void * p_property_data,size_t property_data_len)222 static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_receive_failed(
223     const void * p_property_data,
224     size_t       property_data_len)
225 {
226     uint8_t  error;
227     uint32_t id;
228 
229     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
230                                                 property_data_len,
231                                                 SPINEL_DATATYPE_NRF_802154_RECEIVE_FAILED,
232                                                 &error,
233                                                 &id);
234 
235     if (siz < 0)
236     {
237         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
238     }
239 
240     nrf_802154_receive_failed(error, id);
241 
242     return NRF_802154_SERIALIZATION_ERROR_OK;
243 }
244 
245 /**
246  * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TX_ACK_STARTED
247  *
248  * @param[in]  p_property_data    Pointer to a buffer that contains data to be decoded.
249  * @param[in]  property_data_len  Size of the @ref p_data buffer.
250  */
spinel_decode_prop_nrf_802154_tx_ack_started(const void * p_property_data,size_t property_data_len)251 static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_tx_ack_started(
252     const void * p_property_data,
253     size_t       property_data_len)
254 {
255     const uint8_t * p_tx_ack;
256     size_t          tx_ack_len;
257 
258     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
259                                                 property_data_len,
260                                                 SPINEL_DATATYPE_NRF_802154_TX_ACK_STARTED,
261                                                 &p_tx_ack,
262                                                 &tx_ack_len);
263 
264     if ((siz < 0) || (p_tx_ack == NULL) || (p_tx_ack[0] != tx_ack_len))
265     {
266         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
267     }
268 
269     nrf_802154_tx_ack_started(p_tx_ack);
270 
271     return NRF_802154_SERIALIZATION_ERROR_OK;
272 }
273 
274 /**
275  * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMITTED_RAW.
276  *
277  * @param[in]  p_property_data    Pointer to a buffer that contains data to be decoded.
278  * @param[in]  property_data_len  Size of the @ref p_data buffer.
279  */
spinel_decode_prop_nrf_802154_transmitted_raw(const void * p_property_data,size_t property_data_len)280 static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmitted_raw(
281     const void * p_property_data,
282     size_t       property_data_len)
283 {
284     uint32_t                            frame_handle;
285     uint32_t                            remote_ack_handle;
286     void                              * p_ack;
287     size_t                              ack_hdata_len;
288     size_t                              frame_hdata_len;
289     void                              * p_local_frame;
290     void                              * p_serialized_frame;
291     void                              * p_ack_local_ptr = NULL;
292     nrf_802154_transmit_done_metadata_t metadata        = {0};
293 
294     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
295                                                 property_data_len,
296                                                 SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW,
297                                                 NRF_802154_TRANSMITTED_RAW_DECODE(frame_handle,
298                                                                                   p_serialized_frame,
299                                                                                   frame_hdata_len,
300                                                                                   metadata,
301                                                                                   remote_ack_handle,
302                                                                                   ack_hdata_len));
303 
304     p_ack = metadata.data.transmitted.p_ack;
305 
306     if (siz < 0)
307     {
308         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
309     }
310 
311     // Search for the original frame buffer based on the provided handle
312     bool frame_found = nrf_802154_buffer_mgr_src_search_by_buffer_handle(
313         nrf_802154_spinel_src_buffer_mgr_get(),
314         frame_handle,
315         &p_local_frame);
316 
317     if (!frame_found)
318     {
319         // The frame is expected to be found, because it's the application that requested
320         // to transmit it in the first place. Return error if it has not been found
321         return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER;
322     }
323 
324     // Handle the Ack
325     if (NRF_802154_DATA_LEN_FROM_HDATA_LEN(ack_hdata_len) == 0)
326     {
327         // Length equal to 0 indicates that p_ack was originally a NULL pointer
328         // Do not handle the Ack
329     }
330     else
331     {
332         // Associate the remote Ack handle with a local pointer and copy the buffer content there
333         bool ack_added = nrf_802154_buffer_mgr_dst_add(
334             nrf_802154_spinel_dst_buffer_mgr_get(),
335             remote_ack_handle,
336             p_ack,
337             NRF_802154_DATA_LEN_FROM_HDATA_LEN(ack_hdata_len),
338             &p_ack_local_ptr);
339 
340         if (!ack_added)
341         {
342             return NRF_802154_SERIALIZATION_ERROR_NO_MEMORY;
343         }
344     }
345 
346     frame_found = nrf_802154_buffer_mgr_src_remove_by_buffer_handle(
347         nrf_802154_spinel_src_buffer_mgr_get(),
348         frame_handle);
349 
350     if (!frame_found)
351     {
352         return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER;
353     }
354 
355     memcpy(p_local_frame,
356            p_serialized_frame,
357            NRF_802154_DATA_LEN_FROM_HDATA_LEN(frame_hdata_len));
358 
359     // Overwrite ACK frame pointer with a newly allocated one.
360     metadata.data.transmitted.p_ack = p_ack_local_ptr;
361     nrf_802154_transmitted_raw(p_local_frame, &metadata);
362 
363     return NRF_802154_SERIALIZATION_ERROR_OK;
364 }
365 
366 /**
367  * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED.
368  *
369  * @param[in]  p_property_data    Pointer to a buffer that contains data to be decoded.
370  * @param[in]  property_data_len  Size of the @ref p_data buffer.
371  */
spinel_decode_prop_nrf_802154_transmit_failed(const void * p_property_data,size_t property_data_len)372 static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_failed(
373     const void * p_property_data,
374     size_t       property_data_len)
375 {
376     uint32_t                            frame_handle;
377     nrf_802154_tx_error_t               tx_error;
378     void                              * p_serialized_frame;
379     void                              * p_local_frame;
380     size_t                              frame_hdata_len;
381     nrf_802154_transmit_done_metadata_t metadata = {0};
382 
383     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
384                                                 property_data_len,
385                                                 SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED,
386                                                 NRF_802154_TRANSMIT_FAILED_DECODE(frame_handle,
387                                                                                   p_serialized_frame,
388                                                                                   frame_hdata_len,
389                                                                                   tx_error,
390                                                                                   metadata));
391 
392     if (siz < 0)
393     {
394         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
395     }
396 
397     // Search for the original frame buffer based on the provided handle
398     bool frame_found = nrf_802154_buffer_mgr_src_search_by_buffer_handle(
399         nrf_802154_spinel_src_buffer_mgr_get(),
400         frame_handle,
401         &p_local_frame);
402 
403     if (!frame_found)
404     {
405         // The frame is expected to be found, because it's the application that requested
406         // to transmit it in the first place. Return error if it has not been found
407         return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER;
408     }
409 
410     frame_found = nrf_802154_buffer_mgr_src_remove_by_buffer_handle(
411         nrf_802154_spinel_src_buffer_mgr_get(),
412         frame_handle);
413 
414     if (!frame_found)
415     {
416         return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER;
417     }
418 
419     memcpy(p_local_frame,
420            p_serialized_frame,
421            NRF_802154_DATA_LEN_FROM_HDATA_LEN(frame_hdata_len));
422 
423     nrf_802154_transmit_failed(p_local_frame, tx_error, &metadata);
424 
425     return NRF_802154_SERIALIZATION_ERROR_OK;
426 }
427 
nrf_802154_spinel_decode_prop_last_status(const void * p_property_data,size_t property_data_len,spinel_status_t * status)428 nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_last_status(
429     const void      * p_property_data,
430     size_t            property_data_len,
431     spinel_status_t * status)
432 {
433     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
434                                                 property_data_len,
435                                                 SPINEL_DATATYPE_SPINEL_PROP_LAST_STATUS,
436                                                 status);
437 
438     return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
439             NRF_802154_SERIALIZATION_ERROR_OK);
440 }
441 
nrf_802154_spinel_decode_prop_generic_bool(const void * p_property_data,size_t property_data_len,bool * p_bool_response)442 nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_generic_bool(
443     const void * p_property_data,
444     size_t       property_data_len,
445     bool       * p_bool_response)
446 {
447     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
448                                                 property_data_len,
449                                                 SPINEL_DATATYPE_BOOL_S,
450                                                 p_bool_response);
451 
452     return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
453             NRF_802154_SERIALIZATION_ERROR_OK);
454 }
455 
nrf_802154_spinel_decode_prop_generic_uint8(const void * p_property_data,size_t property_data_len,uint8_t * p_uint8_response)456 nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_generic_uint8(
457     const void * p_property_data,
458     size_t       property_data_len,
459     uint8_t    * p_uint8_response)
460 {
461     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
462                                                 property_data_len,
463                                                 SPINEL_DATATYPE_UINT8_S,
464                                                 p_uint8_response);
465 
466     return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
467             NRF_802154_SERIALIZATION_ERROR_OK);
468 }
469 
nrf_802154_spinel_decode_prop_generic_uint16(const void * p_property_data,size_t property_data_len,uint16_t * p_uint16_response)470 nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_generic_uint16(
471     const void * p_property_data,
472     size_t       property_data_len,
473     uint16_t   * p_uint16_response)
474 {
475     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
476                                                 property_data_len,
477                                                 SPINEL_DATATYPE_UINT16_S,
478                                                 p_uint16_response);
479 
480     return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
481             NRF_802154_SERIALIZATION_ERROR_OK);
482 }
483 
nrf_802154_spinel_decode_prop_nrf_802154_tx_power_get_ret(const void * p_property_data,size_t property_data_len,int8_t * p_power)484 nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_tx_power_get_ret(
485     const void * p_property_data,
486     size_t       property_data_len,
487     int8_t     * p_power)
488 {
489     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
490                                                 property_data_len,
491                                                 SPINEL_DATATYPE_NRF_802154_TX_POWER_GET_RET,
492                                                 p_power);
493 
494     return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
495             NRF_802154_SERIALIZATION_ERROR_OK);
496 }
497 
nrf_802154_spinel_decode_prop_nrf_802154_capabilities_get_ret(const void * p_property_data,size_t property_data_len,nrf_802154_capabilities_t * p_capabilities)498 nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_capabilities_get_ret(
499     const void                * p_property_data,
500     size_t                      property_data_len,
501     nrf_802154_capabilities_t * p_capabilities)
502 {
503     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
504                                                 property_data_len,
505                                                 SPINEL_DATATYPE_NRF_802154_CAPABILITIES_GET_RET,
506                                                 p_capabilities);
507 
508     return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
509             NRF_802154_SERIALIZATION_ERROR_OK);
510 }
511 
nrf_802154_spinel_decode_prop_nrf_802154_time_get_ret(const void * p_property_data,size_t property_data_len,uint64_t * p_time)512 nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_time_get_ret(
513     const void * p_property_data,
514     size_t       property_data_len,
515     uint64_t   * p_time)
516 {
517     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
518                                                 property_data_len,
519                                                 SPINEL_DATATYPE_NRF_802154_TIME_GET_RET,
520                                                 p_time);
521 
522     return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
523             NRF_802154_SERIALIZATION_ERROR_OK);
524 }
525 
nrf_802154_spinel_decode_prop_nrf_802154_cca_cfg_get_ret(const void * p_property_data,size_t property_data_len,nrf_802154_cca_cfg_t * p_cfg)526 nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_cca_cfg_get_ret(
527     const void           * p_property_data,
528     size_t                 property_data_len,
529     nrf_802154_cca_cfg_t * p_cfg)
530 {
531     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
532                                                 property_data_len,
533                                                 SPINEL_DATATYPE_NRF_802154_CCA_CFG_GET_RET,
534                                                 NRF_802154_CCA_CFG_DECODE(*p_cfg));
535 
536     return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
537             NRF_802154_SERIALIZATION_ERROR_OK);
538 }
539 
nrf_802154_spinel_decode_prop_nrf_802154_stat_timestamps_get_ret(const void * p_property_data,size_t property_data_len,nrf_802154_stat_timestamps_t * p_stat_timestamps)540 nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_stat_timestamps_get_ret(
541     const void                   * p_property_data,
542     size_t                         property_data_len,
543     nrf_802154_stat_timestamps_t * p_stat_timestamps)
544 {
545     spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
546                                                 property_data_len,
547                                                 SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_GET_RET,
548                                                 NRF_802154_STAT_TIMESTAMPS_DECODE(
549                                                     *p_stat_timestamps));
550 
551     return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
552             NRF_802154_SERIALIZATION_ERROR_OK);
553 }
554 
nrf_802154_spinel_decode_cmd_prop_value_is(const void * p_cmd_data,size_t cmd_data_len)555 nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_is(
556     const void * p_cmd_data,
557     size_t       cmd_data_len)
558 {
559     spinel_prop_key_t property;
560     const void      * p_property_data;
561     size_t            property_data_len;
562     spinel_ssize_t    siz;
563 
564     siz = spinel_datatype_unpack(p_cmd_data,
565                                  cmd_data_len,
566                                  SPINEL_DATATYPE_UINT_PACKED_S SPINEL_DATATYPE_DATA_S,
567                                  &property,
568                                  &p_property_data,
569                                  &property_data_len);
570 
571     if (siz < 0)
572     {
573         return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
574     }
575 
576     switch (property)
577     {
578         case SPINEL_PROP_LAST_STATUS:
579         // fall through
580         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SLEEP:
581         // fall through
582         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SLEEP_IF_IDLE:
583         // fall through
584         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE:
585         // fall through
586         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT:
587         // fall through
588         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT_CANCEL:
589         // fall through
590         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA:
591             // fall through
592 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
593         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CONTINUOUS_CARRIER:
594         // fall through
595         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_MODULATED_CARRIER:
596             // fall through
597 #endif
598         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ENERGY_DETECTION:
599         // fall through
600         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TX_POWER_GET:
601         // fall through
602         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CHANNEL_GET:
603         // fall through
604         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CAPABILITIES_GET:
605         // fall through
606         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET:
607         // fall through
608         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_GET:
609         // fall through
610         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_STORE:
611         // fall through
612         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_REMOVE:
613         // fall through
614         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PENDING_BIT_FOR_ADDR_SET:
615         // fall through
616         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PENDING_BIT_FOR_ADDR_CLEAR:
617         // fall through
618         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ACK_DATA_SET:
619         // fall through
620         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ACK_DATA_CLEAR:
621         // fall through
622         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW:
623         // fall through
624         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW_AT:
625         // fall through
626         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_AT_CANCEL:
627             // fall through
628 #if NRF_802154_CSMA_CA_ENABLED
629         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_CSMA_CA_RAW:
630         // fall through
631         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_SET:
632         // fall through
633         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_GET:
634         // fall through
635         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_SET:
636         // fall through
637         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_GET:
638         // fall through
639         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_SET:
640         // fall through
641         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET:
642             // fall through
643 #endif // NRF_802154_CSMA_CA_ENABLED
644 #if NRF_802154_TEST_MODES_ENABLED
645         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TEST_MODE_CSMACA_BACKOFF_SET:
646         // fall through
647         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TEST_MODE_CSMACA_BACKOFF_GET:
648             // fall through
649 #endif // NRF_802154_TEST_MODES_ENABLED
650 #if NRF_802154_IFS_ENABLED
651         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_IFS_MODE_SET:
652         // fall through
653         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_IFS_MODE_GET:
654         // fall through
655         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_IFS_MIN_SIFS_PERIOD_GET:
656         // fall through
657         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_IFS_MIN_LIFS_PERIOD_GET:
658             // fall through
659 #endif // NRF_802154_IFS_ENABLED
660         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_STAT_TIMESTAMPS_GET:
661             nrf_802154_spinel_response_notifier_property_notify(property,
662                                                                 p_property_data,
663                                                                 property_data_len);
664             return NRF_802154_SERIALIZATION_ERROR_OK;
665 
666         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_DONE:
667             return spinel_decode_prop_nrf_802154_cca_done(p_property_data,
668                                                           property_data_len);
669 
670         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_FAILED:
671             return spinel_decode_prop_nrf_802154_cca_failed(p_property_data,
672                                                             property_data_len);
673 
674         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ENERGY_DETECTED:
675             return spinel_decode_prop_nrf_802154_energy_detected(p_property_data,
676                                                                  property_data_len);
677 
678         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ENERGY_DETECTION_FAILED:
679             return spinel_decode_prop_nrf_802154_energy_detection_failed(p_property_data,
680                                                                          property_data_len);
681 
682         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVED_TIMESTAMP_RAW:
683             return spinel_decode_prop_nrf_802154_received_timestamp_raw(p_property_data,
684                                                                         property_data_len);
685 
686         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMITTED_RAW:
687             return spinel_decode_prop_nrf_802154_transmitted_raw(p_property_data,
688                                                                  property_data_len);
689 
690         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_FAILED:
691             return spinel_decode_prop_nrf_802154_transmit_failed(p_property_data,
692                                                                  property_data_len);
693 
694         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_FAILED:
695             return spinel_decode_prop_nrf_802154_receive_failed(p_property_data,
696                                                                 property_data_len);
697 
698         case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TX_ACK_STARTED:
699             return spinel_decode_prop_nrf_802154_tx_ack_started(p_property_data,
700                                                                 property_data_len);
701 
702         default:
703             NRF_802154_SPINEL_LOG_RAW("Unsupported property: %s(%u)\n",
704                                       spinel_prop_key_to_cstr(property),
705                                       property);
706             return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
707     }
708 }
709 
nrf_802154_spinel_dispatch_cmd(spinel_command_t cmd,const void * p_cmd_data,size_t cmd_data_len)710 nrf_802154_ser_err_t nrf_802154_spinel_dispatch_cmd(spinel_command_t cmd,
711                                                     const void     * p_cmd_data,
712                                                     size_t           cmd_data_len)
713 {
714     switch (cmd)
715     {
716         case SPINEL_CMD_PROP_VALUE_IS:
717             return nrf_802154_spinel_decode_cmd_prop_value_is(p_cmd_data, cmd_data_len);
718 
719         default:
720             NRF_802154_SPINEL_LOG_RAW("Unsupported command: %s(%u)\n",
721                                       spinel_command_to_cstr(cmd),
722                                       cmd);
723             return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
724     }
725 }
726 
727 #ifndef TEST
nrf_802154_received_timestamp_raw(uint8_t * p_data,int8_t rssi,uint8_t lqi,uint64_t timestamp)728 __WEAK void nrf_802154_received_timestamp_raw(uint8_t * p_data,
729                                               int8_t    rssi,
730                                               uint8_t   lqi,
731                                               uint64_t  timestamp)
732 {
733     (void)p_data;
734     (void)rssi;
735     (void)lqi;
736     (void)timestamp;
737     // Intentionally empty
738 }
739 
nrf_802154_receive_failed(nrf_802154_rx_error_t error,uint32_t id)740 __WEAK void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id)
741 {
742     (void)error;
743     (void)id;
744     // Intentionally empty
745 }
746 
nrf_802154_transmitted_raw(uint8_t * p_data,const nrf_802154_transmit_done_metadata_t * p_metadata)747 __WEAK void nrf_802154_transmitted_raw(uint8_t                                   * p_data,
748                                        const nrf_802154_transmit_done_metadata_t * p_metadata)
749 {
750     (void)p_data;
751     (void)p_metadata;
752     // Intentionally empty
753 }
754 
nrf_802154_transmit_failed(uint8_t * p_data,nrf_802154_tx_error_t error,const nrf_802154_transmit_done_metadata_t * p_metadata)755 __WEAK void nrf_802154_transmit_failed(uint8_t                                   * p_data,
756                                        nrf_802154_tx_error_t                       error,
757                                        const nrf_802154_transmit_done_metadata_t * p_metadata)
758 {
759     (void)p_data;
760     (void)error;
761     (void)p_metadata;
762     // Intentionally empty
763 }
764 
nrf_802154_tx_ack_started(const uint8_t * p_data)765 __WEAK void nrf_802154_tx_ack_started(const uint8_t * p_data)
766 {
767     (void)p_data;
768     // Intentionally empty
769 }
770 
nrf_802154_cca_done(bool channel_free)771 __WEAK void nrf_802154_cca_done(bool channel_free)
772 {
773     (void)channel_free;
774     // Intentionally empty
775 }
776 
nrf_802154_cca_failed(nrf_802154_cca_error_t error)777 __WEAK void nrf_802154_cca_failed(nrf_802154_cca_error_t error)
778 {
779     (void)error;
780     // Intentionally empty
781 }
782 
nrf_802154_energy_detected(uint8_t ed_level)783 __WEAK void nrf_802154_energy_detected(uint8_t ed_level)
784 {
785     (void)ed_level;
786     // Intentionally empty
787 }
788 
nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error)789 __WEAK void nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error)
790 {
791     (void)error;
792     // Intentionally empty
793 }
794 
795 #endif // TEST
796