1 /******************************************************************************
2 *
3 * Copyright 1999-2012 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 for BLE device control utilities, and LE
22 * security functions.
23 *
24 ******************************************************************************/
25
26 #define LOG_TAG "ble"
27
28 #include <bluetooth/log.h>
29
30 #include <cstdint>
31
32 #include "base/functional/bind.h"
33 #include "hci/controller_interface.h"
34 #include "main/shim/entry.h"
35 #include "stack/btm/btm_int_types.h"
36 #include "stack/gatt/gatt_int.h"
37 #include "stack/include/acl_api.h"
38 #include "stack/include/ble_hci_link_interface.h"
39 #include "stack/include/bt_types.h"
40 #include "stack/include/btm_ble_api.h"
41 #include "stack/include/btm_client_interface.h"
42 #include "stack/include/btu_hcif.h"
43 #include "stack/include/gatt_api.h"
44 #include "stack/include/hcimsgs.h"
45
46 using namespace bluetooth;
47
48 extern tBTM_CB btm_cb;
49
50 /*******************************************************************************
51 *
52 * Function BTM_BleReceiverTest
53 *
54 * Description This function is called to start the LE Receiver test
55 *
56 * Parameter rx_freq - Frequency Range
57 * p_cmd_cmpl_cback - Command Complete callback
58 *
59 ******************************************************************************/
BTM_BleReceiverTest(uint8_t rx_freq,tBTM_CMPL_CB * p_cmd_cmpl_cback)60 void BTM_BleReceiverTest(uint8_t rx_freq, tBTM_CMPL_CB* p_cmd_cmpl_cback) {
61 btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
62
63 btsnd_hcic_ble_receiver_test(rx_freq);
64 }
65
66 /*******************************************************************************
67 *
68 * Function BTM_BleTransmitterTest
69 *
70 * Description This function is called to start the LE Transmitter test
71 *
72 * Parameter tx_freq - Frequency Range
73 * test_data_len - Length in bytes of payload data in each
74 * packet
75 * packet_payload - Pattern to use in the payload
76 * p_cmd_cmpl_cback - Command Complete callback
77 *
78 ******************************************************************************/
BTM_BleTransmitterTest(uint8_t tx_freq,uint8_t test_data_len,uint8_t packet_payload,tBTM_CMPL_CB * p_cmd_cmpl_cback)79 void BTM_BleTransmitterTest(uint8_t tx_freq, uint8_t test_data_len, uint8_t packet_payload,
80 tBTM_CMPL_CB* p_cmd_cmpl_cback) {
81 btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
82 btsnd_hcic_ble_transmitter_test(tx_freq, test_data_len, packet_payload);
83 }
84
85 /*******************************************************************************
86 *
87 * Function BTM_BleTestEnd
88 *
89 * Description This function is called to stop the in-progress TX or RX
90 * test
91 *
92 * Parameter p_cmd_cmpl_cback - Command complete callback
93 *
94 ******************************************************************************/
BTM_BleTestEnd(tBTM_CMPL_CB * p_cmd_cmpl_cback)95 void BTM_BleTestEnd(tBTM_CMPL_CB* p_cmd_cmpl_cback) {
96 btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
97
98 btsnd_hcic_ble_test_end();
99 }
100
101 /*******************************************************************************
102 * Internal Functions
103 ******************************************************************************/
btm_ble_test_command_complete(uint8_t * p)104 void btm_ble_test_command_complete(uint8_t* p) {
105 tBTM_CMPL_CB* p_cb = btm_cb.devcb.p_le_test_cmd_cmpl_cb;
106
107 btm_cb.devcb.p_le_test_cmd_cmpl_cb = NULL;
108
109 if (p_cb) {
110 (*p_cb)(p);
111 }
112 }
113
114 /*******************************************************************************
115 *
116 * Function BTM_UseLeLink
117 *
118 * Description This function is to select the underlying physical link to
119 * use.
120 *
121 * Returns true to use LE, false use BR/EDR.
122 *
123 ******************************************************************************/
BTM_UseLeLink(const RawAddress & bd_addr)124 bool BTM_UseLeLink(const RawAddress& bd_addr) {
125 if (get_btm_client_interface().peer.BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_BR_EDR)) {
126 return false;
127 } else if (get_btm_client_interface().peer.BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE)) {
128 return true;
129 }
130
131 tBT_DEVICE_TYPE dev_type;
132 tBLE_ADDR_TYPE addr_type;
133 get_btm_client_interface().peer.BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
134 return dev_type == BT_DEVICE_TYPE_BLE;
135 }
136
read_phy_cb(base::Callback<void (uint8_t tx_phy,uint8_t rx_phy,uint8_t status)> cb,uint8_t * data,uint16_t len)137 static void read_phy_cb(base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb,
138 uint8_t* data, uint16_t len) {
139 uint8_t status, tx_phy, rx_phy;
140 uint16_t handle;
141
142 log::assert_that(len == 5, "Received bad response length:{}", len);
143 uint8_t* pp = data;
144 STREAM_TO_UINT8(status, pp);
145 STREAM_TO_UINT16(handle, pp);
146 handle = handle & 0x0FFF;
147 STREAM_TO_UINT8(tx_phy, pp);
148 STREAM_TO_UINT8(rx_phy, pp);
149
150 cb.Run(tx_phy, rx_phy, status);
151 }
152
153 /*******************************************************************************
154 *
155 * Function BTM_BleReadPhy
156 *
157 * Description To read the current PHYs for specified LE connection
158 *
159 *
160 * Returns void
161 *
162 ******************************************************************************/
BTM_BleReadPhy(const RawAddress & bd_addr,base::Callback<void (uint8_t tx_phy,uint8_t rx_phy,uint8_t status)> cb)163 void BTM_BleReadPhy(const RawAddress& bd_addr,
164 base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb) {
165 if (!get_btm_client_interface().peer.BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE)) {
166 log::error("Wrong mode: no LE link exist or LE not supported");
167 cb.Run(0, 0, HCI_ERR_NO_CONNECTION);
168 return;
169 }
170
171 // The connection PHY is always LE_1M when the controller supports
172 // neither LE_2M nor LE_CODED PHYs.
173 if (!bluetooth::shim::GetController()->SupportsBle2mPhy() &&
174 !bluetooth::shim::GetController()->SupportsBleCodedPhy()) {
175 cb.Run(1, 1, HCI_SUCCESS);
176 return;
177 }
178
179 uint16_t handle = get_btm_client_interface().peer.BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
180
181 const uint8_t len = HCIC_PARAM_SIZE_BLE_READ_PHY;
182 uint8_t data[len];
183 uint8_t* pp = data;
184 UINT16_TO_STREAM(pp, handle);
185 btu_hcif_send_cmd_with_cb(HCI_BLE_READ_PHY, data, len, base::Bind(&read_phy_cb, std::move(cb)));
186 }
187
BTM_BleSetPhy(const RawAddress & bd_addr,uint8_t tx_phys,uint8_t rx_phys,uint16_t phy_options)188 void BTM_BleSetPhy(const RawAddress& bd_addr, uint8_t tx_phys, uint8_t rx_phys,
189 uint16_t phy_options) {
190 if (!get_btm_client_interface().peer.BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE)) {
191 log::info(
192 "Unable to set phy preferences because no le acl is connected to "
193 "device");
194 return;
195 }
196
197 uint8_t all_phys = 0;
198 if (tx_phys == 0) {
199 all_phys &= 0x01;
200 }
201 if (rx_phys == 0) {
202 all_phys &= 0x02;
203 }
204
205 uint16_t handle = get_btm_client_interface().peer.BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
206
207 // checking if local controller supports it!
208 if (!bluetooth::shim::GetController()->SupportsBle2mPhy() &&
209 !bluetooth::shim::GetController()->SupportsBleCodedPhy()) {
210 log::info("Local controller unable to support setting of le phy parameters");
211 gatt_notify_phy_updated(static_cast<tHCI_STATUS>(GATT_REQ_NOT_SUPPORTED), handle, tx_phys,
212 rx_phys);
213 return;
214 }
215
216 if (!acl_peer_supports_ble_2m_phy(handle) && !acl_peer_supports_ble_coded_phy(handle)) {
217 log::info("Remote device unable to support setting of le phy parameter");
218 gatt_notify_phy_updated(static_cast<tHCI_STATUS>(GATT_REQ_NOT_SUPPORTED), handle, tx_phys,
219 rx_phys);
220 return;
221 }
222
223 const uint8_t len = HCIC_PARAM_SIZE_BLE_SET_PHY;
224 uint8_t data[len];
225 uint8_t* pp = data;
226 UINT16_TO_STREAM(pp, handle);
227 UINT8_TO_STREAM(pp, all_phys);
228 UINT8_TO_STREAM(pp, tx_phys);
229 UINT8_TO_STREAM(pp, rx_phys);
230 UINT16_TO_STREAM(pp, phy_options);
231 btu_hcif_send_cmd_with_cb(HCI_BLE_SET_PHY, data, len, base::Bind([](uint8_t*, uint16_t) {}));
232 }
233