// Copyright 2022, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "gatt_shim.h"
#include
#include
#include
#include
#include "include/hardware/bluetooth.h"
#include "include/hardware/bt_common_types.h"
#include "include/hardware/bt_gatt_client.h"
#include "include/hardware/bt_gatt_server.h"
#include "os/log.h"
#include "rust/cxx.h"
#include "stack/include/gatt_api.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
bt_status_t do_in_jni_thread(const base::Location& from_here,
base::OnceClosure task);
namespace {
std::optional AddressOfConnection(uint16_t conn_id) {
tGATT_IF gatt_if;
RawAddress remote_bda;
tBT_TRANSPORT transport;
auto valid =
GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport);
if (!valid) {
return std::nullopt;
}
return remote_bda;
}
} // namespace
namespace bluetooth {
namespace gatt {
void GattServerCallbacks::OnServerRead(uint16_t conn_id, uint32_t trans_id,
uint16_t attr_handle,
AttributeBackingType attr_type,
uint32_t offset, bool is_long) const {
auto addr = AddressOfConnection(conn_id);
if (!addr.has_value()) {
LOG_WARN(
"Dropping server read characteristic since connection %d not found",
conn_id);
return;
}
switch (attr_type) {
case AttributeBackingType::CHARACTERISTIC:
do_in_jni_thread(
FROM_HERE,
base::Bind(callbacks.request_read_characteristic_cb, conn_id,
trans_id, addr.value(), attr_handle, offset, is_long));
break;
case AttributeBackingType::DESCRIPTOR:
do_in_jni_thread(
FROM_HERE,
base::Bind(callbacks.request_read_descriptor_cb, conn_id, trans_id,
addr.value(), attr_handle, offset, is_long));
break;
default:
LOG_ALWAYS_FATAL("Unexpected backing type %d", attr_type);
}
}
void GattServerCallbacks::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 value) const {
auto addr = AddressOfConnection(conn_id);
if (!addr.has_value()) {
LOG_WARN(
"Dropping server write characteristic since connection %d not found",
conn_id);
return;
}
auto buf = new uint8_t[value.size()];
std::copy(value.begin(), value.end(), buf);
switch (attr_type) {
case AttributeBackingType::CHARACTERISTIC:
do_in_jni_thread(
FROM_HERE,
base::Bind(callbacks.request_write_characteristic_cb, conn_id,
trans_id, addr.value(), attr_handle, offset, need_response,
is_prepare, base::Owned(buf), value.size()));
break;
case AttributeBackingType::DESCRIPTOR:
do_in_jni_thread(
FROM_HERE,
base::Bind(callbacks.request_write_descriptor_cb, conn_id, trans_id,
addr.value(), attr_handle, offset, need_response,
is_prepare, base::Owned(buf), value.size()));
break;
default:
LOG_ALWAYS_FATAL("Unexpected backing type %hhu", attr_type);
}
}
void GattServerCallbacks::OnIndicationSentConfirmation(uint16_t conn_id,
int status) const {
do_in_jni_thread(FROM_HERE,
base::Bind(callbacks.indication_sent_cb, conn_id, status));
}
void GattServerCallbacks::OnExecute(uint16_t conn_id, uint32_t trans_id,
bool execute) const {
auto addr = AddressOfConnection(conn_id);
if (!addr.has_value()) {
LOG_WARN("Dropping server execute write since connection %d not found",
conn_id);
return;
}
do_in_jni_thread(
FROM_HERE, base::Bind(callbacks.request_exec_write_cb, conn_id, trans_id,
addr.value(), execute));
}
} // namespace gatt
} // namespace bluetooth