CDC Badge OS
Firmware for the CDC Badge v1.0 hardware security key
Loading...
Searching...
No Matches
BleAdvParser.cpp
Go to the documentation of this file.
1
10
12#include <cstring>
13
14namespace cdc::hal::BleAdvParser {
15
19static constexpr uint8_t AD_TYPE_SHORTENED_NAME = 0x08;
20static constexpr uint8_t AD_TYPE_COMPLETE_NAME = 0x09;
21static constexpr uint8_t AD_TYPE_INCOMPLETE_UUID128 = 0x06;
22static constexpr uint8_t AD_TYPE_COMPLETE_UUID128 = 0x07;
23static constexpr uint8_t AD_TYPE_MANUFACTURER_SPECIFIC = 0xFF;
24
25static constexpr uint8_t UUID128_SIZE = 16;
26static constexpr uint8_t COMPANY_ID_SIZE = 2;
27
37template <typename Callback>
38static bool walkAdStructures(const uint8_t* advData, uint8_t len, Callback callback) {
39 if (advData == nullptr || len == 0) {
40 return false;
41 }
42
43 uint8_t offset = 0;
44 while (offset < len) {
45 const uint8_t adLength = advData[offset];
46
47 // Length of 0 signals the end of significant AD structures
48 if (adLength == 0) {
49 break;
50 }
51
52 // The full structure occupies (1 + adLength) bytes.
53 // Verify it fits within the remaining data.
54 if (offset + 1 + adLength > len) {
55 break;
56 }
57
58 const uint8_t adType = advData[offset + 1];
59 const uint8_t* adPayload = &advData[offset + 2];
60 const uint8_t adPayloadLen = adLength - 1; // exclude the type byte
61
62 if (callback(adType, adPayload, adPayloadLen)) {
63 return true;
64 }
65
66 offset += 1 + adLength;
67 }
68
69 return false;
70}
71
81bool findManufacturerData(const uint8_t* advData, uint8_t len,
82 uint16_t* companyId, const uint8_t** data, uint8_t* dataLen) {
83 if (companyId == nullptr || data == nullptr || dataLen == nullptr) {
84 return false;
85 }
86
87 return walkAdStructures(advData, len,
88 [&](uint8_t adType, const uint8_t* payload, uint8_t payloadLen) -> bool {
89 if (adType != AD_TYPE_MANUFACTURER_SPECIFIC) {
90 return false;
91 }
92
93 // Manufacturer data must contain at least the 2-byte company ID
94 if (payloadLen < COMPANY_ID_SIZE) {
95 return false;
96 }
97
98 // Company ID is little-endian
99 *companyId = static_cast<uint16_t>(payload[0]) |
100 (static_cast<uint16_t>(payload[1]) << 8);
101 *data = &payload[COMPANY_ID_SIZE];
102 *dataLen = payloadLen - COMPANY_ID_SIZE;
103
104 return true;
105 });
106}
107
115bool findServiceUuid128(const uint8_t* advData, uint8_t len,
116 const uint8_t uuid128[16]) {
117 if (uuid128 == nullptr) {
118 return false;
119 }
120
121 return walkAdStructures(advData, len,
122 [&](uint8_t adType, const uint8_t* payload, uint8_t payloadLen) -> bool {
123 if (adType != AD_TYPE_INCOMPLETE_UUID128 && adType != AD_TYPE_COMPLETE_UUID128) {
124 return false;
125 }
126
127 // Payload contains one or more 16-byte UUIDs packed consecutively
128 uint8_t remaining = payloadLen;
129 const uint8_t* ptr = payload;
130 while (remaining >= UUID128_SIZE) {
131 if (std::memcmp(ptr, uuid128, UUID128_SIZE) == 0) {
132 return true;
133 }
134 ptr += UUID128_SIZE;
135 remaining -= UUID128_SIZE;
136 }
137
138 return false;
139 });
140}
141
150bool findName(const uint8_t* advData, uint8_t len,
151 char* name, uint8_t nameMaxLen) {
152 if (name == nullptr || nameMaxLen == 0) {
153 return false;
154 }
155
156 // Ensure the output is always null-terminated even on failure
157 name[0] = '\0';
158
159 return walkAdStructures(advData, len,
160 [&](uint8_t adType, const uint8_t* payload, uint8_t payloadLen) -> bool {
161 if (adType != AD_TYPE_COMPLETE_NAME && adType != AD_TYPE_SHORTENED_NAME) {
162 return false;
163 }
164
165 // Determine how many characters we can copy (reserve 1 byte for null)
166 const uint8_t copyLen = (payloadLen < static_cast<uint8_t>(nameMaxLen - 1))
167 ? payloadLen
168 : static_cast<uint8_t>(nameMaxLen - 1);
169
170 std::memcpy(name, payload, copyLen);
171 name[copyLen] = '\0';
172
173 return true;
174 });
175}
176
177} // namespace cdc::hal::BleAdvParser
char name[cdc::hal::ISecureElement::RMEM_NAME_LEN]
static constexpr uint8_t AD_TYPE_INCOMPLETE_UUID128
static constexpr uint8_t UUID128_SIZE
bool findServiceUuid128(const uint8_t *advData, uint8_t len, const uint8_t uuid128[16])
Checks whether a specific 128-bit service UUID is present in AD structures.
static constexpr uint8_t AD_TYPE_MANUFACTURER_SPECIFIC
static constexpr uint8_t AD_TYPE_COMPLETE_UUID128
static constexpr uint8_t AD_TYPE_SHORTENED_NAME
AD type constants from BLE Core Spec Supplement, Part A.
bool findManufacturerData(const uint8_t *advData, uint8_t len, uint16_t *companyId, const uint8_t **data, uint8_t *dataLen)
Extracts manufacturer-specific AD payload and company identifier.
static bool walkAdStructures(const uint8_t *advData, uint8_t len, Callback callback)
Iterates over AD structures and invokes a callback for each structure.
static constexpr uint8_t AD_TYPE_COMPLETE_NAME
static constexpr uint8_t COMPANY_ID_SIZE
bool findName(const uint8_t *advData, uint8_t len, char *name, uint8_t nameMaxLen)
Extracts local device name from advertising data.