byteorder.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2016 Intel Corporation.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #ifndef _BLE_MESH_BYTEORDER_H_
  7. #define _BLE_MESH_BYTEORDER_H_
  8. #include "mesh/types.h"
  9. #include "mesh/trace.h"
  10. #ifdef __cplusplus
  11. extern "C" {
  12. #endif
  13. /* Internal helpers only used by the sys_* APIs further below */
  14. #ifndef __bswap_16
  15. #define __bswap_16(x) ((uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
  16. #endif
  17. #ifndef __bswap_24
  18. #define __bswap_24(x) ((uint32_t) ((((x) >> 16) & 0xff) | \
  19. (((x)) & 0xff00) | \
  20. (((x) & 0xff) << 16)))
  21. #endif
  22. #ifndef __bswap_32
  23. #define __bswap_32(x) ((uint32_t) ((((x) >> 24) & 0xff) | \
  24. (((x) >> 8) & 0xff00) | \
  25. (((x) & 0xff00) << 8) | \
  26. (((x) & 0xff) << 24)))
  27. #endif
  28. #ifndef __bswap_48
  29. #define __bswap_48(x) ((uint64_t) ((((x) >> 40) & 0xff) | \
  30. (((x) >> 24) & 0xff00) | \
  31. (((x) >> 8) & 0xff0000) | \
  32. (((x) & 0xff0000) << 8) | \
  33. (((x) & 0xff00) << 24) | \
  34. (((x) & 0xff) << 40)))
  35. #endif
  36. #ifndef __bswap_64
  37. #define __bswap_64(x) ((uint64_t) ((((x) >> 56) & 0xff) | \
  38. (((x) >> 40) & 0xff00) | \
  39. (((x) >> 24) & 0xff0000) | \
  40. (((x) >> 8) & 0xff000000) | \
  41. (((x) & 0xff000000) << 8) | \
  42. (((x) & 0xff0000) << 24) | \
  43. (((x) & 0xff00) << 40) | \
  44. (((x) & 0xff) << 56)))
  45. #endif
  46. /** @def sys_le16_to_cpu
  47. * @brief Convert 16-bit integer from little-endian to host endianness.
  48. *
  49. * @param val 16-bit integer in little-endian format.
  50. *
  51. * @return 16-bit integer in host endianness.
  52. */
  53. /** @def sys_cpu_to_le16
  54. * @brief Convert 16-bit integer from host endianness to little-endian.
  55. *
  56. * @param val 16-bit integer in host endianness.
  57. *
  58. * @return 16-bit integer in little-endian format.
  59. */
  60. /** @def sys_le24_to_cpu
  61. * @brief Convert 24-bit integer from little-endian to host endianness.
  62. *
  63. * @param val 24-bit integer in little-endian format.
  64. *
  65. * @return 24-bit integer in host endianness.
  66. */
  67. /** @def sys_cpu_to_le24
  68. * @brief Convert 24-bit integer from host endianness to little-endian.
  69. *
  70. * @param val 24-bit integer in host endianness.
  71. *
  72. * @return 24-bit integer in little-endian format.
  73. */
  74. /** @def sys_le32_to_cpu
  75. * @brief Convert 32-bit integer from little-endian to host endianness.
  76. *
  77. * @param val 32-bit integer in little-endian format.
  78. *
  79. * @return 32-bit integer in host endianness.
  80. */
  81. /** @def sys_cpu_to_le32
  82. * @brief Convert 32-bit integer from host endianness to little-endian.
  83. *
  84. * @param val 32-bit integer in host endianness.
  85. *
  86. * @return 32-bit integer in little-endian format.
  87. */
  88. /** @def sys_le48_to_cpu
  89. * @brief Convert 48-bit integer from little-endian to host endianness.
  90. *
  91. * @param val 48-bit integer in little-endian format.
  92. *
  93. * @return 48-bit integer in host endianness.
  94. */
  95. /** @def sys_cpu_to_le48
  96. * @brief Convert 48-bit integer from host endianness to little-endian.
  97. *
  98. * @param val 48-bit integer in host endianness.
  99. *
  100. * @return 48-bit integer in little-endian format.
  101. */
  102. /** @def sys_be16_to_cpu
  103. * @brief Convert 16-bit integer from big-endian to host endianness.
  104. *
  105. * @param val 16-bit integer in big-endian format.
  106. *
  107. * @return 16-bit integer in host endianness.
  108. */
  109. /** @def sys_cpu_to_be16
  110. * @brief Convert 16-bit integer from host endianness to big-endian.
  111. *
  112. * @param val 16-bit integer in host endianness.
  113. *
  114. * @return 16-bit integer in big-endian format.
  115. */
  116. /** @def sys_be24_to_cpu
  117. * @brief Convert 24-bit integer from big-endian to host endianness.
  118. *
  119. * @param val 24-bit integer in big-endian format.
  120. *
  121. * @return 24-bit integer in host endianness.
  122. */
  123. /** @def sys_cpu_to_be24
  124. * @brief Convert 24-bit integer from host endianness to big-endian.
  125. *
  126. * @param val 24-bit integer in host endianness.
  127. *
  128. * @return 24-bit integer in big-endian format.
  129. */
  130. /** @def sys_be32_to_cpu
  131. * @brief Convert 32-bit integer from big-endian to host endianness.
  132. *
  133. * @param val 32-bit integer in big-endian format.
  134. *
  135. * @return 32-bit integer in host endianness.
  136. */
  137. /** @def sys_cpu_to_be32
  138. * @brief Convert 32-bit integer from host endianness to big-endian.
  139. *
  140. * @param val 32-bit integer in host endianness.
  141. *
  142. * @return 32-bit integer in big-endian format.
  143. */
  144. /** @def sys_be48_to_cpu
  145. * @brief Convert 48-bit integer from big-endian to host endianness.
  146. *
  147. * @param val 48-bit integer in big-endian format.
  148. *
  149. * @return 48-bit integer in host endianness.
  150. */
  151. /** @def sys_cpu_to_be48
  152. * @brief Convert 48-bit integer from host endianness to big-endian.
  153. *
  154. * @param val 48-bit integer in host endianness.
  155. *
  156. * @return 48-bit integer in big-endian format.
  157. */
  158. #ifndef sys_le16_to_cpu
  159. #define sys_le16_to_cpu(val) (val)
  160. #endif
  161. #ifndef sys_cpu_to_le16
  162. #define sys_cpu_to_le16(val) (val)
  163. #endif
  164. #ifndef sys_le24_to_cpu
  165. #define sys_le24_to_cpu(val) (val)
  166. #endif
  167. #ifndef sys_cpu_to_le24
  168. #define sys_cpu_to_le24(val) (val)
  169. #endif
  170. #ifndef sys_le32_to_cpu
  171. #define sys_le32_to_cpu(val) (val)
  172. #endif
  173. #ifndef sys_cpu_to_le32
  174. #define sys_cpu_to_le32(val) (val)
  175. #endif
  176. #ifndef sys_le48_to_cpu
  177. #define sys_le48_to_cpu(val) (val)
  178. #endif
  179. #ifndef sys_cpu_to_le48
  180. #define sys_cpu_to_le48(val) (val)
  181. #endif
  182. #ifndef sys_le64_to_cpu
  183. #define sys_le64_to_cpu(val) (val)
  184. #endif
  185. #ifndef sys_cpu_to_le64
  186. #define sys_cpu_to_le64(val) (val)
  187. #endif
  188. #ifndef sys_be16_to_cpu
  189. #define sys_be16_to_cpu(val) __bswap_16(val)
  190. #endif
  191. #ifndef sys_cpu_to_be16
  192. #define sys_cpu_to_be16(val) __bswap_16(val)
  193. #endif
  194. #ifndef sys_be24_to_cpu
  195. #define sys_be24_to_cpu(val) __bswap_24(val)
  196. #endif
  197. #ifndef sys_cpu_to_be24
  198. #define sys_cpu_to_be24(val) __bswap_24(val)
  199. #endif
  200. #ifndef sys_be32_to_cpu
  201. #define sys_be32_to_cpu(val) __bswap_32(val)
  202. #endif
  203. #ifndef sys_cpu_to_be32
  204. #define sys_cpu_to_be32(val) __bswap_32(val)
  205. #endif
  206. #ifndef sys_be48_to_cpu
  207. #define sys_be48_to_cpu(val) __bswap_48(val)
  208. #endif
  209. #ifndef sys_cpu_to_be48
  210. #define sys_cpu_to_be48(val) __bswap_48(val)
  211. #endif
  212. #ifndef sys_be64_to_cpu
  213. #define sys_be64_to_cpu(val) __bswap_64(val)
  214. #endif
  215. #ifndef sys_cpu_to_be64
  216. #define sys_cpu_to_be64(val) __bswap_64(val)
  217. #endif
  218. /**
  219. * @brief Put a 16-bit integer as big-endian to arbitrary location.
  220. *
  221. * Put a 16-bit integer, originally in host endianness, to a
  222. * potentially unaligned memory location in big-endian format.
  223. *
  224. * @param val 16-bit integer in host endianness.
  225. * @param dst Destination memory address to store the result.
  226. */
  227. static inline void sys_put_be16(uint16_t val, uint8_t dst[2])
  228. {
  229. dst[0] = val >> 8;
  230. dst[1] = val;
  231. }
  232. /**
  233. * @brief Put a 24-bit integer as big-endian to arbitrary location.
  234. *
  235. * Put a 24-bit integer, originally in host endianness, to a
  236. * potentially unaligned memory location in big-endian format.
  237. *
  238. * @param val 24-bit integer in host endianness.
  239. * @param dst Destination memory address to store the result.
  240. */
  241. static inline void sys_put_be24(uint32_t val, uint8_t dst[3])
  242. {
  243. dst[0] = val >> 16;
  244. sys_put_be16(val, &dst[1]);
  245. }
  246. /**
  247. * @brief Put a 32-bit integer as big-endian to arbitrary location.
  248. *
  249. * Put a 32-bit integer, originally in host endianness, to a
  250. * potentially unaligned memory location in big-endian format.
  251. *
  252. * @param val 32-bit integer in host endianness.
  253. * @param dst Destination memory address to store the result.
  254. */
  255. static inline void sys_put_be32(uint32_t val, uint8_t dst[4])
  256. {
  257. sys_put_be16(val >> 16, dst);
  258. sys_put_be16(val, &dst[2]);
  259. }
  260. /**
  261. * @brief Put a 48-bit integer as big-endian to arbitrary location.
  262. *
  263. * Put a 48-bit integer, originally in host endianness, to a
  264. * potentially unaligned memory location in big-endian format.
  265. *
  266. * @param val 48-bit integer in host endianness.
  267. * @param dst Destination memory address to store the result.
  268. */
  269. static inline void sys_put_be48(uint64_t val, uint8_t dst[6])
  270. {
  271. sys_put_be16(val >> 32, dst);
  272. sys_put_be32(val, &dst[2]);
  273. }
  274. /**
  275. * @brief Put a 64-bit integer as big-endian to arbitrary location.
  276. *
  277. * Put a 64-bit integer, originally in host endianness, to a
  278. * potentially unaligned memory location in big-endian format.
  279. *
  280. * @param val 64-bit integer in host endianness.
  281. * @param dst Destination memory address to store the result.
  282. */
  283. static inline void sys_put_be64(uint64_t val, uint8_t dst[8])
  284. {
  285. sys_put_be32(val >> 32, dst);
  286. sys_put_be32(val, &dst[4]);
  287. }
  288. /**
  289. * @brief Put a 16-bit integer as little-endian to arbitrary location.
  290. *
  291. * Put a 16-bit integer, originally in host endianness, to a
  292. * potentially unaligned memory location in little-endian format.
  293. *
  294. * @param val 16-bit integer in host endianness.
  295. * @param dst Destination memory address to store the result.
  296. */
  297. static inline void sys_put_le16(uint16_t val, uint8_t dst[2])
  298. {
  299. dst[0] = val;
  300. dst[1] = val >> 8;
  301. }
  302. /**
  303. * @brief Put a 24-bit integer as little-endian to arbitrary location.
  304. *
  305. * Put a 24-bit integer, originally in host endianness, to a
  306. * potentially unaligned memory location in little-endian format.
  307. *
  308. * @param val 24-bit integer in host endianness.
  309. * @param dst Destination memory address to store the result.
  310. */
  311. static inline void sys_put_le24(uint32_t val, uint8_t dst[3])
  312. {
  313. sys_put_le16(val, dst);
  314. dst[2] = val >> 16;
  315. }
  316. /**
  317. * @brief Put a 32-bit integer as little-endian to arbitrary location.
  318. *
  319. * Put a 32-bit integer, originally in host endianness, to a
  320. * potentially unaligned memory location in little-endian format.
  321. *
  322. * @param val 32-bit integer in host endianness.
  323. * @param dst Destination memory address to store the result.
  324. */
  325. static inline void sys_put_le32(uint32_t val, uint8_t dst[4])
  326. {
  327. sys_put_le16(val, dst);
  328. sys_put_le16(val >> 16, &dst[2]);
  329. }
  330. /**
  331. * @brief Put a 48-bit integer as little-endian to arbitrary location.
  332. *
  333. * Put a 48-bit integer, originally in host endianness, to a
  334. * potentially unaligned memory location in little-endian format.
  335. *
  336. * @param val 48-bit integer in host endianness.
  337. * @param dst Destination memory address to store the result.
  338. */
  339. static inline void sys_put_le48(uint64_t val, uint8_t dst[6])
  340. {
  341. sys_put_le32(val, dst);
  342. sys_put_le16(val >> 32, &dst[4]);
  343. }
  344. /**
  345. * @brief Put a 64-bit integer as little-endian to arbitrary location.
  346. *
  347. * Put a 64-bit integer, originally in host endianness, to a
  348. * potentially unaligned memory location in little-endian format.
  349. *
  350. * @param val 64-bit integer in host endianness.
  351. * @param dst Destination memory address to store the result.
  352. */
  353. static inline void sys_put_le64(uint64_t val, uint8_t dst[8])
  354. {
  355. sys_put_le32(val, dst);
  356. sys_put_le32(val >> 32, &dst[4]);
  357. }
  358. /**
  359. * @brief Get a 16-bit integer stored in big-endian format.
  360. *
  361. * Get a 16-bit integer, stored in big-endian format in a potentially
  362. * unaligned memory location, and convert it to the host endianness.
  363. *
  364. * @param src Location of the big-endian 16-bit integer to get.
  365. *
  366. * @return 16-bit integer in host endianness.
  367. */
  368. static inline uint16_t sys_get_be16(const uint8_t src[2])
  369. {
  370. return ((uint16_t)src[0] << 8) | src[1];
  371. }
  372. /**
  373. * @brief Get a 24-bit integer stored in big-endian format.
  374. *
  375. * Get a 24-bit integer, stored in big-endian format in a potentially
  376. * unaligned memory location, and convert it to the host endianness.
  377. *
  378. * @param src Location of the big-endian 24-bit integer to get.
  379. *
  380. * @return 24-bit integer in host endianness.
  381. */
  382. static inline uint32_t sys_get_be24(const uint8_t src[3])
  383. {
  384. return ((uint32_t)src[0] << 16) | sys_get_be16(&src[1]);
  385. }
  386. /**
  387. * @brief Get a 32-bit integer stored in big-endian format.
  388. *
  389. * Get a 32-bit integer, stored in big-endian format in a potentially
  390. * unaligned memory location, and convert it to the host endianness.
  391. *
  392. * @param src Location of the big-endian 32-bit integer to get.
  393. *
  394. * @return 32-bit integer in host endianness.
  395. */
  396. static inline uint32_t sys_get_be32(const uint8_t src[4])
  397. {
  398. return ((uint32_t)sys_get_be16(&src[0]) << 16) | sys_get_be16(&src[2]);
  399. }
  400. /**
  401. * @brief Get a 48-bit integer stored in big-endian format.
  402. *
  403. * Get a 48-bit integer, stored in big-endian format in a potentially
  404. * unaligned memory location, and convert it to the host endianness.
  405. *
  406. * @param src Location of the big-endian 48-bit integer to get.
  407. *
  408. * @return 48-bit integer in host endianness.
  409. */
  410. static inline uint64_t sys_get_be48(const uint8_t src[6])
  411. {
  412. return ((uint64_t)sys_get_be32(&src[0]) << 32) | sys_get_be16(&src[4]);
  413. }
  414. /**
  415. * @brief Get a 64-bit integer stored in big-endian format.
  416. *
  417. * Get a 64-bit integer, stored in big-endian format in a potentially
  418. * unaligned memory location, and convert it to the host endianness.
  419. *
  420. * @param src Location of the big-endian 64-bit integer to get.
  421. *
  422. * @return 64-bit integer in host endianness.
  423. */
  424. static inline uint64_t sys_get_be64(const uint8_t src[8])
  425. {
  426. return ((uint64_t)sys_get_be32(&src[0]) << 32) | sys_get_be32(&src[4]);
  427. }
  428. /**
  429. * @brief Get a 16-bit integer stored in little-endian format.
  430. *
  431. * Get a 16-bit integer, stored in little-endian format in a potentially
  432. * unaligned memory location, and convert it to the host endianness.
  433. *
  434. * @param src Location of the little-endian 16-bit integer to get.
  435. *
  436. * @return 16-bit integer in host endianness.
  437. */
  438. static inline uint16_t sys_get_le16(const uint8_t src[2])
  439. {
  440. return ((uint16_t)src[1] << 8) | src[0];
  441. }
  442. /**
  443. * @brief Get a 24-bit integer stored in big-endian format.
  444. *
  445. * Get a 24-bit integer, stored in big-endian format in a potentially
  446. * unaligned memory location, and convert it to the host endianness.
  447. *
  448. * @param src Location of the big-endian 24-bit integer to get.
  449. *
  450. * @return 24-bit integer in host endianness.
  451. */
  452. static inline uint32_t sys_get_le24(const uint8_t src[3])
  453. {
  454. return ((uint32_t)src[2] << 16) | sys_get_le16(&src[0]);
  455. }
  456. /**
  457. * @brief Get a 32-bit integer stored in little-endian format.
  458. *
  459. * Get a 32-bit integer, stored in little-endian format in a potentially
  460. * unaligned memory location, and convert it to the host endianness.
  461. *
  462. * @param src Location of the little-endian 32-bit integer to get.
  463. *
  464. * @return 32-bit integer in host endianness.
  465. */
  466. static inline uint32_t sys_get_le32(const uint8_t src[4])
  467. {
  468. return ((uint32_t)sys_get_le16(&src[2]) << 16) | sys_get_le16(&src[0]);
  469. }
  470. /**
  471. * @brief Get a 48-bit integer stored in little-endian format.
  472. *
  473. * Get a 48-bit integer, stored in little-endian format in a potentially
  474. * unaligned memory location, and convert it to the host endianness.
  475. *
  476. * @param src Location of the little-endian 48-bit integer to get.
  477. *
  478. * @return 48-bit integer in host endianness.
  479. */
  480. static inline uint64_t sys_get_le48(const uint8_t src[6])
  481. {
  482. return ((uint64_t)sys_get_le32(&src[2]) << 32) | sys_get_le16(&src[0]);
  483. }
  484. /**
  485. * @brief Get a 64-bit integer stored in little-endian format.
  486. *
  487. * Get a 64-bit integer, stored in little-endian format in a potentially
  488. * unaligned memory location, and convert it to the host endianness.
  489. *
  490. * @param src Location of the little-endian 64-bit integer to get.
  491. *
  492. * @return 64-bit integer in host endianness.
  493. */
  494. static inline uint64_t sys_get_le64(const uint8_t src[8])
  495. {
  496. return ((uint64_t)sys_get_le32(&src[4]) << 32) | sys_get_le32(&src[0]);
  497. }
  498. /**
  499. * @brief Swap one buffer content into another
  500. *
  501. * Copy the content of src buffer into dst buffer in reversed order,
  502. * i.e.: src[n] will be put in dst[end-n]
  503. * Where n is an index and 'end' the last index in both arrays.
  504. * The 2 memory pointers must be pointing to different areas, and have
  505. * a minimum size of given length.
  506. *
  507. * @param dst A valid pointer on a memory area where to copy the data in
  508. * @param src A valid pointer on a memory area where to copy the data from
  509. * @param length Size of both dst and src memory areas
  510. */
  511. static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
  512. {
  513. uint8_t *pdst = (uint8_t *)dst;
  514. const uint8_t *psrc = (const uint8_t *)src;
  515. __ASSERT(((psrc < pdst && (psrc + length) <= pdst) ||
  516. (psrc > pdst && (pdst + length) <= psrc)),
  517. "Source and destination buffers must not overlap");
  518. psrc += length - 1;
  519. for (; length > 0; length--) {
  520. *pdst++ = *psrc--;
  521. }
  522. }
  523. /**
  524. * @brief Swap buffer content
  525. *
  526. * In-place memory swap, where final content will be reversed.
  527. * I.e.: buf[n] will be put in buf[end-n]
  528. * Where n is an index and 'end' the last index of buf.
  529. *
  530. * @param buf A valid pointer on a memory area to swap
  531. * @param length Size of buf memory area
  532. */
  533. static inline void sys_mem_swap(void *buf, size_t length)
  534. {
  535. size_t i;
  536. for (i = 0; i < (length / 2); i++) {
  537. uint8_t tmp = ((uint8_t *)buf)[i];
  538. ((uint8_t *)buf)[i] = ((uint8_t *)buf)[length - 1 - i];
  539. ((uint8_t *)buf)[length - 1 - i] = tmp;
  540. }
  541. }
  542. #ifdef __cplusplus
  543. }
  544. #endif
  545. #endif /* _BLE_MESH_BYTEORDER_H_ */