1 /*
2  * Copyright 2019 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 "hci/facade/facade.h"
18 
19 #include <bluetooth/log.h>
20 
21 #include <memory>
22 
23 #include "blueberry/facade/hci/hci_facade.grpc.pb.h"
24 #include "common/bind.h"
25 #include "grpc/grpc_event_queue.h"
26 #include "hci/controller.h"
27 #include "hci/hci_layer.h"
28 #include "hci/hci_packets.h"
29 
30 using ::grpc::ServerAsyncResponseWriter;
31 using ::grpc::ServerAsyncWriter;
32 using ::grpc::ServerContext;
33 
34 namespace bluetooth {
35 namespace hci {
36 namespace facade {
37 
38 using namespace blueberry::facade::hci;
39 
40 class HciFacadeService : public HciFacade::Service {
41  public:
HciFacadeService(HciLayer * hci_layer,Controller * controller,::bluetooth::os::Handler * facade_handler)42   HciFacadeService(HciLayer* hci_layer, Controller* controller, ::bluetooth::os::Handler* facade_handler)
43       : hci_layer_(hci_layer), controller_(controller), facade_handler_(facade_handler) {}
44 
~HciFacadeService()45   virtual ~HciFacadeService() {
46     if (unregister_acl_dequeue_) {
47       hci_layer_->GetAclQueueEnd()->UnregisterDequeue();
48     }
49     if (waiting_acl_packet_ != nullptr) {
50       hci_layer_->GetAclQueueEnd()->UnregisterEnqueue();
51       if (waiting_acl_packet_ != nullptr) {
52         waiting_acl_packet_.reset();
53       }
54     }
55   }
56 
57   class TestCommandBuilder : public CommandBuilder {
58    public:
TestCommandBuilder(std::vector<uint8_t> bytes)59     explicit TestCommandBuilder(std::vector<uint8_t> bytes) : CommandBuilder(OpCode::NONE), bytes_(std::move(bytes)) {}
size() const60     size_t size() const override {
61       return bytes_.size();
62     }
Serialize(BitInserter & bit_inserter) const63     void Serialize(BitInserter& bit_inserter) const override {
64       for (auto&& b : bytes_) {
65         bit_inserter.insert_byte(b);
66       }
67     }
68 
69    private:
70     std::vector<uint8_t> bytes_;
71   };
72 
SendCommand(::grpc::ServerContext *,const::blueberry::facade::Data * command,::google::protobuf::Empty *)73   ::grpc::Status SendCommand(
74       ::grpc::ServerContext* /* context */,
75       const ::blueberry::facade::Data* command,
76       ::google::protobuf::Empty* /* response */) override {
77     auto payload = std::vector<uint8_t>(command->payload().begin(), command->payload().end());
78     auto packet = std::make_unique<TestCommandBuilder>(payload);
79     auto opcode = static_cast<const bluetooth::hci::OpCode>(payload.at(1) << 8 | payload.at(0));
80     if (Checker::IsCommandStatusOpcode(opcode)) {
81       hci_layer_->EnqueueCommand(std::move(packet), facade_handler_->BindOnceOn(this, &HciFacadeService::on_status));
82     } else {
83       hci_layer_->EnqueueCommand(std::move(packet), facade_handler_->BindOnceOn(this, &HciFacadeService::on_complete));
84     }
85     return ::grpc::Status::OK;
86   }
87 
RequestEvent(::grpc::ServerContext *,const::blueberry::facade::hci::EventRequest * event,::google::protobuf::Empty *)88   ::grpc::Status RequestEvent(
89       ::grpc::ServerContext* /* context */,
90       const ::blueberry::facade::hci::EventRequest* event,
91       ::google::protobuf::Empty* /* response */) override {
92     hci_layer_->RegisterEventHandler(
93         static_cast<EventCode>(event->code()), facade_handler_->BindOn(this, &HciFacadeService::on_event));
94     return ::grpc::Status::OK;
95   }
96 
RequestLeSubevent(::grpc::ServerContext *,const::blueberry::facade::hci::EventRequest * event,::google::protobuf::Empty *)97   ::grpc::Status RequestLeSubevent(
98       ::grpc::ServerContext* /* context */,
99       const ::blueberry::facade::hci::EventRequest* event,
100       ::google::protobuf::Empty* /* response */) override {
101     hci_layer_->RegisterLeEventHandler(
102         static_cast<SubeventCode>(event->code()), facade_handler_->BindOn(this, &HciFacadeService::on_le_subevent));
103     return ::grpc::Status::OK;
104   }
105 
StreamEvents(::grpc::ServerContext * context,const::google::protobuf::Empty *,::grpc::ServerWriter<::blueberry::facade::Data> * writer)106   ::grpc::Status StreamEvents(
107       ::grpc::ServerContext* context,
108       const ::google::protobuf::Empty* /* request */,
109       ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
110     return pending_events_.RunLoop(context, writer);
111   };
112 
StreamLeSubevents(::grpc::ServerContext * context,const::google::protobuf::Empty *,::grpc::ServerWriter<::blueberry::facade::Data> * writer)113   ::grpc::Status StreamLeSubevents(
114       ::grpc::ServerContext* context,
115       const ::google::protobuf::Empty* /* request */,
116       ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
117     return pending_le_events_.RunLoop(context, writer);
118   };
119 
120   class TestAclBuilder : public AclBuilder {
121    public:
TestAclBuilder(std::vector<uint8_t> payload)122     explicit TestAclBuilder(std::vector<uint8_t> payload)
123         : AclBuilder(0xbad, PacketBoundaryFlag::CONTINUING_FRAGMENT, BroadcastFlag::ACTIVE_PERIPHERAL_BROADCAST),
124           bytes_(std::move(payload)) {}
125 
size() const126     size_t size() const override {
127       return bytes_.size();
128     }
Serialize(BitInserter & bit_inserter) const129     void Serialize(BitInserter& bit_inserter) const override {
130       for (auto&& b : bytes_) {
131         bit_inserter.insert_byte(b);
132       }
133     }
134 
135    private:
136     std::vector<uint8_t> bytes_;
137   };
138 
SendAcl(::grpc::ServerContext *,const::blueberry::facade::Data * acl,::google::protobuf::Empty *)139   ::grpc::Status SendAcl(
140       ::grpc::ServerContext* /* context */,
141       const ::blueberry::facade::Data* acl,
142       ::google::protobuf::Empty* /* response */) override {
143     waiting_acl_packet_ =
144         std::make_unique<TestAclBuilder>(std::vector<uint8_t>(acl->payload().begin(), acl->payload().end()));
145     std::promise<void> enqueued;
146     auto future = enqueued.get_future();
147     if (!completed_packets_callback_registered_) {
148       controller_->RegisterCompletedAclPacketsCallback(
149           facade_handler_->Bind([](uint16_t, uint16_t) { /* do nothing */ }));
150       completed_packets_callback_registered_ = true;
151     }
152     hci_layer_->GetAclQueueEnd()->RegisterEnqueue(
153         facade_handler_,
154         common::Bind(&HciFacadeService::handle_enqueue_acl, common::Unretained(this), common::Unretained(&enqueued)));
155     auto result = future.wait_for(std::chrono::milliseconds(100));
156     log::assert_that(
157         std::future_status::ready == result, "assert failed: std::future_status::ready == result");
158     return ::grpc::Status::OK;
159   }
160 
StreamAcl(::grpc::ServerContext * context,const::google::protobuf::Empty *,::grpc::ServerWriter<::blueberry::facade::Data> * writer)161   ::grpc::Status StreamAcl(
162       ::grpc::ServerContext* context,
163       const ::google::protobuf::Empty* /* request */,
164       ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
165     hci_layer_->GetAclQueueEnd()->RegisterDequeue(
166         facade_handler_, common::Bind(&HciFacadeService::on_acl_ready, common::Unretained(this)));
167     unregister_acl_dequeue_ = true;
168     return pending_acl_events_.RunLoop(context, writer);
169   };
170 
171  private:
handle_enqueue_acl(std::promise<void> * promise)172   std::unique_ptr<AclBuilder> handle_enqueue_acl(std::promise<void>* promise) {
173     promise->set_value();
174     hci_layer_->GetAclQueueEnd()->UnregisterEnqueue();
175     return std::move(waiting_acl_packet_);
176   }
177 
on_acl_ready()178   void on_acl_ready() {
179     auto acl_ptr = hci_layer_->GetAclQueueEnd()->TryDequeue();
180     log::assert_that(acl_ptr != nullptr, "assert failed: acl_ptr != nullptr");
181     log::assert_that(acl_ptr->IsValid(), "assert failed: acl_ptr->IsValid()");
182     log::info("Got an Acl message for handle 0x{:x}", acl_ptr->GetHandle());
183     ::blueberry::facade::Data incoming;
184     incoming.set_payload(std::string(acl_ptr->begin(), acl_ptr->end()));
185     pending_acl_events_.OnIncomingEvent(std::move(incoming));
186   }
187 
on_event(hci::EventView view)188   void on_event(hci::EventView view) {
189     log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
190     log::info("Got an Event {}", EventCodeText(view.GetEventCode()));
191     ::blueberry::facade::Data response;
192     response.set_payload(std::string(view.begin(), view.end()));
193     pending_events_.OnIncomingEvent(std::move(response));
194   }
195 
on_le_subevent(hci::LeMetaEventView view)196   void on_le_subevent(hci::LeMetaEventView view) {
197     log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
198     log::info("Got an LE Event {}", SubeventCodeText(view.GetSubeventCode()));
199     ::blueberry::facade::Data response;
200     response.set_payload(std::string(view.begin(), view.end()));
201     pending_le_events_.OnIncomingEvent(std::move(response));
202   }
203 
on_complete(hci::CommandCompleteView view)204   void on_complete(hci::CommandCompleteView view) {
205     log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
206     log::info("Got a Command complete {}", OpCodeText(view.GetCommandOpCode()));
207     ::blueberry::facade::Data response;
208     response.set_payload(std::string(view.begin(), view.end()));
209     pending_events_.OnIncomingEvent(std::move(response));
210   }
211 
on_status(hci::CommandStatusView view)212   void on_status(hci::CommandStatusView view) {
213     log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
214     log::info("Got a Command status {}", OpCodeText(view.GetCommandOpCode()));
215     ::blueberry::facade::Data response;
216     response.set_payload(std::string(view.begin(), view.end()));
217     pending_events_.OnIncomingEvent(std::move(response));
218   }
219 
220   HciLayer* hci_layer_;
221   Controller* controller_;
222   ::bluetooth::os::Handler* facade_handler_;
223   ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_events_{"StreamEvents"};
224   ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_le_events_{"StreamLeSubevents"};
225   ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_acl_events_{"StreamAcl"};
226   bool unregister_acl_dequeue_{false};
227   std::unique_ptr<TestAclBuilder> waiting_acl_packet_;
228   bool completed_packets_callback_registered_{false};
229 };
230 
ListDependencies(ModuleList * list) const231 void HciFacadeModule::ListDependencies(ModuleList* list) const {
232   ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
233   list->add<HciLayer>();
234   list->add<Controller>();
235 }
236 
Start()237 void HciFacadeModule::Start() {
238   ::bluetooth::grpc::GrpcFacadeModule::Start();
239   service_ = new HciFacadeService(GetDependency<HciLayer>(), GetDependency<Controller>(), GetHandler());
240 }
241 
Stop()242 void HciFacadeModule::Stop() {
243   delete service_;
244   ::bluetooth::grpc::GrpcFacadeModule::Stop();
245 }
246 
GetService() const247 ::grpc::Service* HciFacadeModule::GetService() const {
248   return service_;
249 }
250 
__anonae7156b60202() 251 const ModuleFactory HciFacadeModule::Factory = ::bluetooth::ModuleFactory([]() { return new HciFacadeModule(); });
252 
253 }  // namespace facade
254 }  // namespace hci
255 }  // namespace bluetooth
256