1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "gd/rust/topshim/btif/btif_shim.h"
18
19 #include <algorithm>
20 #include <cstdlib>
21 #include <cstring>
22 #include <memory>
23
24 #include "btcore/include/hal_util.h"
25 #include "include/hardware/bluetooth.h"
26 #include "rust/cxx.h"
27 #include "src/btif.rs.h"
28
29 namespace bluetooth {
30 namespace topshim {
31 namespace rust {
32 namespace internal {
33 // We need a global pointer to the Bluetooth interface because callbacks don't
34 // pass back a pointer to the interface object. As a consequence, attempting to
35 // initialize the interface multiple times should cause an abort.
36 static BluetoothIntf* g_btif;
37
38 namespace rusty = ::bluetooth::topshim::rust;
39
prop_to_vec(int num_properties,bt_property_t * properties)40 static ::rust::Vec<BtProperty> prop_to_vec(int num_properties, bt_property_t* properties) {
41 ::rust::Vec<BtProperty> rust_properties;
42
43 for (int i = 0; i < num_properties; ++i) {
44 ::rust::Vec<::rust::u8> val;
45 val.reserve(properties[i].len);
46
47 ::rust::u8* p = static_cast<::rust::u8*>(properties[i].val);
48 for (int j = 0; j < properties[i].len; ++j) {
49 val.push_back(p[j]);
50 }
51
52 BtProperty prop = {.prop_type = properties[i].type, .len = properties[i].len, .val = std::move(val)};
53 rust_properties.push_back(std::move(prop));
54 }
55
56 return rust_properties;
57 }
58
to_rust_address(RawAddress * address)59 static RustRawAddress to_rust_address(RawAddress* address) {
60 RustRawAddress raddr;
61 std::copy(std::begin(address->address), std::end(address->address), std::begin(raddr.address));
62
63 return raddr;
64 }
65
from_rust_address(const RustRawAddress & address)66 static RawAddress from_rust_address(const RustRawAddress& address) {
67 RawAddress r;
68 r.FromOctets(address.address.data());
69
70 return r;
71 }
72
bdname_to_string(bt_bdname_t * bdname)73 static ::rust::String bdname_to_string(bt_bdname_t* bdname) {
74 if (!bdname) {
75 return std::string("");
76 }
77
78 return std::string(reinterpret_cast<const char*>(bdname->name));
79 }
80
adapter_state_changed_cb(bt_state_t state)81 static void adapter_state_changed_cb(bt_state_t state) {
82 rusty::adapter_state_changed_callback(*g_btif->GetCallbacks(), state);
83 }
84
adapter_properties_cb(bt_status_t status,int num_properties,bt_property_t * properties)85 static void adapter_properties_cb(bt_status_t status, int num_properties, bt_property_t* properties) {
86 rusty::adapter_properties_callback(
87 *g_btif->GetCallbacks(), status, num_properties, prop_to_vec(num_properties, properties));
88 }
89
remote_device_properties_cb(bt_status_t status,RawAddress * bd_addr,int num_properties,bt_property_t * properties)90 static void remote_device_properties_cb(
91 bt_status_t status, RawAddress* bd_addr, int num_properties, bt_property_t* properties) {
92 RustRawAddress addr = to_rust_address(bd_addr);
93
94 rusty::remote_device_properties_callback(
95 *g_btif->GetCallbacks(), status, addr, num_properties, prop_to_vec(num_properties, properties));
96 }
97
device_found_cb(int num_properties,bt_property_t * properties)98 static void device_found_cb(int num_properties, bt_property_t* properties) {
99 rusty::device_found_callback(*g_btif->GetCallbacks(), num_properties, prop_to_vec(num_properties, properties));
100 }
101
discovery_state_changed_cb(bt_discovery_state_t state)102 static void discovery_state_changed_cb(bt_discovery_state_t state) {
103 rusty::discovery_state_changed_callback(*g_btif->GetCallbacks(), state);
104 }
105
pin_request_cb(RawAddress * remote_bd_addr,bt_bdname_t * bd_name,uint32_t cod,bool min_16_digit)106 static void pin_request_cb(RawAddress* remote_bd_addr, bt_bdname_t* bd_name, uint32_t cod, bool min_16_digit) {
107 RustRawAddress addr = to_rust_address(remote_bd_addr);
108 auto name = bdname_to_string(bd_name);
109
110 rusty::pin_request_callback(*g_btif->GetCallbacks(), addr, name, cod, min_16_digit);
111 }
112
ssp_request_cb(RawAddress * remote_bd_addr,bt_bdname_t * bd_name,uint32_t cod,bt_ssp_variant_t pairing_variant,uint32_t pass_key)113 static void ssp_request_cb(
114 RawAddress* remote_bd_addr,
115 bt_bdname_t* bd_name,
116 uint32_t cod,
117 bt_ssp_variant_t pairing_variant,
118 uint32_t pass_key) {
119 RustRawAddress addr = to_rust_address(remote_bd_addr);
120 auto name = bdname_to_string(bd_name);
121
122 rusty::ssp_request_callback(*g_btif->GetCallbacks(), addr, name, cod, pairing_variant, pass_key);
123 }
124
bond_state_changed_cb(bt_status_t status,RawAddress * remote_bd_addr,bt_bond_state_t state)125 static void bond_state_changed_cb(bt_status_t status, RawAddress* remote_bd_addr, bt_bond_state_t state) {
126 RustRawAddress addr = to_rust_address(remote_bd_addr);
127
128 rust::bond_state_changed_callback(*g_btif->GetCallbacks(), status, addr, state);
129 }
130
acl_state_changed_cb(bt_status_t status,RawAddress * remote_bd_addr,bt_acl_state_t state,bt_hci_error_code_t hci_reason)131 static void acl_state_changed_cb(
132 bt_status_t status, RawAddress* remote_bd_addr, bt_acl_state_t state, bt_hci_error_code_t hci_reason) {
133 RustRawAddress addr = to_rust_address(remote_bd_addr);
134
135 rust::acl_state_changed_callback(*g_btif->GetCallbacks(), status, addr, state, hci_reason);
136 }
137
138 // TODO(abps) - Implement remaining callbacks
139
thread_event_cb(bt_cb_thread_evt evt)140 static void thread_event_cb(bt_cb_thread_evt evt) {}
141
dut_mode_recv_cb(uint16_t opcode,uint8_t * buf,uint8_t len)142 static void dut_mode_recv_cb(uint16_t opcode, uint8_t* buf, uint8_t len) {}
143
le_test_mode_cb(bt_status_t status,uint16_t num_packets)144 static void le_test_mode_cb(bt_status_t status, uint16_t num_packets) {}
145
energy_info_cb(bt_activity_energy_info * energy_info,bt_uid_traffic_t * uid_data)146 static void energy_info_cb(bt_activity_energy_info* energy_info, bt_uid_traffic_t* uid_data) {}
147
148 bt_callbacks_t g_callbacks = {
149 sizeof(bt_callbacks_t),
150 adapter_state_changed_cb,
151 adapter_properties_cb,
152 remote_device_properties_cb,
153 device_found_cb,
154 discovery_state_changed_cb,
155 pin_request_cb,
156 ssp_request_cb,
157 bond_state_changed_cb,
158 acl_state_changed_cb,
159 thread_event_cb,
160 dut_mode_recv_cb,
161 le_test_mode_cb,
162 energy_info_cb,
163 };
164 } // namespace internal
165
166 // Bluetooth interface handler
BluetoothIntf()167 BluetoothIntf::BluetoothIntf() : init_(false) {}
168
~BluetoothIntf()169 BluetoothIntf::~BluetoothIntf() {
170 // We made a copy of flags from initFlags; clean them up here
171 if (flags_) {
172 int i = 0;
173 for (const char* flag = flags_[i]; flags_[i] != nullptr; ++i) {
174 std::free(const_cast<void*>(static_cast<const void*>(flag)));
175 }
176
177 std::free(const_cast<void*>(static_cast<const void*>(flags_)));
178 }
179 }
180
ConvertFlags(::rust::Vec<::rust::String> & initFlags)181 void BluetoothIntf::ConvertFlags(::rust::Vec<::rust::String>& initFlags) {
182 // Allocate number of flags + 1 (last entry must be null to signify end)
183 // Must be calloc so our cleanup correctly frees everything
184 flags_ = static_cast<const char**>(std::calloc(initFlags.size() + 1, sizeof(char*)));
185 if (!flags_) return;
186
187 for (int i = 0; i < initFlags.size(); ++i) {
188 flags_[i] = strndup(initFlags[i].data(), initFlags[i].size());
189 if (!flags_) {
190 return;
191 }
192 }
193 }
194
Initialize(::rust::Box<RustCallbacks> callbacks,::rust::Vec<::rust::String> initFlags)195 bool BluetoothIntf::Initialize(::rust::Box<RustCallbacks> callbacks, ::rust::Vec<::rust::String> initFlags) {
196 if (init_) return true;
197
198 callbacks_ = std::make_unique<::rust::Box<RustCallbacks>>(std::move(callbacks));
199 ConvertFlags(initFlags);
200
201 if (!hal_util_load_bt_library(&intf_)) {
202 int ret = intf_->init(
203 &internal::g_callbacks,
204 false, // guest_mode,
205 false, // is_niap_mode,
206 0, // config_compare_result,
207 flags_,
208 false // is_atv
209 );
210
211 // We only accept SUCCESS and not BT_STATUS_DONE. If some other interface
212 // has already been registered, that means our callbacks won't be called and
213 // that is problematic.
214 init_ = ret == BT_STATUS_SUCCESS;
215 }
216
217 return init_;
218 }
219
CleanUp() const220 void BluetoothIntf::CleanUp() const {
221 intf_->cleanup();
222 }
223
Enable() const224 int BluetoothIntf::Enable() const {
225 return intf_->enable();
226 }
227
Disable() const228 int BluetoothIntf::Disable() const {
229 return intf_->disable();
230 }
231
GetAdapterProperties() const232 int BluetoothIntf::GetAdapterProperties() const {
233 return intf_->get_adapter_properties();
234 }
235
GetAdapterProperty(int prop) const236 int BluetoothIntf::GetAdapterProperty(int prop) const {
237 return intf_->get_adapter_property(static_cast<bt_property_type_t>(prop));
238 }
239
convert_to_cprop(const BtProperty & prop)240 static bt_property_t convert_to_cprop(const BtProperty& prop) {
241 bt_property_t c_prop = {
242 .type = static_cast<bt_property_type_t>(prop.prop_type),
243 .len = prop.len,
244 .val = reinterpret_cast<void*>(const_cast<unsigned char*>(prop.val.data())),
245 };
246
247 return c_prop;
248 }
249
SetAdapterProperty(const BtProperty & prop) const250 int BluetoothIntf::SetAdapterProperty(const BtProperty& prop) const {
251 bt_property_t c_prop = convert_to_cprop(prop);
252 return intf_->set_adapter_property(&c_prop);
253 }
254
GetRemoteDeviceProperties(const RustRawAddress & address) const255 int BluetoothIntf::GetRemoteDeviceProperties(const RustRawAddress& address) const {
256 RawAddress addr = internal::from_rust_address(address);
257
258 return intf_->get_remote_device_properties(&addr);
259 }
260
GetRemoteDeviceProperty(const RustRawAddress & address,int prop_type) const261 int BluetoothIntf::GetRemoteDeviceProperty(const RustRawAddress& address, int prop_type) const {
262 RawAddress addr = internal::from_rust_address(address);
263 return intf_->get_remote_device_property(&addr, static_cast<bt_property_type_t>(prop_type));
264 }
265
SetRemoteDeviceProperty(const RustRawAddress & address,const BtProperty & prop) const266 int BluetoothIntf::SetRemoteDeviceProperty(const RustRawAddress& address, const BtProperty& prop) const {
267 RawAddress addr = internal::from_rust_address(address);
268
269 bt_property_t c_prop = convert_to_cprop(prop);
270 return intf_->set_remote_device_property(&addr, &c_prop);
271 }
272
GetRemoteServices(const RustRawAddress & address) const273 int BluetoothIntf::GetRemoteServices(const RustRawAddress& address) const {
274 RawAddress addr = internal::from_rust_address(address);
275
276 return intf_->get_remote_services(&addr);
277 }
278
StartDiscovery() const279 int BluetoothIntf::StartDiscovery() const {
280 return intf_->start_discovery();
281 }
282
CancelDiscovery() const283 int BluetoothIntf::CancelDiscovery() const {
284 return intf_->cancel_discovery();
285 }
286
CreateBond(const RustRawAddress & address,int transport) const287 int BluetoothIntf::CreateBond(const RustRawAddress& address, int transport) const {
288 RawAddress addr = internal::from_rust_address(address);
289
290 return intf_->create_bond(&addr, transport);
291 }
292
RemoveBond(const RustRawAddress & address) const293 int BluetoothIntf::RemoveBond(const RustRawAddress& address) const {
294 RawAddress addr = internal::from_rust_address(address);
295
296 return intf_->remove_bond(&addr);
297 }
298
CancelBond(const RustRawAddress & address) const299 int BluetoothIntf::CancelBond(const RustRawAddress& address) const {
300 RawAddress addr = internal::from_rust_address(address);
301
302 return intf_->cancel_bond(&addr);
303 }
304
GetConnectionState(const RustRawAddress & address) const305 int BluetoothIntf::GetConnectionState(const RustRawAddress& address) const {
306 RawAddress addr = internal::from_rust_address(address);
307
308 return intf_->get_connection_state(&addr);
309 }
310
PinReply(const RustRawAddress & address,uint8_t accept,uint8_t pin_len,const BtPinCode & code) const311 int BluetoothIntf::PinReply(
312 const RustRawAddress& address, uint8_t accept, uint8_t pin_len, const BtPinCode& code) const {
313 RawAddress addr = internal::from_rust_address(address);
314
315 bt_pin_code_t pin_code;
316 std::copy(std::begin(code.pin), std::end(code.pin), pin_code.pin);
317
318 return intf_->pin_reply(&addr, accept, pin_len, &pin_code);
319 }
320
SspReply(const RustRawAddress & address,int ssp_variant,uint8_t accept,uint32_t passkey) const321 int BluetoothIntf::SspReply(const RustRawAddress& address, int ssp_variant, uint8_t accept, uint32_t passkey) const {
322 RawAddress addr = internal::from_rust_address(address);
323
324 return intf_->ssp_reply(&addr, static_cast<bt_ssp_variant_t>(ssp_variant), accept, passkey);
325 }
326
Load()327 std::unique_ptr<BluetoothIntf> Load() {
328 // Don't allow the bluetooth interface to be allocated twice
329 if (internal::g_btif) std::abort();
330
331 auto btif = std::make_unique<BluetoothIntf>();
332 internal::g_btif = btif.get();
333 return btif;
334 }
335
336 } // namespace rust
337 } // namespace topshim
338 } // namespace bluetooth
339