1 /*
2 * Copyright 2018 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 "test_command_handler.h"
18
19 #include <stdlib.h>
20
21 #include <fstream>
22 #include <memory>
23 #include <regex>
24
25 #include "device_boutique.h"
26 #include "log.h"
27 #include "phy.h"
28 #include "rootcanal/configuration.pb.h"
29
30 using std::vector;
31
32 namespace rootcanal {
33
ParseIntParam(std::string const & in)34 static size_t ParseIntParam(std::string const& in) {
35 return static_cast<size_t>(std::strtoul(in.c_str(), nullptr, 0));
36 }
37
TestCommandHandler(TestModel & test_model)38 TestCommandHandler::TestCommandHandler(TestModel& test_model)
39 : model_(test_model) {
40 #define SET_HANDLER(command_name, method) \
41 active_commands_[command_name] = [this](const vector<std::string>& param) { \
42 method(param); \
43 };
44 SET_HANDLER("add", AddDevice);
45 SET_HANDLER("add_remote", AddRemote);
46 SET_HANDLER("del", RemoveDevice);
47 SET_HANDLER("add_phy", AddPhy);
48 SET_HANDLER("del_phy", RemovePhy);
49 SET_HANDLER("add_device_to_phy", AddDeviceToPhy);
50 SET_HANDLER("del_device_from_phy", RemoveDeviceFromPhy);
51 SET_HANDLER("list", List);
52 SET_HANDLER("set_device_address", SetDeviceAddress);
53 SET_HANDLER("set_device_configuration", SetDeviceConfiguration);
54 SET_HANDLER("set_timer_period", SetTimerPeriod);
55 SET_HANDLER("start_timer", StartTimer);
56 SET_HANDLER("stop_timer", StopTimer);
57 SET_HANDLER("reset", Reset);
58 #undef SET_HANDLER
59 send_response_ = [](std::string const&) {};
60 }
61
AddDefaults()62 void TestCommandHandler::AddDefaults() {
63 // Add a phy for LE and one for BR/EDR
64 AddPhy({"LOW_ENERGY"});
65 AddPhy({"BR_EDR"});
66
67 // Add the controller to the Phys
68 AddDeviceToPhy({"1", "1"});
69 AddDeviceToPhy({"1", "2"});
70
71 // Add default test devices and add the devices to the phys
72 //
73 // Add({"beacon", "be:ac:10:00:00:01", "1000"});
74 // AddDeviceToPhy({"2", "1"});
75 //
76 // Add({"sniffer", "ca:12:1c:17:00:01"});
77 // AddDeviceToPhy({"3", "2"});
78 //
79 // Add({"sniffer", "3c:5a:b4:04:05:06"});
80 // AddDeviceToPhy({"4", "2"});
81
82 List({});
83
84 SetTimerPeriod({"10"});
85 StartTimer({});
86 }
87
HandleCommand(const std::string & name,const vector<std::string> & args)88 void TestCommandHandler::HandleCommand(const std::string& name,
89 const vector<std::string>& args) {
90 if (active_commands_.count(name) == 0) {
91 response_string_ = "Unhandled command: " + name;
92 send_response_(response_string_);
93 return;
94 }
95 active_commands_[name](args);
96 }
97
RegisterSendResponse(const std::function<void (const std::string &)> callback)98 void TestCommandHandler::RegisterSendResponse(
99 const std::function<void(const std::string&)> callback) {
100 send_response_ = callback;
101 send_response_("RegisterSendResponse called");
102 }
103
AddDevice(const vector<std::string> & args)104 void TestCommandHandler::AddDevice(const vector<std::string>& args) {
105 if (args.empty()) {
106 response_string_ = "TestCommandHandler 'add' takes an argument";
107 send_response_(response_string_);
108 return;
109 }
110 std::shared_ptr<Device> new_dev = DeviceBoutique::Create(args);
111
112 if (new_dev == NULL) {
113 response_string_ = "TestCommandHandler 'add' " + args[0] + " failed!";
114 send_response_(response_string_);
115 WARNING("{}", response_string_);
116 return;
117 }
118
119 INFO("Add {}", new_dev->ToString());
120 size_t dev_index = model_.AddDevice(new_dev);
121 response_string_ =
122 std::to_string(dev_index) + std::string(":") + new_dev->ToString();
123 send_response_(response_string_);
124 }
125
AddRemote(const vector<std::string> & args)126 void TestCommandHandler::AddRemote(const vector<std::string>& args) {
127 if (args.size() < 3) {
128 response_string_ =
129 "TestCommandHandler usage: add_remote host port phy_type";
130 send_response_(response_string_);
131 return;
132 }
133
134 size_t port = ParseIntParam(args[1]);
135 Phy::Type phy_type = Phy::Type::BR_EDR;
136 if ("LOW_ENERGY" == args[2]) {
137 phy_type = Phy::Type::LOW_ENERGY;
138 }
139 if (port == 0 || port > 0xffff || args[0].size() < 2) {
140 response_string_ = "TestCommandHandler bad arguments to 'add_remote': ";
141 response_string_ += args[0];
142 response_string_ += "@";
143 response_string_ += args[1];
144 send_response_(response_string_);
145 return;
146 }
147
148 model_.AddRemote(args[0], port, phy_type);
149
150 response_string_ = args[0] + std::string("@") + std::to_string(port);
151 send_response_(response_string_);
152 }
153
RemoveDevice(const vector<std::string> & args)154 void TestCommandHandler::RemoveDevice(const vector<std::string>& args) {
155 size_t dev_index = ParseIntParam(args[0]);
156
157 model_.RemoveDevice(dev_index);
158 response_string_ = "TestCommandHandler 'del' called with device at index " +
159 std::to_string(dev_index);
160 send_response_(response_string_);
161 }
162
AddPhy(const vector<std::string> & args)163 void TestCommandHandler::AddPhy(const vector<std::string>& args) {
164 if (args.size() != 1) {
165 response_string_ = "TestCommandHandler 'add_phy' takes one argument";
166 } else if (args[0] == "LOW_ENERGY") {
167 model_.AddPhy(Phy::Type::LOW_ENERGY);
168 response_string_ = "TestCommandHandler 'add_phy' called with LOW_ENERGY";
169 } else if (args[0] == "BR_EDR") {
170 model_.AddPhy(Phy::Type::BR_EDR);
171 response_string_ = "TestCommandHandler 'add_phy' called with BR_EDR";
172 } else {
173 response_string_ =
174 "TestCommandHandler 'add_phy' with unrecognized type " + args[0];
175 }
176 send_response_(response_string_);
177 }
178
RemovePhy(const vector<std::string> & args)179 void TestCommandHandler::RemovePhy(const vector<std::string>& args) {
180 size_t phy_index = ParseIntParam(args[0]);
181
182 model_.RemovePhy(phy_index);
183 response_string_ = "TestCommandHandler 'del_phy' called with phy at index " +
184 std::to_string(phy_index);
185 send_response_(response_string_);
186 }
187
AddDeviceToPhy(const vector<std::string> & args)188 void TestCommandHandler::AddDeviceToPhy(const vector<std::string>& args) {
189 if (args.size() != 2) {
190 response_string_ =
191 "TestCommandHandler 'add_device_to_phy' takes two arguments";
192 send_response_(response_string_);
193 return;
194 }
195 size_t dev_index = ParseIntParam(args[0]);
196 size_t phy_index = ParseIntParam(args[1]);
197 model_.AddDeviceToPhy(dev_index, phy_index);
198 response_string_ =
199 "TestCommandHandler 'add_device_to_phy' called with device " +
200 std::to_string(dev_index) + " and phy " + std::to_string(phy_index);
201 send_response_(response_string_);
202 }
203
RemoveDeviceFromPhy(const vector<std::string> & args)204 void TestCommandHandler::RemoveDeviceFromPhy(const vector<std::string>& args) {
205 if (args.size() != 2) {
206 response_string_ =
207 "TestCommandHandler 'del_device_from_phy' takes two arguments";
208 send_response_(response_string_);
209 return;
210 }
211 size_t dev_index = ParseIntParam(args[0]);
212 size_t phy_index = ParseIntParam(args[1]);
213 model_.RemoveDeviceFromPhy(dev_index, phy_index);
214 response_string_ =
215 "TestCommandHandler 'del_device_from_phy' called with device " +
216 std::to_string(dev_index) + " and phy " + std::to_string(phy_index);
217 send_response_(response_string_);
218 }
219
List(const vector<std::string> & args)220 void TestCommandHandler::List(const vector<std::string>& args) {
221 if (!args.empty()) {
222 INFO("Unused args: arg[0] = {}", args[0]);
223 return;
224 }
225 send_response_(model_.List());
226 }
227
SetDeviceAddress(const vector<std::string> & args)228 void TestCommandHandler::SetDeviceAddress(const vector<std::string>& args) {
229 if (args.size() != 2) {
230 response_string_ =
231 "TestCommandHandler 'set_device_address' takes two arguments";
232 send_response_(response_string_);
233 return;
234 }
235 size_t device_id = ParseIntParam(args[0]);
236 Address device_address{};
237 Address::FromString(args[1], device_address);
238 model_.SetDeviceAddress(device_id, device_address);
239 response_string_ = "set_device_address " + args[0];
240 response_string_ += " ";
241 response_string_ += args[1];
242 send_response_(response_string_);
243 }
244
SetDeviceConfiguration(const vector<std::string> & args)245 void TestCommandHandler::SetDeviceConfiguration(const vector<std::string>& args) {
246 if (args.size() != 2) {
247 response_string_ =
248 "TestCommandHandler 'set_device_configuration' takes two arguments";
249 send_response_(response_string_);
250 return;
251 }
252 size_t device_id = ParseIntParam(args[0]);
253 rootcanal::configuration::ControllerPreset preset =
254 rootcanal::configuration::ControllerPreset::DEFAULT;
255
256 if (args[1] == "default") {
257 preset = rootcanal::configuration::ControllerPreset::DEFAULT;
258 } else if (args[1] == "laird_bl654") {
259 preset = rootcanal::configuration::ControllerPreset::LAIRD_BL654;
260 } else if (args[1] == "csr_rck_pts_dongle") {
261 preset = rootcanal::configuration::ControllerPreset::CSR_RCK_PTS_DONGLE;
262 } else {
263 response_string_ =
264 "TestCommandHandler 'set_device_configuration' invalid configuration preset";
265 send_response_(response_string_);
266 return;
267 }
268
269 rootcanal::configuration::Controller configuration;
270 configuration.set_preset(preset);
271 model_.SetDeviceConfiguration(device_id, configuration);
272 response_string_ = "set_device_configuration " + args[0];
273 response_string_ += " ";
274 response_string_ += args[1];
275 send_response_(response_string_);
276 }
277
SetTimerPeriod(const vector<std::string> & args)278 void TestCommandHandler::SetTimerPeriod(const vector<std::string>& args) {
279 if (args.size() != 1) {
280 INFO("SetTimerPeriod takes 1 argument");
281 }
282 size_t period = ParseIntParam(args[0]);
283 if (period != 0) {
284 response_string_ = "set timer period to ";
285 response_string_ += args[0];
286 model_.SetTimerPeriod(std::chrono::milliseconds(period));
287 } else {
288 response_string_ = "invalid timer period ";
289 response_string_ += args[0];
290 }
291 send_response_(response_string_);
292 }
293
StartTimer(const vector<std::string> & args)294 void TestCommandHandler::StartTimer(const vector<std::string>& args) {
295 if (!args.empty()) {
296 INFO("Unused args: arg[0] = {}", args[0]);
297 }
298 model_.StartTimer();
299 response_string_ = "timer started";
300 send_response_(response_string_);
301 }
302
StopTimer(const vector<std::string> & args)303 void TestCommandHandler::StopTimer(const vector<std::string>& args) {
304 if (!args.empty()) {
305 INFO("Unused args: arg[0] = {}", args[0]);
306 }
307 model_.StopTimer();
308 response_string_ = "timer stopped";
309 send_response_(response_string_);
310 }
311
Reset(const std::vector<std::string> & args)312 void TestCommandHandler::Reset(const std::vector<std::string>& args) {
313 if (!args.empty()) {
314 INFO("Unused args: arg[0] = {}", args[0]);
315 }
316 model_.Reset();
317 response_string_ = "model reset";
318 send_response_(response_string_);
319 }
320
321 } // namespace rootcanal
322