diff --git a/core/include/byteorder.h b/core/include/byteorder.h index f2acea7f60..3e018897e6 100644 --- a/core/include/byteorder.h +++ b/core/include/byteorder.h @@ -20,6 +20,7 @@ #define BYTEORDER_H #include +#include "unaligned.h" #if defined(__MACH__) # include "clang_compat.h" @@ -485,7 +486,9 @@ static inline uint16_t byteorder_bebuftohs(const uint8_t *buf) #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ return (uint16_t)((buf[0] << 8) | (buf[1] << 0)); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - return (uint16_t)((buf[1] << 8) | (buf[0] << 0)); + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + return unaligned_get_u16(buf); #endif } @@ -497,10 +500,9 @@ static inline uint32_t byteorder_bebuftohl(const uint8_t *buf) | ((uint32_t) buf[2] << 8) | ((uint32_t) buf[3] << 0)); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - return (((uint32_t) buf[3] << 24) - | ((uint32_t) buf[2] << 16) - | ((uint32_t) buf[1] << 8) - | ((uint32_t) buf[0] << 0)); + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + return unaligned_get_u32(buf); #endif } @@ -510,8 +512,9 @@ static inline void byteorder_htobebufs(uint8_t *buf, uint16_t val) buf[0] = (uint8_t)(val >> 8); buf[1] = (uint8_t)(val >> 0); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - buf[1] = (uint8_t)(val >> 8); - buf[0] = (uint8_t)(val >> 0); + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + memcpy(buf, &val, sizeof(val)); #endif } @@ -523,10 +526,9 @@ static inline void byteorder_htobebufl(uint8_t *buf, uint32_t val) buf[2] = (uint8_t)(val >> 8); buf[3] = (uint8_t)(val >> 0); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - buf[3] = (uint8_t)(val >> 24); - buf[2] = (uint8_t)(val >> 16); - buf[1] = (uint8_t)(val >> 8); - buf[0] = (uint8_t)(val >> 0); + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + memcpy(buf, &val, sizeof(val)); #endif } diff --git a/sys/include/unaligned.h b/sys/include/unaligned.h index 9dba9ae2fd..ced46ac328 100644 --- a/sys/include/unaligned.h +++ b/sys/include/unaligned.h @@ -48,6 +48,11 @@ typedef struct __attribute__((packed)) { uint16_t val; /**< value */ } uint16_una_t; +/** @brief Unaligned access helper struct (uint32_t version) */ +typedef struct __attribute__((packed)) { + uint32_t val; /**< value */ +} uint32_una_t; + /** * @brief Get uint16_t from possibly unaligned pointer * @@ -57,7 +62,20 @@ typedef struct __attribute__((packed)) { */ static inline uint16_t unaligned_get_u16(const void *ptr) { - const uint16_una_t *tmp = ptr; + const uint16_una_t *tmp = (const uint16_una_t *)ptr; + return tmp->val; +} + +/** + * @brief Get uint32_t from possibly unaligned pointer + * + * @param[in] ptr pointer to read from + * + * @returns value read from @p ptr + */ +static inline uint32_t unaligned_get_u32(const void *ptr) +{ + const uint32_una_t *tmp = (const uint32_una_t *)ptr; return tmp->val; }