1 #pragma once 2 3 #include <sdbusplus/async.hpp> 4 5 #include <functional> 6 #include <optional> 7 8 /** 9 * @brief Asynchronously executes a shell command. 10 * @param ctx Async context for monitoring the pipe. 11 * @param cmd Shell command to execute. 12 * @return Task resolving to true on success (exit code 0), false otherwise. 13 */ 14 sdbusplus::async::task<bool> asyncSystem( 15 sdbusplus::async::context& ctx, const std::string& cmd, 16 std::optional<std::reference_wrapper<std::string>> result = std::nullopt); 17 18 /** 19 * @brief Convert bytes to an integer of the given type. 20 * 21 * @tparam IntegerType Output integer type (e.g., uint16_t, uint32_t). 22 * @tparam Container A container of uint8_t bytes. 23 * @param data Byte data to convert. 24 * @param bigEndian Set true for big-endian order; false for little-endian. 25 * @return Converted integer. 26 */ 27 template <typename IntegerType, typename Container> 28 IntegerType bytesToInt(const Container& data, bool bigEndian = false) 29 { 30 static_assert(std::is_integral_v<IntegerType>, 31 "IntegerType must be an integral type"); 32 static_assert(std::is_same_v<typename Container::value_type, uint8_t>, 33 "Container must hold uint8_t elements"); 34 35 constexpr size_t maxBytes = sizeof(IntegerType); 36 size_t size = std::min(data.size(), maxBytes); 37 38 IntegerType result = 0; 39 for (size_t i = 0; i < size; ++i) 40 { 41 size_t shift = bigEndian ? (size - 1 - i) * 8 : i * 8; 42 result |= static_cast<IntegerType>(data[i]) << shift; 43 } 44 45 return result; 46 } 47 48 template <typename> 49 inline constexpr bool always_false = false; 50 51 /** 52 * @brief Constructs a vector of bytes (`std::vector<uint8_t>`) from a variable 53 * number of arguments, which can include enums, integral values, 54 * and initializer lists. 55 * 56 * This function is useful when building byte packets or command sequences 57 * to be sent over communication protocols (e.g., I2C, UART, SPI). 58 * 59 * @tparam Args Types of arguments to convert into bytes 60 * @param args The values to encode into the byte vector 61 * @return std::vector<uint8_t> A flattened list of bytes 62 * 63 * @note Passing unsupported types will trigger a compile-time static_assert. 64 * @note Endianness: Multi-byte integers use little-endian order. 65 * 66 * @code 67 * enum class Command : uint8_t { Start = 0x01 }; 68 * auto buf = buildByteVector(Command::Start, 0x1234, {0xAA, 0xBB}); 69 * // Result: { 0x01, 0x34, 0x12, 0xAA, 0xBB } 70 * @endcode 71 */ 72 template <typename... Args> 73 std::vector<uint8_t> buildByteVector(Args&&... args) 74 { 75 std::vector<uint8_t> buf; 76 77 auto append = [&](auto&& value) { 78 using T = std::decay_t<decltype(value)>; 79 80 if constexpr (std::is_enum_v<T>) 81 { 82 buf.push_back(static_cast<uint8_t>(value)); 83 } 84 else if constexpr (std::is_integral_v<T>) 85 { 86 for (size_t i = 0; i < sizeof(T); ++i) 87 { 88 buf.push_back(static_cast<uint8_t>(value >> (i * 8))); 89 } 90 } 91 else if constexpr (std::is_same_v<T, std::initializer_list<uint8_t>>) 92 { 93 buf.insert(buf.end(), value.begin(), value.end()); 94 } 95 else 96 { 97 static_assert(always_false<T>, 98 "Unsupported type in buildByteVector"); 99 } 100 }; 101 102 (append(std::forward<Args>(args)), ...); 103 104 return buf; 105 } 106