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