1 /** @file
2  *  @brief Byte order helpers.
3  */
4 
5 /*
6  * Copyright (c) 2015-2016, Intel Corporation.
7  *
8  * SPDX-License-Identifier: Apache-2.0
9  */
10 
11 #ifndef ZEPHYR_INCLUDE_SYS_BYTEORDER_H_
12 #define ZEPHYR_INCLUDE_SYS_BYTEORDER_H_
13 
14 #include <zephyr/types.h>
15 #include <stddef.h>
16 #include <zephyr/sys/__assert.h>
17 #include <zephyr/toolchain.h>
18 
19 #define BSWAP_16(x) ((uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
20 #define BSWAP_24(x) ((uint32_t) ((((x) >> 16) & 0xff) | \
21 				   (((x)) & 0xff00) | \
22 				   (((x) & 0xff) << 16)))
23 #define BSWAP_32(x) ((uint32_t) ((((x) >> 24) & 0xff) | \
24 				   (((x) >> 8) & 0xff00) | \
25 				   (((x) & 0xff00) << 8) | \
26 				   (((x) & 0xff) << 24)))
27 #define BSWAP_40(x) ((uint64_t) ((((x) >> 32) & 0xff) | \
28 				   (((x) >> 16) & 0xff00) | \
29 				   (((x)) & 0xff0000) | \
30 				   (((x) & 0xff00) << 16) | \
31 				   (((x) & 0xff) << 32)))
32 #define BSWAP_48(x) ((uint64_t) ((((x) >> 40) & 0xff) | \
33 				   (((x) >> 24) & 0xff00) | \
34 				   (((x) >> 8) & 0xff0000) | \
35 				   (((x) & 0xff0000) << 8) | \
36 				   (((x) & 0xff00) << 24) | \
37 				   (((x) & 0xff) << 40)))
38 #define BSWAP_64(x) ((uint64_t) ((((x) >> 56) & 0xff) | \
39 				   (((x) >> 40) & 0xff00) | \
40 				   (((x) >> 24) & 0xff0000) | \
41 				   (((x) >> 8) & 0xff000000) | \
42 				   (((x) & 0xff000000) << 8) | \
43 				   (((x) & 0xff0000) << 24) | \
44 				   (((x) & 0xff00) << 40) | \
45 				   (((x) & 0xff) << 56)))
46 
47 /** @def sys_le16_to_cpu
48  *  @brief Convert 16-bit integer from little-endian to host endianness.
49  *
50  *  @param val 16-bit integer in little-endian format.
51  *
52  *  @return 16-bit integer in host endianness.
53  */
54 
55 /** @def sys_cpu_to_le16
56  *  @brief Convert 16-bit integer from host endianness to little-endian.
57  *
58  *  @param val 16-bit integer in host endianness.
59  *
60  *  @return 16-bit integer in little-endian format.
61  */
62 
63 /** @def sys_le24_to_cpu
64  *  @brief Convert 24-bit integer from little-endian to host endianness.
65  *
66  *  @param val 24-bit integer in little-endian format.
67  *
68  *  @return 24-bit integer in host endianness.
69  */
70 
71 /** @def sys_cpu_to_le24
72  *  @brief Convert 24-bit integer from host endianness to little-endian.
73  *
74  *  @param val 24-bit integer in host endianness.
75  *
76  *  @return 24-bit integer in little-endian format.
77  */
78 
79 /** @def sys_le32_to_cpu
80  *  @brief Convert 32-bit integer from little-endian to host endianness.
81  *
82  *  @param val 32-bit integer in little-endian format.
83  *
84  *  @return 32-bit integer in host endianness.
85  */
86 
87 /** @def sys_cpu_to_le32
88  *  @brief Convert 32-bit integer from host endianness to little-endian.
89  *
90  *  @param val 32-bit integer in host endianness.
91  *
92  *  @return 32-bit integer in little-endian format.
93  */
94 
95 /** @def sys_le48_to_cpu
96  *  @brief Convert 48-bit integer from little-endian to host endianness.
97  *
98  *  @param val 48-bit integer in little-endian format.
99  *
100  *  @return 48-bit integer in host endianness.
101  */
102 
103 /** @def sys_cpu_to_le48
104  *  @brief Convert 48-bit integer from host endianness to little-endian.
105  *
106  *  @param val 48-bit integer in host endianness.
107  *
108  *  @return 48-bit integer in little-endian format.
109  */
110 
111 /** @def sys_be16_to_cpu
112  *  @brief Convert 16-bit integer from big-endian to host endianness.
113  *
114  *  @param val 16-bit integer in big-endian format.
115  *
116  *  @return 16-bit integer in host endianness.
117  */
118 
119 /** @def sys_cpu_to_be16
120  *  @brief Convert 16-bit integer from host endianness to big-endian.
121  *
122  *  @param val 16-bit integer in host endianness.
123  *
124  *  @return 16-bit integer in big-endian format.
125  */
126 
127 /** @def sys_be24_to_cpu
128  *  @brief Convert 24-bit integer from big-endian to host endianness.
129  *
130  *  @param val 24-bit integer in big-endian format.
131  *
132  *  @return 24-bit integer in host endianness.
133  */
134 
135 /** @def sys_cpu_to_be24
136  *  @brief Convert 24-bit integer from host endianness to big-endian.
137  *
138  *  @param val 24-bit integer in host endianness.
139  *
140  *  @return 24-bit integer in big-endian format.
141  */
142 
143 /** @def sys_be32_to_cpu
144  *  @brief Convert 32-bit integer from big-endian to host endianness.
145  *
146  *  @param val 32-bit integer in big-endian format.
147  *
148  *  @return 32-bit integer in host endianness.
149  */
150 
151 /** @def sys_cpu_to_be32
152  *  @brief Convert 32-bit integer from host endianness to big-endian.
153  *
154  *  @param val 32-bit integer in host endianness.
155  *
156  *  @return 32-bit integer in big-endian format.
157  */
158 
159 /** @def sys_be48_to_cpu
160  *  @brief Convert 48-bit integer from big-endian to host endianness.
161  *
162  *  @param val 48-bit integer in big-endian format.
163  *
164  *  @return 48-bit integer in host endianness.
165  */
166 
167 /** @def sys_cpu_to_be48
168  *  @brief Convert 48-bit integer from host endianness to big-endian.
169  *
170  *  @param val 48-bit integer in host endianness.
171  *
172  *  @return 48-bit integer in big-endian format.
173  */
174 
175 /** @def sys_uint16_to_array
176  *  @brief Convert 16-bit unsigned integer to byte array.
177  *
178  *  @details Byte order aware macro to treat an unsigned integer
179  *           as an array, rather than an integer literal. For example,
180  *           `0x0123` would be converted to `{0x01, 0x23}` for big endian
181  *           machines, and `{0x23, 0x01}` for little endian machines.
182  *
183  *  @param val 16-bit unsigned integer.
184  *
185  *  @return 16-bit unsigned integer as byte array.
186  */
187 
188 /** @def sys_uint32_to_array
189  *  @brief Convert 32-bit unsigned integer to byte array.
190  *
191  *  @details Byte order aware macro to treat an unsigned integer
192  *           as an array, rather than an integer literal. For example,
193  *           `0x01234567` would be converted to `{0x01, 0x23, 0x45, 0x67}`
194  *           for big endian machines, and `{0x67, 0x45, 0x23, 0x01}` for
195  *           little endian machines.
196  *
197  *  @param val 32-bit unsigned integer.
198  *
199  *  @return 32-bit unsigned integer as byte array.
200  */
201 
202 /** @def sys_uint64_to_array
203  *  @brief Convert 64-bit unsigned integer to byte array.
204  *
205  *  @details Byte order aware macro to treat an unsigned integer
206  *           as an array, rather than an integer literal. For example,
207  *           `0x0123456789abcdef` would be converted to
208  *           `{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}`
209  *           for big endian machines, and
210  *           `{0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01}` for
211  *           little endian machines.
212  *
213  *  @param val 64-bit unsigned integer.
214  *
215  *  @return 64-bit unsigned integer as byte array.
216  */
217 
218 #ifdef CONFIG_LITTLE_ENDIAN
219 #define sys_le16_to_cpu(val) (val)
220 #define sys_cpu_to_le16(val) (val)
221 #define sys_le24_to_cpu(val) (val)
222 #define sys_cpu_to_le24(val) (val)
223 #define sys_le32_to_cpu(val) (val)
224 #define sys_cpu_to_le32(val) (val)
225 #define sys_le40_to_cpu(val) (val)
226 #define sys_cpu_to_le40(val) (val)
227 #define sys_le48_to_cpu(val) (val)
228 #define sys_cpu_to_le48(val) (val)
229 #define sys_le64_to_cpu(val) (val)
230 #define sys_cpu_to_le64(val) (val)
231 #define sys_be16_to_cpu(val) BSWAP_16(val)
232 #define sys_cpu_to_be16(val) BSWAP_16(val)
233 #define sys_be24_to_cpu(val) BSWAP_24(val)
234 #define sys_cpu_to_be24(val) BSWAP_24(val)
235 #define sys_be32_to_cpu(val) BSWAP_32(val)
236 #define sys_cpu_to_be32(val) BSWAP_32(val)
237 #define sys_be40_to_cpu(val) BSWAP_40(val)
238 #define sys_cpu_to_be40(val) BSWAP_40(val)
239 #define sys_be48_to_cpu(val) BSWAP_48(val)
240 #define sys_cpu_to_be48(val) BSWAP_48(val)
241 #define sys_be64_to_cpu(val) BSWAP_64(val)
242 #define sys_cpu_to_be64(val) BSWAP_64(val)
243 
244 #define sys_uint16_to_array(val) {		\
245 	((val) & 0xff),				\
246 	(((val) >> 8) & 0xff)}
247 
248 #define sys_uint32_to_array(val) {		\
249 	((val) & 0xff),				\
250 	(((val) >> 8) & 0xff),			\
251 	(((val) >> 16) & 0xff),			\
252 	(((val) >> 24) & 0xff)}
253 
254 #define sys_uint64_to_array(val) {		\
255 	((val) & 0xff),				\
256 	(((val) >> 8) & 0xff),			\
257 	(((val) >> 16) & 0xff),			\
258 	(((val) >> 24) & 0xff),			\
259 	(((val) >> 32) & 0xff),			\
260 	(((val) >> 40) & 0xff),			\
261 	(((val) >> 48) & 0xff),			\
262 	(((val) >> 56) & 0xff)}
263 
264 #else
265 #define sys_le16_to_cpu(val) BSWAP_16(val)
266 #define sys_cpu_to_le16(val) BSWAP_16(val)
267 #define sys_le24_to_cpu(val) BSWAP_24(val)
268 #define sys_cpu_to_le24(val) BSWAP_24(val)
269 #define sys_le32_to_cpu(val) BSWAP_32(val)
270 #define sys_cpu_to_le32(val) BSWAP_32(val)
271 #define sys_le40_to_cpu(val) BSWAP_40(val)
272 #define sys_cpu_to_le40(val) BSWAP_40(val)
273 #define sys_le48_to_cpu(val) BSWAP_48(val)
274 #define sys_cpu_to_le48(val) BSWAP_48(val)
275 #define sys_le64_to_cpu(val) BSWAP_64(val)
276 #define sys_cpu_to_le64(val) BSWAP_64(val)
277 #define sys_be16_to_cpu(val) (val)
278 #define sys_cpu_to_be16(val) (val)
279 #define sys_be24_to_cpu(val) (val)
280 #define sys_cpu_to_be24(val) (val)
281 #define sys_be32_to_cpu(val) (val)
282 #define sys_cpu_to_be32(val) (val)
283 #define sys_be40_to_cpu(val) (val)
284 #define sys_cpu_to_be40(val) (val)
285 #define sys_be48_to_cpu(val) (val)
286 #define sys_cpu_to_be48(val) (val)
287 #define sys_be64_to_cpu(val) (val)
288 #define sys_cpu_to_be64(val) (val)
289 
290 #define sys_uint16_to_array(val) {		\
291 	(((val) >> 8) & 0xff),			\
292 	((val) & 0xff)}
293 
294 #define sys_uint32_to_array(val) {		\
295 	(((val) >> 24) & 0xff),			\
296 	(((val) >> 16) & 0xff),			\
297 	(((val) >> 8) & 0xff),			\
298 	((val) & 0xff)}
299 
300 #define sys_uint64_to_array(val) {		\
301 	(((val) >> 56) & 0xff),			\
302 	(((val) >> 48) & 0xff),			\
303 	(((val) >> 40) & 0xff),			\
304 	(((val) >> 32) & 0xff),			\
305 	(((val) >> 24) & 0xff),			\
306 	(((val) >> 16) & 0xff),			\
307 	(((val) >> 8) & 0xff),			\
308 	((val) & 0xff)}
309 
310 #endif
311 
312 /**
313  *  @brief Put a 16-bit integer as big-endian to arbitrary location.
314  *
315  *  Put a 16-bit integer, originally in host endianness, to a
316  *  potentially unaligned memory location in big-endian format.
317  *
318  *  @param val 16-bit integer in host endianness.
319  *  @param dst Destination memory address to store the result.
320  */
sys_put_be16(uint16_t val,uint8_t dst[2])321 static inline void sys_put_be16(uint16_t val, uint8_t dst[2])
322 {
323 	dst[0] = val >> 8;
324 	dst[1] = val;
325 }
326 
327 /**
328  *  @brief Put a 24-bit integer as big-endian to arbitrary location.
329  *
330  *  Put a 24-bit integer, originally in host endianness, to a
331  *  potentially unaligned memory location in big-endian format.
332  *
333  *  @param val 24-bit integer in host endianness.
334  *  @param dst Destination memory address to store the result.
335  */
sys_put_be24(uint32_t val,uint8_t dst[3])336 static inline void sys_put_be24(uint32_t val, uint8_t dst[3])
337 {
338 	dst[0] = val >> 16;
339 	sys_put_be16(val, &dst[1]);
340 }
341 
342 /**
343  *  @brief Put a 32-bit integer as big-endian to arbitrary location.
344  *
345  *  Put a 32-bit integer, originally in host endianness, to a
346  *  potentially unaligned memory location in big-endian format.
347  *
348  *  @param val 32-bit integer in host endianness.
349  *  @param dst Destination memory address to store the result.
350  */
sys_put_be32(uint32_t val,uint8_t dst[4])351 static inline void sys_put_be32(uint32_t val, uint8_t dst[4])
352 {
353 	sys_put_be16(val >> 16, dst);
354 	sys_put_be16(val, &dst[2]);
355 }
356 /**
357  *  @brief Put a 40-bit integer as big-endian to arbitrary location.
358  *
359  *  Put a 40-bit integer, originally in host endianness, to a
360  *  potentially unaligned memory location in big-endian format.
361  *
362  *  @param val 40-bit integer in host endianness.
363  *  @param dst Destination memory address to store the result.
364  */
sys_put_be40(uint64_t val,uint8_t dst[5])365 static inline void sys_put_be40(uint64_t val, uint8_t dst[5])
366 {
367 	dst[0] = val >> 32;
368 	sys_put_be32(val, &dst[1]);
369 }
370 
371 /**
372  *  @brief Put a 48-bit integer as big-endian to arbitrary location.
373  *
374  *  Put a 48-bit integer, originally in host endianness, to a
375  *  potentially unaligned memory location in big-endian format.
376  *
377  *  @param val 48-bit integer in host endianness.
378  *  @param dst Destination memory address to store the result.
379  */
sys_put_be48(uint64_t val,uint8_t dst[6])380 static inline void sys_put_be48(uint64_t val, uint8_t dst[6])
381 {
382 	sys_put_be16(val >> 32, dst);
383 	sys_put_be32(val, &dst[2]);
384 }
385 
386 /**
387  *  @brief Put a 64-bit integer as big-endian to arbitrary location.
388  *
389  *  Put a 64-bit integer, originally in host endianness, to a
390  *  potentially unaligned memory location in big-endian format.
391  *
392  *  @param val 64-bit integer in host endianness.
393  *  @param dst Destination memory address to store the result.
394  */
sys_put_be64(uint64_t val,uint8_t dst[8])395 static inline void sys_put_be64(uint64_t val, uint8_t dst[8])
396 {
397 	sys_put_be32(val >> 32, dst);
398 	sys_put_be32(val, &dst[4]);
399 }
400 
401 /**
402  *  @brief Put a 16-bit integer as little-endian to arbitrary location.
403  *
404  *  Put a 16-bit integer, originally in host endianness, to a
405  *  potentially unaligned memory location in little-endian format.
406  *
407  *  @param val 16-bit integer in host endianness.
408  *  @param dst Destination memory address to store the result.
409  */
sys_put_le16(uint16_t val,uint8_t dst[2])410 static inline void sys_put_le16(uint16_t val, uint8_t dst[2])
411 {
412 	dst[0] = val;
413 	dst[1] = val >> 8;
414 }
415 
416 /**
417  *  @brief Put a 24-bit integer as little-endian to arbitrary location.
418  *
419  *  Put a 24-bit integer, originally in host endianness, to a
420  *  potentially unaligned memory location in little-endian format.
421  *
422  *  @param val 24-bit integer in host endianness.
423  *  @param dst Destination memory address to store the result.
424  */
sys_put_le24(uint32_t val,uint8_t dst[3])425 static inline void sys_put_le24(uint32_t val, uint8_t dst[3])
426 {
427 	sys_put_le16(val, dst);
428 	dst[2] = val >> 16;
429 }
430 
431 /**
432  *  @brief Put a 32-bit integer as little-endian to arbitrary location.
433  *
434  *  Put a 32-bit integer, originally in host endianness, to a
435  *  potentially unaligned memory location in little-endian format.
436  *
437  *  @param val 32-bit integer in host endianness.
438  *  @param dst Destination memory address to store the result.
439  */
sys_put_le32(uint32_t val,uint8_t dst[4])440 static inline void sys_put_le32(uint32_t val, uint8_t dst[4])
441 {
442 	sys_put_le16(val, dst);
443 	sys_put_le16(val >> 16, &dst[2]);
444 }
445 
446 /**
447  *  @brief Put a 40-bit integer as little-endian to arbitrary location.
448  *
449  *  Put a 40-bit integer, originally in host endianness, to a
450  *  potentially unaligned memory location in little-endian format.
451  *
452  *  @param val 40-bit integer in host endianness.
453  *  @param dst Destination memory address to store the result.
454  */
sys_put_le40(uint64_t val,uint8_t dst[5])455 static inline void sys_put_le40(uint64_t val, uint8_t dst[5])
456 {
457 	sys_put_le32(val, dst);
458 	dst[4] = val >> 32;
459 }
460 
461 /**
462  *  @brief Put a 48-bit integer as little-endian to arbitrary location.
463  *
464  *  Put a 48-bit integer, originally in host endianness, to a
465  *  potentially unaligned memory location in little-endian format.
466  *
467  *  @param val 48-bit integer in host endianness.
468  *  @param dst Destination memory address to store the result.
469  */
sys_put_le48(uint64_t val,uint8_t dst[6])470 static inline void sys_put_le48(uint64_t val, uint8_t dst[6])
471 {
472 	sys_put_le32(val, dst);
473 	sys_put_le16(val >> 32, &dst[4]);
474 }
475 
476 /**
477  *  @brief Put a 64-bit integer as little-endian to arbitrary location.
478  *
479  *  Put a 64-bit integer, originally in host endianness, to a
480  *  potentially unaligned memory location in little-endian format.
481  *
482  *  @param val 64-bit integer in host endianness.
483  *  @param dst Destination memory address to store the result.
484  */
sys_put_le64(uint64_t val,uint8_t dst[8])485 static inline void sys_put_le64(uint64_t val, uint8_t dst[8])
486 {
487 	sys_put_le32(val, dst);
488 	sys_put_le32(val >> 32, &dst[4]);
489 }
490 
491 /**
492  *  @brief Get a 16-bit integer stored in big-endian format.
493  *
494  *  Get a 16-bit integer, stored in big-endian format in a potentially
495  *  unaligned memory location, and convert it to the host endianness.
496  *
497  *  @param src Location of the big-endian 16-bit integer to get.
498  *
499  *  @return 16-bit integer in host endianness.
500  */
sys_get_be16(const uint8_t src[2])501 static inline uint16_t sys_get_be16(const uint8_t src[2])
502 {
503 	return ((uint16_t)src[0] << 8) | src[1];
504 }
505 
506 /**
507  *  @brief Get a 24-bit integer stored in big-endian format.
508  *
509  *  Get a 24-bit integer, stored in big-endian format in a potentially
510  *  unaligned memory location, and convert it to the host endianness.
511  *
512  *  @param src Location of the big-endian 24-bit integer to get.
513  *
514  *  @return 24-bit integer in host endianness.
515  */
sys_get_be24(const uint8_t src[3])516 static inline uint32_t sys_get_be24(const uint8_t src[3])
517 {
518 	return ((uint32_t)src[0] << 16) | sys_get_be16(&src[1]);
519 }
520 
521 /**
522  *  @brief Get a 32-bit integer stored in big-endian format.
523  *
524  *  Get a 32-bit integer, stored in big-endian format in a potentially
525  *  unaligned memory location, and convert it to the host endianness.
526  *
527  *  @param src Location of the big-endian 32-bit integer to get.
528  *
529  *  @return 32-bit integer in host endianness.
530  */
sys_get_be32(const uint8_t src[4])531 static inline uint32_t sys_get_be32(const uint8_t src[4])
532 {
533 	return ((uint32_t)sys_get_be16(&src[0]) << 16) | sys_get_be16(&src[2]);
534 }
535 
536 /**
537  *  @brief Get a 40-bit integer stored in big-endian format.
538  *
539  *  Get a 40-bit integer, stored in big-endian format in a potentially
540  *  unaligned memory location, and convert it to the host endianness.
541  *
542  *  @param src Location of the big-endian 40-bit integer to get.
543  *
544  *  @return 40-bit integer in host endianness.
545  */
sys_get_be40(const uint8_t src[5])546 static inline uint64_t sys_get_be40(const uint8_t src[5])
547 {
548 	return ((uint64_t)sys_get_be32(&src[0]) << 8) | src[4];
549 }
550 
551 /**
552  *  @brief Get a 48-bit integer stored in big-endian format.
553  *
554  *  Get a 48-bit integer, stored in big-endian format in a potentially
555  *  unaligned memory location, and convert it to the host endianness.
556  *
557  *  @param src Location of the big-endian 48-bit integer to get.
558  *
559  *  @return 48-bit integer in host endianness.
560  */
sys_get_be48(const uint8_t src[6])561 static inline uint64_t sys_get_be48(const uint8_t src[6])
562 {
563 	return ((uint64_t)sys_get_be32(&src[0]) << 16) | sys_get_be16(&src[4]);
564 }
565 
566 /**
567  *  @brief Get a 64-bit integer stored in big-endian format.
568  *
569  *  Get a 64-bit integer, stored in big-endian format in a potentially
570  *  unaligned memory location, and convert it to the host endianness.
571  *
572  *  @param src Location of the big-endian 64-bit integer to get.
573  *
574  *  @return 64-bit integer in host endianness.
575  */
sys_get_be64(const uint8_t src[8])576 static inline uint64_t sys_get_be64(const uint8_t src[8])
577 {
578 	return ((uint64_t)sys_get_be32(&src[0]) << 32) | sys_get_be32(&src[4]);
579 }
580 
581 /**
582  *  @brief Get a 16-bit integer stored in little-endian format.
583  *
584  *  Get a 16-bit integer, stored in little-endian format in a potentially
585  *  unaligned memory location, and convert it to the host endianness.
586  *
587  *  @param src Location of the little-endian 16-bit integer to get.
588  *
589  *  @return 16-bit integer in host endianness.
590  */
sys_get_le16(const uint8_t src[2])591 static inline uint16_t sys_get_le16(const uint8_t src[2])
592 {
593 	return ((uint16_t)src[1] << 8) | src[0];
594 }
595 
596 /**
597  *  @brief Get a 24-bit integer stored in little-endian format.
598  *
599  *  Get a 24-bit integer, stored in little-endian format in a potentially
600  *  unaligned memory location, and convert it to the host endianness.
601  *
602  *  @param src Location of the little-endian 24-bit integer to get.
603  *
604  *  @return 24-bit integer in host endianness.
605  */
sys_get_le24(const uint8_t src[3])606 static inline uint32_t sys_get_le24(const uint8_t src[3])
607 {
608 	return ((uint32_t)src[2] << 16) | sys_get_le16(&src[0]);
609 }
610 
611 /**
612  *  @brief Get a 32-bit integer stored in little-endian format.
613  *
614  *  Get a 32-bit integer, stored in little-endian format in a potentially
615  *  unaligned memory location, and convert it to the host endianness.
616  *
617  *  @param src Location of the little-endian 32-bit integer to get.
618  *
619  *  @return 32-bit integer in host endianness.
620  */
sys_get_le32(const uint8_t src[4])621 static inline uint32_t sys_get_le32(const uint8_t src[4])
622 {
623 	return ((uint32_t)sys_get_le16(&src[2]) << 16) | sys_get_le16(&src[0]);
624 }
625 
626 /**
627  *  @brief Get a 40-bit integer stored in little-endian format.
628  *
629  *  Get a 40-bit integer, stored in little-endian format in a potentially
630  *  unaligned memory location, and convert it to the host endianness.
631  *
632  *  @param src Location of the little-endian 40-bit integer to get.
633  *
634  *  @return 40-bit integer in host endianness.
635  */
sys_get_le40(const uint8_t src[5])636 static inline uint64_t sys_get_le40(const uint8_t src[5])
637 {
638 	return ((uint64_t)sys_get_le32(&src[1]) << 8) | src[0];
639 }
640 
641 /**
642  *  @brief Get a 48-bit integer stored in little-endian format.
643  *
644  *  Get a 48-bit integer, stored in little-endian format in a potentially
645  *  unaligned memory location, and convert it to the host endianness.
646  *
647  *  @param src Location of the little-endian 48-bit integer to get.
648  *
649  *  @return 48-bit integer in host endianness.
650  */
sys_get_le48(const uint8_t src[6])651 static inline uint64_t sys_get_le48(const uint8_t src[6])
652 {
653 	return ((uint64_t)sys_get_le32(&src[2]) << 16) | sys_get_le16(&src[0]);
654 }
655 
656 /**
657  *  @brief Get a 64-bit integer stored in little-endian format.
658  *
659  *  Get a 64-bit integer, stored in little-endian format in a potentially
660  *  unaligned memory location, and convert it to the host endianness.
661  *
662  *  @param src Location of the little-endian 64-bit integer to get.
663  *
664  *  @return 64-bit integer in host endianness.
665  */
sys_get_le64(const uint8_t src[8])666 static inline uint64_t sys_get_le64(const uint8_t src[8])
667 {
668 	return ((uint64_t)sys_get_le32(&src[4]) << 32) | sys_get_le32(&src[0]);
669 }
670 
671 /**
672  * @brief Swap one buffer content into another
673  *
674  * Copy the content of src buffer into dst buffer in reversed order,
675  * i.e.: src[n] will be put in dst[end-n]
676  * Where n is an index and 'end' the last index in both arrays.
677  * The 2 memory pointers must be pointing to different areas, and have
678  * a minimum size of given length.
679  *
680  * @param dst A valid pointer on a memory area where to copy the data in
681  * @param src A valid pointer on a memory area where to copy the data from
682  * @param length Size of both dst and src memory areas
683  */
sys_memcpy_swap(void * dst,const void * src,size_t length)684 static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
685 {
686 	uint8_t *pdst = (uint8_t *)dst;
687 	const uint8_t *psrc = (const uint8_t *)src;
688 
689 	__ASSERT(((psrc < pdst && (psrc + length) <= pdst) ||
690 		  (psrc > pdst && (pdst + length) <= psrc)),
691 		 "Source and destination buffers must not overlap");
692 
693 	psrc += length - 1;
694 
695 	for (; length > 0; length--) {
696 		*pdst++ = *psrc--;
697 	}
698 }
699 
700 /**
701  * @brief Swap buffer content
702  *
703  * In-place memory swap, where final content will be reversed.
704  * I.e.: buf[n] will be put in buf[end-n]
705  * Where n is an index and 'end' the last index of buf.
706  *
707  * @param buf A valid pointer on a memory area to swap
708  * @param length Size of buf memory area
709  */
sys_mem_swap(void * buf,size_t length)710 static inline void sys_mem_swap(void *buf, size_t length)
711 {
712 	size_t i;
713 
714 	for (i = 0; i < (length/2); i++) {
715 		uint8_t tmp = ((uint8_t *)buf)[i];
716 
717 		((uint8_t *)buf)[i] = ((uint8_t *)buf)[length - 1 - i];
718 		((uint8_t *)buf)[length - 1 - i] = tmp;
719 	}
720 }
721 
722 #endif /* ZEPHYR_INCLUDE_SYS_BYTEORDER_H_ */
723