3      Copyright (C) Dean Camera, 2012. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, distribute, and sell this 
  13   software and its documentation for any purpose is hereby granted 
  14   without fee, provided that the above copyright notice appear in 
  15   all copies and that both that the copyright notice and this 
  16   permission notice and warranty disclaimer appear in supporting 
  17   documentation, and that the name of the author not be used in 
  18   advertising or publicity pertaining to distribution of the 
  19   software without specific, written prior permission. 
  21   The author disclaim all warranties with regard to this 
  22   software, including all implied warranties of merchantability 
  23   and fitness.  In no event shall the author be liable for any 
  24   special, indirect or consequential damages or any damages 
  25   whatsoever resulting from loss of use, data or profits, whether 
  26   in an action of contract, negligence or other tortious action, 
  27   arising out of or in connection with the use or performance of 
  32  *  \brief Endianness and Byte Ordering macros and functions. 
  34  *  \copydetails Group_Endianness 
  37 /** \ingroup Group_Endianness 
  38  *  \defgroup Group_ByteSwapping Byte Reordering 
  39  *  \brief Macros and functions for forced byte reordering. 
  42 /** \ingroup Group_Endianness 
  43  *  \defgroup Group_EndianConversion Endianness Conversion 
  44  *  \brief Macros and functions for automatic endianness conversion. 
  47 /** \ingroup Group_Common 
  48  *  \defgroup Group_Endianness Endianness and Byte Ordering 
  49  *  \brief Convenience macros and functions relating to byte (re-)ordering 
  51  *  Common library convenience macros and functions relating to byte (re-)ordering. 
  56 #ifndef __LUFA_ENDIANNESS_H__ 
  57 #define __LUFA_ENDIANNESS_H__ 
  59         /* Enable C linkage for C++ Compilers: */ 
  60                 #if defined(__cplusplus) 
  64         /* Preprocessor Checks: */ 
  65                 #if !defined(__INCLUDE_FROM_COMMON_H) 
  66                         #error Do not include this file directly. Include LUFA/Common/Common.h instead to gain this functionality. 
  69                 #if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN)) 
  70                         #error ARCH_BIG_ENDIAN or ARCH_LITTLE_ENDIAN not set for the specified architecture. 
  73         /* Public Interface - May be used in end-application: */ 
  75                         /** Swaps the byte ordering of a 16-bit value at compile-time. Do not use this macro for swapping byte orderings 
  76                          *  of dynamic values computed at runtime, use \ref SwapEndian_16() instead. The result of this macro can be used 
  77                          *  inside struct or other variable initializers outside of a function, something that is not possible with the 
  78                          *  inline function variant. 
  80                          *  \ingroup Group_ByteSwapping 
  82                          *  \param[in] x  16-bit value whose byte ordering is to be swapped. 
  84                          *  \return Input value with the byte ordering reversed. 
  86                         #define SWAPENDIAN_16(x)            (uint16_t)((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8)) 
  88                         /** Swaps the byte ordering of a 32-bit value at compile-time. Do not use this macro for swapping byte orderings 
  89                          *  of dynamic values computed at runtime- use \ref SwapEndian_32() instead. The result of this macro can be used 
  90                          *  inside struct or other variable initializers outside of a function, something that is not possible with the 
  91                          *  inline function variant. 
  93                          *  \ingroup Group_ByteSwapping 
  95                          *  \param[in] x  32-bit value whose byte ordering is to be swapped. 
  97                          *  \return Input value with the byte ordering reversed. 
  99                         #define SWAPENDIAN_32(x)            (uint32_t)((((x) & 0xFF000000UL) >> 24UL) | (((x) & 0x00FF0000UL) >> 8UL) | \ 
 100                                                                        (((x) & 0x0000FF00UL) << 8UL)  | (((x) & 0x000000FFUL) << 24UL)) 
 102                         #if defined(ARCH_BIG_ENDIAN) && !defined(le16_to_cpu) 
 103                                 #define le16_to_cpu(x)           SwapEndian_16(x) 
 104                                 #define le32_to_cpu(x)           SwapEndian_32(x) 
 105                                 #define be16_to_cpu(x)           (x) 
 106                                 #define be32_to_cpu(x)           (x) 
 107                                 #define cpu_to_le16(x)           SwapEndian_16(x) 
 108                                 #define cpu_to_le32(x)           SwapEndian_32(x) 
 109                                 #define cpu_to_be16(x)           (x) 
 110                                 #define cpu_to_be32(x)           (x) 
 111                                 #define LE16_TO_CPU(x)           SWAPENDIAN_16(x) 
 112                                 #define LE32_TO_CPU(x)           SWAPENDIAN_32(x) 
 113                                 #define BE16_TO_CPU(x)           (x) 
 114                                 #define BE32_TO_CPU(x)           (x) 
 115                                 #define CPU_TO_LE16(x)           SWAPENDIAN_16(x) 
 116                                 #define CPU_TO_LE32(x)           SWAPENDIAN_32(x) 
 117                                 #define CPU_TO_BE16(x)           (x) 
 118                                 #define CPU_TO_BE32(x)           (x) 
 119                         #elif !defined(le16_to_cpu) 
 120                                 /** \name Run-time endianness conversion */ 
 123                                 /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the 
 124                                  *  Endianness of the currently selected CPU architecture. 
 126                                  *  On little endian architectures, this macro does nothing. 
 128                                  *  \note This macro is designed for run-time conversion of data - for compile-time endianness 
 129                                  *        conversion, use \ref LE16_TO_CPU instead. 
 131                                  *  \ingroup Group_EndianConversion 
 133                                  *  \param[in] x  Data to perform the endianness conversion on. 
 135                                  *  \return Endian corrected version of the input value. 
 137                                 #define le16_to_cpu(x)           (x) 
 139                                 /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the 
 140                                  *  Endianness of the currently selected CPU architecture. 
 142                                  *  On little endian architectures, this macro does nothing. 
 144                                  *  \note This macro is designed for run-time conversion of data - for compile-time endianness 
 145                                  *        conversion, use \ref LE32_TO_CPU instead. 
 147                                  *  \ingroup Group_EndianConversion 
 149                                  *  \param[in] x  Data to perform the endianness conversion on. 
 151                                  *  \return Endian corrected version of the input value. 
 153                                 #define le32_to_cpu(x)           (x) 
 155                                 /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the 
 156                                  *  Endianness of the currently selected CPU architecture. 
 158                                  *  On big endian architectures, this macro does nothing. 
 160                                  *  \note This macro is designed for run-time conversion of data - for compile-time endianness 
 161                                  *        conversion, use \ref BE16_TO_CPU instead. 
 163                                  *  \ingroup Group_EndianConversion 
 165                                  *  \param[in] x  Data to perform the endianness conversion on. 
 167                                  *  \return Endian corrected version of the input value. 
 169                                 #define be16_to_cpu(x)           SwapEndian_16(x) 
 171                                 /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the 
 172                                  *  Endianness of the currently selected CPU architecture. 
 174                                  *  On big endian architectures, this macro does nothing. 
 176                                  *  \note This macro is designed for run-time conversion of data - for compile-time endianness 
 177                                  *        conversion, use \ref BE32_TO_CPU instead. 
 179                                  *  \ingroup Group_EndianConversion 
 181                                  *  \param[in] x  Data to perform the endianness conversion on. 
 183                                  *  \return Endian corrected version of the input value. 
 185                                 #define be32_to_cpu(x)           SwapEndian_32(x) 
 187                                 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it 
 188                                  *  is in Little Endian format regardless of the currently selected CPU architecture. 
 190                                  *  On little endian architectures, this macro does nothing. 
 192                                  *  \note This macro is designed for run-time conversion of data - for compile-time endianness 
 193                                  *        conversion, use \ref CPU_TO_LE16 instead. 
 195                                  *  \ingroup Group_EndianConversion 
 197                                  *  \param[in] x  Data to perform the endianness conversion on. 
 199                                  *  \return Endian corrected version of the input value. 
 201                                 #define cpu_to_le16(x)           (x) 
 203                                 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it 
 204                                  *  is in Little Endian format regardless of the currently selected CPU architecture. 
 206                                  *  On little endian architectures, this macro does nothing. 
 208                                  *  \note This macro is designed for run-time conversion of data - for compile-time endianness 
 209                                  *        conversion, use \ref CPU_TO_LE32 instead. 
 211                                  *  \ingroup Group_EndianConversion 
 213                                  *  \param[in] x  Data to perform the endianness conversion on. 
 215                                  *  \return Endian corrected version of the input value. 
 217                                 #define cpu_to_le32(x)           (x) 
 219                                 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it 
 220                                  *  is in Big Endian format regardless of the currently selected CPU architecture. 
 222                                  *  On big endian architectures, this macro does nothing. 
 224                                  *  \note This macro is designed for run-time conversion of data - for compile-time endianness 
 225                                  *        conversion, use \ref CPU_TO_BE16 instead. 
 227                                  *  \ingroup Group_EndianConversion 
 229                                  *  \param[in] x  Data to perform the endianness conversion on. 
 231                                  *  \return Endian corrected version of the input value. 
 233                                 #define cpu_to_be16(x)           SwapEndian_16(x) 
 235                                 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it 
 236                                  *  is in Big Endian format regardless of the currently selected CPU architecture. 
 238                                  *  On big endian architectures, this macro does nothing. 
 240                                  *  \note This macro is designed for run-time conversion of data - for compile-time endianness 
 241                                  *        conversion, use \ref CPU_TO_BE32 instead. 
 243                                  *  \ingroup Group_EndianConversion 
 245                                  *  \param[in] x  Data to perform the endianness conversion on. 
 247                                  *  \return Endian corrected version of the input value. 
 249                                 #define cpu_to_be32(x)           SwapEndian_32(x) 
 253                                 /** \name Compile-time endianness conversion */ 
 256                                 /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the 
 257                                  *  Endianness of the currently selected CPU architecture. 
 259                                  *  On little endian architectures, this macro does nothing. 
 261                                  *  \note This macro is designed for compile-time conversion of data - for run time endianness 
 262                                  *        conversion, use \ref le16_to_cpu instead. 
 264                                  *  \ingroup Group_EndianConversion 
 266                                  *  \param[in] x  Data to perform the endianness conversion on. 
 268                                  *  \return Endian corrected version of the input value. 
 270                                 #define LE16_TO_CPU(x)           (x) 
 272                                 /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the 
 273                                  *  Endianness of the currently selected CPU architecture. 
 275                                  *  On little endian architectures, this macro does nothing. 
 277                                  *  \note This macro is designed for compile-time conversion of data - for run time endianness 
 278                                  *        conversion, use \ref le32_to_cpu instead. 
 280                                  *  \ingroup Group_EndianConversion 
 282                                  *  \param[in] x  Data to perform the endianness conversion on. 
 284                                  *  \return Endian corrected version of the input value. 
 286                                 #define LE32_TO_CPU(x)           (x) 
 288                                 /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the 
 289                                  *  Endianness of the currently selected CPU architecture. 
 291                                  *  On big endian architectures, this macro does nothing. 
 293                                  *  \note This macro is designed for compile-time conversion of data - for run-time endianness 
 294                                  *        conversion, use \ref be16_to_cpu instead. 
 296                                  *  \ingroup Group_EndianConversion 
 298                                  *  \param[in] x  Data to perform the endianness conversion on. 
 300                                  *  \return Endian corrected version of the input value. 
 302                                 #define BE16_TO_CPU(x)           SWAPENDIAN_16(x) 
 304                                 /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the 
 305                                  *  Endianness of the currently selected CPU architecture. 
 307                                  *  On big endian architectures, this macro does nothing. 
 309                                  *  \note This macro is designed for compile-time conversion of data - for run-time endianness 
 310                                  *        conversion, use \ref be32_to_cpu instead. 
 312                                  *  \ingroup Group_EndianConversion 
 314                                  *  \param[in] x  Data to perform the endianness conversion on. 
 316                                  *  \return Endian corrected version of the input value. 
 318                                 #define BE32_TO_CPU(x)           SWAPENDIAN_32(x) 
 320                                 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it 
 321                                  *  is in Little Endian format regardless of the currently selected CPU architecture. 
 323                                  *  On little endian architectures, this macro does nothing. 
 325                                  *  \note This macro is designed for compile-time conversion of data - for run-time endianness 
 326                                  *        conversion, use \ref cpu_to_le16 instead. 
 328                                  *  \ingroup Group_EndianConversion 
 330                                  *  \param[in] x  Data to perform the endianness conversion on. 
 332                                  *  \return Endian corrected version of the input value. 
 334                                 #define CPU_TO_LE16(x)           (x) 
 336                                 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it 
 337                                  *  is in Little Endian format regardless of the currently selected CPU architecture. 
 339                                  *  On little endian architectures, this macro does nothing. 
 341                                  *  \note This macro is designed for compile-time conversion of data - for run-time endianness 
 342                                  *        conversion, use \ref cpu_to_le32 instead. 
 344                                  *  \ingroup Group_EndianConversion 
 346                                  *  \param[in] x  Data to perform the endianness conversion on. 
 348                                  *  \return Endian corrected version of the input value. 
 350                                 #define CPU_TO_LE32(x)           (x) 
 352                                 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it 
 353                                  *  is in Big Endian format regardless of the currently selected CPU architecture. 
 355                                  *  On big endian architectures, this macro does nothing. 
 357                                  *  \note This macro is designed for compile-time conversion of data - for run-time endianness 
 358                                  *        conversion, use \ref cpu_to_be16 instead. 
 360                                  *  \ingroup Group_EndianConversion 
 362                                  *  \param[in] x  Data to perform the endianness conversion on. 
 364                                  *  \return Endian corrected version of the input value. 
 366                                 #define CPU_TO_BE16(x)           SWAPENDIAN_16(x) 
 368                                 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it 
 369                                  *  is in Big Endian format regardless of the currently selected CPU architecture. 
 371                                  *  On big endian architectures, this macro does nothing. 
 373                                  *  \note This macro is designed for compile-time conversion of data - for run-time endianness 
 374                                  *        conversion, use \ref cpu_to_be32 instead. 
 376                                  *  \ingroup Group_EndianConversion 
 378                                  *  \param[in] x  Data to perform the endianness conversion on. 
 380                                  *  \return Endian corrected version of the input value. 
 382                                 #define CPU_TO_BE32(x)           SWAPENDIAN_32(x) 
 387                 /* Inline Functions: */ 
 388                         /** Function to reverse the byte ordering of the individual bytes in a 16 bit value. 
 390                          *  \ingroup Group_ByteSwapping 
 392                          *  \param[in] Word  Word of data whose bytes are to be swapped. 
 394                          *  \return Input data with the individual bytes reversed. 
 396                         static inline uint16_t SwapEndian_16(const uint16_t Word
) ATTR_WARN_UNUSED_RESULT ATTR_CONST
; 
 397                         static inline uint16_t SwapEndian_16(const uint16_t Word
) 
 399                                 if (GCC_IS_COMPILE_CONST(Word
)) 
 400                                   return SWAPENDIAN_16(Word
); 
 412                                 Temp 
= Data
.Bytes
[0]; 
 413                                 Data
.Bytes
[0] = Data
.Bytes
[1]; 
 414                                 Data
.Bytes
[1] = Temp
; 
 419                         /** Function to reverse the byte ordering of the individual bytes in a 32 bit value. 
 421                          *  \ingroup Group_ByteSwapping 
 423                          *  \param[in] DWord  Double word of data whose bytes are to be swapped. 
 425                          *  \return Input data with the individual bytes reversed. 
 427                         static inline uint32_t SwapEndian_32(const uint32_t DWord
) ATTR_WARN_UNUSED_RESULT ATTR_CONST
; 
 428                         static inline uint32_t SwapEndian_32(const uint32_t DWord
) 
 430                                 if (GCC_IS_COMPILE_CONST(DWord
)) 
 431                                   return SWAPENDIAN_32(DWord
); 
 443                                 Temp 
= Data
.Bytes
[0]; 
 444                                 Data
.Bytes
[0] = Data
.Bytes
[3]; 
 445                                 Data
.Bytes
[3] = Temp
; 
 447                                 Temp 
= Data
.Bytes
[1]; 
 448                                 Data
.Bytes
[1] = Data
.Bytes
[2]; 
 449                                 Data
.Bytes
[2] = Temp
; 
 454                         /** Function to reverse the byte ordering of the individual bytes in a n byte value. 
 456                          *  \ingroup Group_ByteSwapping 
 458                          *  \param[in,out] Data    Pointer to a number containing an even number of bytes to be reversed. 
 459                          *  \param[in]     Length  Length of the data in bytes. 
 461                          *  \return Input data with the individual bytes reversed. 
 463                         static inline void SwapEndian_n(void* const Data
, 
 464                                                         uint8_t Length
) ATTR_NON_NULL_PTR_ARG(1); 
 465                         static inline void SwapEndian_n(void* const Data
, 
 468                                 uint8_t* CurrDataPos 
= (uint8_t*)Data
; 
 472                                         uint8_t Temp 
= *CurrDataPos
; 
 473                                         *CurrDataPos 
= *(CurrDataPos 
+ Length 
- 1); 
 474                                         *(CurrDataPos 
+ Length 
- 1) = Temp
; 
 481         /* Disable C linkage for C++ Compilers: */ 
 482                 #if defined(__cplusplus)