1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "gatt_shim.h"
16
17 #include <base/functional/bind.h>
18 #include <base/functional/callback.h>
19 #include <base/location.h>
20 #include <bluetooth/log.h>
21
22 #include <cstdint>
23 #include <optional>
24
25 #include "include/hardware/bluetooth.h"
26 #include "include/hardware/bt_common_types.h"
27 #include "include/hardware/bt_gatt_client.h"
28 #include "include/hardware/bt_gatt_server.h"
29 #include "rust/cxx.h"
30 #include "stack/include/gatt_api.h"
31 #include "types/bluetooth/uuid.h"
32 #include "types/raw_address.h"
33
34 bt_status_t do_in_jni_thread(base::OnceClosure task);
35
36 namespace {
AddressOfConnection(uint16_t conn_id)37 std::optional<RawAddress> AddressOfConnection(uint16_t conn_id) {
38 tGATT_IF gatt_if;
39 RawAddress remote_bda;
40 tBT_TRANSPORT transport;
41 auto valid =
42 GATT_GetConnectionInfor(static_cast<tCONN_ID>(conn_id), &gatt_if, remote_bda, &transport);
43 if (!valid) {
44 return std::nullopt;
45 }
46 return remote_bda;
47 }
48 } // namespace
49
50 namespace bluetooth {
51 namespace gatt {
52
OnServerRead(uint16_t conn_id,uint32_t trans_id,uint16_t attr_handle,AttributeBackingType attr_type,uint32_t offset,bool is_long) const53 void GattServerCallbacks::OnServerRead(uint16_t conn_id, uint32_t trans_id, uint16_t attr_handle,
54 AttributeBackingType attr_type, uint32_t offset,
55 bool is_long) const {
56 auto addr = AddressOfConnection(conn_id);
57 if (!addr.has_value()) {
58 log::warn("Dropping server read characteristic since connection {} not found", conn_id);
59 return;
60 }
61
62 switch (attr_type) {
63 case AttributeBackingType::CHARACTERISTIC:
64 do_in_jni_thread(base::BindOnce(callbacks.request_read_characteristic_cb, conn_id, trans_id,
65 addr.value(), attr_handle, offset, is_long));
66 break;
67 case AttributeBackingType::DESCRIPTOR:
68 do_in_jni_thread(base::BindOnce(callbacks.request_read_descriptor_cb, conn_id, trans_id,
69 addr.value(), attr_handle, offset, is_long));
70 break;
71 default:
72 log::fatal("Unexpected backing type {}", attr_type);
73 }
74 }
75
request_write_with_vec(request_write_callback cb,int conn_id,int trans_id,const RawAddress & bda,int attr_handle,int offset,bool need_rsp,bool is_prep,const std::vector<uint8_t> & value)76 static void request_write_with_vec(request_write_callback cb, int conn_id, int trans_id,
77 const RawAddress& bda, int attr_handle, int offset,
78 bool need_rsp, bool is_prep, const std::vector<uint8_t>& value) {
79 cb(conn_id, trans_id, bda, attr_handle, offset, need_rsp, is_prep, value.data(), value.size());
80 }
81
OnServerWrite(uint16_t conn_id,uint32_t trans_id,uint16_t attr_handle,AttributeBackingType attr_type,uint32_t offset,bool need_response,bool is_prepare,::rust::Slice<const uint8_t> value) const82 void GattServerCallbacks::OnServerWrite(uint16_t conn_id, uint32_t trans_id, uint16_t attr_handle,
83 AttributeBackingType attr_type, uint32_t offset,
84 bool need_response, bool is_prepare,
85 ::rust::Slice<const uint8_t> value) const {
86 auto addr = AddressOfConnection(conn_id);
87 if (!addr.has_value()) {
88 log::warn("Dropping server write characteristic since connection {} not found", conn_id);
89 return;
90 }
91
92 auto buf = std::vector<uint8_t>(value.begin(), value.end());
93
94 switch (attr_type) {
95 case AttributeBackingType::CHARACTERISTIC:
96 do_in_jni_thread(base::BindOnce(
97 request_write_with_vec, callbacks.request_write_characteristic_cb, conn_id, trans_id,
98 addr.value(), attr_handle, offset, need_response, is_prepare, std::move(buf)));
99 break;
100 case AttributeBackingType::DESCRIPTOR:
101 do_in_jni_thread(base::BindOnce(request_write_with_vec, callbacks.request_write_descriptor_cb,
102 conn_id, trans_id, addr.value(), attr_handle, offset,
103 need_response, is_prepare, std::move(buf)));
104 break;
105 default:
106 log::fatal("Unexpected backing type {}", attr_type);
107 }
108 }
109
OnIndicationSentConfirmation(uint16_t conn_id,int status) const110 void GattServerCallbacks::OnIndicationSentConfirmation(uint16_t conn_id, int status) const {
111 do_in_jni_thread(base::BindOnce(callbacks.indication_sent_cb, conn_id, status));
112 }
113
OnExecute(uint16_t conn_id,uint32_t trans_id,bool execute) const114 void GattServerCallbacks::OnExecute(uint16_t conn_id, uint32_t trans_id, bool execute) const {
115 auto addr = AddressOfConnection(conn_id);
116 if (!addr.has_value()) {
117 log::warn("Dropping server execute write since connection {} not found", conn_id);
118 return;
119 }
120
121 do_in_jni_thread(base::BindOnce(callbacks.request_exec_write_cb, conn_id, trans_id, addr.value(),
122 execute));
123 }
124
125 } // namespace gatt
126 } // namespace bluetooth
127