1 /*
2  * Copyright (c) 2017 - 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 /**
36  * @file
37  *   This file implements hooks for the 802.15.4 driver Core module.
38  *
39  * Hooks are used by optional driver features to modify way in which notifications are propagated
40  * through the driver.
41  *
42  */
43 
44 #include "nrf_802154_core_hooks.h"
45 
46 #include <stdbool.h>
47 
48 #include "mac_features/nrf_802154_ack_timeout.h"
49 #include "mac_features/nrf_802154_csma_ca.h"
50 #include "mac_features/nrf_802154_delayed_trx.h"
51 #include "mac_features/nrf_802154_ie_writer.h"
52 #include "mac_features/nrf_802154_security_writer.h"
53 #include "mac_features/nrf_802154_ifs.h"
54 #include "nrf_802154_encrypt.h"
55 #include "nrf_802154_config.h"
56 
57 typedef bool (* abort_hook)(nrf_802154_term_t term_lvl, req_originator_t req_orig);
58 typedef bool (* pre_transmission_hook)(uint8_t                                 * p_frame,
59                                        nrf_802154_transmit_params_t            * p_params,
60                                        nrf_802154_transmit_failed_notification_t notify_function);
61 typedef bool (* tx_setup_hook)(uint8_t                                 * p_frame,
62                                nrf_802154_transmit_params_t            * p_params,
63                                nrf_802154_transmit_failed_notification_t notify_function);
64 typedef void (* transmitted_hook)(const uint8_t * p_frame);
65 typedef bool (* tx_failed_hook)(uint8_t * p_frame, nrf_802154_tx_error_t error);
66 typedef void (* tx_ack_failed_hook)(uint8_t * p_ack, nrf_802154_tx_error_t error);
67 typedef bool (* tx_started_hook)(uint8_t * p_frame);
68 typedef void (* rx_started_hook)(const uint8_t * p_frame);
69 typedef void (* rx_ack_started_hook)(void);
70 typedef void (* tx_ack_started_hook)(uint8_t * p_ack);
71 
72 /* Since some compilers do not allow empty initializers for arrays with unspecified bounds,
73  * NULL pointer is appended to below arrays if the compiler used is not GCC. It is intentionally
74  * unused, but it prevents the arrays from being empty. GCC manages to optimize empty arrays away,
75  * so such a solution is unnecessary. */
76 
77 static const abort_hook m_abort_hooks[] =
78 {
79 #if NRF_802154_CSMA_CA_ENABLED
80     nrf_802154_csma_ca_abort,
81 #endif
82 
83 #if NRF_802154_ACK_TIMEOUT_ENABLED
84     nrf_802154_ack_timeout_abort,
85 #endif
86 
87 #if NRF_802154_DELAYED_TRX_ENABLED
88     nrf_802154_delayed_trx_abort,
89 #endif
90 
91 #if NRF_802154_IFS_ENABLED
92     nrf_802154_ifs_abort,
93 #endif
94 
95     NULL,
96 };
97 
98 static const pre_transmission_hook m_pre_transmission_hooks[] =
99 {
100 #if NRF_802154_IFS_ENABLED
101     nrf_802154_ifs_pretransmission,
102 #endif
103     NULL,
104 };
105 
106 static const tx_setup_hook m_tx_setup_hooks[] =
107 {
108 #if NRF_802154_IE_WRITER_ENABLED
109     nrf_802154_ie_writer_tx_setup,
110 #endif
111 #if NRF_802154_SECURITY_WRITER_ENABLED
112     nrf_802154_security_writer_tx_setup,
113 #endif
114 #if NRF_802154_ENCRYPTION_ENABLED
115     nrf_802154_encrypt_tx_setup,
116 #endif
117     NULL,
118 };
119 
120 static const transmitted_hook m_transmitted_hooks[] =
121 {
122 #if NRF_802154_ACK_TIMEOUT_ENABLED
123     nrf_802154_ack_timeout_transmitted_hook,
124 #endif
125 #if NRF_802154_IFS_ENABLED
126     nrf_802154_ifs_transmitted_hook,
127 #endif
128     NULL,
129 };
130 
131 static const tx_failed_hook m_tx_failed_hooks[] =
132 {
133 #if NRF_802154_CSMA_CA_ENABLED
134     nrf_802154_csma_ca_tx_failed_hook,
135 #endif
136 
137 #if NRF_802154_ACK_TIMEOUT_ENABLED
138     nrf_802154_ack_timeout_tx_failed_hook,
139 #endif
140 
141 #if NRF_802154_ENCRYPTION_ENABLED
142     nrf_802154_encrypt_tx_failed_hook,
143 #endif
144 
145     NULL,
146 };
147 
148 static const tx_ack_failed_hook m_tx_ack_failed_hooks[] =
149 {
150 #if NRF_802154_ENCRYPTION_ENABLED
151     nrf_802154_encrypt_tx_ack_failed_hook,
152 #endif
153 
154     NULL,
155 };
156 
157 static const tx_started_hook m_tx_started_hooks[] =
158 {
159 #if NRF_802154_CSMA_CA_ENABLED
160     nrf_802154_csma_ca_tx_started_hook,
161 #endif
162 
163 #if NRF_802154_ACK_TIMEOUT_ENABLED
164     nrf_802154_ack_timeout_tx_started_hook,
165 #endif
166 
167 #if NRF_802154_SECURITY_WRITER_ENABLED
168     nrf_802154_security_writer_tx_started_hook,
169 #endif
170 
171 #if NRF_802154_IE_WRITER_ENABLED
172     nrf_802154_ie_writer_tx_started_hook,
173 #endif
174 
175 #if NRF_802154_ENCRYPTION_ENABLED
176     nrf_802154_encrypt_tx_started_hook,
177 #endif
178 
179     NULL,
180 };
181 
182 static const rx_started_hook m_rx_started_hooks[] =
183 {
184 #if NRF_802154_DELAYED_TRX_ENABLED
185     nrf_802154_delayed_trx_rx_started_hook,
186 #endif
187 
188     NULL,
189 };
190 
191 static const rx_ack_started_hook m_rx_ack_started_hooks[] =
192 {
193 #if NRF_802154_ACK_TIMEOUT_ENABLED
194     nrf_802154_ack_timeout_rx_ack_started_hook,
195 #endif
196 
197     NULL,
198 };
199 
200 static const tx_ack_started_hook m_tx_ack_started_hooks[] =
201 {
202 #if NRF_802154_IE_WRITER_ENABLED
203     nrf_802154_ie_writer_tx_ack_started_hook,
204 #endif
205 
206 #if NRF_802154_ENCRYPTION_ENABLED
207     nrf_802154_encrypt_tx_ack_started_hook,
208 #endif
209 
210     NULL,
211 };
212 
nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl,req_originator_t req_orig)213 bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_t req_orig)
214 {
215     bool result = true;
216 
217     for (uint32_t i = 0; i < sizeof(m_abort_hooks) / sizeof(m_abort_hooks[0]); i++)
218     {
219         if (m_abort_hooks[i] == NULL)
220         {
221             break;
222         }
223 
224         result = m_abort_hooks[i](term_lvl, req_orig);
225 
226         if (!result)
227         {
228             break;
229         }
230     }
231 
232     return result;
233 }
234 
nrf_802154_core_hooks_pre_transmission(uint8_t * p_frame,nrf_802154_transmit_params_t * p_params,nrf_802154_transmit_failed_notification_t notify_function)235 bool nrf_802154_core_hooks_pre_transmission(
236     uint8_t                                 * p_frame,
237     nrf_802154_transmit_params_t            * p_params,
238     nrf_802154_transmit_failed_notification_t notify_function)
239 {
240     bool result = true;
241 
242     for (uint32_t i = 0; i < sizeof(m_pre_transmission_hooks) / sizeof(m_pre_transmission_hooks[0]);
243          i++)
244     {
245         if (m_pre_transmission_hooks[i] == NULL)
246         {
247             break;
248         }
249 
250         result = m_pre_transmission_hooks[i](p_frame, p_params, notify_function);
251 
252         if (!result)
253         {
254             break;
255         }
256     }
257 
258     return result;
259 }
260 
nrf_802154_core_hooks_tx_setup(uint8_t * p_frame,nrf_802154_transmit_params_t * p_params,nrf_802154_transmit_failed_notification_t notify_function)261 bool nrf_802154_core_hooks_tx_setup(
262     uint8_t                                 * p_frame,
263     nrf_802154_transmit_params_t            * p_params,
264     nrf_802154_transmit_failed_notification_t notify_function)
265 {
266     bool result = true;
267 
268     for (uint32_t i = 0; i < sizeof(m_tx_setup_hooks) / sizeof(m_tx_setup_hooks[0]);
269          i++)
270     {
271         if (m_tx_setup_hooks[i] == NULL)
272         {
273             break;
274         }
275 
276         result = m_tx_setup_hooks[i](p_frame, p_params, notify_function);
277 
278         if (!result)
279         {
280             break;
281         }
282     }
283 
284     return result;
285 }
286 
nrf_802154_core_hooks_transmitted(const uint8_t * p_frame)287 void nrf_802154_core_hooks_transmitted(const uint8_t * p_frame)
288 {
289     for (uint32_t i = 0; i < sizeof(m_transmitted_hooks) / sizeof(m_transmitted_hooks[0]); i++)
290     {
291         if (m_transmitted_hooks[i] == NULL)
292         {
293             break;
294         }
295 
296         m_transmitted_hooks[i](p_frame);
297     }
298 }
299 
nrf_802154_core_hooks_tx_failed(uint8_t * p_frame,nrf_802154_tx_error_t error)300 bool nrf_802154_core_hooks_tx_failed(uint8_t * p_frame, nrf_802154_tx_error_t error)
301 {
302     bool result = true;
303 
304     for (uint32_t i = 0; i < sizeof(m_tx_failed_hooks) / sizeof(m_tx_failed_hooks[0]); i++)
305     {
306         if (m_tx_failed_hooks[i] == NULL)
307         {
308             break;
309         }
310 
311         result = m_tx_failed_hooks[i](p_frame, error);
312 
313         if (!result)
314         {
315             break;
316         }
317     }
318 
319     return result;
320 }
321 
nrf_802154_core_hooks_tx_ack_failed(uint8_t * p_ack,nrf_802154_tx_error_t error)322 void nrf_802154_core_hooks_tx_ack_failed(uint8_t * p_ack, nrf_802154_tx_error_t error)
323 {
324     for (uint32_t i = 0; i < sizeof(m_tx_ack_failed_hooks) / sizeof(m_tx_ack_failed_hooks[0]); i++)
325     {
326         if (m_tx_ack_failed_hooks[i] == NULL)
327         {
328             break;
329         }
330 
331         m_tx_ack_failed_hooks[i](p_ack, error);
332     }
333 }
334 
nrf_802154_core_hooks_tx_started(uint8_t * p_frame)335 bool nrf_802154_core_hooks_tx_started(uint8_t * p_frame)
336 {
337     bool result = true;
338 
339     for (uint32_t i = 0; i < sizeof(m_tx_started_hooks) / sizeof(m_tx_started_hooks[0]); i++)
340     {
341         if (m_tx_started_hooks[i] == NULL)
342         {
343             break;
344         }
345 
346         result = m_tx_started_hooks[i](p_frame);
347 
348         if (!result)
349         {
350             break;
351         }
352     }
353 
354     return result;
355 }
356 
nrf_802154_core_hooks_rx_started(const uint8_t * p_frame)357 void nrf_802154_core_hooks_rx_started(const uint8_t * p_frame)
358 {
359     for (uint32_t i = 0; i < sizeof(m_rx_started_hooks) / sizeof(m_rx_started_hooks[0]); i++)
360     {
361         if (m_rx_started_hooks[i] == NULL)
362         {
363             break;
364         }
365 
366         m_rx_started_hooks[i](p_frame);
367     }
368 }
369 
nrf_802154_core_hooks_rx_ack_started(void)370 void nrf_802154_core_hooks_rx_ack_started(void)
371 {
372     for (uint32_t i = 0; i < sizeof(m_rx_ack_started_hooks) / sizeof(m_rx_ack_started_hooks[0]);
373          i++)
374     {
375         if (m_rx_ack_started_hooks[i] == NULL)
376         {
377             break;
378         }
379 
380         m_rx_ack_started_hooks[i]();
381     }
382 }
383 
nrf_802154_core_hooks_tx_ack_started(uint8_t * p_ack)384 void nrf_802154_core_hooks_tx_ack_started(uint8_t * p_ack)
385 {
386     for (uint32_t i = 0; i < sizeof(m_tx_ack_started_hooks) / sizeof(m_tx_ack_started_hooks[0]);
387          i++)
388     {
389         if (m_tx_ack_started_hooks[i] == NULL)
390         {
391             break;
392         }
393 
394         m_tx_ack_started_hooks[i](p_ack);
395     }
396 }
397