aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Embedded_SW/Embedded/Common
diff options
context:
space:
mode:
authorShlomo Hecht <shlomo@twine-s.com>2018-03-06 12:09:02 +0200
committerShlomo Hecht <shlomo@twine-s.com>2018-03-06 12:09:02 +0200
commitfb2d080fbbcea3a91e598b4ea8837a230de6a319 (patch)
tree6b3ce09a252d2ebab8189a92b3326ffbba6dbe4b /Software/Embedded_SW/Embedded/Common
parentd734bb5cf08ba2433b74fc86a8858d2437d1a237 (diff)
downloadTango-fb2d080fbbcea3a91e598b4ea8837a230de6a319.tar.gz
Tango-fb2d080fbbcea3a91e598b4ea8837a230de6a319.zip
A new forlder for embedded software in our common structure
Diffstat (limited to 'Software/Embedded_SW/Embedded/Common')
-rw-r--r--Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.c723
-rw-r--r--Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.h40
-rw-r--r--Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.c996
-rw-r--r--Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.h74
-rw-r--r--Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.c621
-rw-r--r--Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.h43
-rw-r--r--Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.c51
-rw-r--r--Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.h14
-rw-r--r--Software/Embedded_SW/Embedded/Common/Utilities/Update.c98
-rw-r--r--Software/Embedded_SW/Embedded/Common/Utilities/Utils.c245
-rw-r--r--Software/Embedded_SW/Embedded/Common/Utilities/Utils.h33
-rw-r--r--Software/Embedded_SW/Embedded/Common/Utilities/ustdlib.c1825
-rw-r--r--Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.c227
-rw-r--r--Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.h112
-rw-r--r--Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.c3642
-rw-r--r--Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.h1106
-rw-r--r--Software/Embedded_SW/Embedded/Common/report/distributor.c851
-rw-r--r--Software/Embedded_SW/Embedded/Common/report/distributor.h94
-rw-r--r--Software/Embedded_SW/Embedded/Common/report/filter.c526
-rw-r--r--Software/Embedded_SW/Embedded/Common/report/filter.h74
-rw-r--r--Software/Embedded_SW/Embedded/Common/report/report.h593
-rw-r--r--Software/Embedded_SW/Embedded/Common/report/reportInit.c161
22 files changed, 12149 insertions, 0 deletions
diff --git a/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.c b/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.c
new file mode 100644
index 000000000..76f9c0398
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.c
@@ -0,0 +1,723 @@
+
+//*****************************************************************************
+//
+//! \addtogroup sw_crc_api
+//! @{
+//
+//*****************************************************************************
+#include "Common/Software_CRC/sw_crc.h"
+
+//*****************************************************************************
+//
+// The CRC table for the polynomial C(x) = x^8 + x^2 + x + 1 (CRC-8-CCITT).
+//
+//*****************************************************************************
+static const uint8_t g_pui8Crc8CCITT[256] =
+{
+ 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
+ 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
+ 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
+ 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
+ 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
+ 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
+ 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
+ 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
+ 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
+ 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
+ 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
+ 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
+ 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
+ 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
+ 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
+ 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
+ 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
+ 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
+ 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
+ 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
+ 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
+ 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
+ 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
+ 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
+ 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
+ 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
+ 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
+ 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
+ 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
+ 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
+ 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
+ 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
+};
+
+//*****************************************************************************
+//
+// The CRC-16 table for the polynomial C(x) = x^16 + x^15 + x^2 + 1 (standard
+// CRC-16, also known as CRC-16-IBM and CRC-16-ANSI).
+//
+//*****************************************************************************
+static const uint16_t g_pui16Crc16[256] =
+{
+ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+ 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+ 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+ 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+ 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+ 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+ 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+ 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+ 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+ 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+ 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+ 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+ 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+ 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+ 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+ 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+ 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+ 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+ 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+ 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+ 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+ 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+ 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+ 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+ 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+ 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+ 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+ 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+ 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+ 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+ 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+ 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
+};
+
+//*****************************************************************************
+//
+// The CRC-32 table for the polynomial C(x) = x^32 + x^26 + x^23 + x^22 +
+// x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 (standard
+// CRC32 as used in Ethernet, MPEG-2, PNG, etc.).
+//
+//*****************************************************************************
+static const uint32_t g_pui32Crc32[] =
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+//*****************************************************************************
+//
+// This macro executes one iteration of the CRC-8-CCITT.
+//
+//*****************************************************************************
+#define CRC8_ITER(crc, data) g_pui8Crc8CCITT[(uint8_t)((crc) ^ (data))]
+
+//*****************************************************************************
+//
+// This macro executes one iteration of the CRC-16.
+//
+//*****************************************************************************
+#define CRC16_ITER(crc, data) (((crc) >> 8) ^ \
+ g_pui16Crc16[(uint8_t)((crc) ^ (data))])
+
+//*****************************************************************************
+//
+// This macro executes one iteration of the CRC-32.
+//
+//*****************************************************************************
+#define CRC32_ITER(crc, data) (((crc) >> 8) ^ \
+ g_pui32Crc32[(uint8_t)((crc & 0xFF) ^ \
+ (data))])
+
+//*****************************************************************************
+//
+//! Calculates the CRC-8-CCITT of an array of bytes.
+//!
+//! \param ui8Crc is the starting CRC-8-CCITT value.
+//! \param pui8Data is a pointer to the data buffer.
+//! \param ui32Count is the number of bytes in the data buffer.
+//!
+//! This function is used to calculate the CRC-8-CCITT of the input buffer.
+//! The CRC-8-CCITT is computed in a running fashion, meaning that the entire
+//! data block that is to have its CRC-8-CCITT computed does not need to be
+//! supplied all at once. If the input buffer contains the entire block of
+//! data, then \b ui8Crc should be set to 0. If, however, the entire block of
+//! data is not available, then \b ui8Crc should be set to 0 for the first
+//! portion of the data, and then the returned value should be passed back in
+//! as \b ui8Crc for the next portion of the data.
+//!
+//! For example, to compute the CRC-8-CCITT of a block that has been split into
+//! three pieces, use the following:
+//!
+//! \verbatim
+//! ui8Crc = Crc8CCITT(0, pui8Data1, ui32Len1);
+//! ui8Crc = Crc8CCITT(ui8Crc, pui8Data2, ui32Len2);
+//! ui8Crc = Crc8CCITT(ui8Crc, pui8Data3, ui32Len3);
+//! \endverbatim
+//!
+//! Computing a CRC-8-CCITT in a running fashion is useful in cases where the
+//! data is arriving via a serial link (for example) and is therefore not all
+//! available at one time.
+//!
+//! \return The CRC-8-CCITT of the input data.
+//
+//*****************************************************************************
+uint8_t
+Crc8CCITT(uint8_t ui8Crc, const uint8_t *pui8Data, uint32_t ui32Count)
+{
+ uint32_t ui32Temp;
+
+ //
+ // If the data buffer is not 16 bit-aligned, then perform a single step of
+ // the CRC to make it 16 bit-aligned.
+ //
+ if((uint32_t)pui8Data & 1)
+ {
+ //
+ // Perform the CRC on this input byte.
+ //
+ ui8Crc = CRC8_ITER(ui8Crc, *pui8Data);
+
+ //
+ // Skip this input byte.
+ //
+ pui8Data++;
+ ui32Count--;
+ }
+
+ //
+ // If the data buffer is not word-aligned and there are at least two bytes
+ // of data left, then perform two steps of the CRC to make it word-aligned.
+ //
+ if(((uint32_t)pui8Data & 2) && (ui32Count > 1))
+ {
+ //
+ // Read the next 16 bits.
+ //
+ ui32Temp = *(uint16_t *)pui8Data;
+
+ //
+ // Perform the CRC on these two bytes.
+ //
+ ui8Crc = CRC8_ITER(ui8Crc, ui32Temp);
+ ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 8);
+
+ //
+ // Skip these input bytes.
+ //
+ pui8Data += 2;
+ ui32Count -= 2;
+ }
+
+ //
+ // While there is at least a word remaining in the data buffer, perform
+ // four steps of the CRC to consume a word.
+ //
+ while(ui32Count > 3)
+ {
+ //
+ // Read the next word.
+ //
+ ui32Temp = *(uint32_t *)pui8Data;
+
+ //
+ // Perform the CRC on these four bytes.
+ //
+ ui8Crc = CRC8_ITER(ui8Crc, ui32Temp);
+ ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 8);
+ ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 16);
+ ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 24);
+
+ //
+ // Skip these input bytes.
+ //
+ pui8Data += 4;
+ ui32Count -= 4;
+ }
+
+ //
+ // If there are 16 bits left in the input buffer, then perform two steps of
+ // the CRC.
+ //
+ if(ui32Count > 1)
+ {
+ //
+ // Read the 16 bits.
+ //
+ ui32Temp = *(uint16_t *)pui8Data;
+
+ //
+ // Perform the CRC on these two bytes.
+ //
+ ui8Crc = CRC8_ITER(ui8Crc, ui32Temp);
+ ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 8);
+
+ //
+ // Skip these input bytes.
+ //
+ pui8Data += 2;
+ ui32Count -= 2;
+ }
+
+ //
+ // If there is a final byte remaining in the input buffer, then perform a
+ // single step of the CRC.
+ //
+ if(ui32Count != 0)
+ {
+ ui8Crc = CRC8_ITER(ui8Crc, *pui8Data);
+ }
+
+ //
+ // Return the resulting CRC-8-CCITT value.
+ //
+ return(ui8Crc);
+}
+
+//*****************************************************************************
+//
+//! Calculates the CRC-16 of an array of bytes.
+//!
+//! \param ui16Crc is the starting CRC-16 value.
+//! \param pui8Data is a pointer to the data buffer.
+//! \param ui32Count is the number of bytes in the data buffer.
+//!
+//! This function is used to calculate the CRC-16 of the input buffer. The
+//! CRC-16 is computed in a running fashion, meaning that the entire data block
+//! that is to have its CRC-16 computed does not need to be supplied all at
+//! once. If the input buffer contains the entire block of data, then
+//! \b ui16Crc should be set to 0. If, however, the entire block of data is
+//! not available, then \b ui16Crc should be set to 0 for the first portion of
+//! the data, and then the returned value should be passed back in as
+//! \b ui16Crc for the next portion of the data.
+//!
+//! For example, to compute the CRC-16 of a block that has been split into
+//! three pieces, use the following:
+//!
+//! \verbatim
+//! ui16Crc = Crc16(0, pui8Data1, ui32Len1);
+//! ui16Crc = Crc16(ui16Crc, pui8Data2, ui32Len2);
+//! ui16Crc = Crc16(ui16Crc, pui8Data3, ui32Len3);
+//! \endverbatim
+//!
+//! Computing a CRC-16 in a running fashion is useful in cases where the data
+//! is arriving via a serial link (for example) and is therefore not all
+//! available at one time.
+//!
+//! \return The CRC-16 of the input data.
+//
+//*****************************************************************************
+uint16_t
+Crc16(uint16_t ui16Crc, const uint8_t *pui8Data, uint32_t ui32Count)
+{
+ uint32_t ui32Temp;
+
+ //
+ // If the data buffer is not 16 bit-aligned, then perform a single step of
+ // the CRC to make it 16 bit-aligned.
+ //
+ if((uint32_t)pui8Data & 1)
+ {
+ //
+ // Perform the CRC on this input byte.
+ //
+ ui16Crc = CRC16_ITER(ui16Crc, *pui8Data);
+
+ //
+ // Skip this input byte.
+ //
+ pui8Data++;
+ ui32Count--;
+ }
+
+ //
+ // If the data buffer is not word-aligned and there are at least two bytes
+ // of data left, then perform two steps of the CRC to make it word-aligned.
+ //
+ if(((uint32_t)pui8Data & 2) && (ui32Count > 1))
+ {
+ //
+ // Read the next 16 bits.
+ //
+ ui32Temp = *(uint16_t *)pui8Data;
+
+ //
+ // Perform the CRC on these two bytes.
+ //
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp);
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 8);
+
+ //
+ // Skip these input bytes.
+ //
+ pui8Data += 2;
+ ui32Count -= 2;
+ }
+
+ //
+ // While there is at least a word remaining in the data buffer, perform
+ // four steps of the CRC to consume a word.
+ //
+ while(ui32Count > 3)
+ {
+ //
+ // Read the next word.
+ //
+ ui32Temp = *(uint32_t *)pui8Data;
+
+ //
+ // Perform the CRC on these four bytes.
+ //
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp);
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 8);
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 16);
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 24);
+
+ //
+ // Skip these input bytes.
+ //
+ pui8Data += 4;
+ ui32Count -= 4;
+ }
+
+ //
+ // If there are two bytes left in the input buffer, then perform two steps
+ // of the CRC.
+ //
+ if(ui32Count > 1)
+ {
+ //
+ // Read the two bytes.
+ //
+ ui32Temp = *(uint16_t *)pui8Data;
+
+ //
+ // Perform the CRC on these two bytes.
+ //
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp);
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 8);
+
+ //
+ // Skip these input bytes.
+ //
+ pui8Data += 2;
+ ui32Count -= 2;
+ }
+
+ //
+ // If there is a final byte remaining in the input buffer, then perform a
+ // single step of the CRC.
+ //
+ if(ui32Count != 0)
+ {
+ ui16Crc = CRC16_ITER(ui16Crc, *pui8Data);
+ }
+
+ //
+ // Return the resulting CRC-16 value.
+ //
+ return(ui16Crc);
+}
+
+//*****************************************************************************
+//
+//! Calculates the CRC-16 of an array of words.
+//!
+//! \param ui32WordLen is the length of the array in words (the number of bytes
+//! divided by 4).
+//! \param pui32Data is a pointer to the data buffer.
+//!
+//! This function is a wrapper around the running CRC-16 function, providing
+//! the CRC-16 for a single block of data.
+//!
+//! \return The CRC-16 of the input data.
+//
+//*****************************************************************************
+uint16_t
+Crc16Array(uint32_t ui32WordLen, const uint32_t *pui32Data)
+{
+ //
+ // Calculate and return the CRC-16 of this array of words.
+ //
+ return(Crc16(0, (const uint8_t *)pui32Data, ui32WordLen * 4));
+}
+
+//*****************************************************************************
+//
+//! Calculates three CRC-16s of an array of words.
+//!
+//! \param ui32WordLen is the length of the array in words (the number of bytes
+//! divided by 4).
+//! \param pui32Data is a pointer to the data buffer.
+//! \param pui16Crc3 is a pointer to an array in which to place the three
+//! CRC-16 values.
+//!
+//! This function is used to calculate three CRC-16s of the input buffer; the
+//! first uses every byte from the array, the second uses only the even-index
+//! bytes from the array (in other words, bytes 0, 2, 4, etc.), and the third
+//! uses only the odd-index bytes from the array (in other words, bytes 1, 3,
+//! 5, etc.).
+//!
+//! \return None
+//
+//*****************************************************************************
+void
+Crc16Array3(uint32_t ui32WordLen, const uint32_t *pui32Data,
+ uint16_t *pui16Crc3)
+{
+ uint16_t ui16Crc, ui16Cri8Odd, ui16Cri8Even;
+
+ //
+ // Initialize the CRC values to zero.
+ //
+ ui16Crc = 0;
+ ui16Cri8Odd = 0;
+ ui16Cri8Even = 0;
+
+ //
+ // Loop while there are more words in the data buffer.
+ //
+ while(ui32WordLen--)
+ {
+ //
+ // Read the next word.
+ //
+ uint32_t ui32Temp = *pui32Data++;
+
+ //
+ // Perform the first CRC on all four data bytes.
+ //
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp);
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 8);
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 16);
+ ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 24);
+
+ //
+ // Perform the second CRC on only the even-index data bytes.
+ //
+ ui16Cri8Even = CRC16_ITER(ui16Cri8Even, ui32Temp);
+ ui16Cri8Even = CRC16_ITER(ui16Cri8Even, ui32Temp >> 16);
+
+ //
+ // Perform the third CRC on only the odd-index data bytes.
+ //
+ ui16Cri8Odd = CRC16_ITER(ui16Cri8Odd, ui32Temp >> 8);
+ ui16Cri8Odd = CRC16_ITER(ui16Cri8Odd, ui32Temp >> 24);
+ }
+
+ //
+ // Return the resulting CRC-16 values.
+ //
+ pui16Crc3[0] = ui16Crc;
+ pui16Crc3[1] = ui16Cri8Even;
+ pui16Crc3[2] = ui16Cri8Odd;
+}
+
+//*****************************************************************************
+//
+//! Calculates the CRC-32 of an array of bytes.
+//!
+//! \param ui32Crc is the starting CRC-32 value.
+//! \param pui8Data is a pointer to the data buffer.
+//! \param ui32Count is the number of bytes in the data buffer.
+//!
+//! This function is used to calculate the CRC-32 of the input buffer. The
+//! CRC-32 is computed in a running fashion, meaning that the entire data block
+//! that is to have its CRC-32 computed does not need to be supplied all at
+//! once. If the input buffer contains the entire block of data, then
+//! \b ui32Crc should be set to 0xFFFFFFFF. If, however, the entire block of
+//! data is not available, then \b ui32Crc should be set to 0xFFFFFFFF for the
+//! first portion of the data, and then the returned value should be passed
+//! back in as \b ui32Crc for the next portion of the data. Once all data has
+//! been passed to the function, the final CRC-32 can be obtained by inverting
+//! the last returned value.
+//!
+//! For example, to compute the CRC-32 of a block that has been split into
+//! three pieces, use the following:
+//!
+//! \verbatim
+//! ui32Crc = Crc32(0xFFFFFFFF, pui8Data1, ui32Len1);
+//! ui32Crc = Crc32(ui32Crc, pui8Data2, ui32Len2);
+//! ui32Crc = Crc32(ui32Crc, pui8Data3, ui32Len3);
+//! ui32Crc ^= 0xFFFFFFFF;
+//! \endverbatim
+//!
+//! Computing a CRC-32 in a running fashion is useful in cases where the data
+//! is arriving via a serial link (for example) and is therefore not all
+//! available at one time.
+//!
+//! \return The accumulated CRC-32 of the input data.
+//
+//*****************************************************************************
+uint32_t
+Crc32(uint32_t ui32Crc, const uint8_t *pui8Data, uint32_t ui32Count)
+{
+ uint32_t ui32Temp;
+
+ //
+ // If the data buffer is not 16 bit-aligned, then perform a single step
+ // of the CRC to make it 16 bit-aligned.
+ //
+ if((uint32_t)pui8Data & 1)
+ {
+ //
+ // Perform the CRC on this input byte.
+ //
+ ui32Crc = CRC32_ITER(ui32Crc, *pui8Data);
+
+ //
+ // Skip this input byte.
+ //
+ pui8Data++;
+ ui32Count--;
+ }
+
+ //
+ // If the data buffer is not word-aligned and there are at least two bytes
+ // of data left, then perform two steps of the CRC to make it word-aligned.
+ //
+ if(((uint32_t)pui8Data & 2) && (ui32Count > 1))
+ {
+ //
+ // Read the next int16_t.
+ //
+ ui32Temp = *(uint16_t *)pui8Data;
+
+ //
+ // Perform the CRC on these two bytes.
+ //
+ ui32Crc = CRC32_ITER(ui32Crc, ui32Temp);
+ ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 8);
+
+ //
+ // Skip these input bytes.
+ //
+ pui8Data += 2;
+ ui32Count -= 2;
+ }
+
+ //
+ // While there is at least a word remaining in the data buffer, perform
+ // four steps of the CRC to consume a word.
+ //
+ while(ui32Count > 3)
+ {
+ //
+ // Read the next word.
+ //
+ ui32Temp = *(uint32_t *)pui8Data;
+
+ //
+ // Perform the CRC on these four bytes.
+ //
+ ui32Crc = CRC32_ITER(ui32Crc, ui32Temp);
+ ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 8);
+ ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 16);
+ ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 24);
+
+ //
+ // Skip these input bytes.
+ //
+ pui8Data += 4;
+ ui32Count -= 4;
+ }
+
+ //
+ // If there are 16 bits left in the input buffer, then perform two steps of
+ // the CRC.
+ //
+ if(ui32Count > 1)
+ {
+ //
+ // Read the two bytes.
+ //
+ ui32Temp = *(uint16_t *)pui8Data;
+
+ //
+ // Perform the CRC on these two bytes.
+ //
+ ui32Crc = CRC32_ITER(ui32Crc, ui32Temp);
+ ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 8);
+
+ //
+ // Skip these input bytes.
+ //
+ pui8Data += 2;
+ ui32Count -= 2;
+ }
+
+ //
+ // If there is a final byte remaining in the input buffer, then perform a
+ // single step of the CRC.
+ //
+ if(ui32Count != 0)
+ {
+ ui32Crc = CRC32_ITER(ui32Crc, *pui8Data);
+ }
+
+ //
+ // Return the resulting CRC-32 value.
+ //
+ return(ui32Crc);
+}
+
diff --git a/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.h b/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.h
new file mode 100644
index 000000000..92f4c1ee7
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.h
@@ -0,0 +1,40 @@
+
+#ifndef COMMON_SW_CRC_H_
+#define COMMON_SW_CRC_H_
+//*****************************************************************************
+//
+// If building with a C++ compiler, make all of the definitions in this header
+// have a C binding.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include <stdint.h>
+
+//*****************************************************************************
+//
+// Prototypes for the functions.
+//
+//*****************************************************************************
+extern uint8_t Crc8CCITT(uint8_t ui8Crc, const uint8_t *pui8Data,
+ uint32_t ui32Count);
+extern uint16_t Crc16(uint16_t ui16Crc, const uint8_t *pui8Data,
+ uint32_t ui32Count);
+extern uint16_t Crc16Array(uint32_t ui32WordLen, const uint32_t *pui32Data);
+extern void Crc16Array3(uint32_t ui32WordLen, const uint32_t *pui32Data,
+ uint16_t *pui16Crc3);
+extern uint32_t Crc32(uint32_t ui32Crc, const uint8_t *pui8Data,
+ uint32_t ui32Count);
+
+//*****************************************************************************
+//
+// Mark the end of the C bindings section for C++ compilers.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* COMMON_SW_CRC_H_ */
diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.c b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.c
new file mode 100644
index 000000000..2899a6a41
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.c
@@ -0,0 +1,996 @@
+//*****************************************************************************
+//
+// Configure the device pins for different signals
+//
+// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// Neither the name of Texas Instruments Incorporated nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+// This file was automatically generated on 25.2.2018 at 10:21:42
+// by TI PinMux version 4.0.1510
+//
+//*****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "inc/hw_gpio.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_types.h"
+#include "driverlib/gpio.h"
+#include "driverlib/pin_map.h"
+#include "driverlib/rom.h"
+#include "driverlib/rom_map.h"
+#include "driverlib/sysctl.h"
+#include "pinout.h"
+
+//*****************************************************************************
+//
+//! \addtogroup pinout_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! Configures the device pins for the customer specific usage.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+PinoutSet(void)
+{
+ //
+ // Enable Peripheral Clocks
+ //
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOR);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOS);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOT);
+
+ //
+ // Configure the GPIO Pin Mux for PD1
+ // for AIN14
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PE3
+ // for AIN0
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PK1
+ // for AIN17
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PE6
+ // for AIN20
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_6);
+
+ //
+ // Unlock the Port Pin and Set the Commit Bit
+ //
+ HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY;
+ HWREG(GPIO_PORTD_BASE+GPIO_O_CR) |= GPIO_PIN_7;
+ HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK) = 0x0;
+
+ //
+ // Configure the GPIO Pin Mux for PD7
+ // for AIN4
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PD5
+ // for AIN6
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PD0
+ // for AIN15
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PD3
+ // for AIN12
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PE1
+ // for AIN2
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PB5
+ // for AIN11
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PK3
+ // for AIN19
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PK0
+ // for AIN16
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PD2
+ // for AIN13
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PE4
+ // for AIN9
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_4);
+
+ //
+ // Unlock the Port Pin and Set the Commit Bit
+ //
+ HWREG(GPIO_PORTE_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY;
+ HWREG(GPIO_PORTE_BASE+GPIO_O_CR) |= GPIO_PIN_7;
+ HWREG(GPIO_PORTE_BASE+GPIO_O_LOCK) = 0x0;
+
+ //
+ // Configure the GPIO Pin Mux for PE7
+ // for AIN21
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PE5
+ // for AIN8
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PE2
+ // for AIN1
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PE0
+ // for AIN3
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PK2
+ // for AIN18
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PB4
+ // for AIN10
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PD4
+ // for AIN7
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PD6
+ // for AIN5
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PT2
+ // for CAN1RX
+ //
+ MAP_GPIOPinConfigure(GPIO_PT2_CAN1RX);
+ MAP_GPIOPinTypeCAN(GPIO_PORTT_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PT3
+ // for CAN1TX
+ //
+ MAP_GPIOPinConfigure(GPIO_PT3_CAN1TX);
+ MAP_GPIOPinTypeCAN(GPIO_PORTT_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PK4
+ // for EPI0S32
+ //
+ MAP_GPIOPinConfigure(GPIO_PK4_EPI0S32);
+ GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PL4
+ // for EPI0S26
+ //
+ MAP_GPIOPinConfigure(GPIO_PL4_EPI0S26);
+ GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PK6
+ // for EPI0S25
+ //
+ MAP_GPIOPinConfigure(GPIO_PK6_EPI0S25);
+ GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PL0
+ // for EPI0S16
+ //
+ MAP_GPIOPinConfigure(GPIO_PL0_EPI0S16);
+ GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PG0
+ // for EPI0S11
+ //
+ MAP_GPIOPinConfigure(GPIO_PG0_EPI0S11);
+ GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PA6
+ // for EPI0S8
+ //
+ MAP_GPIOPinConfigure(GPIO_PA6_EPI0S8);
+ GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PH1
+ // for EPI0S1
+ //
+ MAP_GPIOPinConfigure(GPIO_PH1_EPI0S1);
+ GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PN3
+ // for EPI0S30
+ //
+ MAP_GPIOPinConfigure(GPIO_PN3_EPI0S30);
+ GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PB2
+ // for EPI0S27
+ //
+ MAP_GPIOPinConfigure(GPIO_PB2_EPI0S27);
+ GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PN4
+ // for EPI0S34
+ //
+ MAP_GPIOPinConfigure(GPIO_PN4_EPI0S34);
+ GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PQ1
+ // for EPI0S21
+ //
+ MAP_GPIOPinConfigure(GPIO_PQ1_EPI0S21);
+ GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PL3
+ // for EPI0S19
+ //
+ MAP_GPIOPinConfigure(GPIO_PL3_EPI0S19);
+ GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PM0
+ // for EPI0S15
+ //
+ MAP_GPIOPinConfigure(GPIO_PM0_EPI0S15);
+ GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PM2
+ // for EPI0S13
+ //
+ MAP_GPIOPinConfigure(GPIO_PM2_EPI0S13);
+ GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PB3
+ // for EPI0S28
+ //
+ MAP_GPIOPinConfigure(GPIO_PB3_EPI0S28);
+ GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PQ3
+ // for EPI0S23
+ //
+ MAP_GPIOPinConfigure(GPIO_PQ3_EPI0S23);
+ GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PG1
+ // for EPI0S10
+ //
+ MAP_GPIOPinConfigure(GPIO_PG1_EPI0S10);
+ GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PK5
+ // for EPI0S31
+ //
+ MAP_GPIOPinConfigure(GPIO_PK5_EPI0S31);
+ GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PN2
+ // for EPI0S29
+ //
+ MAP_GPIOPinConfigure(GPIO_PN2_EPI0S29);
+ GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PH3
+ // for EPI0S3
+ //
+ MAP_GPIOPinConfigure(GPIO_PH3_EPI0S3);
+ GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PC5
+ // for EPI0S6
+ //
+ MAP_GPIOPinConfigure(GPIO_PC5_EPI0S6);
+ GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PA7
+ // for EPI0S9
+ //
+ MAP_GPIOPinConfigure(GPIO_PA7_EPI0S9);
+ GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PH0
+ // for EPI0S0
+ //
+ MAP_GPIOPinConfigure(GPIO_PH0_EPI0S0);
+ GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PC4
+ // for EPI0S7
+ //
+ MAP_GPIOPinConfigure(GPIO_PC4_EPI0S7);
+ GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PL1
+ // for EPI0S17
+ //
+ MAP_GPIOPinConfigure(GPIO_PL1_EPI0S17);
+ GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PL5
+ // for EPI0S33
+ //
+ MAP_GPIOPinConfigure(GPIO_PL5_EPI0S33);
+ GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PN5
+ // for EPI0S35
+ //
+ MAP_GPIOPinConfigure(GPIO_PN5_EPI0S35);
+ GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PM1
+ // for EPI0S14
+ //
+ MAP_GPIOPinConfigure(GPIO_PM1_EPI0S14);
+ GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PK7
+ // for EPI0S24
+ //
+ MAP_GPIOPinConfigure(GPIO_PK7_EPI0S24);
+ GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PC7
+ // for EPI0S4
+ //
+ MAP_GPIOPinConfigure(GPIO_PC7_EPI0S4);
+ GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PL2
+ // for EPI0S18
+ //
+ MAP_GPIOPinConfigure(GPIO_PL2_EPI0S18);
+ GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PM3
+ // for EPI0S12
+ //
+ MAP_GPIOPinConfigure(GPIO_PM3_EPI0S12);
+ GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PQ0
+ // for EPI0S20
+ //
+ MAP_GPIOPinConfigure(GPIO_PQ0_EPI0S20);
+ GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PQ2
+ // for EPI0S22
+ //
+ MAP_GPIOPinConfigure(GPIO_PQ2_EPI0S22);
+ GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PC6
+ // for EPI0S5
+ //
+ MAP_GPIOPinConfigure(GPIO_PC6_EPI0S5);
+ GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PH2
+ // for EPI0S2
+ //
+ MAP_GPIOPinConfigure(GPIO_PH2_EPI0S2);
+ GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PB6
+ // for GPIO_PB6
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PB7
+ // for GPIO_PB7
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PJ3
+ // for GPIO_PJ3
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PQ6
+ // for GPIO_PQ6
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PS5
+ // for GPIO_PS5
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PS7
+ // for GPIO_PS7
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PN7
+ // for GPIO_PN7
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTN_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PS6
+ // for GPIO_PS6
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PT1
+ // for GPIO_PT1
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTT_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PT0
+ // for GPIO_PT0
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTT_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PS4
+ // for GPIO_PS4
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PN6
+ // for GPIO_PN6
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PF6
+ // for GPIO_PF6
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PM7
+ // for GPIO_PM7
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTM_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PM6
+ // for GPIO_PM6
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PF7
+ // for GPIO_PF7
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PR3
+ // for GPIO_PR3
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTR_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PM4
+ // for GPIO_PM4
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PJ2
+ // for GPIO_PJ2
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PM5
+ // for GPIO_PM5
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PH4
+ // for GPIO_PH4
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PH7
+ // for GPIO_PH7
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PH6
+ // for GPIO_PH6
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PH5
+ // for GPIO_PH5
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PQ7
+ // for GPIO_PQ7
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PJ4
+ // for GPIO_PJ4
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PJ5
+ // for GPIO_PJ5
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PS2
+ // for GPIO_PS2
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PS3
+ // for GPIO_PS3
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PJ7
+ // for GPIO_PJ7
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PS1
+ // for GPIO_PS1
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PP5
+ // for GPIO_PP5
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PP3
+ // for GPIO_PP3
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PS0
+ // for GPIO_PS0
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PN1
+ // for GPIO_PN1
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PN0
+ // for GPIO_PN0
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PJ0
+ // for GPIO_PJ0
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PP4
+ // for GPIO_PP4
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PJ1
+ // for GPIO_PJ1
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PP0
+ // for GPIO_PP0
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PP1
+ // for GPIO_PP1
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PP2
+ // for GPIO_PP2
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PR2
+ // for GPIO_PR2
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTR_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PJ6
+ // for GPIO_PJ6
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PP6
+ // for GPIO_PP6
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PP7
+ // for GPIO_PP7
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PR6
+ // for I2C4SCL
+ //
+ MAP_GPIOPinConfigure(GPIO_PR6_I2C4SCL);
+ MAP_GPIOPinTypeI2CSCL(GPIO_PORTR_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PR7
+ // for I2C4SDA
+ //
+ MAP_GPIOPinConfigure(GPIO_PR7_I2C4SDA);
+ MAP_GPIOPinTypeI2C(GPIO_PORTR_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PR4
+ // for I2C3SCL
+ //
+ MAP_GPIOPinConfigure(GPIO_PR4_I2C3SCL);
+ MAP_GPIOPinTypeI2CSCL(GPIO_PORTR_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PR5
+ // for I2C3SDA
+ //
+ MAP_GPIOPinConfigure(GPIO_PR5_I2C3SDA);
+ MAP_GPIOPinTypeI2C(GPIO_PORTR_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PG2
+ // for I2C2SCL
+ //
+ MAP_GPIOPinConfigure(GPIO_PG2_I2C2SCL);
+ MAP_GPIOPinTypeI2CSCL(GPIO_PORTG_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PG3
+ // for I2C2SDA
+ //
+ MAP_GPIOPinConfigure(GPIO_PG3_I2C2SDA);
+ MAP_GPIOPinTypeI2C(GPIO_PORTG_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PR0
+ // for I2C1SCL
+ //
+ MAP_GPIOPinConfigure(GPIO_PR0_I2C1SCL);
+ MAP_GPIOPinTypeI2CSCL(GPIO_PORTR_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PR1
+ // for I2C1SDA
+ //
+ MAP_GPIOPinConfigure(GPIO_PR1_I2C1SDA);
+ MAP_GPIOPinTypeI2C(GPIO_PORTR_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PF1
+ // for SSI3XDAT0
+ //
+ MAP_GPIOPinConfigure(GPIO_PF1_SSI3XDAT0);
+ MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PF5
+ // for SSI3XDAT3
+ //
+ MAP_GPIOPinConfigure(GPIO_PF5_SSI3XDAT3);
+ MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PF0
+ // for SSI3XDAT1
+ //
+ MAP_GPIOPinConfigure(GPIO_PF0_SSI3XDAT1);
+ MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PF2
+ // for SSI3FSS
+ //
+ MAP_GPIOPinConfigure(GPIO_PF2_SSI3FSS);
+ MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PF4
+ // for SSI3XDAT2
+ //
+ MAP_GPIOPinConfigure(GPIO_PF4_SSI3XDAT2);
+ MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PF3
+ // for SSI3CLK
+ //
+ MAP_GPIOPinConfigure(GPIO_PF3_SSI3CLK);
+ MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PG5
+ // for SSI2XDAT0
+ //
+ MAP_GPIOPinConfigure(GPIO_PG5_SSI2XDAT0);
+ MAP_GPIOPinTypeSSI(GPIO_PORTG_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PG4
+ // for SSI2XDAT1
+ //
+ MAP_GPIOPinConfigure(GPIO_PG4_SSI2XDAT1);
+ MAP_GPIOPinTypeSSI(GPIO_PORTG_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PG6
+ // for SSI2FSS
+ //
+ MAP_GPIOPinConfigure(GPIO_PG6_SSI2FSS);
+ MAP_GPIOPinTypeSSI(GPIO_PORTG_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PG7
+ // for SSI2CLK
+ //
+ MAP_GPIOPinConfigure(GPIO_PG7_SSI2CLK);
+ MAP_GPIOPinTypeSSI(GPIO_PORTG_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PA0
+ // for U0RX
+ //
+ MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
+ MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PA1
+ // for U0TX
+ //
+ MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
+ MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_1);
+
+ //
+ // Configure the GPIO Pin Mux for PQ4
+ // for U1RX
+ //
+ MAP_GPIOPinConfigure(GPIO_PQ4_U1RX);
+ MAP_GPIOPinTypeUART(GPIO_PORTQ_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PQ5
+ // for U1TX
+ //
+ MAP_GPIOPinConfigure(GPIO_PQ5_U1TX);
+ MAP_GPIOPinTypeUART(GPIO_PORTQ_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PA4
+ // for U3RX
+ //
+ MAP_GPIOPinConfigure(GPIO_PA4_U3RX);
+ MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_4);
+
+ //
+ // Configure the GPIO Pin Mux for PA5
+ // for U3TX
+ //
+ MAP_GPIOPinConfigure(GPIO_PA5_U3TX);
+ MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_5);
+
+ //
+ // Configure the GPIO Pin Mux for PA2
+ // for U4RX
+ //
+ MAP_GPIOPinConfigure(GPIO_PA2_U4RX);
+ MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_2);
+
+ //
+ // Configure the GPIO Pin Mux for PA3
+ // for U4TX
+ //
+ MAP_GPIOPinConfigure(GPIO_PA3_U4TX);
+ MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_3);
+
+ //
+ // Configure the GPIO Pin Mux for PL6
+ // for USB0DP
+ //
+ MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6);
+
+ //
+ // Configure the GPIO Pin Mux for PL7
+ // for USB0DM
+ //
+ MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_7);
+
+ //
+ // Configure the GPIO Pin Mux for PB0
+ // for USB0ID
+ //
+ MAP_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0);
+
+ //
+ // Configure the GPIO Pin Mux for PB1
+ // for USB0VBUS
+ //
+ MAP_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_1);
+
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+
diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.h b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.h
new file mode 100644
index 000000000..ebbe0b7d6
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.h
@@ -0,0 +1,74 @@
+//*****************************************************************************
+// pinout.h
+//
+// configure the device pins for different signals
+//
+// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// Neither the name of Texas Instruments Incorporated nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+// This file was automatically generated on 25.2.2018 at 10:21:42
+// by TI PinMux version 4.0.1510
+//
+//*****************************************************************************
+
+#ifndef __DRIVERS_PINOUT_H__
+#define __DRIVERS_PINOUT_H__
+
+//*****************************************************************************
+//
+// If building with a C++ compiler, make all of the definitions in this header
+// have a C binding.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Prototypes.
+//
+//*****************************************************************************
+extern void PinoutSet(void);
+
+//*****************************************************************************
+//
+// Mark the end of the C bindings section for C++ compilers.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __DRIVERS_PINOUT_H__
diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.c b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.c
new file mode 100644
index 000000000..1cb86ce4f
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.c
@@ -0,0 +1,621 @@
+//*****************************************************************************
+// Copyright (c) 2014 Texas Instruments Incorporated. All rights reserved.
+// Software License Agreement
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// Neither the name of Texas Instruments Incorporated nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This file was automatically generated by the Tiva C Series PinMux Utility
+// Version: 1.0.4
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <inc/hw_types.h>
+#include <inc/hw_memmap.h>
+#include <inc/hw_gpio.h>
+#include <driverlib/sysctl.h>
+#include <driverlib/pin_map.h>
+#include <driverlib/rom_map.h>
+#include <driverlib/gpio.h>
+
+#include "Common/Sys_PinOut_Config/Pin.h"
+
+#ifdef ROM_GPIOPinTypeEthernetLED
+#define MAP_GPIOPinTypeEthernetLED \
+ ROM_GPIOPinTypeEthernetLED
+#else
+#define MAP_GPIOPinTypeEthernetLED \
+ GPIOPinTypeEthernetLED
+#endif
+
+//*****************************************************************************
+void
+PortFunctionInit(void)
+{
+ //
+ // Enable Peripheral Clocks
+ //
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C4);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART5);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
+
+ //hardware timers enabled manually because the pinout tool
+ //initialize automatically gpio per timer , deleting the gpio disables the timer
+ //manual initialization works well without gpios
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER4);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER6);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER7);
+
+
+
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOR);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOS);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOT);
+ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_WDOG0);
+ //
+ // Enable pin PD2 for ADC AIN13
+ //
+ //MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PE3 for ADC AIN0
+ //
+ //MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PK0 for ADC AIN16
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PE6 for ADC AIN20
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PD3 for ADC AIN12
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PE1 for ADC AIN2
+ //
+ //MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PK1 for ADC AIN17
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PK3 for ADC AIN19
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PP6 for ADC AIN23
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTP_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PE7 for ADC AIN21
+ // First open the lock and select the bits we want to modify in the GPIO commit register.
+ //
+ HWREG(GPIO_PORTE_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
+ HWREG(GPIO_PORTE_BASE + GPIO_O_CR) = 0x80;
+
+ //
+ // Now modify the configuration of the pins that we unlocked.
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PB4 for ADC AIN10
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PD6 for ADC AIN5
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PE2 for ADC AIN1
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PE0 for ADC AIN3
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PK2 for ADC AIN18
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PP7 for ADC AIN22
+ //
+ MAP_GPIOPinTypeADC(GPIO_PORTP_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PK4 for EPHY0 EN0LED0
+ //
+ MAP_GPIOPinConfigure(GPIO_PK4_EN0LED0);
+ MAP_GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PK5 for EPHY0 EN0LED2
+ //
+ MAP_GPIOPinConfigure(GPIO_PK5_EN0LED2);
+ MAP_GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PK6 for EPHY0 EN0LED1
+ //
+ MAP_GPIOPinConfigure(GPIO_PK6_EN0LED1);
+ MAP_GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PD0 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PD1 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PE4 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PF7 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PF6 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PG4 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PG5 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PG0 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PG1 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PH2 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PH0 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PH4 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PH6 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTH_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PH7 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTH_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PH5 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTH_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PH1 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PH3 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PJ7 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PJ6 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PJ2 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PJ3 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PL3 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PL0 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PL1 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PL4 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PL2 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PL5 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PM1 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PM0 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PM3 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PM5 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTM_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PM2 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PN7 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTN_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PN1 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PN4 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PN0 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTN_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PP2 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PP4 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PP3 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PP5 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PP0 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PQ5 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PQ7 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PR3 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTR_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PR1 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTR_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PS4 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PS0 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PS2 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PS5 for GPIOOutput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PS3 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PT2 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTT_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PT0 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOInput(GPIO_PORTT_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PA7 for GPIOInput
+ //
+ MAP_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PB3 for I2C0 I2C0SDA
+ //
+ MAP_GPIOPinConfigure(GPIO_PB3_I2C0SDA);
+ MAP_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PB2 for I2C0 I2C0SCL
+ //
+ MAP_GPIOPinConfigure(GPIO_PB2_I2C0SCL);
+ MAP_GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PG6 for I2C4 I2C4SCL
+ //
+ MAP_GPIOPinConfigure(GPIO_PG6_I2C4SCL);
+ MAP_GPIOPinTypeI2CSCL(GPIO_PORTG_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PG7 for I2C4 I2C4SDA
+ //
+ MAP_GPIOPinConfigure(GPIO_PG7_I2C4SDA);
+ MAP_GPIOPinTypeI2C(GPIO_PORTG_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PR2 for PWM0 M0PWM2
+ //
+ MAP_GPIOPinConfigure(GPIO_PR2_M0PWM2);
+ MAP_GPIOPinTypePWM(GPIO_PORTR_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PR7 for PWM0 M0PWM7
+ //
+ MAP_GPIOPinConfigure(GPIO_PR7_M0PWM7);
+ MAP_GPIOPinTypePWM(GPIO_PORTR_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PR5 for PWM0 M0PWM5
+ //
+ MAP_GPIOPinConfigure(GPIO_PR5_M0PWM5);
+ MAP_GPIOPinTypePWM(GPIO_PORTR_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PR0 for PWM0 M0PWM0
+ //
+ MAP_GPIOPinConfigure(GPIO_PR0_M0PWM0);
+ MAP_GPIOPinTypePWM(GPIO_PORTR_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PA3 for SSI0 SSI0FSS
+ //
+ MAP_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
+ MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_3);
+
+ //
+ // Enable pin PA4 for SSI0 SSI0XDAT0
+ //
+ MAP_GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);
+ MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PA5 for SSI0 SSI0XDAT1
+ //
+ MAP_GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);
+ MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PA2 for SSI0 SSI0CLK
+ //
+ MAP_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
+ MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2);
+
+ //
+ // Enable pin PQ0 for SSI3 SSI3CLK
+ //
+ MAP_GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
+ MAP_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PF1 for SSI3 SSI3XDAT0
+ //
+ MAP_GPIOPinConfigure(GPIO_PF1_SSI3XDAT0);
+ MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PQ1 for SSI3 SSI3FSS
+ //
+ MAP_GPIOPinConfigure(GPIO_PQ1_SSI3FSS);
+ MAP_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_1);
+
+ //
+ // Enable pin PF5 for SSI3 SSI3XDAT3
+ //
+ MAP_GPIOPinConfigure(GPIO_PF5_SSI3XDAT3);
+ MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PF0 for SSI3 SSI3XDAT1
+ //
+ MAP_GPIOPinConfigure(GPIO_PF0_SSI3XDAT1);
+ MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0);
+
+ //
+ // Enable pin PC7 for UART5 U5TX
+ //
+ MAP_GPIOPinConfigure(GPIO_PC7_U5TX);
+ MAP_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PC6 for UART5 U5RX
+ //
+ MAP_GPIOPinConfigure(GPIO_PC6_U5RX);
+ MAP_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PC5 for UART7 U7TX
+ //
+ MAP_GPIOPinConfigure(GPIO_PC5_U7TX);
+ MAP_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_5);
+
+ //
+ // Enable pin PC4 for UART7 U7RX
+ //
+ MAP_GPIOPinConfigure(GPIO_PC4_U7RX);
+ MAP_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4);
+
+ //
+ // Enable pin PL6 for USB0 USB0DP
+ //
+ MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6);
+
+ //
+ // Enable pin PL7 for USB0 USB0DM
+ //
+ MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_7);
+
+ //
+ // Enable pin PB1 for USB0 USB0VBUS
+ //
+ MAP_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_1);
+}
diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.h b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.h
new file mode 100644
index 000000000..d5e51f6b4
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.h
@@ -0,0 +1,43 @@
+//*****************************************************************************
+// Copyright (c) 2014 Texas Instruments Incorporated. All rights reserved.
+// Software License Agreement
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// Neither the name of Texas Instruments Incorporated nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This file was automatically generated by the Tiva C Series PinMux Utility
+// Version: 1.0.4
+//
+//*****************************************************************************
+
+#ifndef __PIN_H__
+#define __PIN_H__
+
+extern void PortFunctionInit(void);
+
+#endif // __PIN_H__
diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.c b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.c
new file mode 100644
index 000000000..8e378309a
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.c
@@ -0,0 +1,51 @@
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <driverlib/gpio.h>
+#include <inc/hw_memmap.h>
+
+void InitPinOutPullUps(void)
+{
+ GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_INT_PIN_1,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_INT_PIN_2,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_INT_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTE_BASE, GPIO_INT_PIN_1,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTE_BASE, GPIO_INT_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_INT_PIN_1,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTH_BASE, GPIO_INT_PIN_5,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTH_BASE, GPIO_INT_PIN_6,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTH_BASE, GPIO_INT_PIN_7,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_INT_PIN_2,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_INT_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_INT_PIN_7,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTM_BASE, GPIO_INT_PIN_5,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTN_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTN_BASE, GPIO_INT_PIN_7,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTP_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTP_BASE, GPIO_INT_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTP_BASE, GPIO_INT_PIN_5,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTQ_BASE, GPIO_INT_PIN_5,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTQ_BASE, GPIO_INT_PIN_7,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTS_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTS_BASE, GPIO_INT_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+ GPIOPadConfigSet(GPIO_PORTT_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+ GPIOPadConfigSet(GPIO_PORTT_BASE, GPIO_INT_PIN_2,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
+
+}
+
+
+
+
diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.h b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.h
new file mode 100644
index 000000000..c83281cd9
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.h
@@ -0,0 +1,14 @@
+/****************************************************************************************************
+ * init ialization of pull up's over GPIO
+ * those pins must be configured as inputs in the pinmap file by using MAP_GPIOPinTypeGPIOInput func
+ * here is added onlu the pull up defenition
+ *****************************************************************************************************/
+
+#ifndef PIN_CONFIG_H_
+#define PIN_CONFIG_H_
+
+
+void InitPinOutPullUps(void);
+
+
+#endif /* PIN_CONFIG_H_ */
diff --git a/Software/Embedded_SW/Embedded/Common/Utilities/Update.c b/Software/Embedded_SW/Embedded/Common/Utilities/Update.c
new file mode 100644
index 000000000..8eeee64cf
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Utilities/Update.c
@@ -0,0 +1,98 @@
+
+#include "include.h"
+//#include <stdbool.h>
+
+//#include "Drivers/USB_Communication/USBCDCD.h"
+
+
+extern Semaphore_Handle updateSem;
+
+
+void UpdateUsb(void)
+{
+ //
+ // Terminate the USB device and detach from the bus.
+ //
+ USBDCDTerm(0);
+
+ //
+ // Disable all interrupts.
+ //
+ ROM_IntMasterDisable();
+
+ //
+ // Disable SysTick and its interrupt.
+ //
+ ROM_SysTickIntDisable();
+ ROM_SysTickDisable();
+
+ //
+ // Disable all processor interrupts. Instead of disabling them one at a
+ // time, a direct write to NVIC is done to disable all peripheral
+ // interrupts.
+ //
+ HWREG(NVIC_DIS0) = 0xffffffff;
+ HWREG(NVIC_DIS1) = 0xffffffff;
+ HWREG(NVIC_DIS2) = 0xffffffff;
+ HWREG(NVIC_DIS3) = 0xffffffff;
+ HWREG(NVIC_DIS4) = 0xffffffff;
+
+ //
+ // Enable and reset the USB peripheral.
+ //
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
+ ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_USB0);
+ ROM_USBClockEnable(USB0_BASE, 8, USB_CLOCK_INTERNAL);
+
+ //
+ // Wait for about a second.
+ //
+ ROM_SysCtlDelay(SYS_CLK_FREQ / 3);
+
+ //
+ // Re-enable interrupts at the NVIC level.
+ //
+ ROM_IntMasterEnable();
+
+ //
+ // Call the USB boot loader.
+ //
+ ROM_UpdateUSB(0);
+
+ //
+ // Should never get here, but just in case.
+ //
+ while(1)
+ {
+ }
+}
+
+Void updateTask(UArg arg0, UArg arg1)
+{
+
+ //
+ // Wait until new updTE ARRIVED
+ //
+ Semaphore_pend(updateSem, BIOS_WAIT_FOREVER);
+ UpdateUsb();
+}
+extern Semaphore_Handle ReconnectSem;
+
+
+void ReconnectUsb(void)
+{
+ //USBCDC_close();
+}
+
+Void ReconnectTask(UArg arg0, UArg arg1)
+{
+
+ //
+ // Wait until new updTE ARRIVED
+ //
+ while (1)
+ {
+ Semaphore_pend(ReconnectSem, BIOS_WAIT_FOREVER);
+ ReconnectUsb();
+ }
+}
diff --git a/Software/Embedded_SW/Embedded/Common/Utilities/Utils.c b/Software/Embedded_SW/Embedded/Common/Utilities/Utils.c
new file mode 100644
index 000000000..d792d9b5f
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Utilities/Utils.c
@@ -0,0 +1,245 @@
+/************************************************************
+ * Utils.h
+ * general module of system utility functions
+ **************************************************************/
+
+#include <inc/hw_ints.h>
+#include <inc/hw_memmap.h>
+#include <driverlib/rom.h>
+#include <time.h>
+#include "Common/Utilities/Utils.h"
+//#include <driverlib/systick.h>
+#include "driverlib/hibernate.h"
+
+static const float speedCoef = 5.3051647697298445256294587790838f;//(200 micro steping)/2*Pi*Radius - 200 micro steping
+
+//*****************************************************************************
+
+bool DanserCheckPosition(uint16_t position , Danser_t danser, bool test)
+{
+ if (test == false) return true;
+#ifdef DEBUG_DANCER
+ ProfileType_t profileType = GetCurrentProfileType();
+ if (position < DANSER_POS_MIN)
+ {
+ if(danser == Winder)
+ {
+ if(profileType == Manual)
+ {
+ JigStopAllWithError("Thread torn in winder danser");//for stoping the system operation
+ }
+ else if (profileType == User)
+ {
+ //notify the UI about an error and pause the system
+ SendMessageToHost(ERROR_IN_PROFILE_EXECUTION,"Thread torn in winder danser");
+ JigPauseAll();
+ }
+ }
+ else
+ {
+ if(profileType == Manual)
+ {
+ JigStopAllWithError("Thread torn in pooler danser");//for stoping the system operation
+ }
+ else if (profileType == User)
+ {
+ //notify the UI about an error and pause the system
+ SendMessageToHost(ERROR_IN_PROFILE_EXECUTION,"Thread torn in pooler danser");
+ JigPauseAll();
+ }
+ }
+ return false;
+ }
+
+ if (position > DANSER_POS_MAX)
+ {
+ if(danser == Pooler)
+ {
+ if(profileType == Manual)
+ {
+ JigStopAllWithError("Thread stocked in pooler danser");
+ }
+ else if (profileType == User)
+ {
+ SendMessageToHost(ERROR_IN_PROFILE_EXECUTION,"Thread stuck in pooler danser");
+ JigPauseAll();
+ }
+ }
+ else
+ {
+ if(profileType == Manual)
+ {
+ JigStopAllWithError("Thread stocked in winder danser");
+ }
+ else if (profileType ==User)
+ {
+ SendMessageToHost(ERROR_IN_PROFILE_EXECUTION,"Thread stuck in winder danser");
+ JigPauseAll();
+ }
+ }
+ return false;
+ }
+#endif
+ return true;
+}
+
+//*****************************************************************************
+//convert thread speed recieved in milimeters per second into motor steps of pps
+//*****************************************************************************
+uint16_t ConvertSpeed2Pps(uint16_t milimeterPerSecond)
+{
+ float res = speedCoef*(float)milimeterPerSecond;
+ return (uint16_t)res;
+}
+//*****************************************************************************
+
+uint16_t ConvertPpsToSpeed(uint16_t Pps)
+{
+ float res = (float)Pps/speedCoef;
+ return (uint16_t)res;
+
+}
+
+//*****************************************************************************
+//
+// Init WD timer
+//
+//*****************************************************************************
+void InitWatchdog(uint32_t clock)
+{
+ //
+ // Enable the watchdog interrupt.
+ //
+ ROM_IntEnable(INT_WATCHDOG);
+
+ //
+ // Set the period of the watchdog timer.
+ //
+ ROM_WatchdogReloadSet(WATCHDOG0_BASE, clock);
+
+ //
+ // Enable reset generation from the watchdog timer.
+ //
+ ROM_WatchdogResetEnable(WATCHDOG0_BASE);
+
+ //
+ // Enable the watchdog timer.
+ //
+ ROM_WatchdogEnable(WATCHDOG0_BASE);
+}
+void utilsInit(uint32_t ui32SysClock)
+{
+
+ cb_init();
+// SysTickPeriodSet(120000);
+// SysTickEnable();
+ // Configure Hibernate module clock.
+ //
+ HibernateEnableExpClk(ui32SysClock);
+
+
+ // Enable RTC mode.
+ //
+ HibernateRTCEnable();
+
+ //
+ // Configure the hibernate module counter to 24-hour calendar mode.
+ //
+ // HibernateCounterMode(HIBERNATE_COUNTER_24HR);
+ // Configure the hibernate module counter to RTC counter mode.
+ HibernateCounterMode(HIBERNATE_COUNTER_RTC);
+
+
+}
+
+
+uint32_t UsersysTickGet (void) {
+ uint32_t tick = 0;
+// tick = SysTickValueGet();
+ tick = HibernateRTCSSGet()*10000/0x8000;
+ return tick;
+}
+
+//*****************************************************************************
+//
+// The interrupt handler for the watchdog. This feeds the dog (so that the
+// processor does not get reset) and winks the LED connected to GPIO B3.
+//
+//*****************************************************************************
+void WatchdogIntHandler(void)
+{
+ //
+ // Clear the watchdog interrupt.
+ //
+ ROM_WatchdogIntClear(WATCHDOG0_BASE);
+}
+
+bool sendDataToHost = false;
+void UtilsSetCommunicationOk(void)
+{
+ sendDataToHost = true;
+}
+
+typedef struct circular_buffer
+{
+ void *buffer; // data buffer
+ void *buffer_end; // end of data buffer
+ uint16_t capacity; // maximum number of items in the buffer
+ uint16_t count; // number of items in the buffer
+ uint16_t sz; // size of each item in the buffer
+ void *head; // pointer to head
+ void *tail; // pointer to tail
+} circular_buffer;
+
+uint8_t LogBuffer[8002];
+circular_buffer cb;
+void cb_init()
+{
+ //cb.buffer = malloc(capacity * sz);
+ //if(cb.buffer == NULL)
+ // handle error
+ cb.buffer = LogBuffer;
+ cb.buffer_end = &LogBuffer[3950];
+ cb.capacity = 4000;
+ cb.count = 0;
+ cb.sz = 60;
+ cb.head = cb.buffer;
+ cb.tail = cb.buffer;
+}
+
+void cb_free(circular_buffer *cb)
+{
+ //free(cb.buffer);
+ // clear out other fields too, just to be safe
+}
+
+void cb_push_back(/*circular_buffer *cb,*/ const void *item, int size)
+{
+ if(cb.count == cb.capacity){
+ return;
+ // handle error
+ }
+ if ((int)(cb.head) + size > (int)(cb.buffer_end)){
+ size = (int)(cb.buffer_end) - (int)(cb.head);
+ }
+
+ memcpy(cb.head, item, size);
+ cb.head = (char*)cb.head + size;
+ if(cb.head >= cb.buffer_end)
+ cb.head = cb.buffer;
+ cb.count++;
+// if (sendDataToHost)
+// SendMessageToHost(DEBUG_LOG,item);
+}
+
+void cb_pop_front(/*circular_buffer *cb,*/ void *item)
+{
+ if(cb.count == 0){
+ // handle error
+ }
+ memcpy(item, cb.tail, cb.sz);
+ cb.tail = (char*)cb.tail + cb.sz;
+ if(cb.tail == cb.buffer_end)
+ cb.tail = cb.buffer;
+ cb.count--;
+}
diff --git a/Software/Embedded_SW/Embedded/Common/Utilities/Utils.h b/Software/Embedded_SW/Embedded/Common/Utilities/Utils.h
new file mode 100644
index 000000000..363cf6eec
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Utilities/Utils.h
@@ -0,0 +1,33 @@
+/************************************************************
+ * Utils.h
+ * general module of system utility functions
+ **************************************************************/
+
+#ifndef COMMON_UTILS_H_
+#define COMMON_UTILS_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+
+//digital read of the potentiometer limits
+#define DANSER_POS_MIN 1300
+#define DANSER_POS_MAX 3500
+
+typedef enum
+{
+ Winder = 0,
+ Pooler
+}Danser_t;
+
+
+void cb_init();
+void cb_push_back(/*void *cb,*/ const void *item, int size);
+void utilsInit(uint32_t ui32SysClock);
+uint32_t UsersysTickGet (void);
+bool DanserCheckPosition(uint16_t position , Danser_t danser, bool test);
+void InitWatchdog(uint32_t clock);
+uint16_t ConvertSpeed2Pps(uint16_t milimeterPerSecond);
+uint16_t ConvertPpsToSpeed(uint16_t Pps);
+void UtilsSetCommunicationOk(void);
+#endif /* COMMON_UTILS_H_ */
diff --git a/Software/Embedded_SW/Embedded/Common/Utilities/ustdlib.c b/Software/Embedded_SW/Embedded/Common/Utilities/ustdlib.c
new file mode 100644
index 000000000..efee94611
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/Utilities/ustdlib.c
@@ -0,0 +1,1825 @@
+//*****************************************************************************
+//
+// ustdlib.c - Simple standard library functions.
+//
+// Copyright (c) 2007-2015 Texas Instruments Incorporated. All rights reserved.
+// Software License Agreement
+//
+// Texas Instruments (TI) is supplying this software for use solely and
+// exclusively on TI's microcontroller products. The software is owned by
+// TI and/or its suppliers, and is protected under applicable copyright
+// laws. You may not combine this software with "viral" open-source
+// software in order to form a larger program.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
+// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
+// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
+// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+// DAMAGES, FOR ANY REASON WHATSOEVER.
+//
+// This is part of revision 2.1.2.111 of the Tiva Utility Library.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <driverlib/debug.h>
+#include <utils/ustdlib.h>
+
+//*****************************************************************************
+//
+//! \addtogroup ustdlib_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// A mapping from an integer between 0 and 15 to its ASCII character
+// equivalent.
+//
+//*****************************************************************************
+static const char * const g_pcHex = "0123456789abcdef";
+
+//*****************************************************************************
+//
+//! Copies a certain number of characters from one string to another.
+//!
+//! \param s1 is a pointer to the destination buffer into which characters
+//! are to be copied.
+//! \param s2 is a pointer to the string from which characters are to be
+//! copied.
+//! \param n is the number of characters to copy to the destination buffer.
+//!
+//! This function copies at most \e n characters from the string pointed to
+//! by \e s2 into the buffer pointed to by \e s1. If the end of \e s2 is found
+//! before \e n characters have been copied, remaining characters in \e s1
+//! will be padded with zeroes until \e n characters have been written. Note
+//! that the destination string will only be NULL terminated if the number of
+//! characters to be copied is greater than the length of \e s2.
+//!
+//! \return Returns \e s1.
+//
+//*****************************************************************************
+char *
+ustrncpy(char * restrict s1, const char * restrict s2, size_t n)
+{
+ size_t count;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(s1);
+ ASSERT(s2);
+
+ //
+ // Start at the beginning of the source string.
+ //
+ count = 0;
+
+ //
+ // Copy the source string until we run out of source characters or
+ // destination space.
+ //
+ while(n && s2[count])
+ {
+ s1[count] = s2[count];
+ count++;
+ n--;
+ }
+
+ //
+ // Pad the destination if we are not yet done.
+ //
+ while(n)
+ {
+ s1[count++] = (char)0;
+ n--;
+ }
+
+ //
+ // Pass the destination pointer back to the caller.
+ //
+ return(s1);
+}
+
+//*****************************************************************************
+//
+//! A simple vsnprintf function supporting \%c, \%d, \%p, \%s, \%u, \%x, and
+//! \%X.
+//!
+//! \param s points to the buffer where the converted string is stored.
+//! \param n is the size of the buffer.
+//! \param format is the format string.
+//! \param arg is the list of optional arguments, which depend on the
+//! contents of the format string.
+//!
+//! This function is very similar to the C library <tt>vsnprintf()</tt>
+//! function. Only the following formatting characters are supported:
+//!
+//! - \%c to print a character
+//! - \%d or \%i to print a decimal value
+//! - \%s to print a string
+//! - \%u to print an unsigned decimal value
+//! - \%x to print a hexadecimal value using lower case letters
+//! - \%X to print a hexadecimal value using lower case letters (not upper case
+//! letters as would typically be used)
+//! - \%p to print a pointer as a hexadecimal value
+//! - \%\% to print out a \% character
+//!
+//! For \%d, \%i, \%p, \%s, \%u, \%x, and \%X, an optional number may reside
+//! between the \% and the format character, which specifies the minimum number
+//! of characters to use for that value; if preceded by a 0 then the extra
+//! characters will be filled with zeros instead of spaces. For example,
+//! ``\%8d'' will use eight characters to print the decimal value with spaces
+//! added to reach eight; ``\%08d'' will use eight characters as well but will
+//! add zeroes instead of spaces.
+//!
+//! The type of the arguments after \e format must match the requirements of
+//! the format string. For example, if an integer was passed where a string
+//! was expected, an error of some kind will most likely occur.
+//!
+//! The \e n parameter limits the number of characters that will be
+//! stored in the buffer pointed to by \e s to prevent the possibility of
+//! a buffer overflow. The buffer size should be large enough to hold the
+//! expected converted output string, including the null termination character.
+//!
+//! The function will return the number of characters that would be converted
+//! as if there were no limit on the buffer size. Therefore it is possible for
+//! the function to return a count that is greater than the specified buffer
+//! size. If this happens, it means that the output was truncated.
+//!
+//! \return Returns the number of characters that were to be stored, not
+//! including the NULL termination character, regardless of space in the
+//! buffer.
+//
+//*****************************************************************************
+int
+uvsnprintf(char * restrict s, size_t n, const char * restrict format,
+ va_list arg)
+{
+ unsigned long ulIdx, ulValue, ulCount, ulBase, ulNeg;
+ char *pcStr, cFill;
+ int iConvertCount = 0;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(s);
+ ASSERT(n);
+ ASSERT(format);
+
+ //
+ // Adjust buffer size limit to allow one space for null termination.
+ //
+ if(n)
+ {
+ n--;
+ }
+
+ //
+ // Initialize the count of characters converted.
+ //
+ iConvertCount = 0;
+
+ //
+ // Loop while there are more characters in the format string.
+ //
+ while(*format)
+ {
+ //
+ // Find the first non-% character, or the end of the string.
+ //
+ for(ulIdx = 0; (format[ulIdx] != '%') && (format[ulIdx] != '\0');
+ ulIdx++)
+ {
+ }
+
+ //
+ // Write this portion of the string to the output buffer. If there are
+ // more characters to write than there is space in the buffer, then
+ // only write as much as will fit in the buffer.
+ //
+ if(ulIdx > n)
+ {
+ ustrncpy(s, format, n);
+ s += n;
+ n = 0;
+ }
+ else
+ {
+ ustrncpy(s, format, ulIdx);
+ s += ulIdx;
+ n -= ulIdx;
+ }
+
+ //
+ // Update the conversion count. This will be the number of characters
+ // that should have been written, even if there was not room in the
+ // buffer.
+ //
+ iConvertCount += ulIdx;
+
+ //
+ // Skip the portion of the format string that was written.
+ //
+ format += ulIdx;
+
+ //
+ // See if the next character is a %.
+ //
+ if(*format == '%')
+ {
+ //
+ // Skip the %.
+ //
+ format++;
+
+ //
+ // Set the digit count to zero, and the fill character to space
+ // (that is, to the defaults).
+ //
+ ulCount = 0;
+ cFill = ' ';
+
+ //
+ // It may be necessary to get back here to process more characters.
+ // Goto's aren't pretty, but effective. I feel extremely dirty for
+ // using not one but two of the beasts.
+ //
+again:
+
+ //
+ // Determine how to handle the next character.
+ //
+ switch(*format++)
+ {
+ //
+ // Handle the digit characters.
+ //
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ //
+ // If this is a zero, and it is the first digit, then the
+ // fill character is a zero instead of a space.
+ //
+ if((format[-1] == '0') && (ulCount == 0))
+ {
+ cFill = '0';
+ }
+
+ //
+ // Update the digit count.
+ //
+ ulCount *= 10;
+ ulCount += format[-1] - '0';
+
+ //
+ // Get the next character.
+ //
+ goto again;
+ }
+
+ //
+ // Handle the %c command.
+ //
+ case 'c':
+ {
+ //
+ // Get the value from the varargs.
+ //
+ ulValue = va_arg(arg, unsigned long);
+
+ //
+ // Copy the character to the output buffer, if there is
+ // room. Update the buffer size remaining.
+ //
+ if(n != 0)
+ {
+ *s++ = (char)ulValue;
+ n--;
+ }
+
+ //
+ // Update the conversion count.
+ //
+ iConvertCount++;
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+
+ //
+ // Handle the %d and %i commands.
+ //
+ case 'd':
+ case 'i':
+ {
+ //
+ // Get the value from the varargs.
+ //
+ ulValue = va_arg(arg, unsigned long);
+
+ //
+ // If the value is negative, make it positive and indicate
+ // that a minus sign is needed.
+ //
+ if((long)ulValue < 0)
+ {
+ //
+ // Make the value positive.
+ //
+ ulValue = -(long)ulValue;
+
+ //
+ // Indicate that the value is negative.
+ //
+ ulNeg = 1;
+ }
+ else
+ {
+ //
+ // Indicate that the value is positive so that a
+ // negative sign isn't inserted.
+ //
+ ulNeg = 0;
+ }
+
+ //
+ // Set the base to 10.
+ //
+ ulBase = 10;
+
+ //
+ // Convert the value to ASCII.
+ //
+ goto convert;
+ }
+
+ //
+ // Handle the %s command.
+ //
+ case 's':
+ {
+ //
+ // Get the string pointer from the varargs.
+ //
+ pcStr = va_arg(arg, char *);
+
+ //
+ // Determine the length of the string.
+ //
+ for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++)
+ {
+ }
+
+ //
+ // Update the convert count to include any padding that
+ // should be necessary (regardless of whether we have space
+ // to write it or not).
+ //
+ if(ulCount > ulIdx)
+ {
+ iConvertCount += (ulCount - ulIdx);
+ }
+
+ //
+ // Copy the string to the output buffer. Only copy as much
+ // as will fit in the buffer. Update the output buffer
+ // pointer and the space remaining.
+ //
+ if(ulIdx > n)
+ {
+ ustrncpy(s, pcStr, n);
+ s += n;
+ n = 0;
+ }
+ else
+ {
+ ustrncpy(s, pcStr, ulIdx);
+ s += ulIdx;
+ n -= ulIdx;
+
+ //
+ // Write any required padding spaces assuming there is
+ // still space in the buffer.
+ //
+ if(ulCount > ulIdx)
+ {
+ ulCount -= ulIdx;
+ if(ulCount > n)
+ {
+ ulCount = n;
+ }
+ n = -ulCount;
+
+ while(ulCount--)
+ {
+ *s++ = ' ';
+ }
+ }
+ }
+
+ //
+ // Update the conversion count. This will be the number of
+ // characters that should have been written, even if there
+ // was not room in the buffer.
+ //
+ iConvertCount += ulIdx;
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+
+ //
+ // Handle the %u command.
+ //
+ case 'u':
+ {
+ //
+ // Get the value from the varargs.
+ //
+ ulValue = va_arg(arg, unsigned long);
+
+ //
+ // Set the base to 10.
+ //
+ ulBase = 10;
+
+ //
+ // Indicate that the value is positive so that a minus sign
+ // isn't inserted.
+ //
+ ulNeg = 0;
+
+ //
+ // Convert the value to ASCII.
+ //
+ goto convert;
+ }
+
+ //
+ // Handle the %x and %X commands. Note that they are treated
+ // identically; that is, %X will use lower case letters for a-f
+ // instead of the upper case letters is should use. We also
+ // alias %p to %x.
+ //
+ case 'x':
+ case 'X':
+ case 'p':
+ {
+ //
+ // Get the value from the varargs.
+ //
+ ulValue = va_arg(arg, unsigned long);
+
+ //
+ // Set the base to 16.
+ //
+ ulBase = 16;
+
+ //
+ // Indicate that the value is positive so that a minus sign
+ // isn't inserted.
+ //
+ ulNeg = 0;
+
+ //
+ // Determine the number of digits in the string version of
+ // the value.
+ //
+convert:
+ for(ulIdx = 1;
+ (((ulIdx * ulBase) <= ulValue) &&
+ (((ulIdx * ulBase) / ulBase) == ulIdx));
+ ulIdx *= ulBase, ulCount--)
+ {
+ }
+
+ //
+ // If the value is negative, reduce the count of padding
+ // characters needed.
+ //
+ if(ulNeg)
+ {
+ ulCount--;
+ }
+
+ //
+ // If the value is negative and the value is padded with
+ // zeros, then place the minus sign before the padding.
+ //
+ if(ulNeg && (n != 0) && (cFill == '0'))
+ {
+ //
+ // Place the minus sign in the output buffer.
+ //
+ *s++ = '-';
+ n--;
+
+ //
+ // Update the conversion count.
+ //
+ iConvertCount++;
+
+ //
+ // The minus sign has been placed, so turn off the
+ // negative flag.
+ //
+ ulNeg = 0;
+ }
+
+ //
+ // See if there are more characters in the specified field
+ // width than there are in the conversion of this value.
+ //
+ if((ulCount > 1) && (ulCount < 65536))
+ {
+ //
+ // Loop through the required padding characters.
+ //
+ for(ulCount--; ulCount; ulCount--)
+ {
+ //
+ // Copy the character to the output buffer if there
+ // is room.
+ //
+ if(n != 0)
+ {
+ *s++ = cFill;
+ n--;
+ }
+
+ //
+ // Update the conversion count.
+ //
+ iConvertCount++;
+ }
+ }
+
+ //
+ // If the value is negative, then place the minus sign
+ // before the number.
+ //
+ if(ulNeg && (n != 0))
+ {
+ //
+ // Place the minus sign in the output buffer.
+ //
+ *s++ = '-';
+ n--;
+
+ //
+ // Update the conversion count.
+ //
+ iConvertCount++;
+ }
+
+ //
+ // Convert the value into a string.
+ //
+ for(; ulIdx; ulIdx /= ulBase)
+ {
+ //
+ // Copy the character to the output buffer if there is
+ // room.
+ //
+ if(n != 0)
+ {
+ *s++ = g_pcHex[(ulValue / ulIdx) % ulBase];
+ n--;
+ }
+
+ //
+ // Update the conversion count.
+ //
+ iConvertCount++;
+ }
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+
+ //
+ // Handle the %% command.
+ //
+ case '%':
+ {
+ //
+ // Simply write a single %.
+ //
+ if(n != 0)
+ {
+ *s++ = format[-1];
+ n--;
+ }
+
+ //
+ // Update the conversion count.
+ //
+ iConvertCount++;
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+
+ //
+ // Handle all other commands.
+ //
+ default:
+ {
+ //
+ // Indicate an error.
+ //
+ if(n >= 5)
+ {
+ ustrncpy(s, "ERROR", 5);
+ s += 5;
+ n -= 5;
+ }
+ else
+ {
+ ustrncpy(s, "ERROR", n);
+ s += n;
+ n = 0;
+ }
+
+ //
+ // Update the conversion count.
+ //
+ iConvertCount += 5;
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // Null terminate the string in the buffer.
+ //
+ *s = 0;
+
+ //
+ // Return the number of characters in the full converted string.
+ //
+ return(iConvertCount);
+}
+
+//*****************************************************************************
+//
+//! A simple sprintf function supporting \%c, \%d, \%p, \%s, \%u, \%x, and \%X.
+//!
+//! \param s is the buffer where the converted string is stored.
+//! \param format is the format string.
+//! \param ... are the optional arguments, which depend on the contents of the
+//! format string.
+//!
+//! This function is very similar to the C library <tt>sprintf()</tt> function.
+//! Only the following formatting characters are supported:
+//!
+//! - \%c to print a character
+//! - \%d or \%i to print a decimal value
+//! - \%s to print a string
+//! - \%u to print an unsigned decimal value
+//! - \%x to print a hexadecimal value using lower case letters
+//! - \%X to print a hexadecimal value using lower case letters (not upper case
+//! letters as would typically be used)
+//! - \%p to print a pointer as a hexadecimal value
+//! - \%\% to print out a \% character
+//!
+//! For \%d, \%i, \%p, \%s, \%u, \%x, and \%X, an optional number may reside
+//! between the \% and the format character, which specifies the minimum number
+//! of characters to use for that value; if preceded by a 0 then the extra
+//! characters will be filled with zeros instead of spaces. For example,
+//! ``\%8d'' will use eight characters to print the decimal value with spaces
+//! added to reach eight; ``\%08d'' will use eight characters as well but will
+//! add zeros instead of spaces.
+//!
+//! The type of the arguments after \e format must match the requirements of
+//! the format string. For example, if an integer was passed where a string
+//! was expected, an error of some kind will most likely occur.
+//!
+//! The caller must ensure that the buffer \e s is large enough to hold the
+//! entire converted string, including the null termination character.
+//!
+//! \return Returns the count of characters that were written to the output
+//! buffer, not including the NULL termination character.
+//
+//*****************************************************************************
+int
+usprintf(char * restrict s, const char *format, ...)
+{
+ va_list arg;
+ int ret;
+
+ //
+ // Start the varargs processing.
+ //
+ va_start(arg, format);
+
+ //
+ // Call vsnprintf to perform the conversion. Use a large number for the
+ // buffer size.
+ //
+ ret = uvsnprintf(s, 0xffff, format, arg);
+
+ //
+ // End the varargs processing.
+ //
+ va_end(arg);
+
+ //
+ // Return the conversion count.
+ //
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! A simple snprintf function supporting \%c, \%d, \%p, \%s, \%u, \%x, and
+//! \%X.
+//!
+//! \param s is the buffer where the converted string is stored.
+//! \param n is the size of the buffer.
+//! \param format is the format string.
+//! \param ... are the optional arguments, which depend on the contents of the
+//! format string.
+//!
+//! This function is very similar to the C library <tt>sprintf()</tt> function.
+//! Only the following formatting characters are supported:
+//!
+//! - \%c to print a character
+//! - \%d or \%i to print a decimal value
+//! - \%s to print a string
+//! - \%u to print an unsigned decimal value
+//! - \%x to print a hexadecimal value using lower case letters
+//! - \%X to print a hexadecimal value using lower case letters (not upper case
+//! letters as would typically be used)
+//! - \%p to print a pointer as a hexadecimal value
+//! - \%\% to print out a \% character
+//!
+//! For \%d, \%i, \%p, \%s, \%u, \%x, and \%X, an optional number may reside
+//! between the \% and the format character, which specifies the minimum number
+//! of characters to use for that value; if preceded by a 0 then the extra
+//! characters will be filled with zeros instead of spaces. For example,
+//! ``\%8d'' will use eight characters to print the decimal value with spaces
+//! added to reach eight; ``\%08d'' will use eight characters as well but will
+//! add zeros instead of spaces.
+//!
+//! The type of the arguments after \e format must match the requirements of
+//! the format string. For example, if an integer was passed where a string
+//! was expected, an error of some kind will most likely occur.
+//!
+//! The function will copy at most \e n - 1 characters into the buffer
+//! \e s. One space is reserved in the buffer for the null termination
+//! character.
+//!
+//! The function will return the number of characters that would be converted
+//! as if there were no limit on the buffer size. Therefore it is possible for
+//! the function to return a count that is greater than the specified buffer
+//! size. If this happens, it means that the output was truncated.
+//!
+//! \return Returns the number of characters that were to be stored, not
+//! including the NULL termination character, regardless of space in the
+//! buffer.
+//
+//*****************************************************************************
+int
+usnprintf(char * restrict s, size_t n, const char * restrict format, ...)
+{
+ va_list arg;
+ int ret;
+
+ //
+ // Start the varargs processing.
+ //
+ va_start(arg, format);
+
+ //
+ // Call vsnprintf to perform the conversion.
+ //
+ ret = uvsnprintf(s, n, format, arg);
+
+ //
+ // End the varargs processing.
+ //
+ va_end(arg);
+
+ //
+ // Return the conversion count.
+ //
+ return(ret);
+}
+
+//*****************************************************************************
+//
+// This array contains the number of days in a year at the beginning of each
+// month of the year, in a non-leap year.
+//
+//*****************************************************************************
+static const time_t g_psDaysToMonth[12] =
+{
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+//*****************************************************************************
+//
+//! Converts from seconds to calendar date and time.
+//!
+//! \param timer is the number of seconds.
+//! \param tm is a pointer to the time structure that is filled in with the
+//! broken down date and time.
+//!
+//! This function converts a number of seconds since midnight GMT on January 1,
+//! 1970 (traditional Unix epoch) into the equivalent month, day, year, hours,
+//! minutes, and seconds representation.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+ulocaltime(time_t timer, struct tm *tm)
+{
+ time_t temp, months;
+
+ //
+ // Extract the number of seconds, converting time to the number of minutes.
+ //
+ temp = timer / 60;
+ tm->tm_sec = timer - (temp * 60);
+ timer = temp;
+
+ //
+ // Extract the number of minutes, converting time to the number of hours.
+ //
+ temp = timer / 60;
+ tm->tm_min = timer - (temp * 60);
+ timer = temp;
+
+ //
+ // Extract the number of hours, converting time to the number of days.
+ //
+ temp = timer / 24;
+ tm->tm_hour = timer - (temp * 24);
+ timer = temp;
+
+ //
+ // Compute the day of the week.
+ //
+ tm->tm_wday = (timer + 4) % 7;
+
+ //
+ // Compute the number of leap years that have occurred since 1968, the
+ // first leap year before 1970. For the beginning of a leap year, cut the
+ // month loop below at March so that the leap day is classified as February
+ // 29 followed by March 1, instead of March 1 followed by another March 1.
+ //
+ timer += 366 + 365;
+ temp = timer / ((4 * 365) + 1);
+ if((timer - (temp * ((4 * 365) + 1))) > (31 + 28))
+ {
+ temp++;
+ months = 12;
+ }
+ else
+ {
+ months = 2;
+ }
+
+ //
+ // Extract the year.
+ //
+ tm->tm_year = ((timer - temp) / 365) + 68;
+ timer -= ((tm->tm_year - 68) * 365) + temp;
+
+ //
+ // Extract the month.
+ //
+ for(temp = 0; temp < months; temp++)
+ {
+ if(g_psDaysToMonth[temp] > timer)
+ {
+ break;
+ }
+ }
+ tm->tm_mon = temp - 1;
+
+ //
+ // Extract the day of the month.
+ //
+ tm->tm_mday = timer - g_psDaysToMonth[temp - 1] + 1;
+}
+
+//*****************************************************************************
+//
+//! Compares two time structures and determines if one is greater than,
+//! less than, or equal to the other.
+//!
+//! \param t1 is the first time structure to compare.
+//! \param t2 is the second time structure to compare.
+//!
+//! This function compares two time structures and returns a signed number
+//! to indicate the result of the comparison. If the time represented by
+//! \e t1 is greater than the time represented by \e t2 then a positive
+//! number is returned. Likewise if \e t1 is less than \e t2 then a
+//! negative number is returned. If the two times are equal then the function
+//! returns 0.
+//!
+//! \return Returns 0 if the two times are equal, +1 if \e t1 is greater
+//! than \e t2, and -1 if \e t1 is less than \e t2.
+//
+//*****************************************************************************
+static int
+ucmptime(struct tm *t1, struct tm *t2)
+{
+ //
+ // Compare each field in descending signficance to determine if
+ // greater than, less than, or equal.
+ //
+ if(t1->tm_year > t2->tm_year)
+ {
+ return(1);
+ }
+ else if(t1->tm_year < t2->tm_year)
+ {
+ return(-1);
+ }
+ else if(t1->tm_mon > t2->tm_mon)
+ {
+ return(1);
+ }
+ else if(t1->tm_mon < t2->tm_mon)
+ {
+ return(-1);
+ }
+ else if(t1->tm_mday > t2->tm_mday)
+ {
+ return(1);
+ }
+ else if(t1->tm_mday < t2->tm_mday)
+ {
+ return(-1);
+ }
+ else if(t1->tm_hour > t2->tm_hour)
+ {
+ return(1);
+ }
+ else if(t1->tm_hour < t2->tm_hour)
+ {
+ return(-1);
+ }
+ else if(t1->tm_min > t2->tm_min)
+ {
+ return(1);
+ }
+ else if(t1->tm_min < t2->tm_min)
+ {
+ return(-1);
+ }
+ else if(t1->tm_sec > t2->tm_sec)
+ {
+ return(1);
+ }
+ else if(t1->tm_sec < t2->tm_sec)
+ {
+ return(-1);
+ }
+ else
+ {
+ //
+ // Reaching this branch of the conditional means that all of the
+ // fields are equal, and thus the two times are equal.
+ //
+ return(0);
+ }
+}
+
+//*****************************************************************************
+//
+//! Converts calendar date and time to seconds.
+//!
+//! \param timeptr is a pointer to the time structure that is filled in with
+//! the broken down date and time.
+//!
+//! This function converts the date and time represented by the \e timeptr
+//! structure pointer to the number of seconds since midnight GMT on January 1,
+//! 1970 (traditional Unix epoch).
+//!
+//! \return Returns the calendar time and date as seconds. If the conversion
+//! was not possible then the function returns (uint32_t)(-1).
+//
+//*****************************************************************************
+time_t
+umktime(struct tm *timeptr)
+{
+ struct tm sTimeGuess;
+ unsigned long ulTimeGuess = 0x80000000;
+ unsigned long ulAdjust = 0x40000000;
+ int iSign;
+
+ //
+ // Seed the binary search with the first guess.
+ //
+ ulocaltime(ulTimeGuess, &sTimeGuess);
+ iSign = ucmptime(timeptr, &sTimeGuess);
+
+ //
+ // While the time is not yet found, execute a binary search.
+ //
+ while(iSign && ulAdjust)
+ {
+ //
+ // Adjust the time guess up or down depending on the result of the
+ // last compare.
+ //
+ ulTimeGuess = ((iSign > 0) ? (ulTimeGuess + ulAdjust) :
+ (ulTimeGuess - ulAdjust));
+ ulAdjust /= 2;
+
+ //
+ // Compare the new time guess against the time pointed at by the
+ // function parameters.
+ //
+ ulocaltime(ulTimeGuess, &sTimeGuess);
+ iSign = ucmptime(timeptr, &sTimeGuess);
+ }
+
+ //
+ // If the above loop was exited with iSign == 0, that means that the
+ // time in seconds was found, so return that value to the caller.
+ //
+ if(iSign == 0)
+ {
+ return(ulTimeGuess);
+ }
+
+ //
+ // Otherwise the time could not be converted so return an error.
+ //
+ else
+ {
+ return((unsigned long)-1);
+ }
+}
+
+//*****************************************************************************
+//
+//! Converts a string into its numeric equivalent.
+//!
+//! \param nptr is a pointer to the string containing the integer.
+//! \param endptr is a pointer that will be set to the first character past
+//! the integer in the string.
+//! \param base is the radix to use for the conversion; can be zero to
+//! auto-select the radix or between 2 and 16 to explicitly specify the radix.
+//!
+//! This function is very similar to the C library <tt>strtoul()</tt> function.
+//! It scans a string for the first token (that is, non-white space) and
+//! converts the value at that location in the string into an integer value.
+//!
+//! \return Returns the result of the conversion.
+//
+//*****************************************************************************
+unsigned long
+ustrtoul(const char * restrict nptr, const char ** restrict endptr, int base)
+{
+ unsigned long ulRet, ulDigit, ulNeg, ulValid;
+ const char *pcPtr;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(nptr);
+ ASSERT((base == 0) || ((base > 1) && (base <= 16)));
+
+ //
+ // Initially, the result is zero.
+ //
+ ulRet = 0;
+ ulNeg = 0;
+ ulValid = 0;
+
+ //
+ // Skip past any leading white space.
+ //
+ pcPtr = nptr;
+ while((*pcPtr == ' ') || (*pcPtr == '\t'))
+ {
+ pcPtr++;
+ }
+
+ //
+ // Take a leading + or - from the value.
+ //
+ if(*pcPtr == '-')
+ {
+ ulNeg = 1;
+ pcPtr++;
+ }
+ else if(*pcPtr == '+')
+ {
+ pcPtr++;
+ }
+
+ //
+ // See if the radix was not specified, or is 16, and the value starts with
+ // "0x" or "0X" (to indicate a hex value).
+ //
+ if(((base == 0) || (base == 16)) && (*pcPtr == '0') &&
+ ((pcPtr[1] == 'x') || (pcPtr[1] == 'X')))
+ {
+ //
+ // Skip the leading "0x".
+ //
+ pcPtr += 2;
+
+ //
+ // Set the radix to 16.
+ //
+ base = 16;
+ }
+
+ //
+ // See if the radix was not specified.
+ //
+ if(base == 0)
+ {
+ //
+ // See if the value starts with "0".
+ //
+ if(*pcPtr == '0')
+ {
+ //
+ // Values that start with "0" are assumed to be radix 8.
+ //
+ base = 8;
+ }
+ else
+ {
+ //
+ // Otherwise, the values are assumed to be radix 10.
+ //
+ base = 10;
+ }
+ }
+
+ //
+ // Loop while there are more valid digits to consume.
+ //
+ while(1)
+ {
+ //
+ // See if this character is a number.
+ //
+ if((*pcPtr >= '0') && (*pcPtr <= '9'))
+ {
+ //
+ // Convert the character to its integer equivalent.
+ //
+ ulDigit = *pcPtr++ - '0';
+ }
+
+ //
+ // Otherwise, see if this character is an upper case letter.
+ //
+ else if((*pcPtr >= 'A') && (*pcPtr <= 'Z'))
+ {
+ //
+ // Convert the character to its integer equivalent.
+ //
+ ulDigit = *pcPtr++ - 'A' + 10;
+ }
+
+ //
+ // Otherwise, see if this character is a lower case letter.
+ //
+ else if((*pcPtr >= 'a') && (*pcPtr <= 'z'))
+ {
+ //
+ // Convert the character to its integer equivalent.
+ //
+ ulDigit = *pcPtr++ - 'a' + 10;
+ }
+
+ //
+ // Otherwise, this is not a valid character.
+ //
+ else
+ {
+ //
+ // Stop converting this value.
+ //
+ break;
+ }
+
+ //
+ // See if this digit is valid for the chosen radix.
+ //
+ if(ulDigit >= base)
+ {
+ //
+ // Since this was not a valid digit, move the pointer back to the
+ // character that therefore should not have been consumed.
+ //
+ pcPtr--;
+
+ //
+ // Stop converting this value.
+ //
+ break;
+ }
+
+ //
+ // Add this digit to the converted value.
+ //
+ ulRet *= base;
+ ulRet += ulDigit;
+
+ //
+ // Since a digit has been added, this is now a valid result.
+ //
+ ulValid = 1;
+ }
+
+ //
+ // Set the return string pointer to the first character not consumed.
+ //
+ if(endptr)
+ {
+ *endptr = ulValid ? pcPtr : nptr;
+ }
+
+ //
+ // Return the converted value.
+ //
+ return(ulNeg ? (0 - ulRet) : ulRet);
+}
+
+//*****************************************************************************
+//
+// An array of the value of ten raised to the power-of-two exponents. This is
+// used for converting the decimal exponent into the floating-point value of
+// 10^exp.
+//
+//*****************************************************************************
+static const float g_pfExponents[] =
+{
+ 1.0e+01,
+ 1.0e+02,
+ 1.0e+04,
+ 1.0e+08,
+ 1.0e+16,
+ 1.0e+32,
+};
+
+//*****************************************************************************
+//
+//! Converts a string into its floating-point equivalent.
+//!
+//! \param nptr is a pointer to the string containing the floating-point
+//! value.
+//! \param endptr is a pointer that will be set to the first character past
+//! the floating-point value in the string.
+//!
+//! This function is very similar to the C library <tt>strtof()</tt> function.
+//! It scans a string for the first token (that is, non-white space) and
+//! converts the value at that location in the string into a floating-point
+//! value.
+//!
+//! \return Returns the result of the conversion.
+//
+//*****************************************************************************
+float
+ustrtof(const char *nptr, const char **endptr)
+{
+ unsigned long ulNeg, ulValid;
+ float fRet;
+ const char *pcPtr;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(nptr);
+
+ //
+ // Initially, the result is zero.
+ //
+ fRet = 0;
+ ulNeg = 0;
+ ulValid = 0;
+
+ //
+ // Skip past any leading white space.
+ //
+ pcPtr = nptr;
+ while((*pcPtr == ' ') || (*pcPtr == '\t'))
+ {
+ pcPtr++;
+ }
+
+ //
+ // Take a leading + or - from the value.
+ //
+ if(*pcPtr == '-')
+ {
+ ulNeg = 1;
+ pcPtr++;
+ }
+ else if(*pcPtr == '+')
+ {
+ pcPtr++;
+ }
+
+ //
+ // Loop while there are valid digits to consume.
+ //
+ while((*pcPtr >= '0') && (*pcPtr <= '9'))
+ {
+ //
+ // Add this digit to the converted value.
+ //
+ fRet *= 10;
+ fRet += *pcPtr++ - '0';
+
+ //
+ // Since a digit has been added, this is now a valid result.
+ //
+ ulValid = 1;
+ }
+
+ //
+ // See if the next character is a period and the character after that is a
+ // digit, indicating the start of the fractional portion of the value.
+ //
+ if((*pcPtr == '.') && (pcPtr[1] >= '0') && (pcPtr[1] <= '9'))
+ {
+ //
+ // Skip the period.
+ //
+ pcPtr++;
+
+ //
+ // Loop while there are valid fractional digits to consume.
+ //
+ float fDigit = 0.1;
+ while((*pcPtr >= '0') && (*pcPtr <= '9'))
+ {
+ //
+ // Add this digit to the converted value.
+ //
+ fRet += (*pcPtr++ - '0') * fDigit;
+ fDigit /= (float)10.0;
+
+ //
+ // Since a digit has been added, this is now a valid result.
+ //
+ ulValid = 1;
+ }
+ }
+
+ //
+ // See if the next character is an "e" and a valid number has been
+ // converted, indicating the start of the exponent.
+ //
+ if(((pcPtr[0] == 'e') || (pcPtr[0] == 'E')) && (ulValid == 1) &&
+ (((pcPtr[1] >= '0') && (pcPtr[1] <= '9')) ||
+ (((pcPtr[1] == '+') || (pcPtr[1] == '-')) &&
+ (pcPtr[2] >= '0') && (pcPtr[2] <= '9'))))
+ {
+ //
+ // Skip the "e".
+ //
+ pcPtr++;
+
+ //
+ // Take a leading + or - from the exponenet.
+ //
+ unsigned long ulExpNeg = 0;
+ if(*pcPtr == '-')
+ {
+ ulExpNeg = 1;
+ pcPtr++;
+ }
+ else if(*pcPtr == '+')
+ {
+ pcPtr++;
+ }
+
+ //
+ // Loop while there are valid digits in the exponent.
+ //
+ unsigned long ulExp = 0;
+ while((*pcPtr >= '0') && (*pcPtr <= '9'))
+ {
+ //
+ // Add this digit to the converted value.
+ //
+ ulExp *= 10;
+ ulExp += *pcPtr++ - '0';
+ }
+
+ //
+ // Raise ten to the power of the exponent. Do this via binary
+ // decomposition; for each binary bit set in the exponent, multiply the
+ // floating-point representation by ten raised to that binary value
+ // (extracted from the table above).
+ //
+ float fExp = 1;
+ unsigned long ulIdx = 0;
+ for(; ulIdx < 7; ulIdx++)
+ {
+ if(ulExp & (1 << ulIdx))
+ {
+ fExp *= g_pfExponents[ulIdx];
+ }
+ }
+
+ //
+ // If the exponent is negative, then the exponent needs to be inverted.
+ //
+ if(ulExpNeg == 1)
+ {
+ fExp = 1 / fExp;
+ }
+
+ //
+ // Multiply the result by the computed exponent value.
+ //
+ fRet *= fExp;
+ }
+
+ //
+ // Set the return string pointer to the first character not consumed.
+ //
+ if(endptr)
+ {
+ *endptr = ulValid ? pcPtr : nptr;
+ }
+
+ //
+ // Return the converted value.
+ //
+ return(ulNeg ? (0 - fRet) : fRet);
+}
+
+//*****************************************************************************
+//
+//! Returns the length of a null-terminated string.
+//!
+//! \param s is a pointer to the string whose length is to be found.
+//!
+//! This function is very similar to the C library <tt>strlen()</tt> function.
+//! It determines the length of the null-terminated string passed and returns
+//! this to the caller.
+//!
+//! This implementation assumes that single byte character strings are passed
+//! and will return incorrect values if passed some UTF-8 strings.
+//!
+//! \return Returns the length of the string pointed to by \e s.
+//
+//*****************************************************************************
+size_t
+ustrlen(const char *s)
+{
+ size_t len;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(s);
+
+ //
+ // Initialize the length.
+ //
+ len = 0;
+
+ //
+ // Step throug the string looking for a zero character (marking its end).
+ //
+ while(s[len])
+ {
+ //
+ // Zero not found so move on to the next character.
+ //
+ len++;
+ }
+
+ return(len);
+}
+
+//*****************************************************************************
+//
+//! Finds a substring within a string.
+//!
+//! \param s1 is a pointer to the string that will be searched.
+//! \param s2 is a pointer to the substring that is to be found within
+//! \e s1.
+//!
+//! This function is very similar to the C library <tt>strstr()</tt> function.
+//! It scans a string for the first instance of a given substring and returns
+//! a pointer to that substring. If the substring cannot be found, a NULL
+//! pointer is returned.
+//!
+//! \return Returns a pointer to the first occurrence of \e s2 within
+//! \e s1 or NULL if no match is found.
+//
+//*****************************************************************************
+char *
+ustrstr(const char *s1, const char *s2)
+{
+ size_t n;
+
+ //
+ // Get the length of the string to be found.
+ //
+ n = ustrlen(s2);
+
+ //
+ // Loop while we have not reached the end of the string.
+ //
+ while(*s1)
+ {
+ //
+ // Check to see if the substring appears at this position.
+ //
+ if(ustrncmp(s2, s1, n) == 0)
+ {
+ //
+ // It does so return the pointer.
+ //
+ return((char *)s1);
+ }
+
+ //
+ // Move to the next position in the string being searched.
+ //
+ s1++;
+ }
+
+ //
+ // We reached the end of the string without finding the substring so
+ // return NULL.
+ //
+ return((char *)0);
+}
+
+//*****************************************************************************
+//
+//! Compares two strings without regard to case.
+//!
+//! \param s1 points to the first string to be compared.
+//! \param s2 points to the second string to be compared.
+//! \param n is the maximum number of characters to compare.
+//!
+//! This function is very similar to the C library <tt>strncasecmp()</tt>
+//! function. It compares at most \e n characters of two strings without
+//! regard to case. The comparison ends if a terminating NULL character is
+//! found in either string before \e n characters are compared. In this case,
+//! the shorter string is deemed the lesser.
+//!
+//! \return Returns 0 if the two strings are equal, -1 if \e s1 is less
+//! than \e s2 and 1 if \e s1 is greater than \e s2.
+//
+//*****************************************************************************
+int
+ustrncasecmp(const char *s1, const char *s2, size_t n)
+{
+ //
+ // Loop while there are more characters to compare.
+ //
+ while(n)
+ {
+ //
+ // If we reached a NULL in both strings, they must be equal so
+ // we end the comparison and return 0
+ //
+ if(!*s1 && !*s2)
+ {
+ return(0);
+ }
+
+ //
+ // Lower case the characters at the current position before we compare.
+ //
+ char c1 = (((*s1 >= 'A') && (*s1 <= 'Z')) ? (*s1 + ('a' - 'A')) : *s1);
+ char c2 = (((*s2 >= 'A') && (*s2 <= 'Z')) ? (*s2 + ('a' - 'A')) : *s2);
+
+ //
+ // Compare the two characters and, if different, return the relevant
+ // return code.
+ //
+ if(c2 < c1)
+ {
+ return(1);
+ }
+ if(c1 < c2)
+ {
+ return(-1);
+ }
+
+ //
+ // Move on to the next character.
+ //
+ s1++;
+ s2++;
+ n--;
+ }
+
+ //
+ // If we fall out, the strings must be equal for at least the first n
+ // characters so return 0 to indicate this.
+ //
+ return(0);
+}
+
+//*****************************************************************************
+//
+//! Compares two strings without regard to case.
+//!
+//! \param s1 points to the first string to be compared.
+//! \param s2 points to the second string to be compared.
+//!
+//! This function is very similar to the C library <tt>strcasecmp()</tt>
+//! function. It compares two strings without regard to case. The comparison
+//! ends if a terminating NULL character is found in either string. In this
+//! case, the int16_ter string is deemed the lesser.
+//!
+//! \return Returns 0 if the two strings are equal, -1 if \e s1 is less
+//! than \e s2 and 1 if \e s1 is greater than \e s2.
+//
+//*****************************************************************************
+int
+ustrcasecmp(const char *s1, const char *s2)
+{
+ //
+ // Just let ustrncasecmp() handle this.
+ //
+ return(ustrncasecmp(s1, s2, (size_t)-1));
+}
+
+//*****************************************************************************
+//
+//! Compares two strings.
+//!
+//! \param s1 points to the first string to be compared.
+//! \param s2 points to the second string to be compared.
+//! \param n is the maximum number of characters to compare.
+//!
+//! This function is very similar to the C library <tt>strncmp()</tt> function.
+//! It compares at most \e n characters of two strings taking case into
+//! account. The comparison ends if a terminating NULL character is found in
+//! either string before \e n characters are compared. In this case, the
+//! int16_ter string is deemed the lesser.
+//!
+//! \return Returns 0 if the two strings are equal, -1 if \e s1 is less
+//! than \e s2 and 1 if \e s1 is greater than \e s2.
+//
+//*****************************************************************************
+int
+ustrncmp(const char *s1, const char *s2, size_t n)
+{
+ //
+ // Loop while there are more characters.
+ //
+ while(n)
+ {
+ //
+ // If we reached a NULL in both strings, they must be equal so we end
+ // the comparison and return 0
+ //
+ if(!*s1 && !*s2)
+ {
+ return(0);
+ }
+
+ //
+ // Compare the two characters and, if different, return the relevant
+ // return code.
+ //
+ if(*s2 < *s1)
+ {
+ return(1);
+ }
+ if(*s1 < *s2)
+ {
+ return(-1);
+ }
+
+ //
+ // Move on to the next character.
+ //
+ s1++;
+ s2++;
+ n--;
+ }
+
+ //
+ // If we fall out, the strings must be equal for at least the first n
+ // characters so return 0 to indicate this.
+ //
+ return(0);
+}
+
+//*****************************************************************************
+//
+//! Compares two strings.
+//!
+//! \param s1 points to the first string to be compared.
+//! \param s2 points to the second string to be compared.
+//!
+//! This function is very similar to the C library <tt>strcmp()</tt>
+//! function. It compares two strings, taking case into account. The
+//! comparison ends if a terminating NULL character is found in either string.
+//! In this case, the int16_ter string is deemed the lesser.
+//!
+//! \return Returns 0 if the two strings are equal, -1 if \e s1 is less
+//! than \e s2 and 1 if \e s1 is greater than \e s2.
+//
+//*****************************************************************************
+int
+ustrcmp(const char *s1, const char *s2)
+{
+ //
+ // Pass this on to ustrncmp.
+ //
+ return(ustrncmp(s1, s2, (size_t)-1));
+}
+
+//*****************************************************************************
+//
+// Random Number Generator Seed Value
+//
+//*****************************************************************************
+static unsigned int g_iRandomSeed = 1;
+
+//*****************************************************************************
+//
+//! Set the random number generator seed.
+//!
+//! \param seed is the new seed value to use for the random number
+//! generator.
+//!
+//! This function is very similar to the C library <tt>srand()</tt> function.
+//! It will set the seed value used in the <tt>urand()</tt> function.
+//!
+//! \return None
+//
+//*****************************************************************************
+void
+usrand(unsigned int seed)
+{
+ g_iRandomSeed = seed;
+}
+
+//*****************************************************************************
+//
+//! Generate a new (pseudo) random number
+//!
+//! This function is very similar to the C library <tt>rand()</tt> function.
+//! It will generate a pseudo-random number sequence based on the seed value.
+//!
+//! \return A pseudo-random number will be returned.
+//
+//*****************************************************************************
+int
+urand(void)
+{
+ //
+ // Generate a new pseudo-random number with a linear congruence random
+ // number generator. This new random number becomes the seed for the next
+ // random number.
+ //
+ g_iRandomSeed = (g_iRandomSeed * 1664525) + 1013904223;
+
+ //
+ // Return the new random number.
+ //
+ return((int)g_iRandomSeed);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.c b/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.c
new file mode 100644
index 000000000..7493ef609
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.c
@@ -0,0 +1,227 @@
+/* Generated by the protocol buffer compiler. DO NOT EDIT! */
+/* Generated from: person.proto */
+
+/* Do not generate deprecated warnings for self */
+#ifndef PROTOBUF_C__NO_DEPRECATED
+#define PROTOBUF_C__NO_DEPRECATED
+#endif
+
+#include "person-pb-c.h"
+void address__init
+ (Address *message)
+{
+ static const Address init_value = ADDRESS__INIT;
+ *message = init_value;
+}
+size_t address__get_packed_size
+ (const Address *message)
+{
+ assert(message->base.descriptor == &address__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t address__pack
+ (const Address *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &address__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t address__pack_to_buffer
+ (const Address *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &address__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+Address *
+ address__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (Address *)
+ protobuf_c_message_unpack (&address__descriptor,
+ allocator, len, data);
+}
+void address__free_unpacked
+ (Address *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &address__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void person__init
+ (Person *message)
+{
+ static const Person init_value = PERSON__INIT;
+ *message = init_value;
+}
+size_t person__get_packed_size
+ (const Person *message)
+{
+ assert(message->base.descriptor == &person__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t person__pack
+ (const Person *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &person__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t person__pack_to_buffer
+ (const Person *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &person__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+Person *
+ person__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (Person *)
+ protobuf_c_message_unpack (&person__descriptor,
+ allocator, len, data);
+}
+void person__free_unpacked
+ (Person *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &person__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+static const ProtobufCFieldDescriptor address__field_descriptors[2] =
+{
+ {
+ "street",
+ 1,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(Address, street),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "number",
+ 2,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_INT32,
+ offsetof(Address, has_number),
+ offsetof(Address, number),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned address__field_indices_by_name[] = {
+ 1, /* field[1] = number */
+ 0, /* field[0] = street */
+};
+static const ProtobufCIntRange address__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 2 }
+};
+const ProtobufCMessageDescriptor address__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "Address",
+ "Address",
+ "Address",
+ "",
+ sizeof(Address),
+ 2,
+ address__field_descriptors,
+ address__field_indices_by_name,
+ 1, address__number_ranges,
+ (ProtobufCMessageInit) address__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor person__field_descriptors[4] =
+{
+ {
+ "name",
+ 1,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(Person, name),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "age",
+ 2,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_INT32,
+ offsetof(Person, has_age),
+ offsetof(Person, age),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "email",
+ 3,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(Person, email),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "address",
+ 4,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(Person, n_address),
+ offsetof(Person, address),
+ &address__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned person__field_indices_by_name[] = {
+ 3, /* field[3] = address */
+ 1, /* field[1] = age */
+ 2, /* field[2] = email */
+ 0, /* field[0] = name */
+};
+static const ProtobufCIntRange person__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 4 }
+};
+const ProtobufCMessageDescriptor person__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "Person",
+ "Person",
+ "Person",
+ "",
+ sizeof(Person),
+ 4,
+ person__field_descriptors,
+ person__field_indices_by_name,
+ 1, person__number_ranges,
+ (ProtobufCMessageInit) person__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
diff --git a/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.h b/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.h
new file mode 100644
index 000000000..87b0007b1
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.h
@@ -0,0 +1,112 @@
+/* Generated by the protocol buffer compiler. DO NOT EDIT! */
+/* Generated from: person.proto */
+
+#ifndef PROTOBUF_C_person_2eproto__INCLUDED
+#define PROTOBUF_C_person_2eproto__INCLUDED
+
+#include <protobuf-c.h>
+
+PROTOBUF_C__BEGIN_DECLS
+
+#if PROTOBUF_C_VERSION_NUMBER < 1003000
+# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
+#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION
+# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
+#endif
+
+
+typedef struct _Address Address;
+typedef struct _Person Person;
+
+
+/* --- enums --- */
+
+
+/* --- messages --- */
+
+struct _Address
+{
+ ProtobufCMessage base;
+ char *street;
+ protobuf_c_boolean has_number;
+ int32_t number;
+};
+#define ADDRESS__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&address__descriptor) \
+ , NULL, 0, 0 }
+
+
+struct _Person
+{
+ ProtobufCMessage base;
+ char *name;
+ protobuf_c_boolean has_age;
+ int32_t age;
+ char *email;
+ size_t n_address;
+ Address **address;
+};
+#define PERSON__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&person__descriptor) \
+ , NULL, 0, 0, NULL, 0,NULL }
+
+
+/* Address methods */
+void address__init
+ (Address *message);
+size_t address__get_packed_size
+ (const Address *message);
+size_t address__pack
+ (const Address *message,
+ uint8_t *out);
+size_t address__pack_to_buffer
+ (const Address *message,
+ ProtobufCBuffer *buffer);
+Address *
+ address__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void address__free_unpacked
+ (Address *message,
+ ProtobufCAllocator *allocator);
+/* Person methods */
+void person__init
+ (Person *message);
+size_t person__get_packed_size
+ (const Person *message);
+size_t person__pack
+ (const Person *message,
+ uint8_t *out);
+size_t person__pack_to_buffer
+ (const Person *message,
+ ProtobufCBuffer *buffer);
+Person *
+ person__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void person__free_unpacked
+ (Person *message,
+ ProtobufCAllocator *allocator);
+/* --- per-message closures --- */
+
+typedef void (*Address_Closure)
+ (const Address *message,
+ void *closure_data);
+typedef void (*Person_Closure)
+ (const Person *message,
+ void *closure_data);
+
+/* --- services --- */
+
+
+/* --- descriptors --- */
+
+extern const ProtobufCMessageDescriptor address__descriptor;
+extern const ProtobufCMessageDescriptor person__descriptor;
+
+PROTOBUF_C__END_DECLS
+
+
+#endif /* PROTOBUF_C_person_2eproto__INCLUDED */
diff --git a/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.c b/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.c
new file mode 100644
index 000000000..5debac820
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.c
@@ -0,0 +1,3642 @@
+/*
+ * Copyright (c) 2008-2015, Dave Benson and the protobuf-c authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*! \file
+ * Support library for `protoc-c` generated code.
+ *
+ * This file implements the public API used by the code generated
+ * by `protoc-c`.
+ *
+ * \authors Dave Benson and the protobuf-c authors
+ *
+ * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
+ */
+
+/**
+ * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math
+ * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64).
+ *
+ * \todo Use size_t consistently.
+ */
+
+#include <stdlib.h> /* for malloc, free */
+#include <string.h> /* for strcmp, strlen, memcpy, memmove, memset */
+
+#include "protobuf-c.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0)
+
+/* Workaround for Microsoft compilers. */
+#ifdef _MSC_VER
+# define inline __inline
+#endif
+
+/**
+ * \defgroup internal Internal functions and macros
+ *
+ * These are not exported by the library but are useful to developers working
+ * on `libprotobuf-c` itself.
+ */
+
+/**
+ * \defgroup macros Utility macros for manipulating structures
+ *
+ * Macros and constants used to manipulate the base "classes" generated by
+ * `protobuf-c`. They also define limits and check correctness.
+ *
+ * \ingroup internal
+ * @{
+ */
+
+/** The maximum length of a 64-bit integer in varint encoding. */
+#define MAX_UINT64_ENCODED_SIZE 10
+
+#ifndef PROTOBUF_C_UNPACK_ERROR
+# define PROTOBUF_C_UNPACK_ERROR(...)
+#endif
+
+const char protobuf_c_empty_string[] = "";
+
+/**
+ * Internal `ProtobufCMessage` manipulation macro.
+ *
+ * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and
+ * STRUCT_MEMBER_PTR().
+ */
+#define STRUCT_MEMBER_P(struct_p, struct_offset) \
+ ((void *) ((uint8_t *) (struct_p) + (struct_offset)))
+
+/**
+ * Return field in a `ProtobufCMessage` based on offset.
+ *
+ * Take a pointer to a `ProtobufCMessage` and find the field at the offset.
+ * Cast it to the passed type.
+ */
+#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
+ (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
+
+/**
+ * Return field in a `ProtobufCMessage` based on offset.
+ *
+ * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast
+ * it to a pointer to the passed type.
+ */
+#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
+ ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
+
+/* Assertions for magic numbers. */
+
+#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
+ assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC)
+
+#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
+ assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
+
+#define ASSERT_IS_MESSAGE(message) \
+ ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
+
+#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
+ assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC)
+
+/**@}*/
+
+/* --- version --- */
+
+const char *
+protobuf_c_version(void)
+{
+ return PROTOBUF_C_VERSION;
+}
+
+uint32_t
+protobuf_c_version_number(void)
+{
+ return PROTOBUF_C_VERSION_NUMBER;
+}
+
+/* --- allocator --- */
+
+static void *
+system_alloc(void *allocator_data, size_t size)
+{
+ return malloc(size);
+}
+
+static void
+system_free(void *allocator_data, void *data)
+{
+ free(data);
+}
+
+static inline void *
+do_alloc(ProtobufCAllocator *allocator, size_t size)
+{
+ return allocator->alloc(allocator->allocator_data, size);
+}
+
+static inline void
+do_free(ProtobufCAllocator *allocator, void *data)
+{
+ if (data != NULL)
+ allocator->free(allocator->allocator_data, data);
+}
+
+/*
+ * This allocator uses the system's malloc() and free(). It is the default
+ * allocator used if NULL is passed as the ProtobufCAllocator to an exported
+ * function.
+ */
+static ProtobufCAllocator protobuf_c__allocator = {
+ .alloc = &system_alloc,
+ .free = &system_free,
+ .allocator_data = NULL,
+};
+
+/* === buffer-simple === */
+
+void
+protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer,
+ size_t len, const uint8_t *data)
+{
+ ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
+ size_t new_len = simp->len + len;
+
+ if (new_len > simp->alloced) {
+ ProtobufCAllocator *allocator = simp->allocator;
+ size_t new_alloced = simp->alloced * 2;
+ uint8_t *new_data;
+
+ if (allocator == NULL)
+ allocator = &protobuf_c__allocator;
+ while (new_alloced < new_len)
+ new_alloced += new_alloced;
+ new_data = do_alloc(allocator, new_alloced);
+ if (!new_data)
+ return;
+ memcpy(new_data, simp->data, simp->len);
+ if (simp->must_free_data)
+ do_free(allocator, simp->data);
+ else
+ simp->must_free_data = TRUE;
+ simp->data = new_data;
+ simp->alloced = new_alloced;
+ }
+ memcpy(simp->data + simp->len, data, len);
+ simp->len = new_len;
+}
+
+/**
+ * \defgroup packedsz protobuf_c_message_get_packed_size() implementation
+ *
+ * Routines mainly used by protobuf_c_message_get_packed_size().
+ *
+ * \ingroup internal
+ * @{
+ */
+
+/**
+ * Return the number of bytes required to store the tag for the field. Includes
+ * 3 bits for the wire-type, and a single bit that denotes the end-of-tag.
+ *
+ * \param number
+ * Field tag to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+get_tag_size(uint32_t number)
+{
+ if (number < (1UL << 4)) {
+ return 1;
+ } else if (number < (1UL << 11)) {
+ return 2;
+ } else if (number < (1UL << 18)) {
+ return 3;
+ } else if (number < (1UL << 25)) {
+ return 4;
+ } else {
+ return 5;
+ }
+}
+
+/**
+ * Return the number of bytes required to store a variable-length unsigned
+ * 32-bit integer in base-128 varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+uint32_size(uint32_t v)
+{
+ if (v < (1UL << 7)) {
+ return 1;
+ } else if (v < (1UL << 14)) {
+ return 2;
+ } else if (v < (1UL << 21)) {
+ return 3;
+ } else if (v < (1UL << 28)) {
+ return 4;
+ } else {
+ return 5;
+ }
+}
+
+/**
+ * Return the number of bytes required to store a variable-length signed 32-bit
+ * integer in base-128 varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+int32_size(int32_t v)
+{
+ if (v < 0) {
+ return 10;
+ } else if (v < (1L << 7)) {
+ return 1;
+ } else if (v < (1L << 14)) {
+ return 2;
+ } else if (v < (1L << 21)) {
+ return 3;
+ } else if (v < (1L << 28)) {
+ return 4;
+ } else {
+ return 5;
+ }
+}
+
+/**
+ * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed
+ * integer.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * ZigZag encoded integer.
+ */
+static inline uint32_t
+zigzag32(int32_t v)
+{
+ if (v < 0)
+ return (-(uint32_t)v) * 2 - 1;
+ else
+ return (uint32_t)(v) * 2;
+}
+
+/**
+ * Return the number of bytes required to store a signed 32-bit integer,
+ * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128
+ * varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+sint32_size(int32_t v)
+{
+ return uint32_size(zigzag32(v));
+}
+
+/**
+ * Return the number of bytes required to store a 64-bit unsigned integer in
+ * base-128 varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+uint64_size(uint64_t v)
+{
+ uint32_t upper_v = (uint32_t) (v >> 32);
+
+ if (upper_v == 0) {
+ return uint32_size((uint32_t) v);
+ } else if (upper_v < (1UL << 3)) {
+ return 5;
+ } else if (upper_v < (1UL << 10)) {
+ return 6;
+ } else if (upper_v < (1UL << 17)) {
+ return 7;
+ } else if (upper_v < (1UL << 24)) {
+ return 8;
+ } else if (upper_v < (1UL << 31)) {
+ return 9;
+ } else {
+ return 10;
+ }
+}
+
+/**
+ * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed
+ * integer.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * ZigZag encoded integer.
+ */
+static inline uint64_t
+zigzag64(int64_t v)
+{
+ if (v < 0)
+ return (-(uint64_t)v) * 2 - 1;
+ else
+ return (uint64_t)(v) * 2;
+}
+
+/**
+ * Return the number of bytes required to store a signed 64-bit integer,
+ * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128
+ * varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+sint64_size(int64_t v)
+{
+ return uint64_size(zigzag64(v));
+}
+
+/**
+ * Calculate the serialized size of a single required message field, including
+ * the space needed by the preceding tag.
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+required_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ const void *member)
+{
+ size_t rv = get_tag_size(field->id);
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ return rv + sint32_size(*(const int32_t *) member);
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ return rv + int32_size(*(const int32_t *) member);
+ case PROTOBUF_C_TYPE_UINT32:
+ return rv + uint32_size(*(const uint32_t *) member);
+ case PROTOBUF_C_TYPE_SINT64:
+ return rv + sint64_size(*(const int64_t *) member);
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ return rv + uint64_size(*(const uint64_t *) member);
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ return rv + 4;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ return rv + 8;
+ case PROTOBUF_C_TYPE_BOOL:
+ return rv + 1;
+ case PROTOBUF_C_TYPE_FLOAT:
+ return rv + 4;
+ case PROTOBUF_C_TYPE_DOUBLE:
+ return rv + 8;
+ case PROTOBUF_C_TYPE_STRING: {
+ const char *str = *(char * const *) member;
+ size_t len = str ? strlen(str) : 0;
+ return rv + uint32_size(len) + len;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ size_t len = ((const ProtobufCBinaryData *) member)->len;
+ return rv + uint32_size(len) + len;
+ }
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
+ size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0;
+ return rv + uint32_size(subrv) + subrv;
+ }
+ }
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ return 0;
+}
+
+/**
+ * Calculate the serialized size of a single oneof message field, including
+ * the space needed by the preceding tag. Returns 0 if the oneof field isn't
+ * selected or is not set.
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param oneof_case
+ * Enum value that selects the field in the oneof.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+oneof_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ uint32_t oneof_case,
+ const void *member)
+{
+ if (oneof_case != field->id) {
+ return 0;
+ }
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void * const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ }
+ return required_field_get_packed_size(field, member);
+}
+
+/**
+ * Calculate the serialized size of a single optional message field, including
+ * the space needed by the preceding tag. Returns 0 if the optional field isn't
+ * set.
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param has
+ * True if the field exists, false if not.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+optional_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ const protobuf_c_boolean has,
+ const void *member)
+{
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void * const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ } else {
+ if (!has)
+ return 0;
+ }
+ return required_field_get_packed_size(field, member);
+}
+
+static protobuf_c_boolean
+field_is_zeroish(const ProtobufCFieldDescriptor *field,
+ const void *member)
+{
+ protobuf_c_boolean ret = FALSE;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_BOOL:
+ ret = (0 == *(const protobuf_c_boolean *) member);
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_SINT32:
+ case PROTOBUF_C_TYPE_INT32:
+ case PROTOBUF_C_TYPE_UINT32:
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ ret = (0 == *(const uint32_t *) member);
+ break;
+ case PROTOBUF_C_TYPE_SINT64:
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ ret = (0 == *(const uint64_t *) member);
+ break;
+ case PROTOBUF_C_TYPE_FLOAT:
+ ret = (0 == *(const float *) member);
+ break;
+ case PROTOBUF_C_TYPE_DOUBLE:
+ ret = (0 == *(const double *) member);
+ break;
+ case PROTOBUF_C_TYPE_STRING:
+ ret = (NULL == *(const char * const *) member) ||
+ ('\0' == **(const char * const *) member);
+ break;
+ case PROTOBUF_C_TYPE_BYTES:
+ case PROTOBUF_C_TYPE_MESSAGE:
+ ret = (NULL == *(const void * const *) member);
+ break;
+ default:
+ ret = TRUE;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Calculate the serialized size of a single unlabeled message field, including
+ * the space needed by the preceding tag. Returns 0 if the field isn't set or
+ * if it is set to a "zeroish" value (null pointer or 0 for numerical values).
+ * Unlabeled fields are supported only in proto3.
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+unlabeled_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ const void *member)
+{
+ if (field_is_zeroish(field, member))
+ return 0;
+ return required_field_get_packed_size(field, member);
+}
+
+/**
+ * Calculate the serialized size of repeated message fields, which may consist
+ * of any number of values (including 0). Includes the space needed by the
+ * preceding tags (as needed).
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param count
+ * Number of repeated field members.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ size_t count, const void *member)
+{
+ size_t header_size;
+ size_t rv = 0;
+ unsigned i;
+ void *array = *(void * const *) member;
+
+ if (count == 0)
+ return 0;
+ header_size = get_tag_size(field->id);
+ if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
+ header_size *= count;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ for (i = 0; i < count; i++)
+ rv += sint32_size(((int32_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ for (i = 0; i < count; i++)
+ rv += int32_size(((int32_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_UINT32:
+ for (i = 0; i < count; i++)
+ rv += uint32_size(((uint32_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_SINT64:
+ for (i = 0; i < count; i++)
+ rv += sint64_size(((int64_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ for (i = 0; i < count; i++)
+ rv += uint64_size(((uint64_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ rv += 4 * count;
+ break;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ rv += 8 * count;
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ rv += count;
+ break;
+ case PROTOBUF_C_TYPE_STRING:
+ for (i = 0; i < count; i++) {
+ size_t len = strlen(((char **) array)[i]);
+ rv += uint32_size(len) + len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_BYTES:
+ for (i = 0; i < count; i++) {
+ size_t len = ((ProtobufCBinaryData *) array)[i].len;
+ rv += uint32_size(len) + len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_MESSAGE:
+ for (i = 0; i < count; i++) {
+ size_t len = protobuf_c_message_get_packed_size(
+ ((ProtobufCMessage **) array)[i]);
+ rv += uint32_size(len) + len;
+ }
+ break;
+ }
+
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
+ header_size += uint32_size(rv);
+ return header_size + rv;
+}
+
+/**
+ * Calculate the serialized size of an unknown field, i.e. one that is passed
+ * through mostly uninterpreted. This is required for forward compatibility if
+ * new fields are added to the message descriptor.
+ *
+ * \param field
+ * Unknown field type.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field)
+{
+ return get_tag_size(field->tag) + field->len;
+}
+
+/**@}*/
+
+/*
+ * Calculate the serialized size of the message.
+ */
+size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
+{
+ unsigned i;
+ size_t rv = 0;
+
+ ASSERT_IS_MESSAGE(message);
+ for (i = 0; i < message->descriptor->n_fields; i++) {
+ const ProtobufCFieldDescriptor *field =
+ message->descriptor->fields + i;
+ const void *member =
+ ((const char *) message) + field->offset;
+ const void *qmember =
+ ((const char *) message) + field->quantifier_offset;
+
+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
+ rv += required_field_get_packed_size(field, member);
+ } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
+ field->label == PROTOBUF_C_LABEL_NONE) &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
+ rv += oneof_field_get_packed_size(
+ field,
+ *(const uint32_t *) qmember,
+ member
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
+ rv += optional_field_get_packed_size(
+ field,
+ *(protobuf_c_boolean *) qmember,
+ member
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_NONE) {
+ rv += unlabeled_field_get_packed_size(
+ field,
+ member
+ );
+ } else {
+ rv += repeated_field_get_packed_size(
+ field,
+ *(const size_t *) qmember,
+ member
+ );
+ }
+ }
+ for (i = 0; i < message->n_unknown_fields; i++)
+ rv += unknown_field_get_packed_size(&message->unknown_fields[i]);
+ return rv;
+}
+
+/**
+ * \defgroup pack protobuf_c_message_pack() implementation
+ *
+ * Routines mainly used by protobuf_c_message_pack().
+ *
+ * \ingroup internal
+ * @{
+ */
+
+/**
+ * Pack an unsigned 32-bit integer in base-128 varint encoding and return the
+ * number of bytes written, which must be 5 or less.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+uint32_pack(uint32_t value, uint8_t *out)
+{
+ unsigned rv = 0;
+
+ if (value >= 0x80) {
+ out[rv++] = value | 0x80;
+ value >>= 7;
+ if (value >= 0x80) {
+ out[rv++] = value | 0x80;
+ value >>= 7;
+ if (value >= 0x80) {
+ out[rv++] = value | 0x80;
+ value >>= 7;
+ if (value >= 0x80) {
+ out[rv++] = value | 0x80;
+ value >>= 7;
+ }
+ }
+ }
+ }
+ /* assert: value<128 */
+ out[rv++] = value;
+ return rv;
+}
+
+/**
+ * Pack a signed 32-bit integer and return the number of bytes written.
+ * Negative numbers are encoded as two's complement 64-bit integers.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+int32_pack(int32_t value, uint8_t *out)
+{
+ if (value < 0) {
+ out[0] = value | 0x80;
+ out[1] = (value >> 7) | 0x80;
+ out[2] = (value >> 14) | 0x80;
+ out[3] = (value >> 21) | 0x80;
+ out[4] = (value >> 28) | 0x80;
+ out[5] = out[6] = out[7] = out[8] = 0xff;
+ out[9] = 0x01;
+ return 10;
+ } else {
+ return uint32_pack(value, out);
+ }
+}
+
+/**
+ * Pack a signed 32-bit integer using ZigZag encoding and return the number of
+ * bytes written.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+sint32_pack(int32_t value, uint8_t *out)
+{
+ return uint32_pack(zigzag32(value), out);
+}
+
+/**
+ * Pack a 64-bit unsigned integer using base-128 varint encoding and return the
+ * number of bytes written.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+uint64_pack(uint64_t value, uint8_t *out)
+{
+ uint32_t hi = (uint32_t) (value >> 32);
+ uint32_t lo = (uint32_t) value;
+ unsigned rv;
+
+ if (hi == 0)
+ return uint32_pack((uint32_t) lo, out);
+ out[0] = (lo) | 0x80;
+ out[1] = (lo >> 7) | 0x80;
+ out[2] = (lo >> 14) | 0x80;
+ out[3] = (lo >> 21) | 0x80;
+ if (hi < 8) {
+ out[4] = (hi << 4) | (lo >> 28);
+ return 5;
+ } else {
+ out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80;
+ hi >>= 3;
+ }
+ rv = 5;
+ while (hi >= 128) {
+ out[rv++] = hi | 0x80;
+ hi >>= 7;
+ }
+ out[rv++] = hi;
+ return rv;
+}
+
+/**
+ * Pack a 64-bit signed integer in ZigZag encoding and return the number of
+ * bytes written.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+sint64_pack(int64_t value, uint8_t *out)
+{
+ return uint64_pack(zigzag64(value), out);
+}
+
+/**
+ * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire
+ * types fixed32, sfixed32, float. Similar to "htole32".
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+fixed32_pack(uint32_t value, void *out)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(out, &value, 4);
+#else
+ uint8_t *buf = out;
+
+ buf[0] = value;
+ buf[1] = value >> 8;
+ buf[2] = value >> 16;
+ buf[3] = value >> 24;
+#endif
+ return 4;
+}
+
+/**
+ * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire
+ * types fixed64, sfixed64, double. Similar to "htole64".
+ *
+ * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit
+ * version would be appreciated, plus a way to decide to use 64-bit math where
+ * convenient.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+fixed64_pack(uint64_t value, void *out)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(out, &value, 8);
+#else
+ fixed32_pack(value, out);
+ fixed32_pack(value >> 32, ((char *) out) + 4);
+#endif
+ return 8;
+}
+
+/**
+ * Pack a boolean value as an integer and return the number of bytes written.
+ *
+ * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c
+ * that is idiomatic C++ in some STL implementations.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+boolean_pack(protobuf_c_boolean value, uint8_t *out)
+{
+ *out = value ? TRUE : FALSE;
+ return 1;
+}
+
+/**
+ * Pack a NUL-terminated C string and return the number of bytes written. The
+ * output includes a length delimiter.
+ *
+ * The NULL pointer is treated as an empty string. This isn't really necessary,
+ * but it allows people to leave required strings blank. (See Issue #13 in the
+ * bug tracker for a little more explanation).
+ *
+ * \param str
+ * String to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+string_pack(const char *str, uint8_t *out)
+{
+ if (str == NULL) {
+ out[0] = 0;
+ return 1;
+ } else {
+ size_t len = strlen(str);
+ size_t rv = uint32_pack(len, out);
+ memcpy(out + rv, str, len);
+ return rv + len;
+ }
+}
+
+/**
+ * Pack a ProtobufCBinaryData and return the number of bytes written. The output
+ * includes a length delimiter.
+ *
+ * \param bd
+ * ProtobufCBinaryData to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out)
+{
+ size_t len = bd->len;
+ size_t rv = uint32_pack(len, out);
+ memcpy(out + rv, bd->data, len);
+ return rv + len;
+}
+
+/**
+ * Pack a ProtobufCMessage and return the number of bytes written. The output
+ * includes a length delimiter.
+ *
+ * \param message
+ * ProtobufCMessage object to pack.
+ * \param[out] out
+ * Packed message.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out)
+{
+ if (message == NULL) {
+ out[0] = 0;
+ return 1;
+ } else {
+ size_t rv = protobuf_c_message_pack(message, out + 1);
+ uint32_t rv_packed_size = uint32_size(rv);
+ if (rv_packed_size != 1)
+ memmove(out + rv_packed_size, out + 1, rv);
+ return uint32_pack(rv, out) + rv;
+ }
+}
+
+/**
+ * Pack a field tag.
+ *
+ * Wire-type will be added in required_field_pack().
+ *
+ * \todo Just call uint64_pack on 64-bit platforms.
+ *
+ * \param id
+ * Tag value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+tag_pack(uint32_t id, uint8_t *out)
+{
+ if (id < (1UL << (32 - 3)))
+ return uint32_pack(id << 3, out);
+ else
+ return uint64_pack(((uint64_t) id) << 3, out);
+}
+
+/**
+ * Pack a required field and return the number of bytes written.
+ *
+ * \param field
+ * Field descriptor.
+ * \param member
+ * The field member.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+required_field_pack(const ProtobufCFieldDescriptor *field,
+ const void *member, uint8_t *out)
+{
+ size_t rv = tag_pack(field->id, out);
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + sint32_pack(*(const int32_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + int32_pack(*(const int32_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_UINT32:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + uint32_pack(*(const uint32_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_SINT64:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + sint64_pack(*(const int64_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + uint64_pack(*(const uint64_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
+ return rv + fixed32_pack(*(const uint32_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
+ return rv + fixed64_pack(*(const uint64_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_BOOL:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv);
+ case PROTOBUF_C_TYPE_STRING:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ return rv + string_pack(*(char *const *) member, out + rv);
+ case PROTOBUF_C_TYPE_BYTES:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv);
+ case PROTOBUF_C_TYPE_MESSAGE:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv);
+ }
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ return 0;
+}
+
+/**
+ * Pack a oneof field and return the number of bytes written. Only packs the
+ * field that is selected by the case enum.
+ *
+ * \param field
+ * Field descriptor.
+ * \param oneof_case
+ * Enum value that selects the field in the oneof.
+ * \param member
+ * The field member.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+oneof_field_pack(const ProtobufCFieldDescriptor *field,
+ uint32_t oneof_case,
+ const void *member, uint8_t *out)
+{
+ if (oneof_case != field->id) {
+ return 0;
+ }
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void * const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ }
+ return required_field_pack(field, member, out);
+}
+
+/**
+ * Pack an optional field and return the number of bytes written.
+ *
+ * \param field
+ * Field descriptor.
+ * \param has
+ * Whether the field is set.
+ * \param member
+ * The field member.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+optional_field_pack(const ProtobufCFieldDescriptor *field,
+ const protobuf_c_boolean has,
+ const void *member, uint8_t *out)
+{
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void * const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ } else {
+ if (!has)
+ return 0;
+ }
+ return required_field_pack(field, member, out);
+}
+
+/**
+ * Pack an unlabeled field and return the number of bytes written.
+ *
+ * \param field
+ * Field descriptor.
+ * \param member
+ * The field member.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+unlabeled_field_pack(const ProtobufCFieldDescriptor *field,
+ const void *member, uint8_t *out)
+{
+ if (field_is_zeroish(field, member))
+ return 0;
+ return required_field_pack(field, member, out);
+}
+
+/**
+ * Given a field type, return the in-memory size.
+ *
+ * \todo Implement as a table lookup.
+ *
+ * \param type
+ * Field type.
+ * \return
+ * Size of the field.
+ */
+static inline size_t
+sizeof_elt_in_repeated_array(ProtobufCType type)
+{
+ switch (type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ case PROTOBUF_C_TYPE_INT32:
+ case PROTOBUF_C_TYPE_UINT32:
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ case PROTOBUF_C_TYPE_ENUM:
+ return 4;
+ case PROTOBUF_C_TYPE_SINT64:
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ return 8;
+ case PROTOBUF_C_TYPE_BOOL:
+ return sizeof(protobuf_c_boolean);
+ case PROTOBUF_C_TYPE_STRING:
+ case PROTOBUF_C_TYPE_MESSAGE:
+ return sizeof(void *);
+ case PROTOBUF_C_TYPE_BYTES:
+ return sizeof(ProtobufCBinaryData);
+ }
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ return 0;
+}
+
+/**
+ * Pack an array of 32-bit quantities.
+ *
+ * \param[out] out
+ * Destination.
+ * \param[in] in
+ * Source.
+ * \param[in] n
+ * Number of elements in the source array.
+ */
+static void
+copy_to_little_endian_32(void *out, const void *in, const unsigned n)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(out, in, n * 4);
+#else
+ unsigned i;
+ const uint32_t *ini = in;
+ for (i = 0; i < n; i++)
+ fixed32_pack(ini[i], (uint32_t *) out + i);
+#endif
+}
+
+/**
+ * Pack an array of 64-bit quantities.
+ *
+ * \param[out] out
+ * Destination.
+ * \param[in] in
+ * Source.
+ * \param[in] n
+ * Number of elements in the source array.
+ */
+static void
+copy_to_little_endian_64(void *out, const void *in, const unsigned n)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(out, in, n * 8);
+#else
+ unsigned i;
+ const uint64_t *ini = in;
+ for (i = 0; i < n; i++)
+ fixed64_pack(ini[i], (uint64_t *) out + i);
+#endif
+}
+
+/**
+ * Get the minimum number of bytes required to pack a field value of a
+ * particular type.
+ *
+ * \param type
+ * Field type.
+ * \return
+ * Number of bytes.
+ */
+static unsigned
+get_type_min_size(ProtobufCType type)
+{
+ if (type == PROTOBUF_C_TYPE_SFIXED32 ||
+ type == PROTOBUF_C_TYPE_FIXED32 ||
+ type == PROTOBUF_C_TYPE_FLOAT)
+ {
+ return 4;
+ }
+ if (type == PROTOBUF_C_TYPE_SFIXED64 ||
+ type == PROTOBUF_C_TYPE_FIXED64 ||
+ type == PROTOBUF_C_TYPE_DOUBLE)
+ {
+ return 8;
+ }
+ return 1;
+}
+
+/**
+ * Packs the elements of a repeated field and returns the serialised field and
+ * its length.
+ *
+ * \param field
+ * Field descriptor.
+ * \param count
+ * Number of elements in the repeated field array.
+ * \param member
+ * Pointer to the elements for this repeated field.
+ * \param[out] out
+ * Serialised representation of the repeated field.
+ * \return
+ * Number of bytes serialised to `out`.
+ */
+static size_t
+repeated_field_pack(const ProtobufCFieldDescriptor *field,
+ size_t count, const void *member, uint8_t *out)
+{
+ void *array = *(void * const *) member;
+ unsigned i;
+
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
+ unsigned header_len;
+ unsigned len_start;
+ unsigned min_length;
+ unsigned payload_len;
+ unsigned length_size_min;
+ unsigned actual_length_size;
+ uint8_t *payload_at;
+
+ if (count == 0)
+ return 0;
+ header_len = tag_pack(field->id, out);
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ len_start = header_len;
+ min_length = get_type_min_size(field->type) * count;
+ length_size_min = uint32_size(min_length);
+ header_len += length_size_min;
+ payload_at = out + header_len;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ copy_to_little_endian_32(payload_at, array, count);
+ payload_at += count * 4;
+ break;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ copy_to_little_endian_64(payload_at, array, count);
+ payload_at += count * 8;
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32: {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += int32_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_SINT32: {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += sint32_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_SINT64: {
+ const int64_t *arr = (const int64_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += sint64_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_UINT32: {
+ const uint32_t *arr = (const uint32_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += uint32_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64: {
+ const uint64_t *arr = (const uint64_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += uint64_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_BOOL: {
+ const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array;
+ for (i = 0; i < count; i++)
+ payload_at += boolean_pack(arr[i], payload_at);
+ break;
+ }
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+
+ payload_len = payload_at - (out + header_len);
+ actual_length_size = uint32_size(payload_len);
+ if (length_size_min != actual_length_size) {
+ assert(actual_length_size == length_size_min + 1);
+ memmove(out + header_len + 1, out + header_len,
+ payload_len);
+ header_len++;
+ }
+ uint32_pack(payload_len, out + len_start);
+ return header_len + payload_len;
+ } else {
+ /* not "packed" cased */
+ /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
+ size_t rv = 0;
+ unsigned siz = sizeof_elt_in_repeated_array(field->type);
+
+ for (i = 0; i < count; i++) {
+ rv += required_field_pack(field, array, out + rv);
+ array = (char *)array + siz;
+ }
+ return rv;
+ }
+}
+
+static size_t
+unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out)
+{
+ size_t rv = tag_pack(field->tag, out);
+ out[0] |= field->wire_type;
+ memcpy(out + rv, field->data, field->len);
+ return rv + field->len;
+}
+
+/**@}*/
+
+size_t
+protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out)
+{
+ unsigned i;
+ size_t rv = 0;
+
+ ASSERT_IS_MESSAGE(message);
+ for (i = 0; i < message->descriptor->n_fields; i++) {
+ const ProtobufCFieldDescriptor *field =
+ message->descriptor->fields + i;
+ const void *member = ((const char *) message) + field->offset;
+
+ /*
+ * It doesn't hurt to compute qmember (a pointer to the
+ * quantifier field of the structure), but the pointer is only
+ * valid if the field is:
+ * - a repeated field, or
+ * - a field that is part of a oneof
+ * - an optional field that isn't a pointer type
+ * (Meaning: not a message or a string).
+ */
+ const void *qmember =
+ ((const char *) message) + field->quantifier_offset;
+
+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
+ rv += required_field_pack(field, member, out + rv);
+ } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
+ field->label == PROTOBUF_C_LABEL_NONE) &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
+ rv += oneof_field_pack(
+ field,
+ *(const uint32_t *) qmember,
+ member,
+ out + rv
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
+ rv += optional_field_pack(
+ field,
+ *(const protobuf_c_boolean *) qmember,
+ member,
+ out + rv
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_NONE) {
+ rv += unlabeled_field_pack(field, member, out + rv);
+ } else {
+ rv += repeated_field_pack(field, *(const size_t *) qmember,
+ member, out + rv);
+ }
+ }
+ for (i = 0; i < message->n_unknown_fields; i++)
+ rv += unknown_field_pack(&message->unknown_fields[i], out + rv);
+ return rv;
+}
+
+/**
+ * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation
+ *
+ * Routines mainly used by protobuf_c_message_pack_to_buffer().
+ *
+ * \ingroup internal
+ * @{
+ */
+
+/**
+ * Pack a required field to a virtual buffer.
+ *
+ * \param field
+ * Field descriptor.
+ * \param member
+ * The element to be packed.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes packed.
+ */
+static size_t
+required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ const void *member, ProtobufCBuffer *buffer)
+{
+ size_t rv;
+ uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
+
+ rv = tag_pack(field->id, scratch);
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += sint32_pack(*(const int32_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += int32_pack(*(const int32_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_UINT32:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += uint32_pack(*(const uint32_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_SINT64:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += sint64_pack(*(const int64_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += uint64_pack(*(const uint64_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
+ rv += fixed32_pack(*(const uint32_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
+ rv += fixed64_pack(*(const uint64_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_STRING: {
+ const char *str = *(char *const *) member;
+ size_t sublen = str ? strlen(str) : 0;
+
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ rv += uint32_pack(sublen, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ buffer->append(buffer, sublen, (const uint8_t *) str);
+ rv += sublen;
+ break;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member);
+ size_t sublen = bd->len;
+
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ rv += uint32_pack(sublen, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ buffer->append(buffer, sublen, bd->data);
+ rv += sublen;
+ break;
+ }
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ uint8_t simple_buffer_scratch[256];
+ size_t sublen;
+ const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
+ ProtobufCBufferSimple simple_buffer =
+ PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch);
+
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ if (msg == NULL)
+ sublen = 0;
+ else
+ sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base);
+ rv += uint32_pack(sublen, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ buffer->append(buffer, sublen, simple_buffer.data);
+ rv += sublen;
+ PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer);
+ break;
+ }
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+ return rv;
+}
+
+/**
+ * Pack a oneof field to a buffer. Only packs the field that is selected by the case enum.
+ *
+ * \param field
+ * Field descriptor.
+ * \param oneof_case
+ * Enum value that selects the field in the oneof.
+ * \param member
+ * The element to be packed.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes serialised to `buffer`.
+ */
+static size_t
+oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ uint32_t oneof_case,
+ const void *member, ProtobufCBuffer *buffer)
+{
+ if (oneof_case != field->id) {
+ return 0;
+ }
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void *const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ }
+ return required_field_pack_to_buffer(field, member, buffer);
+}
+
+/**
+ * Pack an optional field to a buffer.
+ *
+ * \param field
+ * Field descriptor.
+ * \param has
+ * Whether the field is set.
+ * \param member
+ * The element to be packed.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes serialised to `buffer`.
+ */
+static size_t
+optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ const protobuf_c_boolean has,
+ const void *member, ProtobufCBuffer *buffer)
+{
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void *const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ } else {
+ if (!has)
+ return 0;
+ }
+ return required_field_pack_to_buffer(field, member, buffer);
+}
+
+/**
+ * Pack an unlabeled field to a buffer.
+ *
+ * \param field
+ * Field descriptor.
+ * \param member
+ * The element to be packed.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes serialised to `buffer`.
+ */
+static size_t
+unlabeled_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ const void *member, ProtobufCBuffer *buffer)
+{
+ if (field_is_zeroish(field, member))
+ return 0;
+ return required_field_pack_to_buffer(field, member, buffer);
+}
+
+/**
+ * Get the packed size of an array of same field type.
+ *
+ * \param field
+ * Field descriptor.
+ * \param count
+ * Number of elements of this type.
+ * \param array
+ * The elements to get the size of.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+get_packed_payload_length(const ProtobufCFieldDescriptor *field,
+ unsigned count, const void *array)
+{
+ unsigned rv = 0;
+ unsigned i;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ return count * 4;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ return count * 8;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32: {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ rv += int32_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_SINT32: {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ rv += sint32_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_UINT32: {
+ const uint32_t *arr = (const uint32_t *) array;
+ for (i = 0; i < count; i++)
+ rv += uint32_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_SINT64: {
+ const int64_t *arr = (const int64_t *) array;
+ for (i = 0; i < count; i++)
+ rv += sint64_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64: {
+ const uint64_t *arr = (const uint64_t *) array;
+ for (i = 0; i < count; i++)
+ rv += uint64_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_BOOL:
+ return count;
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+ return rv;
+}
+
+/**
+ * Pack an array of same field type to a virtual buffer.
+ *
+ * \param field
+ * Field descriptor.
+ * \param count
+ * Number of elements of this type.
+ * \param array
+ * The elements to get the size of.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes packed.
+ */
+static size_t
+pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field,
+ unsigned count, const void *array,
+ ProtobufCBuffer *buffer)
+{
+ uint8_t scratch[16];
+ size_t rv = 0;
+ unsigned i;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+#if !defined(WORDS_BIGENDIAN)
+ rv = count * 4;
+ goto no_packing_needed;
+#else
+ for (i = 0; i < count; i++) {
+ unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+#endif
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+#if !defined(WORDS_BIGENDIAN)
+ rv = count * 8;
+ goto no_packing_needed;
+#else
+ for (i = 0; i < count; i++) {
+ unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+#endif
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ for (i = 0; i < count; i++) {
+ unsigned len = int32_pack(((int32_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_SINT32:
+ for (i = 0; i < count; i++) {
+ unsigned len = sint32_pack(((int32_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_UINT32:
+ for (i = 0; i < count; i++) {
+ unsigned len = uint32_pack(((uint32_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_SINT64:
+ for (i = 0; i < count; i++) {
+ unsigned len = sint64_pack(((int64_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ for (i = 0; i < count; i++) {
+ unsigned len = uint64_pack(((uint64_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ for (i = 0; i < count; i++) {
+ unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ return count;
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+ return rv;
+
+#if !defined(WORDS_BIGENDIAN)
+no_packing_needed:
+ buffer->append(buffer, rv, array);
+ return rv;
+#endif
+}
+
+static size_t
+repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ unsigned count, const void *member,
+ ProtobufCBuffer *buffer)
+{
+ char *array = *(char * const *) member;
+
+ if (count == 0)
+ return 0;
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
+ uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
+ size_t rv = tag_pack(field->id, scratch);
+ size_t payload_len = get_packed_payload_length(field, count, array);
+ size_t tmp;
+
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ rv += uint32_pack(payload_len, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ tmp = pack_buffer_packed_payload(field, count, array, buffer);
+ assert(tmp == payload_len);
+ return rv + payload_len;
+ } else {
+ size_t siz;
+ unsigned i;
+ /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
+ unsigned rv = 0;
+
+ siz = sizeof_elt_in_repeated_array(field->type);
+ for (i = 0; i < count; i++) {
+ rv += required_field_pack_to_buffer(field, array, buffer);
+ array += siz;
+ }
+ return rv;
+ }
+}
+
+static size_t
+unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field,
+ ProtobufCBuffer *buffer)
+{
+ uint8_t header[MAX_UINT64_ENCODED_SIZE];
+ size_t rv = tag_pack(field->tag, header);
+
+ header[0] |= field->wire_type;
+ buffer->append(buffer, rv, header);
+ buffer->append(buffer, field->len, field->data);
+ return rv + field->len;
+}
+
+/**@}*/
+
+size_t
+protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ unsigned i;
+ size_t rv = 0;
+
+ ASSERT_IS_MESSAGE(message);
+ for (i = 0; i < message->descriptor->n_fields; i++) {
+ const ProtobufCFieldDescriptor *field =
+ message->descriptor->fields + i;
+ const void *member =
+ ((const char *) message) + field->offset;
+ const void *qmember =
+ ((const char *) message) + field->quantifier_offset;
+
+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
+ rv += required_field_pack_to_buffer(field, member, buffer);
+ } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
+ field->label == PROTOBUF_C_LABEL_NONE) &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
+ rv += oneof_field_pack_to_buffer(
+ field,
+ *(const uint32_t *) qmember,
+ member,
+ buffer
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
+ rv += optional_field_pack_to_buffer(
+ field,
+ *(const protobuf_c_boolean *) qmember,
+ member,
+ buffer
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_NONE) {
+ rv += unlabeled_field_pack_to_buffer(
+ field,
+ member,
+ buffer
+ );
+ } else {
+ rv += repeated_field_pack_to_buffer(
+ field,
+ *(const size_t *) qmember,
+ member,
+ buffer
+ );
+ }
+ }
+ for (i = 0; i < message->n_unknown_fields; i++)
+ rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer);
+
+ return rv;
+}
+
+/**
+ * \defgroup unpack unpacking implementation
+ *
+ * Routines mainly used by the unpacking functions.
+ *
+ * \ingroup internal
+ * @{
+ */
+
+static inline int
+int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value)
+{
+ unsigned n;
+ unsigned start;
+
+ if (n_ranges == 0)
+ return -1;
+ start = 0;
+ n = n_ranges;
+ while (n > 1) {
+ unsigned mid = start + n / 2;
+
+ if (value < ranges[mid].start_value) {
+ n = mid - start;
+ } else if (value >= ranges[mid].start_value +
+ (int) (ranges[mid + 1].orig_index -
+ ranges[mid].orig_index))
+ {
+ unsigned new_start = mid + 1;
+ n = start + n - new_start;
+ start = new_start;
+ } else
+ return (value - ranges[mid].start_value) +
+ ranges[mid].orig_index;
+ }
+ if (n > 0) {
+ unsigned start_orig_index = ranges[start].orig_index;
+ unsigned range_size =
+ ranges[start + 1].orig_index - start_orig_index;
+
+ if (ranges[start].start_value <= value &&
+ value < (int) (ranges[start].start_value + range_size))
+ {
+ return (value - ranges[start].start_value) +
+ start_orig_index;
+ }
+ }
+ return -1;
+}
+
+static size_t
+parse_tag_and_wiretype(size_t len,
+ const uint8_t *data,
+ uint32_t *tag_out,
+ ProtobufCWireType *wiretype_out)
+{
+ unsigned max_rv = len > 5 ? 5 : len;
+ uint32_t tag = (data[0] & 0x7f) >> 3;
+ unsigned shift = 4;
+ unsigned rv;
+
+ *wiretype_out = data[0] & 7;
+ if ((data[0] & 0x80) == 0) {
+ *tag_out = tag;
+ return 1;
+ }
+ for (rv = 1; rv < max_rv; rv++) {
+ if (data[rv] & 0x80) {
+ tag |= (data[rv] & 0x7f) << shift;
+ shift += 7;
+ } else {
+ tag |= data[rv] << shift;
+ *tag_out = tag;
+ return rv + 1;
+ }
+ }
+ return 0; /* error: bad header */
+}
+
+/* sizeof(ScannedMember) must be <= (1UL<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
+#define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
+typedef struct _ScannedMember ScannedMember;
+/** Field as it's being read. */
+struct _ScannedMember {
+ uint32_t tag; /**< Field tag. */
+ uint8_t wire_type; /**< Field type. */
+ uint8_t length_prefix_len; /**< Prefix length. */
+ const ProtobufCFieldDescriptor *field; /**< Field descriptor. */
+ size_t len; /**< Field length. */
+ const uint8_t *data; /**< Pointer to field data. */
+};
+
+static inline uint32_t
+scan_length_prefixed_data(size_t len, const uint8_t *data,
+ size_t *prefix_len_out)
+{
+ unsigned hdr_max = len < 5 ? len : 5;
+ unsigned hdr_len;
+ uint32_t val = 0;
+ unsigned i;
+ unsigned shift = 0;
+
+ for (i = 0; i < hdr_max; i++) {
+ val |= (data[i] & 0x7f) << shift;
+ shift += 7;
+ if ((data[i] & 0x80) == 0)
+ break;
+ }
+ if (i == hdr_max) {
+ PROTOBUF_C_UNPACK_ERROR("error parsing length for length-prefixed data");
+ return 0;
+ }
+ hdr_len = i + 1;
+ *prefix_len_out = hdr_len;
+ if (hdr_len + val > len) {
+ PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %u", val);
+ return 0;
+ }
+ return hdr_len + val;
+}
+
+static size_t
+max_b128_numbers(size_t len, const uint8_t *data)
+{
+ size_t rv = 0;
+ while (len--)
+ if ((*data++ & 0x80) == 0)
+ ++rv;
+ return rv;
+}
+
+/**@}*/
+
+/**
+ * Merge earlier message into a latter message.
+ *
+ * For numeric types and strings, if the same value appears multiple
+ * times, the parser accepts the last value it sees. For embedded
+ * message fields, the parser merges multiple instances of the same
+ * field. That is, all singular scalar fields in the latter instance
+ * replace those in the former, singular embedded messages are merged,
+ * and repeated fields are concatenated.
+ *
+ * The earlier message should be freed after calling this function, as
+ * some of its fields may have been reused and changed to their default
+ * values during the merge.
+ */
+static protobuf_c_boolean
+merge_messages(ProtobufCMessage *earlier_msg,
+ ProtobufCMessage *latter_msg,
+ ProtobufCAllocator *allocator)
+{
+ unsigned i;
+ const ProtobufCFieldDescriptor *fields =
+ latter_msg->descriptor->fields;
+ for (i = 0; i < latter_msg->descriptor->n_fields; i++) {
+ if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t *n_earlier =
+ STRUCT_MEMBER_PTR(size_t, earlier_msg,
+ fields[i].quantifier_offset);
+ uint8_t **p_earlier =
+ STRUCT_MEMBER_PTR(uint8_t *, earlier_msg,
+ fields[i].offset);
+ size_t *n_latter =
+ STRUCT_MEMBER_PTR(size_t, latter_msg,
+ fields[i].quantifier_offset);
+ uint8_t **p_latter =
+ STRUCT_MEMBER_PTR(uint8_t *, latter_msg,
+ fields[i].offset);
+
+ if (*n_earlier > 0) {
+ if (*n_latter > 0) {
+ /* Concatenate the repeated field */
+ size_t el_size =
+ sizeof_elt_in_repeated_array(fields[i].type);
+ uint8_t *new_field;
+
+ new_field = do_alloc(allocator,
+ (*n_earlier + *n_latter) * el_size);
+ if (!new_field)
+ return FALSE;
+
+ memcpy(new_field, *p_earlier,
+ *n_earlier * el_size);
+ memcpy(new_field +
+ *n_earlier * el_size,
+ *p_latter,
+ *n_latter * el_size);
+
+ do_free(allocator, *p_latter);
+ do_free(allocator, *p_earlier);
+ *p_latter = new_field;
+ *n_latter = *n_earlier + *n_latter;
+ } else {
+ /* Zero copy the repeated field from the earlier message */
+ *n_latter = *n_earlier;
+ *p_latter = *p_earlier;
+ }
+ /* Make sure the field does not get double freed */
+ *n_earlier = 0;
+ *p_earlier = 0;
+ }
+ } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL ||
+ fields[i].label == PROTOBUF_C_LABEL_NONE) {
+ const ProtobufCFieldDescriptor *field;
+ uint32_t *earlier_case_p = STRUCT_MEMBER_PTR(uint32_t,
+ earlier_msg,
+ fields[i].
+ quantifier_offset);
+ uint32_t *latter_case_p = STRUCT_MEMBER_PTR(uint32_t,
+ latter_msg,
+ fields[i].
+ quantifier_offset);
+ protobuf_c_boolean need_to_merge = FALSE;
+ void *earlier_elem;
+ void *latter_elem;
+ const void *def_val;
+
+ if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
+ if (*latter_case_p == 0) {
+ /* lookup correct oneof field */
+ int field_index =
+ int_range_lookup(
+ latter_msg->descriptor
+ ->n_field_ranges,
+ latter_msg->descriptor
+ ->field_ranges,
+ *earlier_case_p);
+ field = latter_msg->descriptor->fields +
+ field_index;
+ } else {
+ /* Oneof is present in the latter message, move on */
+ continue;
+ }
+ } else {
+ field = &fields[i];
+ }
+
+ earlier_elem = STRUCT_MEMBER_P(earlier_msg, field->offset);
+ latter_elem = STRUCT_MEMBER_P(latter_msg, field->offset);
+ def_val = field->default_value;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ ProtobufCMessage *em = *(ProtobufCMessage **) earlier_elem;
+ ProtobufCMessage *lm = *(ProtobufCMessage **) latter_elem;
+ if (em != NULL) {
+ if (lm != NULL) {
+ if (!merge_messages(em, lm, allocator))
+ return FALSE;
+ /* Already merged */
+ need_to_merge = FALSE;
+ } else {
+ /* Zero copy the message */
+ need_to_merge = TRUE;
+ }
+ }
+ break;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ uint8_t *e_data =
+ ((ProtobufCBinaryData *) earlier_elem)->data;
+ uint8_t *l_data =
+ ((ProtobufCBinaryData *) latter_elem)->data;
+ const ProtobufCBinaryData *d_bd =
+ (ProtobufCBinaryData *) def_val;
+
+ need_to_merge =
+ (e_data != NULL &&
+ (d_bd == NULL ||
+ e_data != d_bd->data)) &&
+ (l_data == NULL ||
+ (d_bd != NULL &&
+ l_data == d_bd->data));
+ break;
+ }
+ case PROTOBUF_C_TYPE_STRING: {
+ char *e_str = *(char **) earlier_elem;
+ char *l_str = *(char **) latter_elem;
+ const char *d_str = def_val;
+
+ need_to_merge = e_str != d_str && l_str == d_str;
+ break;
+ }
+ default: {
+ /* Could be has field or case enum, the logic is
+ * equivalent, since 0 (FALSE) means not set for
+ * oneof */
+ need_to_merge = (*earlier_case_p != 0) &&
+ (*latter_case_p == 0);
+ break;
+ }
+ }
+
+ if (need_to_merge) {
+ size_t el_size =
+ sizeof_elt_in_repeated_array(field->type);
+ memcpy(latter_elem, earlier_elem, el_size);
+ /*
+ * Reset the element from the old message to 0
+ * to make sure earlier message deallocation
+ * doesn't corrupt zero-copied data in the new
+ * message, earlier message will be freed after
+ * this function is called anyway
+ */
+ memset(earlier_elem, 0, el_size);
+
+ if (field->quantifier_offset != 0) {
+ /* Set the has field or the case enum,
+ * if applicable */
+ *latter_case_p = *earlier_case_p;
+ *earlier_case_p = 0;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Count packed elements.
+ *
+ * Given a raw slab of packed-repeated values, determine the number of
+ * elements. This function detects certain kinds of errors but not
+ * others; the remaining error checking is done by
+ * parse_packed_repeated_member().
+ */
+static protobuf_c_boolean
+count_packed_elements(ProtobufCType type,
+ size_t len, const uint8_t *data, size_t *count_out)
+{
+ switch (type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ if (len % 4 != 0) {
+ PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types");
+ return FALSE;
+ }
+ *count_out = len / 4;
+ return TRUE;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ if (len % 8 != 0) {
+ PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types");
+ return FALSE;
+ }
+ *count_out = len / 8;
+ return TRUE;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ case PROTOBUF_C_TYPE_SINT32:
+ case PROTOBUF_C_TYPE_UINT32:
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_SINT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ *count_out = max_b128_numbers(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_BOOL:
+ *count_out = len;
+ return TRUE;
+ case PROTOBUF_C_TYPE_STRING:
+ case PROTOBUF_C_TYPE_BYTES:
+ case PROTOBUF_C_TYPE_MESSAGE:
+ default:
+ PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type);
+ return FALSE;
+ }
+}
+
+static inline uint32_t
+parse_uint32(unsigned len, const uint8_t *data)
+{
+ uint32_t rv = data[0] & 0x7f;
+ if (len > 1) {
+ rv |= ((uint32_t) (data[1] & 0x7f) << 7);
+ if (len > 2) {
+ rv |= ((uint32_t) (data[2] & 0x7f) << 14);
+ if (len > 3) {
+ rv |= ((uint32_t) (data[3] & 0x7f) << 21);
+ if (len > 4)
+ rv |= ((uint32_t) (data[4]) << 28);
+ }
+ }
+ }
+ return rv;
+}
+
+static inline uint32_t
+parse_int32(unsigned len, const uint8_t *data)
+{
+ return parse_uint32(len, data);
+}
+
+static inline int32_t
+unzigzag32(uint32_t v)
+{
+ if (v & 1)
+ return -(v >> 1) - 1;
+ else
+ return v >> 1;
+}
+
+static inline uint32_t
+parse_fixed_uint32(const uint8_t *data)
+{
+#if !defined(WORDS_BIGENDIAN)
+ uint32_t t;
+ memcpy(&t, data, 4);
+ return t;
+#else
+ return data[0] |
+ ((uint32_t) (data[1]) << 8) |
+ ((uint32_t) (data[2]) << 16) |
+ ((uint32_t) (data[3]) << 24);
+#endif
+}
+
+static uint64_t
+parse_uint64(unsigned len, const uint8_t *data)
+{
+ unsigned shift, i;
+ uint64_t rv;
+
+ if (len < 5)
+ return parse_uint32(len, data);
+ rv = ((uint64_t) (data[0] & 0x7f)) |
+ ((uint64_t) (data[1] & 0x7f) << 7) |
+ ((uint64_t) (data[2] & 0x7f) << 14) |
+ ((uint64_t) (data[3] & 0x7f) << 21);
+ shift = 28;
+ for (i = 4; i < len; i++) {
+ rv |= (((uint64_t) (data[i] & 0x7f)) << shift);
+ shift += 7;
+ }
+ return rv;
+}
+
+static inline int64_t
+unzigzag64(uint64_t v)
+{
+ if (v & 1)
+ return -(v >> 1) - 1;
+ else
+ return v >> 1;
+}
+
+static inline uint64_t
+parse_fixed_uint64(const uint8_t *data)
+{
+#if !defined(WORDS_BIGENDIAN)
+ uint64_t t;
+ memcpy(&t, data, 8);
+ return t;
+#else
+ return (uint64_t) parse_fixed_uint32(data) |
+ (((uint64_t) parse_fixed_uint32(data + 4)) << 32);
+#endif
+}
+
+static protobuf_c_boolean
+parse_boolean(unsigned len, const uint8_t *data)
+{
+ unsigned i;
+ for (i = 0; i < len; i++)
+ if (data[i] & 0x7f)
+ return TRUE;
+ return FALSE;
+}
+
+static protobuf_c_boolean
+parse_required_member(ScannedMember *scanned_member,
+ void *member,
+ ProtobufCAllocator *allocator,
+ protobuf_c_boolean maybe_clear)
+{
+ unsigned len = scanned_member->len;
+ const uint8_t *data = scanned_member->data;
+ ProtobufCWireType wire_type = scanned_member->wire_type;
+
+ switch (scanned_member->field->type) {
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(int32_t *) member = parse_int32(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_UINT32:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(uint32_t *) member = parse_uint32(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_SINT32:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(int32_t *) member = unzigzag32(parse_uint32(len, data));
+ return TRUE;
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
+ return FALSE;
+ *(uint32_t *) member = parse_fixed_uint32(data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(uint64_t *) member = parse_uint64(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_SINT64:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(int64_t *) member = unzigzag64(parse_uint64(len, data));
+ return TRUE;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
+ return FALSE;
+ *(uint64_t *) member = parse_fixed_uint64(data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_BOOL:
+ *(protobuf_c_boolean *) member = parse_boolean(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_STRING: {
+ char **pstr = member;
+ unsigned pref_len = scanned_member->length_prefix_len;
+
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
+ return FALSE;
+
+ if (maybe_clear && *pstr != NULL) {
+ const char *def = scanned_member->field->default_value;
+ if (*pstr != NULL && *pstr != def)
+ do_free(allocator, *pstr);
+ }
+ *pstr = do_alloc(allocator, len - pref_len + 1);
+ if (*pstr == NULL)
+ return FALSE;
+ memcpy(*pstr, data + pref_len, len - pref_len);
+ (*pstr)[len - pref_len] = 0;
+ return TRUE;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ ProtobufCBinaryData *bd = member;
+ const ProtobufCBinaryData *def_bd;
+ unsigned pref_len = scanned_member->length_prefix_len;
+
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
+ return FALSE;
+
+ def_bd = scanned_member->field->default_value;
+ if (maybe_clear &&
+ bd->data != NULL &&
+ (def_bd == NULL || bd->data != def_bd->data))
+ {
+ do_free(allocator, bd->data);
+ }
+ if (len - pref_len > 0) {
+ bd->data = do_alloc(allocator, len - pref_len);
+ if (bd->data == NULL)
+ return FALSE;
+ memcpy(bd->data, data + pref_len, len - pref_len);
+ } else {
+ bd->data = NULL;
+ }
+ bd->len = len - pref_len;
+ return TRUE;
+ }
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ ProtobufCMessage **pmessage = member;
+ ProtobufCMessage *subm;
+ const ProtobufCMessage *def_mess;
+ protobuf_c_boolean merge_successful = TRUE;
+ unsigned pref_len = scanned_member->length_prefix_len;
+
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
+ return FALSE;
+
+ def_mess = scanned_member->field->default_value;
+ subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
+ allocator,
+ len - pref_len,
+ data + pref_len);
+
+ if (maybe_clear &&
+ *pmessage != NULL &&
+ *pmessage != def_mess)
+ {
+ if (subm != NULL)
+ merge_successful = merge_messages(*pmessage, subm, allocator);
+ /* Delete the previous message */
+ protobuf_c_message_free_unpacked(*pmessage, allocator);
+ }
+ *pmessage = subm;
+ if (subm == NULL || !merge_successful)
+ return FALSE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static protobuf_c_boolean
+parse_oneof_member (ScannedMember *scanned_member,
+ void *member,
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ uint32_t *oneof_case = STRUCT_MEMBER_PTR(uint32_t, message,
+ scanned_member->field->quantifier_offset);
+
+ /* If we have already parsed a member of this oneof, free it. */
+ if (*oneof_case != 0) {
+ /* lookup field */
+ int field_index =
+ int_range_lookup(message->descriptor->n_field_ranges,
+ message->descriptor->field_ranges,
+ *oneof_case);
+ const ProtobufCFieldDescriptor *old_field =
+ message->descriptor->fields + field_index;
+ size_t el_size = sizeof_elt_in_repeated_array(old_field->type);
+
+ switch (old_field->type) {
+ case PROTOBUF_C_TYPE_STRING: {
+ char **pstr = member;
+ const char *def = old_field->default_value;
+ if (*pstr != NULL && *pstr != def)
+ do_free(allocator, *pstr);
+ break;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ ProtobufCBinaryData *bd = member;
+ const ProtobufCBinaryData *def_bd = old_field->default_value;
+ if (bd->data != NULL &&
+ (def_bd == NULL || bd->data != def_bd->data))
+ {
+ do_free(allocator, bd->data);
+ }
+ break;
+ }
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ ProtobufCMessage **pmessage = member;
+ const ProtobufCMessage *def_mess = old_field->default_value;
+ if (*pmessage != NULL && *pmessage != def_mess)
+ protobuf_c_message_free_unpacked(*pmessage, allocator);
+ break;
+ }
+ default:
+ break;
+ }
+
+ memset (member, 0, el_size);
+ }
+ if (!parse_required_member (scanned_member, member, allocator, TRUE))
+ return FALSE;
+
+ *oneof_case = scanned_member->tag;
+ return TRUE;
+}
+
+
+static protobuf_c_boolean
+parse_optional_member(ScannedMember *scanned_member,
+ void *member,
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if (!parse_required_member(scanned_member, member, allocator, TRUE))
+ return FALSE;
+ if (scanned_member->field->quantifier_offset != 0)
+ STRUCT_MEMBER(protobuf_c_boolean,
+ message,
+ scanned_member->field->quantifier_offset) = TRUE;
+ return TRUE;
+}
+
+static protobuf_c_boolean
+parse_repeated_member(ScannedMember *scanned_member,
+ void *member,
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ const ProtobufCFieldDescriptor *field = scanned_member->field;
+ size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
+ size_t siz = sizeof_elt_in_repeated_array(field->type);
+ char *array = *(char **) member;
+
+ if (!parse_required_member(scanned_member, array + siz * (*p_n),
+ allocator, FALSE))
+ {
+ return FALSE;
+ }
+ *p_n += 1;
+ return TRUE;
+}
+
+static unsigned
+scan_varint(unsigned len, const uint8_t *data)
+{
+ unsigned i;
+ if (len > 10)
+ len = 10;
+ for (i = 0; i < len; i++)
+ if ((data[i] & 0x80) == 0)
+ break;
+ if (i == len)
+ return 0;
+ return i + 1;
+}
+
+static protobuf_c_boolean
+parse_packed_repeated_member(ScannedMember *scanned_member,
+ void *member,
+ ProtobufCMessage *message)
+{
+ const ProtobufCFieldDescriptor *field = scanned_member->field;
+ size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
+ size_t siz = sizeof_elt_in_repeated_array(field->type);
+ void *array = *(char **) member + siz * (*p_n);
+ const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
+ size_t rem = scanned_member->len - scanned_member->length_prefix_len;
+ size_t count = 0;
+ unsigned i;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ count = (scanned_member->len - scanned_member->length_prefix_len) / 4;
+#if !defined(WORDS_BIGENDIAN)
+ goto no_unpacking_needed;
+#else
+ for (i = 0; i < count; i++) {
+ ((uint32_t *) array)[i] = parse_fixed_uint32(at);
+ at += 4;
+ }
+ break;
+#endif
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ count = (scanned_member->len - scanned_member->length_prefix_len) / 8;
+#if !defined(WORDS_BIGENDIAN)
+ goto no_unpacking_needed;
+#else
+ for (i = 0; i < count; i++) {
+ ((uint64_t *) array)[i] = parse_fixed_uint64(at);
+ at += 8;
+ }
+ break;
+#endif
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value");
+ return FALSE;
+ }
+ ((int32_t *) array)[count++] = parse_int32(s, at);
+ at += s;
+ rem -= s;
+ }
+ break;
+ case PROTOBUF_C_TYPE_SINT32:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value");
+ return FALSE;
+ }
+ ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at));
+ at += s;
+ rem -= s;
+ }
+ break;
+ case PROTOBUF_C_TYPE_UINT32:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value");
+ return FALSE;
+ }
+ ((uint32_t *) array)[count++] = parse_uint32(s, at);
+ at += s;
+ rem -= s;
+ }
+ break;
+
+ case PROTOBUF_C_TYPE_SINT64:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value");
+ return FALSE;
+ }
+ ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at));
+ at += s;
+ rem -= s;
+ }
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value");
+ return FALSE;
+ }
+ ((int64_t *) array)[count++] = parse_uint64(s, at);
+ at += s;
+ rem -= s;
+ }
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ count = rem;
+ for (i = 0; i < count; i++) {
+ if (at[i] > 1) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
+ return FALSE;
+ }
+ ((protobuf_c_boolean *) array)[i] = at[i];
+ }
+ break;
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+ *p_n += count;
+ return TRUE;
+
+#if !defined(WORDS_BIGENDIAN)
+no_unpacking_needed:
+ memcpy(array, at, count * siz);
+ *p_n += count;
+ return TRUE;
+#endif
+}
+
+static protobuf_c_boolean
+is_packable_type(ProtobufCType type)
+{
+ return
+ type != PROTOBUF_C_TYPE_STRING &&
+ type != PROTOBUF_C_TYPE_BYTES &&
+ type != PROTOBUF_C_TYPE_MESSAGE;
+}
+
+static protobuf_c_boolean
+parse_member(ScannedMember *scanned_member,
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ const ProtobufCFieldDescriptor *field = scanned_member->field;
+ void *member;
+
+ if (field == NULL) {
+ ProtobufCMessageUnknownField *ufield =
+ message->unknown_fields +
+ (message->n_unknown_fields++);
+ ufield->tag = scanned_member->tag;
+ ufield->wire_type = scanned_member->wire_type;
+ ufield->len = scanned_member->len;
+ ufield->data = do_alloc(allocator, scanned_member->len);
+ if (ufield->data == NULL)
+ return FALSE;
+ memcpy(ufield->data, scanned_member->data, ufield->len);
+ return TRUE;
+ }
+ member = (char *) message + field->offset;
+ switch (field->label) {
+ case PROTOBUF_C_LABEL_REQUIRED:
+ return parse_required_member(scanned_member, member,
+ allocator, TRUE);
+ case PROTOBUF_C_LABEL_OPTIONAL:
+ case PROTOBUF_C_LABEL_NONE:
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) {
+ return parse_oneof_member(scanned_member, member,
+ message, allocator);
+ } else {
+ return parse_optional_member(scanned_member, member,
+ message, allocator);
+ }
+ case PROTOBUF_C_LABEL_REPEATED:
+ if (scanned_member->wire_type ==
+ PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
+ is_packable_type(field->type)))
+ {
+ return parse_packed_repeated_member(scanned_member,
+ member, message);
+ } else {
+ return parse_repeated_member(scanned_member,
+ member, message,
+ allocator);
+ }
+ }
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ return 0;
+}
+
+/**
+ * Initialise messages generated by old code.
+ *
+ * This function is used if desc->message_init == NULL (which occurs
+ * for old code, and which would be useful to support allocating
+ * descriptors dynamically).
+ */
+static void
+message_init_generic(const ProtobufCMessageDescriptor *desc,
+ ProtobufCMessage *message)
+{
+ unsigned i;
+
+ memset(message, 0, desc->sizeof_message);
+ message->descriptor = desc;
+ for (i = 0; i < desc->n_fields; i++) {
+ if (desc->fields[i].default_value != NULL &&
+ desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
+ {
+ void *field =
+ STRUCT_MEMBER_P(message, desc->fields[i].offset);
+ const void *dv = desc->fields[i].default_value;
+
+ switch (desc->fields[i].type) {
+ case PROTOBUF_C_TYPE_INT32:
+ case PROTOBUF_C_TYPE_SINT32:
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_UINT32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ case PROTOBUF_C_TYPE_ENUM:
+ memcpy(field, dv, 4);
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_SINT64:
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_UINT64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ memcpy(field, dv, 8);
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ memcpy(field, dv, sizeof(protobuf_c_boolean));
+ break;
+ case PROTOBUF_C_TYPE_BYTES:
+ memcpy(field, dv, sizeof(ProtobufCBinaryData));
+ break;
+
+ case PROTOBUF_C_TYPE_STRING:
+ case PROTOBUF_C_TYPE_MESSAGE:
+ /*
+ * The next line essentially implements a cast
+ * from const, which is totally unavoidable.
+ */
+ *(const void **) field = dv;
+ break;
+ }
+ }
+ }
+}
+
+/**@}*/
+
+/*
+ * ScannedMember slabs (an unpacking implementation detail). Before doing real
+ * unpacking, we first scan through the elements to see how many there are (for
+ * repeated fields), and which field to use (for non-repeated fields given
+ * twice).
+ *
+ * In order to avoid allocations for small messages, we keep a stack-allocated
+ * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we
+ * fill that up, we allocate each slab twice as large as the previous one.
+ */
+#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4
+
+/*
+ * The number of slabs, including the stack-allocated ones; choose the number so
+ * that we would overflow if we needed a slab larger than provided.
+ */
+#define MAX_SCANNED_MEMBER_SLAB \
+ (sizeof(unsigned int)*8 - 1 \
+ - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \
+ - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
+
+#define REQUIRED_FIELD_BITMAP_SET(index) \
+ (required_fields_bitmap[(index)/8] |= (1UL<<((index)%8)))
+
+#define REQUIRED_FIELD_BITMAP_IS_SET(index) \
+ (required_fields_bitmap[(index)/8] & (1UL<<((index)%8)))
+
+ProtobufCMessage *
+protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
+ ProtobufCAllocator *allocator,
+ size_t len, const uint8_t *data)
+{
+ ProtobufCMessage *rv;
+ size_t rem = len;
+ const uint8_t *at = data;
+ const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
+ ScannedMember first_member_slab[1UL <<
+ FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
+
+ /*
+ * scanned_member_slabs[i] is an array of arrays of ScannedMember.
+ * The first slab (scanned_member_slabs[0] is just a pointer to
+ * first_member_slab), above. All subsequent slabs will be allocated
+ * using the allocator.
+ */
+ ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1];
+ unsigned which_slab = 0; /* the slab we are currently populating */
+ unsigned in_slab_index = 0; /* number of members in the slab */
+ size_t n_unknown = 0;
+ unsigned f;
+ unsigned j;
+ unsigned i_slab;
+ unsigned last_field_index = 0;
+ unsigned required_fields_bitmap_len;
+ unsigned char required_fields_bitmap_stack[16];
+ unsigned char *required_fields_bitmap = required_fields_bitmap_stack;
+ protobuf_c_boolean required_fields_bitmap_alloced = FALSE;
+
+ ASSERT_IS_MESSAGE_DESCRIPTOR(desc);
+
+ if (allocator == NULL)
+ allocator = &protobuf_c__allocator;
+
+ rv = do_alloc(allocator, desc->sizeof_message);
+ if (!rv)
+ return (NULL);
+ scanned_member_slabs[0] = first_member_slab;
+
+ required_fields_bitmap_len = (desc->n_fields + 7) / 8;
+ if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) {
+ required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len);
+ if (!required_fields_bitmap) {
+ do_free(allocator, rv);
+ return (NULL);
+ }
+ required_fields_bitmap_alloced = TRUE;
+ }
+ memset(required_fields_bitmap, 0, required_fields_bitmap_len);
+
+ /*
+ * Generated code always defines "message_init". However, we provide a
+ * fallback for (1) users of old protobuf-c generated-code that do not
+ * provide the function, and (2) descriptors constructed from some other
+ * source (most likely, direct construction from the .proto file).
+ */
+ if (desc->message_init != NULL)
+ protobuf_c_message_init(desc, rv);
+ else
+ message_init_generic(desc, rv);
+
+ while (rem > 0) {
+ uint32_t tag;
+ ProtobufCWireType wire_type;
+ size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type);
+ const ProtobufCFieldDescriptor *field;
+ ScannedMember tmp;
+
+ if (used == 0) {
+ PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u",
+ (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+ /*
+ * \todo Consider optimizing for field[1].id == tag, if field[1]
+ * exists!
+ */
+ if (last_field == NULL || last_field->id != tag) {
+ /* lookup field */
+ int field_index =
+ int_range_lookup(desc->n_field_ranges,
+ desc->field_ranges,
+ tag);
+ if (field_index < 0) {
+ field = NULL;
+ n_unknown++;
+ } else {
+ field = desc->fields + field_index;
+ last_field = field;
+ last_field_index = field_index;
+ }
+ } else {
+ field = last_field;
+ }
+
+ if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED)
+ REQUIRED_FIELD_BITMAP_SET(last_field_index);
+
+ at += used;
+ rem -= used;
+ tmp.tag = tag;
+ tmp.wire_type = wire_type;
+ tmp.field = field;
+ tmp.data = at;
+ tmp.length_prefix_len = 0;
+
+ switch (wire_type) {
+ case PROTOBUF_C_WIRE_TYPE_VARINT: {
+ unsigned max_len = rem < 10 ? rem : 10;
+ unsigned i;
+
+ for (i = 0; i < max_len; i++)
+ if ((at[i] & 0x80) == 0)
+ break;
+ if (i == max_len) {
+ PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u",
+ (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+ tmp.len = i + 1;
+ break;
+ }
+ case PROTOBUF_C_WIRE_TYPE_64BIT:
+ if (rem < 8) {
+ PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u",
+ (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+ tmp.len = 8;
+ break;
+ case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: {
+ size_t pref_len;
+
+ tmp.len = scan_length_prefixed_data(rem, at, &pref_len);
+ if (tmp.len == 0) {
+ /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
+ goto error_cleanup_during_scan;
+ }
+ tmp.length_prefix_len = pref_len;
+ break;
+ }
+ case PROTOBUF_C_WIRE_TYPE_32BIT:
+ if (rem < 4) {
+ PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u",
+ (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+ tmp.len = 4;
+ break;
+ default:
+ PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u",
+ wire_type, (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+
+ if (in_slab_index == (1UL <<
+ (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
+ {
+ size_t size;
+
+ in_slab_index = 0;
+ if (which_slab == MAX_SCANNED_MEMBER_SLAB) {
+ PROTOBUF_C_UNPACK_ERROR("too many fields");
+ goto error_cleanup_during_scan;
+ }
+ which_slab++;
+ size = sizeof(ScannedMember)
+ << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
+ scanned_member_slabs[which_slab] = do_alloc(allocator, size);
+ if (scanned_member_slabs[which_slab] == NULL)
+ goto error_cleanup_during_scan;
+ }
+ scanned_member_slabs[which_slab][in_slab_index++] = tmp;
+
+ if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t *n = STRUCT_MEMBER_PTR(size_t, rv,
+ field->quantifier_offset);
+ if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
+ is_packable_type(field->type)))
+ {
+ size_t count;
+ if (!count_packed_elements(field->type,
+ tmp.len -
+ tmp.length_prefix_len,
+ tmp.data +
+ tmp.length_prefix_len,
+ &count))
+ {
+ PROTOBUF_C_UNPACK_ERROR("counting packed elements");
+ goto error_cleanup_during_scan;
+ }
+ *n += count;
+ } else {
+ *n += 1;
+ }
+ }
+
+ at += tmp.len;
+ rem -= tmp.len;
+ }
+
+ /* allocate space for repeated fields, also check that all required fields have been set */
+ for (f = 0; f < desc->n_fields; f++) {
+ const ProtobufCFieldDescriptor *field = desc->fields + f;
+ if (field->label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t siz =
+ sizeof_elt_in_repeated_array(field->type);
+ size_t *n_ptr =
+ STRUCT_MEMBER_PTR(size_t, rv,
+ field->quantifier_offset);
+ if (*n_ptr != 0) {
+ unsigned n = *n_ptr;
+ void *a;
+ *n_ptr = 0;
+ assert(rv->descriptor != NULL);
+#define CLEAR_REMAINING_N_PTRS() \
+ for(f++;f < desc->n_fields; f++) \
+ { \
+ field = desc->fields + f; \
+ if (field->label == PROTOBUF_C_LABEL_REPEATED) \
+ STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
+ }
+ a = do_alloc(allocator, siz * n);
+ if (!a) {
+ CLEAR_REMAINING_N_PTRS();
+ goto error_cleanup;
+ }
+ STRUCT_MEMBER(void *, rv, field->offset) = a;
+ }
+ } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
+ if (field->default_value == NULL &&
+ !REQUIRED_FIELD_BITMAP_IS_SET(f))
+ {
+ CLEAR_REMAINING_N_PTRS();
+ PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'",
+ desc->name, field->name);
+ goto error_cleanup;
+ }
+ }
+ }
+#undef CLEAR_REMAINING_N_PTRS
+
+ /* allocate space for unknown fields */
+ if (n_unknown) {
+ rv->unknown_fields = do_alloc(allocator,
+ n_unknown * sizeof(ProtobufCMessageUnknownField));
+ if (rv->unknown_fields == NULL)
+ goto error_cleanup;
+ }
+
+ /* do real parsing */
+ for (i_slab = 0; i_slab <= which_slab; i_slab++) {
+ unsigned max = (i_slab == which_slab) ?
+ in_slab_index : (1UL << (i_slab + 4));
+ ScannedMember *slab = scanned_member_slabs[i_slab];
+
+ for (j = 0; j < max; j++) {
+ if (!parse_member(slab + j, rv, allocator)) {
+ PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s",
+ slab->field ? slab->field->name : "*unknown-field*",
+ desc->name);
+ goto error_cleanup;
+ }
+ }
+ }
+
+ /* cleanup */
+ for (j = 1; j <= which_slab; j++)
+ do_free(allocator, scanned_member_slabs[j]);
+ if (required_fields_bitmap_alloced)
+ do_free(allocator, required_fields_bitmap);
+ return rv;
+
+error_cleanup:
+ protobuf_c_message_free_unpacked(rv, allocator);
+ for (j = 1; j <= which_slab; j++)
+ do_free(allocator, scanned_member_slabs[j]);
+ if (required_fields_bitmap_alloced)
+ do_free(allocator, required_fields_bitmap);
+ return NULL;
+
+error_cleanup_during_scan:
+ do_free(allocator, rv);
+ for (j = 1; j <= which_slab; j++)
+ do_free(allocator, scanned_member_slabs[j]);
+ if (required_fields_bitmap_alloced)
+ do_free(allocator, required_fields_bitmap);
+ return NULL;
+}
+
+void
+protobuf_c_message_free_unpacked(ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ const ProtobufCMessageDescriptor *desc;
+ unsigned f;
+
+ if (message == NULL)
+ return;
+
+ desc = message->descriptor;
+
+ ASSERT_IS_MESSAGE(message);
+
+ if (allocator == NULL)
+ allocator = &protobuf_c__allocator;
+ message->descriptor = NULL;
+ for (f = 0; f < desc->n_fields; f++) {
+ if (0 != (desc->fields[f].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) &&
+ desc->fields[f].id !=
+ STRUCT_MEMBER(uint32_t, message, desc->fields[f].quantifier_offset))
+ {
+ /* This is not the selected oneof, skip it */
+ continue;
+ }
+
+ if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t n = STRUCT_MEMBER(size_t,
+ message,
+ desc->fields[f].quantifier_offset);
+ void *arr = STRUCT_MEMBER(void *,
+ message,
+ desc->fields[f].offset);
+
+ if (arr != NULL) {
+ if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
+ unsigned i;
+ for (i = 0; i < n; i++)
+ do_free(allocator, ((char **) arr)[i]);
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
+ unsigned i;
+ for (i = 0; i < n; i++)
+ do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data);
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
+ unsigned i;
+ for (i = 0; i < n; i++)
+ protobuf_c_message_free_unpacked(
+ ((ProtobufCMessage **) arr)[i],
+ allocator
+ );
+ }
+ do_free(allocator, arr);
+ }
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
+ char *str = STRUCT_MEMBER(char *, message,
+ desc->fields[f].offset);
+
+ if (str && str != desc->fields[f].default_value)
+ do_free(allocator, str);
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
+ void *data = STRUCT_MEMBER(ProtobufCBinaryData, message,
+ desc->fields[f].offset).data;
+ const ProtobufCBinaryData *default_bd;
+
+ default_bd = desc->fields[f].default_value;
+ if (data != NULL &&
+ (default_bd == NULL ||
+ default_bd->data != data))
+ {
+ do_free(allocator, data);
+ }
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
+ ProtobufCMessage *sm;
+
+ sm = STRUCT_MEMBER(ProtobufCMessage *, message,
+ desc->fields[f].offset);
+ if (sm && sm != desc->fields[f].default_value)
+ protobuf_c_message_free_unpacked(sm, allocator);
+ }
+ }
+
+ for (f = 0; f < message->n_unknown_fields; f++)
+ do_free(allocator, message->unknown_fields[f].data);
+ if (message->unknown_fields != NULL)
+ do_free(allocator, message->unknown_fields);
+
+ do_free(allocator, message);
+}
+
+void
+protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor,
+ void *message)
+{
+ descriptor->message_init((ProtobufCMessage *) (message));
+}
+
+protobuf_c_boolean
+protobuf_c_message_check(const ProtobufCMessage *message)
+{
+ unsigned i;
+
+ if (!message ||
+ !message->descriptor ||
+ message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
+ {
+ return FALSE;
+ }
+
+ for (i = 0; i < message->descriptor->n_fields; i++) {
+ const ProtobufCFieldDescriptor *f = message->descriptor->fields + i;
+ ProtobufCType type = f->type;
+ ProtobufCLabel label = f->label;
+ void *field = STRUCT_MEMBER_P (message, f->offset);
+
+ if (label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset);
+
+ if (*quantity > 0 && *(void **) field == NULL) {
+ return FALSE;
+ }
+
+ if (type == PROTOBUF_C_TYPE_MESSAGE) {
+ ProtobufCMessage **submessage = *(ProtobufCMessage ***) field;
+ unsigned j;
+ for (j = 0; j < *quantity; j++) {
+ if (!protobuf_c_message_check(submessage[j]))
+ return FALSE;
+ }
+ } else if (type == PROTOBUF_C_TYPE_STRING) {
+ char **string = *(char ***) field;
+ unsigned j;
+ for (j = 0; j < *quantity; j++) {
+ if (!string[j])
+ return FALSE;
+ }
+ } else if (type == PROTOBUF_C_TYPE_BYTES) {
+ ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field;
+ unsigned j;
+ for (j = 0; j < *quantity; j++) {
+ if (bd[j].len > 0 && bd[j].data == NULL)
+ return FALSE;
+ }
+ }
+
+ } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */
+
+ if (type == PROTOBUF_C_TYPE_MESSAGE) {
+ ProtobufCMessage *submessage = *(ProtobufCMessage **) field;
+ if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) {
+ if (!protobuf_c_message_check(submessage))
+ return FALSE;
+ }
+ } else if (type == PROTOBUF_C_TYPE_STRING) {
+ char *string = *(char **) field;
+ if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL)
+ return FALSE;
+ } else if (type == PROTOBUF_C_TYPE_BYTES) {
+ protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset);
+ ProtobufCBinaryData *bd = field;
+ if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) {
+ if (bd->len > 0 && bd->data == NULL)
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/* === services === */
+
+typedef void (*GenericHandler) (void *service,
+ const ProtobufCMessage *input,
+ ProtobufCClosure closure,
+ void *closure_data);
+void
+protobuf_c_service_invoke_internal(ProtobufCService *service,
+ unsigned method_index,
+ const ProtobufCMessage *input,
+ ProtobufCClosure closure,
+ void *closure_data)
+{
+ GenericHandler *handlers;
+ GenericHandler handler;
+
+ /*
+ * Verify that method_index is within range. If this fails, you are
+ * likely invoking a newly added method on an old service. (Although
+ * other memory corruption bugs can cause this assertion too.)
+ */
+ assert(method_index < service->descriptor->n_methods);
+
+ /*
+ * Get the array of virtual methods (which are enumerated by the
+ * generated code).
+ */
+ handlers = (GenericHandler *) (service + 1);
+
+ /*
+ * Get our method and invoke it.
+ * \todo Seems like handler == NULL is a situation that needs handling.
+ */
+ handler = handlers[method_index];
+ (*handler)(service, input, closure, closure_data);
+}
+
+void
+protobuf_c_service_generated_init(ProtobufCService *service,
+ const ProtobufCServiceDescriptor *descriptor,
+ ProtobufCServiceDestroy destroy)
+{
+ ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
+ service->descriptor = descriptor;
+ service->destroy = destroy;
+ service->invoke = protobuf_c_service_invoke_internal;
+ memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler));
+}
+
+void protobuf_c_service_destroy(ProtobufCService *service)
+{
+ service->destroy(service);
+}
+
+/* --- querying the descriptors --- */
+
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc,
+ const char *name)
+{
+ unsigned start = 0;
+ unsigned count;
+
+ if (desc == NULL || desc->values_by_name == NULL)
+ return NULL;
+
+ count = desc->n_value_names;
+
+ while (count > 1) {
+ unsigned mid = start + count / 2;
+ int rv = strcmp(desc->values_by_name[mid].name, name);
+ if (rv == 0)
+ return desc->values + desc->values_by_name[mid].index;
+ else if (rv < 0) {
+ count = start + count - (mid + 1);
+ start = mid + 1;
+ } else
+ count = mid - start;
+ }
+ if (count == 0)
+ return NULL;
+ if (strcmp(desc->values_by_name[start].name, name) == 0)
+ return desc->values + desc->values_by_name[start].index;
+ return NULL;
+}
+
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc,
+ int value)
+{
+ int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value);
+ if (rv < 0)
+ return NULL;
+ return desc->values + rv;
+}
+
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc,
+ const char *name)
+{
+ unsigned start = 0;
+ unsigned count;
+ const ProtobufCFieldDescriptor *field;
+
+ if (desc == NULL || desc->fields_sorted_by_name == NULL)
+ return NULL;
+
+ count = desc->n_fields;
+
+ while (count > 1) {
+ unsigned mid = start + count / 2;
+ int rv;
+ field = desc->fields + desc->fields_sorted_by_name[mid];
+ rv = strcmp(field->name, name);
+ if (rv == 0)
+ return field;
+ else if (rv < 0) {
+ count = start + count - (mid + 1);
+ start = mid + 1;
+ } else
+ count = mid - start;
+ }
+ if (count == 0)
+ return NULL;
+ field = desc->fields + desc->fields_sorted_by_name[start];
+ if (strcmp(field->name, name) == 0)
+ return field;
+ return NULL;
+}
+
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc,
+ unsigned value)
+{
+ int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value);
+ if (rv < 0)
+ return NULL;
+ return desc->fields + rv;
+}
+
+const ProtobufCMethodDescriptor *
+protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc,
+ const char *name)
+{
+ unsigned start = 0;
+ unsigned count;
+
+ if (desc == NULL || desc->method_indices_by_name == NULL)
+ return NULL;
+
+ count = desc->n_methods;
+
+ while (count > 1) {
+ unsigned mid = start + count / 2;
+ unsigned mid_index = desc->method_indices_by_name[mid];
+ const char *mid_name = desc->methods[mid_index].name;
+ int rv = strcmp(mid_name, name);
+
+ if (rv == 0)
+ return desc->methods + desc->method_indices_by_name[mid];
+ if (rv < 0) {
+ count = start + count - (mid + 1);
+ start = mid + 1;
+ } else {
+ count = mid - start;
+ }
+ }
+ if (count == 0)
+ return NULL;
+ if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
+ return desc->methods + desc->method_indices_by_name[start];
+ return NULL;
+}
diff --git a/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.h b/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.h
new file mode 100644
index 000000000..c8fa4fc2a
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.h
@@ -0,0 +1,1106 @@
+/*
+ * Copyright (c) 2008-2017, Dave Benson and the protobuf-c authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*! \file
+ * \mainpage Introduction
+ *
+ * This is [protobuf-c], a C implementation of [Protocol Buffers].
+ *
+ * This file defines the public API for the `libprotobuf-c` support library.
+ * This API includes interfaces that can be used directly by client code as well
+ * as the interfaces used by the code generated by the `protoc-c` compiler.
+ *
+ * The `libprotobuf-c` support library performs the actual serialization and
+ * deserialization of Protocol Buffers messages. It interacts with structures,
+ * definitions, and metadata generated by the `protoc-c` compiler from .proto
+ * files.
+ *
+ * \authors Dave Benson and the `protobuf-c` authors.
+ *
+ * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
+ *
+ * [protobuf-c]: https://github.com/protobuf-c/protobuf-c
+ * [Protocol Buffers]: https://developers.google.com/protocol-buffers/
+ * [BSD-2-Clause]: http://opensource.org/licenses/BSD-2-Clause
+ *
+ * \page gencode Generated Code
+ *
+ * For each enum, we generate a C enum. For each message, we generate a C
+ * structure which can be cast to a `ProtobufCMessage`.
+ *
+ * For each enum and message, we generate a descriptor object that allows us to
+ * implement a kind of reflection on the structures.
+ *
+ * First, some naming conventions:
+ *
+ * - The name of the type for enums and messages and services is camel case
+ * (meaning WordsAreCrammedTogether) except that double underscores are used
+ * to delimit scopes. For example, the following `.proto` file:
+ *
+~~~{.proto}
+ package foo.bar;
+ message BazBah {
+ optional int32 val = 1;
+ }
+~~~
+ *
+ * would generate a C type `Foo__Bar__BazBah`.
+ *
+ * - Identifiers for functions and globals are all lowercase, with camel case
+ * words separated by single underscores. For example, one of the function
+ * prototypes generated by `protoc-c` for the above example:
+ *
+~~~{.c}
+Foo__Bar__BazBah *
+ foo__bar__baz_bah__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+~~~
+ *
+ * - Identifiers for enum values contain an uppercase prefix which embeds the
+ * package name and the enum type name.
+ *
+ * - A double underscore is used to separate further components of identifier
+ * names.
+ *
+ * For example, in the name of the unpack function above, the package name
+ * `foo.bar` has become `foo__bar`, the message name BazBah has become
+ * `baz_bah`, and the method name is `unpack`. These are all joined with double
+ * underscores to form the C identifier `foo__bar__baz_bah__unpack`.
+ *
+ * We also generate descriptor objects for messages and enums. These are
+ * declared in the `.pb-c.h` files:
+ *
+~~~{.c}
+extern const ProtobufCMessageDescriptor foo__bar__baz_bah__descriptor;
+~~~
+ *
+ * The message structures all begin with `ProtobufCMessageDescriptor *` which is
+ * sufficient to allow them to be cast to `ProtobufCMessage`.
+ *
+ * For each message defined in a `.proto` file, we generate a number of
+ * functions and macros. Each function name contains a prefix based on the
+ * package name and message name in order to make it a unique C identifier.
+ *
+ * - `INIT`. Statically initializes a message object, initializing its
+ * descriptor and setting its fields to default values. Uninitialized
+ * messages cannot be processed by the protobuf-c library.
+ *
+~~~{.c}
+#define FOO__BAR__BAZ_BAH__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&foo__bar__baz_bah__descriptor), 0 }
+~~~
+ * - `init()`. Initializes a message object, initializing its descriptor and
+ * setting its fields to default values. Uninitialized messages cannot be
+ * processed by the protobuf-c library.
+ *
+~~~{.c}
+void foo__bar__baz_bah__init
+ (Foo__Bar__BazBah *message);
+~~~
+ * - `unpack()`. Unpacks data for a particular message format. Note that the
+ * `allocator` parameter is usually `NULL` to indicate that the system's
+ * `malloc()` and `free()` functions should be used for dynamically allocating
+ * memory.
+ *
+~~~{.c}
+Foo__Bar__BazBah *
+ foo__bar__baz_bah__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+~~~
+ *
+ * - `free_unpacked()`. Frees a message object obtained with the `unpack()`
+ * method. Freeing `NULL` is allowed (the same as with `free()`).
+ *
+~~~{.c}
+void foo__bar__baz_bah__free_unpacked
+ (Foo__Bar__BazBah *message,
+ ProtobufCAllocator *allocator);
+~~~
+ *
+ * - `get_packed_size()`. Calculates the length in bytes of the serialized
+ * representation of the message object.
+ *
+~~~{.c}
+size_t foo__bar__baz_bah__get_packed_size
+ (const Foo__Bar__BazBah *message);
+~~~
+ *
+ * - `pack()`. Pack a message object into a preallocated buffer. Assumes that
+ * the buffer is large enough. (Use `get_packed_size()` first.)
+ *
+~~~{.c}
+size_t foo__bar__baz_bah__pack
+ (const Foo__Bar__BazBah *message,
+ uint8_t *out);
+~~~
+ *
+ * - `pack_to_buffer()`. Packs a message into a "virtual buffer". This is an
+ * object which defines an "append bytes" callback to consume data as it is
+ * serialized.
+ *
+~~~{.c}
+size_t foo__bar__baz_bah__pack_to_buffer
+ (const Foo__Bar__BazBah *message,
+ ProtobufCBuffer *buffer);
+~~~
+ *
+ * \page pack Packing and unpacking messages
+ *
+ * To pack a message, first compute the packed size of the message with
+ * protobuf_c_message_get_packed_size(), then allocate a buffer of at least
+ * that size, then call protobuf_c_message_pack().
+ *
+ * Alternatively, a message can be serialized without calculating the final size
+ * first. Use the protobuf_c_message_pack_to_buffer() function and provide a
+ * ProtobufCBuffer object which implements an "append" method that consumes
+ * data.
+ *
+ * To unpack a message, call the protobuf_c_message_unpack() function. The
+ * result can be cast to an object of the type that matches the descriptor for
+ * the message.
+ *
+ * The result of unpacking a message should be freed with
+ * protobuf_c_message_free_unpacked().
+ */
+
+#ifndef PROTOBUF_C_H
+#define PROTOBUF_C_H
+
+#include <assert.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+# define PROTOBUF_C__BEGIN_DECLS extern "C" {
+# define PROTOBUF_C__END_DECLS }
+#else
+# define PROTOBUF_C__BEGIN_DECLS
+# define PROTOBUF_C__END_DECLS
+#endif
+
+PROTOBUF_C__BEGIN_DECLS
+
+#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB)
+# ifdef PROTOBUF_C_EXPORT
+# define PROTOBUF_C__API __declspec(dllexport)
+# else
+# define PROTOBUF_C__API __declspec(dllimport)
+# endif
+#else
+# define PROTOBUF_C__API
+#endif
+
+#if !defined(PROTOBUF_C__NO_DEPRECATED) && \
+ ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# define PROTOBUF_C__DEPRECATED __attribute__((__deprecated__))
+#else
+# define PROTOBUF_C__DEPRECATED
+#endif
+
+#ifndef PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE
+ #define PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(enum_name) \
+ , _##enum_name##_IS_INT_SIZE = INT_MAX
+#endif
+
+#define PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC 0x14159bc3
+#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9
+#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af
+
+/* Empty string used for initializers */
+extern const char protobuf_c_empty_string[];
+
+/**
+ * \defgroup api Public API
+ *
+ * This is the public API for `libprotobuf-c`. These interfaces are stable and
+ * subject to Semantic Versioning guarantees.
+ *
+ * @{
+ */
+
+/**
+ * Values for the `flags` word in `ProtobufCFieldDescriptor`.
+ */
+typedef enum {
+ /** Set if the field is repeated and marked with the `packed` option. */
+ PROTOBUF_C_FIELD_FLAG_PACKED = (1 << 0),
+
+ /** Set if the field is marked with the `deprecated` option. */
+ PROTOBUF_C_FIELD_FLAG_DEPRECATED = (1 << 1),
+
+ /** Set if the field is a member of a oneof (union). */
+ PROTOBUF_C_FIELD_FLAG_ONEOF = (1 << 2),
+} ProtobufCFieldFlag;
+
+/**
+ * Message field rules.
+ *
+ * \see [Defining A Message Type] in the Protocol Buffers documentation.
+ *
+ * [Defining A Message Type]:
+ * https://developers.google.com/protocol-buffers/docs/proto#simple
+ */
+typedef enum {
+ /** A well-formed message must have exactly one of this field. */
+ PROTOBUF_C_LABEL_REQUIRED,
+
+ /**
+ * A well-formed message can have zero or one of this field (but not
+ * more than one).
+ */
+ PROTOBUF_C_LABEL_OPTIONAL,
+
+ /**
+ * This field can be repeated any number of times (including zero) in a
+ * well-formed message. The order of the repeated values will be
+ * preserved.
+ */
+ PROTOBUF_C_LABEL_REPEATED,
+
+ /**
+ * This field has no label. This is valid only in proto3 and is
+ * equivalent to OPTIONAL but no "has" quantifier will be consulted.
+ */
+ PROTOBUF_C_LABEL_NONE,
+} ProtobufCLabel;
+
+/**
+ * Field value types.
+ *
+ * \see [Scalar Value Types] in the Protocol Buffers documentation.
+ *
+ * [Scalar Value Types]:
+ * https://developers.google.com/protocol-buffers/docs/proto#scalar
+ */
+typedef enum {
+ PROTOBUF_C_TYPE_INT32, /**< int32 */
+ PROTOBUF_C_TYPE_SINT32, /**< signed int32 */
+ PROTOBUF_C_TYPE_SFIXED32, /**< signed int32 (4 bytes) */
+ PROTOBUF_C_TYPE_INT64, /**< int64 */
+ PROTOBUF_C_TYPE_SINT64, /**< signed int64 */
+ PROTOBUF_C_TYPE_SFIXED64, /**< signed int64 (8 bytes) */
+ PROTOBUF_C_TYPE_UINT32, /**< unsigned int32 */
+ PROTOBUF_C_TYPE_FIXED32, /**< unsigned int32 (4 bytes) */
+ PROTOBUF_C_TYPE_UINT64, /**< unsigned int64 */
+ PROTOBUF_C_TYPE_FIXED64, /**< unsigned int64 (8 bytes) */
+ PROTOBUF_C_TYPE_FLOAT, /**< float */
+ PROTOBUF_C_TYPE_DOUBLE, /**< double */
+ PROTOBUF_C_TYPE_BOOL, /**< boolean */
+ PROTOBUF_C_TYPE_ENUM, /**< enumerated type */
+ PROTOBUF_C_TYPE_STRING, /**< UTF-8 or ASCII string */
+ PROTOBUF_C_TYPE_BYTES, /**< arbitrary byte sequence */
+ PROTOBUF_C_TYPE_MESSAGE, /**< nested message */
+} ProtobufCType;
+
+/**
+ * Field wire types.
+ *
+ * \see [Message Structure] in the Protocol Buffers documentation.
+ *
+ * [Message Structure]:
+ * https://developers.google.com/protocol-buffers/docs/encoding#structure
+ */
+typedef enum {
+ PROTOBUF_C_WIRE_TYPE_VARINT = 0,
+ PROTOBUF_C_WIRE_TYPE_64BIT = 1,
+ PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED = 2,
+ /* "Start group" and "end group" wire types are unsupported. */
+ PROTOBUF_C_WIRE_TYPE_32BIT = 5,
+} ProtobufCWireType;
+
+struct ProtobufCAllocator;
+struct ProtobufCBinaryData;
+struct ProtobufCBuffer;
+struct ProtobufCBufferSimple;
+struct ProtobufCEnumDescriptor;
+struct ProtobufCEnumValue;
+struct ProtobufCEnumValueIndex;
+struct ProtobufCFieldDescriptor;
+struct ProtobufCIntRange;
+struct ProtobufCMessage;
+struct ProtobufCMessageDescriptor;
+struct ProtobufCMessageUnknownField;
+struct ProtobufCMethodDescriptor;
+struct ProtobufCService;
+struct ProtobufCServiceDescriptor;
+
+typedef struct ProtobufCAllocator ProtobufCAllocator;
+typedef struct ProtobufCBinaryData ProtobufCBinaryData;
+typedef struct ProtobufCBuffer ProtobufCBuffer;
+typedef struct ProtobufCBufferSimple ProtobufCBufferSimple;
+typedef struct ProtobufCEnumDescriptor ProtobufCEnumDescriptor;
+typedef struct ProtobufCEnumValue ProtobufCEnumValue;
+typedef struct ProtobufCEnumValueIndex ProtobufCEnumValueIndex;
+typedef struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor;
+typedef struct ProtobufCIntRange ProtobufCIntRange;
+typedef struct ProtobufCMessage ProtobufCMessage;
+typedef struct ProtobufCMessageDescriptor ProtobufCMessageDescriptor;
+typedef struct ProtobufCMessageUnknownField ProtobufCMessageUnknownField;
+typedef struct ProtobufCMethodDescriptor ProtobufCMethodDescriptor;
+typedef struct ProtobufCService ProtobufCService;
+typedef struct ProtobufCServiceDescriptor ProtobufCServiceDescriptor;
+
+/** Boolean type. */
+typedef int protobuf_c_boolean;
+
+typedef void (*ProtobufCClosure)(const ProtobufCMessage *, void *closure_data);
+typedef void (*ProtobufCMessageInit)(ProtobufCMessage *);
+typedef void (*ProtobufCServiceDestroy)(ProtobufCService *);
+
+/**
+ * Structure for defining a custom memory allocator.
+ */
+struct ProtobufCAllocator {
+ /** Function to allocate memory. */
+ void *(*alloc)(void *allocator_data, size_t size);
+
+ /** Function to free memory. */
+ void (*free)(void *allocator_data, void *pointer);
+
+ /** Opaque pointer passed to `alloc` and `free` functions. */
+ void *allocator_data;
+};
+
+/**
+ * Structure for the protobuf `bytes` scalar type.
+ *
+ * The data contained in a `ProtobufCBinaryData` is an arbitrary sequence of
+ * bytes. It may contain embedded `NUL` characters and is not required to be
+ * `NUL`-terminated.
+ */
+struct ProtobufCBinaryData {
+ size_t len; /**< Number of bytes in the `data` field. */
+ uint8_t *data; /**< Data bytes. */
+};
+
+/**
+ * Structure for defining a virtual append-only buffer. Used by
+ * protobuf_c_message_pack_to_buffer() to abstract the consumption of serialized
+ * bytes.
+ *
+ * `ProtobufCBuffer` "subclasses" may be defined on the stack. For example, to
+ * write to a `FILE` object:
+ *
+~~~{.c}
+typedef struct {
+ ProtobufCBuffer base;
+ FILE *fp;
+} BufferAppendToFile;
+
+static void
+my_buffer_file_append(ProtobufCBuffer *buffer,
+ size_t len,
+ const uint8_t *data)
+{
+ BufferAppendToFile *file_buf = (BufferAppendToFile *) buffer;
+ fwrite(data, len, 1, file_buf->fp); // XXX: No error handling!
+}
+~~~
+ *
+ * To use this new type of ProtobufCBuffer, it could be called as follows:
+ *
+~~~{.c}
+...
+BufferAppendToFile tmp = {0};
+tmp.base.append = my_buffer_file_append;
+tmp.fp = fp;
+protobuf_c_message_pack_to_buffer(&message, &tmp);
+...
+~~~
+ */
+struct ProtobufCBuffer {
+ /** Append function. Consumes the `len` bytes stored at `data`. */
+ void (*append)(ProtobufCBuffer *buffer,
+ size_t len,
+ const uint8_t *data);
+};
+
+/**
+ * Simple buffer "subclass" of `ProtobufCBuffer`.
+ *
+ * A `ProtobufCBufferSimple` object is declared on the stack and uses a
+ * scratch buffer provided by the user for the initial allocation. It performs
+ * exponential resizing, using dynamically allocated memory. A
+ * `ProtobufCBufferSimple` object can be created and used as follows:
+ *
+~~~{.c}
+uint8_t pad[128];
+ProtobufCBufferSimple simple = PROTOBUF_C_BUFFER_SIMPLE_INIT(pad);
+ProtobufCBuffer *buffer = (ProtobufCBuffer *) &simple;
+~~~
+ *
+ * `buffer` can now be used with `protobuf_c_message_pack_to_buffer()`. Once a
+ * message has been serialized to a `ProtobufCBufferSimple` object, the
+ * serialized data bytes can be accessed from the `.data` field.
+ *
+ * To free the memory allocated by a `ProtobufCBufferSimple` object, if any,
+ * call PROTOBUF_C_BUFFER_SIMPLE_CLEAR() on the object, for example:
+ *
+~~~{.c}
+PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple);
+~~~
+ *
+ * \see PROTOBUF_C_BUFFER_SIMPLE_INIT
+ * \see PROTOBUF_C_BUFFER_SIMPLE_CLEAR
+ */
+struct ProtobufCBufferSimple {
+ /** "Base class". */
+ ProtobufCBuffer base;
+ /** Number of bytes allocated in `data`. */
+ size_t alloced;
+ /** Number of bytes currently stored in `data`. */
+ size_t len;
+ /** Data bytes. */
+ uint8_t *data;
+ /** Whether `data` must be freed. */
+ protobuf_c_boolean must_free_data;
+ /** Allocator to use. May be NULL to indicate the system allocator. */
+ ProtobufCAllocator *allocator;
+};
+
+/**
+ * Describes an enumeration as a whole, with all of its values.
+ */
+struct ProtobufCEnumDescriptor {
+ /** Magic value checked to ensure that the API is used correctly. */
+ uint32_t magic;
+
+ /** The qualified name (e.g., "namespace.Type"). */
+ const char *name;
+ /** The unqualified name as given in the .proto file (e.g., "Type"). */
+ const char *short_name;
+ /** Identifier used in generated C code. */
+ const char *c_name;
+ /** The dot-separated namespace. */
+ const char *package_name;
+
+ /** Number elements in `values`. */
+ unsigned n_values;
+ /** Array of distinct values, sorted by numeric value. */
+ const ProtobufCEnumValue *values;
+
+ /** Number of elements in `values_by_name`. */
+ unsigned n_value_names;
+ /** Array of named values, including aliases, sorted by name. */
+ const ProtobufCEnumValueIndex *values_by_name;
+
+ /** Number of elements in `value_ranges`. */
+ unsigned n_value_ranges;
+ /** Value ranges, for faster lookups by numeric value. */
+ const ProtobufCIntRange *value_ranges;
+
+ /** Reserved for future use. */
+ void *reserved1;
+ /** Reserved for future use. */
+ void *reserved2;
+ /** Reserved for future use. */
+ void *reserved3;
+ /** Reserved for future use. */
+ void *reserved4;
+};
+
+/**
+ * Represents a single value of an enumeration.
+ */
+struct ProtobufCEnumValue {
+ /** The string identifying this value in the .proto file. */
+ const char *name;
+
+ /** The string identifying this value in generated C code. */
+ const char *c_name;
+
+ /** The numeric value assigned in the .proto file. */
+ int value;
+};
+
+/**
+ * Used by `ProtobufCEnumDescriptor` to look up enum values.
+ */
+struct ProtobufCEnumValueIndex {
+ /** Name of the enum value. */
+ const char *name;
+ /** Index into values[] array. */
+ unsigned index;
+};
+
+/**
+ * Describes a single field in a message.
+ */
+struct ProtobufCFieldDescriptor {
+ /** Name of the field as given in the .proto file. */
+ const char *name;
+
+ /** Tag value of the field as given in the .proto file. */
+ uint32_t id;
+
+ /** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */
+ ProtobufCLabel label;
+
+ /** The type of the field. */
+ ProtobufCType type;
+
+ /**
+ * The offset in bytes of the message's C structure's quantifier field
+ * (the `has_MEMBER` field for optional members or the `n_MEMBER` field
+ * for repeated members or the case enum for oneofs).
+ */
+ unsigned quantifier_offset;
+
+ /**
+ * The offset in bytes into the message's C structure for the member
+ * itself.
+ */
+ unsigned offset;
+
+ /**
+ * A type-specific descriptor.
+ *
+ * If `type` is `PROTOBUF_C_TYPE_ENUM`, then `descriptor` points to the
+ * corresponding `ProtobufCEnumDescriptor`.
+ *
+ * If `type` is `PROTOBUF_C_TYPE_MESSAGE`, then `descriptor` points to
+ * the corresponding `ProtobufCMessageDescriptor`.
+ *
+ * Otherwise this field is NULL.
+ */
+ const void *descriptor; /* for MESSAGE and ENUM types */
+
+ /** The default value for this field, if defined. May be NULL. */
+ const void *default_value;
+
+ /**
+ * A flag word. Zero or more of the bits defined in the
+ * `ProtobufCFieldFlag` enum may be set.
+ */
+ uint32_t flags;
+
+ /** Reserved for future use. */
+ unsigned reserved_flags;
+ /** Reserved for future use. */
+ void *reserved2;
+ /** Reserved for future use. */
+ void *reserved3;
+};
+
+/**
+ * Helper structure for optimizing int => index lookups in the case
+ * where the keys are mostly consecutive values, as they presumably are for
+ * enums and fields.
+ *
+ * The data structures requires that the values in the original array are
+ * sorted.
+ */
+struct ProtobufCIntRange {
+ int start_value;
+ unsigned orig_index;
+ /*
+ * NOTE: the number of values in the range can be inferred by looking
+ * at the next element's orig_index. A dummy element is added to make
+ * this simple.
+ */
+};
+
+/**
+ * An instance of a message.
+ *
+ * `ProtobufCMessage` is a light-weight "base class" for all messages.
+ *
+ * In particular, `ProtobufCMessage` doesn't have any allocation policy
+ * associated with it. That's because it's common to create `ProtobufCMessage`
+ * objects on the stack. In fact, that's what we recommend for sending messages.
+ * If the object is allocated from the stack, you can't really have a memory
+ * leak.
+ *
+ * This means that calls to functions like protobuf_c_message_unpack() which
+ * return a `ProtobufCMessage` must be paired with a call to a free function,
+ * like protobuf_c_message_free_unpacked().
+ */
+struct ProtobufCMessage {
+ /** The descriptor for this message type. */
+ const ProtobufCMessageDescriptor *descriptor;
+ /** The number of elements in `unknown_fields`. */
+ unsigned n_unknown_fields;
+ /** The fields that weren't recognized by the parser. */
+ ProtobufCMessageUnknownField *unknown_fields;
+};
+
+/**
+ * Describes a message.
+ */
+struct ProtobufCMessageDescriptor {
+ /** Magic value checked to ensure that the API is used correctly. */
+ uint32_t magic;
+
+ /** The qualified name (e.g., "namespace.Type"). */
+ const char *name;
+ /** The unqualified name as given in the .proto file (e.g., "Type"). */
+ const char *short_name;
+ /** Identifier used in generated C code. */
+ const char *c_name;
+ /** The dot-separated namespace. */
+ const char *package_name;
+
+ /**
+ * Size in bytes of the C structure representing an instance of this
+ * type of message.
+ */
+ size_t sizeof_message;
+
+ /** Number of elements in `fields`. */
+ unsigned n_fields;
+ /** Field descriptors, sorted by tag number. */
+ const ProtobufCFieldDescriptor *fields;
+ /** Used for looking up fields by name. */
+ const unsigned *fields_sorted_by_name;
+
+ /** Number of elements in `field_ranges`. */
+ unsigned n_field_ranges;
+ /** Used for looking up fields by id. */
+ const ProtobufCIntRange *field_ranges;
+
+ /** Message initialisation function. */
+ ProtobufCMessageInit message_init;
+
+ /** Reserved for future use. */
+ void *reserved1;
+ /** Reserved for future use. */
+ void *reserved2;
+ /** Reserved for future use. */
+ void *reserved3;
+};
+
+/**
+ * An unknown message field.
+ */
+struct ProtobufCMessageUnknownField {
+ /** The tag number. */
+ uint32_t tag;
+ /** The wire type of the field. */
+ ProtobufCWireType wire_type;
+ /** Number of bytes in `data`. */
+ size_t len;
+ /** Field data. */
+ uint8_t *data;
+};
+
+/**
+ * Method descriptor.
+ */
+struct ProtobufCMethodDescriptor {
+ /** Method name. */
+ const char *name;
+ /** Input message descriptor. */
+ const ProtobufCMessageDescriptor *input;
+ /** Output message descriptor. */
+ const ProtobufCMessageDescriptor *output;
+};
+
+/**
+ * Service.
+ */
+struct ProtobufCService {
+ /** Service descriptor. */
+ const ProtobufCServiceDescriptor *descriptor;
+ /** Function to invoke the service. */
+ void (*invoke)(ProtobufCService *service,
+ unsigned method_index,
+ const ProtobufCMessage *input,
+ ProtobufCClosure closure,
+ void *closure_data);
+ /** Function to destroy the service. */
+ void (*destroy)(ProtobufCService *service);
+};
+
+/**
+ * Service descriptor.
+ */
+struct ProtobufCServiceDescriptor {
+ /** Magic value checked to ensure that the API is used correctly. */
+ uint32_t magic;
+
+ /** Service name. */
+ const char *name;
+ /** Short version of service name. */
+ const char *short_name;
+ /** C identifier for the service name. */
+ const char *c_name;
+ /** Package name. */
+ const char *package;
+ /** Number of elements in `methods`. */
+ unsigned n_methods;
+ /** Method descriptors, in the order defined in the .proto file. */
+ const ProtobufCMethodDescriptor *methods;
+ /** Sort index of methods. */
+ const unsigned *method_indices_by_name;
+};
+
+/**
+ * Get the version of the protobuf-c library. Note that this is the version of
+ * the library linked against, not the version of the headers compiled against.
+ *
+ * \return A string containing the version number of protobuf-c.
+ */
+PROTOBUF_C__API
+const char *
+protobuf_c_version(void);
+
+/**
+ * Get the version of the protobuf-c library. Note that this is the version of
+ * the library linked against, not the version of the headers compiled against.
+ *
+ * \return A 32 bit unsigned integer containing the version number of
+ * protobuf-c, represented in base-10 as (MAJOR*1E6) + (MINOR*1E3) + PATCH.
+ */
+PROTOBUF_C__API
+uint32_t
+protobuf_c_version_number(void);
+
+/**
+ * The version of the protobuf-c headers, represented as a string using the same
+ * format as protobuf_c_version().
+ */
+#define PROTOBUF_C_VERSION "1.3.0"
+
+/**
+ * The version of the protobuf-c headers, represented as an integer using the
+ * same format as protobuf_c_version_number().
+ */
+#define PROTOBUF_C_VERSION_NUMBER 1003000
+
+/**
+ * The minimum protoc-c version which works with the current version of the
+ * protobuf-c headers.
+ */
+#define PROTOBUF_C_MIN_COMPILER_VERSION 1000000
+
+/**
+ * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by name.
+ *
+ * \param desc
+ * The `ProtobufCEnumDescriptor` object.
+ * \param name
+ * The `name` field from the corresponding `ProtobufCEnumValue` object to
+ * match.
+ * \return
+ * A `ProtobufCEnumValue` object.
+ * \retval NULL
+ * If not found or if the optimize_for = CODE_SIZE option was set.
+ */
+PROTOBUF_C__API
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value_by_name(
+ const ProtobufCEnumDescriptor *desc,
+ const char *name);
+
+/**
+ * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by numeric
+ * value.
+ *
+ * \param desc
+ * The `ProtobufCEnumDescriptor` object.
+ * \param value
+ * The `value` field from the corresponding `ProtobufCEnumValue` object to
+ * match.
+ *
+ * \return
+ * A `ProtobufCEnumValue` object.
+ * \retval NULL
+ * If not found.
+ */
+PROTOBUF_C__API
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value(
+ const ProtobufCEnumDescriptor *desc,
+ int value);
+
+/**
+ * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
+ * the name of the field.
+ *
+ * \param desc
+ * The `ProtobufCMessageDescriptor` object.
+ * \param name
+ * The name of the field.
+ * \return
+ * A `ProtobufCFieldDescriptor` object.
+ * \retval NULL
+ * If not found or if the optimize_for = CODE_SIZE option was set.
+ */
+PROTOBUF_C__API
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field_by_name(
+ const ProtobufCMessageDescriptor *desc,
+ const char *name);
+
+/**
+ * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
+ * the tag value of the field.
+ *
+ * \param desc
+ * The `ProtobufCMessageDescriptor` object.
+ * \param value
+ * The tag value of the field.
+ * \return
+ * A `ProtobufCFieldDescriptor` object.
+ * \retval NULL
+ * If not found.
+ */
+PROTOBUF_C__API
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field(
+ const ProtobufCMessageDescriptor *desc,
+ unsigned value);
+
+/**
+ * Determine the number of bytes required to store the serialised message.
+ *
+ * \param message
+ * The message object to serialise.
+ * \return
+ * Number of bytes.
+ */
+PROTOBUF_C__API
+size_t
+protobuf_c_message_get_packed_size(const ProtobufCMessage *message);
+
+/**
+ * Serialise a message from its in-memory representation.
+ *
+ * This function stores the serialised bytes of the message in a pre-allocated
+ * buffer.
+ *
+ * \param message
+ * The message object to serialise.
+ * \param[out] out
+ * Buffer to store the bytes of the serialised message. This buffer must
+ * have enough space to store the packed message. Use
+ * protobuf_c_message_get_packed_size() to determine the number of bytes
+ * required.
+ * \return
+ * Number of bytes stored in `out`.
+ */
+PROTOBUF_C__API
+size_t
+protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out);
+
+/**
+ * Serialise a message from its in-memory representation to a virtual buffer.
+ *
+ * This function calls the `append` method of a `ProtobufCBuffer` object to
+ * consume the bytes generated by the serialiser.
+ *
+ * \param message
+ * The message object to serialise.
+ * \param buffer
+ * The virtual buffer object.
+ * \return
+ * Number of bytes passed to the virtual buffer.
+ */
+PROTOBUF_C__API
+size_t
+protobuf_c_message_pack_to_buffer(
+ const ProtobufCMessage *message,
+ ProtobufCBuffer *buffer);
+
+/**
+ * Unpack a serialised message into an in-memory representation.
+ *
+ * \param descriptor
+ * The message descriptor.
+ * \param allocator
+ * `ProtobufCAllocator` to use for memory allocation. May be NULL to
+ * specify the default allocator.
+ * \param len
+ * Length in bytes of the serialised message.
+ * \param data
+ * Pointer to the serialised message.
+ * \return
+ * An unpacked message object.
+ * \retval NULL
+ * If an error occurred during unpacking.
+ */
+PROTOBUF_C__API
+ProtobufCMessage *
+protobuf_c_message_unpack(
+ const ProtobufCMessageDescriptor *descriptor,
+ ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+
+/**
+ * Free an unpacked message object.
+ *
+ * This function should be used to deallocate the memory used by a call to
+ * protobuf_c_message_unpack().
+ *
+ * \param message
+ * The message object to free. May be NULL.
+ * \param allocator
+ * `ProtobufCAllocator` to use for memory deallocation. May be NULL to
+ * specify the default allocator.
+ */
+PROTOBUF_C__API
+void
+protobuf_c_message_free_unpacked(
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator);
+
+/**
+ * Check the validity of a message object.
+ *
+ * Makes sure all required fields (`PROTOBUF_C_LABEL_REQUIRED`) are present.
+ * Recursively checks nested messages.
+ *
+ * \retval TRUE
+ * Message is valid.
+ * \retval FALSE
+ * Message is invalid.
+ */
+PROTOBUF_C__API
+protobuf_c_boolean
+protobuf_c_message_check(const ProtobufCMessage *);
+
+/** Message initialiser. */
+#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL }
+
+/**
+ * Initialise a message object from a message descriptor.
+ *
+ * \param descriptor
+ * Message descriptor.
+ * \param message
+ * Allocated block of memory of size `descriptor->sizeof_message`.
+ */
+PROTOBUF_C__API
+void
+protobuf_c_message_init(
+ const ProtobufCMessageDescriptor *descriptor,
+ void *message);
+
+/**
+ * Free a service.
+ *
+ * \param service
+ * The service object to free.
+ */
+PROTOBUF_C__API
+void
+protobuf_c_service_destroy(ProtobufCService *service);
+
+/**
+ * Look up a `ProtobufCMethodDescriptor` by name.
+ *
+ * \param desc
+ * Service descriptor.
+ * \param name
+ * Name of the method.
+ *
+ * \return
+ * A `ProtobufCMethodDescriptor` object.
+ * \retval NULL
+ * If not found or if the optimize_for = CODE_SIZE option was set.
+ */
+PROTOBUF_C__API
+const ProtobufCMethodDescriptor *
+protobuf_c_service_descriptor_get_method_by_name(
+ const ProtobufCServiceDescriptor *desc,
+ const char *name);
+
+/**
+ * Initialise a `ProtobufCBufferSimple` object.
+ */
+#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \
+{ \
+ { protobuf_c_buffer_simple_append }, \
+ sizeof(array_of_bytes), \
+ 0, \
+ (array_of_bytes), \
+ 0, \
+ NULL \
+}
+
+/**
+ * Clear a `ProtobufCBufferSimple` object, freeing any allocated memory.
+ */
+#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \
+do { \
+ if ((simp_buf)->must_free_data) { \
+ if ((simp_buf)->allocator != NULL) \
+ (simp_buf)->allocator->free( \
+ (simp_buf)->allocator, \
+ (simp_buf)->data); \
+ else \
+ free((simp_buf)->data); \
+ } \
+} while (0)
+
+/**
+ * The `append` method for `ProtobufCBufferSimple`.
+ *
+ * \param buffer
+ * The buffer object to append to. Must actually be a
+ * `ProtobufCBufferSimple` object.
+ * \param len
+ * Number of bytes in `data`.
+ * \param data
+ * Data to append.
+ */
+PROTOBUF_C__API
+void
+protobuf_c_buffer_simple_append(
+ ProtobufCBuffer *buffer,
+ size_t len,
+ const unsigned char *data);
+
+PROTOBUF_C__API
+void
+protobuf_c_service_generated_init(
+ ProtobufCService *service,
+ const ProtobufCServiceDescriptor *descriptor,
+ ProtobufCServiceDestroy destroy);
+
+PROTOBUF_C__API
+void
+protobuf_c_service_invoke_internal(
+ ProtobufCService *service,
+ unsigned method_index,
+ const ProtobufCMessage *input,
+ ProtobufCClosure closure,
+ void *closure_data);
+
+/**@}*/
+
+PROTOBUF_C__END_DECLS
+
+#endif /* PROTOBUF_C_H */
diff --git a/Software/Embedded_SW/Embedded/Common/report/distributor.c b/Software/Embedded_SW/Embedded/Common/report/distributor.c
new file mode 100644
index 000000000..38b9ccff8
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/report/distributor.c
@@ -0,0 +1,851 @@
+/******************************************************************************
+ * File name : distributor.c
+ * Title : REPORT PACKAGE - Message Distributor
+ * Date created : 01 SEP, 1996
+ * Revision : 1.0
+ * Author : Zvika Zilberman
+ *
+ * Description : Report distributor provides the duplicating of
+ * messages to the several destinations.
+ *
+ ******************************************************************************
+ *
+ * Procedures:
+ *
+ * ReportFd - Add or remove file descriptor to/from the
+ * list of destinations
+ * ReportFunc - Add or remove funtion to/from the list of
+ * destnations
+ * ReportEnableAll - Resume the work of distributor
+ *
+ * Functions, internal for Report:
+ *
+ * distibutorInit - Initialize message distributor
+ * reportDistribute - Send message to destibutor
+ *
+ * Local functions:
+ *
+ * messageDistribute - Forward message to all destinations.
+ * reportService - Distibutor Task main function
+ *
+ ******************************************************************************
+ *
+ * History:
+ * 01.09.96 Ilia Maller - start of coding
+ * 21.02.97 Ilia Maller - minor improvements
+ * 17.09.97 Zvika Zilberman - porting to DCME SWINFRA
+ *
+ ******************************************************************************/
+
+/*------------- Includes --------------------------------*/
+#include "include.h"
+
+#include "report.h"
+#include "filter.h"
+#include "distributor.h"
+
+/*------------- Local Definitions -----------------------*/
+
+#define SEVERITY_MASK(severity) ((severity) & 0x10)
+#define REPORT_ROOT_NAME "system"
+#define REPORT_TASK_STACK_SIZE 1024
+
+typedef struct
+{
+ FormatType format;
+ char message[REPORT_MAX_MSG_LEN];
+ char FileName[REPORT_MAX_MSG_LEN];
+ int LineNumber;
+ int errorCode;
+ ErrorSeverity severity;
+ int parameter1;
+ int parameter2;
+}INPUT_MESSAGE;
+
+#define INPUT_MESSAGE_LEN sizeof(INPUT_MESSAGE)
+
+typedef struct
+{
+ int fd;
+ ReportFunction function;
+}DESTINATION;
+
+#define DESTINATION_SIZE sizeof(DESTINATION)
+
+#define NUM_OF_DESTINATIONS 4
+typedef struct
+{
+ char name[11];
+ bool IsActive; /* false - discard its messages. true - send them. */
+ bool IsAlive; /* false - if not in action, can not be used or seen */
+ DESTINATION dest[NUM_OF_DESTINATIONS];
+} DistributorElement;
+
+
+static void messageDistribute(char *msg,
+ int DistTableEntry,
+ char *FileName,
+ int LineNumber,
+ int errorCode,
+ int parameter1,
+ int parameter2);
+/*static STATUS reportFormat(char *buffer,
+ int *maxlen,
+ const char *message,
+ int errorCode,
+ ErrorSeverity severity,
+ int parameter1,
+ int parameter2);*/
+static int FindFreeDestinationElement(int DistTableEntry);
+
+/*------------- Local Data ------------------------------*/
+
+static Mailbox_Handle inputQueue;
+
+/* Table where output of distributor (destinations) stored
+ Every element of the table may be or file descriptor
+ or function address.
+ The destinations stored unsorted */
+static DistributorElement *Dist_Table;
+static int DistCounter; /* number of current elements in the table */
+static int NumOfDistributions;
+
+/***************************************************************************
+ *
+ * Name : distibutorInit
+ *
+ * Function : Initialize message distributor
+ *
+ * Notes : Function uses malloc for memory allocation
+ *
+ * Parameters: priority - distributor task priority
+ * maxMsgs - maximum number of messages stored in
+ * destributor task queue
+ * maxDstr - maximum number of distributors
+ *
+ * Return value: STATUS - OK or ERROR
+ **************************************************************************/
+STATUS distibutorInit( int priority, int maxMsgs, int maxDstr )
+{
+
+ static int initialized = false;
+ int i, j;
+
+ if (initialized)
+ return OK;
+
+ NumOfDistributions = maxDstr;
+ /* create mailbox to recive messages */
+ inputQueue = Mailbox_create(INPUT_MESSAGE_LEN,maxMsgs, 0,0);
+ if (inputQueue == NULL)
+ return ERROR;
+
+ /* create table for destionations. malloc takes care about allignment */
+ Dist_Table = (DistributorElement *)malloc(sizeof(DistributorElement)*(maxDstr+1));
+ if (Dist_Table == NULL)
+ return ERROR;
+ /* initialize table */
+ for (i=0; i<=maxDstr; i++)
+ {
+ for (j=0; j<NUM_OF_DESTINATIONS; j++)
+ {
+ Dist_Table[i].dest[j].fd = -1;
+ Dist_Table[i].dest[j].function = NULL;
+ }
+ Dist_Table[i].IsActive = false;
+ Dist_Table[i].IsAlive = false;
+ }
+ /* Reset the internal (basic) distributor */
+ strcpy(Dist_Table[0].name,REPORT_ROOT_NAME);
+ Dist_Table[0].IsActive = true;
+ Dist_Table[0].IsAlive = true;
+
+ /* initialize local data */
+ DistCounter = 1;
+
+ initialized = true;
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : reportDistribute
+ *
+ * Function : Send message to destibutor
+ *
+ * Notes : Function trancates message if it length grater
+ * than INPUT_MESSAGE_LEN
+ *
+ * Parameters: message - user message
+ * extErrorType - error type and severity
+ * errorCode - error code
+ * parameter1 - user parameter 1
+ * parameter2 - user parameter 2
+ *
+ * Return value: STATUS - OK or ERROR
+ **************************************************************************/
+STATUS reportDistribute(FormatType format,
+ const char *message,
+ char *FileName,
+ int LineNumber,
+ int errorCode,
+ ErrorSeverity severity,
+ int parameter1,
+ int parameter2)
+{
+ INPUT_MESSAGE msg;
+ int Distributor = GET_PRIVATE_SEVERITY(severity);
+
+ if (Distributor > 0)
+ {
+ if (Dist_Table[Distributor].IsAlive == false)
+ return OK;
+ if (Dist_Table[Distributor].IsActive == false)
+ return OK;
+ }
+ else if (Dist_Table[0].IsActive == false)
+ return OK;
+ /* truncate if message length greater than defined */
+ msg.format = format;
+ strncpy(msg.message, message, REPORT_MAX_MSG_LEN);
+ msg.errorCode = errorCode;
+ msg.severity = severity;
+ msg.parameter1 = parameter1;
+ msg.parameter2 = parameter2;
+
+ if (inputQueue != NULL)
+ Mailbox_post(inputQueue , &msg, BIOS_NO_WAIT);
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : reportService
+ *
+ * Function : Distibutor Task main function
+ *
+ * Notes :
+ *
+ * Return value: void
+ **************************************************************************/
+Void reportService(UArg arg0, UArg arg1)
+{
+ INPUT_MESSAGE msg;
+ //static char buf[REPORT_MAX_MSG_LEN + REPORT_MSG_FORMAT_LEN];
+ int DistTableEntry;//,msgLen, errCode, par1, par2;
+
+ while(1)
+ {
+ Mailbox_pend(inputQueue , &msg, BIOS_WAIT_FOREVER);
+
+ DistTableEntry = (SEVERITY_MASK(msg.severity) == RpPrivate) ? (msg.severity >> 5) : 0;
+// /* format received string */
+// /*if (msg.format == REPORT_FORMAT)
+// {
+// msgLen = REPORT_MAX_MSG_LEN + REPORT_MSG_FORMAT_LEN;
+// reportFormat(buf, &msgLen, msg.message, msg.errorCode,
+// msg.severity, msg.parameter1, msg.parameter2);
+// errCode = msg.errorCode;
+// par1 = msg.parameter1;
+// par2 = msg.parameter2;
+// }
+// else /* MESSAGE_FORMAT - regular message */
+// {
+// msgLen = strlen(msg.message);
+// if (msgLen > REPORT_MAX_MSG_LEN-1)
+// msgLen = REPORT_MAX_MSG_LEN-1;
+// strcpy(buf,msg.message);
+// errCode = 0;
+// par1 = 0;
+// par2 = 0;
+// }*/
+ /* send message to subscribers */
+ messageDistribute( msg.message, DistTableEntry,msg.FileName, msg.LineNumber,msg.errorCode,msg.severity,msg.parameter2);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------- Private Severity -----------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/***************************************************************************
+ *
+ * Name : ReportDistributor
+ *
+ * Function : Add static distributor
+ *
+ * Notes : The name is given in order to note the severity name
+ * during the report exception.
+ *
+ * Parameters: distributorName - The severity's name must be up to 10
+ * letters long.
+ * SwitchAddRemove - REPORT_ADD to add the new static severity,
+ * REPORT_REMOVE to remove it.
+ *
+ * Return value: the new distributor handle, or -1 and thus:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_NAME_ALREADY_DISABLE if the distributor
+ * was already removed,
+ * errno = REPORT_ERROR_NAME_NOT_EXISTS if the distributorName
+ * not exists,
+ * errno = REPORT_ERROR_TABLE_FULL if there are already too
+ * many distributors,
+ * errno = REPORT_ERROR_NAME_EXISTS if the distributorName
+ * already exists.
+ **************************************************************************/
+DistributorHandle ReportDistributor(const char *distributorName, uint32_t SwitchAddRemove)
+{
+ int index;
+
+ if ((DistCounter > NumOfDistributions) && (SwitchAddRemove == REPORT_ADD))
+ {
+ errno = REPORT_ERROR_TABLE_FULL;
+ return -1;
+ }
+ if (strlen(distributorName) > 10)
+ {
+ errno = REPORT_ERROR_NAME_TOO_LONG;
+ return -1;
+ }
+ else if ((strcmp(distributorName,"system")==0) || ((strcmp(distributorName,"SYSTEM")==0)))
+ {
+ errno = REPORT_ERROR_NAME;
+ return -1;
+ }
+ if (IsNameExistsInFiltersTable(distributorName))
+ {
+ errno = REPORT_ERROR_NAME_EXISTS;
+ return -1;
+ }
+ for (index=1; index<DistCounter; index++)
+ if (strcmp(Dist_Table[index].name,distributorName)==0)
+ {
+ if (SwitchAddRemove == REPORT_ADD)
+ {
+ if (Dist_Table[index].IsAlive)
+ {
+ errno = REPORT_ERROR_NAME_EXISTS;
+ return -1;
+ }
+ else
+ {
+ Dist_Table[index].IsAlive = true;
+ return index;
+ }
+ }
+ else /* Private severity disable */
+ {
+ if (Dist_Table[index].IsAlive)
+ {
+ Dist_Table[index].IsAlive = false;
+ return index;
+ }
+ else
+ {
+ errno = REPORT_ERROR_NAME_ALREADY_DISABLE;
+ return -1;
+ }
+ }
+ }
+ if (SwitchAddRemove == REPORT_REMOVE)
+ {
+ errno = REPORT_ERROR_NAME_NOT_EXISTS;
+ return -1; /* nothing to remove */
+ }
+ strcpy(Dist_Table[DistCounter].name,distributorName);
+ Dist_Table[DistCounter].IsAlive = true;
+ DistCounter++;
+ return (DistCounter-1);
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportAddDistributor
+ *
+ * Function : Add static distributor
+ *
+ * Notes :
+ *
+ * Parameters: distributorName - The name must be up to 10 letters long
+ *
+ * Return value: the new distributor handle, or -1 and thus:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_TABLE_FULL if there are already too
+ * many distributors,
+ * errno = REPORT_ERROR_NAME_EXISTS if the distributorName
+ * already exists.
+ **************************************************************************/
+DistributorHandle ReportAddDistributor(const char *distributorName)
+{
+ return ReportDistributor(distributorName,REPORT_ADD);
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportRemoveDistributor
+ *
+ * Function : Remove static distributor
+ *
+ * Notes : The distributor's messages will be discarded.
+ * Its name will be no longer seen in the distributor's list
+ * when the REP_CONTROL is typed in the Monitor.
+ *
+ * Parameters: distributorName - The severity's name must be up to 10
+ * letters long.
+ *
+ * Return value: OK; or ERROR and thus errno is set to one of the following:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_NAME_ALREADY_DISABLE if the distributor
+ * was already removed,
+ * errno = REPORT_ERROR_NAME_NOT_EXISTS if the distributorName
+ * not exists.
+ **************************************************************************/
+STATUS ReportRemoveDistributor(const char *distributorName)
+{
+ return ReportDistributor(distributorName,REPORT_REMOVE);
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportDistributorControl
+ *
+ * Function : Disable / enable the flow of reports given its static
+ * severity
+ *
+ * Notes : Disable reports using the constant REPORT_OFF
+ * Enable the reports using the constant REPORT_ON
+ *
+ * Return value: OK or ERROR if illegal Distributor
+ **************************************************************************/
+STATUS ReportDistributorControl(DistributorHandle Distributor, uint32_t SwitchOnOff)
+{
+ if ((Distributor > DistCounter) || (Distributor < 0))
+ return ERROR;
+ Dist_Table[Distributor].IsActive = (SwitchOnOff == REPORT_ON) ? true : false;
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportGetDistributorHandleByName
+ *
+ * Function : Get the severity handle given the severity's name
+ *
+ * Notes :
+ *
+ * Return value: the handle; or -1 if no such name
+ **************************************************************************/
+DistributorHandle ReportGetDistributorHandleByName(const char *distributorName)
+{
+ int index;
+
+ for (index = 0; index <= DistCounter; index++)
+ if (ReportStrCmp(distributorName,Dist_Table[index].name))
+ {
+ if (Dist_Table[index].IsAlive)
+ return index;
+ else
+ return -1; /* disable used */
+ }
+ return -1;
+}
+
+
+/***************************************************************************
+ *
+ * Name : GetDistributorParamsByHandle
+ *
+ * Function : Get the static severity details according to its handle
+ *
+ * Parameters : DistributorHandle - table entry
+ * name - buffer to contain the static severity's name
+ * IsActive - a reference to a boolean flag
+ *
+ * Notes : The name field must exceeds 10 bytes long
+ *
+ * Return value: OK or ERROR and then:
+ * errno = REPORT_ERROR_ILLEGAL_PARAMETER if no such entry
+ * errno = REPORT_ERROR_FILTER_NOT_ALIVE if the static
+ * severity has already removed.
+ **************************************************************************/
+STATUS GetDistributorParamsByHandle(uint32_t DistributorHandle, char *name, bool *IsActive)
+{
+ if (DistributorHandle >= DistCounter)
+ {
+ errno = REPORT_ERROR_ILLEGAL_PARAMETER;
+ return ERROR;
+ }
+ if ((Dist_Table[DistributorHandle].IsAlive) == false)
+ {
+ errno = REPORT_ERROR_FILTER_NOT_ALIVE;
+ return ERROR;
+ }
+ strcpy(name,Dist_Table[DistributorHandle].name);
+ *IsActive = Dist_Table[DistributorHandle].IsActive;
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportFd
+ *
+ * Function : Add or remove a file descriptor to/from the output distributor
+ *
+ * Notes :
+ *
+ * Parameters: fd - file descriptor. Supplied by the user
+ * SwitchAddRemove - REPORT_ADD to add the fd
+ * REPORT_REMOVE to remove it.
+ * Distributor - 0 if not concerned with any static
+ * severity, or the static severity's handle
+ * to set with the given fd
+ *
+ * Return value: OK or ERROR with:
+ * errno = REPORT_ERROR_NOT_ENOUGH_MEMORY if destination list
+ * is full
+ * errno = REPORT_ERROR_ILLEGAL_PARAMETER if (fd == -1) or
+ * not found if asked to remove
+ **************************************************************************/
+STATUS ReportFd(int fd, uint32_t SwitchAddRemove, DistributorHandle Distributor)
+{
+ int index = 0, i;
+
+ if (SwitchAddRemove == REPORT_ADD)
+ {
+ index = FindFreeDestinationElement(Distributor);
+ /* check for the table overflow */
+ if (index == -1)
+ {
+ errno = REPORT_ERROR_NOT_ENOUGH_MEMORY;
+ return ERROR;
+ }
+ }
+ /* consistency check: don't add illegal fd */
+ if (fd == -1)
+ {
+ errno = REPORT_ERROR_ILLEGAL_PARAMETER;
+ return ERROR;
+ }
+
+ /* search for fd */
+ for( i = 0; i < NUM_OF_DESTINATIONS; i++ )
+ if ( Dist_Table[Distributor].dest[i].fd == fd )
+ break;
+
+ if (i == NUM_OF_DESTINATIONS)
+ {
+ if (SwitchAddRemove == REPORT_REMOVE)
+ {
+ errno = REPORT_ERROR_CODE_NOT_FOUND;
+ return ERROR;
+ }
+ /* Add fd */
+ /* add new destination to the end of the table */
+ Dist_Table[Distributor].dest[index].fd = fd;
+ /* set the function to NULL to ensure that destination is nothing but fd */
+ Dist_Table[Distributor].dest[index].function = NULL;
+ }
+ else if (SwitchAddRemove == REPORT_ADD)
+ return OK; /* this fd is already exists in the table */
+ else /* Remove fd */
+ Dist_Table[Distributor].dest[i].fd = -1;
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportFunc
+ *
+ * Function : Add or remove an output routine to/from the distributor
+ *
+ * Notes :
+ *
+ * Parameters: func - hook to the routine. Supplied by the user .
+ * SwitchAddRemove - REPORT_ADD to add the hook
+ * REPORT_REMOVE to remove it.
+ * Distributor - Set 0 if not concerned with any static
+ * severity, or give the static severity's
+ * handle to set with the given fd.
+ *
+ * Return value: OK or ERROR with:
+ * errno = REPORT_ERROR_NOT_ENOUGH_MEMORY if destination list
+ * is full
+ * errno = REPORT_ERROR_ILLEGAL_PARAMETER if (func == NULL)
+ **************************************************************************/
+STATUS ReportFunc(ReportFunction func, uint32_t SwitchAddRemove, DistributorHandle Distributor)
+{
+ int index = 0, i;
+
+ if (SwitchAddRemove == REPORT_ADD)
+ {
+ index = FindFreeDestinationElement(Distributor);
+ /* check for the table overflow */
+ if (index == -1)
+ {
+ errno = REPORT_ERROR_NOT_ENOUGH_MEMORY;
+ return ERROR;
+ }
+ }
+ /* consistency check: don't add illegal pointer */
+ if( func == NULL )
+ {
+ errno = REPORT_ERROR_ILLEGAL_PARAMETER;
+ return ERROR;
+ }
+
+ /* search for func - if already exists */
+ for( i = 0; i < NUM_OF_DESTINATIONS; i++ )
+ if (Dist_Table[Distributor].dest[i].function == func)
+ break;
+
+ if (i == NUM_OF_DESTINATIONS)
+ {
+ if (SwitchAddRemove == REPORT_REMOVE) /* nothing to remove */
+ {
+ errno = REPORT_ERROR_CODE_NOT_FOUND;
+ return ERROR;
+ }
+ /* Add routine */
+ /* add new destination to the end of the table */
+ Dist_Table[Distributor].dest[index].function = func;
+ /* set the fd to illegal value to ensure that destination is nothing but function */
+ Dist_Table[Distributor].dest[index].fd = -1;
+ }
+ else if (SwitchAddRemove == REPORT_ADD)
+ return OK; /* this routine is already exists in the table */
+ else /* Remove routine */
+ Dist_Table[Distributor].dest[i].function = NULL;
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportMessage2Dist
+ *
+ * Function : Report a message to the appropriate distributor
+ *
+ * Notes : The distributor handle should be passed using the macro
+ * SET_PRIVATE_DISTRIBUTOR
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+STATUS ReportMessage2Dist(DistributorHandle distributor, const char *message)
+{
+ return reportDistribute(MESSAGE_FORMAT, message,NULL, 0, 0, distributor, 0, 0);
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportMonitorFunc
+ *
+ * Function : Add/remove an output routine that prints to the monitor
+ *
+ * Notes : Hiding Report messages from appearing on the monitor is
+ * enable when the HALT> prompt is shown (by pressing <ENTER>).
+ * The filtering is done using an internal routine.
+ * This routine can be added/removed using this call.
+ * It can be added either to the regular distributor or to the
+ * distributor of each of the static severities.
+ *
+ * Parameters: SwitchAddRemove - REPORT_ADD to add the routine
+ * REPORT_REMOVE to remove it.
+ * Distributor - Set 0 if not concerned with any static
+ * severity, or give the static severity's
+ * handle to set with it .
+ *
+ * Return value: void
+ **************************************************************************/
+/*void ReportMonitorFunc(uint32_t SwitchAddRemove, uint32_t Distributor)
+{
+ switch (SwitchAddRemove)
+ {
+ case REPORT_ADD:
+ ReportFunc(MonitorFuncRoutine, REPORT_ADD, Distributor);
+ break;
+ case REPORT_REMOVE:
+ ReportFunc(MonitorFuncRoutine, REPORT_REMOVE, Distributor);
+ break;
+ }
+}
+*/
+
+/*------------- messageDistribute ------------------------*/
+/*
+ * Forward message to all destinations.
+ *
+ * Parameters:
+ * void* msg - address of the message
+ * int len - message length
+ *
+ * Returns:
+ * None
+ *
+ */
+
+static void messageDistribute(char *msg,
+ int DistTableEntry,
+ char *FileName,
+ int LineNumber,
+ int errorCode,
+ int parameter1,
+ int parameter2)
+{
+ int index;
+
+ /* pass through the table and send message to destination.
+ Assume for consistency: when the destination is fd,
+ it should not be -1 and function must be NULL.
+ If the destination is function, it's address must not be NULL
+ and fd should be -1 */
+ for (index = 0; index < NUM_OF_DESTINATIONS; index++ )
+ {
+ if (Dist_Table[DistTableEntry].dest[index].function != NULL)
+ Dist_Table[DistTableEntry].dest[index].function(msg,FileName,LineNumber,errorCode,parameter1,parameter2);
+ }
+}
+
+
+/*------------- reportFormat --------------------------*/
+/*
+ * The function converts mesage with error type, code, etc. into string
+ * with length using the following format (example):
+ * "H/W Error #12,05,01: Bus error (0xffde,0x1234)"
+ *
+ * Parameters:
+ * char* buffer - buffer to store the formatted message
+ * int* maxlen - length of the buffer. If the estimated length
+ * of the formatted message exceeds maxlen,
+ * function returns ERROR, set errno to
+ * REPORT_ERROR_NOT_ENOUGH_MEMORY and buffer left unchanged.
+ * char* message - user message
+ * UNIT16 extErrorType - error type and severity
+ * ERRORCODE errorCode - error code
+ * uint32_t32 parameter1 - user parameter 1
+ * uint32_t32 parameter2 - user parameter 2
+ *
+ */
+
+//STATUS reportFormat(char *buffer,
+// int *maxlen,
+// const char *message,
+// int errorCode,
+// ErrorSeverity severity,
+// int parameter1,
+// int parameter2)
+//{
+// int DstrTableEntry;
+// char *name;
+// static char* severities[8] = {"Message","Warning","","Error","","","","Fatal error"};
+//
+// /* Total message length w/o text is REPORT_MSG_FORMAT_LEN bytes */
+// int msgLen = strlen(message) + REPORT_MSG_FORMAT_LEN;
+//
+// /* check if message fit the supplied buffer */
+// if (*maxlen < msgLen)
+// {
+// errno = REPORT_ERROR_NOT_ENOUGH_MEMORY;
+// return ERROR;
+// }
+// /* Format message.
+// ATTENTION: DON'T forget to change REPORT_MSG_FORMAT_LEN
+// when changing the format string */
+// if (SEVERITY_MASK(severity) == RpPrivate)
+// {
+// DstrTableEntry = (severity >> 5);
+// if (Dist_Table[DstrTableEntry].IsAlive == false)
+// {
+// errno = REPORT_ERROR_ILLEGAL_PARAMETER;
+// return ERROR;
+// }
+// name = Dist_Table[DstrTableEntry].name;
+// }
+// else
+// name = severities[severity-1];
+//
+// *maxlen = sprintf(buffer,"%s: #%d: %s (0x%x,0x%x)\r\n",name,errorCode,message,parameter1,parameter2);
+// return OK;
+//}
+
+
+/***************************************************************************
+ *
+ * Name : FindFreeDestinationElement
+ *
+ * Function : Find Free Destination Element.
+ *
+ * Notes :
+ *
+ * Return value: index if found , ERROR - otherwise
+ **************************************************************************/
+int FindFreeDestinationElement(int DistTableEntry)
+{
+ int index;
+
+ for (index=0; index<NUM_OF_DESTINATIONS; index++)
+ if ((Dist_Table[DistTableEntry].dest[index].fd == -1) &&
+ (Dist_Table[DistTableEntry].dest[index].function == NULL))
+ return index;
+
+ return ERROR;
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportStrCmp
+ *
+ * Function : compare between two string with case-insensitive.
+ *
+ * Notes :
+ *
+ * Return value: true - strings are identical; false - otherwise
+ **************************************************************************/
+bool ReportStrCmp(const char *str1, const char *str2)
+{
+ int i=0;
+
+ while ((str1[i] != '\0') || (str2[i] != '\0'))
+ {
+ if (tolower(str1[i]) != tolower(str2[i]))
+ return false;
+ i++;
+ }
+ if ((str1[i] == '\0') && (str2[i] == '\0'))
+ return true;
+ return false;
+}
+
+
+/***************************************************************************
+ *
+ * Name : IsNameExistsInDistributorTable
+ *
+ * Function : Check if a given name is already found in the table
+ * of the static severities
+ *
+ * Notes :
+ *
+ * Return value: true if found; false otherwise
+ **************************************************************************/
+bool IsNameExistsInDistributorTable(const char *name)
+{
+ int index;
+
+ for (index=0; index<=DistCounter; index++)
+ if (ReportStrCmp(name,Dist_Table[index].name) == true)
+ return true;
+ return false;
+
+}
+
+
diff --git a/Software/Embedded_SW/Embedded/Common/report/distributor.h b/Software/Embedded_SW/Embedded/Common/report/distributor.h
new file mode 100644
index 000000000..4b7f9185a
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/report/distributor.h
@@ -0,0 +1,94 @@
+
+#ifndef __RDISTRIBUTOR_H__
+#define __RDISTRIBUTOR_H__
+
+/* The following enum is to inform about the kind of message format. For example:
+ * MESSAGE_FORMAT: this is a message
+ * REPORT_FORMAT: distributor.h.7, Error: this is a message. 0, (0x0,0x1) */
+typedef enum { MESSAGE_FORMAT, REPORT_FORMAT } FormatType;
+
+/* Use the following macro in order to get the private severity as the */
+/* severity parameter from one of the Report routines */
+#define GET_PRIVATE_SEVERITY(handle) (DistributorHandle)((handle)>>5)
+
+/* The mask of currently enabled severity. */
+extern bool filterTest(ErrorSeverity severity);
+
+extern STATUS distibutorInit( int priority, int maxMsgs, int maxDestinations );
+
+extern STATUS reportDistribute(FormatType format,
+ const char *message,
+ char *FileName,
+ int LineNumber,
+ int errorCode,
+ ErrorSeverity severity,
+ int parameter1,
+ int parameter2);
+
+
+/***************************************************************************
+ *
+ * Name : ReportStrCmp
+ *
+ * Function : compare between two string with case-insensitive.
+ *
+ * Notes :
+ *
+ * Return value: TRUE - strings are identical; FALSE - otherwise
+ **************************************************************************/
+extern bool ReportStrCmp(const char *str1, const char *str2);
+
+
+/***************************************************************************
+ *
+ * Name : IsNameExistsInDistributorTable
+ *
+ * Function : Check if a given name is already found in the table
+ * of the private severities
+ *
+ * Notes :
+ *
+ * Return value: TRUE if found; FALSE otherwise
+ **************************************************************************/
+extern bool IsNameExistsInDistributorTable(const char *name);
+
+/***************************************************************************
+ *
+ * Name : ReportGetDistributorHandleByName
+ *
+ * Function : Get the severity handle given the severity's name
+ *
+ * Notes :
+ *
+ * Return value: the handle; or -1 if no such name
+ **************************************************************************/
+extern DistributorHandle ReportGetDistributorHandleByName(const char *distributorName);
+
+
+/***************************************************************************
+ *
+ * Name : GetDistributorParamsByHandle
+ *
+ * Function : Get the private severity details according to its handle
+ *
+ * Parameters : DistributorHandle - table entry
+ * name - buffer to contain the private severity's name
+ * IsActive - FALSE if the private severity
+ *
+ * Notes : The name field must exceeds 10 bytes long
+ *
+ * Return value: OK or ERROR and then:
+ * errno = REPORT_ERROR_ILLEGAL_PARAMETER if no such entry
+ * errno = REPORT_ERROR_FILTER_NOT_ALIVE if the private
+ * severity has already removed (and thus it is no
+ * no longer exists until re-added).
+ **************************************************************************/
+extern STATUS GetDistributorParamsByHandle(uint32_t DistributorHandle,
+ char *name,
+ bool *IsActive);
+/* Total message length w/o message text in bytes
+ (for reportMsgFormat function ) */
+#define REPORT_MSG_FORMAT_LEN 61
+
+#endif /* __RDISTRIBUTOR_H__ */
+
diff --git a/Software/Embedded_SW/Embedded/Common/report/filter.c b/Software/Embedded_SW/Embedded/Common/report/filter.c
new file mode 100644
index 000000000..7efc56d36
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/report/filter.c
@@ -0,0 +1,526 @@
+ /*+*************************************************************************
+ * File name : FILTER.C
+ * Title : TERMINAL DRIVER INTERFACE
+ * Project : NEVADA
+ * Subsystem : SYSTEM
+ * Date created: 18 SEP, 1997
+ * Revision : Rev 1.0
+ * Author : Zvika Zilberman
+ * History : 18.09.97 Zvika Zilberman - porting to DCME SWINFRA
+ *
+ * Description : This file includes the FILTER part of the report package
+ *
+ *
+ * Procedures:
+ *
+ * Report - Report message using filters and message multiplexing.
+ * ReportSeveritySet - Set message severity
+ *
+ ******************************************************************************/
+
+#include "report.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "stdint.h" /* RETCODE */
+#include "filter.h"
+#include "distributor.h" /* reportDistribute */
+
+#define MAX_STRING_LEN 255
+
+/*------------- Local Data ------------------------------*/
+
+/* the filter's table */
+
+packageFilter *packageFilterTable;
+uint8_t filterTableSize;
+uint8_t filterNumOfCurrentEntries;
+
+/* The mask of currently enabled severity. */
+static ErrorSeverity SeverityLevel;
+
+/* flag allows or dennies filter usage */
+static bool filterDontUse;
+
+
+/***************************************************************************
+ *
+ * Name : filterTableInit
+ *
+ * Function : Init the filtering mechanism
+ *
+ * Notes :
+ *
+ * Return value: OK; ERROR if malloc is failed
+ **************************************************************************/
+STATUS filterTableInit(uint32_t TableSize)
+{
+ int index;
+
+ filterTableSize = TableSize;
+ packageFilterTable = (packageFilter*)malloc(sizeof(packageFilter)*TableSize);
+ if (packageFilterTable == NULL)
+ return ERROR;
+ for (index=0; index<TableSize; index++)
+ packageFilterTable[index].IsActive = true;
+ filterNumOfCurrentEntries = 0;
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportFilterPackage
+ *
+ * Function : Add or remove a filter to/from the filter's data base
+ *
+ * Notes :
+ *
+ * Parameters : filterName - The filter's name must be up to 10 letters
+ * long
+ * SwitchAddRemove - REPORT_ADD to add the new filter,
+ * REPORT_REMOVE to remove it.
+ *
+ * Return value: the new filter handle; or -1 in case of an ERROR, thus:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_TABLE_FULL if there are already too
+ * many filters,
+ * errno = REPORT_ERROR_NAME_EXISTS if the filterName already exists.
+ **************************************************************************/
+int ReportFilterPackage(const char *filterName, uint8_t SwitchAddRemove)
+{
+ int index;
+
+ if ((filterNumOfCurrentEntries == filterTableSize) && (SwitchAddRemove == REPORT_ADD))
+ {
+ errno = REPORT_ERROR_TABLE_FULL;
+ return -1;
+ }
+ else if (strlen(filterName) > 10)
+ {
+ errno = REPORT_ERROR_NAME_TOO_LONG;
+ return -1;
+ }
+ else if ((IsNameExistsInDistributorTable(filterName)) && (SwitchAddRemove == REPORT_ADD))
+ {
+ errno = REPORT_ERROR_NAME_EXISTS;
+ return -1;
+ }
+ for (index=0; index<filterNumOfCurrentEntries; index++)
+ if (ReportStrCmp(packageFilterTable[index].filterName,filterName))
+ {
+ if (SwitchAddRemove == REPORT_ADD)
+ {
+ if (packageFilterTable[index].IsActive)
+ {
+ errno = REPORT_ERROR_NAME_EXISTS;
+ return -1;
+ }
+ else
+ {
+ packageFilterTable[index].IsActive = true;
+ return index;
+ }
+ }
+ else /* Filter disable */
+ {
+ if (packageFilterTable[index].IsActive)
+ {
+ packageFilterTable[index].IsActive = false;
+ return index;
+ }
+ else
+ {
+ errno = REPORT_ERROR_NAME_ALREADY_DISABLE;
+ return -1;
+ }
+ }
+ }
+ if (SwitchAddRemove == REPORT_REMOVE)
+ {
+ errno = REPORT_ERROR_NAME_NOT_EXISTS;
+ return -1; /* nothing to remove */
+ }
+ strcpy(packageFilterTable[filterNumOfCurrentEntries].filterName,filterName);
+ packageFilterTable[filterNumOfCurrentEntries].filterDontUse = true;
+ filterNumOfCurrentEntries++;
+ return (filterNumOfCurrentEntries-1);
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportAddFilterPackage
+ *
+ * Function : Add a package filter to the package filter's data base
+ *
+ * Notes :
+ *
+ * Parameters : filterName - The filter's name must be up to 10 letters
+ * long
+ *
+ * Return value: the new filter handle; or -1 in case of an ERROR, thus:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_TABLE_FULL if there are already too
+ * many filters,
+ * errno = REPORT_ERROR_NAME_EXISTS if the filterName already exists.
+ **************************************************************************/
+PackageHandle ReportAddFilterPackage(const char *filterName)
+{
+ return ReportFilterPackage(filterName, REPORT_ADD);
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportRemoveFilterPackage
+ *
+ * Function : Remove a package filter from the package filter's data base
+ *
+ * Notes :
+ *
+ * Parameters : filterName - The filter's name must be up to 10 letters
+ * long
+ *
+ * Return value: OK; or ERROR and thus errno is set to one of the following:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_NAME_ALREADY_DISABLE if the filter was
+ * already removed,
+ * errno = REPORT_ERROR_NAME_NOT_EXISTS if the filterName not exists.
+ **************************************************************************/
+STATUS ReportRemoveFilterPackage(const char *filterName)
+{
+ return ReportFilterPackage(filterName, REPORT_REMOVE);
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportSwitchPackageFilter
+ *
+ * Function : Switch the filter of the given handle
+ *
+ * Notes : REPORT_ON - filter is active. messages do not discarded.
+ * REPORT_OFF - filter is not active. Its messages are discarded.
+ *
+ * Return value: OK; or ERROR if wrong handle
+ **************************************************************************/
+STATUS ReportSwitchPackageFilter(PackageHandle ReportPackageHandle, uint32_t SwitchOnOff)
+{
+ if (ReportPackageHandle >= filterNumOfCurrentEntries)
+ return ERROR;
+ packageFilterTable[ReportPackageHandle].filterDontUse = (SwitchOnOff == REPORT_OFF);
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : GetFilterParamsByHandle
+ *
+ * Function : Get the filter details according to its handle
+ *
+ * Notes : filterNameBuf must exceeds 10 bytes long
+ *
+ * Return value: OK; or ERROR if wrong handle
+ **************************************************************************/
+STATUS GetFilterParamsByHandle(uint32_t filterHandle,
+ packageFilter *pPackage)
+{
+ if (filterHandle >= filterNumOfCurrentEntries)
+ return ERROR;
+ strcpy(pPackage->filterName,packageFilterTable[filterHandle].filterName);
+ pPackage->filterDontUse = packageFilterTable[filterHandle].filterDontUse;
+ pPackage->IsActive = packageFilterTable[filterHandle].IsActive;
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : GetFilterHandleByName
+ *
+ * Function : Get the filter handle given the filter's name
+ *
+ * Notes :
+ *
+ * Return value: the handle; or -1 if no such name
+ **************************************************************************/
+int ReportGetFilterHandleByName(const char *filterName)
+{
+ int index;
+
+ for (index = 0; index < filterNumOfCurrentEntries; index++)
+ if (ReportStrCmp(filterName,packageFilterTable[index].filterName) == true)
+ {
+ if (packageFilterTable[index].IsActive)
+ return index;
+ else
+ return -1; /* disable used */
+ }
+ return -1;
+}
+
+
+/***************************************************************************
+ *
+ * Name : IsNameExistsInFiltersTable
+ *
+ * Function : Check if a given name is already found in the filter's
+ * table.
+ *
+ * Notes :
+ *
+ * Return value: true if found; false otherwise
+ **************************************************************************/
+bool IsNameExistsInFiltersTable(const char *name)
+{
+ int index;
+
+ for (index = 0; index < filterNumOfCurrentEntries; index++)
+ if (ReportStrCmp(name,packageFilterTable[index].filterName) == true)
+ return true;
+ return false;
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportFilterTest
+ *
+ * Function : Test the filter's handle to check if to report or not
+ *
+ * Notes :
+ *
+ * Return value: true - discard the report; false - report.
+ **************************************************************************/
+bool ReportFilterTest(uint8_t filterHandle)
+{
+ if (filterHandle >= filterNumOfCurrentEntries)
+ return false;
+ return (packageFilterTable[filterHandle].filterDontUse);
+}
+
+
+bool filterTest(ErrorSeverity severity)
+{
+ if (filterDontUse)
+ return true; /* The filter machnism is disabled - */
+ /* all errors are enabled */
+ if( SeverityLevel <= severity ) /* check for severity */
+ return true;
+
+ return false;
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportSeveritySet
+ *
+ * Function : Determine the filter level of the message's severity
+ *
+ * Notes : Messages with severity below this level wont be sent to
+ * their output
+ *
+ * Return value: void
+ **************************************************************************/
+void ReportSeveritySet(ErrorSeverity level)
+{
+ SeverityLevel = level;
+}
+
+
+/***************************************************************************
+ *
+ * Name : Report
+ *
+ * Function : PEPORT main routine
+ *
+ * Notes :
+ *
+ * Parameters: message - user's message
+ * errorCode - should be the return code of the routine that
+ * failed and made this report
+ * severity - the error level
+ * parameter1 - user params no.1 (for additional information)
+ * parameter2 - another user params.
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+STATUS Report(const char *message,
+ char *FileName,
+ int LineNumber,
+ int errorCode,
+ ErrorSeverity severity,
+ int parameter1,
+ int parameter2)
+{
+
+ /* if message passes the filter send it to distributor */
+ if (filterTest(severity) || (GET_PRIVATE_SEVERITY(severity) > 0))
+ return reportDistribute(REPORT_FORMAT,
+ message,
+ FileName,
+ LineNumber,
+ errorCode,
+ severity,
+ parameter1,
+ parameter2);
+ return OK;
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportMessage2SysDist
+ *
+ * Function : Report a message to the System Distributor
+ *
+ * Notes : The severity of this report is always <Message>
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+/*STATUS ReportMessage2SysDist(const char *message)
+{
+ if (filterTest(RpMessage) == false)
+ return OK;
+ return reportDistribute(MESSAGE_FORMAT, message,NULL,0, 0, RpMessage, 0, 0);
+}
+
+STATUS ReportMessage(const char *message)
+{
+ if (filterTest(RpMessage) == false)
+ return OK;
+ return reportDistribute(MESSAGE_FORMAT, message, NULL, 0,0, RpMessage, 0, 0);
+}
+
+*/
+/***************************************************************************
+ *
+ * Name : ReportPackageMessage2SysDist
+ *
+ * Function : Report a message to the System distributor if the handle
+ * is not filtered
+ *
+ * Notes : The severity of this report is always <Message>
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+/*STATUS ReportPackageMessage2SysDist(PackageHandle ReportPackageHandle, const char *message)
+{
+ if (filterTest(RpMessage) == false)
+ return OK;
+ if (ReportFilterTest(ReportPackageHandle))
+ return OK;
+ return ReportMessage2SysDist(message);
+}
+*/
+
+/***************************************************************************
+ *
+ * Name : ReportFormatMessage2SysDist
+ *
+ * Function : Report a formatted message (like printf) to the System
+ * distributor
+ *
+ * Notes : The severity of this report is always <Message>
+ * IMPORTANT: the formatting is done in the context of the
+ * calling application!!
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+/*STATUS ReportFormatMessage2SysDist(const char *format, ...)
+{
+ static char text[MAX_STRING_LEN];
+ va_list ap;
+
+ if (filterTest(RpMessage) == false)
+ return OK;
+
+ va_start (ap , format );
+ vsprintf ( text , format , ap );
+ va_end ( ap );
+ return reportDistribute(MESSAGE_FORMAT, text, NULL,0,0, RpMessage, 0, 0);
+}
+
+STATUS Reportf(const char *format, ...)
+{
+ static char text[MAX_STRING_LEN];
+ va_list ap;
+
+ if (filterTest(RpMessage) == false)
+ return OK;
+
+ va_start (ap , format );
+ vsprintf ( text , format , ap );
+ va_end ( ap );
+ return reportDistribute(MESSAGE_FORMAT, text, NULL,0,0, RpMessage, 0, 0);
+}
+
+*/
+/***************************************************************************
+ *
+ * Name : ReportWithFilter
+ *
+ * Function : PEPORT with filter - main routine
+ *
+ * Notes : It is recommended to use one of the macros below instead
+ * of using this routine directly. This is because the macros
+ * support other benefits such: file name, line number etc.
+ *
+ * Parameters: handle - filter's handle
+ * message - user's message
+ * errorCode - should be the return code of the routine that
+ * failed and made this report
+ * severity - the error level
+ * parameter1 - user params no.1 (for additional information)
+ * parameter2 - another user param.
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+STATUS ReportWithPackageFilter(PackageHandle ReportPackageHandle,
+ const char *message,
+ char *FileName,
+ int LineNumber,
+ int errorCode,
+ ErrorSeverity severity,
+ int parameter1,
+ int parameter2)
+{
+ if (ReportFilterTest(ReportPackageHandle))
+ return OK; /* discard message */
+ return Report(message,FileName,LineNumber,errorCode,severity,parameter1,parameter2);
+}
+
+
+/***************************************************************************
+ *
+ * Name : ReportFormatPackageMessage2SysDist
+ *
+ * Function : Report a formatted message (like printf) to the output
+ * if handle is not filtered
+ *
+ * Notes : The severity of this report is always <Message>
+ * IMPORTANT: the formatting is done in the context of the
+ * calling task!!
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+/*STATUS ReportFormatPackageMessage2SysDist(PackageHandle ReportPackageHandle,
+ const char *format, ...)
+{
+ static char text[MAX_STRING_LEN];
+ va_list ap;
+
+ if (ReportFilterTest(ReportPackageHandle))
+ return OK;
+ if (filterTest(RpMessage) == false)
+ return OK;
+ va_start (ap , format );
+ vsprintf ( text , format , ap );
+ va_end ( ap );
+ return reportDistribute(MESSAGE_FORMAT, text, NULL,0,0, RpMessage, 0, 0);
+}*/
+
diff --git a/Software/Embedded_SW/Embedded/Common/report/filter.h b/Software/Embedded_SW/Embedded/Common/report/filter.h
new file mode 100644
index 000000000..481f6cb66
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/report/filter.h
@@ -0,0 +1,74 @@
+
+#ifndef __RFILTER_H__
+#define __RFILTER_H__
+
+/* the type definition of the filter per package */
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef struct packageFilter {
+ char filterName[11]; /* up to 10 letter of filter's name */
+ bool filterDontUse; /* TRUE - dont use. FALSE - send to report */
+ bool IsActive; /* TRUE - can be used. FALSE - disable it */
+} packageFilter;
+
+/***************************************************************************
+ *
+ * Name : filterTableInit
+ *
+ * Function : Init the filtering mechanism
+ *
+ * Notes :
+ *
+ * Return value: OK; ERROR if malloc is failed
+ **************************************************************************/
+extern STATUS filterTableInit(uint32_t TableSize);
+
+
+/***************************************************************************
+ *
+ * Name : GetFilterParamsByHandle
+ *
+ * Function : Get the filter details according to its handle
+ *
+ * Notes : filterNameBuf must exceeds 10 bytes long
+ *
+ * Return value: OK; or ERROR if wrong handle
+ **************************************************************************/
+extern STATUS GetFilterParamsByHandle(uint32_t filterHandle,
+ packageFilter *pPackage);
+
+
+/***************************************************************************
+ *
+ * Name : IsNameExistsInFiltersTable
+ *
+ * Function : Check if a given name is already found in the filter's
+ * table.
+ *
+ * Notes :
+ *
+ * Return value: TRUE if found; FALSE otherwise
+ **************************************************************************/
+extern bool IsNameExistsInFiltersTable(const char *name);
+
+
+/***************************************************************************
+ *
+ * Name : GetFilterHandleByName
+ *
+ * Function : Get the filter handle given the filter's name
+ *
+ * Notes :
+ *
+ * Return value: the handle; or -1 if no such name (or filter was removed).
+ **************************************************************************/
+extern int ReportGetFilterHandleByName(const char *filterName);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RFILTER_H__ */
+
diff --git a/Software/Embedded_SW/Embedded/Common/report/report.h b/Software/Embedded_SW/Embedded/Common/report/report.h
new file mode 100644
index 000000000..d98844d71
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/report/report.h
@@ -0,0 +1,593 @@
+/******************************************************************************
+ * File name : REPORT.H
+ * Title : INFRA REPORT PACKAGE - Application Interface
+ * Date created : 16 SEP, 1997
+ * Revision : 2.0
+ * Author : Zvika Zilberman
+ *
+ * Description : This package provides services for reporting and
+ * debug tracing. The package includes:
+ * - Error coding convention definitions
+ * - Message report interface
+ * - Message filtering interface
+ * - Message distributor interface
+ * - Compatibility with UT_EXCEPTION package
+ *
+ ******************************************************************************
+ *
+ * History:
+ * 01.05.96 Roie Geron - first cut
+ * 01.09.96 Ilia Maller - start of coding
+ * 21.02.97 Ilia Maller - minor improvements
+ * 16.09.97 Zvika Zilberman - porting to DCME SWINFRA (0200 - 0240)
+ * 29.07.98 Zvika Zilberman - approach to new generation (0300 - 0320)
+ * 10.11.98 Zvika Zilberman - update the new generation (0330)
+ *
+ ******************************************************************************
+ * Dependencies of SWINFRA packages:
+ * Terminal
+ * Monitor
+ ******************************************************************************/
+
+#ifndef __REPORT_H__
+#define __REPORT_H__
+
+
+/*---------------------------- Includes ---------------------------------------*/
+
+#include "include.h"
+#include <assert.h> /* _ASSET_STR */
+#include "PMR/common/MessageContainer.pb-c.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*#define OK 0
+#define ERROR -1
+//#define FALSE false
+//#define TRUE true
+#define OFF 0
+#define ON 1
+*/
+#define RET_NOTOK -1
+#define RET_OK 0
+typedef int STATUS;
+/*--------------------------- Type definitions -------------------------------*/
+
+/* This following redefinition is the filter level. Reports with lower severity than */
+/* the filter's one, won't be sent to the output. */
+typedef int ErrorSeverity;
+
+#define RpMessage 0x1
+#define RpWarning 0x2
+#define RpError 0x4
+#define RpFatalError 0x8
+#define RpPrivate 0x10
+typedef int DistributorHandle;
+typedef int PackageHandle;
+
+#define REPORT_MAX_MSG_LEN 128
+
+/* Use the following macro in order to pass the private severity as the */
+/* severity parameter to one of the Report routines */
+#define SET_PRIVATE_DISTRIBUTOR(handle) (ErrorSeverity)(Private | ((handle)<<5))
+
+/* The following are some constant for control and manipulation throughout the */
+/* Report's control routines */
+#define REPORT_OFF 0
+#define REPORT_ON 1
+#define REPORT_REMOVE 0
+#define REPORT_ADD 1
+
+/* This is a prototype of the output hook. When adding a function to the distributor, */
+/* the routine's prototype should be the same as here */
+typedef int (* ReportFunction)(char *message, /* The formatted message */
+ char *FileName,
+ int LineNumber,
+ int errorCode, /* error code that caused the report */
+ int parameter1, /* user parameter no. 1 */
+ int parameter2); /* user parameter no. 2 */
+
+/* Initialization struct. Default values are below */
+typedef struct{
+ int DistributorTaskPriority; /* The report task's priority */
+ int DistributorQueueMaxMsgs; /* Maximum number of messages in the queue */
+ int MaxNumberOfPrivateDistributors; /* Maximum number of private distributor */
+ int MaxNumOfFilterNames; /* Maximum number of filters to enable the applica */
+}ReportInitParams;
+/* these values can be used as default in the above package configuration */
+#define REPORT_TASK_PRIORITY 150
+#define REPORT_MAX_FILTER_PACKAGES 20
+#define REPORT_QUEUE_MAX_MSGS 100
+
+
+/*----------------------------------------------------------------------------*/
+/*---------------------- Report Tracing and Exceptions -----------------------*/
+/*---------------------------- without filtering -----------------------------*/
+/*----------------------------------------------------------------------------*/
+//void SendStatusResponse (uint32_t Code, char *Token);
+/***************************************************************************
+ *
+ * Name : ReportInit
+ *
+ * Function : PEPORT library init
+ *
+ * Notes : Should be called before any other function from the Report
+ * package.
+ *
+ * Return value: OK or ERROR if malloc has failed or task creation has
+ * failed
+ **************************************************************************/
+extern STATUS ReportInit(ReportInitParams InitParams);
+extern uint32_t ReportInitMessage(MessageContainer* requestContainer);
+
+/***************************************************************************
+ *
+ * Name : Report
+ *
+ * Function : PEPORT main routine
+ *
+ * Notes : It is recommended to use one of the macros below (Debug
+ * Tracing ) instead of using this routine directly. This
+ * is because the macros support other benefits such: file
+ * name, line number etc.
+ *
+ * Parameters: message - user's message
+ * errorCode - should be the return code of the routine that
+ * failed and made this report
+ * severity - the error level
+ * parameter1 - user params no.1 (for additional information)
+ * parameter2 - another user param.
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+extern STATUS Report(const char *message,
+ char *FileName,
+ int LineNumber,
+ int errorCode,
+ ErrorSeverity severity,
+ int parameter1,
+ int parameter2);
+
+
+/***************************************************************************
+ *
+ * Name : ReportMessage2SysDist
+ *
+ * Function : Report a message to the System distributor
+ *
+ * Notes : The severity of this report is always <Message>
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+extern STATUS ReportMessage2SysDist(const char *message);
+
+
+/***************************************************************************
+ *
+ * Name : ReportFormatMessage2SysDist
+ *
+ * Function : Report a formatted message (like printf) to the System
+ * distributor
+ *
+ * Notes : The severity of this report is always <Message>
+ * IMPORTANT: the formatting is done in the context of the
+ * calling task!!
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+extern STATUS ReportFormatMessage2SysDist(const char *format, ...);
+
+
+/***************************************************************************
+ *
+ * Name : ReportMessage2Dist
+ *
+ * Function : Report a message to the appropriate distributor
+ *
+ * Notes : The distributor handle should be passed using the macro
+ * SET_PRIVATE_DISTRIBUTOR
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+extern STATUS ReportMessage2Dist(DistributorHandle distributor, const char *message);
+
+
+/***************************************************************************
+ *
+ * Name : REPORT_ERR
+ *
+ * Function : Report an error
+ *
+ * Notes : Attention: this is a macro. Will add the file name & the
+ * line number where the error is reported
+ *
+ * Parameters : See above, Report.
+ *
+ * Return value: OK; or Report's return code
+ **************************************************************************/
+#define REPORT_ERR(msg, error, severity, par1, par2) \
+ Report(REPORT_LINE(msg), error, severity, par1, par2)
+
+
+/***************************************************************************
+ *
+ * Name : REPORT_IF_ERROR
+ *
+ * Function : if <condition> is TRUE then report an error
+ *
+ * Notes : Attention: this is a macro. Will add the file name & the
+ * line number where the error is reported
+ *
+ * Parameters : See above, Report.
+ *
+ * Return value: OK; or Report's return code
+ **************************************************************************/
+#define REPORT_IF_ERROR(condition, msg, error, severity, par1, par2) \
+ ((condition) ? Report(REPORT_LINE(msg), error, severity, par1, par2) : OK)
+
+/*----------------------------------------------------------------------------*/
+/*---------------------- Report Tracing and Exceptions -----------------------*/
+/*----------------------------- with filtering -------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/***************************************************************************
+ *
+ * Name : ReportWithPackageFilter
+ *
+ * Function : PEPORT with package filter - main routine
+ *
+ * Notes : It is recommended to use one of the macros below instead
+ * of using this routine directly. This is because the macros
+ * support other benefits such: file name, line number etc.
+ *
+ * Parameters: ReportPackageHandle - filter's handle
+ * message - user's message
+ * errorCode - should be the return code of the routine
+ * that failed and made this report
+ * severity - the error level
+ * parameter1 - user params no.1 (for additional
+ * information)
+ * parameter2 - another user param.
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+extern STATUS ReportWithPackageFilter(PackageHandle ReportPackageHandle,
+ const char *message,
+ char *FileName,
+ int LineNumber,
+ int errorCode,
+ ErrorSeverity severity,
+ int parameter1,
+ int parameter2);
+
+
+/***************************************************************************
+ *
+ * Name : ReportPackageMessage2SysDist
+ *
+ * Function : Report a message to the System distributor if the handle
+ * is not filtered
+ *
+ * Notes : The severity of this report is always <Message>
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+/*extern STATUS ReportPackageMessage2SysDist(PackageHandle ReportPackageHandle,
+ const char *message);
+*/
+
+/***************************************************************************
+ *
+ * Name : ReportFormatPackageMessage2SysDist
+ *
+ * Function : Report a formatted message (like printf) to the output
+ * if handle is not filtered
+ *
+ * Notes : The severity of this report is always <Message>
+ * IMPORTANT: the formatting is done in the context of the
+ * calling task!!
+ *
+ * Return value: OK or ERROR if failed to send to distributor
+ **************************************************************************/
+/*extern STATUS ReportFormatPackageMessage2SysDist(PackageHandle ReportPackageHandle,
+ const char *format, ...);
+*/
+
+/***************************************************************************
+ *
+ * Name : REPORT_ERR_FILTER
+ *
+ * Function : Report an error if handle is not filtered
+ *
+ * Notes : Attention: this is a macro. Will add the file name & the
+ * line number where the error is reported
+ *
+ * Parameters : See above, Report.
+ *
+ * Return value: OK; or Report's return code
+ **************************************************************************/
+#define REPORT_ERR_FILTER(handle, msg, FileName, LineNumber,error, severity, par1, par2) \
+ ReportWithPackageFilter(handle, REPORT_LINE(msg), FileName, LineNumber,error, severity, par1, par2)
+
+
+/***************************************************************************
+ *
+ * Name : REPORT_IF_ERROR_FILTER
+ *
+ * Function : if <condition> is TRUE and handle is not filtered
+ * then report an error
+ *
+ * Notes : Attention: this is a macro. Will add the file name & the
+ * line number where the error is reported
+ *
+ * Parameters : See above, Report.
+ *
+ * Return value: OK; or Report's return code
+ **************************************************************************/
+#define REPORT_IF_ERROR_FILTER(condition, handle, msg, FileName, LineNumber,error, severity, par1, par2) \
+ ((condition) ? REPORT_ERR_FILTER(handle,msg,FileName, LineNumber,error,severity,par1,par2) : OK)
+
+
+/***************************************************************************
+ *
+ * Name : ReportAddFilterPackage
+ *
+ * Function : Add a package filter to the package filter's data base
+ *
+ * Notes :
+ *
+ * Parameters : filterName - The filter's name must be up to 10 letters
+ * long
+ *
+ * Return value: The new filter handle; or -1 in case of an ERROR, thus:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_TABLE_FULL if there are already too
+ * many filters,
+ * errno = REPORT_ERROR_NAME_EXISTS if the filterName already exists.
+ **************************************************************************/
+extern PackageHandle ReportAddFilterPackage(const char *filterName);
+
+
+/***************************************************************************
+ *
+ * Name : ReportRemoveFilterPackage
+ *
+ * Function : Remove a package filter from the package filter's data base
+ *
+ * Notes :
+ *
+ * Parameters : filterName - The filter's name must be up to 10 letters
+ * long
+ *
+ * Return value: OK; or ERROR and thus errno is set to one of the following:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_NAME_ALREADY_DISABLE if the filter was
+ * already removed,
+ * errno = REPORT_ERROR_NAME_NOT_EXISTS if the filterName not exists.
+ **************************************************************************/
+extern STATUS ReportRemoveFilterPackage(const char *filterName);
+
+
+/***************************************************************************
+ *
+ * Name : ReportSwitchPackageFilter
+ *
+ * Function : Switch the filter of the given handle
+ *
+ * Notes : REPORT_ON - filter is active. messages do not discarded.
+ * REPORT_OFF - filter is not active. Its messages are discarded.
+ *
+ * Return value: OK; or ERROR if wrong handle
+ **************************************************************************/
+extern STATUS ReportSwitchPackageFilter(PackageHandle ReportPackageHandle, uint32_t SwitchOnOff);
+
+/*----------------------------------------------------------------------------*/
+/*---------------------------- Distributor -----------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/***************************************************************************
+ *
+ * Name : ReportAddDistributor
+ *
+ * Function : Add private distributor
+ *
+ * Notes :
+ *
+ * Parameters: distributorName - The name must be up to 10 letters long
+ *
+ * Return value: The new distributor handle, or -1 and thus:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_TABLE_FULL if there are already too
+ * many distributors,
+ * errno = REPORT_ERROR_NAME_EXISTS if the distributorName
+ * already exists.
+ **************************************************************************/
+extern DistributorHandle ReportAddDistributor(const char *distributorName);
+
+
+/***************************************************************************
+ *
+ * Name : ReportRemoveDistributor
+ *
+ * Function : Remove private distributor
+ *
+ * Notes : The distributor's messages will be discarded.
+ * Its name will be no longer seen in the distributor's list
+ * when the REP_CONTROL is typed in the Monitor.
+ *
+ * Parameters: distributorName - The severity's name must be up to 10
+ * letters long.
+ *
+ * Return value: OK; or ERROR and thus errno is set to one of the following:
+ * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name,
+ * errno = REPORT_ERROR_NAME_ALREADY_DISABLE if the distributor
+ * was already removed,
+ * errno = REPORT_ERROR_NAME_NOT_EXISTS if the distributorName
+ * not exists.
+ **************************************************************************/
+extern DistributorHandle ReportRemoveDistributor(const char *distributorName);
+
+
+/***************************************************************************
+ *
+ * Name : ReportDistributorControl
+ *
+ * Function : Disable / enable the flow of reports given its private
+ * severity
+ *
+ * Notes : Disable reports using the constant REPORT_OFF
+ * Enable the reports using the constant REPORT_ON
+ *
+ * Return value: OK or ERROR if illegal Distributor
+ **************************************************************************/
+extern STATUS ReportDistributorControl(DistributorHandle Distributor, uint32_t SwitchOnOff);
+
+/*----------------------------------------------------------------------------*/
+/*------------------------ Message Distributor -------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/***************************************************************************
+ *
+ * Name : ReportFd
+ *
+ * Function : Add or remove a file descriptor to/from the output distributor
+ *
+ * Notes :
+ *
+ * Parameters: fd - file descriptor. Supplied by the user
+ * SwitchAddRemove - REPORT_ADD to add the fd
+ * REPORT_REMOVE to remove it.
+ * Distributor - 0 if not concerned with any private
+ * severity, or the private severity's handle
+ * to set with the given fd
+ *
+ * Return value: OK or ERROR with:
+ * errno = REPORT_ERROR_NOT_ENOUGH_MEMORY if destination list
+ * is full
+ * errno = REPORT_ERROR_ILLEGAL_PARAMETER if (fd == -1) or
+ * not found if asked to remove
+ **************************************************************************/
+extern STATUS ReportFd(int fd, uint32_t SwitchAddRemove, DistributorHandle Distributor);
+
+
+/***************************************************************************
+ *
+ * Name : ReportFunc
+ *
+ * Function : Add or remove an output routine to/from the distributor
+ *
+ * Notes :
+ *
+ * Parameters: func - hook to the routine. Supplied by the user .
+ * SwitchAddRemove - REPORT_ADD to add the hook
+ * REPORT_REMOVE to remove it.
+ * Distributor - Set 0 if not concerned with any private
+ * severity, or give the private severity's
+ * handle to set with the given fd.
+ *
+ * Return value: OK or ERROR with:
+ * errno = REPORT_ERROR_NOT_ENOUGH_MEMORY if destination list
+ * is full
+ * errno = REPORT_ERROR_ILLEGAL_PARAMETER if (func == NULL)
+ **************************************************************************/
+extern STATUS ReportFunc(ReportFunction func,
+ uint32_t SwitchAddRemove,
+ DistributorHandle Distributor);
+
+
+/***************************************************************************
+ *
+ * Name : ReportMonitorFunc
+ *
+ * Function : Add/remove an output routine that prints to the monitor
+ *
+ * Notes : Hiding Report messages from appearing on the monitor is
+ * enable when the HALT> prompt is shown (by pressing <ENTER>).
+ * The filtering is done using an internal routine.
+ * This routine can be added/removed using this call.
+ * It can be added either to the regular distributor or to each
+ * of the private distributors
+ *
+ * Parameters: SwitchAddRemove - REPORT_ADD to add the routine
+ * REPORT_REMOVE to remove it.
+ * Distributor - Set 0 if not concerned with any private
+ * severity, or give the private severity's
+ * handle to set with it .
+ *
+ * Return value: void
+ **************************************************************************/
+extern void ReportMonitorFunc(uint32_t SwitchAddRemove, uint32_t Distributor);
+
+/*----------------------------------------------------------------------------*/
+/*------------------------------ Severity ------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/***************************************************************************
+ *
+ * Name : ReportSeveritySet
+ *
+ * Function : Determine the filter level of the message's severity
+ *
+ * Notes : Messages with severity below this level wont be sent to
+ * their output
+ * It does not affect the private severities
+ *
+ * Return value: void
+ **************************************************************************/
+extern void ReportSeveritySet(ErrorSeverity level);
+
+/*----------------------------------------------------------------------------*/
+
+#define S1(x) #x
+#define S2(x) S1(x)
+//#define LOCATION __FILE__ " : " S2(__LINE__)
+#define REPORT_LINE(message) __FILE__ "." S2(__LINE__) ":t"S2(UsersysTickGet())" : " S2(message)
+//#define REPORT_LINE(message) __FILE__ "." _ASSERT_STR(__LINE__) ": " message
+
+/*----------------------------------------------------------------------------*/
+/*---------------------- Backward Support to UT_Except -----------------------*/
+/*----------------------------------------------------------------------------*/
+
+#define ON_ERROR_REPORT_ERROR(msg) if ( rc != 0 ) \
+ Report("\n\r*** ERROR :" REPORT_LINE(msg),__FILE__,__LINE__,rc,RpFatalError,0,0)
+
+#define REPORT_ERROR(rc,msg) \
+ Report("\n\r*** ERROR :" REPORT_LINE(msg),__FILE__,__LINE__,rc,RpFatalError,0,0)
+
+#define ON_ERROR_LOG_ERROR(msg) if ( rc != 0 ) \
+ Report("\n\r*** ERROR :" REPORT_LINE(msg),__FILE__,__LINE__,rc,RpError,0,0)
+
+#define LOG_ERROR(rc,msg) \
+ Report("\n\r*** ERROR :" REPORT_LINE(msg),__FILE__,__LINE__,rc,RpError,0,0)
+
+/*----------------------------------------------------------------------------*/
+/*----------------------- Backward Compatible --------------------------------*/
+/*----------------------------------------------------------------------------*/
+extern STATUS ReportMessage(const char *message);
+extern STATUS Reportf(const char *format, ...);
+#define ReportFilterMessage ReportPackageMessage2SysDist
+
+/*----------------------------------------------------------------------------*/
+/*---------------------------- Error Codes -----------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/* Error, returned by errno in Report's routines */
+#define REPORT_ERROR_ILLEGAL_PARAMETER 1
+#define REPORT_ERROR_CODE_NOT_FOUND 2
+#define REPORT_ERROR_FILTER_NOT_ALIVE 3
+#define REPORT_ERROR_NAME 10
+#define REPORT_ERROR_NAME_EXISTS 11
+#define REPORT_ERROR_NAME_NOT_EXISTS 12
+#define REPORT_ERROR_NAME_TOO_LONG 13
+#define REPORT_ERROR_NAME_ALREADY_DISABLE 14
+#define REPORT_ERROR_NOT_ENOUGH_MEMORY 20
+#define REPORT_ERROR_TABLE_FULL 21
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __REPORT_H__ */
+
diff --git a/Software/Embedded_SW/Embedded/Common/report/reportInit.c b/Software/Embedded_SW/Embedded/Common/report/reportInit.c
new file mode 100644
index 000000000..c7ea0c194
--- /dev/null
+++ b/Software/Embedded_SW/Embedded/Common/report/reportInit.c
@@ -0,0 +1,161 @@
+/******************************************************************************
+ * File name : reportInit.c
+ * Title : REPORT PACKAGE - Application Interface
+ * Date created : 01 SEP, 1996
+ * Revision : 1.0
+ * Author : Ilia Maller, Zvika Zilberman
+ *
+ * Description :
+ *
+ ******************************************************************************
+ *
+ * Procedures:
+ *
+ * ReportInit - Initialise report package
+ *
+ ******************************************************************************
+ *
+ * History:
+ * 01.09.96 Ilia Maller - start of coding
+ * 21.02.97 Ilia Maller - minor improvements
+ * 17.09.97 Zvika Zilberman - porting to DCME SWINFRA
+ *
+ ******************************************************************************/
+
+/*------------- Includes --------------------------------*/
+
+#include <stdio.h> /* puts(), etc. */
+#include "report.h"
+#include "distributor.h" /* distibutorInit */
+#include "filter.h"
+#include "include.h"
+
+#include <Modules/Stubs_Handler/DataDef.h>
+#include "PMR/common/MessageContainer.pb-c.h"
+#include "PMR/debugging/DebugLogRequest.pb-c.h"
+#include "PMR/debugging/DebugLogResponse.pb-c.h"
+#include "drivers/twine_usblib/usb_serial_adapter.h"
+//#include "graphics_adapter.h"
+#include "Modules/Stubs_Handler/Container.h"
+
+#include "Modules/thread/thread.h"
+
+MotorConfigStruc MotorsCfg[MAX_THREAD_MOTORS_NUM];
+InternalWinderConfigStruc InternalWinderCfg;
+char protobufToken[36];
+/*void SendStatusResponse (uint32_t Code, char *Token)
+{
+ MessageContainer responseContainer;
+ StatusResponse response = STATUS_RESPONSE__INIT;
+
+
+ response.has_status = true;
+ response.status = (ErrorCode)Code;
+
+ responseContainer = createContainer(MESSAGE_TYPE__StatusResponse, Token, true, &response, &status_response__pack, &status_response__get_packed_size);
+ uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer));
+ size_t container_size = message_container__pack(&responseContainer, container_buffer);
+ SendChars((char*)container_buffer, container_size);
+ free(container_buffer);
+
+
+}*/
+
+int ReportResponseFunc(char *message, /* The formatted message */
+ char *FileName,
+ int LineNumber,
+ int errorCode, /* error code that caused the report */
+ int parameter1, /* user parameter no. 1 */
+ int parameter2) /* user parameter no. 2 */
+{
+ MessageContainer responseContainer;
+
+ DebugLogResponse response = DEBUG_LOG_RESPONSE__INIT;
+ response.filename = FileName;
+ response.has_linenumber = true;
+ response.linenumber = LineNumber;
+ /*response.has_errorcode = true;
+ response.errorcode = (ErrorCode)errorCode;
+ response.has_severity = true;
+ response.severity = (Severity)parameter1;*/
+ response.has_filter = true;
+ response.has_category = true;
+ response.category = (DebugLogCategory)parameter1;
+ response.filter = parameter2;
+ strcpy (response.message,message);
+ responseContainer = createContainer(MESSAGE_TYPE__DebugLogResponse, protobufToken, false, &response, &debug_log_response__pack, &debug_log_response__get_packed_size);
+ uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer));
+ size_t container_size = message_container__pack(&responseContainer, container_buffer);
+ SendChars((char*)container_buffer, container_size);
+
+ return OK;
+
+}
+
+
+uint32_t ReportInitMessage(MessageContainer* requestContainer)
+{
+ uint32_t status = NOT_SUPPORTED;
+ //MessageContainer responseContainer;
+
+ ReportInitParams InitParams;
+
+ DebugLogRequest* request = debug_log_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);
+ strcpy (protobufToken, requestContainer->token);
+ InitParams.DistributorQueueMaxMsgs = 20;
+ InitParams.DistributorTaskPriority = 6;
+ InitParams.MaxNumOfFilterNames = 1;
+ InitParams.MaxNumberOfPrivateDistributors = 2;
+ status |= ReportInit (InitParams);
+ DistributorHandle ReportHandle = ReportAddDistributor("ProtoBuf");
+ if (ReportHandle == NULL) status |= 0x8;
+ status |= ReportFunc(ReportResponseFunc , REPORT_ADD, ReportHandle);
+
+ return status;
+}
+
+#define REPORT_RESERVED_NUM_OF_FILTER_PACKAGES 30 /* This reserved for swinfra packages */
+
+/***************************************************************************
+ *
+ * Name : ReportInit
+ *
+ * Function : PEPORT library init
+ *
+ * Notes : Should be called before any other function from the Report
+ * package.
+ *
+ * Return value: OK or ERROR if malloc has failed or task creation has
+ * failed
+ **************************************************************************/
+STATUS ReportInit(ReportInitParams InitParams)
+{
+ static int initialized = false;
+ STATUS status;
+ int MaxNumOfFilterNames;
+
+ if (initialized)
+ return OK;
+
+ /* Set the filter to receive all kind */
+ ReportSeveritySet(RpMessage);
+
+ /* Configure distributor */
+ if( distibutorInit(InitParams.DistributorTaskPriority,
+ InitParams.DistributorQueueMaxMsgs,
+ InitParams.MaxNumberOfPrivateDistributors) == -1)
+ return ERROR;
+
+ /* Add the support of the monitor commands */
+ //ReportMonitorInit();
+ /* Add the Monitor Output routine, by default */
+ //ReportMonitorFunc(REPORT_ADD, 0);
+
+ MaxNumOfFilterNames = InitParams.MaxNumOfFilterNames;
+ MaxNumOfFilterNames += REPORT_RESERVED_NUM_OF_FILTER_PACKAGES;
+ status = filterTableInit(MaxNumOfFilterNames);
+ if (status == OK)
+ initialized = true;
+
+ return status;
+}