blob: 9650bcd0022d39af7e768d41a72053c920ee695c [file] [log] [blame]
/*
* Copyright 2019 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 "hci/facade/facade.h"
#include <memory>
#include "common/bind.h"
#include "grpc/grpc_event_queue.h"
#include "hci/controller.h"
#include "hci/facade/facade.grpc.pb.h"
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
using ::grpc::ServerAsyncResponseWriter;
using ::grpc::ServerAsyncWriter;
using ::grpc::ServerContext;
namespace bluetooth {
namespace hci {
namespace facade {
class HciLayerFacadeService : public HciLayerFacade::Service {
public:
HciLayerFacadeService(HciLayer* hci_layer, Controller* controller, ::bluetooth::os::Handler* facade_handler)
: hci_layer_(hci_layer), controller_(controller), facade_handler_(facade_handler) {}
virtual ~HciLayerFacadeService() {
if (unregister_acl_dequeue_) {
hci_layer_->GetAclQueueEnd()->UnregisterDequeue();
}
if (waiting_acl_packet_ != nullptr) {
hci_layer_->GetAclQueueEnd()->UnregisterEnqueue();
if (waiting_acl_packet_ != nullptr) {
waiting_acl_packet_.reset();
}
}
}
class TestCommandBuilder : public CommandPacketBuilder {
public:
explicit TestCommandBuilder(std::vector<uint8_t> bytes)
: CommandPacketBuilder(OpCode::NONE), bytes_(std::move(bytes)) {}
size_t size() const override {
return bytes_.size();
}
void Serialize(BitInserter& bit_inserter) const override {
for (auto&& b : bytes_) {
bit_inserter.insert_byte(b);
}
}
private:
std::vector<uint8_t> bytes_;
};
::grpc::Status EnqueueCommandWithComplete(::grpc::ServerContext* context, const ::bluetooth::hci::CommandMsg* command,
::google::protobuf::Empty* response) override {
auto packet = std::make_unique<TestCommandBuilder>(
std::vector<uint8_t>(command->command().begin(), command->command().end()));
hci_layer_->EnqueueCommand(std::move(packet),
common::BindOnce(&HciLayerFacadeService::on_complete, common::Unretained(this)),
facade_handler_);
return ::grpc::Status::OK;
}
::grpc::Status EnqueueCommandWithStatus(::grpc::ServerContext* context, const ::bluetooth::hci::CommandMsg* command,
::google::protobuf::Empty* response) override {
auto packet = std::make_unique<TestCommandBuilder>(
std::vector<uint8_t>(command->command().begin(), command->command().end()));
hci_layer_->EnqueueCommand(std::move(packet),
common::BindOnce(&HciLayerFacadeService::on_status, common::Unretained(this)),
facade_handler_);
return ::grpc::Status::OK;
}
::grpc::Status RegisterEventHandler(::grpc::ServerContext* context, const ::bluetooth::hci::EventCodeMsg* event,
::google::protobuf::Empty* response) override {
hci_layer_->RegisterEventHandler(static_cast<EventCode>(event->code()),
common::Bind(&HciLayerFacadeService::on_event, common::Unretained(this)),
facade_handler_);
return ::grpc::Status::OK;
}
::grpc::Status RegisterLeEventHandler(::grpc::ServerContext* context,
const ::bluetooth::hci::LeSubeventCodeMsg* event,
::google::protobuf::Empty* response) override {
hci_layer_->RegisterLeEventHandler(static_cast<SubeventCode>(event->code()),
common::Bind(&HciLayerFacadeService::on_le_subevent, common::Unretained(this)),
facade_handler_);
return ::grpc::Status::OK;
}
::grpc::Status FetchEvents(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
::grpc::ServerWriter<EventMsg>* writer) override {
return pending_events_.RunLoop(context, writer);
};
::grpc::Status FetchLeSubevents(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
::grpc::ServerWriter<LeSubeventMsg>* writer) override {
return pending_le_events_.RunLoop(context, writer);
};
class TestAclBuilder : public AclPacketBuilder {
public:
explicit TestAclBuilder(uint16_t handle, uint8_t packet_boundary_flag, uint8_t broadcast_flag,
std::vector<uint8_t> payload)
: AclPacketBuilder(0xbad, PacketBoundaryFlag::CONTINUING_FRAGMENT, BroadcastFlag::ACTIVE_SLAVE_BROADCAST),
handle_(handle), pb_flag_(packet_boundary_flag), b_flag_(broadcast_flag), bytes_(std::move(payload)) {}
size_t size() const override {
return bytes_.size();
}
void Serialize(BitInserter& bit_inserter) const override {
LOG_INFO("handle 0x%hx boundary 0x%hhx broadcast 0x%hhx", handle_, pb_flag_, b_flag_);
bit_inserter.insert_byte(handle_);
bit_inserter.insert_bits((handle_ >> 8) & 0xf, 4);
bit_inserter.insert_bits(pb_flag_, 2);
bit_inserter.insert_bits(b_flag_, 2);
bit_inserter.insert_byte(bytes_.size() & 0xff);
bit_inserter.insert_byte((bytes_.size() & 0xff00) >> 8);
for (auto&& b : bytes_) {
bit_inserter.insert_byte(b);
}
}
private:
uint16_t handle_;
uint8_t pb_flag_;
uint8_t b_flag_;
std::vector<uint8_t> bytes_;
};
::grpc::Status SendAclData(::grpc::ServerContext* context, const ::bluetooth::hci::AclMsg* acl,
::google::protobuf::Empty* response) override {
waiting_acl_packet_ =
std::make_unique<TestAclBuilder>(acl->handle(), acl->packet_boundary_flag(), acl->broadcast_flag(),
std::vector<uint8_t>(acl->data().begin(), acl->data().end()));
std::promise<void> enqueued;
auto future = enqueued.get_future();
if (!completed_packets_callback_registered_) {
controller_->RegisterCompletedAclPacketsCallback(common::Bind([](uint16_t, uint16_t) { /* do nothing */ }),
facade_handler_);
completed_packets_callback_registered_ = true;
}
hci_layer_->GetAclQueueEnd()->RegisterEnqueue(
facade_handler_, common::Bind(&HciLayerFacadeService::handle_enqueue_acl, common::Unretained(this),
common::Unretained(&enqueued)));
auto result = future.wait_for(std::chrono::milliseconds(100));
ASSERT(std::future_status::ready == result);
return ::grpc::Status::OK;
}
::grpc::Status FetchAclPackets(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
::grpc::ServerWriter<AclMsg>* writer) override {
hci_layer_->GetAclQueueEnd()->RegisterDequeue(
facade_handler_, common::Bind(&HciLayerFacadeService::on_acl_ready, common::Unretained(this)));
unregister_acl_dequeue_ = true;
return pending_acl_events_.RunLoop(context, writer);
};
private:
std::unique_ptr<AclPacketBuilder> handle_enqueue_acl(std::promise<void>* promise) {
promise->set_value();
hci_layer_->GetAclQueueEnd()->UnregisterEnqueue();
return std::move(waiting_acl_packet_);
}
void on_acl_ready() {
auto acl_ptr = hci_layer_->GetAclQueueEnd()->TryDequeue();
ASSERT(acl_ptr != nullptr);
ASSERT(acl_ptr->IsValid());
LOG_INFO("Got an Acl message for handle 0x%hx", acl_ptr->GetHandle());
AclMsg incoming;
incoming.set_data(std::string(acl_ptr->begin(), acl_ptr->end()));
pending_acl_events_.OnIncomingEvent(std::move(incoming));
}
void on_event(hci::EventPacketView view) {
ASSERT(view.IsValid());
LOG_INFO("Got an Event %s", EventCodeText(view.GetEventCode()).c_str());
EventMsg response;
response.set_event(std::string(view.begin(), view.end()));
pending_events_.OnIncomingEvent(std::move(response));
}
void on_le_subevent(hci::LeMetaEventView view) {
ASSERT(view.IsValid());
LOG_INFO("Got an LE Event %s", SubeventCodeText(view.GetSubeventCode()).c_str());
LeSubeventMsg response;
response.set_event(std::string(view.begin(), view.end()));
pending_le_events_.OnIncomingEvent(std::move(response));
}
void on_complete(hci::CommandCompleteView view) {
ASSERT(view.IsValid());
LOG_INFO("Got a Command complete %s", OpCodeText(view.GetCommandOpCode()).c_str());
EventMsg response;
response.set_event(std::string(view.begin(), view.end()));
pending_events_.OnIncomingEvent(std::move(response));
}
void on_status(hci::CommandStatusView view) {
ASSERT(view.IsValid());
LOG_INFO("Got a Command status %s", OpCodeText(view.GetCommandOpCode()).c_str());
EventMsg response;
response.set_event(std::string(view.begin(), view.end()));
pending_events_.OnIncomingEvent(std::move(response));
}
HciLayer* hci_layer_;
Controller* controller_;
::bluetooth::os::Handler* facade_handler_;
::bluetooth::grpc::GrpcEventQueue<EventMsg> pending_events_{"FetchHciEvent"};
::bluetooth::grpc::GrpcEventQueue<LeSubeventMsg> pending_le_events_{"FetchLeSubevent"};
::bluetooth::grpc::GrpcEventQueue<AclMsg> pending_acl_events_{"FetchAclData"};
bool unregister_acl_dequeue_{false};
std::unique_ptr<TestAclBuilder> waiting_acl_packet_;
bool completed_packets_callback_registered_{false};
};
void HciLayerFacadeModule::ListDependencies(ModuleList* list) {
::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
list->add<HciLayer>();
list->add<Controller>();
}
void HciLayerFacadeModule::Start() {
::bluetooth::grpc::GrpcFacadeModule::Start();
service_ = new HciLayerFacadeService(GetDependency<HciLayer>(), GetDependency<Controller>(), GetHandler());
}
void HciLayerFacadeModule::Stop() {
delete service_;
::bluetooth::grpc::GrpcFacadeModule::Stop();
}
::grpc::Service* HciLayerFacadeModule::GetService() const {
return service_;
}
const ModuleFactory HciLayerFacadeModule::Factory =
::bluetooth::ModuleFactory([]() { return new HciLayerFacadeModule(); });
} // namespace facade
} // namespace hci
} // namespace bluetooth