1 /*
2 * Copyright (c) 2018, 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 procedures to set pending bit and 802.15.4-2015 information
38 * elements in nRF 802.15.4 radio driver.
39 *
40 */
41
42 #include "nrf_802154_ack_data.h"
43
44 #include "nrf_802154_assert.h"
45 #include <string.h>
46
47 #include "mac_features/nrf_802154_frame_parser.h"
48 #include "nrf_802154_config.h"
49 #include "nrf_802154_const.h"
50
51 /// Maximum number of Short Addresses of nodes for which there is ACK data to set.
52 #define NUM_SHORT_ADDRESSES NRF_802154_PENDING_SHORT_ADDRESSES
53 /// Maximum number of Extended Addresses of nodes for which there is ACK data to set.
54 #define NUM_EXTENDED_ADDRESSES NRF_802154_PENDING_EXTENDED_ADDRESSES
55
56 /// Structure representing pending bit setting variables.
57 typedef struct
58 {
59 bool enabled; /// If setting pending bit is enabled.
60 uint8_t short_addr[NUM_SHORT_ADDRESSES][SHORT_ADDRESS_SIZE]; /// Array of short addresses of nodes for which there is pending data in the buffer.
61 uint8_t extended_addr[NUM_EXTENDED_ADDRESSES][EXTENDED_ADDRESS_SIZE]; /// Array of extended addresses of nodes for which there is pending data in the buffer.
62 uint32_t num_of_short_addr; /// Current number of short addresses of nodes for which there is pending data in the buffer.
63 uint32_t num_of_ext_addr; /// Current number of extended addresses of nodes for which there is pending data in the buffer.
64 } pending_bit_arrays_t;
65
66 // Structure representing a single IE record.
67 typedef struct
68 {
69 uint8_t p_data[NRF_802154_MAX_ACK_IE_SIZE]; /// Pointer to IE data buffer.
70 uint8_t len; /// Length of the buffer.
71 } ie_data_t;
72
73 // Structure representing IE records sent in an ACK message to a given short address.
74 typedef struct
75 {
76 uint8_t addr[SHORT_ADDRESS_SIZE]; /// Short address of peer node.
77 ie_data_t ie_data; /// Pointer to IE records.
78 } ack_short_ie_data_t;
79
80 // Structure representing IE records sent in an ACK message to a given extended address.
81 typedef struct
82 {
83 uint8_t addr[EXTENDED_ADDRESS_SIZE]; /// Extended address of peer node.
84 ie_data_t ie_data; /// Pointer to IE records.
85 } ack_ext_ie_data_t;
86
87 // Structure representing IE data setting variables.
88 typedef struct
89 {
90 ack_short_ie_data_t short_data[NUM_SHORT_ADDRESSES]; /// Array of short addresses and IE records sent to these addresses.
91 ack_ext_ie_data_t ext_data[NUM_EXTENDED_ADDRESSES]; /// Array of extended addresses and IE records sent to these addresses.
92 uint32_t num_of_short_data; /// Current number of short addresses stored in @p short_data.
93 uint32_t num_of_ext_data; /// Current number of extended addresses stored in @p ext_data.
94 } ie_arrays_t;
95
96 // TODO: Combine below arrays to perform binary search only once per Ack generation.
97 static pending_bit_arrays_t m_pending_bit;
98 static ie_arrays_t m_ie;
99 static nrf_802154_src_addr_match_t m_src_matching_method;
100
101 /***************************************************************************************************
102 * @section Array handling helper functions
103 **************************************************************************************************/
104
105 /**
106 * @brief Compare two extended addresses.
107 *
108 * @param[in] p_first_addr Pointer to a first address that should be compared.
109 * @param[in] p_second_addr Pointer to a second address that should be compared.
110 *
111 * @retval -1 First address is less than the second address.
112 * @retval 0 First address is equal to the second address.
113 * @retval 1 First address is greater than the second address.
114 */
extended_addr_compare(const uint8_t * p_first_addr,const uint8_t * p_second_addr)115 static int8_t extended_addr_compare(const uint8_t * p_first_addr, const uint8_t * p_second_addr)
116 {
117 uint32_t first_addr;
118 uint32_t second_addr;
119
120 // Compare extended address in two steps to prevent unaligned access error.
121 for (uint32_t i = 0; i < EXTENDED_ADDRESS_SIZE / sizeof(uint32_t); i++)
122 {
123 first_addr = *(uint32_t *)(p_first_addr + (i * sizeof(uint32_t)));
124 second_addr = *(uint32_t *)(p_second_addr + (i * sizeof(uint32_t)));
125
126 if (first_addr < second_addr)
127 {
128 return -1;
129 }
130 else if (first_addr > second_addr)
131 {
132 return 1;
133 }
134 }
135
136 return 0;
137 }
138
139 /**
140 * @brief Compare two short addresses.
141 *
142 * @param[in] p_first_addr Pointer to a first address that should be compared.
143 * @param[in] p_second_addr Pointer to a second address that should be compared.
144 *
145 * @retval -1 First address is less than the second address.
146 * @retval 0 First address is equal to the second address.
147 * @retval 1 First address is greater than the second address.
148 */
short_addr_compare(const uint8_t * p_first_addr,const uint8_t * p_second_addr)149 static int8_t short_addr_compare(const uint8_t * p_first_addr, const uint8_t * p_second_addr)
150 {
151 uint16_t first_addr = *(uint16_t *)(p_first_addr);
152 uint16_t second_addr = *(uint16_t *)(p_second_addr);
153
154 if (first_addr < second_addr)
155 {
156 return -1;
157 }
158 else if (first_addr > second_addr)
159 {
160 return 1;
161 }
162 else
163 {
164 return 0;
165 }
166 }
167
168 /**
169 * @brief Compare two addresses.
170 *
171 * @param[in] p_first_addr Pointer to a first address that should be compared.
172 * @param[in] p_second_addr Pointer to a second address that should be compared.
173 * @param[in] extended Indication if @p p_first_addr and @p p_second_addr are extended or short addresses.
174 *
175 * @retval -1 First address is less than the second address.
176 * @retval 0 First address is equal to the second address.
177 * @retval 1 First address is greater than the second address.
178 */
addr_compare(const uint8_t * p_first_addr,const uint8_t * p_second_addr,bool extended)179 static int8_t addr_compare(const uint8_t * p_first_addr,
180 const uint8_t * p_second_addr,
181 bool extended)
182 {
183 if (extended)
184 {
185 return extended_addr_compare(p_first_addr, p_second_addr);
186 }
187 else
188 {
189 return short_addr_compare(p_first_addr, p_second_addr);
190 }
191 }
192
193 /**
194 * @brief Perform a binary search for an address in a list of addresses.
195 *
196 * @param[in] p_addr Pointer to an address that is searched for.
197 * @param[in] p_addr_array Pointer to a list of addresses to be searched.
198 * @param[out] p_location If the address @p p_addr appears in the list, this is its index in the address list.
199 * Otherwise, it is the index which @p p_addr would have if it was placed in the list
200 * (ascending order assumed).
201 * @param[in] extended Indication if @p p_addr is an extended or a short addresses.
202 *
203 * @retval true Address @p p_addr is in the list.
204 * @retval false Address @p p_addr is not in the list.
205 */
addr_binary_search(const uint8_t * p_addr,const uint8_t * p_addr_array,uint32_t * p_location,nrf_802154_ack_data_t data_type,bool extended)206 static bool addr_binary_search(const uint8_t * p_addr,
207 const uint8_t * p_addr_array,
208 uint32_t * p_location,
209 nrf_802154_ack_data_t data_type,
210 bool extended)
211 {
212 uint32_t addr_array_len = 0;
213 uint8_t entry_size = 0;
214
215 switch (data_type)
216 {
217 case NRF_802154_ACK_DATA_PENDING_BIT:
218 entry_size = extended ? EXTENDED_ADDRESS_SIZE : SHORT_ADDRESS_SIZE;
219 addr_array_len = extended ?
220 m_pending_bit.num_of_ext_addr : m_pending_bit.num_of_short_addr;
221 break;
222
223 case NRF_802154_ACK_DATA_IE:
224 entry_size = extended ? sizeof(ack_ext_ie_data_t) : sizeof(ack_short_ie_data_t);
225 addr_array_len = extended ? m_ie.num_of_ext_data : m_ie.num_of_short_data;
226 break;
227
228 default:
229 NRF_802154_ASSERT(false);
230 break;
231 }
232
233 // The actual algorithm
234 int32_t low = 0;
235 uint32_t midpoint = 0;
236 int32_t high = addr_array_len;
237
238 while (high >= low)
239 {
240 midpoint = (uint32_t)(low + (high - low) / 2);
241
242 if (midpoint >= addr_array_len)
243 {
244 break;
245 }
246
247 switch (addr_compare(p_addr, p_addr_array + entry_size * midpoint, extended))
248 {
249 case -1:
250 high = (int32_t)(midpoint - 1);
251 break;
252
253 case 0:
254 *p_location = midpoint;
255 return true;
256
257 case 1:
258 low = (int32_t)(midpoint + 1);
259 break;
260
261 default:
262 break;
263 }
264 }
265
266 /* If in the last iteration of the loop the last case was utilized, it means that the midpoint
267 * found by the algorithm is less than the address to be added. The midpoint should be therefore
268 * shifted to the next position. As a simplified example, a { 1, 3, 4 } array can be considered.
269 * Suppose that a number equal to 2 is about to be added to the array. At the beginning of the
270 * last iteration, midpoint is equal to 1 and low and high are equal to 0. Midpoint is then set
271 * to 0 and with last case being utilized, low is set to 1. However, midpoint equal to 0 is
272 * incorrect, as in the last iteration first element of the array proves to be less than the
273 * element to be added to the array. With the below code, midpoint is then shifted to 1. */
274 if ((uint32_t)low == midpoint + 1)
275 {
276 midpoint++;
277 }
278
279 *p_location = midpoint;
280 return false;
281 }
282
283 /**
284 * @brief Find an address in a list of addresses.
285 *
286 * @param[in] p_addr Pointer to an address that is searched for.
287 * @param[out] p_location If the address @p p_addr appears in the list, this is its index in the address list.
288 * Otherwise, it is the index which @p p_addr would have if it was placed in the list
289 * (ascending order assumed).
290 * @param[in] extended Indication if @p p_addr is an extended or a short addresses.
291 *
292 * @retval true Address @p p_addr is in the list.
293 * @retval false Address @p p_addr is not in the list.
294 */
addr_index_find(const uint8_t * p_addr,uint32_t * p_location,nrf_802154_ack_data_t data_type,bool extended)295 static bool addr_index_find(const uint8_t * p_addr,
296 uint32_t * p_location,
297 nrf_802154_ack_data_t data_type,
298 bool extended)
299 {
300 uint8_t * p_addr_array;
301 bool valid_data_type = true;
302
303 switch (data_type)
304 {
305 case NRF_802154_ACK_DATA_PENDING_BIT:
306 p_addr_array = extended ? (uint8_t *)m_pending_bit.extended_addr :
307 (uint8_t *)m_pending_bit.short_addr;
308 break;
309
310 case NRF_802154_ACK_DATA_IE:
311 p_addr_array = extended ? (uint8_t *)m_ie.ext_data : (uint8_t *)m_ie.short_data;
312 break;
313
314 default:
315 valid_data_type = false;
316 NRF_802154_ASSERT(false);
317 break;
318 }
319
320 if (!valid_data_type)
321 {
322 return false;
323 }
324
325 return addr_binary_search(p_addr, p_addr_array, p_location, data_type, extended);
326 }
327
328 /**
329 * @brief Thread implementation of the address matching algorithm.
330 *
331 * @param[in] p_frame_data Pointer to the frame parser data for which the ACK frame is being prepared.
332 *
333 * @retval true Pending bit is to be set.
334 * @retval false Pending bit is to be cleared.
335 */
addr_match_thread(const nrf_802154_frame_parser_data_t * p_frame_data)336 static bool addr_match_thread(const nrf_802154_frame_parser_data_t * p_frame_data)
337 {
338 uint32_t location;
339 bool extended = nrf_802154_frame_parser_src_addr_is_extended(p_frame_data);
340 const uint8_t * p_src_addr = nrf_802154_frame_parser_src_addr_get(p_frame_data);
341
342 // The pending bit is set by default.
343 if (!m_pending_bit.enabled || (NULL == p_src_addr))
344 {
345 return true;
346 }
347
348 return addr_index_find(p_src_addr, &location, NRF_802154_ACK_DATA_PENDING_BIT, extended);
349 }
350
351 /**
352 * @brief Zigbee implementation of the address matching algorithm.
353 *
354 * @param[in] p_frame_data Pointer to the frame parser data for which the ACK frame is being prepared.
355 *
356 * @retval true Pending bit is to be set.
357 * @retval false Pending bit is to be cleared.
358 */
addr_match_zigbee(const nrf_802154_frame_parser_data_t * p_frame_data)359 static bool addr_match_zigbee(const nrf_802154_frame_parser_data_t * p_frame_data)
360 {
361 uint8_t src_addr_type;
362 uint32_t location;
363 const uint8_t * p_cmd;
364 const uint8_t * p_src_addr;
365 bool ret = false;
366
367 // If ack data generator module is disabled do not perform check, return true by default.
368 if (!m_pending_bit.enabled)
369 {
370 return true;
371 }
372
373 // Check the frame type.
374 p_src_addr = nrf_802154_frame_parser_src_addr_get(p_frame_data);
375 src_addr_type = nrf_802154_frame_parser_src_addr_type_get(p_frame_data);
376
377 p_cmd = nrf_802154_frame_parser_mac_command_id_get(p_frame_data);
378
379 // Check frame type and command type.
380 if ((p_cmd != NULL) && (*p_cmd == MAC_CMD_DATA_REQ))
381 {
382 // Check addressing type - in long case address, pb should always be 1.
383 if (src_addr_type == SRC_ADDR_TYPE_SHORT)
384 {
385 // Return true if address is not found on the m_pending_bits list.
386 ret = !addr_index_find(p_src_addr,
387 &location,
388 NRF_802154_ACK_DATA_PENDING_BIT,
389 false);
390 }
391 else
392 {
393 ret = true;
394 }
395 }
396
397 return ret;
398 }
399
400 /**
401 * @brief Standard-compliant implementation of the address matching algorithm.
402 *
403 * Function always returns true. It is IEEE 802.15.4 compliant, as per 6.7.3.
404 * Higher layer should ensure empty data frame with no AR is sent afterwards.
405 *
406 * @param[in] p_frame_data Pointer to the frame parser data for which the ACK frame is being prepared.
407 *
408 * @retval true Pending bit is to be set.
409 */
addr_match_standard_compliant(const nrf_802154_frame_parser_data_t * p_frame_data)410 static bool addr_match_standard_compliant(const nrf_802154_frame_parser_data_t * p_frame_data)
411 {
412 (void)p_frame_data;
413 return true;
414 }
415
416 /**
417 * @brief Add an address to the address list in ascending order.
418 *
419 * @param[in] p_addr Pointer to the address to be added.
420 * @param[in] location Index of the location where @p p_addr should be added.
421 * @param[in] extended Indication if @p p_addr is an extended or a short addresses.
422 *
423 * @retval true Address @p p_addr has been added to the list successfully.
424 * @retval false Address @p p_addr could not be added to the list.
425 */
addr_add(const uint8_t * p_addr,uint32_t location,nrf_802154_ack_data_t data_type,bool extended)426 static bool addr_add(const uint8_t * p_addr,
427 uint32_t location,
428 nrf_802154_ack_data_t data_type,
429 bool extended)
430 {
431 uint32_t * p_addr_array_len;
432 uint32_t max_addr_array_len;
433 uint8_t * p_addr_array;
434 uint8_t entry_size;
435 bool valid_data_type = true;
436
437 switch (data_type)
438 {
439 case NRF_802154_ACK_DATA_PENDING_BIT:
440 if (extended)
441 {
442 p_addr_array = (uint8_t *)m_pending_bit.extended_addr;
443 max_addr_array_len = NUM_EXTENDED_ADDRESSES;
444 p_addr_array_len = &m_pending_bit.num_of_ext_addr;
445 entry_size = EXTENDED_ADDRESS_SIZE;
446 }
447 else
448 {
449 p_addr_array = (uint8_t *)m_pending_bit.short_addr;
450 max_addr_array_len = NUM_SHORT_ADDRESSES;
451 p_addr_array_len = &m_pending_bit.num_of_short_addr;
452 entry_size = SHORT_ADDRESS_SIZE;
453 }
454 break;
455
456 case NRF_802154_ACK_DATA_IE:
457 if (extended)
458 {
459 p_addr_array = (uint8_t *)m_ie.ext_data;
460 max_addr_array_len = NUM_EXTENDED_ADDRESSES;
461 p_addr_array_len = &m_ie.num_of_ext_data;
462 entry_size = sizeof(ack_ext_ie_data_t);
463 }
464 else
465 {
466 p_addr_array = (uint8_t *)m_ie.short_data;
467 max_addr_array_len = NUM_SHORT_ADDRESSES;
468 p_addr_array_len = &m_ie.num_of_short_data;
469 entry_size = sizeof(ack_short_ie_data_t);
470 }
471 break;
472
473 default:
474 valid_data_type = false;
475 NRF_802154_ASSERT(false);
476 break;
477 }
478
479 if (!valid_data_type || (*p_addr_array_len == max_addr_array_len))
480 {
481 return false;
482 }
483
484 uint8_t * p_entry_at_location = p_addr_array + entry_size * location;
485
486 memmove(p_entry_at_location + entry_size,
487 p_entry_at_location,
488 (*p_addr_array_len - location) * entry_size);
489
490 memcpy(p_entry_at_location,
491 p_addr,
492 extended ? EXTENDED_ADDRESS_SIZE : SHORT_ADDRESS_SIZE);
493
494 if (data_type == NRF_802154_ACK_DATA_IE)
495 {
496 /* The content of ie_data_t in the structure indexed by location
497 * is uninitialized (can have old content). Let's initialize it. */
498 ie_data_t * p_ie_data = extended ?
499 &(((ack_ext_ie_data_t *)p_entry_at_location)->ie_data) :
500 &(((ack_short_ie_data_t *)p_entry_at_location)->ie_data);
501
502 p_ie_data->len = 0U;
503 /* p_ie_data->p_data does not need initialization when len is set to zero. */
504 }
505
506 (*p_addr_array_len)++;
507
508 return true;
509 }
510
511 /**
512 * @brief Remove an address from the address list keeping it in ascending order.
513 *
514 * @param[in] location Index of the element to be removed from the list.
515 * @param[in] extended Indication if address to remove is an extended or a short address.
516 *
517 * @retval true Address @p p_addr has been removed from the list successfully.
518 * @retval false Address @p p_addr could not removed from the list.
519 */
addr_remove(uint32_t location,nrf_802154_ack_data_t data_type,bool extended)520 static bool addr_remove(uint32_t location, nrf_802154_ack_data_t data_type, bool extended)
521 {
522 uint32_t * p_addr_array_len;
523 uint8_t * p_addr_array;
524 uint8_t entry_size;
525 bool valid_data_type = true;
526
527 switch (data_type)
528 {
529 case NRF_802154_ACK_DATA_PENDING_BIT:
530 if (extended)
531 {
532 p_addr_array = (uint8_t *)m_pending_bit.extended_addr;
533 p_addr_array_len = &m_pending_bit.num_of_ext_addr;
534 entry_size = EXTENDED_ADDRESS_SIZE;
535 }
536 else
537 {
538 p_addr_array = (uint8_t *)m_pending_bit.short_addr;
539 p_addr_array_len = &m_pending_bit.num_of_short_addr;
540 entry_size = SHORT_ADDRESS_SIZE;
541 }
542 break;
543
544 case NRF_802154_ACK_DATA_IE:
545 if (extended)
546 {
547 p_addr_array = (uint8_t *)m_ie.ext_data;
548 p_addr_array_len = &m_ie.num_of_ext_data;
549 entry_size = sizeof(ack_ext_ie_data_t);
550 }
551 else
552 {
553 p_addr_array = (uint8_t *)m_ie.short_data;
554 p_addr_array_len = &m_ie.num_of_short_data;
555 entry_size = sizeof(ack_short_ie_data_t);
556 }
557 break;
558
559 default:
560 valid_data_type = false;
561 NRF_802154_ASSERT(false);
562 break;
563 }
564
565 if (!valid_data_type || (*p_addr_array_len == 0))
566 {
567 return false;
568 }
569
570 memmove(p_addr_array + entry_size * location,
571 p_addr_array + entry_size * (location + 1),
572 (*p_addr_array_len - location - 1) * entry_size);
573
574 (*p_addr_array_len)--;
575
576 return true;
577 }
578
579 /**
580 * @brief Replace or append an Information Element to the ACK data.
581 *
582 * If the target ACK data already contains an Information Element with the same
583 * ID as the new Information Element, the existing IE is replaced with the new
584 * one. Otherwise, the new IE is appended to the target ACK data.
585 *
586 * @param[in] location Index of the ACK data buffer to be modified.
587 * @param[in] extended Indication whether the ACK data buffer for
588 * an extended or a short address is to be modified.
589 * @param[in] p_data New Information Element data.
590 * @param[in] data_len New Information Element data length.
591 *
592 * @retval true The new Information Element has been added successfully.
593 * @retval false The new Information Element has not fitted in the buffer.
594 */
ie_data_set(uint32_t location,bool extended,const uint8_t * p_data,uint8_t data_len)595 static bool ie_data_set(uint32_t location, bool extended, const uint8_t * p_data, uint8_t data_len)
596 {
597 ie_data_t * ie_data =
598 extended ? &m_ie.ext_data[location].ie_data : &m_ie.short_data[location].ie_data;
599
600 const uint8_t new_ie_id = nrf_802154_frame_parser_ie_id_get(p_data);
601
602 for (const uint8_t * ie = nrf_802154_frame_parser_header_ie_iterator_begin(ie_data->p_data);
603 nrf_802154_frame_parser_ie_iterator_end(ie, ie_data->p_data + ie_data->len) == false;
604 ie = nrf_802154_frame_parser_ie_iterator_next(ie))
605 {
606 if (nrf_802154_frame_parser_ie_id_get(ie) != new_ie_id)
607 {
608 continue;
609 }
610
611 if (IE_DATA_OFFSET + nrf_802154_frame_parser_ie_length_get(ie) != data_len)
612 {
613 /* Overwriting an existing IE with a different size is not supported. */
614 return false;
615 }
616
617 memcpy((uint8_t *)ie, p_data, data_len);
618 return true;
619 }
620
621 /* Append IE data with the new IE. */
622
623 if (ie_data->len + data_len > NRF_802154_MAX_ACK_IE_SIZE)
624 {
625 /* No space to fit it the new IE. */
626 return false;
627 }
628
629 memcpy(ie_data->p_data + ie_data->len, p_data, data_len);
630 ie_data->len += data_len;
631
632 return true;
633 }
634
635 /***************************************************************************************************
636 * @section Public API
637 **************************************************************************************************/
638
nrf_802154_ack_data_init(void)639 void nrf_802154_ack_data_init(void)
640 {
641 memset(&m_pending_bit, 0, sizeof(m_pending_bit));
642 memset(&m_ie, 0, sizeof(m_ie));
643
644 m_pending_bit.enabled = true;
645 m_src_matching_method = NRF_802154_SRC_ADDR_MATCH_THREAD;
646 }
647
nrf_802154_ack_data_enable(bool enabled)648 void nrf_802154_ack_data_enable(bool enabled)
649 {
650 m_pending_bit.enabled = enabled;
651 }
652
nrf_802154_ack_data_for_addr_set(const uint8_t * p_addr,bool extended,nrf_802154_ack_data_t data_type,const void * p_data,uint8_t data_len)653 bool nrf_802154_ack_data_for_addr_set(const uint8_t * p_addr,
654 bool extended,
655 nrf_802154_ack_data_t data_type,
656 const void * p_data,
657 uint8_t data_len)
658 {
659 uint32_t location = 0;
660
661 if (addr_index_find(p_addr, &location, data_type, extended) ||
662 addr_add(p_addr, location, data_type, extended))
663 {
664 if (data_type == NRF_802154_ACK_DATA_IE)
665 {
666 return ie_data_set(location, extended, p_data, data_len);
667 }
668
669 return true;
670 }
671 else
672 {
673 return false;
674 }
675 }
676
nrf_802154_ack_data_for_addr_clear(const uint8_t * p_addr,bool extended,nrf_802154_ack_data_t data_type)677 bool nrf_802154_ack_data_for_addr_clear(const uint8_t * p_addr,
678 bool extended,
679 nrf_802154_ack_data_t data_type)
680 {
681 uint32_t location = 0;
682
683 if (addr_index_find(p_addr, &location, data_type, extended))
684 {
685 return addr_remove(location, data_type, extended);
686 }
687 else
688 {
689 return false;
690 }
691 }
692
nrf_802154_ack_data_reset(bool extended,nrf_802154_ack_data_t data_type)693 void nrf_802154_ack_data_reset(bool extended, nrf_802154_ack_data_t data_type)
694 {
695 switch (data_type)
696 {
697 case NRF_802154_ACK_DATA_PENDING_BIT:
698 if (extended)
699 {
700 m_pending_bit.num_of_ext_addr = 0;
701 }
702 else
703 {
704 m_pending_bit.num_of_short_addr = 0;
705 }
706 break;
707
708 case NRF_802154_ACK_DATA_IE:
709 if (extended)
710 {
711 m_ie.num_of_ext_data = 0;
712 }
713 else
714 {
715 m_ie.num_of_short_data = 0;
716 }
717 break;
718
719 default:
720 break;
721 }
722 }
723
nrf_802154_ack_data_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_method)724 void nrf_802154_ack_data_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_method)
725 {
726 switch (match_method)
727 {
728 case NRF_802154_SRC_ADDR_MATCH_THREAD:
729 case NRF_802154_SRC_ADDR_MATCH_ZIGBEE:
730 case NRF_802154_SRC_ADDR_MATCH_ALWAYS_1:
731 m_src_matching_method = match_method;
732 break;
733
734 default:
735 NRF_802154_ASSERT(false);
736 }
737
738 }
739
nrf_802154_ack_data_pending_bit_should_be_set(const nrf_802154_frame_parser_data_t * p_frame_data)740 bool nrf_802154_ack_data_pending_bit_should_be_set(
741 const nrf_802154_frame_parser_data_t * p_frame_data)
742 {
743 bool ret;
744
745 switch (m_src_matching_method)
746 {
747 case NRF_802154_SRC_ADDR_MATCH_THREAD:
748 ret = addr_match_thread(p_frame_data);
749 break;
750
751 case NRF_802154_SRC_ADDR_MATCH_ZIGBEE:
752 ret = addr_match_zigbee(p_frame_data);
753 break;
754
755 case NRF_802154_SRC_ADDR_MATCH_ALWAYS_1:
756 ret = addr_match_standard_compliant(p_frame_data);
757 break;
758
759 default:
760 ret = false;
761 NRF_802154_ASSERT(false);
762 }
763
764 return ret;
765 }
766
nrf_802154_ack_data_ie_get(const uint8_t * p_src_addr,bool src_addr_extended,uint8_t * p_ie_length)767 const uint8_t * nrf_802154_ack_data_ie_get(const uint8_t * p_src_addr,
768 bool src_addr_extended,
769 uint8_t * p_ie_length)
770 {
771 uint32_t location;
772
773 if (NULL == p_src_addr)
774 {
775 return NULL;
776 }
777
778 if (addr_index_find(p_src_addr, &location, NRF_802154_ACK_DATA_IE, src_addr_extended))
779 {
780 if (src_addr_extended)
781 {
782 *p_ie_length = m_ie.ext_data[location].ie_data.len;
783 return m_ie.ext_data[location].ie_data.p_data;
784 }
785 else
786 {
787 *p_ie_length = m_ie.short_data[location].ie_data.len;
788 return m_ie.short_data[location].ie_data.p_data;
789 }
790 }
791 else
792 {
793 *p_ie_length = 0;
794 return NULL;
795 }
796 }
797