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() {
41 hal_->unregisterIncomingPacketCallback();
42 }
43
SendCommand(::grpc::ServerContext * context,const::blueberry::facade::Data * request,::google::protobuf::Empty * response)44 ::grpc::Status SendCommand(
45 ::grpc::ServerContext* context,
46 const ::blueberry::facade::Data* request,
47 ::google::protobuf::Empty* response) override {
48 std::unique_lock<std::mutex> lock(mutex_);
49 can_send_hci_command_ = false;
50 std::string req_string = request->payload();
51 hal_->sendHciCommand(std::vector<uint8_t>(req_string.begin(), req_string.end()));
52 while (!can_send_hci_command_) {
53 cv_.wait(lock);
54 }
55 return ::grpc::Status::OK;
56 }
57
SendAcl(::grpc::ServerContext * context,const::blueberry::facade::Data * request,::google::protobuf::Empty * response)58 ::grpc::Status SendAcl(
59 ::grpc::ServerContext* context,
60 const ::blueberry::facade::Data* request,
61 ::google::protobuf::Empty* response) override {
62 std::string req_string = request->payload();
63 hal_->sendAclData(std::vector<uint8_t>(req_string.begin(), req_string.end()));
64 return ::grpc::Status::OK;
65 }
66
SendSco(::grpc::ServerContext * context,const::blueberry::facade::Data * request,::google::protobuf::Empty * response)67 ::grpc::Status SendSco(
68 ::grpc::ServerContext* context,
69 const ::blueberry::facade::Data* request,
70 ::google::protobuf::Empty* response) override {
71 std::string req_string = request->payload();
72 hal_->sendScoData(std::vector<uint8_t>(req_string.begin(), req_string.end()));
73 return ::grpc::Status::OK;
74 }
75
StreamEvents(::grpc::ServerContext * context,const::google::protobuf::Empty * request,::grpc::ServerWriter<::blueberry::facade::Data> * writer)76 ::grpc::Status StreamEvents(
77 ::grpc::ServerContext* context,
78 const ::google::protobuf::Empty* request,
79 ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
80 return pending_hci_events_.RunLoop(context, writer);
81 };
82
StreamAcl(::grpc::ServerContext * context,const::google::protobuf::Empty * request,::grpc::ServerWriter<::blueberry::facade::Data> * writer)83 ::grpc::Status StreamAcl(
84 ::grpc::ServerContext* context,
85 const ::google::protobuf::Empty* request,
86 ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
87 return pending_acl_events_.RunLoop(context, writer);
88 };
89
StreamSco(::grpc::ServerContext * context,const::google::protobuf::Empty * request,::grpc::ServerWriter<::blueberry::facade::Data> * writer)90 ::grpc::Status StreamSco(
91 ::grpc::ServerContext* context,
92 const ::google::protobuf::Empty* request,
93 ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
94 return pending_sco_events_.RunLoop(context, writer);
95 };
96
StreamIso(::grpc::ServerContext * context,const::google::protobuf::Empty * request,::grpc::ServerWriter<::blueberry::facade::Data> * writer)97 ::grpc::Status StreamIso(
98 ::grpc::ServerContext* context,
99 const ::google::protobuf::Empty* request,
100 ::grpc::ServerWriter<::blueberry::facade::Data>* writer) override {
101 return pending_iso_events_.RunLoop(context, writer);
102 };
103
hciEventReceived(bluetooth::hal::HciPacket event)104 void hciEventReceived(bluetooth::hal::HciPacket event) override {
105 {
106 ::blueberry::facade::Data response;
107 response.set_payload(std::string(event.begin(), event.end()));
108 pending_hci_events_.OnIncomingEvent(std::move(response));
109 }
110 can_send_hci_command_ = true;
111 cv_.notify_one();
112 }
113
aclDataReceived(bluetooth::hal::HciPacket data)114 void aclDataReceived(bluetooth::hal::HciPacket data) override {
115 ::blueberry::facade::Data response;
116 response.set_payload(std::string(data.begin(), data.end()));
117 pending_acl_events_.OnIncomingEvent(std::move(response));
118 }
119
scoDataReceived(bluetooth::hal::HciPacket data)120 void scoDataReceived(bluetooth::hal::HciPacket data) override {
121 ::blueberry::facade::Data response;
122 response.set_payload(std::string(data.begin(), data.end()));
123 pending_sco_events_.OnIncomingEvent(std::move(response));
124 }
125
isoDataReceived(bluetooth::hal::HciPacket data)126 void isoDataReceived(bluetooth::hal::HciPacket data) override {
127 ::blueberry::facade::Data response;
128 response.set_payload(std::string(data.begin(), data.end()));
129 pending_iso_events_.OnIncomingEvent(std::move(response));
130 }
131
132 private:
133 HciHal* hal_;
134 bool can_send_hci_command_ = true;
135 mutable std::mutex mutex_;
136 std::condition_variable cv_;
137 ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_hci_events_{"StreamEvents"};
138 ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_acl_events_{"StreamAcl"};
139 ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_sco_events_{"StreamSco"};
140 ::bluetooth::grpc::GrpcEventQueue<::blueberry::facade::Data> pending_iso_events_{"StreamIso"};
141 };
142
ListDependencies(ModuleList * list) const143 void HciHalFacadeModule::ListDependencies(ModuleList* list) const {
144 ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
145 list->add<HciHal>();
146 }
147
Start()148 void HciHalFacadeModule::Start() {
149 ::bluetooth::grpc::GrpcFacadeModule::Start();
150 service_ = new HciHalFacadeService(GetDependency<HciHal>());
151 }
152
Stop()153 void HciHalFacadeModule::Stop() {
154 delete service_;
155 ::bluetooth::grpc::GrpcFacadeModule::Stop();
156 }
157
GetService() const158 ::grpc::Service* HciHalFacadeModule::GetService() const {
159 return service_;
160 }
161
__anon8b9339c00102() 162 const ModuleFactory HciHalFacadeModule::Factory = ::bluetooth::ModuleFactory([]() { return new HciHalFacadeModule(); });
163
164 } // namespace hal
165 } // namespace bluetooth
166