Arman Uguray | 72fab6a | 2013-01-10 19:32:42 -0800 | [diff] [blame^] | 1 | // Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "shill/cellular_capability_universal_cdma.h" |
| 6 | |
| 7 | #include <chromeos/dbus/service_constants.h> |
| 8 | #include <base/stringprintf.h> |
| 9 | #include <base/string_number_conversions.h> |
| 10 | #include <base/string_util.h> |
| 11 | |
| 12 | #include "shill/cellular_operator_info.h" |
| 13 | #include "shill/dbus_properties_proxy_interface.h" |
| 14 | #include "shill/logging.h" |
| 15 | #include "shill/proxy_factory.h" |
| 16 | |
| 17 | #ifdef MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN |
| 18 | #error "Do not include mm-modem.h" |
| 19 | #endif |
| 20 | |
| 21 | using base::UintToString; |
| 22 | |
| 23 | using std::string; |
| 24 | using std::vector; |
| 25 | |
| 26 | namespace shill { |
| 27 | |
| 28 | namespace { |
| 29 | |
| 30 | string FormattedSID(const string &sid) { |
| 31 | return "[SID=" + sid + "]"; |
| 32 | } |
| 33 | |
| 34 | } // namespace |
| 35 | |
| 36 | // static |
| 37 | unsigned int |
| 38 | CellularCapabilityUniversalCDMA::friendly_service_name_id_cdma_ = 0; |
| 39 | |
| 40 | CellularCapabilityUniversalCDMA::CellularCapabilityUniversalCDMA( |
| 41 | Cellular *cellular, |
| 42 | ProxyFactory *proxy_factory, |
| 43 | ModemInfo *modem_info) |
| 44 | : CellularCapabilityUniversal(cellular, |
| 45 | proxy_factory, |
| 46 | modem_info), |
| 47 | cdma_1x_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN), |
| 48 | cdma_evdo_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN), |
| 49 | nid_(0), |
| 50 | sid_(0) { |
| 51 | SLOG(Cellular, 2) << "Cellular capability constructed: Universal CDMA"; |
| 52 | // TODO(armansito): Need to expose PRL version here to carry through |
| 53 | // activation. PRL version is not obtainable from ModemManager and will |
| 54 | // need to be stored in a special place (such as CellularOperatorInfo). |
| 55 | // See crbug.com/197330. |
| 56 | } |
| 57 | |
| 58 | void CellularCapabilityUniversalCDMA::InitProxies() { |
| 59 | SLOG(Cellular, 2) << __func__; |
| 60 | modem_cdma_proxy_.reset( |
| 61 | proxy_factory()->CreateMM1ModemModemCdmaProxy(cellular()->dbus_path(), |
| 62 | cellular()->dbus_owner())); |
| 63 | CellularCapabilityUniversal::InitProxies(); |
| 64 | } |
| 65 | |
| 66 | void CellularCapabilityUniversalCDMA::ReleaseProxies() { |
| 67 | SLOG(Cellular, 2) << __func__; |
| 68 | modem_cdma_proxy_.reset(); |
| 69 | CellularCapabilityUniversal::ReleaseProxies(); |
| 70 | } |
| 71 | |
| 72 | void CellularCapabilityUniversalCDMA::Activate( |
| 73 | const string &carrier, |
| 74 | Error *error, |
| 75 | const ResultCallback &callback) { |
| 76 | // TODO(armansito): Implement activation. |
| 77 | OnUnsupportedOperation(__func__, error); |
| 78 | } |
| 79 | |
| 80 | void CellularCapabilityUniversalCDMA::CompleteActivation(Error *error) { |
| 81 | // TODO(armansito): Implement activation. |
| 82 | OnUnsupportedOperation(__func__, error); |
| 83 | } |
| 84 | |
| 85 | void CellularCapabilityUniversalCDMA::DisconnectCleanup() { |
| 86 | SLOG(Cellular, 2) << __func__; |
| 87 | // TODO(armansito): Handle activation logic here. |
| 88 | } |
| 89 | |
| 90 | void CellularCapabilityUniversalCDMA::OnServiceCreated() { |
| 91 | SLOG(Cellular, 2) << __func__; |
| 92 | // TODO (armansito): Set storage identifier here based on the superclass |
| 93 | // implementation. |
| 94 | bool activation_required = IsServiceActivationRequired(); |
| 95 | cellular()->service()->SetActivationState( |
| 96 | activation_required ? |
| 97 | flimflam::kActivationStateNotActivated : |
| 98 | flimflam::kActivationStateActivated); |
| 99 | cellular()->service()->SetActivateOverNonCellularNetwork(activation_required); |
| 100 | UpdateServingOperator(); |
| 101 | UpdateOLP(); |
| 102 | } |
| 103 | |
| 104 | void CellularCapabilityUniversalCDMA::UpdateOLP() { |
| 105 | SLOG(Cellular,2) << __func__; |
| 106 | if (!modem_info()->cellular_operator_info()) |
| 107 | return; |
| 108 | |
| 109 | const CellularService::OLP *result = |
| 110 | modem_info()->cellular_operator_info()->GetOLPBySID( |
| 111 | UintToString(sid_)); |
| 112 | if (!result) |
| 113 | return; |
| 114 | |
| 115 | CellularService::OLP olp; |
| 116 | olp.CopyFrom(*result); |
| 117 | string post_data = olp.GetPostData(); |
| 118 | ReplaceSubstringsAfterOffset(&post_data, 0, "${esn}", esn()); |
| 119 | ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}", mdn()); |
| 120 | ReplaceSubstringsAfterOffset(&post_data, 0, "${meid}", meid()); |
| 121 | olp.SetPostData(post_data); |
| 122 | cellular()->service()->SetOLP(olp); |
| 123 | } |
| 124 | |
| 125 | void CellularCapabilityUniversalCDMA::GetProperties() { |
| 126 | SLOG(Cellular, 2) << __func__; |
| 127 | CellularCapabilityUniversal::GetProperties(); |
| 128 | |
| 129 | scoped_ptr<DBusPropertiesProxyInterface> properties_proxy( |
| 130 | proxy_factory()->CreateDBusPropertiesProxy(cellular()->dbus_path(), |
| 131 | cellular()->dbus_owner())); |
| 132 | DBusPropertiesMap properties( |
| 133 | properties_proxy->GetAll(MM_DBUS_INTERFACE_MODEM_MODEMCDMA)); |
| 134 | OnModemCDMAPropertiesChanged(properties, vector<string>()); |
| 135 | } |
| 136 | |
| 137 | string CellularCapabilityUniversalCDMA::CreateFriendlyServiceName() { |
| 138 | SLOG(Cellular, 2) << __func__ << ": " << GetRoamingStateString(); |
| 139 | |
| 140 | if (provider_.GetCode().empty()) { |
| 141 | UpdateOperatorInfo(); |
| 142 | } |
| 143 | |
| 144 | string name = provider_.GetName(); |
| 145 | if (!name.empty()) { |
| 146 | // TODO(armansito): We may need to show the provider name in a |
| 147 | // specific way if roaming. |
| 148 | return name; |
| 149 | } |
| 150 | |
| 151 | string code = provider_.GetCode(); |
| 152 | if (!code.empty()) { |
| 153 | return "cellular_sid_" + code; |
| 154 | } |
| 155 | |
| 156 | return base::StringPrintf("CDMANetwork%u", friendly_service_name_id_cdma_++); |
| 157 | } |
| 158 | |
| 159 | void CellularCapabilityUniversalCDMA::UpdateOperatorInfo() { |
| 160 | SLOG(Cellular, 2) << __func__; |
| 161 | |
| 162 | if (sid_ == 0 || !modem_info()->cellular_operator_info()) { |
| 163 | SLOG(Cellular, 2) << "No provider is currently available."; |
| 164 | provider_.SetCode(""); |
| 165 | return; |
| 166 | } |
| 167 | |
| 168 | string sid = UintToString(sid_); |
| 169 | const CellularOperatorInfo::CellularOperator *provider = |
| 170 | modem_info()->cellular_operator_info()->GetCellularOperatorBySID(sid); |
| 171 | if (!provider) { |
| 172 | SLOG(Cellular, 2) << "CDMA provider with " |
| 173 | << FormattedSID(sid) |
| 174 | << " not found."; |
| 175 | return; |
| 176 | } |
| 177 | |
| 178 | if (!provider->name_list().empty()) { |
| 179 | provider_.SetName(provider->name_list()[0].name); |
| 180 | } |
| 181 | provider_.SetCode(sid); |
| 182 | provider_.SetCountry(provider->country()); |
| 183 | |
| 184 | // TODO(armansito): The CDMA interface only returns information about the |
| 185 | // current serving carrier, so for now both the home provider and the |
| 186 | // serving operator will be the same in case of roaming. We should figure |
| 187 | // out if there is a way to (and whether or not it is necessary to) |
| 188 | // determine if we're roaming. |
| 189 | cellular()->set_home_provider(provider_); |
| 190 | |
| 191 | UpdateServingOperator(); |
| 192 | } |
| 193 | |
| 194 | void CellularCapabilityUniversalCDMA::UpdateServingOperator() { |
| 195 | SLOG(Cellular, 2) << __func__; |
| 196 | if (cellular()->service().get()) { |
| 197 | cellular()->service()->SetServingOperator(cellular()->home_provider()); |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | void CellularCapabilityUniversalCDMA::Register(const ResultCallback &callback) { |
| 202 | // TODO(armansito): Remove once 3GPP is implemented in its own class. |
| 203 | } |
| 204 | |
| 205 | void CellularCapabilityUniversalCDMA::RegisterOnNetwork( |
| 206 | const string &network_id, |
| 207 | Error *error, |
| 208 | const ResultCallback &callback) { |
| 209 | // TODO(armansito): Remove once 3GPP is implemented in its own class. |
| 210 | } |
| 211 | |
| 212 | bool CellularCapabilityUniversalCDMA::IsRegistered() { |
| 213 | return (cdma_1x_registration_state_ == |
| 214 | MM_MODEM_CDMA_REGISTRATION_STATE_HOME || |
| 215 | cdma_1x_registration_state_ == |
| 216 | MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING || |
| 217 | cdma_evdo_registration_state_ == |
| 218 | MM_MODEM_CDMA_REGISTRATION_STATE_HOME || |
| 219 | cdma_evdo_registration_state_ == |
| 220 | MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING); |
| 221 | } |
| 222 | |
| 223 | void CellularCapabilityUniversalCDMA::SetUnregistered(bool /*searching*/) { |
| 224 | cdma_1x_registration_state_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; |
| 225 | cdma_evdo_registration_state_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; |
| 226 | } |
| 227 | |
| 228 | void CellularCapabilityUniversalCDMA::RequirePIN( |
| 229 | const string &pin, bool require, |
| 230 | Error *error, const ResultCallback &callback) { |
| 231 | // TODO(armansito): Remove once 3GPP is implemented in its own class. |
| 232 | } |
| 233 | |
| 234 | void CellularCapabilityUniversalCDMA::EnterPIN( |
| 235 | const string &pin, |
| 236 | Error *error, |
| 237 | const ResultCallback &callback) { |
| 238 | // TODO(armansito): Remove once 3GPP is implemented in its own class. |
| 239 | } |
| 240 | |
| 241 | void CellularCapabilityUniversalCDMA::UnblockPIN( |
| 242 | const string &unblock_code, |
| 243 | const string &pin, |
| 244 | Error *error, |
| 245 | const ResultCallback &callback) { |
| 246 | // TODO(armansito): Remove once 3GPP is implemented in its own class. |
| 247 | } |
| 248 | |
| 249 | void CellularCapabilityUniversalCDMA::ChangePIN( |
| 250 | const string &old_pin, const string &new_pin, |
| 251 | Error *error, const ResultCallback &callback) { |
| 252 | // TODO(armansito): Remove once 3GPP is implemented in its own class. |
| 253 | } |
| 254 | |
| 255 | void CellularCapabilityUniversalCDMA::Scan(Error *error, |
| 256 | const ResultCallback &callback) { |
| 257 | // TODO(armansito): Remove once 3GPP is implemented in its own class. |
| 258 | } |
| 259 | |
| 260 | void CellularCapabilityUniversalCDMA::OnSimPathChanged( |
| 261 | const string &sim_path) { |
| 262 | // TODO(armansito): Remove once 3GPP is implemented in its own class. |
| 263 | } |
| 264 | |
| 265 | string CellularCapabilityUniversalCDMA::GetRoamingStateString() const { |
| 266 | uint32 state = cdma_evdo_registration_state_; |
| 267 | if (state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) { |
| 268 | state = cdma_1x_registration_state_; |
| 269 | } |
| 270 | switch (state) { |
| 271 | case MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN: |
| 272 | case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED: |
| 273 | break; |
| 274 | case MM_MODEM_CDMA_REGISTRATION_STATE_HOME: |
| 275 | return flimflam::kRoamingStateHome; |
| 276 | case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING: |
| 277 | return flimflam::kRoamingStateRoaming; |
| 278 | default: |
| 279 | NOTREACHED(); |
| 280 | } |
| 281 | return flimflam::kRoamingStateUnknown; |
| 282 | } |
| 283 | |
| 284 | void CellularCapabilityUniversalCDMA::OnDBusPropertiesChanged( |
| 285 | const string &interface, |
| 286 | const DBusPropertiesMap &changed_properties, |
| 287 | const vector<string> &invalidated_properties) { |
| 288 | SLOG(Cellular, 2) << __func__ << "(" << interface << ")"; |
| 289 | if (interface == MM_DBUS_INTERFACE_MODEM_MODEMCDMA) { |
| 290 | OnModemCDMAPropertiesChanged(changed_properties, invalidated_properties); |
| 291 | } else { |
| 292 | CellularCapabilityUniversal::OnDBusPropertiesChanged( |
| 293 | interface, changed_properties, invalidated_properties); |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | void CellularCapabilityUniversalCDMA::OnModemCDMAPropertiesChanged( |
| 298 | const DBusPropertiesMap &properties, |
| 299 | const std::vector<std::string> &/*invalidated_properties*/) { |
| 300 | SLOG(Cellular, 2) << __func__; |
| 301 | string str_value; |
| 302 | if (DBusProperties::GetString(properties, |
| 303 | MM_MODEM_MODEMCDMA_PROPERTY_MEID, |
| 304 | &str_value)) |
| 305 | set_meid(str_value); |
| 306 | if (DBusProperties::GetString(properties, |
| 307 | MM_MODEM_MODEMCDMA_PROPERTY_ESN, |
| 308 | &str_value)) |
| 309 | set_esn(str_value); |
| 310 | |
| 311 | uint32_t sid = sid_; |
| 312 | uint32_t nid = nid_; |
| 313 | MMModemCdmaRegistrationState state_1x = cdma_1x_registration_state_; |
| 314 | MMModemCdmaRegistrationState state_evdo = cdma_evdo_registration_state_; |
| 315 | bool registration_changed = false; |
| 316 | uint32_t uint_value; |
| 317 | if (DBusProperties::GetUint32( |
| 318 | properties, |
| 319 | MM_MODEM_MODEMCDMA_PROPERTY_CDMA1XREGISTRATIONSTATE, |
| 320 | &uint_value)) { |
| 321 | state_1x = static_cast<MMModemCdmaRegistrationState>(uint_value); |
| 322 | registration_changed = true; |
| 323 | } |
| 324 | if (DBusProperties::GetUint32( |
| 325 | properties, |
| 326 | MM_MODEM_MODEMCDMA_PROPERTY_EVDOREGISTRATIONSTATE, |
| 327 | &uint_value)) { |
| 328 | state_evdo = static_cast<MMModemCdmaRegistrationState>(uint_value); |
| 329 | registration_changed = true; |
| 330 | } |
| 331 | if (DBusProperties::GetUint32( |
| 332 | properties, |
| 333 | MM_MODEM_MODEMCDMA_PROPERTY_SID, |
| 334 | &uint_value)) { |
| 335 | sid = uint_value; |
| 336 | registration_changed = true; |
| 337 | } |
| 338 | if (DBusProperties::GetUint32( |
| 339 | properties, |
| 340 | MM_MODEM_MODEMCDMA_PROPERTY_NID, |
| 341 | &uint_value)) { |
| 342 | nid = uint_value; |
| 343 | registration_changed = true; |
| 344 | } |
| 345 | if (registration_changed) |
| 346 | OnCDMARegistrationChanged(state_1x, state_evdo, sid, nid); |
| 347 | } |
| 348 | |
| 349 | void CellularCapabilityUniversalCDMA::OnCDMARegistrationChanged( |
| 350 | MMModemCdmaRegistrationState state_1x, |
| 351 | MMModemCdmaRegistrationState state_evdo, |
| 352 | uint32_t sid, uint32_t nid) { |
| 353 | SLOG(Cellular, 2) << __func__ |
| 354 | << ": state_1x=" << state_1x |
| 355 | << ", state_evdo=" << state_evdo; |
| 356 | cdma_1x_registration_state_ = state_1x; |
| 357 | cdma_evdo_registration_state_ = state_evdo; |
| 358 | sid_ = sid; |
| 359 | nid_ = nid; |
| 360 | UpdateOperatorInfo(); |
| 361 | cellular()->HandleNewRegistrationState(); |
| 362 | } |
| 363 | |
| 364 | } // namespace shill |