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 "neighbor/facade/facade.h"
18
19 #include <memory>
20
21 #include "common/bind.h"
22 #include "grpc/grpc_event_queue.h"
23 #include "hci/hci_packets.h"
24 #include "neighbor/facade/facade.grpc.pb.h"
25
26 using ::grpc::ServerAsyncResponseWriter;
27 using ::grpc::ServerAsyncWriter;
28 using ::grpc::ServerContext;
29
30 namespace bluetooth {
31 namespace neighbor {
32 namespace facade {
33
34 class NeighborFacadeService : public NeighborFacade::Service {
35 public:
NeighborFacadeService(ConnectabilityModule * connectability_module,DiscoverabilityModule * discoverability_module,InquiryModule * inquiry_module,NameModule * name_module,PageModule *,ScanModule * scan_module,::bluetooth::os::Handler * facade_handler)36 NeighborFacadeService(
37 ConnectabilityModule* connectability_module,
38 DiscoverabilityModule* discoverability_module,
39 InquiryModule* inquiry_module,
40 NameModule* name_module,
41 PageModule*,
42 ScanModule* scan_module,
43 ::bluetooth::os::Handler* facade_handler)
44 : connectability_module_(connectability_module),
45 discoverability_module_(discoverability_module),
46 inquiry_module_(inquiry_module),
47 name_module_(name_module),
48 scan_module_(scan_module),
49 facade_handler_(facade_handler) {}
50
SetConnectability(::grpc::ServerContext * context,const::bluetooth::neighbor::EnableMsg * request,::google::protobuf::Empty * response)51 ::grpc::Status SetConnectability(
52 ::grpc::ServerContext* context,
53 const ::bluetooth::neighbor::EnableMsg* request,
54 ::google::protobuf::Empty* response) override {
55 if (request->enabled()) {
56 connectability_module_->StartConnectability();
57 } else {
58 connectability_module_->StopConnectability();
59 }
60 return ::grpc::Status::OK;
61 }
62
SetDiscoverability(::grpc::ServerContext * context,const::bluetooth::neighbor::DiscoverabilitiyMsg * request,::google::protobuf::Empty * response)63 ::grpc::Status SetDiscoverability(
64 ::grpc::ServerContext* context,
65 const ::bluetooth::neighbor::DiscoverabilitiyMsg* request,
66 ::google::protobuf::Empty* response) override {
67 switch (request->mode()) {
68 case DiscoverabilityMode::OFF:
69 discoverability_module_->StopDiscoverability();
70 break;
71 case DiscoverabilityMode::LIMITED:
72 discoverability_module_->StartLimitedDiscoverability();
73 break;
74 case DiscoverabilityMode::GENERAL:
75 discoverability_module_->StartGeneralDiscoverability();
76 break;
77 default:
78 LOG_ALWAYS_FATAL("Unknown discoverability mode %d", static_cast<int>(request->mode()));
79 }
80 return ::grpc::Status::OK;
81 }
82
SetInquiryMode(::grpc::ServerContext * context,const::bluetooth::neighbor::InquiryMsg * request,::grpc::ServerWriter<InquiryResultMsg> * writer)83 ::grpc::Status SetInquiryMode(
84 ::grpc::ServerContext* context,
85 const ::bluetooth::neighbor::InquiryMsg* request,
86 ::grpc::ServerWriter<InquiryResultMsg>* writer) override {
87 inquiry_module_->RegisterCallbacks(inquiry_callbacks_);
88 switch (request->result_mode()) {
89 case ResultMode::STANDARD:
90 inquiry_module_->SetStandardInquiryResultMode();
91 break;
92 case ResultMode::RSSI:
93 inquiry_module_->SetInquiryWithRssiResultMode();
94 break;
95 case ResultMode::EXTENDED:
96 inquiry_module_->SetExtendedInquiryResultMode();
97 break;
98 default:
99 LOG_ALWAYS_FATAL("Unknown result mode %d", static_cast<int>(request->result_mode()));
100 }
101 switch (request->inquiry_mode()) {
102 case DiscoverabilityMode::OFF:
103 inquiry_module_->StopInquiry();
104 break;
105 case DiscoverabilityMode::LIMITED:
106 inquiry_module_->StartLimitedInquiry(request->length_1_28s(), request->max_results());
107 break;
108 case DiscoverabilityMode::GENERAL:
109 inquiry_module_->StartGeneralInquiry(request->length_1_28s(), request->max_results());
110 break;
111 default:
112 LOG_ALWAYS_FATAL("Unknown discoverability mode %d", static_cast<int>(request->inquiry_mode()));
113 }
114 return pending_events_.RunLoop(context, writer);
115 }
116
ReadRemoteName(::grpc::ServerContext * context,const::bluetooth::neighbor::RemoteNameRequestMsg * request,::google::protobuf::Empty * response)117 ::grpc::Status ReadRemoteName(
118 ::grpc::ServerContext* context,
119 const ::bluetooth::neighbor::RemoteNameRequestMsg* request,
120 ::google::protobuf::Empty* response) override {
121 hci::Address remote;
122 ASSERT(hci::Address::FromString(request->address(), remote));
123 hci::PageScanRepetitionMode mode;
124 switch (request->page_scan_repetition_mode()) {
125 case 0:
126 mode = hci::PageScanRepetitionMode::R0;
127 break;
128 case 1:
129 mode = hci::PageScanRepetitionMode::R1;
130 break;
131 case 2:
132 mode = hci::PageScanRepetitionMode::R2;
133 break;
134 default:
135 LOG_ALWAYS_FATAL("Unknown PageScanRepetition mode %d", static_cast<int>(request->page_scan_repetition_mode()));
136 }
137 name_module_->ReadRemoteNameRequest(
138 remote,
139 mode,
140 request->clock_offset(),
141 (request->clock_offset() != 0 ? hci::ClockOffsetValid::VALID : hci::ClockOffsetValid::INVALID),
142 common::Bind(&NeighborFacadeService::on_remote_name, common::Unretained(this)),
143 facade_handler_);
144 return ::grpc::Status::OK;
145 }
146
GetRemoteNameEvents(::grpc::ServerContext * context,const::google::protobuf::Empty * request,::grpc::ServerWriter<RemoteNameResponseMsg> * writer)147 ::grpc::Status GetRemoteNameEvents(
148 ::grpc::ServerContext* context,
149 const ::google::protobuf::Empty* request,
150 ::grpc::ServerWriter<RemoteNameResponseMsg>* writer) override {
151 return pending_remote_names_.RunLoop(context, writer);
152 }
153
EnableInquiryScan(::grpc::ServerContext * context,const::bluetooth::neighbor::EnableMsg * request,::google::protobuf::Empty * response)154 ::grpc::Status EnableInquiryScan(
155 ::grpc::ServerContext* context,
156 const ::bluetooth::neighbor::EnableMsg* request,
157 ::google::protobuf::Empty* response) override {
158 if (request->enabled()) {
159 scan_module_->SetInquiryScan();
160 } else {
161 scan_module_->ClearInquiryScan();
162 }
163 return ::grpc::Status::OK;
164 }
165
EnablePageScan(::grpc::ServerContext * context,const::bluetooth::neighbor::EnableMsg * request,::google::protobuf::Empty * response)166 ::grpc::Status EnablePageScan(
167 ::grpc::ServerContext* context,
168 const ::bluetooth::neighbor::EnableMsg* request,
169 ::google::protobuf::Empty* response) override {
170 if (request->enabled()) {
171 scan_module_->SetPageScan();
172 } else {
173 scan_module_->ClearPageScan();
174 }
175 return ::grpc::Status::OK;
176 }
177
178 private:
on_incoming_inquiry_result(hci::EventView view)179 void on_incoming_inquiry_result(hci::EventView view) {
180 InquiryResultMsg inquiry_result_msg;
181 inquiry_result_msg.set_packet(std::string(view.begin(), view.end()));
182 pending_events_.OnIncomingEvent(std::move(inquiry_result_msg));
183 }
184
on_incoming_inquiry_complete(hci::ErrorCode status)185 void on_incoming_inquiry_complete(hci::ErrorCode status) {
186 InquiryResultMsg inquiry_result_msg;
187 inquiry_result_msg.set_packet(hci::ErrorCodeText(status));
188 pending_events_.OnIncomingEvent(std::move(inquiry_result_msg));
189 }
190
191 InquiryCallbacks inquiry_callbacks_{
__anon7aed44c10102() 192 .result = [this](hci::InquiryResultView view) { on_incoming_inquiry_result(view); },
__anon7aed44c10202() 193 .result_with_rssi = [this](hci::InquiryResultWithRssiView view) { on_incoming_inquiry_result(view); },
__anon7aed44c10302() 194 .extended_result = [this](hci::ExtendedInquiryResultView view) { on_incoming_inquiry_result(view); },
__anon7aed44c10402() 195 .complete = [this](hci::ErrorCode status) { on_incoming_inquiry_complete(status); }};
196
on_remote_name(hci::ErrorCode status,hci::Address address,std::array<uint8_t,248> name)197 void on_remote_name(hci::ErrorCode status, hci::Address address, std::array<uint8_t, 248> name) {
198 RemoteNameResponseMsg response;
199 response.set_status(static_cast<int>(status));
200 response.set_address(address.ToString());
201 response.set_name(name.begin(), name.size());
202 pending_remote_names_.OnIncomingEvent(response);
203 }
204
205 ConnectabilityModule* connectability_module_;
206 DiscoverabilityModule* discoverability_module_;
207 InquiryModule* inquiry_module_;
208 NameModule* name_module_;
209 ScanModule* scan_module_;
210 ::bluetooth::os::Handler* facade_handler_;
211 ::bluetooth::grpc::GrpcEventQueue<InquiryResultMsg> pending_events_{"InquiryResponses"};
212 ::bluetooth::grpc::GrpcEventQueue<RemoteNameResponseMsg> pending_remote_names_{"RemoteNameResponses"};
213 };
214
ListDependencies(ModuleList * list)215 void NeighborFacadeModule::ListDependencies(ModuleList* list) {
216 ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
217 list->add<ConnectabilityModule>();
218 list->add<DiscoverabilityModule>();
219 list->add<InquiryModule>();
220 list->add<NameModule>();
221 list->add<PageModule>();
222 list->add<ScanModule>();
223 }
224
Start()225 void NeighborFacadeModule::Start() {
226 ::bluetooth::grpc::GrpcFacadeModule::Start();
227 service_ = new NeighborFacadeService(
228 GetDependency<ConnectabilityModule>(),
229 GetDependency<DiscoverabilityModule>(),
230 GetDependency<InquiryModule>(),
231 GetDependency<NameModule>(),
232 GetDependency<PageModule>(),
233 GetDependency<ScanModule>(),
234 GetHandler());
235 }
236
Stop()237 void NeighborFacadeModule::Stop() {
238 delete service_;
239 ::bluetooth::grpc::GrpcFacadeModule::Stop();
240 }
241
GetService() const242 ::grpc::Service* NeighborFacadeModule::GetService() const {
243 return service_;
244 }
245
246 const ModuleFactory NeighborFacadeModule::Factory =
__anon7aed44c10502() 247 ::bluetooth::ModuleFactory([]() { return new NeighborFacadeModule(); });
248
249 } // namespace facade
250 } // namespace neighbor
251 } // namespace bluetooth
252