blob: 69e9bf12e85c192cc0917c46b76e1ba57f0957ce [file] [log] [blame]
// Copyright (c) 2013 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 "shill/cellular_capability_universal_cdma.h"
#include <chromeos/dbus/service_constants.h>
#include <base/stringprintf.h>
#include <base/string_number_conversions.h>
#include <base/string_util.h>
#include "shill/cellular_operator_info.h"
#include "shill/dbus_properties_proxy_interface.h"
#include "shill/logging.h"
#include "shill/proxy_factory.h"
#ifdef MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN
#error "Do not include mm-modem.h"
#endif
using base::UintToString;
using std::string;
using std::vector;
namespace shill {
namespace {
string FormattedSID(const string &sid) {
return "[SID=" + sid + "]";
}
} // namespace
// static
unsigned int
CellularCapabilityUniversalCDMA::friendly_service_name_id_cdma_ = 0;
CellularCapabilityUniversalCDMA::CellularCapabilityUniversalCDMA(
Cellular *cellular,
ProxyFactory *proxy_factory,
ModemInfo *modem_info)
: CellularCapabilityUniversal(cellular,
proxy_factory,
modem_info),
cdma_1x_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
cdma_evdo_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
nid_(0),
sid_(0) {
SLOG(Cellular, 2) << "Cellular capability constructed: Universal CDMA";
// TODO(armansito): Need to expose PRL version here to carry through
// activation. PRL version is not obtainable from ModemManager and will
// need to be stored in a special place (such as CellularOperatorInfo).
// See crbug.com/197330.
}
void CellularCapabilityUniversalCDMA::InitProxies() {
SLOG(Cellular, 2) << __func__;
modem_cdma_proxy_.reset(
proxy_factory()->CreateMM1ModemModemCdmaProxy(cellular()->dbus_path(),
cellular()->dbus_owner()));
CellularCapabilityUniversal::InitProxies();
}
void CellularCapabilityUniversalCDMA::ReleaseProxies() {
SLOG(Cellular, 2) << __func__;
modem_cdma_proxy_.reset();
CellularCapabilityUniversal::ReleaseProxies();
}
void CellularCapabilityUniversalCDMA::Activate(
const string &carrier,
Error *error,
const ResultCallback &callback) {
// TODO(armansito): Implement activation.
OnUnsupportedOperation(__func__, error);
}
void CellularCapabilityUniversalCDMA::CompleteActivation(Error *error) {
// TODO(armansito): Implement activation.
OnUnsupportedOperation(__func__, error);
}
void CellularCapabilityUniversalCDMA::DisconnectCleanup() {
SLOG(Cellular, 2) << __func__;
// TODO(armansito): Handle activation logic here.
}
void CellularCapabilityUniversalCDMA::OnServiceCreated() {
SLOG(Cellular, 2) << __func__;
// TODO (armansito): Set storage identifier here based on the superclass
// implementation.
bool activation_required = IsServiceActivationRequired();
cellular()->service()->SetActivationState(
activation_required ?
flimflam::kActivationStateNotActivated :
flimflam::kActivationStateActivated);
cellular()->service()->SetActivateOverNonCellularNetwork(activation_required);
UpdateServingOperator();
UpdateOLP();
}
void CellularCapabilityUniversalCDMA::UpdateOLP() {
SLOG(Cellular,2) << __func__;
if (!modem_info()->cellular_operator_info())
return;
const CellularService::OLP *result =
modem_info()->cellular_operator_info()->GetOLPBySID(
UintToString(sid_));
if (!result)
return;
CellularService::OLP olp;
olp.CopyFrom(*result);
string post_data = olp.GetPostData();
ReplaceSubstringsAfterOffset(&post_data, 0, "${esn}", esn());
ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}", mdn());
ReplaceSubstringsAfterOffset(&post_data, 0, "${meid}", meid());
olp.SetPostData(post_data);
cellular()->service()->SetOLP(olp);
}
void CellularCapabilityUniversalCDMA::GetProperties() {
SLOG(Cellular, 2) << __func__;
CellularCapabilityUniversal::GetProperties();
scoped_ptr<DBusPropertiesProxyInterface> properties_proxy(
proxy_factory()->CreateDBusPropertiesProxy(cellular()->dbus_path(),
cellular()->dbus_owner()));
DBusPropertiesMap properties(
properties_proxy->GetAll(MM_DBUS_INTERFACE_MODEM_MODEMCDMA));
OnModemCDMAPropertiesChanged(properties, vector<string>());
}
string CellularCapabilityUniversalCDMA::CreateFriendlyServiceName() {
SLOG(Cellular, 2) << __func__ << ": " << GetRoamingStateString();
if (provider_.GetCode().empty()) {
UpdateOperatorInfo();
}
string name = provider_.GetName();
if (!name.empty()) {
// TODO(armansito): We may need to show the provider name in a
// specific way if roaming.
return name;
}
string code = provider_.GetCode();
if (!code.empty()) {
return "cellular_sid_" + code;
}
return base::StringPrintf("CDMANetwork%u", friendly_service_name_id_cdma_++);
}
void CellularCapabilityUniversalCDMA::UpdateOperatorInfo() {
SLOG(Cellular, 2) << __func__;
if (sid_ == 0 || !modem_info()->cellular_operator_info()) {
SLOG(Cellular, 2) << "No provider is currently available.";
provider_.SetCode("");
return;
}
string sid = UintToString(sid_);
const CellularOperatorInfo::CellularOperator *provider =
modem_info()->cellular_operator_info()->GetCellularOperatorBySID(sid);
if (!provider) {
SLOG(Cellular, 2) << "CDMA provider with "
<< FormattedSID(sid)
<< " not found.";
return;
}
if (!provider->name_list().empty()) {
provider_.SetName(provider->name_list()[0].name);
}
provider_.SetCode(sid);
provider_.SetCountry(provider->country());
// TODO(armansito): The CDMA interface only returns information about the
// current serving carrier, so for now both the home provider and the
// serving operator will be the same in case of roaming. We should figure
// out if there is a way to (and whether or not it is necessary to)
// determine if we're roaming.
cellular()->set_home_provider(provider_);
UpdateServingOperator();
}
void CellularCapabilityUniversalCDMA::UpdateServingOperator() {
SLOG(Cellular, 2) << __func__;
if (cellular()->service().get()) {
cellular()->service()->SetServingOperator(cellular()->home_provider());
}
}
void CellularCapabilityUniversalCDMA::Register(const ResultCallback &callback) {
// TODO(armansito): Remove once 3GPP is implemented in its own class.
}
void CellularCapabilityUniversalCDMA::RegisterOnNetwork(
const string &network_id,
Error *error,
const ResultCallback &callback) {
// TODO(armansito): Remove once 3GPP is implemented in its own class.
}
bool CellularCapabilityUniversalCDMA::IsRegistered() {
return (cdma_1x_registration_state_ ==
MM_MODEM_CDMA_REGISTRATION_STATE_HOME ||
cdma_1x_registration_state_ ==
MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING ||
cdma_evdo_registration_state_ ==
MM_MODEM_CDMA_REGISTRATION_STATE_HOME ||
cdma_evdo_registration_state_ ==
MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING);
}
void CellularCapabilityUniversalCDMA::SetUnregistered(bool /*searching*/) {
cdma_1x_registration_state_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
cdma_evdo_registration_state_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
}
void CellularCapabilityUniversalCDMA::RequirePIN(
const string &pin, bool require,
Error *error, const ResultCallback &callback) {
// TODO(armansito): Remove once 3GPP is implemented in its own class.
}
void CellularCapabilityUniversalCDMA::EnterPIN(
const string &pin,
Error *error,
const ResultCallback &callback) {
// TODO(armansito): Remove once 3GPP is implemented in its own class.
}
void CellularCapabilityUniversalCDMA::UnblockPIN(
const string &unblock_code,
const string &pin,
Error *error,
const ResultCallback &callback) {
// TODO(armansito): Remove once 3GPP is implemented in its own class.
}
void CellularCapabilityUniversalCDMA::ChangePIN(
const string &old_pin, const string &new_pin,
Error *error, const ResultCallback &callback) {
// TODO(armansito): Remove once 3GPP is implemented in its own class.
}
void CellularCapabilityUniversalCDMA::Scan(Error *error,
const ResultCallback &callback) {
// TODO(armansito): Remove once 3GPP is implemented in its own class.
}
void CellularCapabilityUniversalCDMA::OnSimPathChanged(
const string &sim_path) {
// TODO(armansito): Remove once 3GPP is implemented in its own class.
}
string CellularCapabilityUniversalCDMA::GetRoamingStateString() const {
uint32 state = cdma_evdo_registration_state_;
if (state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
state = cdma_1x_registration_state_;
}
switch (state) {
case MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN:
case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED:
break;
case MM_MODEM_CDMA_REGISTRATION_STATE_HOME:
return flimflam::kRoamingStateHome;
case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING:
return flimflam::kRoamingStateRoaming;
default:
NOTREACHED();
}
return flimflam::kRoamingStateUnknown;
}
void CellularCapabilityUniversalCDMA::OnDBusPropertiesChanged(
const string &interface,
const DBusPropertiesMap &changed_properties,
const vector<string> &invalidated_properties) {
SLOG(Cellular, 2) << __func__ << "(" << interface << ")";
if (interface == MM_DBUS_INTERFACE_MODEM_MODEMCDMA) {
OnModemCDMAPropertiesChanged(changed_properties, invalidated_properties);
} else {
CellularCapabilityUniversal::OnDBusPropertiesChanged(
interface, changed_properties, invalidated_properties);
}
}
void CellularCapabilityUniversalCDMA::OnModemCDMAPropertiesChanged(
const DBusPropertiesMap &properties,
const std::vector<std::string> &/*invalidated_properties*/) {
SLOG(Cellular, 2) << __func__;
string str_value;
if (DBusProperties::GetString(properties,
MM_MODEM_MODEMCDMA_PROPERTY_MEID,
&str_value))
set_meid(str_value);
if (DBusProperties::GetString(properties,
MM_MODEM_MODEMCDMA_PROPERTY_ESN,
&str_value))
set_esn(str_value);
uint32_t sid = sid_;
uint32_t nid = nid_;
MMModemCdmaRegistrationState state_1x = cdma_1x_registration_state_;
MMModemCdmaRegistrationState state_evdo = cdma_evdo_registration_state_;
bool registration_changed = false;
uint32_t uint_value;
if (DBusProperties::GetUint32(
properties,
MM_MODEM_MODEMCDMA_PROPERTY_CDMA1XREGISTRATIONSTATE,
&uint_value)) {
state_1x = static_cast<MMModemCdmaRegistrationState>(uint_value);
registration_changed = true;
}
if (DBusProperties::GetUint32(
properties,
MM_MODEM_MODEMCDMA_PROPERTY_EVDOREGISTRATIONSTATE,
&uint_value)) {
state_evdo = static_cast<MMModemCdmaRegistrationState>(uint_value);
registration_changed = true;
}
if (DBusProperties::GetUint32(
properties,
MM_MODEM_MODEMCDMA_PROPERTY_SID,
&uint_value)) {
sid = uint_value;
registration_changed = true;
}
if (DBusProperties::GetUint32(
properties,
MM_MODEM_MODEMCDMA_PROPERTY_NID,
&uint_value)) {
nid = uint_value;
registration_changed = true;
}
if (registration_changed)
OnCDMARegistrationChanged(state_1x, state_evdo, sid, nid);
}
void CellularCapabilityUniversalCDMA::OnCDMARegistrationChanged(
MMModemCdmaRegistrationState state_1x,
MMModemCdmaRegistrationState state_evdo,
uint32_t sid, uint32_t nid) {
SLOG(Cellular, 2) << __func__
<< ": state_1x=" << state_1x
<< ", state_evdo=" << state_evdo;
cdma_1x_registration_state_ = state_1x;
cdma_evdo_registration_state_ = state_evdo;
sid_ = sid;
nid_ = nid;
UpdateOperatorInfo();
cellular()->HandleNewRegistrationState();
}
} // namespace shill