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/location.h>
19 #include <bluetooth/log.h>
20
21 #include <cstdint>
22 #include <optional>
23
24 #include "include/hardware/bluetooth.h"
25 #include "include/hardware/bt_common_types.h"
26 #include "include/hardware/bt_gatt_client.h"
27 #include "include/hardware/bt_gatt_server.h"
28 #include "os/log.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(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,
54 uint16_t attr_handle,
55 AttributeBackingType attr_type,
56 uint32_t offset, bool is_long) const {
57 auto addr = AddressOfConnection(conn_id);
58 if (!addr.has_value()) {
59 log::warn(
60 "Dropping server read characteristic since connection {} not found",
61 conn_id);
62 return;
63 }
64
65 switch (attr_type) {
66 case AttributeBackingType::CHARACTERISTIC:
67 do_in_jni_thread(base::BindOnce(callbacks.request_read_characteristic_cb,
68 conn_id, trans_id, addr.value(),
69 attr_handle, offset, is_long));
70 break;
71 case AttributeBackingType::DESCRIPTOR:
72 do_in_jni_thread(base::BindOnce(callbacks.request_read_descriptor_cb,
73 conn_id, trans_id, addr.value(),
74 attr_handle, offset, is_long));
75 break;
76 default:
77 log::fatal("Unexpected backing type {}", attr_type);
78 }
79 }
80
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)81 static void request_write_with_vec(request_write_callback cb, int conn_id,
82 int trans_id, const RawAddress& bda,
83 int attr_handle, int offset, bool need_rsp,
84 bool is_prep,
85 const std::vector<uint8_t>& value) {
86 cb(conn_id, trans_id, bda, attr_handle, offset, need_rsp, is_prep,
87 value.data(), value.size());
88 }
89
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) const90 void GattServerCallbacks::OnServerWrite(
91 uint16_t conn_id, uint32_t trans_id, uint16_t attr_handle,
92 AttributeBackingType attr_type, uint32_t offset, bool need_response,
93 bool is_prepare, ::rust::Slice<const uint8_t> value) const {
94 auto addr = AddressOfConnection(conn_id);
95 if (!addr.has_value()) {
96 log::warn(
97 "Dropping server write characteristic since connection {} not found",
98 conn_id);
99 return;
100 }
101
102 auto buf = std::vector<uint8_t>(value.begin(), value.end());
103
104 switch (attr_type) {
105 case AttributeBackingType::CHARACTERISTIC:
106 do_in_jni_thread(base::BindOnce(
107 request_write_with_vec, callbacks.request_write_characteristic_cb,
108 conn_id, trans_id, addr.value(), attr_handle, offset, need_response,
109 is_prepare, std::move(buf)));
110 break;
111 case AttributeBackingType::DESCRIPTOR:
112 do_in_jni_thread(base::BindOnce(
113 request_write_with_vec, callbacks.request_write_descriptor_cb,
114 conn_id, trans_id, addr.value(), attr_handle, offset, need_response,
115 is_prepare, std::move(buf)));
116 break;
117 default:
118 log::fatal("Unexpected backing type {}", attr_type);
119 }
120 }
121
OnIndicationSentConfirmation(uint16_t conn_id,int status) const122 void GattServerCallbacks::OnIndicationSentConfirmation(uint16_t conn_id,
123 int status) const {
124 do_in_jni_thread(
125 base::BindOnce(callbacks.indication_sent_cb, conn_id, status));
126 }
127
OnExecute(uint16_t conn_id,uint32_t trans_id,bool execute) const128 void GattServerCallbacks::OnExecute(uint16_t conn_id, uint32_t trans_id,
129 bool execute) const {
130 auto addr = AddressOfConnection(conn_id);
131 if (!addr.has_value()) {
132 log::warn("Dropping server execute write since connection {} not found",
133 conn_id);
134 return;
135 }
136
137 do_in_jni_thread(base::BindOnce(callbacks.request_exec_write_cb, conn_id,
138 trans_id, addr.value(), execute));
139 }
140
141 } // namespace gatt
142 } // namespace bluetooth
143