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