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 "hal/facade.h"
18 
19 #include <memory>
20 #include <mutex>
21 
22 #include "blueberry/facade/hal/hal_facade.grpc.pb.h"
23 #include "grpc/grpc_event_queue.h"
24 #include "hal/hci_hal.h"
25 
26 using ::grpc::ServerAsyncResponseWriter;
27 using ::grpc::ServerAsyncWriter;
28 using ::grpc::ServerContext;
29 
30 namespace bluetooth {
31 namespace hal {
32 
33 class HciHalFacadeService : public blueberry::facade::hal::HciHalFacade::Service,
34                             public ::bluetooth::hal::HciHalCallbacks {
35 public:
HciHalFacadeService(HciHal * hal)36   explicit HciHalFacadeService(HciHal* hal) : hal_(hal) {
37     hal->registerIncomingPacketCallback(this);
38   }
39 
~HciHalFacadeService()40   ~HciHalFacadeService() { hal_->unregisterIncomingPacketCallback(); }
41 
SendCommand(::grpc::ServerContext *,const::blueberry::facade::Data * request,::google::protobuf::Empty *)42   ::grpc::Status SendCommand(::grpc::ServerContext* /* context */,
43                              const ::blueberry::facade::Data* request,
44                              ::google::protobuf::Empty* /* response */) override {
45     std::unique_lock<std::mutex> lock(mutex_);
46     can_send_hci_command_ = false;
47     std::string req_string = request->payload();
48     hal_->sendHciCommand(std::vector<uint8_t>(req_string.begin(), req_string.end()));
49     while (!can_send_hci_command_) {
50       cv_.wait(lock);
51     }
52     return ::grpc::Status::OK;
53   }
54 
SendAcl(::grpc::ServerContext *,const::blueberry::facade::Data * request,::google::protobuf::Empty *)55   ::grpc::Status SendAcl(::grpc::ServerContext* /* context */,
56                          const ::blueberry::facade::Data* request,
57                          ::google::protobuf::Empty* /* response */) override {
58     std::string req_string = request->payload();
59     hal_->sendAclData(std::vector<uint8_t>(req_string.begin(), req_string.end()));
60     return ::grpc::Status::OK;
61   }
62 
SendSco(::grpc::ServerContext *,const::blueberry::facade::Data * request,::google::protobuf::Empty *)63   ::grpc::Status SendSco(::grpc::ServerContext* /* context */,
64                          const ::blueberry::facade::Data* request,
65                          ::google::protobuf::Empty* /* response */) override {
66     std::string req_string = request->payload();
67     hal_->sendScoData(std::vector<uint8_t>(req_string.begin(), req_string.end()));
68     return ::grpc::Status::OK;
69   }
70 
StreamEvents(::grpc::ServerContext * context,const::google::protobuf::Empty *,::grpc::ServerWriter<::blueberry::facade::Data> * writer)71   ::grpc::Status StreamEvents(::grpc::ServerContext* context,
72                               const ::google::protobuf::Empty* /* request */,
73                               ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
74     return pending_hci_events_.RunLoop(context, writer);
75   }
76 
StreamAcl(::grpc::ServerContext * context,const::google::protobuf::Empty *,::grpc::ServerWriter<::blueberry::facade::Data> * writer)77   ::grpc::Status StreamAcl(::grpc::ServerContext* context,
78                            const ::google::protobuf::Empty* /* request */,
79                            ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
80     return pending_acl_events_.RunLoop(context, writer);
81   }
82 
StreamSco(::grpc::ServerContext * context,const::google::protobuf::Empty *,::grpc::ServerWriter<::blueberry::facade::Data> * writer)83   ::grpc::Status StreamSco(::grpc::ServerContext* context,
84                            const ::google::protobuf::Empty* /* request */,
85                            ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
86     return pending_sco_events_.RunLoop(context, writer);
87   }
88 
StreamIso(::grpc::ServerContext * context,const::google::protobuf::Empty *,::grpc::ServerWriter<::blueberry::facade::Data> * writer)89   ::grpc::Status StreamIso(::grpc::ServerContext* context,
90                            const ::google::protobuf::Empty* /* request */,
91                            ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
92     return pending_iso_events_.RunLoop(context, writer);
93   }
94 
hciEventReceived(bluetooth::hal::HciPacket event)95   void hciEventReceived(bluetooth::hal::HciPacket event) override {
96     {
97       ::blueberry::facade::Data response;
98       response.set_payload(std::string(event.begin(), event.end()));
99       pending_hci_events_.OnIncomingEvent(std::move(response));
100     }
101     can_send_hci_command_ = true;
102     cv_.notify_one();
103   }
104 
aclDataReceived(bluetooth::hal::HciPacket data)105   void aclDataReceived(bluetooth::hal::HciPacket data) override {
106     ::blueberry::facade::Data response;
107     response.set_payload(std::string(data.begin(), data.end()));
108     pending_acl_events_.OnIncomingEvent(std::move(response));
109   }
110 
scoDataReceived(bluetooth::hal::HciPacket data)111   void scoDataReceived(bluetooth::hal::HciPacket data) override {
112     ::blueberry::facade::Data response;
113     response.set_payload(std::string(data.begin(), data.end()));
114     pending_sco_events_.OnIncomingEvent(std::move(response));
115   }
116 
isoDataReceived(bluetooth::hal::HciPacket data)117   void isoDataReceived(bluetooth::hal::HciPacket data) override {
118     ::blueberry::facade::Data response;
119     response.set_payload(std::string(data.begin(), data.end()));
120     pending_iso_events_.OnIncomingEvent(std::move(response));
121   }
122 
123 private:
124   HciHal* hal_;
125   bool can_send_hci_command_ = true;
126   mutable std::mutex mutex_;
127   std::condition_variable cv_;
128   ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_hci_events_{"StreamEvents"};
129   ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_acl_events_{"StreamAcl"};
130   ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_sco_events_{"StreamSco"};
131   ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_iso_events_{"StreamIso"};
132 };
133 
ListDependencies(ModuleList * list) const134 void HciHalFacadeModule::ListDependencies(ModuleList* list) const {
135   ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
136   list->add<HciHal>();
137 }
138 
Start()139 void HciHalFacadeModule::Start() {
140   ::bluetooth::grpc::GrpcFacadeModule::Start();
141   service_ = new HciHalFacadeService(GetDependency<HciHal>());
142 }
143 
Stop()144 void HciHalFacadeModule::Stop() {
145   delete service_;
146   ::bluetooth::grpc::GrpcFacadeModule::Stop();
147 }
148 
GetService() const149 ::grpc::Service* HciHalFacadeModule::GetService() const { return service_; }
150 
151 const ModuleFactory HciHalFacadeModule::Factory =
__anon1b68e04a0102() 152         ::bluetooth::ModuleFactory([]() { return new HciHalFacadeModule(); });
153 
154 }  // namespace hal
155 }  // namespace bluetooth
156