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