1 /*
2 * Copyright 2019 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - www.ehima.com
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 #include "ble_scanner_hci_interface.h"
19
20 #include <base/bind.h>
21
22 #include "acl_api.h"
23 #include "btm_api.h"
24 #include "device/include/controller.h"
25 #include "hcidefs.h"
26 #include "hcimsgs.h"
27
28 #include "osi/include/log.h"
29
30 namespace {
31 BleScannerHciInterface* instance = nullptr;
32
status_callback(base::Callback<void (uint8_t)> cb,uint8_t * data,uint16_t len)33 static void status_callback(base::Callback<void(uint8_t)> cb, uint8_t* data,
34 uint16_t len) {
35 uint8_t status;
36
37 LOG_ASSERT(len == 1) << "Received bad response length: " << len;
38 STREAM_TO_UINT8(status, data);
39
40 DVLOG(1) << __func__ << " Received status_cb";
41 cb.Run(status);
42 }
43
status_handle_callback(base::Callback<void (uint8_t,uint16_t)> cb,uint8_t * data,uint16_t len)44 static void status_handle_callback(base::Callback<void(uint8_t, uint16_t)> cb,
45 uint8_t* data, uint16_t len) {
46 uint8_t status;
47 uint16_t handle = HCI_INVALID_HANDLE;
48
49 LOG_ASSERT((len > 0) && (len < 4)) << "Received bad response length: " << len;
50 uint8_t* pp = data;
51 STREAM_TO_UINT8(status, pp);
52
53 if (status == HCI_SUCCESS) {
54 LOG_ASSERT(len == 3) << "Received bad response length: " << len;
55
56 STREAM_TO_UINT16(handle, pp);
57 handle = handle & 0x0EFF;
58
59 DVLOG(1) << __func__ << " Received status_handle_callback";
60 } else {
61 DVLOG(1) << __func__ << " hci response error code: " << int{status};
62 }
63 cb.Run(status, handle);
64 }
65
66 /**
67 * BleScannerHciInterface allows the caller to sync to a periodic advertising
68 * train and receive periodic advertising data events through a registered
69 * observer's callbacks. It also provides a synchronisation transfer API,
70 * including in-controller allow list support. The right feature-complete
71 * interface implementation is chosen during the init phase based on the
72 * controller's list of supported features.
73 */
74 class BleScannerImplBase : public BleScannerHciInterface {
75 public:
SetScanEventObserver(ScanEventObserver * observer)76 void SetScanEventObserver(ScanEventObserver* observer) override {
77 VLOG(1) << __func__;
78 // TODO: Support multiple observers if ever needed.
79 scan_event_observer = observer;
80 }
81
PeriodicScanStart(uint8_t options,uint8_t set_id,uint8_t adv_addr_type,const RawAddress & adv_addr,uint16_t skip_num,uint16_t sync_timeout,uint8_t sync_cte_type)82 void PeriodicScanStart(uint8_t options, uint8_t set_id, uint8_t adv_addr_type,
83 const RawAddress& adv_addr, uint16_t skip_num,
84 uint16_t sync_timeout,
85 uint8_t sync_cte_type) override {
86 VLOG(1) << __func__;
87 btsnd_hcic_ble_periodic_advertising_create_sync(
88 options, set_id, adv_addr_type, adv_addr, skip_num, sync_timeout,
89 sync_cte_type);
90 }
91
PeriodicScanCancelStart(status_cb command_complete)92 void PeriodicScanCancelStart(status_cb command_complete) override {
93 VLOG(1) << __func__;
94 btsnd_hcic_ble_periodic_advertising_create_sync_cancel(
95 base::Bind(&status_callback, std::move(command_complete)));
96 }
97
PeriodicScanTerminate(uint16_t sync_handle,status_cb command_complete)98 void PeriodicScanTerminate(uint16_t sync_handle,
99 status_cb command_complete) override {
100 VLOG(1) << __func__;
101 btsnd_hcic_ble_periodic_advertising_terminate_sync(
102 sync_handle, base::Bind(&status_callback, std::move(command_complete)));
103 }
104
PeriodicScanResultEvtEnable(uint16_t sync_handle,bool enable,status_cb command_complete)105 void PeriodicScanResultEvtEnable(uint16_t sync_handle, bool enable,
106 status_cb command_complete) override {
107 VLOG(1) << __func__;
108 btsnd_hcic_ble_set_periodic_advertising_receive_enable(
109 sync_handle, enable,
110 base::Bind(&status_callback, std::move(command_complete)));
111 }
112
PeriodicAdvertiserListGetSize(BleScannerHciInterface::list_size_cb command_complete)113 void PeriodicAdvertiserListGetSize(
114 BleScannerHciInterface::list_size_cb command_complete) override {
115 VLOG(1) << __func__;
116 command_complete.Run(
117 controller_get_interface()->get_ble_periodic_advertiser_list_size());
118 }
119
PeriodicAdvertiserListAddDevice(uint8_t adv_addr_type,RawAddress & adv_addr,uint8_t set_id,status_cb command_complete)120 void PeriodicAdvertiserListAddDevice(uint8_t adv_addr_type,
121 RawAddress& adv_addr, uint8_t set_id,
122 status_cb command_complete) override {
123 VLOG(1) << __func__;
124 btsnd_hci_ble_add_device_to_periodic_advertiser_list(
125 adv_addr_type, adv_addr, set_id,
126 base::Bind(&status_callback, std::move(command_complete)));
127 }
128
PeriodicAdvertiserListRemoveDevice(uint8_t adv_addr_type,RawAddress & adv_addr,uint8_t set_id,status_cb command_complete)129 void PeriodicAdvertiserListRemoveDevice(uint8_t adv_addr_type,
130 RawAddress& adv_addr, uint8_t set_id,
131 status_cb command_complete) override {
132 VLOG(1) << __func__;
133 btsnd_hci_ble_remove_device_from_periodic_advertiser_list(
134 adv_addr_type, adv_addr, set_id,
135 base::Bind(&status_callback, std::move(command_complete)));
136 }
137
PeriodicAdvertiserListClear(status_cb command_complete)138 void PeriodicAdvertiserListClear(status_cb command_complete) override {
139 VLOG(1) << __func__;
140 btsnd_hci_ble_clear_periodic_advertiser_list(
141 base::Bind(&status_callback, std::move(command_complete)));
142 };
143
PeriodicAdvSyncTransfer(const RawAddress & bd_addr,uint16_t service_data,uint16_t sync_handle,BleScannerHciInterface::handle_cb command_complete)144 void PeriodicAdvSyncTransfer(
145 const RawAddress& bd_addr, uint16_t service_data, uint16_t sync_handle,
146 BleScannerHciInterface::handle_cb command_complete) override {
147 VLOG(1) << __func__;
148 uint16_t acl_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
149
150 if (acl_handle == HCI_INVALID_HANDLE) {
151 LOG(ERROR) << __func__
152 << ": Wrong mode: no LE link exist or LE not supported";
153 return;
154 }
155
156 btsnd_hcic_ble_periodic_advertising_sync_transfer(
157 acl_handle, service_data, sync_handle,
158 base::Bind(&status_handle_callback, std::move(command_complete)));
159 }
160
PeriodicAdvSetInfoTransfer(const RawAddress & bd_addr,uint16_t service_data,uint8_t adv_handle,handle_cb command_complete)161 void PeriodicAdvSetInfoTransfer(const RawAddress& bd_addr,
162 uint16_t service_data, uint8_t adv_handle,
163 handle_cb command_complete) override {
164 VLOG(1) << __func__;
165 uint16_t acl_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
166
167 if (acl_handle == HCI_INVALID_HANDLE) {
168 LOG(ERROR) << __func__
169 << ": Wrong mode: no LE link exist or LE not supported";
170 return;
171 }
172
173 btsnd_hcic_ble_periodic_advertising_set_info_transfer(
174 acl_handle, service_data, adv_handle,
175 base::Bind(&status_handle_callback, std::move(command_complete)));
176 }
177
SetPeriodicAdvSyncTransferParams(const RawAddress & bd_addr,uint8_t mode,uint16_t skip,uint16_t sync_timeout,uint8_t cte_type,bool set_defaults,status_cb command_complete)178 void SetPeriodicAdvSyncTransferParams(const RawAddress& bd_addr, uint8_t mode,
179 uint16_t skip, uint16_t sync_timeout,
180 uint8_t cte_type, bool set_defaults,
181 status_cb command_complete) override {
182 VLOG(1) << __func__;
183 uint16_t acl_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
184
185 if (acl_handle == HCI_INVALID_HANDLE) {
186 LOG(ERROR) << __func__
187 << ": Wrong mode: no LE link exist or LE not supported";
188 return;
189 }
190
191 if (set_defaults)
192 btsnd_hcic_ble_set_default_periodic_advertising_sync_transfer_params(
193 acl_handle, mode, skip, sync_timeout, cte_type,
194 base::Bind(&status_callback, std::move(command_complete)));
195 else
196 btsnd_hcic_ble_set_periodic_advertising_sync_transfer_params(
197 acl_handle, mode, skip, sync_timeout, cte_type,
198 base::Bind(&status_callback, std::move(command_complete)));
199 }
200
OnPeriodicAdvSyncEstablished(uint8_t status,uint16_t sync_handle,uint8_t adv_sid,uint8_t adv_addr_type,RawAddress adv_addr,uint8_t adv_phy,uint16_t adv_interval,uint8_t adv_clock_accuracy)201 void OnPeriodicAdvSyncEstablished(uint8_t status, uint16_t sync_handle,
202 uint8_t adv_sid, uint8_t adv_addr_type,
203 RawAddress adv_addr, uint8_t adv_phy,
204 uint16_t adv_interval,
205 uint8_t adv_clock_accuracy) {
206 if (scan_event_observer) {
207 scan_event_observer->OnPeriodicScanEstablished(
208 status, sync_handle, adv_sid, adv_addr_type, adv_addr, adv_phy,
209 adv_interval, adv_clock_accuracy);
210 }
211 }
212
OnPeriodicScanResult(uint16_t sync_handle,uint8_t tx_power,int8_t rssi,uint8_t cte_type,uint8_t pkt_data_status,uint8_t pkt_data_len,uint8_t * p_pkt_data)213 void OnPeriodicScanResult(uint16_t sync_handle, uint8_t tx_power, int8_t rssi,
214 uint8_t cte_type, uint8_t pkt_data_status,
215 uint8_t pkt_data_len, uint8_t* p_pkt_data) {
216 // The observer should handle the caching and reassembly of the fragmented
217 // packet.
218 if (scan_event_observer) {
219 scan_event_observer->OnPeriodicScanResult(sync_handle, tx_power, rssi,
220 cte_type, pkt_data_status,
221 pkt_data_len, p_pkt_data);
222 }
223 }
224
OnPeriodicSyncLost(uint16_t sync_handle)225 void OnPeriodicSyncLost(uint16_t sync_handle) {
226 if (scan_event_observer)
227 scan_event_observer->OnPeriodicScanLost(sync_handle);
228 }
229
230 private:
231 ScanEventObserver* scan_event_observer = nullptr;
232 };
233
234 class BleScannerListImpl : public virtual BleScannerImplBase {
PeriodicAdvertiserListAddDevice(uint8_t adv_addr_type,RawAddress & adv_addr,uint8_t set_id,status_cb command_complete)235 void PeriodicAdvertiserListAddDevice(uint8_t adv_addr_type,
236 RawAddress& adv_addr, uint8_t set_id,
237 status_cb command_complete) override {
238 VLOG(1) << __func__;
239 btsnd_hci_ble_add_device_to_periodic_advertiser_list(
240 adv_addr_type, adv_addr, set_id,
241 base::Bind(&status_callback, std::move(command_complete)));
242 }
243
PeriodicAdvertiserListRemoveDevice(uint8_t adv_addr_type,RawAddress & adv_addr,uint8_t set_id,status_cb command_complete)244 void PeriodicAdvertiserListRemoveDevice(uint8_t adv_addr_type,
245 RawAddress& adv_addr, uint8_t set_id,
246 status_cb command_complete) override {
247 VLOG(1) << __func__;
248 btsnd_hci_ble_remove_device_from_periodic_advertiser_list(
249 adv_addr_type, adv_addr, set_id,
250 base::Bind(&status_callback, std::move(command_complete)));
251 }
252
PeriodicAdvertiserListClear(status_cb command_complete)253 void PeriodicAdvertiserListClear(status_cb command_complete) override {
254 VLOG(1) << __func__;
255 btsnd_hci_ble_clear_periodic_advertiser_list(
256 base::Bind(&status_callback, std::move(command_complete)));
257 };
258 };
259
260 class BleScannerSyncTransferImpl : public virtual BleScannerImplBase {
PeriodicAdvSyncTransfer(const RawAddress & bd_addr,uint16_t service_data,uint16_t sync_handle,BleScannerHciInterface::handle_cb command_complete)261 void PeriodicAdvSyncTransfer(
262 const RawAddress& bd_addr, uint16_t service_data, uint16_t sync_handle,
263 BleScannerHciInterface::handle_cb command_complete) override {
264 uint16_t acl_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
265
266 if (acl_handle == HCI_INVALID_HANDLE) {
267 LOG(ERROR) << __func__
268 << ": Wrong mode: no LE link exist or LE not supported";
269 return;
270 }
271
272 btsnd_hcic_ble_periodic_advertising_sync_transfer(
273 acl_handle, service_data, sync_handle,
274 base::Bind(&status_handle_callback, std::move(command_complete)));
275 }
276
PeriodicAdvSetInfoTransfer(const RawAddress & bd_addr,uint16_t service_data,uint8_t adv_handle,handle_cb command_complete)277 void PeriodicAdvSetInfoTransfer(const RawAddress& bd_addr,
278 uint16_t service_data, uint8_t adv_handle,
279 handle_cb command_complete) override {
280 uint16_t acl_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
281
282 if (acl_handle == HCI_INVALID_HANDLE) {
283 LOG(ERROR) << __func__
284 << ": Wrong mode: no LE link exist or LE not supported";
285 return;
286 }
287
288 btsnd_hcic_ble_periodic_advertising_set_info_transfer(
289 acl_handle, service_data, adv_handle,
290 base::Bind(&status_handle_callback, std::move(command_complete)));
291 }
292
SetPeriodicAdvSyncTransferParams(const RawAddress & bd_addr,uint8_t mode,uint16_t skip,uint16_t sync_timeout,uint8_t cte_type,bool set_defaults,status_cb command_complete)293 void SetPeriodicAdvSyncTransferParams(const RawAddress& bd_addr, uint8_t mode,
294 uint16_t skip, uint16_t sync_timeout,
295 uint8_t cte_type, bool set_defaults,
296 status_cb command_complete) override {
297 uint16_t acl_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
298
299 if (acl_handle == HCI_INVALID_HANDLE) {
300 LOG(ERROR) << __func__
301 << ": Wrong mode: no LE link exist or LE not supported";
302 return;
303 }
304
305 if (set_defaults)
306 btsnd_hcic_ble_set_default_periodic_advertising_sync_transfer_params(
307 acl_handle, mode, skip, sync_timeout, cte_type,
308 base::Bind(&status_callback, std::move(command_complete)));
309 else
310 btsnd_hcic_ble_set_periodic_advertising_sync_transfer_params(
311 acl_handle, mode, skip, sync_timeout, cte_type,
312 base::Bind(&status_callback, std::move(command_complete)));
313 }
314 };
315
316 class BleScannerCompleteImpl : public BleScannerListImpl,
317 public BleScannerSyncTransferImpl {
318 // Not much to do here :)
319 };
320
321 } // namespace
322
Initialize()323 void BleScannerHciInterface::Initialize() {
324 VLOG(1) << __func__;
325 LOG_ASSERT(instance == nullptr) << "Was already initialized.";
326
327 if ((controller_get_interface()->get_ble_periodic_advertiser_list_size()) &&
328 (controller_get_interface()
329 ->supports_ble_periodic_advertising_sync_transfer_sender())) {
330 LOG(INFO) << "Advertiser list in controller can be used";
331 LOG(INFO) << "Periodic Adv Sync Transfer Sender role is supported";
332 instance = new BleScannerCompleteImpl();
333 } else if (controller_get_interface()
334 ->supports_ble_periodic_advertising_sync_transfer_sender()) {
335 LOG(INFO) << "Periodic Adv Sync Transfer Sender role is supported";
336 instance = new BleScannerSyncTransferImpl();
337 } else if (controller_get_interface()
338 ->get_ble_periodic_advertiser_list_size()) {
339 LOG(INFO) << "Periodic Adv Sync Transfer Recipient role is supported";
340 instance = new BleScannerListImpl();
341 }
342 // TODO: Implement periodic adv. sync. recipient role if ever needed.
343 }
344
Get()345 BleScannerHciInterface* BleScannerHciInterface::Get() { return instance; }
346
CleanUp()347 void BleScannerHciInterface::CleanUp() {
348 VLOG(1) << __func__;
349
350 delete instance;
351 instance = nullptr;
352 }
353
btm_ble_process_periodic_adv_sync_est_evt(uint8_t data_len,uint8_t * data)354 void btm_ble_process_periodic_adv_sync_est_evt(uint8_t data_len,
355 uint8_t* data) {
356 uint16_t sync_handle, adv_interval;
357 uint8_t status, adv_sid, adv_addr_type, adv_phy, adv_clock_accuracy;
358 RawAddress adv_addr;
359
360 VLOG(1) << __func__;
361
362 LOG_ASSERT(data_len == 15)
363 << "Malformed LE Periodic Advertising Sync Est. Event from controller";
364
365 STREAM_TO_UINT8(status, data);
366 STREAM_TO_UINT16(sync_handle, data);
367 STREAM_TO_UINT8(adv_sid, data);
368 STREAM_TO_UINT8(adv_addr_type, data);
369 STREAM_TO_BDADDR(adv_addr, data);
370 STREAM_TO_UINT8(adv_phy, data);
371 STREAM_TO_UINT16(adv_interval, data);
372 STREAM_TO_UINT8(adv_clock_accuracy, data);
373
374 if (BleScannerHciInterface::Get()) {
375 static_cast<BleScannerImplBase*>(BleScannerHciInterface::Get())
376 ->OnPeriodicAdvSyncEstablished(status, sync_handle, adv_sid,
377 adv_addr_type, adv_addr, adv_phy,
378 adv_interval, adv_clock_accuracy);
379 }
380 }
381
btm_ble_process_periodic_adv_pkt(uint8_t data_len,uint8_t * data)382 void btm_ble_process_periodic_adv_pkt(uint8_t data_len, uint8_t* data) {
383 uint8_t* p = data;
384 uint16_t sync_handle;
385 uint8_t tx_power, cte_type, pkt_data_status, pkt_data_len;
386 int8_t rssi;
387
388 LOG_ASSERT(data_len >= 7)
389 << "Malformed LE Periodic Advertising Report Event from controller";
390
391 STREAM_TO_UINT16(sync_handle, p);
392 STREAM_TO_UINT8(tx_power, p);
393 STREAM_TO_INT8(rssi, p);
394 STREAM_TO_UINT8(cte_type, p);
395 STREAM_TO_UINT8(pkt_data_status, p);
396 STREAM_TO_UINT8(pkt_data_len, p);
397
398 uint8_t* pkt_data = p;
399 p += pkt_data_len;
400
401 if (p > data + data_len) {
402 LOG(ERROR) << __func__ << " Invalid pkt_data_len: " << int{pkt_data_len};
403 return;
404 }
405
406 if (rssi >= 21 && rssi <= 126) {
407 LOG(ERROR) << __func__
408 << " bad rssi value in advertising report: " << int{rssi};
409 }
410
411 if (BleScannerHciInterface::Get()) {
412 static_cast<BleScannerImplBase*>(BleScannerHciInterface::Get())
413 ->OnPeriodicScanResult(sync_handle, tx_power, rssi, cte_type,
414 pkt_data_status, pkt_data_len, pkt_data);
415 }
416 }
417
btm_ble_process_periodic_adv_sync_lost_evt(uint8_t data_len,uint8_t * data)418 void btm_ble_process_periodic_adv_sync_lost_evt(uint8_t data_len,
419 uint8_t* data) {
420 uint16_t sync_handle;
421
422 STREAM_TO_UINT16(sync_handle, data);
423
424 if (BleScannerHciInterface::Get()) {
425 static_cast<BleScannerImplBase*>(BleScannerHciInterface::Get())
426 ->OnPeriodicSyncLost(sync_handle);
427 }
428 }
429