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