1 /******************************************************************************
2 *
3 * Copyright 1999-2014 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains functions that handle inquiries. These include
22 * setting discoverable mode, controlling the mode of the Baseband, and
23 * maintaining a small database of inquiry responses, with API for people
24 * to browse it.
25 *
26 ******************************************************************************/
27
28 #include "stack/include/btm_inq.h"
29
30 #include <bluetooth/log.h>
31 #include <com_android_bluetooth_flags.h>
32 #include <stddef.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include <mutex>
37
38 #include "btif/include/btif_dm.h"
39 #include "common/time_util.h"
40 #include "hci/controller_interface.h"
41 #include "hci/event_checkers.h"
42 #include "hci/hci_interface.h"
43 #include "internal_include/bt_target.h"
44 #include "main/shim/entry.h"
45 #include "main/shim/helpers.h"
46 #include "main/shim/shim.h"
47 #include "osi/include/allocator.h"
48 #include "osi/include/properties.h"
49 #include "osi/include/stack_power_telemetry.h"
50 #include "packet/bit_inserter.h"
51 #include "stack/btm/btm_ble_int.h"
52 #include "stack/btm/btm_eir.h"
53 #include "stack/btm/btm_int_types.h"
54 #include "stack/btm/neighbor_inquiry.h"
55 #include "stack/btm/security_device_record.h"
56 #include "stack/include/acl_api_types.h"
57 #include "stack/include/advertise_data_parser.h"
58 #include "stack/include/bt_hdr.h"
59 #include "stack/include/bt_lap.h"
60 #include "stack/include/bt_types.h"
61 #include "stack/include/bt_uuid16.h"
62 #include "stack/include/btm_client_interface.h"
63 #include "stack/include/btm_log_history.h"
64 #include "stack/include/btm_status.h"
65 #include "stack/include/hci_error_code.h"
66 #include "stack/include/hcidefs.h"
67 #include "stack/include/hcimsgs.h"
68 #include "stack/include/inq_hci_link_interface.h"
69 #include "stack/include/main_thread.h"
70 #include "types/bluetooth/uuid.h"
71 #include "types/raw_address.h"
72
73 /* MACRO to set the service bit mask in a bit stream */
74 #define BTM_EIR_SET_SERVICE(p, service) \
75 (((uint32_t*)(p))[(((uint32_t)(service)) / BTM_EIR_ARRAY_BITS)] |= \
76 ((uint32_t)1 << (((uint32_t)(service)) % BTM_EIR_ARRAY_BITS)))
77
78 /* MACRO to clear the service bit mask in a bit stream */
79 #define BTM_EIR_CLR_SERVICE(p, service) \
80 (((uint32_t*)(p))[(((uint32_t)(service)) / BTM_EIR_ARRAY_BITS)] &= \
81 ~((uint32_t)1 << (((uint32_t)(service)) % BTM_EIR_ARRAY_BITS)))
82
83 /* MACRO to check the service bit mask in a bit stream */
84 #define BTM_EIR_HAS_SERVICE(p, service) \
85 ((((uint32_t*)(p))[(((uint32_t)(service)) / BTM_EIR_ARRAY_BITS)] & \
86 ((uint32_t)1 << (((uint32_t)(service)) % BTM_EIR_ARRAY_BITS))) >> \
87 (((uint32_t)(service)) % BTM_EIR_ARRAY_BITS))
88
89 namespace {
90 constexpr char kBtmLogTag[] = "SCAN";
91
btm_log_history_scan_mode(uint8_t scan_mode)92 void btm_log_history_scan_mode(uint8_t scan_mode) {
93 static uint8_t scan_mode_cached_ = 0xff;
94 if (scan_mode_cached_ == scan_mode) {
95 return;
96 }
97
98 BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Classic updated",
99 std::format("inquiry_scan_enable:{:c} page_scan_enable:{:c}",
100 (scan_mode & HCI_INQUIRY_SCAN_ENABLED) ? 'T' : 'F',
101 (scan_mode & HCI_PAGE_SCAN_ENABLED) ? 'T' : 'F'));
102 scan_mode_cached_ = scan_mode;
103 }
104
105 // Inquiry database lock
106 std::mutex inq_db_lock_;
107 // Inquiry database
108 tINQ_DB_ENT inq_db_[BTM_INQ_DB_SIZE];
109
110 // Inquiry bluetooth device database lock
111 std::mutex bd_db_lock_;
112 tINQ_BDADDR* p_bd_db_; /* Pointer to memory that holds bdaddrs */
113 uint16_t num_bd_entries_; /* Number of entries in database */
114 uint16_t max_bd_entries_; /* Maximum number of entries that can be stored */
115
116 } // namespace
117
118 extern tBTM_CB btm_cb;
119
120 using namespace bluetooth;
121 using bluetooth::Uuid;
122 using bluetooth::hci::CommandCompleteView;
123 using bluetooth::hci::CommandStatusView;
124 using bluetooth::hci::ErrorCode;
125 using bluetooth::hci::EventCode;
126 using bluetooth::hci::EventView;
127 using bluetooth::hci::ExtendedInquiryResultView;
128 using bluetooth::hci::GapDataType;
129 using bluetooth::hci::InquiryBuilder;
130 using bluetooth::hci::InquiryCancelBuilder;
131 using bluetooth::hci::InquiryCancelCompleteView;
132 using bluetooth::hci::InquiryCompleteView;
133 using bluetooth::hci::InquiryResultView;
134 using bluetooth::hci::InquiryResultWithRssiView;
135 using bluetooth::hci::Lap;
136
137 /* 3 second timeout waiting for responses */
138 #define BTM_INQ_REPLY_TIMEOUT_MS (3 * 1000)
139
140 /* TRUE to enable DEBUG traces for btm_inq */
141 #ifndef BTM_INQ_DEBUG
142 #define BTM_INQ_DEBUG FALSE
143 #endif
144
145 #ifndef PROPERTY_PAGE_SCAN_TYPE
146 #define PROPERTY_PAGE_SCAN_TYPE "bluetooth.core.classic.page_scan_type"
147 #endif
148
149 #ifndef PROPERTY_PAGE_SCAN_INTERVAL
150 #define PROPERTY_PAGE_SCAN_INTERVAL "bluetooth.core.classic.page_scan_interval"
151 #endif
152
153 #ifndef PROPERTY_PAGE_SCAN_WINDOW
154 #define PROPERTY_PAGE_SCAN_WINDOW "bluetooth.core.classic.page_scan_window"
155 #endif
156
157 #ifndef PROPERTY_INQ_SCAN_TYPE
158 #define PROPERTY_INQ_SCAN_TYPE "bluetooth.core.classic.inq_scan_type"
159 #endif
160
161 #ifndef PROPERTY_INQ_SCAN_INTERVAL
162 #define PROPERTY_INQ_SCAN_INTERVAL "bluetooth.core.classic.inq_scan_interval"
163 #endif
164
165 #ifndef PROPERTY_INQ_SCAN_WINDOW
166 #define PROPERTY_INQ_SCAN_WINDOW "bluetooth.core.classic.inq_scan_window"
167 #endif
168
169 #ifndef PROPERTY_INQ_BY_RSSI
170 #define PROPERTY_INQ_BY_RSSI "persist.bluetooth.inq_by_rssi"
171 #endif
172
173 #define BTIF_DM_DEFAULT_INQ_MAX_DURATION 10
174
175 #ifndef PROPERTY_INQ_LENGTH
176 #define PROPERTY_INQ_LENGTH "bluetooth.core.classic.inq_length"
177 #endif
178
179 /******************************************************************************/
180 /* L O C A L D A T A D E F I N I T I O N S */
181 /******************************************************************************/
182 static const LAP general_inq_lap = {0x9e, 0x8b, 0x33};
183 static const LAP limited_inq_lap = {0x9e, 0x8b, 0x00};
184
185 const uint16_t BTM_EIR_UUID_LKUP_TBL[BTM_EIR_MAX_SERVICES] = {
186 UUID_SERVCLASS_SERVICE_DISCOVERY_SERVER,
187 /* UUID_SERVCLASS_BROWSE_GROUP_DESCRIPTOR, */
188 /* UUID_SERVCLASS_PUBLIC_BROWSE_GROUP, */
189 UUID_SERVCLASS_SERIAL_PORT, UUID_SERVCLASS_LAN_ACCESS_USING_PPP,
190 UUID_SERVCLASS_DIALUP_NETWORKING, UUID_SERVCLASS_IRMC_SYNC, UUID_SERVCLASS_OBEX_OBJECT_PUSH,
191 UUID_SERVCLASS_OBEX_FILE_TRANSFER, UUID_SERVCLASS_IRMC_SYNC_COMMAND, UUID_SERVCLASS_HEADSET,
192 UUID_SERVCLASS_CORDLESS_TELEPHONY, UUID_SERVCLASS_AUDIO_SOURCE, UUID_SERVCLASS_AUDIO_SINK,
193 UUID_SERVCLASS_AV_REM_CTRL_TARGET,
194 /* UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION, */
195 UUID_SERVCLASS_AV_REMOTE_CONTROL,
196 /* UUID_SERVCLASS_VIDEO_CONFERENCING, */
197 UUID_SERVCLASS_INTERCOM, UUID_SERVCLASS_FAX, UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
198 /* UUID_SERVCLASS_WAP, */
199 /* UUID_SERVCLASS_WAP_CLIENT, */
200 UUID_SERVCLASS_PANU, UUID_SERVCLASS_NAP, UUID_SERVCLASS_GN, UUID_SERVCLASS_DIRECT_PRINTING,
201 /* UUID_SERVCLASS_REFERENCE_PRINTING, */
202 UUID_SERVCLASS_IMAGING, UUID_SERVCLASS_IMAGING_RESPONDER,
203 UUID_SERVCLASS_IMAGING_AUTO_ARCHIVE, UUID_SERVCLASS_IMAGING_REF_OBJECTS,
204 UUID_SERVCLASS_HF_HANDSFREE, UUID_SERVCLASS_AG_HANDSFREE,
205 UUID_SERVCLASS_DIR_PRT_REF_OBJ_SERVICE,
206 /* UUID_SERVCLASS_REFLECTED_UI, */
207 UUID_SERVCLASS_BASIC_PRINTING, UUID_SERVCLASS_PRINTING_STATUS,
208 UUID_SERVCLASS_HUMAN_INTERFACE, UUID_SERVCLASS_CABLE_REPLACEMENT, UUID_SERVCLASS_HCRP_PRINT,
209 UUID_SERVCLASS_HCRP_SCAN,
210 /* UUID_SERVCLASS_COMMON_ISDN_ACCESS, */
211 /* UUID_SERVCLASS_VIDEO_CONFERENCING_GW, */
212 /* UUID_SERVCLASS_UDI_MT, */
213 /* UUID_SERVCLASS_UDI_TA, */
214 /* UUID_SERVCLASS_VCP, */
215 UUID_SERVCLASS_SAP, UUID_SERVCLASS_PBAP_PCE, UUID_SERVCLASS_PBAP_PSE,
216 UUID_SERVCLASS_PHONE_ACCESS, UUID_SERVCLASS_HEADSET_HS, UUID_SERVCLASS_PNP_INFORMATION,
217 /* UUID_SERVCLASS_GENERIC_NETWORKING, */
218 /* UUID_SERVCLASS_GENERIC_FILETRANSFER, */
219 /* UUID_SERVCLASS_GENERIC_AUDIO, */
220 /* UUID_SERVCLASS_GENERIC_TELEPHONY, */
221 /* UUID_SERVCLASS_UPNP_SERVICE, */
222 /* UUID_SERVCLASS_UPNP_IP_SERVICE, */
223 /* UUID_SERVCLASS_ESDP_UPNP_IP_PAN, */
224 /* UUID_SERVCLASS_ESDP_UPNP_IP_LAP, */
225 /* UUID_SERVCLASS_ESDP_UPNP_IP_L2CAP, */
226 UUID_SERVCLASS_VIDEO_SOURCE, UUID_SERVCLASS_VIDEO_SINK,
227 /* UUID_SERVCLASS_VIDEO_DISTRIBUTION */
228 UUID_SERVCLASS_MESSAGE_ACCESS, UUID_SERVCLASS_MESSAGE_NOTIFICATION,
229 UUID_SERVCLASS_HDP_SOURCE, UUID_SERVCLASS_HDP_SINK};
230
231 /******************************************************************************/
232 /* L O C A L F U N C T I O N P R O T O T Y P E S */
233 /******************************************************************************/
234 static void btm_clr_inq_db(const RawAddress* p_bda);
235 static void btm_init_inq_result_flt(void);
236
237 static uint8_t btm_convert_uuid_to_eir_service(uint16_t uuid16);
238 static const uint8_t* btm_eir_get_uuid_list(const uint8_t* p_eir, size_t eir_len, uint8_t uuid_size,
239 uint8_t* p_num_uuid, uint8_t* p_uuid_list_type);
240 static void btm_set_eir_uuid(const uint8_t* p_eir, tBTM_INQ_RESULTS* p_results);
241 static void btm_process_cancel_complete(tHCI_STATUS status, uint8_t mode);
242 static void on_incoming_hci_event(EventView event);
is_inquery_by_rssi()243 static bool is_inquery_by_rssi() { return osi_property_get_bool(PROPERTY_INQ_BY_RSSI, false); }
244
245 /*******************************************************************************
246 *
247 * Function BTM_SetDiscoverability
248 *
249 * Description This function is called to set the device into or out of
250 * discoverable mode. Discoverable mode means inquiry
251 * scans are enabled. If a value of '0' is entered for window
252 * or interval, the default values are used.
253 *
254 * Returns tBTM_STATUS::BTM_SUCCESS if successful
255 * tBTM_STATUS::BTM_BUSY if a setting of the filter is already in progress
256 * tBTM_STATUS::BTM_NO_RESOURCES if couldn't get a memory pool buffer
257 * tBTM_STATUS::BTM_ILLEGAL_VALUE if a bad parameter was detected
258 * tBTM_STATUS::BTM_WRONG_MODE if the device is not up.
259 *
260 ******************************************************************************/
BTM_SetDiscoverability(uint16_t inq_mode)261 tBTM_STATUS BTM_SetDiscoverability(uint16_t inq_mode) {
262 uint8_t scan_mode = 0;
263 uint16_t service_class;
264 uint8_t major, minor;
265 DEV_CLASS cod;
266 LAP temp_lap[2];
267 bool is_limited;
268 bool cod_limited;
269
270 log::verbose("");
271 if (bluetooth::shim::GetController()->SupportsBle()) {
272 if (btm_ble_set_discoverability((uint16_t)(inq_mode)) == tBTM_STATUS::BTM_SUCCESS) {
273 btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_BLE_DISCOVERABLE_MASK);
274 btm_cb.btm_inq_vars.discoverable_mode |= (inq_mode & BTM_BLE_DISCOVERABLE_MASK);
275 }
276 }
277 inq_mode &= ~BTM_BLE_DISCOVERABLE_MASK;
278
279 /*** Check mode parameter ***/
280 if (inq_mode > BTM_MAX_DISCOVERABLE) {
281 return tBTM_STATUS::BTM_ILLEGAL_VALUE;
282 }
283
284 /* If the window and/or interval is '0', set to default values */
285 log::verbose("mode {} [NonDisc-0, Lim-1, Gen-2]", inq_mode);
286 (inq_mode != BTM_NON_DISCOVERABLE) ? power_telemetry::GetInstance().LogInqScanStarted()
287 : power_telemetry::GetInstance().LogInqScanStopped();
288
289 /* Set the IAC if needed */
290 if (inq_mode != BTM_NON_DISCOVERABLE) {
291 if (inq_mode & BTM_LIMITED_DISCOVERABLE) {
292 /* Use the GIAC and LIAC codes for limited discoverable mode */
293 memcpy(temp_lap[0], limited_inq_lap, LAP_LEN);
294 memcpy(temp_lap[1], general_inq_lap, LAP_LEN);
295
296 btsnd_hcic_write_cur_iac_lap(2, (LAP* const)temp_lap);
297 } else {
298 btsnd_hcic_write_cur_iac_lap(1, (LAP* const)&general_inq_lap);
299 }
300
301 scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
302 }
303
304 const uint16_t window = osi_property_get_int32(PROPERTY_INQ_SCAN_WINDOW, BTM_DEFAULT_DISC_WINDOW);
305 const uint16_t interval =
306 osi_property_get_int32(PROPERTY_INQ_SCAN_INTERVAL, BTM_DEFAULT_DISC_INTERVAL);
307
308 /* Send down the inquiry scan window and period if changed */
309 if ((window != btm_cb.btm_inq_vars.inq_scan_window) ||
310 (interval != btm_cb.btm_inq_vars.inq_scan_period)) {
311 btsnd_hcic_write_inqscan_cfg(interval, window);
312 btm_cb.btm_inq_vars.inq_scan_window = window;
313 btm_cb.btm_inq_vars.inq_scan_period = interval;
314 }
315
316 if (btm_cb.btm_inq_vars.connectable_mode & BTM_CONNECTABLE_MASK) {
317 scan_mode |= HCI_PAGE_SCAN_ENABLED;
318 }
319
320 btm_log_history_scan_mode(scan_mode);
321 btsnd_hcic_write_scan_enable(scan_mode);
322 btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_DISCOVERABLE_MASK);
323 btm_cb.btm_inq_vars.discoverable_mode |= inq_mode;
324
325 /* Change the service class bit if mode has changed */
326 DEV_CLASS old_cod = BTM_ReadDeviceClass();
327 BTM_COD_SERVICE_CLASS(service_class, old_cod);
328 is_limited = (inq_mode & BTM_LIMITED_DISCOVERABLE) ? true : false;
329 cod_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? true : false;
330 if (is_limited ^ cod_limited) {
331 BTM_COD_MINOR_CLASS(minor, old_cod);
332 BTM_COD_MAJOR_CLASS(major, old_cod);
333 if (is_limited) {
334 service_class |= BTM_COD_SERVICE_LMTD_DISCOVER;
335 } else {
336 service_class &= ~BTM_COD_SERVICE_LMTD_DISCOVER;
337 }
338
339 FIELDS_TO_COD(cod, minor, major, service_class);
340 (void)get_btm_client_interface().local.BTM_SetDeviceClass(cod);
341 }
342
343 return tBTM_STATUS::BTM_SUCCESS;
344 }
345
BTM_EnableInterlacedInquiryScan()346 void BTM_EnableInterlacedInquiryScan() {
347 log::verbose("");
348
349 uint16_t inq_scan_type = osi_property_get_int32(PROPERTY_INQ_SCAN_TYPE, BTM_SCAN_TYPE_INTERLACED);
350
351 if (!bluetooth::shim::GetController()->SupportsInterlacedInquiryScan() ||
352 inq_scan_type != BTM_SCAN_TYPE_INTERLACED ||
353 btm_cb.btm_inq_vars.inq_scan_type == BTM_SCAN_TYPE_INTERLACED) {
354 log::warn(
355 "Unable to set interlaced inquiry scan controller_supported:%c "
356 "property_supported:%c already_in_mode:%c",
357 (bluetooth::shim::GetController()->SupportsInterlacedInquiryScan()) ? 'T' : 'F',
358 (inq_scan_type != BTM_SCAN_TYPE_INTERLACED) ? 'T' : 'F',
359 (btm_cb.btm_inq_vars.inq_scan_type == BTM_SCAN_TYPE_INTERLACED) ? 'T' : 'F');
360 return;
361 }
362
363 btsnd_hcic_write_inqscan_type(BTM_SCAN_TYPE_INTERLACED);
364 btm_cb.btm_inq_vars.inq_scan_type = BTM_SCAN_TYPE_INTERLACED;
365 }
366
BTM_EnableInterlacedPageScan()367 void BTM_EnableInterlacedPageScan() {
368 log::verbose("");
369
370 uint16_t page_scan_type =
371 osi_property_get_int32(PROPERTY_PAGE_SCAN_TYPE, BTM_SCAN_TYPE_INTERLACED);
372
373 if (!bluetooth::shim::GetController()->SupportsInterlacedInquiryScan() ||
374 page_scan_type != BTM_SCAN_TYPE_INTERLACED ||
375 btm_cb.btm_inq_vars.page_scan_type == BTM_SCAN_TYPE_INTERLACED) {
376 log::warn(
377 "Unable to set interlaced page scan controller_supported:%c "
378 "property_supported:%c already_in_mode:%c",
379 (bluetooth::shim::GetController()->SupportsInterlacedInquiryScan()) ? 'T' : 'F',
380 (page_scan_type != BTM_SCAN_TYPE_INTERLACED) ? 'T' : 'F',
381 (btm_cb.btm_inq_vars.page_scan_type == BTM_SCAN_TYPE_INTERLACED) ? 'T' : 'F');
382 return;
383 }
384
385 btsnd_hcic_write_pagescan_type(BTM_SCAN_TYPE_INTERLACED);
386 btm_cb.btm_inq_vars.page_scan_type = BTM_SCAN_TYPE_INTERLACED;
387 }
388
389 /*******************************************************************************
390 *
391 * Function BTM_SetInquiryMode
392 *
393 * Description This function is called to set standard or with RSSI
394 * mode of the inquiry for local device.
395 *
396 * Output Params: mode - standard, with RSSI, extended
397 *
398 * Returns tBTM_STATUS::BTM_SUCCESS if successful
399 * tBTM_STATUS::BTM_NO_RESOURCES if couldn't get a memory pool buffer
400 * tBTM_STATUS::BTM_ILLEGAL_VALUE if a bad parameter was detected
401 * tBTM_STATUS::BTM_WRONG_MODE if the device is not up.
402 *
403 ******************************************************************************/
BTM_SetInquiryMode(uint8_t mode)404 tBTM_STATUS BTM_SetInquiryMode(uint8_t mode) {
405 log::verbose("");
406 if (mode == BTM_INQ_RESULT_STANDARD) {
407 /* mandatory mode */
408 } else if (mode == BTM_INQ_RESULT_WITH_RSSI) {
409 if (!bluetooth::shim::GetController()->SupportsRssiWithInquiryResults()) {
410 return tBTM_STATUS::BTM_MODE_UNSUPPORTED;
411 }
412 } else if (mode == BTM_INQ_RESULT_EXTENDED) {
413 if (!bluetooth::shim::GetController()->SupportsExtendedInquiryResponse()) {
414 return tBTM_STATUS::BTM_MODE_UNSUPPORTED;
415 }
416 } else {
417 return tBTM_STATUS::BTM_ILLEGAL_VALUE;
418 }
419
420 if (!get_btm_client_interface().local.BTM_IsDeviceUp()) {
421 return tBTM_STATUS::BTM_WRONG_MODE;
422 }
423
424 btsnd_hcic_write_inquiry_mode(mode);
425
426 return tBTM_STATUS::BTM_SUCCESS;
427 }
428
429 /*******************************************************************************
430 *
431 * Function BTM_SetConnectability
432 *
433 * Description This function is called to set the device into or out of
434 * connectable mode. Discoverable mode means page scans are
435 * enabled.
436 *
437 * Returns tBTM_STATUS::BTM_SUCCESS if successful
438 * tBTM_STATUS::BTM_ILLEGAL_VALUE if a bad parameter is detected
439 * tBTM_STATUS::BTM_NO_RESOURCES if could not allocate a message buffer
440 * tBTM_STATUS::BTM_WRONG_MODE if the device is not up.
441 *
442 ******************************************************************************/
BTM_SetConnectability(uint16_t page_mode)443 tBTM_STATUS BTM_SetConnectability(uint16_t page_mode) {
444 uint8_t scan_mode = 0;
445
446 if (bluetooth::shim::GetController()->SupportsBle()) {
447 if (btm_ble_set_connectability(page_mode) != tBTM_STATUS::BTM_SUCCESS) {
448 return tBTM_STATUS::BTM_NO_RESOURCES;
449 }
450 btm_cb.btm_inq_vars.connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
451 btm_cb.btm_inq_vars.connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
452 }
453 page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
454
455 /*** Check mode parameter ***/
456 if (page_mode != BTM_NON_CONNECTABLE && page_mode != BTM_CONNECTABLE) {
457 return tBTM_STATUS::BTM_ILLEGAL_VALUE;
458 }
459
460 /*** Only check window and duration if mode is connectable ***/
461 if (page_mode == BTM_CONNECTABLE) {
462 scan_mode |= HCI_PAGE_SCAN_ENABLED;
463 }
464
465 const uint16_t window =
466 osi_property_get_int32(PROPERTY_PAGE_SCAN_WINDOW, BTM_DEFAULT_CONN_WINDOW);
467 const uint16_t interval =
468 osi_property_get_int32(PROPERTY_PAGE_SCAN_INTERVAL, BTM_DEFAULT_CONN_INTERVAL);
469
470 log::verbose("mode={} [NonConn-0, Conn-1], page scan interval=({} * 0.625)ms", page_mode,
471 interval);
472
473 if ((window != btm_cb.btm_inq_vars.page_scan_window) ||
474 (interval != btm_cb.btm_inq_vars.page_scan_period)) {
475 btm_cb.btm_inq_vars.page_scan_window = window;
476 btm_cb.btm_inq_vars.page_scan_period = interval;
477 btsnd_hcic_write_pagescan_cfg(interval, window);
478 }
479
480 /* Keep the inquiry scan as previouosly set */
481 if (btm_cb.btm_inq_vars.discoverable_mode & BTM_DISCOVERABLE_MASK) {
482 scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
483 }
484
485 btm_log_history_scan_mode(scan_mode);
486 btsnd_hcic_write_scan_enable(scan_mode);
487 btm_cb.btm_inq_vars.connectable_mode &= (~BTM_CONNECTABLE_MASK);
488 btm_cb.btm_inq_vars.connectable_mode |= page_mode;
489 return tBTM_STATUS::BTM_SUCCESS;
490 }
491
492 /*******************************************************************************
493 *
494 * Function BTM_IsInquiryActive
495 *
496 * Description This function returns a bit mask of the current inquiry
497 * state
498 *
499 * Returns BTM_INQUIRY_INACTIVE if inactive (0)
500 * BTM_GENERAL_INQUIRY if a general inquiry is active
501 *
502 ******************************************************************************/
BTM_IsInquiryActive(void)503 uint16_t BTM_IsInquiryActive(void) {
504 log::verbose("");
505
506 return btm_cb.btm_inq_vars.inq_active;
507 }
508
509 /*******************************************************************************
510 *
511 * Function BTM_CancelLeScan
512 *
513 * Description This function cancels an le scan if active
514 *
515 ******************************************************************************/
BTM_CancelLeScan()516 static void BTM_CancelLeScan() {
517 #if TARGET_FLOSS
518 log::info("Skipping because FLOSS doesn't use this API for LE scans");
519 return;
520 #else
521 log::assert_that(get_btm_client_interface().local.BTM_IsDeviceUp(),
522 "assert failed: BTM_IsDeviceUp()");
523 if ((btm_cb.btm_inq_vars.inqparms.mode & BTM_BLE_GENERAL_INQUIRY) != 0) {
524 btm_ble_stop_inquiry();
525 }
526 #endif
527 }
528
529 /*******************************************************************************
530 *
531 * Function BTM_CancelInquiry
532 *
533 * Description This function cancels an inquiry if active
534 *
535 ******************************************************************************/
BTM_CancelInquiry(void)536 void BTM_CancelInquiry(void) {
537 log::verbose("");
538
539 log::assert_that(get_btm_client_interface().local.BTM_IsDeviceUp(),
540 "assert failed: BTM_IsDeviceUp()");
541
542 btm_cb.neighbor.inquiry_history_->Push({
543 .status = tBTM_INQUIRY_CMPL::CANCELED,
544 .num_resp = btm_cb.btm_inq_vars.inq_cmpl_info.num_resp,
545 .resp_type =
546 {
547 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_STANDARD],
548 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_WITH_RSSI],
549 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_EXTENDED],
550 },
551 .start_time_ms = btm_cb.neighbor.classic_inquiry.start_time_ms,
552 });
553
554 const auto duration_ms = timestamper_in_milliseconds.GetTimestamp() -
555 btm_cb.neighbor.classic_inquiry.start_time_ms;
556 BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Classic inquiry canceled",
557 std::format("duration_s:{:6.3f} results:{} std:{} rssi:{} ext:{}",
558 duration_ms / 1000.0, btm_cb.neighbor.classic_inquiry.results,
559 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_STANDARD],
560 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_WITH_RSSI],
561 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_EXTENDED]));
562 btm_cb.neighbor.classic_inquiry = {};
563
564 /* Only cancel if not in periodic mode, otherwise the caller should call
565 * BTM_CancelPeriodicMode */
566 if ((btm_cb.btm_inq_vars.inq_active & BTM_INQUIRY_ACTIVE_MASK) != 0) {
567 btm_cb.btm_inq_vars.inq_active = BTM_INQUIRY_INACTIVE;
568 btm_cb.btm_inq_vars.state = BTM_INQ_INACTIVE_STATE;
569 btm_cb.btm_inq_vars.p_inq_results_cb = NULL; /* Do not notify caller anymore */
570 btm_cb.btm_inq_vars.p_inq_cmpl_cb = NULL; /* Do not notify caller anymore */
571
572 if ((btm_cb.btm_inq_vars.inqparms.mode & BTM_GENERAL_INQUIRY) != 0) {
573 bluetooth::shim::GetHciLayer()->EnqueueCommand(
574 InquiryCancelBuilder::Create(),
575 get_main_thread()->BindOnce([](CommandCompleteView complete_view) {
576 check_complete<InquiryCancelCompleteView>(complete_view);
577 btm_process_cancel_complete(HCI_SUCCESS, BTM_GENERAL_INQUIRY);
578 }));
579 }
580 BTM_CancelLeScan();
581
582 btm_cb.btm_inq_vars.inq_counter++;
583 btm_clr_inq_result_flt();
584 }
585 }
586
587 #if TARGET_FLOSS
btm_classic_inquiry_timeout(void *)588 static void btm_classic_inquiry_timeout(void* /* data */) {
589 // When the Inquiry Complete event is received, the classic inquiry
590 // will be marked as completed. Therefore, we only need to mark
591 // the BLE inquiry as completed here to stop processing BLE results
592 // as inquiry results.
593 btm_process_inq_complete(HCI_SUCCESS, BTM_BLE_GENERAL_INQUIRY);
594 }
595 #endif
596
597 /*******************************************************************************
598 *
599 * Function BTM_StartLeScan
600 *
601 * Description This function is called to start an LE scan. Currently
602 * this is only callable from BTM_StartInquiry.
603 *
604 * Returns tBTM_STATUS
605 * BTM_CMD_STARTED if le scan successfully initiated
606 * BTM_WRONG_MODE if controller does not support ble
607 *
608 ******************************************************************************/
BTM_StartLeScan()609 static tBTM_STATUS BTM_StartLeScan() {
610 #if TARGET_FLOSS
611 log::info("Skipping because FLOSS doesn't use this API for LE scans");
612 return tBTM_STATUS::BTM_WRONG_MODE;
613 #else
614 if (shim::GetController()->SupportsBle()) {
615 btm_ble_start_inquiry(btm_cb.btm_inq_vars.inqparms.duration);
616 return tBTM_STATUS::BTM_CMD_STARTED;
617 }
618 log::warn("Trying to do LE scan on a non-LE adapter");
619 btm_cb.btm_inq_vars.inqparms.mode &= ~BTM_BLE_GENERAL_INQUIRY;
620 return tBTM_STATUS::BTM_WRONG_MODE;
621 #endif
622 }
623
624 /*******************************************************************************
625 *
626 * Function BTM_StartInquiry
627 *
628 * Description This function is called to start an inquiry on the
629 * classic BR/EDR link and start an le scan. This is an
630 * Android only API.
631 *
632 * Parameters: p_inqparms - pointer to the inquiry information
633 * mode - GENERAL or LIMITED inquiry, BR/LE bit mask
634 * separately
635 * duration - length in 1.28 sec intervals (If '0', the
636 * inquiry is CANCELLED)
637 * filter_cond_type - BTM_CLR_INQUIRY_FILTER,
638 * BTM_FILTER_COND_DEVICE_CLASS, or
639 * BTM_FILTER_COND_BD_ADDR
640 * filter_cond - value for the filter (based on
641 * filter_cond_type)
642 *
643 * p_results_cb - Pointer to the callback routine which gets
644 * called upon receipt of an inquiry result. If
645 * this field is NULL, the application is not
646 * notified.
647 *
648 * p_cmpl_cb - Pointer to the callback routine which gets
649 * called upon completion. If this field is
650 * NULL, the application is not notified when
651 * completed.
652 * Returns tBTM_STATUS
653 * tBTM_STATUS::BTM_CMD_STARTED if successfully initiated
654 * tBTM_STATUS::BTM_BUSY if already in progress
655 * tBTM_STATUS::BTM_ILLEGAL_VALUE if parameter(s) are out of range
656 * tBTM_STATUS::BTM_NO_RESOURCES if could not allocate resources to start
657 * the command
658 * tBTM_STATUS::BTM_WRONG_MODE if the device is not up.
659 *
660 ******************************************************************************/
BTM_StartInquiry(tBTM_INQ_RESULTS_CB * p_results_cb,tBTM_CMPL_CB * p_cmpl_cb)661 tBTM_STATUS BTM_StartInquiry(tBTM_INQ_RESULTS_CB* p_results_cb, tBTM_CMPL_CB* p_cmpl_cb) {
662 /* Only one active inquiry is allowed in this implementation.
663 Also do not allow an inquiry if the inquiry filter is being updated */
664 if (btm_cb.btm_inq_vars.inq_active) {
665 log::warn(
666 "Active device discovery already in progress inq_active:0x{:02x} "
667 "state:{} counter:{}",
668 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
669 btm_cb.btm_inq_vars.inq_counter);
670 btm_cb.neighbor.inquiry_history_->Push({
671 .status = tBTM_INQUIRY_CMPL::NOT_STARTED,
672 });
673 return tBTM_STATUS::BTM_BUSY;
674 }
675
676 if (btm_cb.btm_inq_vars.registered_for_hci_events == false) {
677 bluetooth::shim::GetHciLayer()->RegisterEventHandler(
678 EventCode::INQUIRY_COMPLETE,
679 get_main_thread()->Bind([](EventView event) { on_incoming_hci_event(event); }));
680 bluetooth::shim::GetHciLayer()->RegisterEventHandler(
681 EventCode::INQUIRY_RESULT,
682 get_main_thread()->Bind([](EventView event) { on_incoming_hci_event(event); }));
683 bluetooth::shim::GetHciLayer()->RegisterEventHandler(
684 EventCode::INQUIRY_RESULT_WITH_RSSI,
685 get_main_thread()->Bind([](EventView event) { on_incoming_hci_event(event); }));
686 bluetooth::shim::GetHciLayer()->RegisterEventHandler(
687 EventCode::EXTENDED_INQUIRY_RESULT,
688 get_main_thread()->Bind([](EventView event) { on_incoming_hci_event(event); }));
689
690 btm_cb.btm_inq_vars.registered_for_hci_events = true;
691 }
692
693 /*** Make sure the device is ready ***/
694 if (!get_btm_client_interface().local.BTM_IsDeviceUp()) {
695 log::error("adapter is not up");
696 btm_cb.neighbor.inquiry_history_->Push({
697 .status = tBTM_INQUIRY_CMPL::NOT_STARTED,
698 });
699 return tBTM_STATUS::BTM_WRONG_MODE;
700 }
701
702 BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Classic inquiry started",
703 std::format("{}", (btm_cb.neighbor.classic_inquiry.start_time_ms == 0)
704 ? ""
705 : "ERROR Already in progress"));
706
707 const uint8_t inq_length =
708 osi_property_get_int32(PROPERTY_INQ_LENGTH, BTIF_DM_DEFAULT_INQ_MAX_DURATION);
709
710 /* Save the inquiry parameters to be used upon the completion of
711 * setting/clearing the inquiry filter */
712 btm_cb.btm_inq_vars.inqparms = {
713 // tBTM_INQ_PARMS
714 .mode = BTM_GENERAL_INQUIRY | BTM_BLE_GENERAL_INQUIRY,
715 .duration = inq_length,
716 };
717
718 /* Initialize the inquiry variables */
719 btm_cb.btm_inq_vars.state = BTM_INQ_ACTIVE_STATE;
720 btm_cb.btm_inq_vars.p_inq_cmpl_cb = p_cmpl_cb;
721 btm_cb.btm_inq_vars.p_inq_results_cb = p_results_cb;
722 btm_cb.btm_inq_vars.inq_cmpl_info = {}; /* Clear the results counter */
723 btm_cb.btm_inq_vars.inq_active = btm_cb.btm_inq_vars.inqparms.mode;
724 btm_cb.neighbor.classic_inquiry = {
725 .start_time_ms = timestamper_in_milliseconds.GetTimestamp(),
726 .results = 0,
727 };
728
729 log::debug("Starting device discovery inq_active:0x{:02x}", btm_cb.btm_inq_vars.inq_active);
730
731 // Also do BLE scanning here if we aren't limiting discovery to classic only.
732 // This path does not play nicely with GD BLE scanning and may cause issues
733 // with other scanners.
734 BTM_StartLeScan();
735
736 btm_clr_inq_result_flt();
737
738 btm_init_inq_result_flt();
739
740 Lap lap;
741 lap.lap_ = general_inq_lap[2];
742
743 // TODO: Register for the inquiry interface and use that
744 bluetooth::shim::GetHciLayer()->EnqueueCommand(
745 InquiryBuilder::Create(lap, btm_cb.btm_inq_vars.inqparms.duration, 0),
746 get_main_thread()->BindOnce([](CommandStatusView status_view) {
747 log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
748 auto status = status_view.GetStatus();
749 if (status == ErrorCode::SUCCESS) {
750 BTIF_dm_report_inquiry_status_change(tBTM_INQUIRY_STATE::BTM_INQUIRY_STARTED);
751 } else {
752 log::info("Inquiry failed to start status: {}", ErrorCodeText(status));
753 }
754 }));
755
756 #if TARGET_FLOSS
757 // If we are only doing classic discovery, we should also set a timeout for
758 // the inquiry if a duration is set.
759 if (btm_cb.btm_inq_vars.inqparms.duration != 0) {
760 /* start inquiry timer */
761 uint64_t duration_ms = btm_cb.btm_inq_vars.inqparms.duration * 1280;
762 alarm_set_on_mloop(btm_cb.btm_inq_vars.classic_inquiry_timer, duration_ms,
763 btm_classic_inquiry_timeout, NULL);
764 }
765 #endif
766
767 return tBTM_STATUS::BTM_CMD_STARTED;
768 }
769
770 /*******************************************************************************
771 *
772 * Function BTM_InqDbRead
773 *
774 * Description This function looks through the inquiry database for a match
775 * based on Bluetooth Device Address. This is the application's
776 * interface to get the inquiry details of a specific BD
777 * address.
778 *
779 * Returns pointer to entry, or NULL if not found
780 *
781 ******************************************************************************/
BTM_InqDbRead(const RawAddress & p_bda)782 tBTM_INQ_INFO* BTM_InqDbRead(const RawAddress& p_bda) {
783 tINQ_DB_ENT* p_ent = btm_inq_db_find(p_bda);
784 return (p_ent == nullptr) ? nullptr : &p_ent->inq_info;
785 }
786
787 /*******************************************************************************
788 *
789 * Function BTM_InqDbFirst
790 *
791 * Description This function looks through the inquiry database for the
792 * first used entry, and returns that. This is used in
793 * conjunction with
794 * BTM_InqDbNext by applications as a way to walk through the
795 * inquiry database.
796 *
797 * Returns pointer to first in-use entry, or NULL if DB is empty
798 *
799 ******************************************************************************/
BTM_InqDbFirst(void)800 tBTM_INQ_INFO* BTM_InqDbFirst(void) {
801 uint16_t xx;
802
803 std::lock_guard<std::mutex> lock(inq_db_lock_);
804 tINQ_DB_ENT* p_ent = inq_db_;
805 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
806 if (p_ent->in_use) {
807 return &p_ent->inq_info;
808 }
809 }
810
811 /* If here, no used entry found */
812 return nullptr;
813 }
814
815 /*******************************************************************************
816 *
817 * Function BTM_InqDbNext
818 *
819 * Description This function looks through the inquiry database for the
820 * next used entry, and returns that. If the input parameter
821 * is NULL, the first entry is returned.
822 *
823 * Returns pointer to next in-use entry, or NULL if no more found.
824 *
825 ******************************************************************************/
BTM_InqDbNext(tBTM_INQ_INFO * p_cur)826 tBTM_INQ_INFO* BTM_InqDbNext(tBTM_INQ_INFO* p_cur) {
827 uint16_t inx;
828
829 std::lock_guard<std::mutex> lock(inq_db_lock_);
830
831 if (p_cur) {
832 tINQ_DB_ENT* p_ent = (tINQ_DB_ENT*)((uint8_t*)p_cur - offsetof(tINQ_DB_ENT, inq_info));
833 inx = (uint16_t)((p_ent - inq_db_) + 1);
834
835 for (p_ent = &inq_db_[inx]; inx < BTM_INQ_DB_SIZE; inx++, p_ent++) {
836 if (p_ent->in_use) {
837 return &p_ent->inq_info;
838 }
839 }
840
841 /* If here, more entries found */
842 return nullptr;
843 } else {
844 return BTM_InqDbFirst();
845 }
846 }
847
848 /*******************************************************************************
849 *
850 * Function BTM_ClearInqDb
851 *
852 * Description This function is called to clear out a device or all devices
853 * from the inquiry database.
854 *
855 * Parameter p_bda - (input) BD_ADDR -> Address of device to clear
856 * (NULL clears all entries)
857 *
858 * Returns tBTM_STATUS::BTM_BUSY if an inquiry, get remote name, or event filter
859 * is active, otherwise tBTM_STATUS::BTM_SUCCESS
860 *
861 ******************************************************************************/
BTM_ClearInqDb(const RawAddress * p_bda)862 tBTM_STATUS BTM_ClearInqDb(const RawAddress* p_bda) {
863 /* If an inquiry or remote name is in progress return busy */
864 if (btm_cb.btm_inq_vars.inq_active != BTM_INQUIRY_INACTIVE) {
865 return tBTM_STATUS::BTM_BUSY;
866 }
867
868 btm_clr_inq_db(p_bda);
869
870 return tBTM_STATUS::BTM_SUCCESS;
871 }
872
873 /*******************************************************************************
874 *
875 * Function btm_clear_all_pending_le_entry
876 *
877 * Description This function is called to clear all LE pending entry in
878 * inquiry database.
879 *
880 * Returns void
881 *
882 ******************************************************************************/
btm_clear_all_pending_le_entry(void)883 static void btm_clear_all_pending_le_entry(void) {
884 uint16_t xx;
885 std::lock_guard<std::mutex> lock(inq_db_lock_);
886 tINQ_DB_ENT* p_ent = inq_db_;
887
888 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
889 /* mark all pending LE entry as unused if an LE only device has scan
890 * response outstanding */
891 if ((p_ent->in_use) && (p_ent->inq_info.results.device_type == BT_DEVICE_TYPE_BLE) &&
892 !p_ent->scan_rsp) {
893 p_ent->in_use = false;
894 }
895 }
896 }
897
898 /*******************************************************************************
899 *******************************************************************************
900 * **
901 * BTM Internal Inquiry Functions **
902 * **
903 *******************************************************************************
904 ******************************************************************************/
905 /*******************************************************************************
906 *
907 * Function btm_inq_db_reset
908 *
909 * Description This function is called at at reset to clear the inquiry
910 * database & pending callback.
911 *
912 * Returns void
913 *
914 ******************************************************************************/
btm_inq_db_reset(void)915 void btm_inq_db_reset(void) {
916 tBTM_REMOTE_DEV_NAME rem_name = {};
917 uint8_t num_responses;
918 uint8_t temp_inq_active;
919
920 log::debug("Resetting inquiry database");
921
922 /* If an inquiry or periodic inquiry is active, reset the mode to inactive */
923 if (btm_cb.btm_inq_vars.inq_active != BTM_INQUIRY_INACTIVE) {
924 /* Save so state can change BEFORE callback is called */
925 temp_inq_active = btm_cb.btm_inq_vars.inq_active;
926 btm_cb.btm_inq_vars.inq_active = BTM_INQUIRY_INACTIVE;
927
928 /* If not a periodic inquiry, the complete callback must be called to notify
929 * caller */
930 if (temp_inq_active == BTM_GENERAL_INQUIRY) {
931 if (btm_cb.btm_inq_vars.p_inq_cmpl_cb) {
932 num_responses = 0;
933 (*btm_cb.btm_inq_vars.p_inq_cmpl_cb)(&num_responses);
934 }
935 }
936 }
937
938 /* Cancel a remote name request if active, and notify the caller (if waiting)
939 */
940 if (btm_cb.rnr.remname_active) {
941 alarm_cancel(btm_cb.rnr.remote_name_timer);
942 btm_cb.rnr.remname_active = false;
943 btm_cb.rnr.remname_bda = RawAddress::kEmpty;
944 btm_cb.rnr.remname_dev_type = BT_DEVICE_TYPE_UNKNOWN;
945
946 if (btm_cb.rnr.p_remname_cmpl_cb) {
947 rem_name.btm_status = tBTM_STATUS::BTM_DEV_RESET;
948 rem_name.hci_status = HCI_SUCCESS;
949
950 (*btm_cb.rnr.p_remname_cmpl_cb)(&rem_name);
951 btm_cb.rnr.p_remname_cmpl_cb = NULL;
952 }
953 }
954
955 btm_cb.btm_inq_vars.state = BTM_INQ_INACTIVE_STATE;
956 btm_cb.btm_inq_vars.p_inq_results_cb = NULL;
957 btm_clr_inq_db(NULL); /* Clear out all the entries in the database */
958 btm_clr_inq_result_flt();
959
960 btm_cb.btm_inq_vars.discoverable_mode = BTM_NON_DISCOVERABLE;
961 btm_cb.btm_inq_vars.connectable_mode = BTM_NON_CONNECTABLE;
962 btm_cb.btm_inq_vars.page_scan_type = BTM_SCAN_TYPE_STANDARD;
963 btm_cb.btm_inq_vars.inq_scan_type = BTM_SCAN_TYPE_STANDARD;
964
965 btm_cb.btm_inq_vars.discoverable_mode |= BTM_BLE_NON_DISCOVERABLE;
966 btm_cb.btm_inq_vars.connectable_mode |= BTM_BLE_NON_CONNECTABLE;
967 return;
968 }
969
970 /*******************************************************************************
971 *
972 * Function btm_clr_inq_db
973 *
974 * Description This function is called to clear out a device or all devices
975 * from the inquiry database.
976 *
977 * Parameter p_bda - (input) BD_ADDR -> Address of device to clear
978 * (NULL clears all entries)
979 *
980 * Returns void
981 *
982 ******************************************************************************/
btm_clr_inq_db(const RawAddress * p_bda)983 static void btm_clr_inq_db(const RawAddress* p_bda) {
984 uint16_t xx;
985
986 #if (BTM_INQ_DEBUG == TRUE)
987 log::verbose("inq_active:0x{:x} state:{}", btm_cb.btm_inq_vars.inq_active,
988 btm_cb.btm_inq_vars.state);
989 #endif
990 std::lock_guard<std::mutex> lock(inq_db_lock_);
991 tINQ_DB_ENT* p_ent = inq_db_;
992 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
993 if (p_ent->in_use) {
994 /* If this is the specified BD_ADDR or clearing all devices */
995 if (p_bda == NULL || (p_ent->inq_info.results.remote_bd_addr == *p_bda)) {
996 p_ent->in_use = false;
997 }
998 }
999 }
1000 #if (BTM_INQ_DEBUG == TRUE)
1001 log::verbose("inq_active:0x{:x} state:{}", btm_cb.btm_inq_vars.inq_active,
1002 btm_cb.btm_inq_vars.state);
1003 #endif
1004 }
1005
1006 /*******************************************************************************
1007 *
1008 * Function btm_[init|clr]_inq_result_flt
1009 *
1010 * Description These functions initialize and clear the bdaddr
1011 * database for a match based on Bluetooth Device Address
1012 *
1013 * Returns None
1014 *
1015 ******************************************************************************/
btm_init_inq_result_flt(void)1016 static void btm_init_inq_result_flt(void) {
1017 std::lock_guard<std::mutex> lock(bd_db_lock_);
1018
1019 if (p_bd_db_ != nullptr) {
1020 log::error("Memory leak with bluetooth device database");
1021 }
1022
1023 /* Allocate memory to hold bd_addrs responding */
1024 p_bd_db_ = (tINQ_BDADDR*)osi_calloc(BT_DEFAULT_BUFFER_SIZE);
1025 max_bd_entries_ = (uint16_t)(BT_DEFAULT_BUFFER_SIZE / sizeof(tINQ_BDADDR));
1026 }
1027
btm_clr_inq_result_flt(void)1028 void btm_clr_inq_result_flt(void) {
1029 std::lock_guard<std::mutex> lock(bd_db_lock_);
1030 if (p_bd_db_ == nullptr) {
1031 log::warn("Memory being reset multiple times");
1032 }
1033
1034 osi_free_and_reset((void**)&p_bd_db_);
1035 num_bd_entries_ = 0;
1036 max_bd_entries_ = 0;
1037 }
1038
1039 /*******************************************************************************
1040 *
1041 * Function btm_inq_find_bdaddr
1042 *
1043 * Description This function looks through the bdaddr database for a match
1044 * based on Bluetooth Device Address
1045 *
1046 * Returns true if found, else false (new entry)
1047 *
1048 ******************************************************************************/
btm_inq_find_bdaddr(const RawAddress & p_bda)1049 bool btm_inq_find_bdaddr(const RawAddress& p_bda) {
1050 std::lock_guard<std::mutex> lock(bd_db_lock_);
1051 tINQ_BDADDR* p_db = p_bd_db_;
1052 uint16_t xx;
1053
1054 /* Don't bother searching, database doesn't exist or periodic mode */
1055 if (!p_db) {
1056 return false;
1057 }
1058
1059 for (xx = 0; xx < num_bd_entries_; xx++, p_db++) {
1060 if (p_db->bd_addr == p_bda && p_db->inq_count == btm_cb.btm_inq_vars.inq_counter) {
1061 return true;
1062 }
1063 }
1064
1065 if (xx < max_bd_entries_) {
1066 p_db->inq_count = btm_cb.btm_inq_vars.inq_counter;
1067 p_db->bd_addr = p_bda;
1068 num_bd_entries_++;
1069 }
1070
1071 /* If here, New Entry */
1072 return false;
1073 }
1074
1075 /*******************************************************************************
1076 *
1077 * Function btm_inq_db_find
1078 *
1079 * Description This function looks through the inquiry database for a match
1080 * based on Bluetooth Device Address
1081 *
1082 * Returns pointer to entry, or NULL if not found
1083 *
1084 ******************************************************************************/
btm_inq_db_find(const RawAddress & p_bda)1085 tINQ_DB_ENT* btm_inq_db_find(const RawAddress& p_bda) {
1086 uint16_t xx;
1087 std::lock_guard<std::mutex> lock(inq_db_lock_);
1088 tINQ_DB_ENT* p_ent = inq_db_;
1089
1090 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1091 if (p_ent->in_use && p_ent->inq_info.results.remote_bd_addr == p_bda) {
1092 return p_ent;
1093 }
1094 }
1095
1096 /* If here, not found */
1097 return nullptr;
1098 }
1099
1100 /*******************************************************************************
1101 *
1102 * Function btm_inq_db_new
1103 *
1104 * Description This function looks through the inquiry database for an
1105 * unused entry. If no entry is free, it allocates the oldest
1106 * entry.
1107 *
1108 * Returns pointer to entry
1109 *
1110 ******************************************************************************/
btm_inq_db_new(const RawAddress & p_bda,bool is_ble)1111 tINQ_DB_ENT* btm_inq_db_new(const RawAddress& p_bda, bool is_ble) {
1112 uint16_t xx = 0, yy = 0;
1113 uint32_t ot = 0xFFFFFFFF;
1114 int8_t i_rssi = 0;
1115
1116 if (is_ble) {
1117 yy = BTM_INQ_DB_SIZE / 2;
1118 } else {
1119 yy = 0;
1120 }
1121
1122 std::lock_guard<std::mutex> lock(inq_db_lock_);
1123 tINQ_DB_ENT* p_ent = &inq_db_[yy];
1124 tINQ_DB_ENT* p_old = &inq_db_[yy];
1125
1126 for (xx = 0; xx < BTM_INQ_DB_SIZE / 2; xx++, p_ent++) {
1127 if (!p_ent->in_use) {
1128 memset(p_ent, 0, sizeof(tINQ_DB_ENT));
1129 p_ent->inq_info.results.remote_bd_addr = p_bda;
1130 p_ent->in_use = true;
1131
1132 return p_ent;
1133 }
1134
1135 if (is_inquery_by_rssi()) {
1136 if (p_ent->inq_info.results.rssi < i_rssi) {
1137 p_old = p_ent;
1138 i_rssi = p_ent->inq_info.results.rssi;
1139 }
1140 } else {
1141 if (p_ent->time_of_resp < ot) {
1142 p_old = p_ent;
1143 ot = p_ent->time_of_resp;
1144 }
1145 }
1146 }
1147
1148 /* If here, no free entry found. Return the oldest. */
1149
1150 memset(p_old, 0, sizeof(tINQ_DB_ENT));
1151 p_old->inq_info.results.remote_bd_addr = p_bda;
1152 p_old->in_use = true;
1153
1154 return p_old;
1155 }
1156
1157 /*******************************************************************************
1158 *
1159 * Function btm_process_inq_results_standard
1160 *
1161 * Description This function is called when inquiry results are received
1162 * from the device. It updates the inquiry database. If the
1163 * inquiry database is full, the oldest entry is discarded.
1164 *
1165 * Returns void
1166 *
1167 ******************************************************************************/
btm_process_inq_results_standard(EventView event)1168 static void btm_process_inq_results_standard(EventView event) {
1169 RawAddress bda;
1170 tINQ_DB_ENT* p_i;
1171 tBTM_INQ_RESULTS* p_cur = NULL;
1172 bool is_new = true;
1173 tBTM_INQ_RESULTS_CB* p_inq_results_cb = btm_cb.btm_inq_vars.p_inq_results_cb;
1174 uint8_t page_scan_rep_mode = 0;
1175 uint8_t page_scan_per_mode = 0;
1176 uint8_t page_scan_mode = 0;
1177 DEV_CLASS dc;
1178 uint16_t clock_offset;
1179 const uint8_t* p_eir_data = NULL;
1180
1181 log::debug("Received inquiry result inq_active:0x{:x} state:{}", btm_cb.btm_inq_vars.inq_active,
1182 btm_cb.btm_inq_vars.state);
1183
1184 /* Only process the results if the BR inquiry is still active */
1185 if (!(btm_cb.btm_inq_vars.inq_active & BTM_GENERAL_INQUIRY)) {
1186 log::info("Inquiry is inactive so dropping inquiry result");
1187 return;
1188 }
1189
1190 auto standard_view = InquiryResultView::Create(event);
1191 log::assert_that(standard_view.IsValid(), "assert failed: standard_view.IsValid()");
1192 auto responses = standard_view.GetResponses();
1193
1194 btm_cb.neighbor.classic_inquiry.results += responses.size();
1195 for (const auto& response : responses) {
1196 /* Extract inquiry results */
1197 bda = bluetooth::ToRawAddress(response.bd_addr_);
1198 page_scan_rep_mode = static_cast<uint8_t>(response.page_scan_repetition_mode_);
1199 page_scan_per_mode = 0; // reserved
1200 page_scan_mode = 0; // reserved
1201
1202 dc[0] = response.class_of_device_.cod[2];
1203 dc[1] = response.class_of_device_.cod[1];
1204 dc[2] = response.class_of_device_.cod[0];
1205
1206 clock_offset = response.clock_offset_;
1207
1208 p_i = btm_inq_db_find(bda);
1209
1210 /* If existing entry, use that, else get a new one (possibly reusing the
1211 * oldest) */
1212 if (p_i == NULL) {
1213 p_i = btm_inq_db_new(bda, false);
1214 is_new = true;
1215 } else {
1216 /* If an entry for the device already exists, overwrite it ONLY if it is
1217 from a previous inquiry. (Ignore it if it is a duplicate response from
1218 the same inquiry.
1219 */
1220 if (p_i->inq_count == btm_cb.btm_inq_vars.inq_counter &&
1221 (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR)) {
1222 is_new = false;
1223 }
1224 }
1225
1226 p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
1227
1228 if (is_new) {
1229 /* Save the info */
1230 p_cur = &p_i->inq_info.results;
1231 p_cur->page_scan_rep_mode = page_scan_rep_mode;
1232 p_cur->page_scan_per_mode = page_scan_per_mode;
1233 p_cur->page_scan_mode = page_scan_mode;
1234 p_cur->dev_class[0] = dc[0];
1235 p_cur->dev_class[1] = dc[1];
1236 p_cur->dev_class[2] = dc[2];
1237 p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
1238
1239 p_i->time_of_resp = bluetooth::common::time_get_os_boottime_ms();
1240
1241 if (p_i->inq_count != btm_cb.btm_inq_vars.inq_counter) {
1242 /* A new response was found */
1243 btm_cb.btm_inq_vars.inq_cmpl_info.num_resp++;
1244 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_STANDARD]++;
1245 }
1246
1247 p_cur->inq_result_type |= BT_DEVICE_TYPE_BREDR;
1248 if (p_i->inq_count != btm_cb.btm_inq_vars.inq_counter) {
1249 p_cur->device_type = BT_DEVICE_TYPE_BREDR;
1250 p_i->scan_rsp = false;
1251 } else {
1252 p_cur->device_type |= BT_DEVICE_TYPE_BREDR;
1253 }
1254 p_i->inq_count = btm_cb.btm_inq_vars.inq_counter; /* Mark entry for current inquiry */
1255
1256 /* Initialize flag to false. This flag is set/used by application */
1257 p_i->inq_info.appl_knows_rem_name = false;
1258 }
1259
1260 if (is_new) {
1261 p_eir_data = NULL;
1262
1263 /* If a callback is registered, call it with the results */
1264 if (p_inq_results_cb) {
1265 (p_inq_results_cb)((tBTM_INQ_RESULTS*)p_cur, p_eir_data, HCI_EXT_INQ_RESPONSE_LEN);
1266 } else {
1267 log::warn("No callback is registered for inquiry result");
1268 }
1269 }
1270 }
1271 }
1272
1273 /*******************************************************************************
1274 *
1275 * Function btm_process_inq_results_rssi
1276 *
1277 * Description This function is called when inquiry results are received
1278 * from the device. It updates the inquiry database. If the
1279 * inquiry database is full, the oldest entry is discarded.
1280 *
1281 * Returns void
1282 *
1283 ******************************************************************************/
btm_process_inq_results_rssi(EventView event)1284 static void btm_process_inq_results_rssi(EventView event) {
1285 RawAddress bda;
1286 tINQ_DB_ENT* p_i;
1287 tBTM_INQ_RESULTS* p_cur = NULL;
1288 bool is_new = true;
1289 bool update = false;
1290 int8_t i_rssi;
1291 tBTM_INQ_RESULTS_CB* p_inq_results_cb = btm_cb.btm_inq_vars.p_inq_results_cb;
1292 uint8_t page_scan_rep_mode = 0;
1293 uint8_t page_scan_per_mode = 0;
1294 uint8_t page_scan_mode = 0;
1295 uint8_t rssi = 0;
1296 DEV_CLASS dc;
1297 uint16_t clock_offset;
1298 const uint8_t* p_eir_data = NULL;
1299
1300 log::debug("Received inquiry result inq_active:0x{:x} state:{}", btm_cb.btm_inq_vars.inq_active,
1301 btm_cb.btm_inq_vars.state);
1302
1303 /* Only process the results if the BR inquiry is still active */
1304 if (!(btm_cb.btm_inq_vars.inq_active & BTM_GENERAL_INQUIRY)) {
1305 log::info("Inquiry is inactive so dropping inquiry result");
1306 return;
1307 }
1308
1309 auto rssi_view = InquiryResultWithRssiView::Create(event);
1310 log::assert_that(rssi_view.IsValid(), "assert failed: rssi_view.IsValid()");
1311 auto responses = rssi_view.GetResponses();
1312
1313 btm_cb.neighbor.classic_inquiry.results += responses.size();
1314 for (const auto& response : responses) {
1315 update = false;
1316 /* Extract inquiry results */
1317 bda = bluetooth::ToRawAddress(response.address_);
1318 page_scan_rep_mode = static_cast<uint8_t>(response.page_scan_repetition_mode_);
1319 page_scan_per_mode = 0; // reserved
1320 page_scan_mode = 0; // reserved
1321
1322 dc[0] = response.class_of_device_.cod[2];
1323 dc[1] = response.class_of_device_.cod[1];
1324 dc[2] = response.class_of_device_.cod[0];
1325
1326 clock_offset = response.clock_offset_;
1327 rssi = response.rssi_;
1328
1329 p_i = btm_inq_db_find(bda);
1330
1331 /* Check if this address has already been processed for this inquiry */
1332 if (btm_inq_find_bdaddr(bda)) {
1333 /* By default suppose no update needed */
1334 i_rssi = (int8_t)rssi;
1335
1336 /* If this new RSSI is higher than the last one */
1337 if ((rssi != 0) && p_i &&
1338 (i_rssi > p_i->inq_info.results.rssi ||
1339 p_i->inq_info.results.rssi == 0
1340 /* BR/EDR inquiry information update */
1341 || (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)) {
1342 p_cur = &p_i->inq_info.results;
1343 log::verbose("update RSSI new:{}, old:{}", i_rssi, p_cur->rssi);
1344 p_cur->rssi = i_rssi;
1345 update = true;
1346 } else {
1347 /* If no update needed continue with next response (if any) */
1348 continue;
1349 }
1350 }
1351
1352 /* If existing entry, use that, else get a new one (possibly reusing the
1353 * oldest) */
1354 if (p_i == NULL) {
1355 p_i = btm_inq_db_new(bda, false);
1356 is_new = true;
1357 } else {
1358 /* If an entry for the device already exists, overwrite it ONLY if it is
1359 from a previous inquiry. (Ignore it if it is a duplicate response from
1360 the same inquiry.
1361 */
1362 if (p_i->inq_count == btm_cb.btm_inq_vars.inq_counter &&
1363 (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR)) {
1364 is_new = false;
1365 }
1366 }
1367
1368 /* keep updating RSSI to have latest value */
1369 p_i->inq_info.results.rssi = (int8_t)rssi;
1370
1371 if (is_new) {
1372 /* Save the info */
1373 p_cur = &p_i->inq_info.results;
1374 p_cur->page_scan_rep_mode = page_scan_rep_mode;
1375 p_cur->page_scan_per_mode = page_scan_per_mode;
1376 p_cur->page_scan_mode = page_scan_mode;
1377 p_cur->dev_class[0] = dc[0];
1378 p_cur->dev_class[1] = dc[1];
1379 p_cur->dev_class[2] = dc[2];
1380 p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
1381
1382 p_i->time_of_resp = bluetooth::common::time_get_os_boottime_ms();
1383
1384 if (p_i->inq_count != btm_cb.btm_inq_vars.inq_counter) {
1385 /* A new response was found */
1386 btm_cb.btm_inq_vars.inq_cmpl_info.num_resp++;
1387 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_WITH_RSSI]++;
1388 }
1389
1390 p_cur->inq_result_type |= BT_DEVICE_TYPE_BREDR;
1391 if (p_i->inq_count != btm_cb.btm_inq_vars.inq_counter) {
1392 p_cur->device_type = BT_DEVICE_TYPE_BREDR;
1393 p_i->scan_rsp = false;
1394 } else {
1395 p_cur->device_type |= BT_DEVICE_TYPE_BREDR;
1396 }
1397 p_i->inq_count = btm_cb.btm_inq_vars.inq_counter; /* Mark entry for current inquiry */
1398
1399 /* Initialize flag to false. This flag is set/used by application */
1400 p_i->inq_info.appl_knows_rem_name = false;
1401 }
1402
1403 if (is_new || update) {
1404 p_eir_data = NULL;
1405
1406 /* If a callback is registered, call it with the results */
1407 if (p_inq_results_cb) {
1408 (p_inq_results_cb)((tBTM_INQ_RESULTS*)p_cur, p_eir_data, HCI_EXT_INQ_RESPONSE_LEN);
1409 } else {
1410 log::warn("No callback is registered for inquiry result");
1411 }
1412 }
1413 }
1414 }
1415
1416 /*******************************************************************************
1417 *
1418 * Function btm_process_inq_results_extended
1419 *
1420 * Description This function is called when inquiry results are received
1421 * from the device. It updates the inquiry database. If the
1422 * inquiry database is full, the oldest entry is discarded.
1423 *
1424 * Returns void
1425 *
1426 ******************************************************************************/
btm_process_inq_results_extended(EventView event)1427 static void btm_process_inq_results_extended(EventView event) {
1428 RawAddress bda;
1429 tINQ_DB_ENT* p_i;
1430 tBTM_INQ_RESULTS* p_cur = NULL;
1431 bool is_new = true;
1432 bool update = false;
1433 int8_t i_rssi;
1434 tBTM_INQ_RESULTS_CB* p_inq_results_cb = btm_cb.btm_inq_vars.p_inq_results_cb;
1435 uint8_t page_scan_rep_mode = 0;
1436 uint8_t page_scan_per_mode = 0;
1437 uint8_t page_scan_mode = 0;
1438 uint8_t rssi = 0;
1439 DEV_CLASS dc;
1440 uint16_t clock_offset;
1441
1442 log::debug("Received inquiry result inq_active:0x{:x} state:{}", btm_cb.btm_inq_vars.inq_active,
1443 btm_cb.btm_inq_vars.state);
1444
1445 /* Only process the results if the BR inquiry is still active */
1446 if (!(btm_cb.btm_inq_vars.inq_active & BTM_GENERAL_INQUIRY)) {
1447 log::info("Inquiry is inactive so dropping inquiry result");
1448 return;
1449 }
1450
1451 auto extended_view = ExtendedInquiryResultView::Create(event);
1452 log::assert_that(extended_view.IsValid(), "assert failed: extended_view.IsValid()");
1453
1454 btm_cb.neighbor.classic_inquiry.results++;
1455 {
1456 update = false;
1457 /* Extract inquiry results */
1458 bda = bluetooth::ToRawAddress(extended_view.GetAddress());
1459 page_scan_rep_mode = static_cast<uint8_t>(extended_view.GetPageScanRepetitionMode());
1460 page_scan_per_mode = 0; // reserved
1461
1462 dc[0] = extended_view.GetClassOfDevice().cod[2];
1463 dc[1] = extended_view.GetClassOfDevice().cod[1];
1464 dc[2] = extended_view.GetClassOfDevice().cod[0];
1465 clock_offset = extended_view.GetClockOffset();
1466 rssi = extended_view.GetRssi();
1467
1468 p_i = btm_inq_db_find(bda);
1469
1470 /* Check if this address has already been processed for this inquiry */
1471 if (btm_inq_find_bdaddr(bda)) {
1472 /* By default suppose no update needed */
1473 i_rssi = (int8_t)rssi;
1474
1475 /* If this new RSSI is higher than the last one */
1476 if ((rssi != 0) && p_i &&
1477 (i_rssi > p_i->inq_info.results.rssi ||
1478 p_i->inq_info.results.rssi == 0
1479 /* BR/EDR inquiry information update */
1480 || (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)) {
1481 p_cur = &p_i->inq_info.results;
1482 log::verbose("update RSSI new:{}, old:{}", i_rssi, p_cur->rssi);
1483 p_cur->rssi = i_rssi;
1484 update = true;
1485 } else {
1486 /* If we received a second Extended Inq Event for an already */
1487 /* discovered device, this is because for the first one EIR was not
1488 received */
1489 if (p_i) {
1490 p_cur = &p_i->inq_info.results;
1491 update = true;
1492 } else {
1493 /* If no update needed continue with next response (if any) */
1494 return;
1495 }
1496 }
1497 }
1498
1499 /* If existing entry, use that, else get a new one (possibly reusing the
1500 * oldest) */
1501 if (p_i == NULL) {
1502 p_i = btm_inq_db_new(bda, false);
1503 is_new = true;
1504 } else {
1505 /* If an entry for the device already exists, overwrite it ONLY if it is
1506 from
1507 a previous inquiry. (Ignore it if it is a duplicate response from the
1508 same
1509 inquiry.
1510 */
1511 if (p_i->inq_count == btm_cb.btm_inq_vars.inq_counter &&
1512 (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR)) {
1513 is_new = false;
1514 }
1515 }
1516
1517 /* keep updating RSSI to have latest value */
1518 p_i->inq_info.results.rssi = (int8_t)rssi;
1519
1520 if (is_new) {
1521 /* Save the info */
1522 p_cur = &p_i->inq_info.results;
1523 p_cur->page_scan_rep_mode = page_scan_rep_mode;
1524 p_cur->page_scan_per_mode = page_scan_per_mode;
1525 p_cur->page_scan_mode = page_scan_mode;
1526 p_cur->dev_class[0] = dc[0];
1527 p_cur->dev_class[1] = dc[1];
1528 p_cur->dev_class[2] = dc[2];
1529 p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
1530
1531 p_i->time_of_resp = bluetooth::common::time_get_os_boottime_ms();
1532
1533 if (p_i->inq_count != btm_cb.btm_inq_vars.inq_counter) {
1534 /* A new response was found */
1535 btm_cb.btm_inq_vars.inq_cmpl_info.num_resp++;
1536 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_EXTENDED]++;
1537 }
1538
1539 p_cur->inq_result_type |= BT_DEVICE_TYPE_BREDR;
1540 if (p_i->inq_count != btm_cb.btm_inq_vars.inq_counter) {
1541 p_cur->device_type = BT_DEVICE_TYPE_BREDR;
1542 p_i->scan_rsp = false;
1543 } else {
1544 p_cur->device_type |= BT_DEVICE_TYPE_BREDR;
1545 }
1546 p_i->inq_count = btm_cb.btm_inq_vars.inq_counter; /* Mark entry for current inquiry */
1547
1548 /* Initialize flag to false. This flag is set/used by application */
1549 p_i->inq_info.appl_knows_rem_name = false;
1550 }
1551
1552 if (is_new || update) {
1553 // Create a vector of EIR data and pad it with 0
1554 auto data = std::vector<uint8_t>();
1555 data.reserve(HCI_EXT_INQ_RESPONSE_LEN);
1556 bluetooth::packet::BitInserter bi(data);
1557 for (const auto& eir : extended_view.GetExtendedInquiryResponse()) {
1558 if (eir.data_type_ != static_cast<GapDataType>(0)) {
1559 eir.Serialize(bi);
1560 }
1561 }
1562 while (data.size() < HCI_EXT_INQ_RESPONSE_LEN) {
1563 data.push_back(0);
1564 }
1565
1566 const uint8_t* p_eir_data = data.data();
1567
1568 {
1569 memset(p_cur->eir_uuid, 0, BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS / 8));
1570 /* set bit map of UUID list from received EIR */
1571 btm_set_eir_uuid(p_eir_data, p_cur);
1572 }
1573
1574 /* If a callback is registered, call it with the results */
1575 if (p_inq_results_cb) {
1576 (p_inq_results_cb)((tBTM_INQ_RESULTS*)p_cur, p_eir_data, HCI_EXT_INQ_RESPONSE_LEN);
1577 } else {
1578 log::warn("No callback is registered for inquiry result");
1579 }
1580 }
1581 }
1582 }
1583
1584 /*******************************************************************************
1585 *
1586 * Function btm_sort_inq_result
1587 *
1588 * Description This function is called when inquiry complete is received
1589 * from the device to sort inquiry results based on rssi.
1590 *
1591 * Returns void
1592 *
1593 ******************************************************************************/
btm_sort_inq_result(void)1594 static void btm_sort_inq_result(void) {
1595 uint8_t xx, yy, num_resp;
1596 std::lock_guard<std::mutex> lock(inq_db_lock_);
1597 tINQ_DB_ENT* p_ent = inq_db_;
1598 tINQ_DB_ENT* p_next = inq_db_ + 1;
1599 int size;
1600 tINQ_DB_ENT* p_tmp = (tINQ_DB_ENT*)osi_malloc(sizeof(tINQ_DB_ENT));
1601
1602 num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp < BTM_INQ_DB_SIZE)
1603 ? btm_cb.btm_inq_vars.inq_cmpl_info.num_resp
1604 : BTM_INQ_DB_SIZE;
1605
1606 size = sizeof(tINQ_DB_ENT);
1607 for (xx = 0; xx < num_resp - 1; xx++, p_ent++) {
1608 for (yy = xx + 1, p_next = p_ent + 1; yy < num_resp; yy++, p_next++) {
1609 if (p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi) {
1610 memcpy(p_tmp, p_next, size);
1611 memcpy(p_next, p_ent, size);
1612 memcpy(p_ent, p_tmp, size);
1613 }
1614 }
1615 }
1616
1617 osi_free(p_tmp);
1618 }
1619
1620 /*******************************************************************************
1621 *
1622 * Function btm_process_inq_complete
1623 *
1624 * Description This function is called when inquiry complete is received
1625 * from the device. Call the callback if not in periodic
1626 * inquiry mode AND it is not NULL
1627 * (The caller wants the event).
1628 *
1629 * The callback pass back the status and the number of
1630 * responses
1631 *
1632 * Returns void
1633 *
1634 ******************************************************************************/
btm_process_inq_complete(tHCI_STATUS status,uint8_t mode)1635 void btm_process_inq_complete(tHCI_STATUS status, uint8_t mode) {
1636 btm_cb.btm_inq_vars.inqparms.mode &= ~(mode);
1637 const auto inq_active = btm_cb.btm_inq_vars.inq_active;
1638
1639 BTIF_dm_report_inquiry_status_change(tBTM_INQUIRY_STATE::BTM_INQUIRY_COMPLETE);
1640
1641 if (status != HCI_SUCCESS) {
1642 log::warn("Received unexpected hci status:{}", hci_error_code_text(status));
1643 }
1644
1645 /* Ignore any stray or late complete messages if the inquiry is not active */
1646 if (btm_cb.btm_inq_vars.inq_active) {
1647 btm_cb.btm_inq_vars.inq_cmpl_info.hci_status = status;
1648
1649 /* Notify caller that the inquiry has completed; (periodic inquiries do not
1650 * send completion events */
1651 if (btm_cb.btm_inq_vars.inqparms.mode == 0) {
1652 btm_clear_all_pending_le_entry();
1653 btm_cb.btm_inq_vars.state = BTM_INQ_INACTIVE_STATE;
1654
1655 /* Increment so the start of a next inquiry has a new count */
1656 btm_cb.btm_inq_vars.inq_counter++;
1657
1658 btm_clr_inq_result_flt();
1659
1660 if ((status == HCI_SUCCESS) &&
1661 bluetooth::shim::GetController()->SupportsRssiWithInquiryResults()) {
1662 btm_sort_inq_result();
1663 }
1664
1665 if (btm_cb.btm_inq_vars.p_inq_cmpl_cb) {
1666 (btm_cb.btm_inq_vars.p_inq_cmpl_cb)((tBTM_INQUIRY_CMPL*)&btm_cb.btm_inq_vars.inq_cmpl_info);
1667 } else {
1668 log::warn("No callback to return inquiry result");
1669 }
1670
1671 btm_cb.neighbor.inquiry_history_->Push({
1672 .status = tBTM_INQUIRY_CMPL::TIMER_POPPED,
1673 .num_resp = btm_cb.btm_inq_vars.inq_cmpl_info.num_resp,
1674 .resp_type =
1675 {
1676 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_STANDARD],
1677 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_WITH_RSSI],
1678 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_EXTENDED],
1679 },
1680 .start_time_ms = btm_cb.neighbor.classic_inquiry.start_time_ms,
1681 });
1682 const auto end_time_ms = timestamper_in_milliseconds.GetTimestamp();
1683 BTM_LogHistory(
1684 kBtmLogTag, RawAddress::kEmpty, "Classic inquiry complete",
1685 std::format("duration_s:{:6.3f} results:{} inq_active:0x{:02x} std:{} rssi:{} ext:{} "
1686 "status:{}",
1687 (end_time_ms - btm_cb.neighbor.classic_inquiry.start_time_ms) / 1000.0,
1688 btm_cb.neighbor.classic_inquiry.results, inq_active,
1689 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_STANDARD],
1690 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_WITH_RSSI],
1691 btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_EXTENDED],
1692 hci_error_code_text(status)));
1693
1694 btm_cb.neighbor.classic_inquiry.start_time_ms = 0;
1695 /* Clear the results callback if set */
1696 btm_cb.btm_inq_vars.p_inq_results_cb = NULL;
1697 btm_cb.btm_inq_vars.inq_active = BTM_INQUIRY_INACTIVE;
1698 btm_cb.btm_inq_vars.p_inq_cmpl_cb = NULL;
1699
1700 } else {
1701 log::info("Inquiry params is not clear so not sending callback inq_parms:{}",
1702 btm_cb.btm_inq_vars.inqparms.mode);
1703 }
1704 } else {
1705 log::error("Received inquiry complete when no inquiry was active");
1706 }
1707 }
1708
1709 /*******************************************************************************
1710 *
1711 * Function btm_process_cancel_complete
1712 *
1713 * Description This function is called when inquiry cancel complete is
1714 * received from the device. This function will also call the
1715 * btm_process_inq_complete. This function is needed to
1716 * differentiate a cancel_cmpl_evt from the inq_cmpl_evt.
1717 *
1718 * Returns void
1719 *
1720 ******************************************************************************/
btm_process_cancel_complete(tHCI_STATUS status,uint8_t mode)1721 static void btm_process_cancel_complete(tHCI_STATUS status, uint8_t mode) {
1722 BTIF_dm_report_inquiry_status_change(tBTM_INQUIRY_STATE::BTM_INQUIRY_CANCELLED);
1723 btm_process_inq_complete(status, mode);
1724 }
1725
1726 /*******************************************************************************
1727 *
1728 * Function BTM_WriteEIR
1729 *
1730 * Description This function is called to write EIR data to controller.
1731 *
1732 * Parameters p_buff - allocated HCI command buffer including extended
1733 * inquriry response
1734 *
1735 * Returns tBTM_STATUS::BTM_SUCCESS - if successful
1736 * tBTM_STATUS::BTM_MODE_UNSUPPORTED - if local device cannot support it
1737 *
1738 ******************************************************************************/
BTM_WriteEIR(BT_HDR * p_buff)1739 tBTM_STATUS BTM_WriteEIR(BT_HDR* p_buff) {
1740 if (bluetooth::shim::GetController()->SupportsExtendedInquiryResponse()) {
1741 log::verbose("Write Extended Inquiry Response to controller");
1742 btsnd_hcic_write_ext_inquiry_response(p_buff, TRUE);
1743 return tBTM_STATUS::BTM_SUCCESS;
1744 } else {
1745 osi_free(p_buff);
1746 return tBTM_STATUS::BTM_MODE_UNSUPPORTED;
1747 }
1748 }
1749
1750 /*******************************************************************************
1751 *
1752 * Function btm_convert_uuid_to_eir_service
1753 *
1754 * Description This function is called to get the bit position of UUID.
1755 *
1756 * Parameters uuid16 - UUID 16-bit
1757 *
1758 * Returns BTM EIR service ID if found
1759 * BTM_EIR_MAX_SERVICES - if not found
1760 *
1761 ******************************************************************************/
btm_convert_uuid_to_eir_service(uint16_t uuid16)1762 static uint8_t btm_convert_uuid_to_eir_service(uint16_t uuid16) {
1763 uint8_t xx;
1764
1765 for (xx = 0; xx < BTM_EIR_MAX_SERVICES; xx++) {
1766 if (uuid16 == BTM_EIR_UUID_LKUP_TBL[xx]) {
1767 return xx;
1768 }
1769 }
1770 return BTM_EIR_MAX_SERVICES;
1771 }
1772
1773 /*******************************************************************************
1774 *
1775 * Function BTM_HasEirService
1776 *
1777 * Description This function is called to know if UUID in bit map of UUID.
1778 *
1779 * Parameters p_eir_uuid - bit map of UUID list
1780 * uuid16 - UUID 16-bit
1781 *
1782 * Returns true - if found
1783 * false - if not found
1784 *
1785 ******************************************************************************/
BTM_HasEirService(const uint32_t * p_eir_uuid,uint16_t uuid16)1786 bool BTM_HasEirService(const uint32_t* p_eir_uuid, uint16_t uuid16) {
1787 uint8_t service_id;
1788
1789 service_id = btm_convert_uuid_to_eir_service(uuid16);
1790 if (service_id < BTM_EIR_MAX_SERVICES) {
1791 return BTM_EIR_HAS_SERVICE(p_eir_uuid, service_id);
1792 } else {
1793 return false;
1794 }
1795 }
1796
1797 /*******************************************************************************
1798 *
1799 * Function BTM_AddEirService
1800 *
1801 * Description This function is called to add a service in bit map of UUID
1802 * list.
1803 *
1804 * Parameters p_eir_uuid - bit mask of UUID list for EIR
1805 * uuid16 - UUID 16-bit
1806 *
1807 * Returns None
1808 *
1809 ******************************************************************************/
BTM_AddEirService(uint32_t * p_eir_uuid,uint16_t uuid16)1810 void BTM_AddEirService(uint32_t* p_eir_uuid, uint16_t uuid16) {
1811 uint8_t service_id;
1812
1813 service_id = btm_convert_uuid_to_eir_service(uuid16);
1814 if (service_id < BTM_EIR_MAX_SERVICES) {
1815 BTM_EIR_SET_SERVICE(p_eir_uuid, service_id);
1816 }
1817 }
1818
1819 /*******************************************************************************
1820 *
1821 * Function BTM_RemoveEirService
1822 *
1823 * Description This function is called to remove a service in bit map of
1824 * UUID list.
1825 *
1826 * Parameters p_eir_uuid - bit mask of UUID list for EIR
1827 * uuid16 - UUID 16-bit
1828 *
1829 * Returns None
1830 *
1831 ******************************************************************************/
BTM_RemoveEirService(uint32_t * p_eir_uuid,uint16_t uuid16)1832 void BTM_RemoveEirService(uint32_t* p_eir_uuid, uint16_t uuid16) {
1833 uint8_t service_id;
1834
1835 service_id = btm_convert_uuid_to_eir_service(uuid16);
1836 if (service_id < BTM_EIR_MAX_SERVICES) {
1837 BTM_EIR_CLR_SERVICE(p_eir_uuid, service_id);
1838 }
1839 }
1840
1841 /*******************************************************************************
1842 *
1843 * Function BTM_GetEirSupportedServices
1844 *
1845 * Description This function is called to get UUID list from bit map of
1846 * UUID list.
1847 *
1848 * Parameters p_eir_uuid - bit mask of UUID list for EIR
1849 * p - reference of current pointer of EIR
1850 * max_num_uuid16 - max number of UUID can be written in EIR
1851 * num_uuid16 - number of UUID have been written in EIR
1852 *
1853 * Returns HCI_EIR_MORE_16BITS_UUID_TYPE, if it has more than max
1854 * HCI_EIR_COMPLETE_16BITS_UUID_TYPE, otherwise
1855 *
1856 ******************************************************************************/
BTM_GetEirSupportedServices(uint32_t * p_eir_uuid,uint8_t ** p,uint8_t max_num_uuid16,uint8_t * p_num_uuid16)1857 uint8_t BTM_GetEirSupportedServices(uint32_t* p_eir_uuid, uint8_t** p, uint8_t max_num_uuid16,
1858 uint8_t* p_num_uuid16) {
1859 uint8_t service_index;
1860
1861 *p_num_uuid16 = 0;
1862
1863 for (service_index = 0; service_index < BTM_EIR_MAX_SERVICES; service_index++) {
1864 if (BTM_EIR_HAS_SERVICE(p_eir_uuid, service_index)) {
1865 if (*p_num_uuid16 < max_num_uuid16) {
1866 UINT16_TO_STREAM(*p, BTM_EIR_UUID_LKUP_TBL[service_index]);
1867 (*p_num_uuid16)++;
1868 } else {
1869 /* if max number of UUIDs are stored and found one more */
1870 return HCI_EIR_MORE_16BITS_UUID_TYPE;
1871 }
1872 }
1873 }
1874 return HCI_EIR_COMPLETE_16BITS_UUID_TYPE;
1875 }
1876
1877 /*******************************************************************************
1878 *
1879 * Function BTM_GetEirUuidList
1880 *
1881 * Description This function parses EIR and returns UUID list.
1882 *
1883 * Parameters p_eir - EIR
1884 * eir_len - EIR len
1885 * uuid_size - Uuid::kNumBytes16, Uuid::kNumBytes32,
1886 * Uuid::kNumBytes128
1887 * p_num_uuid - return number of UUID in found list
1888 * p_uuid_list - return UUID list
1889 * max_num_uuid - maximum number of UUID to be returned
1890 *
1891 * Returns 0 - if not found
1892 * HCI_EIR_COMPLETE_16BITS_UUID_TYPE
1893 * HCI_EIR_MORE_16BITS_UUID_TYPE
1894 * HCI_EIR_COMPLETE_32BITS_UUID_TYPE
1895 * HCI_EIR_MORE_32BITS_UUID_TYPE
1896 * HCI_EIR_COMPLETE_128BITS_UUID_TYPE
1897 * HCI_EIR_MORE_128BITS_UUID_TYPE
1898 *
1899 ******************************************************************************/
BTM_GetEirUuidList(const uint8_t * p_eir,size_t eir_len,uint8_t uuid_size,uint8_t * p_num_uuid,uint8_t * p_uuid_list,uint8_t max_num_uuid)1900 uint8_t BTM_GetEirUuidList(const uint8_t* p_eir, size_t eir_len, uint8_t uuid_size,
1901 uint8_t* p_num_uuid, uint8_t* p_uuid_list, uint8_t max_num_uuid) {
1902 const uint8_t* p_uuid_data;
1903 uint8_t type;
1904 uint8_t yy, xx;
1905 uint16_t* p_uuid16 = (uint16_t*)p_uuid_list;
1906 uint32_t* p_uuid32 = (uint32_t*)p_uuid_list;
1907 char buff[Uuid::kNumBytes128 * 2 + 1];
1908
1909 p_uuid_data = btm_eir_get_uuid_list(p_eir, eir_len, uuid_size, p_num_uuid, &type);
1910 if (p_uuid_data == NULL) {
1911 return 0x00;
1912 }
1913
1914 if (*p_num_uuid > max_num_uuid) {
1915 log::warn("number of uuid in EIR = {}, size of uuid list = {}", *p_num_uuid, max_num_uuid);
1916 *p_num_uuid = max_num_uuid;
1917 }
1918
1919 log::verbose("type = {:02X}, number of uuid = {}", type, *p_num_uuid);
1920
1921 if (uuid_size == Uuid::kNumBytes16) {
1922 for (yy = 0; yy < *p_num_uuid; yy++) {
1923 STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
1924 log::verbose("0x{:04X}", *(p_uuid16 + yy));
1925 }
1926 } else if (uuid_size == Uuid::kNumBytes32) {
1927 for (yy = 0; yy < *p_num_uuid; yy++) {
1928 STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
1929 log::verbose("0x{:08X}", *(p_uuid32 + yy));
1930 }
1931 } else if (uuid_size == Uuid::kNumBytes128) {
1932 for (yy = 0; yy < *p_num_uuid; yy++) {
1933 STREAM_TO_ARRAY16(p_uuid_list + yy * Uuid::kNumBytes128, p_uuid_data);
1934 for (xx = 0; xx < Uuid::kNumBytes128; xx++) {
1935 snprintf(buff + xx * 2, sizeof(buff) - xx * 2, "%02X",
1936 *(p_uuid_list + yy * Uuid::kNumBytes128 + xx));
1937 }
1938 log::verbose("0x{}", buff);
1939 }
1940 }
1941
1942 return type;
1943 }
1944
1945 /*******************************************************************************
1946 *
1947 * Function btm_eir_get_uuid_list
1948 *
1949 * Description This function searches UUID list in EIR.
1950 *
1951 * Parameters p_eir - address of EIR
1952 * eir_len - EIR length
1953 * uuid_size - size of UUID to find
1954 * p_num_uuid - number of UUIDs found
1955 * p_uuid_list_type - EIR data type
1956 *
1957 * Returns NULL - if UUID list with uuid_size is not found
1958 * beginning of UUID list in EIR - otherwise
1959 *
1960 ******************************************************************************/
btm_eir_get_uuid_list(const uint8_t * p_eir,size_t eir_len,uint8_t uuid_size,uint8_t * p_num_uuid,uint8_t * p_uuid_list_type)1961 static const uint8_t* btm_eir_get_uuid_list(const uint8_t* p_eir, size_t eir_len, uint8_t uuid_size,
1962 uint8_t* p_num_uuid, uint8_t* p_uuid_list_type) {
1963 const uint8_t* p_uuid_data;
1964 uint8_t complete_type, more_type;
1965 uint8_t uuid_len;
1966
1967 switch (uuid_size) {
1968 case Uuid::kNumBytes16:
1969 complete_type = HCI_EIR_COMPLETE_16BITS_UUID_TYPE;
1970 more_type = HCI_EIR_MORE_16BITS_UUID_TYPE;
1971 break;
1972 case Uuid::kNumBytes32:
1973 complete_type = HCI_EIR_COMPLETE_32BITS_UUID_TYPE;
1974 more_type = HCI_EIR_MORE_32BITS_UUID_TYPE;
1975 break;
1976 case Uuid::kNumBytes128:
1977 complete_type = HCI_EIR_COMPLETE_128BITS_UUID_TYPE;
1978 more_type = HCI_EIR_MORE_128BITS_UUID_TYPE;
1979 break;
1980 default:
1981 *p_num_uuid = 0;
1982 return NULL;
1983 break;
1984 }
1985
1986 p_uuid_data = AdvertiseDataParser::GetFieldByType(p_eir, eir_len, complete_type, &uuid_len);
1987 if (p_uuid_data == NULL) {
1988 p_uuid_data = AdvertiseDataParser::GetFieldByType(p_eir, eir_len, more_type, &uuid_len);
1989 *p_uuid_list_type = more_type;
1990 } else {
1991 *p_uuid_list_type = complete_type;
1992 }
1993
1994 *p_num_uuid = uuid_len / uuid_size;
1995 return p_uuid_data;
1996 }
1997
1998 /*******************************************************************************
1999 *
2000 * Function btm_convert_uuid_to_uuid16
2001 *
2002 * Description This function converts UUID to UUID 16-bit.
2003 *
2004 * Parameters p_uuid - address of UUID
2005 * uuid_size - size of UUID
2006 *
2007 * Returns 0 - if UUID cannot be converted to UUID 16-bit
2008 * UUID 16-bit - otherwise
2009 *
2010 ******************************************************************************/
btm_convert_uuid_to_uuid16(const uint8_t * p_uuid,uint8_t uuid_size)2011 static uint16_t btm_convert_uuid_to_uuid16(const uint8_t* p_uuid, uint8_t uuid_size) {
2012 static const uint8_t base_uuid[Uuid::kNumBytes128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00,
2013 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
2014 0x00, 0x00, 0x00, 0x00};
2015 uint16_t uuid16 = 0;
2016 uint32_t uuid32;
2017 bool is_base_uuid;
2018 uint8_t xx;
2019
2020 switch (uuid_size) {
2021 case Uuid::kNumBytes16:
2022 STREAM_TO_UINT16(uuid16, p_uuid);
2023 break;
2024 case Uuid::kNumBytes32:
2025 STREAM_TO_UINT32(uuid32, p_uuid);
2026 if (uuid32 < 0x10000) {
2027 uuid16 = (uint16_t)uuid32;
2028 }
2029 break;
2030 case Uuid::kNumBytes128:
2031 /* See if we can compress the UUID down to 16 or 32bit UUIDs */
2032 is_base_uuid = true;
2033 for (xx = 0; xx < Uuid::kNumBytes128 - 4; xx++) {
2034 if (p_uuid[xx] != base_uuid[xx]) {
2035 is_base_uuid = false;
2036 break;
2037 }
2038 }
2039 if (is_base_uuid) {
2040 if ((p_uuid[Uuid::kNumBytes128 - 1] == 0) && (p_uuid[Uuid::kNumBytes128 - 2] == 0)) {
2041 p_uuid += (Uuid::kNumBytes128 - 4);
2042 STREAM_TO_UINT16(uuid16, p_uuid);
2043 }
2044 }
2045 break;
2046 default:
2047 log::warn("btm_convert_uuid_to_uuid16 invalid uuid size");
2048 break;
2049 }
2050
2051 return uuid16;
2052 }
2053
2054 /*******************************************************************************
2055 *
2056 * Function btm_set_eir_uuid
2057 *
2058 * Description This function is called to store received UUID into inquiry
2059 * result.
2060 *
2061 * Parameters p_eir - pointer of EIR significant part
2062 * p_results - pointer of inquiry result
2063 *
2064 * Returns None
2065 *
2066 ******************************************************************************/
btm_set_eir_uuid(const uint8_t * p_eir,tBTM_INQ_RESULTS * p_results)2067 static void btm_set_eir_uuid(const uint8_t* p_eir, tBTM_INQ_RESULTS* p_results) {
2068 const uint8_t* p_uuid_data;
2069 uint8_t num_uuid;
2070 uint16_t uuid16;
2071 uint8_t yy;
2072 uint8_t type = HCI_EIR_MORE_16BITS_UUID_TYPE;
2073
2074 p_uuid_data = btm_eir_get_uuid_list(p_eir, HCI_EXT_INQ_RESPONSE_LEN, Uuid::kNumBytes16, &num_uuid,
2075 &type);
2076
2077 if (type == HCI_EIR_COMPLETE_16BITS_UUID_TYPE) {
2078 p_results->eir_complete_list = true;
2079 } else {
2080 p_results->eir_complete_list = false;
2081 }
2082
2083 log::verbose("eir_complete_list=0x{:02X}", p_results->eir_complete_list);
2084
2085 if (p_uuid_data) {
2086 for (yy = 0; yy < num_uuid; yy++) {
2087 STREAM_TO_UINT16(uuid16, p_uuid_data);
2088 BTM_AddEirService(p_results->eir_uuid, uuid16);
2089 }
2090 }
2091
2092 p_uuid_data = btm_eir_get_uuid_list(p_eir, HCI_EXT_INQ_RESPONSE_LEN, Uuid::kNumBytes32, &num_uuid,
2093 &type);
2094 if (p_uuid_data) {
2095 for (yy = 0; yy < num_uuid; yy++) {
2096 uuid16 = btm_convert_uuid_to_uuid16(p_uuid_data, Uuid::kNumBytes32);
2097 p_uuid_data += Uuid::kNumBytes32;
2098 if (uuid16) {
2099 BTM_AddEirService(p_results->eir_uuid, uuid16);
2100 }
2101 }
2102 }
2103
2104 p_uuid_data = btm_eir_get_uuid_list(p_eir, HCI_EXT_INQ_RESPONSE_LEN, Uuid::kNumBytes128,
2105 &num_uuid, &type);
2106 if (p_uuid_data) {
2107 for (yy = 0; yy < num_uuid; yy++) {
2108 uuid16 = btm_convert_uuid_to_uuid16(p_uuid_data, Uuid::kNumBytes128);
2109 p_uuid_data += Uuid::kNumBytes128;
2110 if (uuid16) {
2111 BTM_AddEirService(p_results->eir_uuid, uuid16);
2112 }
2113 }
2114 }
2115 }
2116
on_inquiry_complete(EventView event)2117 static void on_inquiry_complete(EventView event) {
2118 auto complete = InquiryCompleteView::Create(event);
2119 log::assert_that(complete.IsValid(), "assert failed: complete.IsValid()");
2120 auto status = to_hci_status_code(static_cast<uint8_t>(complete.GetStatus()));
2121
2122 btm_process_inq_complete(status, BTM_GENERAL_INQUIRY);
2123 }
2124 /*******************************************************************************
2125 *
2126 * Function on_incoming_hci_event
2127 *
2128 * Description This function is called to process events from the HCI layer
2129 *
2130 * Parameters event - an EventView with the specific event
2131 *
2132 * Returns None
2133 *
2134 ******************************************************************************/
on_incoming_hci_event(EventView event)2135 static void on_incoming_hci_event(EventView event) {
2136 log::assert_that(event.IsValid(), "assert failed: event.IsValid()");
2137 auto event_code = event.GetEventCode();
2138 switch (event_code) {
2139 case EventCode::INQUIRY_COMPLETE:
2140 on_inquiry_complete(event);
2141 break;
2142 case EventCode::INQUIRY_RESULT:
2143 btm_process_inq_results_standard(event);
2144 break;
2145 case EventCode::INQUIRY_RESULT_WITH_RSSI:
2146 btm_process_inq_results_rssi(event);
2147 break;
2148 case EventCode::EXTENDED_INQUIRY_RESULT:
2149 btm_process_inq_results_extended(event);
2150 break;
2151 default:
2152 log::warn("Dropping unhandled event: {}", EventCodeText(event_code));
2153 }
2154 }
2155
Init()2156 void tBTM_INQUIRY_VAR_ST::Init() {
2157 alarm_free(classic_inquiry_timer);
2158
2159 classic_inquiry_timer = alarm_new("btm_inq.classic_inquiry_timer");
2160
2161 discoverable_mode = BTM_NON_DISCOVERABLE;
2162 connectable_mode = BTM_NON_CONNECTABLE;
2163
2164 page_scan_window = HCI_DEF_PAGESCAN_WINDOW;
2165 page_scan_period = HCI_DEF_PAGESCAN_INTERVAL;
2166 inq_scan_window = HCI_DEF_INQUIRYSCAN_WINDOW;
2167 inq_scan_period = HCI_DEF_INQUIRYSCAN_INTERVAL;
2168 inq_scan_type = BTM_SCAN_TYPE_STANDARD;
2169 page_scan_type = HCI_DEF_SCAN_TYPE;
2170
2171 p_inq_cmpl_cb = nullptr;
2172 p_inq_results_cb = nullptr;
2173
2174 inq_counter = 0;
2175 inqparms = {};
2176 inq_cmpl_info = {};
2177
2178 per_min_delay = 0;
2179 per_max_delay = 0;
2180 state = BTM_INQ_INACTIVE_STATE;
2181 inq_active = 0;
2182 registered_for_hci_events = false;
2183 }
2184
Free()2185 void tBTM_INQUIRY_VAR_ST::Free() { alarm_free(classic_inquiry_timer); }
2186