| // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "wimax_manager/manager.h" |
| |
| #include <fcntl.h> |
| |
| #include <utility> |
| |
| #include <base/files/scoped_file.h> |
| #include <base/logging.h> |
| #include <base/posix/eintr_wrapper.h> |
| #include <base/stl_util.h> |
| #include <google/protobuf/io/zero_copy_stream_impl.h> |
| #include <google/protobuf/text_format.h> |
| |
| #include "wimax_manager/dbus_service_dbus_proxy.h" |
| #include "wimax_manager/device.h" |
| #include "wimax_manager/device_dbus_adaptor.h" |
| #include "wimax_manager/event_dispatcher.h" |
| #include "wimax_manager/gdm_driver.h" |
| #include "wimax_manager/manager_dbus_adaptor.h" |
| #include "wimax_manager/proto_bindings/config.pb.h" |
| #include "wimax_manager/proto_bindings/network_operator.pb.h" |
| |
| namespace wimax_manager { |
| |
| namespace { |
| |
| const int kMaxNumberOfDeviceScans = 15; |
| const int kDefaultDeviceScanIntervalInSeconds = 1; |
| const int kDeviceScanDelayAfterResumeInSeconds = 3; |
| const char kDefaultConfigFile[] = "/usr/share/wimax-manager/default.conf"; |
| |
| } // namespace |
| |
| Manager::Manager(EventDispatcher *dispatcher) |
| : dispatcher_(dispatcher), |
| num_device_scans_(0), |
| dbus_service_(this) { |
| } |
| |
| Manager::~Manager() { |
| Finalize(); |
| } |
| |
| bool Manager::Initialize() { |
| if (driver_.get()) |
| return true; |
| |
| if (!LoadConfig(base::FilePath(kDefaultConfigFile))) { |
| LOG(ERROR) << "Failed to load config"; |
| return false; |
| } |
| |
| dbus_service_.CreateDBusProxy(); |
| dbus_service_.Initialize(); |
| |
| driver_.reset(new(std::nothrow) GdmDriver(this)); |
| if (!driver_.get()) { |
| LOG(ERROR) << "Failed to create driver"; |
| return false; |
| } |
| |
| if (!driver_->Initialize()) { |
| LOG(ERROR) << "Failed to initialize driver"; |
| return false; |
| } |
| |
| if (!ScanDevices()) |
| return false; |
| |
| return true; |
| } |
| |
| bool Manager::Finalize() { |
| CancelDeviceScan(); |
| devices_.clear(); |
| |
| if (dbus_adaptor()) |
| dbus_adaptor()->UpdateDevices(); |
| |
| if (!driver_.get()) |
| return true; |
| |
| if (!driver_->Finalize()) { |
| LOG(ERROR) << "Failed to de-initialize driver"; |
| return false; |
| } |
| |
| driver_.reset(); |
| dbus_service_.Finalize(); |
| return true; |
| } |
| |
| bool Manager::ScanDevices() { |
| device_scan_timer_.Stop(); |
| |
| if (!devices_.empty()) |
| return true; |
| |
| if (!driver_->GetDevices(&devices_)) { |
| LOG(ERROR) << "Failed to get list of devices"; |
| return false; |
| } |
| |
| if (!devices_.empty()) { |
| for (size_t i = 0; i < devices_.size(); ++i) |
| devices_[i]->CreateDBusAdaptor(); |
| |
| dbus_adaptor()->UpdateDevices(); |
| return true; |
| } |
| |
| // Some platforms may not have any WiMAX device, so instead of scanning |
| // indefinitely, stop the device scan after a number of attempts. |
| if (++num_device_scans_ < kMaxNumberOfDeviceScans) { |
| VLOG(1) << "No WiMAX devices detected. Rescan later."; |
| device_scan_timer_.Start( |
| FROM_HERE, |
| base::TimeDelta::FromSeconds(kDefaultDeviceScanIntervalInSeconds), |
| this, |
| &Manager::OnDeviceScan); |
| } |
| return true; |
| } |
| |
| void Manager::OnDeviceScan() { |
| ScanDevices(); |
| } |
| |
| void Manager::CancelDeviceScan() { |
| // Cancel any pending device scan. |
| device_scan_timer_.Stop(); |
| num_device_scans_ = 0; |
| } |
| |
| void Manager::Suspend() { |
| CancelDeviceScan(); |
| devices_.clear(); |
| dbus_adaptor()->UpdateDevices(); |
| } |
| |
| void Manager::Resume() { |
| // After resuming from suspend, the old device may not have been cleaned up. |
| // Delay the device scan to avoid getting the old device. |
| device_scan_timer_.Start( |
| FROM_HERE, |
| base::TimeDelta::FromSeconds(kDeviceScanDelayAfterResumeInSeconds), |
| this, |
| &Manager::OnDeviceScan); |
| } |
| |
| bool Manager::LoadConfig(const base::FilePath &file_path) { |
| int fd = HANDLE_EINTR(open(file_path.MaybeAsASCII().c_str(), O_RDONLY)); |
| if (fd == -1) { |
| PLOG(ERROR) << "Failed to read config file '" |
| << file_path.MaybeAsASCII() << "'"; |
| return false; |
| } |
| |
| base::ScopedFD scoped_fd(fd); |
| google::protobuf::io::FileInputStream file_stream(fd); |
| |
| std::unique_ptr<Config> config(new(std::nothrow) Config()); |
| if (!google::protobuf::TextFormat::Parse(&file_stream, config.get())) |
| return false; |
| |
| config_ = std::move(config); |
| return true; |
| } |
| |
| const NetworkOperator *Manager::GetNetworkOperator( |
| Network::Identifier network_id) const { |
| if (!config_.get()) |
| return nullptr; |
| |
| for (int i = 0; i < config_->network_operator_size(); ++i) { |
| const NetworkOperator &network_operator = config_->network_operator(i); |
| if (network_operator.identifier() == network_id) |
| return &network_operator; |
| } |
| |
| return nullptr; |
| } |
| |
| } // namespace wimax_manager |