/* * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "test_command_handler.h" #include #include #include #include #include "device_boutique.h" #include "log.h" #include "phy.h" #include "rootcanal/configuration.pb.h" using std::vector; namespace rootcanal { static size_t ParseIntParam(std::string const& in) { return static_cast(std::strtoul(in.c_str(), nullptr, 0)); } TestCommandHandler::TestCommandHandler(TestModel& test_model) : model_(test_model) { #define SET_HANDLER(command_name, method) \ active_commands_[command_name] = [this](const vector& param) { \ method(param); \ }; SET_HANDLER("add", AddDevice); SET_HANDLER("add_remote", AddRemote); SET_HANDLER("del", RemoveDevice); SET_HANDLER("add_phy", AddPhy); SET_HANDLER("del_phy", RemovePhy); SET_HANDLER("add_device_to_phy", AddDeviceToPhy); SET_HANDLER("del_device_from_phy", RemoveDeviceFromPhy); SET_HANDLER("list", List); SET_HANDLER("set_device_address", SetDeviceAddress); SET_HANDLER("set_device_configuration", SetDeviceConfiguration); SET_HANDLER("set_timer_period", SetTimerPeriod); SET_HANDLER("start_timer", StartTimer); SET_HANDLER("stop_timer", StopTimer); SET_HANDLER("reset", Reset); #undef SET_HANDLER send_response_ = [](std::string const&) {}; } void TestCommandHandler::AddDefaults() { // Add a phy for LE and one for BR/EDR AddPhy({"LOW_ENERGY"}); AddPhy({"BR_EDR"}); // Add the controller to the Phys AddDeviceToPhy({"1", "1"}); AddDeviceToPhy({"1", "2"}); // Add default test devices and add the devices to the phys // // Add({"beacon", "be:ac:10:00:00:01", "1000"}); // AddDeviceToPhy({"2", "1"}); // // Add({"sniffer", "ca:12:1c:17:00:01"}); // AddDeviceToPhy({"3", "2"}); // // Add({"sniffer", "3c:5a:b4:04:05:06"}); // AddDeviceToPhy({"4", "2"}); List({}); SetTimerPeriod({"10"}); StartTimer({}); } void TestCommandHandler::HandleCommand(const std::string& name, const vector& args) { if (active_commands_.count(name) == 0) { response_string_ = "Unhandled command: " + name; send_response_(response_string_); return; } active_commands_[name](args); } void TestCommandHandler::RegisterSendResponse( const std::function callback) { send_response_ = callback; send_response_("RegisterSendResponse called"); } void TestCommandHandler::AddDevice(const vector& args) { if (args.empty()) { response_string_ = "TestCommandHandler 'add' takes an argument"; send_response_(response_string_); return; } std::shared_ptr new_dev = DeviceBoutique::Create(args); if (new_dev == NULL) { response_string_ = "TestCommandHandler 'add' " + args[0] + " failed!"; send_response_(response_string_); WARNING("{}", response_string_); return; } INFO("Add {}", new_dev->ToString()); size_t dev_index = model_.AddDevice(new_dev); response_string_ = std::to_string(dev_index) + std::string(":") + new_dev->ToString(); send_response_(response_string_); } void TestCommandHandler::AddRemote(const vector& args) { if (args.size() < 3) { response_string_ = "TestCommandHandler usage: add_remote host port phy_type"; send_response_(response_string_); return; } size_t port = ParseIntParam(args[1]); Phy::Type phy_type = Phy::Type::BR_EDR; if ("LOW_ENERGY" == args[2]) { phy_type = Phy::Type::LOW_ENERGY; } if (port == 0 || port > 0xffff || args[0].size() < 2) { response_string_ = "TestCommandHandler bad arguments to 'add_remote': "; response_string_ += args[0]; response_string_ += "@"; response_string_ += args[1]; send_response_(response_string_); return; } model_.AddRemote(args[0], port, phy_type); response_string_ = args[0] + std::string("@") + std::to_string(port); send_response_(response_string_); } void TestCommandHandler::RemoveDevice(const vector& args) { size_t dev_index = ParseIntParam(args[0]); model_.RemoveDevice(dev_index); response_string_ = "TestCommandHandler 'del' called with device at index " + std::to_string(dev_index); send_response_(response_string_); } void TestCommandHandler::AddPhy(const vector& args) { if (args.size() != 1) { response_string_ = "TestCommandHandler 'add_phy' takes one argument"; } else if (args[0] == "LOW_ENERGY") { model_.AddPhy(Phy::Type::LOW_ENERGY); response_string_ = "TestCommandHandler 'add_phy' called with LOW_ENERGY"; } else if (args[0] == "BR_EDR") { model_.AddPhy(Phy::Type::BR_EDR); response_string_ = "TestCommandHandler 'add_phy' called with BR_EDR"; } else { response_string_ = "TestCommandHandler 'add_phy' with unrecognized type " + args[0]; } send_response_(response_string_); } void TestCommandHandler::RemovePhy(const vector& args) { size_t phy_index = ParseIntParam(args[0]); model_.RemovePhy(phy_index); response_string_ = "TestCommandHandler 'del_phy' called with phy at index " + std::to_string(phy_index); send_response_(response_string_); } void TestCommandHandler::AddDeviceToPhy(const vector& args) { if (args.size() != 2) { response_string_ = "TestCommandHandler 'add_device_to_phy' takes two arguments"; send_response_(response_string_); return; } size_t dev_index = ParseIntParam(args[0]); size_t phy_index = ParseIntParam(args[1]); model_.AddDeviceToPhy(dev_index, phy_index); response_string_ = "TestCommandHandler 'add_device_to_phy' called with device " + std::to_string(dev_index) + " and phy " + std::to_string(phy_index); send_response_(response_string_); } void TestCommandHandler::RemoveDeviceFromPhy(const vector& args) { if (args.size() != 2) { response_string_ = "TestCommandHandler 'del_device_from_phy' takes two arguments"; send_response_(response_string_); return; } size_t dev_index = ParseIntParam(args[0]); size_t phy_index = ParseIntParam(args[1]); model_.RemoveDeviceFromPhy(dev_index, phy_index); response_string_ = "TestCommandHandler 'del_device_from_phy' called with device " + std::to_string(dev_index) + " and phy " + std::to_string(phy_index); send_response_(response_string_); } void TestCommandHandler::List(const vector& args) { if (!args.empty()) { INFO("Unused args: arg[0] = {}", args[0]); return; } send_response_(model_.List()); } void TestCommandHandler::SetDeviceAddress(const vector& args) { if (args.size() != 2) { response_string_ = "TestCommandHandler 'set_device_address' takes two arguments"; send_response_(response_string_); return; } size_t device_id = ParseIntParam(args[0]); Address device_address{}; Address::FromString(args[1], device_address); model_.SetDeviceAddress(device_id, device_address); response_string_ = "set_device_address " + args[0]; response_string_ += " "; response_string_ += args[1]; send_response_(response_string_); } void TestCommandHandler::SetDeviceConfiguration(const vector& args) { if (args.size() != 2) { response_string_ = "TestCommandHandler 'set_device_configuration' takes two arguments"; send_response_(response_string_); return; } size_t device_id = ParseIntParam(args[0]); rootcanal::configuration::ControllerPreset preset = rootcanal::configuration::ControllerPreset::DEFAULT; if (args[1] == "default") { preset = rootcanal::configuration::ControllerPreset::DEFAULT; } else if (args[1] == "laird_bl654") { preset = rootcanal::configuration::ControllerPreset::LAIRD_BL654; } else if (args[1] == "csr_rck_pts_dongle") { preset = rootcanal::configuration::ControllerPreset::CSR_RCK_PTS_DONGLE; } else { response_string_ = "TestCommandHandler 'set_device_configuration' invalid configuration preset"; send_response_(response_string_); return; } rootcanal::configuration::Controller configuration; configuration.set_preset(preset); model_.SetDeviceConfiguration(device_id, configuration); response_string_ = "set_device_configuration " + args[0]; response_string_ += " "; response_string_ += args[1]; send_response_(response_string_); } void TestCommandHandler::SetTimerPeriod(const vector& args) { if (args.size() != 1) { INFO("SetTimerPeriod takes 1 argument"); } size_t period = ParseIntParam(args[0]); if (period != 0) { response_string_ = "set timer period to "; response_string_ += args[0]; model_.SetTimerPeriod(std::chrono::milliseconds(period)); } else { response_string_ = "invalid timer period "; response_string_ += args[0]; } send_response_(response_string_); } void TestCommandHandler::StartTimer(const vector& args) { if (!args.empty()) { INFO("Unused args: arg[0] = {}", args[0]); } model_.StartTimer(); response_string_ = "timer started"; send_response_(response_string_); } void TestCommandHandler::StopTimer(const vector& args) { if (!args.empty()) { INFO("Unused args: arg[0] = {}", args[0]); } model_.StopTimer(); response_string_ = "timer stopped"; send_response_(response_string_); } void TestCommandHandler::Reset(const std::vector& args) { if (!args.empty()) { INFO("Unused args: arg[0] = {}", args[0]); } model_.Reset(); response_string_ = "model reset"; send_response_(response_string_); } } // namespace rootcanal