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