/ app / packages / ble_peripheral / windows / Utils.cpp
Utils.cpp
  1  #include "Utils.h"
  2  
  3  #include <iomanip>
  4  #include <iostream>
  5  #include <sstream>
  6  
  7  #include <sdkddkver.h>
  8  
  9  #if WDK_NTDDI_VERSION < NTDDI_WIN10_VB
 10  #error "Windows SDK version before 10.0.19041.0 is not supported"
 11  #elif WDK_NTDDI_VERSION == NTDDI_WIN10_VB
 12  // For Windows SDK version before 10.0.19041.0, remap functions to post-10.0.19041.0 versions
 13  #define WINRT_IMPL_CoGetApartmentType WINRT_CoGetApartmentType
 14  #endif
 15  
 16  #define MAC_ADDRESS_STR_LENGTH (size_t)17 // Two chars per byte, 5 chars for colon
 17  
 18  namespace ble_peripheral
 19  {
 20  
 21      std::string _mac_address_to_str(uint64_t mac_address)
 22      {
 23          uint8_t *mac_ptr = (uint8_t *)&mac_address;
 24          char mac_str[MAC_ADDRESS_STR_LENGTH + 1] = {0};
 25          snprintf(mac_str, MAC_ADDRESS_STR_LENGTH + 1, "%02x:%02x:%02x:%02x:%02x:%02x", mac_ptr[5], mac_ptr[4], mac_ptr[3],
 26                   mac_ptr[2], mac_ptr[1], mac_ptr[0]);
 27          return std::string(mac_str);
 28      }
 29  
 30      uint64_t _str_to_mac_address(std::string mac_str)
 31      {
 32          // TODO: Validate input - Expected Format: XX:XX:XX:XX:XX:XX
 33          uint64_t mac_address_number = 0;
 34          uint8_t *mac_ptr = (uint8_t *)&mac_address_number;
 35          sscanf_s(mac_str.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &mac_ptr[5], &mac_ptr[4], &mac_ptr[3],
 36                   &mac_ptr[2], &mac_ptr[1], &mac_ptr[0]);
 37          return mac_address_number;
 38      }
 39  
 40      winrt::guid uuid_to_guid(const std::string &uuid)
 41      {
 42          // TODO: Add proper cleanup / validation
 43          std::stringstream helper;
 44          for (int i = 0; i < uuid.length(); i++)
 45          {
 46              if (uuid[i] != '-')
 47              {
 48                  helper << uuid[i];
 49              }
 50          }
 51          std::string clean_uuid = helper.str();
 52          winrt::guid guid;
 53          uint64_t *data4_ptr = (uint64_t *)guid.Data4;
 54  
 55          guid.Data1 = static_cast<uint32_t>(std::strtoul(clean_uuid.substr(0, 8).c_str(), nullptr, 16));
 56          guid.Data2 = static_cast<uint16_t>(std::strtoul(clean_uuid.substr(8, 4).c_str(), nullptr, 16));
 57          guid.Data3 = static_cast<uint16_t>(std::strtoul(clean_uuid.substr(12, 4).c_str(), nullptr, 16));
 58          *data4_ptr = _byteswap_uint64(std::strtoull(clean_uuid.substr(16, 16).c_str(), nullptr, 16));
 59  
 60          return guid;
 61      }
 62  
 63      std::string guid_to_uuid(const winrt::guid &guid)
 64      {
 65          std::stringstream helper;
 66          // TODO: It might be cleaner to use snprintf instead of string streams.
 67  
 68          for (uint32_t i = 0; i < 4; i++)
 69          {
 70              // * NOTE: We're performing a byte swap!
 71              helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t *)&guid.Data1)[3 - i];
 72          }
 73          helper << '-';
 74          for (uint32_t i = 0; i < 2; i++)
 75          {
 76              // * NOTE: We're performing a byte swap!
 77              helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t *)&guid.Data2)[1 - i];
 78          }
 79          helper << '-';
 80          for (uint32_t i = 0; i < 2; i++)
 81          {
 82              // * NOTE: We're performing a byte swap!
 83              helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t *)&guid.Data3)[1 - i];
 84          }
 85          helper << '-';
 86          for (uint32_t i = 0; i < 2; i++)
 87          {
 88              helper << std::hex << std::setw(2) << std::setfill('0') << (int)guid.Data4[i];
 89          }
 90          helper << '-';
 91          for (uint32_t i = 0; i < 6; i++)
 92          {
 93              helper << std::hex << std::setw(2) << std::setfill('0') << (int)guid.Data4[2 + i];
 94          }
 95          return helper.str();
 96      }
 97  
 98      std::vector<uint8_t> to_bytevc(IBuffer buffer)
 99      {
100          auto reader = DataReader::FromBuffer(buffer);
101          auto result = std::vector<uint8_t>(reader.UnconsumedBufferLength());
102          reader.ReadBytes(result);
103          return result;
104      }
105  
106      IBuffer from_bytevc(std::vector<uint8_t> bytes)
107      {
108          auto writer = DataWriter();
109          writer.WriteBytes(bytes);
110          return writer.DetachBuffer();
111      }
112  
113      std::string to_hexstring(std::vector<uint8_t> bytes)
114      {
115          auto ss = std::stringstream();
116          for (auto b : bytes)
117              ss << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(b);
118          return ss.str();
119      }
120  
121      std::string to_lower_case(std::string str)
122      {
123          std::transform(str.begin(), str.end(), str.begin(),
124                         [](unsigned char c) -> char
125                         { return static_cast<char>(std::tolower(c)); });
126          return str;
127      }
128  
129      std::string to_uuidstr(winrt::guid guid)
130      {
131          char chars[36 + 1];
132          sprintf_s(chars, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
133                    guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2],
134                    guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
135          return std::string{chars};
136      }
137  
138  } // namespace ble_peripheral