• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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