1 /*
2 * Copyright (c) 2021, 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 <stdint.h>
36 #include <string.h>
37 #include "nrf_802154_assert.h"
38
39 #ifndef NRF_802154_UTILS_BYTEORDER_H
40 #define NRF_802154_UTILS_BYTEORDER_H
41
42 /**
43 * @defgroup nrf_802154_utils_byteorder Utils definitions for byte ordering used in the 802.15.4 driver
44 * @{
45 * @ingroup nrf_802154
46 * @brief Definitions of utils for byte ordering used in the 802.15.4 driver.
47 */
48
49 #if !defined(__BYTE_ORDER__)
50
51 /* Couldn't determine endian-ness of the target machine. */
52 #error "Please define __BYTE_ORDER__!"
53
54 #elif defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
55
56 /**@brief Write 64-bit value from host byte-order to little-endian byte array.
57 *
58 * @param[in] value A 64-bit host-order value to write
59 * @param[out] p_buffer A little-endian byte array to be populated
60 */
host_64_to_little(uint64_t value,uint8_t * p_buffer)61 static inline void host_64_to_little(uint64_t value, uint8_t * p_buffer)
62 {
63 NRF_802154_ASSERT(p_buffer != NULL);
64 memcpy(p_buffer, &value, sizeof(uint64_t));
65 }
66
67 /**@brief Write 32-bit value from host byte-order to little-endian byte array.
68 *
69 * @param[in] value A 32-bit host-order value to write
70 * @param[out] p_buffer A little-endian byte array to be populated
71 */
host_32_to_little(uint32_t value,uint8_t * p_buffer)72 static inline void host_32_to_little(uint32_t value, uint8_t * p_buffer)
73 {
74 NRF_802154_ASSERT(p_buffer != NULL);
75 memcpy(p_buffer, &value, sizeof(uint32_t));
76 }
77
78 /**@brief Write 24-bit value from host byte-order to little-endian byte array.
79 *
80 * @param[in] value A 32-bit host-order value, whose lower 24 bits will be copied
81 * @param[out] p_buffer A little-endian byte array to be populated
82 */
host_24_to_little(uint32_t value,uint8_t * p_buffer)83 static inline void host_24_to_little(uint32_t value, uint8_t * p_buffer)
84 {
85 NRF_802154_ASSERT(p_buffer != NULL);
86 memcpy(p_buffer, &value, 3);
87 }
88
89 /**@brief Write 16-bit value from host byte-order to little-endian byte array.
90 *
91 * @param[in] value A 16-bit host-order value to write
92 * @param[out] p_buffer A little-endian byte array to be populated
93 */
host_16_to_little(uint16_t value,uint8_t * p_buffer)94 static inline void host_16_to_little(uint16_t value, uint8_t * p_buffer)
95 {
96 NRF_802154_ASSERT(p_buffer != NULL);
97 memcpy(p_buffer, &value, sizeof(uint16_t));
98 }
99
100 /**@brief Convert 64-bit value from little-endian byte array to host-order value.
101 *
102 * @param[in] p_buffer A little-endian byte array to be read
103 *
104 * @returns A 64-bit host-order value
105 */
little_64_to_host(uint8_t * p_buffer)106 static inline uint64_t little_64_to_host(uint8_t * p_buffer)
107 {
108 NRF_802154_ASSERT(p_buffer != NULL);
109
110 uint64_t value = 0;
111
112 memcpy(&value, p_buffer, sizeof(uint64_t));
113
114 return value;
115 }
116
117 /**@brief Convert 32-bit value from little-endian byte array to host-order value.
118 *
119 * @param[in] p_buffer A little-endian byte array to be read
120 *
121 * @returns A 32-bit host-order value
122 */
little_32_to_host(uint8_t * p_buffer)123 static inline uint32_t little_32_to_host(uint8_t * p_buffer)
124 {
125 NRF_802154_ASSERT(p_buffer != NULL);
126
127 uint32_t value = 0;
128
129 memcpy(&value, p_buffer, sizeof(uint32_t));
130
131 return value;
132 }
133
134 /**@brief Convert 24-bit value from little-endian byte array to host-order value.
135 *
136 * @param[in] p_buffer A little-endian byte array to be read
137 *
138 * @returns A 24-bit host-order value
139 */
little_24_to_host(uint8_t * p_buffer)140 static inline uint32_t little_24_to_host(uint8_t * p_buffer)
141 {
142 NRF_802154_ASSERT(p_buffer != NULL);
143
144 uint32_t value = 0;
145
146 memcpy(&value, p_buffer, 3);
147
148 return value;
149 }
150
151 /**@brief Convert 16-bit value from little-endian byte array to host-order value.
152 *
153 * @param[in] p_buffer A little-endian byte array to be read
154 *
155 * @returns A 16-bit host-order value
156 */
little_16_to_host(uint8_t * p_buffer)157 static inline uint16_t little_16_to_host(uint8_t * p_buffer)
158 {
159 NRF_802154_ASSERT(p_buffer != NULL);
160
161 uint16_t value = 0;
162
163 memcpy(&value, p_buffer, sizeof(uint16_t));
164
165 return value;
166 }
167
168 /**@brief Write 64-bit value from host byte-order to big-endian byte array.
169 *
170 * @param[in] value A 64-bit host-order value to write
171 * @param[out] p_buffer A big-endian byte array to be populated
172 */
host_64_to_big(uint64_t value,uint8_t * p_buffer)173 static inline void host_64_to_big(uint64_t value, uint8_t * p_buffer)
174 {
175 NRF_802154_ASSERT(p_buffer != NULL);
176
177 uint8_t shift = (sizeof(uint64_t) - 1) * 8;
178
179 for (uint8_t i = 0; i < sizeof(uint64_t); i++, shift -= 8)
180 {
181 p_buffer[i] = (value >> shift) & 0xff;
182 }
183 }
184
185 /**@brief Write 32-bit value from host byte-order to big-endian byte array.
186 *
187 * @param[in] value A 32-bit host-order value to write
188 * @param[out] p_buffer A big-endian byte array to be populated
189 */
host_32_to_big(uint32_t value,uint8_t * p_buffer)190 static inline void host_32_to_big(uint32_t value, uint8_t * p_buffer)
191 {
192 NRF_802154_ASSERT(p_buffer != NULL);
193
194 uint8_t shift = (sizeof(uint32_t) - 1) * 8;
195
196 for (uint8_t i = 0; i < sizeof(uint32_t); i++, shift -= 8)
197 {
198 p_buffer[i] = (value >> shift) & 0xff;
199 }
200 }
201
202 /**@brief Write 24-bit value from host byte-order to big-endian byte array.
203 *
204 * @param[in] value A 24-bit host-order value to write
205 * @param[out] p_buffer A big-endian byte array to be populated
206 */
host_24_to_big(uint32_t value,uint8_t * p_buffer)207 static inline void host_24_to_big(uint32_t value, uint8_t * p_buffer)
208 {
209 NRF_802154_ASSERT(p_buffer != NULL);
210
211 uint8_t shift = (sizeof(uint32_t) - 2) * 8;
212
213 for (uint8_t i = 0; i < sizeof(uint32_t) - 1; i++, shift -= 8)
214 {
215 p_buffer[i] = (value >> shift) & 0xff;
216 }
217 }
218
219 /**@brief Write 16-bit value from host byte-order to big-endian byte array.
220 *
221 * @param[in] value A 16-bit host-order value to write
222 * @param[out] p_buffer A big-endian byte array to be populated
223 */
host_16_to_big(uint16_t value,uint8_t * p_buffer)224 static inline void host_16_to_big(uint16_t value, uint8_t * p_buffer)
225 {
226 NRF_802154_ASSERT(p_buffer != NULL);
227
228 uint8_t shift = (sizeof(uint16_t) - 1) * 8;
229
230 for (uint8_t i = 0; i < sizeof(uint16_t); i++, shift -= 8)
231 {
232 p_buffer[i] = (value >> shift) & 0xff;
233 }
234 }
235
236 /**@brief Convert 64-bit value from big-endian byte array to host-order value.
237 *
238 * @param[in] p_buffer A big-endian byte array to be read
239 *
240 * @returns A 64-bit host-order value
241 */
big_64_to_host(uint8_t * p_buffer)242 static inline uint64_t big_64_to_host(uint8_t * p_buffer)
243 {
244 NRF_802154_ASSERT(p_buffer != NULL);
245
246 uint64_t value = 0;
247
248 for (uint8_t i = 0; i < sizeof(uint64_t); i++)
249 {
250 value = (value << 8) | p_buffer[i];
251 }
252
253 return value;
254 }
255
256 /**@brief Convert 32-bit value from big-endian byte array to host-order value.
257 *
258 * @param[in] p_buffer A big-endian byte array to be read
259 *
260 * @returns A 32-bit host-order value
261 */
big_32_to_host(uint8_t * p_buffer)262 static inline uint32_t big_32_to_host(uint8_t * p_buffer)
263 {
264 NRF_802154_ASSERT(p_buffer != NULL);
265
266 uint32_t value = 0;
267
268 for (uint8_t i = 0; i < sizeof(uint32_t); i++)
269 {
270 value = (value << 8) | p_buffer[i];
271 }
272
273 return value;
274 }
275
276 /**@brief Convert 24-bit value from big-endian byte array to host-order value.
277 *
278 * @param[in] p_buffer A big-endian byte array to be read
279 *
280 * @returns A 24-bit host-order value
281 */
big_24_to_host(uint8_t * p_buffer)282 static inline uint32_t big_24_to_host(uint8_t * p_buffer)
283 {
284 NRF_802154_ASSERT(p_buffer != NULL);
285
286 uint32_t value = 0;
287
288 for (uint8_t i = 0; i < sizeof(uint32_t) - 1; i++)
289 {
290 value = (value << 8) | p_buffer[i];
291 }
292
293 return value;
294 }
295
296 /**@brief Convert 16-bit value from big-endian byte array to host-order value.
297 *
298 * @param[in] p_buffer A big-endian byte array to be read
299 *
300 * @returns A 16-bit host-order value
301 */
big_16_to_host(uint8_t * p_buffer)302 static inline uint16_t big_16_to_host(uint8_t * p_buffer)
303 {
304 NRF_802154_ASSERT(p_buffer != NULL);
305
306 uint16_t value = 0;
307
308 for (uint8_t i = 0; i < sizeof(uint16_t); i++)
309 {
310 value = (value << 8) | p_buffer[i];
311 }
312
313 return value;
314 }
315
316 #else
317
318 /* Most likely the case of big-endian machine. */
319 #error "Unsupported endian-ness of the target machine"
320
321 #endif // __BYTE_ORDER__
322
323 /**
324 *@}
325 **/
326
327 #endif // NRF_802154_UTILS_BYTEORDER_H
328