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