/** @file * @brief Byte order helpers. */ /* * Copyright (c) 2015-2016, Intel Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __BYTEORDER_H__ #define __BYTEORDER_H__ #include #include #include /* Internal helpers only used by the sys_* APIs further below */ #define __bswap_16(x) ((uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))) #define __bswap_32(x) ((uint32_t) ((((x) >> 24) & 0xff) | \ (((x) >> 8) & 0xff00) | \ (((x) & 0xff00) << 8) | \ (((x) & 0xff) << 24))) /** @def sys_le16_to_cpu * @brief Convert 16-bit integer from little-endian to host endianness. * * @param val 16-bit integer in little-endian format. * * @return 16-bit integer in host endianness. */ /** @def sys_cpu_to_le16 * @brief Convert 16-bit integer from host endianness to little-endian. * * @param val 16-bit integer in host endianness. * * @return 16-bit integer in little-endian format. */ /** @def sys_be16_to_cpu * @brief Convert 16-bit integer from big-endian to host endianness. * * @param val 16-bit integer in big-endian format. * * @return 16-bit integer in host endianness. */ /** @def sys_cpu_to_be16 * @brief Convert 16-bit integer from host endianness to big-endian. * * @param val 16-bit integer in host endianness. * * @return 16-bit integer in big-endian format. */ /** @def sys_le32_to_cpu * @brief Convert 32-bit integer from little-endian to host endianness. * * @param val 32-bit integer in little-endian format. * * @return 32-bit integer in host endianness. */ /** @def sys_cpu_to_le32 * @brief Convert 32-bit integer from host endianness to little-endian. * * @param val 32-bit integer in host endianness. * * @return 32-bit integer in little-endian format. */ /** @def sys_be32_to_cpu * @brief Convert 32-bit integer from big-endian to host endianness. * * @param val 32-bit integer in big-endian format. * * @return 32-bit integer in host endianness. */ /** @def sys_cpu_to_be32 * @brief Convert 32-bit integer from host endianness to big-endian. * * @param val 32-bit integer in host endianness. * * @return 32-bit integer in big-endian format. */ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define sys_le16_to_cpu(val) (val) #define sys_cpu_to_le16(val) (val) #define sys_be16_to_cpu(val) __bswap_16(val) #define sys_cpu_to_be16(val) __bswap_16(val) #define sys_le32_to_cpu(val) (val) #define sys_cpu_to_le32(val) (val) #define sys_be32_to_cpu(val) __bswap_32(val) #define sys_cpu_to_be32(val) __bswap_32(val) #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define sys_le16_to_cpu(val) __bswap_16(val) #define sys_cpu_to_le16(val) __bswap_16(val) #define sys_be16_to_cpu(val) (val) #define sys_cpu_to_be16(val) (val) #define sys_le32_to_cpu(val) __bswap_32(val) #define sys_cpu_to_le32(val) __bswap_32(val) #define sys_be32_to_cpu(val) (val) #define sys_cpu_to_be32(val) (val) #else #error "Unknown byte order" #endif /** * @brief Put a 16-bit intger as big-endian to arbitrary location. * * Put a 16-bit integer, originally in host endianness, to a * potentially unaligned memory location in big-endian format. * * @param val 16-bit integer in host endianness. * @param dst Destination memory address to store the result. */ static inline void sys_put_be16(uint16_t val, uint8_t dst[2]) { dst[0] = val >> 8; dst[1] = val; } /** * @brief Put a 32-bit intger as big-endian to arbitrary location. * * Put a 32-bit integer, originally in host endianness, to a * potentially unaligned memory location in big-endian format. * * @param val 32-bit integer in host endianness. * @param dst Destination memory address to store the result. */ static inline void sys_put_be32(uint32_t val, uint8_t dst[4]) { sys_put_be16(val >> 16, dst); sys_put_be16(val, &dst[2]); } /** * @brief Put a 16-bit intger as little-endian to arbitrary location. * * Put a 16-bit integer, originally in host endianness, to a * potentially unaligned memory location in little-endian format. * * @param val 16-bit integer in host endianness. * @param dst Destination memory address to store the result. */ static inline void sys_put_le16(uint16_t val, uint8_t dst[2]) { dst[0] = val; dst[1] = val >> 8; } /** * @brief Put a 32-bit intger as little-endian to arbitrary location. * * Put a 32-bit integer, originally in host endianness, to a * potentially unaligned memory location in little-endian format. * * @param val 32-bit integer in host endianness. * @param dst Destination memory address to store the result. */ static inline void sys_put_le32(uint32_t val, uint8_t dst[4]) { sys_put_le16(val, dst); sys_put_le16(val >> 16, &dst[2]); } /** * @brief Put a 64-bit integer as little-endian to arbitrary location. * * Put a 64-bit integer, originally in host endianness, to a * potentially unaligned memory location in little-endian format. * * @param val 64-bit integer in host endianness. * @param dst Destination memory address to store the result. */ static inline void sys_put_le64(uint64_t val, uint8_t dst[8]) { sys_put_le32(val, dst); sys_put_le32(val >> 32, &dst[4]); } /** * @brief Get a 16-bit intger stored in big-endian format. * * Get a 16-bit integer, stored in big-endian format in a potentially * unaligned memory location, and convert it to the host endianness. * * @param src Location of the big-endian 16-bit integer to get. * * @return 16-bit integer in host endianness. */ static inline uint16_t sys_get_be16(const uint8_t src[2]) { return ((uint16_t)src[0] << 8) | src[1]; } /** * @brief Get a 32-bit intger stored in big-endian format. * * Get a 32-bit integer, stored in big-endian format in a potentially * unaligned memory location, and convert it to the host endianness. * * @param src Location of the big-endian 32-bit integer to get. * * @return 32-bit integer in host endianness. */ static inline uint32_t sys_get_be32(const uint8_t src[4]) { return ((uint32_t)sys_get_be16(&src[0]) << 16) | sys_get_be16(&src[2]); } /** * @brief Get a 16-bit intger stored in little-endian format. * * Get a 16-bit integer, stored in little-endian format in a potentially * unaligned memory location, and convert it to the host endianness. * * @param src Location of the little-endian 16-bit integer to get. * * @return 16-bit integer in host endianness. */ static inline uint16_t sys_get_le16(const uint8_t src[2]) { return ((uint16_t)src[1] << 8) | src[0]; } /** * @brief Get a 32-bit intger stored in little-endian format. * * Get a 32-bit integer, stored in little-endian format in a potentially * unaligned memory location, and convert it to the host endianness. * * @param src Location of the little-endian 32-bit integer to get. * * @return 32-bit integer in host endianness. */ static inline uint32_t sys_get_le32(const uint8_t src[4]) { return ((uint32_t)sys_get_le16(&src[2]) << 16) | sys_get_le16(&src[0]); } /** * @brief Get a 64-bit integer stored in little-endian format. * * Get a 64-bit integer, stored in little-endian format in a potentially * unaligned memory location, and convert it to the host endianness. * * @param src Location of the little-endian 64-bit integer to get. * * @return 64-bit integer in host endianness. */ static inline uint64_t sys_get_le64(const uint8_t src[8]) { return ((uint64_t)sys_get_le32(&src[4]) << 32) | sys_get_le32(&src[0]); } /** * @brief Swap one buffer content into another * * Copy the content of src buffer into dst buffer in reversed order, * i.e.: src[n] will be put in dst[end-n] * Where n is an index and 'end' the last index in both arrays. * The 2 memory pointers must be pointing to different areas, and have * a minimum size of given length. * * @param dst A valid pointer on a memory area where to copy the data in * @param src A valid pointer on a memory area where to copy the data from * @param length Size of both dst and src memory areas */ static inline void sys_memcpy_swap(void *dst, const void *src, size_t length) { __ASSERT(((src < dst && (src + length) <= dst) || (src > dst && (dst + length) <= src)), "Source and destination buffers must not overlap"); src += length - 1; for (; length > 0; length--) { *((uint8_t *)dst++) = *((uint8_t *)src--); } } /** * @brief Swap buffer content * * In-place memory swap, where final content will be reversed. * I.e.: buf[n] will be put in buf[end-n] * Where n is an index and 'end' the last index of buf. * * @param buf A valid pointer on a memory area to swap * @param length Size of buf memory area */ static inline void sys_mem_swap(void *buf, size_t length) { int i; for (i = 0; i < (length/2); i++) { uint8_t tmp = ((uint8_t *)buf)[i]; ((uint8_t *)buf)[i] = ((uint8_t *)buf)[length - 1 - i]; ((uint8_t *)buf)[length - 1 - i] = tmp; } } #endif /* __BYTEORDER_H__ */