xref: /aosp_15_r20/system/chre/util/system/ble_util.cc (revision 84e339476a462649f82315436d70fd732297a399)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "chre/util/system/ble_util.h"
18 
19 #include <cinttypes>
20 
21 #include "chre/platform/log.h"
22 
23 namespace chre {
24 
25 namespace {
26 
27 // Tx Power Level AD Type defined in the BT Core Spec v5.3 Assigned Numbers,
28 // Generic Access Profile (ref:
29 // https://www.bluetooth.com/specifications/assigned-numbers/).
30 constexpr uint8_t kTxPowerLevelAdType = 0x0A;
31 constexpr uint8_t kAdTypeOffset = 1;
32 constexpr uint8_t kExpectedAdDataLength = 2;
33 
34 /**
35  * Gets the TX Power from the data field of legacy AD reports. This function
36  * parses the advertising data which is defined in the BT Core Spec v5.3, Vol 3,
37  * Part C, Section 11, Advertising and Scan Response Data Format, and checks for
38  * the presence of the Tx Power Level AD Type.
39  *
40  * @param data Advertising data.
41  * @param dataLength Length of advertising data.
42  * @return int8_t Tx Power value.
43  */
getTxPowerFromLegacyReport(const uint8_t * data,size_t dataLength)44 int8_t getTxPowerFromLegacyReport(const uint8_t *data, size_t dataLength) {
45   size_t i = 0;
46   while (i < dataLength) {
47     uint8_t adDataLength = data[i];
48     if (adDataLength == 0 || (adDataLength >= dataLength - i)) {
49       break;
50     }
51     if (data[i + kAdTypeOffset] == kTxPowerLevelAdType &&
52         adDataLength == kExpectedAdDataLength) {
53       return static_cast<int8_t>(data[i + kExpectedAdDataLength]);
54     }
55     i += kAdTypeOffset + adDataLength;
56   }
57   return CHRE_BLE_TX_POWER_NONE;
58 }
59 
60 }  // namespace
61 
populateLegacyAdvertisingReportFields(chreBleAdvertisingReport & report)62 void populateLegacyAdvertisingReportFields(chreBleAdvertisingReport &report) {
63   if ((report.eventTypeAndDataStatus & CHRE_BLE_EVENT_TYPE_FLAG_LEGACY) != 0 &&
64       report.txPower == CHRE_BLE_TX_POWER_NONE) {
65     report.txPower = getTxPowerFromLegacyReport(report.data, report.dataLength);
66   }
67 }
68 
69 }  // namespace chre
70