blob: 135d7a0d46451e29989ae6341dc609e14d1797e3 [file] [log] [blame]
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001// Copyright (c) 2012 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.h"
6
7#include <base/bind.h>
Jason Glasgow82f9ab32012-04-04 14:27:19 -04008#include <base/stl_util.h>
Jason Glasgow82f9ab32012-04-04 14:27:19 -04009#include <base/stringprintf.h>
Ben Chan6d0d1e72012-11-06 21:19:28 -080010#include <base/string_util.h>
Jason Glasgow82f9ab32012-04-04 14:27:19 -040011#include <chromeos/dbus/service_constants.h>
12#include <mobile_provider.h>
Ben Chan5c853ef2012-10-05 00:05:37 -070013#include <ModemManager/ModemManager.h>
Jason Glasgow82f9ab32012-04-04 14:27:19 -040014
15#include <string>
16#include <vector>
17
18#include "shill/adaptor_interfaces.h"
Ben Chan15786032012-11-04 21:28:02 -080019#include "shill/cellular_operator_info.h"
Jason Glasgow82f9ab32012-04-04 14:27:19 -040020#include "shill/cellular_service.h"
Jason Glasgowaf583282012-04-18 15:18:22 -040021#include "shill/dbus_properties_proxy_interface.h"
Jason Glasgow82f9ab32012-04-04 14:27:19 -040022#include "shill/error.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070023#include "shill/logging.h"
Jason Glasgow82f9ab32012-04-04 14:27:19 -040024#include "shill/property_accessor.h"
25#include "shill/proxy_factory.h"
26
27#ifdef MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN
28#error "Do not include mm-modem.h"
29#endif
30
Jason Glasgow82f9ab32012-04-04 14:27:19 -040031using base::Bind;
Jason Glasgowef965562012-04-10 16:12:35 -040032using base::Closure;
Jason Glasgow82f9ab32012-04-04 14:27:19 -040033using std::string;
34using std::vector;
35
36namespace shill {
37
38// static
Jason Glasgow14521872012-05-07 19:12:15 -040039const char CellularCapabilityUniversal::kConnectPin[] = "pin";
40const char CellularCapabilityUniversal::kConnectOperatorId[] = "operator-id";
41const char CellularCapabilityUniversal::kConnectBands[] = "bands";
42const char CellularCapabilityUniversal::kConnectAllowedModes[] =
43 "allowed-modes";
44const char CellularCapabilityUniversal::kConnectPreferredMode[] =
45 "preferred-mode";
46const char CellularCapabilityUniversal::kConnectApn[] = "apn";
47const char CellularCapabilityUniversal::kConnectIPType[] = "ip-type";
48const char CellularCapabilityUniversal::kConnectUser[] = "user";
49const char CellularCapabilityUniversal::kConnectPassword[] = "password";
50const char CellularCapabilityUniversal::kConnectNumber[] = "number";
51const char CellularCapabilityUniversal::kConnectAllowRoaming[] =
52 "allow-roaming";
53const char CellularCapabilityUniversal::kConnectRMProtocol[] = "rm-protocol";
Jason Glasgowcd0349c2012-05-03 23:32:15 -040054const char CellularCapabilityUniversal::kStatusProperty[] = "status";
55const char CellularCapabilityUniversal::kOperatorLongProperty[] =
56 "operator-long";
57const char CellularCapabilityUniversal::kOperatorShortProperty[] =
58 "operator-short";
59const char CellularCapabilityUniversal::kOperatorCodeProperty[] =
60 "operator-code";
61const char CellularCapabilityUniversal::kOperatorAccessTechnologyProperty[] =
62 "access-technology";
Jason Glasgow14521872012-05-07 19:12:15 -040063const char CellularCapabilityUniversal::kE362ModelId[] = "E362 WWAN";
64unsigned int CellularCapabilityUniversal::friendly_service_name_id_ = 0;
65
Jason Glasgow82f9ab32012-04-04 14:27:19 -040066
67static const char kPhoneNumber[] = "*99#";
68
69static string AccessTechnologyToString(uint32 access_technologies) {
70 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_LTE)
71 return flimflam::kNetworkTechnologyLte;
72 if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_EVDO0 |
73 MM_MODEM_ACCESS_TECHNOLOGY_EVDOA |
74 MM_MODEM_ACCESS_TECHNOLOGY_EVDOB))
75 return flimflam::kNetworkTechnologyEvdo;
76 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_1XRTT)
77 return flimflam::kNetworkTechnology1Xrtt;
78 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS)
79 return flimflam::kNetworkTechnologyHspaPlus;
80 if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_HSPA |
81 MM_MODEM_ACCESS_TECHNOLOGY_HSUPA |
82 MM_MODEM_ACCESS_TECHNOLOGY_HSDPA))
83 return flimflam::kNetworkTechnologyHspa;
84 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_UMTS)
85 return flimflam::kNetworkTechnologyUmts;
86 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_EDGE)
87 return flimflam::kNetworkTechnologyEdge;
88 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_GPRS)
89 return flimflam::kNetworkTechnologyGprs;
90 if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT |
91 MM_MODEM_ACCESS_TECHNOLOGY_GSM))
92 return flimflam::kNetworkTechnologyGsm;
93 return "";
94}
95
Jason Glasgow9f09aef2012-05-08 16:26:55 -040096static string AccessTechnologyToTechnologyFamily(uint32 access_technologies) {
97 if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_LTE |
98 MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS |
99 MM_MODEM_ACCESS_TECHNOLOGY_HSPA |
100 MM_MODEM_ACCESS_TECHNOLOGY_HSUPA |
101 MM_MODEM_ACCESS_TECHNOLOGY_HSDPA |
102 MM_MODEM_ACCESS_TECHNOLOGY_UMTS |
103 MM_MODEM_ACCESS_TECHNOLOGY_EDGE |
104 MM_MODEM_ACCESS_TECHNOLOGY_GPRS |
105 MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT |
106 MM_MODEM_ACCESS_TECHNOLOGY_GSM))
107 return flimflam::kTechnologyFamilyGsm;
108 if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_EVDO0 |
Ben Chan6d0d1e72012-11-06 21:19:28 -0800109 MM_MODEM_ACCESS_TECHNOLOGY_EVDOA |
110 MM_MODEM_ACCESS_TECHNOLOGY_EVDOB |
Jason Glasgow9f09aef2012-05-08 16:26:55 -0400111 MM_MODEM_ACCESS_TECHNOLOGY_1XRTT))
112 return flimflam::kTechnologyFamilyCdma;
113 return "";
114}
115
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400116CellularCapabilityUniversal::CellularCapabilityUniversal(
117 Cellular *cellular,
118 ProxyFactory *proxy_factory)
119 : CellularCapability(cellular, proxy_factory),
120 weak_ptr_factory_(this),
121 registration_state_(MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN),
122 cdma_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
Darin Petkove636c692012-05-31 10:22:17 +0200123 capabilities_(MM_MODEM_CAPABILITY_NONE),
124 current_capabilities_(MM_MODEM_CAPABILITY_NONE),
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400125 access_technologies_(MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN),
Jason Glasgowaf583282012-04-18 15:18:22 -0400126 supported_modes_(MM_MODEM_MODE_NONE),
127 allowed_modes_(MM_MODEM_MODE_NONE),
128 preferred_mode_(MM_MODEM_MODE_NONE),
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400129 home_provider_(NULL),
Darin Petkovf508c822012-09-21 13:43:17 +0200130 provider_requires_roaming_(false),
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400131 scanning_supported_(true),
132 scanning_(false),
Ben Chanbd3aee82012-10-16 23:52:04 -0700133 scan_interval_(0),
134 sim_present_(false) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700135 SLOG(Cellular, 2) << "Cellular capability constructed: Universal";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400136 PropertyStore *store = cellular->mutable_store();
137
138 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
139 store->RegisterConstBool(flimflam::kSupportNetworkScanProperty,
140 &scanning_supported_);
141 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
142 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
143 &firmware_revision_);
144 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
145 &hardware_revision_);
146 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
147 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
Ben Chana5e27082012-07-31 14:30:28 -0700148 store->RegisterConstString(flimflam::kIccidProperty, &sim_identifier_);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400149 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
150 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
151 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
152 store->RegisterConstString(flimflam::kMinProperty, &min_);
153 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
154 store->RegisterConstString(flimflam::kSelectedNetworkProperty,
155 &selected_network_);
156 store->RegisterConstStringmaps(flimflam::kFoundNetworksProperty,
157 &found_networks_);
Darin Petkovf508c822012-09-21 13:43:17 +0200158 store->RegisterConstBool(shill::kProviderRequiresRoamingProperty,
159 &provider_requires_roaming_);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400160 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
161 store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
162 HelpRegisterDerivedKeyValueStore(
163 flimflam::kSIMLockStatusProperty,
164 &CellularCapabilityUniversal::SimLockStatusToProperty,
165 NULL);
Ben Chanbd3aee82012-10-16 23:52:04 -0700166 store->RegisterConstBool(shill::kSIMPresentProperty, &sim_present_);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400167 store->RegisterConstStringmaps(flimflam::kCellularApnListProperty,
168 &apn_list_);
169}
170
171KeyValueStore CellularCapabilityUniversal::SimLockStatusToProperty(
172 Error */*error*/) {
173 KeyValueStore status;
174 status.SetBool(flimflam::kSIMLockEnabledProperty, sim_lock_status_.enabled);
175 status.SetString(flimflam::kSIMLockTypeProperty, sim_lock_status_.lock_type);
176 status.SetUint(flimflam::kSIMLockRetriesLeftProperty,
177 sim_lock_status_.retries_left);
178 return status;
179}
180
181void CellularCapabilityUniversal::HelpRegisterDerivedKeyValueStore(
182 const string &name,
183 KeyValueStore(CellularCapabilityUniversal::*get)(Error *error),
184 void(CellularCapabilityUniversal::*set)(
185 const KeyValueStore &value, Error *error)) {
186 cellular()->mutable_store()->RegisterDerivedKeyValueStore(
187 name,
188 KeyValueStoreAccessor(
189 new CustomAccessor<CellularCapabilityUniversal, KeyValueStore>(
190 this, get, set)));
191}
192
193void CellularCapabilityUniversal::InitProxies() {
194 modem_3gpp_proxy_.reset(
195 proxy_factory()->CreateMM1ModemModem3gppProxy(cellular()->dbus_path(),
196 cellular()->dbus_owner()));
197 modem_cdma_proxy_.reset(
198 proxy_factory()->CreateMM1ModemModemCdmaProxy(cellular()->dbus_path(),
199 cellular()->dbus_owner()));
200 modem_proxy_.reset(
201 proxy_factory()->CreateMM1ModemProxy(cellular()->dbus_path(),
202 cellular()->dbus_owner()));
203 modem_simple_proxy_.reset(
204 proxy_factory()->CreateMM1ModemSimpleProxy(cellular()->dbus_path(),
205 cellular()->dbus_owner()));
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400206 modem_proxy_->set_state_changed_callback(
207 Bind(&CellularCapabilityUniversal::OnModemStateChangedSignal,
208 weak_ptr_factory_.GetWeakPtr()));
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400209 // Do not create a SIM proxy until the device is enabled because we
210 // do not yet know the object path of the sim object.
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400211 // TODO(jglasgow): register callbacks
212}
213
214void CellularCapabilityUniversal::StartModem(Error *error,
Jason Glasgowef965562012-04-10 16:12:35 -0400215 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700216 SLOG(Cellular, 2) << __func__;
Jason Glasgowef965562012-04-10 16:12:35 -0400217 InitProxies();
218
Gary Moraine285a842012-08-15 08:23:57 -0700219 // ModemManager must be in the disabled state to accept the Enable command.
220 Cellular::ModemState state =
221 static_cast<Cellular::ModemState>(modem_proxy_->State());
222 if (state == Cellular::kModemStateDisabled) {
223 EnableModem(error, callback);
224 } else if (!cellular()->IsUnderlyingDeviceEnabled()) {
225 SLOG(Cellular, 2) << "Enabling of modem deferred because state is "
226 << state;
227 deferred_enable_modem_callback_ =
228 Bind(&CellularCapabilityUniversal::EnableModem,
229 weak_ptr_factory_.GetWeakPtr(), static_cast<Error *>(NULL),
230 callback);
231 } else {
Arman Uguray403fad42012-09-25 17:08:39 -0700232 // Call GetProperties() here to sync up with the modem state
233 GetProperties();
Gary Moraine285a842012-08-15 08:23:57 -0700234 callback.Run(*error);
235 }
236}
237
238void CellularCapabilityUniversal::EnableModem(Error *error,
239 const ResultCallback &callback) {
240 SLOG(Cellular, 2) << __func__;
Jason Glasgowef965562012-04-10 16:12:35 -0400241 CHECK(!callback.is_null());
Thieu Lee3b36592012-08-30 17:50:26 -0700242 Error local_error(Error::kOperationInitiated);
Jason Glasgowef965562012-04-10 16:12:35 -0400243 modem_proxy_->Enable(
244 true,
Gary Moraine285a842012-08-15 08:23:57 -0700245 &local_error,
Jason Glasgowef965562012-04-10 16:12:35 -0400246 Bind(&CellularCapabilityUniversal::Start_EnableModemCompleted,
247 weak_ptr_factory_.GetWeakPtr(), callback),
248 kTimeoutEnable);
Gary Moraine285a842012-08-15 08:23:57 -0700249 if (local_error.IsFailure()) {
250 SLOG(Cellular, 2) << __func__ << "Call to modem_proxy_->Enable() failed";
251 callback.Run(local_error);
252 }
253 if (error) {
254 error->CopyFrom(local_error);
255 }
Jason Glasgowef965562012-04-10 16:12:35 -0400256}
257
258void CellularCapabilityUniversal::Start_EnableModemCompleted(
259 const ResultCallback &callback, const Error &error) {
Eric Shienbrood9b1bd7b2012-04-20 16:42:26 -0400260 SLOG(Cellular, 2) << __func__ << ": " << error;
Jason Glasgowef965562012-04-10 16:12:35 -0400261 if (error.IsFailure()) {
262 callback.Run(error);
263 return;
264 }
265
266 // After modem is enabled, it should be possible to get properties
267 // TODO(jglasgow): handle errors from GetProperties
268 GetProperties();
Jason Glasgow4380f0d2012-05-03 18:05:04 -0400269 callback.Run(error);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400270}
271
272void CellularCapabilityUniversal::StopModem(Error *error,
Jason Glasgow02401cc2012-05-16 10:35:37 -0400273 const ResultCallback &callback) {
Jason Glasgowef965562012-04-10 16:12:35 -0400274 CHECK(!callback.is_null());
275 CHECK(error);
Thieu Led0012052012-07-25 16:09:09 -0700276 Cellular::ModemState state = cellular()->modem_state();
277 SLOG(Cellular, 2) << __func__ << "(" << state << ")";
Jason Glasgowef965562012-04-10 16:12:35 -0400278
Thieu Led0012052012-07-25 16:09:09 -0700279 if (cellular()->IsModemRegistered()) {
Jason Glasgow02401cc2012-05-16 10:35:37 -0400280 string all_bearers("/"); // "/" means all bearers. See Modemanager docs.
Jason Glasgowef965562012-04-10 16:12:35 -0400281 modem_simple_proxy_->Disconnect(
282 all_bearers,
283 error,
284 Bind(&CellularCapabilityUniversal::Stop_DisconnectCompleted,
285 weak_ptr_factory_.GetWeakPtr(), callback),
Thieu Le049adb52012-11-12 17:14:51 -0800286 kTimeoutDisconnect);
Jason Glasgowef965562012-04-10 16:12:35 -0400287 if (error->IsFailure())
288 callback.Run(*error);
289 } else {
Jason Glasgowef965562012-04-10 16:12:35 -0400290 Closure task = Bind(&CellularCapabilityUniversal::Stop_Disable,
291 weak_ptr_factory_.GetWeakPtr(),
292 callback);
293 cellular()->dispatcher()->PostTask(task);
294 }
Gary Moraine285a842012-08-15 08:23:57 -0700295 deferred_enable_modem_callback_.Reset();
Jason Glasgowef965562012-04-10 16:12:35 -0400296}
297
298void CellularCapabilityUniversal::Stop_DisconnectCompleted(
299 const ResultCallback &callback, const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700300 SLOG(Cellular, 2) << __func__;
Jason Glasgowef965562012-04-10 16:12:35 -0400301
302 LOG_IF(ERROR, error.IsFailure()) << "Disconnect failed. Ignoring.";
303 Stop_Disable(callback);
304}
305
306void CellularCapabilityUniversal::Stop_Disable(const ResultCallback &callback) {
307 Error error;
308 modem_proxy_->Enable(
309 false, &error,
310 Bind(&CellularCapabilityUniversal::Stop_DisableCompleted,
311 weak_ptr_factory_.GetWeakPtr(), callback),
Jason Glasgow02401cc2012-05-16 10:35:37 -0400312 kTimeoutEnable);
Jason Glasgowef965562012-04-10 16:12:35 -0400313 if (error.IsFailure())
314 callback.Run(error);
315}
316
317void CellularCapabilityUniversal::Stop_DisableCompleted(
318 const ResultCallback &callback, const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700319 SLOG(Cellular, 2) << __func__;
Jason Glasgowef965562012-04-10 16:12:35 -0400320
321 if (error.IsSuccess())
322 ReleaseProxies();
323 callback.Run(error);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400324}
325
326void CellularCapabilityUniversal::Connect(const DBusPropertiesMap &properties,
327 Error *error,
328 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700329 SLOG(Cellular, 2) << __func__;
Nathan Williamsb54974f2012-04-19 11:16:30 -0400330 DBusPathCallback cb = Bind(&CellularCapabilityUniversal::OnConnectReply,
331 weak_ptr_factory_.GetWeakPtr(),
332 callback);
333 modem_simple_proxy_->Connect(properties, error, cb, kTimeoutConnect);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400334}
335
336void CellularCapabilityUniversal::Disconnect(Error *error,
337 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700338 SLOG(Cellular, 2) << __func__;
Thieu Le5d6864a2012-07-20 11:43:51 -0700339 if (bearer_path_.empty()) {
340 LOG(WARNING) << "In " << __func__ << "(): "
341 << "Ignoring attempt to disconnect without bearer";
Thieu Le3d275392012-07-20 15:32:58 -0700342 } else if (modem_simple_proxy_.get()) {
Thieu Le5d6864a2012-07-20 11:43:51 -0700343 modem_simple_proxy_->Disconnect(bearer_path_,
344 error,
345 callback,
Thieu Le049adb52012-11-12 17:14:51 -0800346 kTimeoutDisconnect);
Thieu Le5d6864a2012-07-20 11:43:51 -0700347 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400348}
349
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400350void CellularCapabilityUniversal::Activate(const string &carrier,
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400351 Error *error,
352 const ResultCallback &callback) {
353 OnUnsupportedOperation(__func__, error);
354}
355
356void CellularCapabilityUniversal::ReleaseProxies() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700357 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400358 modem_3gpp_proxy_.reset();
359 modem_cdma_proxy_.reset();
360 modem_proxy_.reset();
361 modem_simple_proxy_.reset();
362 sim_proxy_.reset();
363}
364
365void CellularCapabilityUniversal::OnServiceCreated() {
366 // If IMSI is available, base the service's storage identifier on it.
367 if (!imsi_.empty()) {
368 cellular()->service()->SetStorageIdentifier(
369 string(flimflam::kTypeCellular) + "_" +
370 cellular()->address() + "_" + imsi_);
371 }
372 cellular()->service()->SetActivationState(
Ben Chan15786032012-11-04 21:28:02 -0800373 IsServiceActivationRequired() ?
374 flimflam::kActivationStateNotActivated :
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400375 flimflam::kActivationStateActivated);
376 UpdateServingOperator();
Ben Chan6d0d1e72012-11-06 21:19:28 -0800377 UpdateOLP();
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400378}
379
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400380// Create the list of APNs to try, in the following order:
381// - last APN that resulted in a successful connection attempt on the
382// current network (if any)
383// - the APN, if any, that was set by the user
384// - the list of APNs found in the mobile broadband provider DB for the
385// home provider associated with the current SIM
386// - as a last resort, attempt to connect with no APN
387void CellularCapabilityUniversal::SetupApnTryList() {
388 apn_try_list_.clear();
389
390 DCHECK(cellular()->service().get());
391 const Stringmap *apn_info = cellular()->service()->GetLastGoodApn();
392 if (apn_info)
393 apn_try_list_.push_back(*apn_info);
394
395 apn_info = cellular()->service()->GetUserSpecifiedApn();
396 if (apn_info)
397 apn_try_list_.push_back(*apn_info);
398
399 apn_try_list_.insert(apn_try_list_.end(), apn_list_.begin(), apn_list_.end());
400}
401
402void CellularCapabilityUniversal::SetupConnectProperties(
403 DBusPropertiesMap *properties) {
404 SetupApnTryList();
405 FillConnectPropertyMap(properties);
406}
407
408void CellularCapabilityUniversal::FillConnectPropertyMap(
409 DBusPropertiesMap *properties) {
410
411 // TODO(jglasgow): Is this really needed anymore?
Jason Glasgow14521872012-05-07 19:12:15 -0400412 (*properties)[kConnectNumber].writer().append_string(
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400413 kPhoneNumber);
414
Jason Glasgow14521872012-05-07 19:12:15 -0400415 (*properties)[kConnectAllowRoaming].writer().append_bool(
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400416 AllowRoaming());
417
418 if (!apn_try_list_.empty()) {
419 // Leave the APN at the front of the list, so that it can be recorded
420 // if the connect attempt succeeds.
421 Stringmap apn_info = apn_try_list_.front();
Ben Chanfad4a0b2012-04-18 15:49:59 -0700422 SLOG(Cellular, 2) << __func__ << ": Using APN "
423 << apn_info[flimflam::kApnProperty];
Jason Glasgow14521872012-05-07 19:12:15 -0400424 (*properties)[kConnectApn].writer().append_string(
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400425 apn_info[flimflam::kApnProperty].c_str());
426 if (ContainsKey(apn_info, flimflam::kApnUsernameProperty))
Jason Glasgow14521872012-05-07 19:12:15 -0400427 (*properties)[kConnectUser].writer().append_string(
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400428 apn_info[flimflam::kApnUsernameProperty].c_str());
429 if (ContainsKey(apn_info, flimflam::kApnPasswordProperty))
Jason Glasgow14521872012-05-07 19:12:15 -0400430 (*properties)[kConnectPassword].writer().append_string(
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400431 apn_info[flimflam::kApnPasswordProperty].c_str());
432 }
433}
434
435void CellularCapabilityUniversal::OnConnectReply(const ResultCallback &callback,
Nathan Williamsb54974f2012-04-19 11:16:30 -0400436 const DBus::Path &path,
437 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700438 SLOG(Cellular, 2) << __func__ << "(" << error << ")";
Nathan Williamsb54974f2012-04-19 11:16:30 -0400439
Jason Glasgow7234ec32012-05-23 16:01:21 -0400440 CellularServiceRefPtr service = cellular()->service();
441 if (!service) {
442 // The service could have been deleted before our Connect() request
443 // completes if the modem was enabled and then quickly disabled.
444 apn_try_list_.clear();
445 } else if (error.IsFailure()) {
446 service->ClearLastGoodApn();
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400447 // The APN that was just tried (and failed) is still at the
448 // front of the list, about to be removed. If the list is empty
449 // after that, try one last time without an APN. This may succeed
450 // with some modems in some cases.
Jason Glasgow14521872012-05-07 19:12:15 -0400451 if (RetriableConnectError(error) && !apn_try_list_.empty()) {
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400452 apn_try_list_.pop_front();
Ben Chanfad4a0b2012-04-18 15:49:59 -0700453 SLOG(Cellular, 2) << "Connect failed with invalid APN, "
454 << apn_try_list_.size() << " remaining APNs to try";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400455 DBusPropertiesMap props;
456 FillConnectPropertyMap(&props);
457 Error error;
458 Connect(props, &error, callback);
459 return;
460 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400461 } else {
462 if (!apn_try_list_.empty()) {
Jason Glasgow7234ec32012-05-23 16:01:21 -0400463 service->SetLastGoodApn(apn_try_list_.front());
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400464 apn_try_list_.clear();
465 }
Nathan Williamsb54974f2012-04-19 11:16:30 -0400466 bearer_path_ = path;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400467 }
468
469 if (!callback.is_null())
470 callback.Run(error);
471}
472
473bool CellularCapabilityUniversal::AllowRoaming() {
Darin Petkovf508c822012-09-21 13:43:17 +0200474 return provider_requires_roaming_ || allow_roaming_property();
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400475}
476
Jason Glasgowef965562012-04-10 16:12:35 -0400477void CellularCapabilityUniversal::GetProperties() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700478 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400479
Jason Glasgowaf583282012-04-18 15:18:22 -0400480 scoped_ptr<DBusPropertiesProxyInterface> properties_proxy(
481 proxy_factory()->CreateDBusPropertiesProxy(cellular()->dbus_path(),
482 cellular()->dbus_owner()));
483 DBusPropertiesMap properties(
484 properties_proxy->GetAll(MM_DBUS_INTERFACE_MODEM));
485 OnModemPropertiesChanged(properties, vector<string>());
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400486
Jason Glasgowaf583282012-04-18 15:18:22 -0400487 properties = properties_proxy->GetAll(MM_DBUS_INTERFACE_MODEM_MODEM3GPP);
488 OnModem3GPPPropertiesChanged(properties, vector<string>());
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400489}
490
491string CellularCapabilityUniversal::CreateFriendlyServiceName() {
Darin Petkova4ca3c32012-08-17 16:05:24 +0200492 SLOG(Cellular, 2) << __func__ << ": " << GetRoamingStateString();
Ben Chan092b12b2012-11-07 22:04:05 -0800493
494 // If |serving_operator_| does not have an operator ID, call
495 // UpdateOperatorInfo() to use |operator_id_| as a fallback when appropriate.
496 if (serving_operator_.GetCode().empty()) {
497 UpdateOperatorInfo();
498 }
499
Darin Petkova4ca3c32012-08-17 16:05:24 +0200500 string name = serving_operator_.GetName();
501 string home_provider_name = cellular()->home_provider().GetName();
502 if (!name.empty()) {
503 // If roaming, try to show "<home-provider> | <serving-operator>", per 3GPP
504 // rules (TS 31.102 and annex A of 122.101).
505 if (registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING &&
506 !home_provider_name.empty()) {
507 return home_provider_name + " | " + name;
508 }
509 return name;
510 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400511 if (registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_HOME &&
Darin Petkova4ca3c32012-08-17 16:05:24 +0200512 !home_provider_name.empty()) {
513 return home_provider_name;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400514 }
Darin Petkova4ca3c32012-08-17 16:05:24 +0200515 string serving_operator_code = serving_operator_.GetCode();
516 if (!serving_operator_code.empty()) {
517 return "cellular_" + serving_operator_code;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400518 }
519 return base::StringPrintf("GSMNetwork%u", friendly_service_name_id_++);
520}
521
522void CellularCapabilityUniversal::SetHomeProvider() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700523 SLOG(Cellular, 2) << __func__ << "(IMSI: " << imsi_
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400524 << " SPN: " << spn_ << ")";
525 // TODO(petkov): The test for NULL provider_db should be done by
526 // mobile_provider_lookup_best_match.
527 if (imsi_.empty() || !cellular()->provider_db()) {
528 return;
529 }
530 mobile_provider *provider =
531 mobile_provider_lookup_best_match(
532 cellular()->provider_db(), spn_.c_str(), imsi_.c_str());
533 if (!provider) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700534 SLOG(Cellular, 2) << "GSM provider not found.";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400535 return;
536 }
Jason Glasgow4380f0d2012-05-03 18:05:04 -0400537
538 // Even if provider is the same as home_provider_, it is possible
539 // that the spn_ has changed. Run all the code below.
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400540 home_provider_ = provider;
Darin Petkovf508c822012-09-21 13:43:17 +0200541 provider_requires_roaming_ = home_provider_->requires_roaming;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400542 Cellular::Operator oper;
Darin Petkovb4fccd22012-08-10 11:59:26 +0200543 if (provider->networks && provider->networks[0]) {
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400544 oper.SetCode(provider->networks[0]);
545 }
546 if (provider->country) {
547 oper.SetCountry(provider->country);
548 }
549 if (spn_.empty()) {
550 const char *name = mobile_provider_get_name(provider);
551 if (name) {
552 oper.SetName(name);
553 }
554 } else {
555 oper.SetName(spn_);
556 }
557 cellular()->set_home_provider(oper);
Darin Petkova4ca3c32012-08-17 16:05:24 +0200558 SLOG(Cellular, 2) << "Home provider: " << oper.GetCode() << ", "
Darin Petkovf508c822012-09-21 13:43:17 +0200559 << oper.GetName() << ", " << oper.GetCountry()
560 << (provider_requires_roaming_ ? ", roaming required" : "");
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400561 InitAPNList();
562}
563
Ben Chan6d0d1e72012-11-06 21:19:28 -0800564void CellularCapabilityUniversal::UpdateOLP() {
565 if (!cellular()->cellular_operator_info())
566 return;
567
568 CellularService::OLP olp;
569 if (!cellular()->cellular_operator_info()->GetOLP(operator_id_, &olp))
570 return;
571
572 string post_data = olp.GetPostData();
573 ReplaceSubstringsAfterOffset(&post_data, 0, "${esn}", esn_);
574 ReplaceSubstringsAfterOffset(&post_data, 0, "${iccid}", sim_identifier_);
575 ReplaceSubstringsAfterOffset(&post_data, 0, "${imei}", imei_);
576 ReplaceSubstringsAfterOffset(&post_data, 0, "${imsi}", imsi_);
577 ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}", mdn_);
578 ReplaceSubstringsAfterOffset(&post_data, 0, "${meid}", meid_);
579 ReplaceSubstringsAfterOffset(&post_data, 0, "${min}", min_);
580 olp.SetPostData(post_data);
581 cellular()->service()->SetOLP(olp);
582}
583
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400584void CellularCapabilityUniversal::UpdateOperatorInfo() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700585 SLOG(Cellular, 2) << __func__;
Ben Chan092b12b2012-11-07 22:04:05 -0800586
587 // If service activation is required, |serving_operator_| may not have an
588 // operator ID. Use |operator_id_| as a fallback when available.
589 // |operator_id_| is retrieved from the SIM card.
590 if (IsServiceActivationRequired() && serving_operator_.GetCode().empty() &&
591 !operator_id_.empty()) {
592 SLOG(Cellular, 2) << "Assuming operator '" << operator_id_
593 << "' as serving operator.";
594 serving_operator_.SetCode(operator_id_);
595 }
596
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400597 const string &network_id = serving_operator_.GetCode();
598 if (!network_id.empty()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700599 SLOG(Cellular, 2) << "Looking up network id: " << network_id;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400600 mobile_provider *provider =
601 mobile_provider_lookup_by_network(cellular()->provider_db(),
602 network_id.c_str());
603 if (provider) {
Darin Petkova4ca3c32012-08-17 16:05:24 +0200604 if (serving_operator_.GetName().empty()) {
605 const char *provider_name = mobile_provider_get_name(provider);
606 if (provider_name && *provider_name) {
607 serving_operator_.SetName(provider_name);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400608 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400609 }
Darin Petkova4ca3c32012-08-17 16:05:24 +0200610 if (provider->country && *provider->country) {
611 serving_operator_.SetCountry(provider->country);
612 }
613 SLOG(Cellular, 2) << "Operator name: " << serving_operator_.GetName()
614 << ", country: " << serving_operator_.GetCountry();
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400615 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700616 SLOG(Cellular, 2) << "GSM provider not found.";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400617 }
618 }
619 UpdateServingOperator();
620}
621
622void CellularCapabilityUniversal::UpdateServingOperator() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700623 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400624 if (cellular()->service().get()) {
625 cellular()->service()->SetServingOperator(serving_operator_);
626 }
627}
628
629void CellularCapabilityUniversal::InitAPNList() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700630 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400631 if (!home_provider_) {
632 return;
633 }
634 apn_list_.clear();
635 for (int i = 0; i < home_provider_->num_apns; ++i) {
636 Stringmap props;
637 mobile_apn *apn = home_provider_->apns[i];
638 if (apn->value) {
639 props[flimflam::kApnProperty] = apn->value;
640 }
641 if (apn->username) {
642 props[flimflam::kApnUsernameProperty] = apn->username;
643 }
644 if (apn->password) {
645 props[flimflam::kApnPasswordProperty] = apn->password;
646 }
647 // Find the first localized and non-localized name, if any.
648 const localized_name *lname = NULL;
649 const localized_name *name = NULL;
650 for (int j = 0; j < apn->num_names; ++j) {
651 if (apn->names[j]->lang) {
652 if (!lname) {
653 lname = apn->names[j];
654 }
655 } else if (!name) {
656 name = apn->names[j];
657 }
658 }
659 if (name) {
660 props[flimflam::kApnNameProperty] = name->name;
661 }
662 if (lname) {
663 props[flimflam::kApnLocalizedNameProperty] = lname->name;
664 props[flimflam::kApnLanguageProperty] = lname->lang;
665 }
666 apn_list_.push_back(props);
667 }
Darin Petkovdb6083f2012-08-16 12:50:23 +0200668 if (cellular()->adaptor()) {
669 cellular()->adaptor()->EmitStringmapsChanged(
670 flimflam::kCellularApnListProperty, apn_list_);
671 } else {
672 LOG(ERROR) << "Null RPC service adaptor.";
673 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400674}
675
Ben Chan15786032012-11-04 21:28:02 -0800676bool CellularCapabilityUniversal::IsServiceActivationRequired() const {
677 // If there is no online payment portal information, it's safer to assume
678 // the service does not require activation.
679 if (!cellular()->cellular_operator_info())
680 return false;
681
682 CellularService::OLP olp;
683 if (!cellular()->cellular_operator_info()->GetOLP(operator_id_, &olp))
684 return false;
685
686 // To avoid false positives, it's safer to assume the service does not
687 // require activation if MDN is not set.
688 if (mdn_.empty())
689 return false;
690
691 // If MDN contains only zeros ('+' and '-' characters are ignored),
692 // the service requires activation.
693 for (size_t i = 0; i < mdn_.size(); ++i) {
694 if (mdn_[i] != '0' && mdn_[i] != '-' && mdn_[i] != '+')
695 return false;
696 }
697 return true;
698}
699
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400700// always called from an async context
701void CellularCapabilityUniversal::Register(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700702 SLOG(Cellular, 2) << __func__ << " \"" << selected_network_ << "\"";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400703 CHECK(!callback.is_null());
704 Error error;
705 ResultCallback cb = Bind(&CellularCapabilityUniversal::OnRegisterReply,
706 weak_ptr_factory_.GetWeakPtr(), callback);
707 modem_3gpp_proxy_->Register(selected_network_, &error, cb, kTimeoutRegister);
708 if (error.IsFailure())
709 callback.Run(error);
710}
711
712void CellularCapabilityUniversal::RegisterOnNetwork(
713 const string &network_id,
714 Error *error,
715 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700716 SLOG(Cellular, 2) << __func__ << "(" << network_id << ")";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400717 CHECK(error);
718 desired_network_ = network_id;
719 ResultCallback cb = Bind(&CellularCapabilityUniversal::OnRegisterReply,
720 weak_ptr_factory_.GetWeakPtr(), callback);
721 modem_3gpp_proxy_->Register(network_id, error, cb, kTimeoutRegister);
722}
723
724void CellularCapabilityUniversal::OnRegisterReply(
725 const ResultCallback &callback,
726 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700727 SLOG(Cellular, 2) << __func__ << "(" << error << ")";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400728
729 if (error.IsSuccess()) {
730 selected_network_ = desired_network_;
731 desired_network_.clear();
732 callback.Run(error);
733 return;
734 }
735 // If registration on the desired network failed,
736 // try to register on the home network.
737 if (!desired_network_.empty()) {
738 desired_network_.clear();
739 selected_network_.clear();
740 LOG(INFO) << "Couldn't register on selected network, trying home network";
741 Register(callback);
742 return;
743 }
744 callback.Run(error);
745}
746
747bool CellularCapabilityUniversal::IsRegistered() {
748 return (registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
749 registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING);
750}
751
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400752void CellularCapabilityUniversal::SetUnregistered(bool searching) {
753 // If we're already in some non-registered state, don't override that
754 if (registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
755 registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
756 registration_state_ =
757 (searching ? MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING :
758 MM_MODEM_3GPP_REGISTRATION_STATE_IDLE);
759 }
760}
761
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400762void CellularCapabilityUniversal::RequirePIN(
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400763 const string &pin, bool require,
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400764 Error *error, const ResultCallback &callback) {
765 CHECK(error);
766 sim_proxy_->EnablePin(pin, require, error, callback, kTimeoutDefault);
767}
768
769void CellularCapabilityUniversal::EnterPIN(const string &pin,
770 Error *error,
771 const ResultCallback &callback) {
772 CHECK(error);
773 sim_proxy_->SendPin(pin, error, callback, kTimeoutDefault);
774}
775
776void CellularCapabilityUniversal::UnblockPIN(const string &unblock_code,
777 const string &pin,
778 Error *error,
779 const ResultCallback &callback) {
780 CHECK(error);
781 sim_proxy_->SendPuk(unblock_code, pin, error, callback, kTimeoutDefault);
782}
783
784void CellularCapabilityUniversal::ChangePIN(
785 const string &old_pin, const string &new_pin,
786 Error *error, const ResultCallback &callback) {
787 CHECK(error);
788 sim_proxy_->ChangePin(old_pin, new_pin, error, callback, kTimeoutDefault);
789}
790
791void CellularCapabilityUniversal::Scan(Error *error,
792 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700793 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400794 CHECK(error);
Jason Glasgowcd0349c2012-05-03 23:32:15 -0400795 if (scanning_) {
796 Error::PopulateAndLog(error, Error::kInProgress, "Already scanning");
797 return;
798 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400799 DBusPropertyMapsCallback cb = Bind(&CellularCapabilityUniversal::OnScanReply,
800 weak_ptr_factory_.GetWeakPtr(), callback);
801 modem_3gpp_proxy_->Scan(error, cb, kTimeoutScan);
Jason Glasgowcd0349c2012-05-03 23:32:15 -0400802 if (!error->IsFailure()) {
803 scanning_ = true;
804 cellular()->adaptor()->EmitBoolChanged(flimflam::kScanningProperty,
805 scanning_);
806 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400807}
808
809void CellularCapabilityUniversal::OnScanReply(const ResultCallback &callback,
810 const ScanResults &results,
811 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700812 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400813
814 // Error handling is weak. The current expectation is that on any
815 // error, found_networks_ should be cleared and a property change
816 // notification sent out.
817 //
818 // TODO(jglasgow): fix error handling
Jason Glasgowcd0349c2012-05-03 23:32:15 -0400819 scanning_ = false;
820 cellular()->adaptor()->EmitBoolChanged(flimflam::kScanningProperty,
821 scanning_);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400822 found_networks_.clear();
823 if (!error.IsFailure()) {
824 for (ScanResults::const_iterator it = results.begin();
825 it != results.end(); ++it) {
826 found_networks_.push_back(ParseScanResult(*it));
827 }
828 }
829 cellular()->adaptor()->EmitStringmapsChanged(flimflam::kFoundNetworksProperty,
830 found_networks_);
Gary Morainceba6aa2012-05-03 10:28:26 -0700831
832 // TODO(gmorain): This check for is_null() is a work-around because
833 // Cellular::Scan() passes a null callback. Instead: 1. Have Cellular::Scan()
834 // pass in a callback. 2. Have Cellular "own" the found_networks_ property
835 // 3. Have Cellular EmitStingMapsChanged() 4. Share the code between GSM and
836 // Universal.
837 if (!callback.is_null())
838 callback.Run(error);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400839}
840
841Stringmap CellularCapabilityUniversal::ParseScanResult(
842 const ScanResult &result) {
843
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400844 /* ScanResults contain the following keys:
845
846 "status"
847 A MMModem3gppNetworkAvailability value representing network
848 availability status, given as an unsigned integer (signature "u").
849 This key will always be present.
850
851 "operator-long"
852 Long-format name of operator, given as a string value (signature
853 "s"). If the name is unknown, this field should not be present.
854
855 "operator-short"
856 Short-format name of operator, given as a string value
857 (signature "s"). If the name is unknown, this field should not
858 be present.
859
860 "operator-code"
861 Mobile code of the operator, given as a string value (signature
862 "s"). Returned in the format "MCCMNC", where MCC is the
863 three-digit ITU E.212 Mobile Country Code and MNC is the two- or
864 three-digit GSM Mobile Network Code. e.g. "31026" or "310260".
865
866 "access-technology"
867 A MMModemAccessTechnology value representing the generic access
868 technology used by this mobile network, given as an unsigned
869 integer (signature "u").
870 */
871 Stringmap parsed;
872
873 uint32 status;
874 if (DBusProperties::GetUint32(result, kStatusProperty, &status)) {
875 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
876 static const char * const kStatusString[] = {
877 "unknown", // MM_MODEM_3GPP_NETWORK_AVAILABILITY_UNKNOWN
878 "available", // MM_MODEM_3GPP_NETWORK_AVAILABILITY_AVAILABLE
879 "current", // MM_MODEM_3GPP_NETWORK_AVAILABILITY_CURRENT
880 "forbidden", // MM_MODEM_3GPP_NETWORK_AVAILABILITY_FORBIDDEN
881 };
882 parsed[flimflam::kStatusProperty] = kStatusString[status];
883 }
884
885 uint32 tech; // MMModemAccessTechnology
886 if (DBusProperties::GetUint32(result, kOperatorAccessTechnologyProperty,
887 &tech)) {
888 parsed[flimflam::kTechnologyProperty] = AccessTechnologyToString(tech);
889 }
890
891 string operator_long, operator_short, operator_code;
892 if (DBusProperties::GetString(result, kOperatorLongProperty, &operator_long))
893 parsed[flimflam::kLongNameProperty] = operator_long;
894 if (DBusProperties::GetString(result, kOperatorShortProperty,
895 &operator_short))
896 parsed[flimflam::kShortNameProperty] = operator_short;
897 if (DBusProperties::GetString(result, kOperatorCodeProperty, &operator_code))
898 parsed[flimflam::kNetworkIdProperty] = operator_code;
899
900 // If the long name is not available but the network ID is, look up the long
901 // name in the mobile provider database.
902 if ((!ContainsKey(parsed, flimflam::kLongNameProperty) ||
903 parsed[flimflam::kLongNameProperty].empty()) &&
904 ContainsKey(parsed, flimflam::kNetworkIdProperty)) {
905 mobile_provider *provider =
906 mobile_provider_lookup_by_network(
907 cellular()->provider_db(),
908 parsed[flimflam::kNetworkIdProperty].c_str());
909 if (provider) {
910 const char *long_name = mobile_provider_get_name(provider);
911 if (long_name && *long_name) {
912 parsed[flimflam::kLongNameProperty] = long_name;
913 }
914 }
915 }
916 return parsed;
917}
918
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400919string CellularCapabilityUniversal::GetNetworkTechnologyString() const {
Jason Glasgow9f09aef2012-05-08 16:26:55 -0400920 // Order is important. Return the highest speed technology
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400921 // TODO(jglasgow): change shill interfaces to a capability model
922
923 return AccessTechnologyToString(access_technologies_);
924}
925
926string CellularCapabilityUniversal::GetRoamingStateString() const {
927 switch (registration_state_) {
928 case MM_MODEM_3GPP_REGISTRATION_STATE_HOME:
929 return flimflam::kRoamingStateHome;
930 case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING:
931 return flimflam::kRoamingStateRoaming;
932 default:
933 break;
934 }
935 return flimflam::kRoamingStateUnknown;
936}
937
938void CellularCapabilityUniversal::GetSignalQuality() {
Nathan Williams218cbcd2012-04-17 16:48:44 -0400939 // TODO(njw): Switch to asynchronous calls (crosbug.com/17583).
940 const DBus::Struct<unsigned int, bool> quality =
941 modem_proxy_->SignalQuality();
942 OnSignalQualityChanged(quality._1);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400943}
944
Jason Glasgow9f09aef2012-05-08 16:26:55 -0400945string CellularCapabilityUniversal::GetTypeString() const {
946 return AccessTechnologyToTechnologyFamily(access_technologies_);
947}
948
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400949void CellularCapabilityUniversal::OnModemPropertiesChanged(
950 const DBusPropertiesMap &properties,
951 const vector<string> &/* invalidated_properties */) {
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400952 // This solves a bootstrapping problem: If the modem is not yet
953 // enabled, there are no proxy objects associated with the capability
954 // object, so modem signals like StateChanged aren't seen. By monitoring
955 // changes to the State property via the ModemManager, we're able to
956 // get the initialization process started, which will result in the
957 // creation of the proxy objects.
958 //
959 // The first time we see the change to State (when the modem state
960 // is Unknown), we simply update the state, and rely on the Manager to
961 // enable the device when it is registered with the Manager. On subsequent
962 // changes to State, we need to explicitly enable the device ourselves.
963 int32 istate;
Jason Glasgowaf583282012-04-18 15:18:22 -0400964 if (DBusProperties::GetInt32(properties, MM_MODEM_PROPERTY_STATE, &istate)) {
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400965 Cellular::ModemState state = static_cast<Cellular::ModemState>(istate);
Jason Glasgowaf583282012-04-18 15:18:22 -0400966 OnModemStateChanged(state);
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400967 }
Jason Glasgowaf583282012-04-18 15:18:22 -0400968 string string_value;
Nathan Williamse9840802012-04-18 18:47:40 -0400969 if (DBusProperties::GetObjectPath(properties,
Jason Glasgowaf583282012-04-18 15:18:22 -0400970 MM_MODEM_PROPERTY_SIM, &string_value))
971 OnSimPathChanged(string_value);
972 uint32 uint_value;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400973 if (DBusProperties::GetUint32(properties,
Jason Glasgowaf583282012-04-18 15:18:22 -0400974 MM_MODEM_PROPERTY_MODEMCAPABILITIES,
975 &uint_value))
976 OnModemCapabilitesChanged(uint_value);
977 if (DBusProperties::GetUint32(properties,
978 MM_MODEM_PROPERTY_CURRENTCAPABILITIES,
979 &uint_value))
980 OnModemCurrentCapabilitiesChanged(uint_value);
981 // not needed: MM_MODEM_PROPERTY_MAXBEARERS
982 // not needed: MM_MODEM_PROPERTY_MAXACTIVEBEARERS
983 if (DBusProperties::GetString(properties,
984 MM_MODEM_PROPERTY_MANUFACTURER,
985 &string_value))
986 OnModemManufacturerChanged(string_value);
987 if (DBusProperties::GetString(properties,
988 MM_MODEM_PROPERTY_MODEL,
989 &string_value))
990 OnModemModelChanged(string_value);
991 if (DBusProperties::GetString(properties,
992 MM_MODEM_PROPERTY_REVISION,
993 &string_value))
994 OnModemRevisionChanged(string_value);
995 // not needed: MM_MODEM_PROPERTY_DEVICEIDENTIFIER
996 // not needed: MM_MODEM_PROPERTY_DEVICE
997 // not needed: MM_MODEM_PROPERTY_DRIVER
998 // not needed: MM_MODEM_PROPERTY_PLUGIN
999 // not needed: MM_MODEM_PROPERTY_EQUIPMENTIDENTIFIER
Nathan Williams218cbcd2012-04-17 16:48:44 -04001000
Jason Glasgowaf583282012-04-18 15:18:22 -04001001 // Unlock required and SimLock
1002 bool locks_changed = false;
1003 uint32_t unlock_required; // This is really of type MMModemLock
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001004 if (DBusProperties::GetUint32(properties,
1005 MM_MODEM_PROPERTY_UNLOCKREQUIRED,
Jason Glasgowaf583282012-04-18 15:18:22 -04001006 &unlock_required)) {
1007 locks_changed = true;
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001008 }
Jason Glasgowaf583282012-04-18 15:18:22 -04001009 LockRetryData lock_retries;
1010 DBusPropertiesMap::const_iterator it =
1011 properties.find(MM_MODEM_PROPERTY_UNLOCKRETRIES);
1012 if (it != properties.end()) {
1013 lock_retries = it->second;
1014 locks_changed = true;
1015 }
1016 if (locks_changed)
1017 OnLockRetriesChanged(static_cast<MMModemLock>(unlock_required),
1018 lock_retries);
1019 if (DBusProperties::GetUint32(properties,
1020 MM_MODEM_PROPERTY_ACCESSTECHNOLOGIES,
1021 &uint_value))
1022 OnAccessTechnologiesChanged(uint_value);
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001023
Jason Glasgowaf583282012-04-18 15:18:22 -04001024 it = properties.find(MM_MODEM_PROPERTY_SIGNALQUALITY);
1025 if (it != properties.end()) {
1026 DBus::Struct<unsigned int, bool> quality = it->second;
1027 OnSignalQualityChanged(quality._1);
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001028 }
Jason Glasgowaf583282012-04-18 15:18:22 -04001029 vector<string> numbers;
1030 if (DBusProperties::GetStrings(properties, MM_MODEM_PROPERTY_OWNNUMBERS,
1031 &numbers)) {
1032 string mdn;
1033 if (numbers.size() > 0)
1034 mdn = numbers[0];
1035 OnMdnChanged(mdn);
1036 }
1037 if (DBusProperties::GetUint32(properties, MM_MODEM_PROPERTY_SUPPORTEDMODES,
1038 &uint_value))
1039 OnSupportedModesChanged(uint_value);
1040 if (DBusProperties::GetUint32(properties, MM_MODEM_PROPERTY_ALLOWEDMODES,
1041 &uint_value))
1042 OnAllowedModesChanged(uint_value);
1043 if (DBusProperties::GetUint32(properties, MM_MODEM_PROPERTY_PREFERREDMODE,
1044 &uint_value))
1045 OnPreferredModeChanged(static_cast<MMModemMode>(uint_value));
1046 // au: MM_MODEM_PROPERTY_SUPPORTEDBANDS,
1047 // au: MM_MODEM_PROPERTY_BANDS
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001048}
1049
1050void CellularCapabilityUniversal::OnDBusPropertiesChanged(
1051 const string &interface,
1052 const DBusPropertiesMap &changed_properties,
Jason Glasgow4c0724a2012-04-17 15:47:40 -04001053 const vector<string> &invalidated_properties) {
Jason Glasgow7234ec32012-05-23 16:01:21 -04001054 SLOG(Cellular, 2) << __func__ << "(" << interface << ")";
Jason Glasgowef965562012-04-10 16:12:35 -04001055 if (interface == MM_DBUS_INTERFACE_MODEM) {
Jason Glasgow4c0724a2012-04-17 15:47:40 -04001056 OnModemPropertiesChanged(changed_properties, invalidated_properties);
Jason Glasgowef965562012-04-10 16:12:35 -04001057 }
Jason Glasgowaf583282012-04-18 15:18:22 -04001058 if (interface == MM_DBUS_INTERFACE_MODEM_MODEM3GPP) {
1059 OnModem3GPPPropertiesChanged(changed_properties, invalidated_properties);
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001060 }
Jason Glasgowaf583282012-04-18 15:18:22 -04001061 if (interface == MM_DBUS_INTERFACE_SIM) {
1062 OnSimPropertiesChanged(changed_properties, invalidated_properties);
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001063 }
1064}
1065
Jason Glasgow14521872012-05-07 19:12:15 -04001066bool CellularCapabilityUniversal::RetriableConnectError(
1067 const Error &error) const {
1068 if (error.type() == Error::kInvalidApn)
1069 return true;
1070
1071 // modemmanager does not ever return kInvalidApn for E362 modems
1072 // with 1.41 firmware. It remains to be seem if this will change
1073 // with 3.x firmware.
1074 if ((model_id_ == kE362ModelId) && (error.type() == Error::kOperationFailed))
1075 return true;
1076
1077 return false;
1078}
1079
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001080void CellularCapabilityUniversal::OnNetworkModeSignal(uint32 /*mode*/) {
1081 // TODO(petkov): Implement this.
1082 NOTIMPLEMENTED();
1083}
1084
Jason Glasgowaf583282012-04-18 15:18:22 -04001085void CellularCapabilityUniversal::OnSimPathChanged(
1086 const string &sim_path) {
1087 if (sim_path == sim_path_)
1088 return;
1089
1090 mm1::SimProxyInterface *proxy = NULL;
1091 if (!sim_path.empty())
1092 proxy = proxy_factory()->CreateSimProxy(sim_path,
1093 cellular()->dbus_owner());
1094 sim_path_ = sim_path;
1095 sim_proxy_.reset(proxy);
1096
1097 if (sim_path.empty()) {
1098 // Clear all data about the sim
Jason Glasgow4380f0d2012-05-03 18:05:04 -04001099 imsi_ = "";
1100 spn_ = "";
Ben Chanbd3aee82012-10-16 23:52:04 -07001101 sim_present_ = false;
Jason Glasgowaf583282012-04-18 15:18:22 -04001102 OnSimIdentifierChanged("");
1103 OnOperatorIdChanged("");
Jason Glasgowaf583282012-04-18 15:18:22 -04001104 } else {
Ben Chanbd3aee82012-10-16 23:52:04 -07001105 sim_present_ = true;
Jason Glasgowaf583282012-04-18 15:18:22 -04001106 scoped_ptr<DBusPropertiesProxyInterface> properties_proxy(
1107 proxy_factory()->CreateDBusPropertiesProxy(sim_path,
1108 cellular()->dbus_owner()));
1109 // TODO(jglasgow): convert to async interface
1110 DBusPropertiesMap properties(
1111 properties_proxy->GetAll(MM_DBUS_INTERFACE_SIM));
1112 OnSimPropertiesChanged(properties, vector<string>());
1113 }
1114}
1115
1116void CellularCapabilityUniversal::OnModemCapabilitesChanged(
1117 uint32 capabilities) {
1118 capabilities_ = capabilities;
1119}
1120
1121void CellularCapabilityUniversal::OnModemCurrentCapabilitiesChanged(
1122 uint32 current_capabilities) {
1123 current_capabilities_ = current_capabilities;
1124}
1125
1126void CellularCapabilityUniversal::OnMdnChanged(
1127 const string &mdn) {
1128 mdn_ = mdn;
1129}
1130
1131void CellularCapabilityUniversal::OnModemManufacturerChanged(
1132 const string &manufacturer) {
1133 manufacturer_ = manufacturer;
1134}
1135
1136void CellularCapabilityUniversal::OnModemModelChanged(
1137 const string &model) {
1138 model_id_ = model;
1139}
1140
1141void CellularCapabilityUniversal::OnModemRevisionChanged(
1142 const string &revision) {
1143 firmware_revision_ = revision;
1144}
1145
1146void CellularCapabilityUniversal::OnModemStateChanged(
1147 Cellular::ModemState state) {
1148 Cellular::ModemState prev_modem_state = cellular()->modem_state();
1149 bool was_enabled = cellular()->IsUnderlyingDeviceEnabled();
1150 if (Cellular::IsEnabledModemState(state))
1151 cellular()->set_modem_state(state);
Gary Moraine285a842012-08-15 08:23:57 -07001152 SLOG(Cellular, 2) << __func__ << ": prev_modem_state: " << prev_modem_state
1153 << " was_enabled: " << was_enabled
1154 << " cellular state: "
1155 << cellular()->GetStateString(cellular()->state());
Jason Glasgowaf583282012-04-18 15:18:22 -04001156 if (prev_modem_state != Cellular::kModemStateUnknown &&
1157 prev_modem_state != Cellular::kModemStateEnabling &&
1158 !was_enabled &&
1159 cellular()->state() == Cellular::kStateDisabled &&
1160 cellular()->IsUnderlyingDeviceEnabled()) {
1161 cellular()->SetEnabled(true);
1162 }
1163}
1164
1165void CellularCapabilityUniversal::OnAccessTechnologiesChanged(
1166 uint32 access_technologies) {
Jason Glasgow9f09aef2012-05-08 16:26:55 -04001167 if (access_technologies_ != access_technologies) {
Jason Glasgowbad114b2012-05-21 15:24:16 -04001168 const string old_type_string(GetTypeString());
Jason Glasgow9f09aef2012-05-08 16:26:55 -04001169 access_technologies_ = access_technologies;
Jason Glasgowbad114b2012-05-21 15:24:16 -04001170 const string new_type_string(GetTypeString());
1171 if (new_type_string != old_type_string) {
1172 // TODO(jglasgow): address layering violation of emitting change
1173 // signal here for a property owned by Cellular.
1174 cellular()->adaptor()->EmitStringChanged(
1175 flimflam::kTechnologyFamilyProperty, new_type_string);
1176 }
Jason Glasgow9f09aef2012-05-08 16:26:55 -04001177 if (cellular()->service().get()) {
1178 cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString());
1179 }
Jason Glasgowaf583282012-04-18 15:18:22 -04001180 }
1181}
1182
1183void CellularCapabilityUniversal::OnSupportedModesChanged(
1184 uint32 supported_modes) {
1185 supported_modes_ = supported_modes;
1186}
1187
1188void CellularCapabilityUniversal::OnAllowedModesChanged(
1189 uint32 allowed_modes) {
1190 allowed_modes_ = allowed_modes;
1191}
1192
1193void CellularCapabilityUniversal::OnPreferredModeChanged(
1194 MMModemMode preferred_mode) {
1195 preferred_mode_ = preferred_mode;
1196}
1197
1198void CellularCapabilityUniversal::OnLockRetriesChanged(
1199 MMModemLock unlock_required,
1200 const LockRetryData &lock_retries) {
Jason Glasgowd4af81d2012-05-03 22:25:05 -04001201 switch (unlock_required) {
Jason Glasgowaf583282012-04-18 15:18:22 -04001202 case MM_MODEM_LOCK_SIM_PIN:
1203 sim_lock_status_.lock_type = "sim-pin";
1204 break;
1205 case MM_MODEM_LOCK_SIM_PUK:
1206 sim_lock_status_.lock_type = "sim-puk";
1207 break;
1208 default:
1209 sim_lock_status_.lock_type = "";
1210 break;
1211 }
1212 LockRetryData::const_iterator it = lock_retries.find(unlock_required);
1213 if (it != lock_retries.end()) {
1214 sim_lock_status_.retries_left = it->second;
1215 } else {
1216 // Unknown, use 999
1217 sim_lock_status_.retries_left = 999;
1218 }
1219 OnSimLockStatusChanged();
1220}
1221
1222void CellularCapabilityUniversal::OnSimLockStatusChanged() {
1223 cellular()->adaptor()->EmitKeyValueStoreChanged(
1224 flimflam::kSIMLockStatusProperty, SimLockStatusToProperty(NULL));
1225}
1226
1227void CellularCapabilityUniversal::OnModem3GPPPropertiesChanged(
1228 const DBusPropertiesMap &properties,
1229 const vector<string> &/* invalidated_properties */) {
Ben Chan6d0d1e72012-11-06 21:19:28 -08001230 SLOG(Cellular, 2) << __func__;
Jason Glasgowaf583282012-04-18 15:18:22 -04001231 string imei;
1232 if (DBusProperties::GetString(properties,
1233 MM_MODEM_MODEM3GPP_PROPERTY_IMEI,
1234 &imei))
1235 OnImeiChanged(imei);
1236
1237 // Handle registration state changes as a single change
1238 string operator_code = serving_operator_.GetCode();
1239 string operator_name = serving_operator_.GetName();
1240 MMModem3gppRegistrationState state = registration_state_;
1241 bool registration_changed = false;
1242 uint32 uint_value;
1243 if (DBusProperties::GetUint32(properties,
1244 MM_MODEM_MODEM3GPP_PROPERTY_REGISTRATIONSTATE,
1245 &uint_value)) {
1246 state = static_cast<MMModem3gppRegistrationState>(uint_value);
1247 registration_changed = true;
1248 }
1249 if (DBusProperties::GetString(properties,
1250 MM_MODEM_MODEM3GPP_PROPERTY_OPERATORCODE,
1251 &operator_code))
1252 registration_changed = true;
1253 if (DBusProperties::GetString(properties,
1254 MM_MODEM_MODEM3GPP_PROPERTY_OPERATORNAME,
1255 &operator_name))
1256 registration_changed = true;
1257 if (registration_changed)
1258 On3GPPRegistrationChanged(state, operator_code, operator_name);
1259
1260 uint32 locks = 0;
1261 if (DBusProperties::GetUint32(
1262 properties, MM_MODEM_MODEM3GPP_PROPERTY_ENABLEDFACILITYLOCKS,
1263 &locks))
1264 OnFacilityLocksChanged(locks);
1265}
1266
1267void CellularCapabilityUniversal::OnImeiChanged(const string &imei) {
1268 imei_ = imei;
1269}
1270
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001271void CellularCapabilityUniversal::On3GPPRegistrationChanged(
1272 MMModem3gppRegistrationState state,
1273 const string &operator_code,
1274 const string &operator_name) {
Ben Chanfad4a0b2012-04-18 15:49:59 -07001275 SLOG(Cellular, 2) << __func__ << ": regstate=" << state
1276 << ", opercode=" << operator_code
1277 << ", opername=" << operator_name;
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001278 registration_state_ = state;
1279 serving_operator_.SetCode(operator_code);
1280 serving_operator_.SetName(operator_name);
1281 UpdateOperatorInfo();
1282 cellular()->HandleNewRegistrationState();
1283}
1284
Eric Shienbrood7fce52c2012-04-13 19:11:02 -04001285void CellularCapabilityUniversal::OnModemStateChangedSignal(
1286 int32 old_state, int32 new_state, uint32 reason) {
Eric Shienbrood9b1bd7b2012-04-20 16:42:26 -04001287 SLOG(Cellular, 2) << __func__ << "(" << old_state << ", " << new_state << ", "
1288 << reason << ")";
Eric Shienbrood7fce52c2012-04-13 19:11:02 -04001289 cellular()->OnModemStateChanged(static_cast<Cellular::ModemState>(old_state),
1290 static_cast<Cellular::ModemState>(new_state),
1291 reason);
Gary Moraine285a842012-08-15 08:23:57 -07001292 if (!deferred_enable_modem_callback_.is_null() &&
1293 (new_state == Cellular::kModemStateDisabled)) {
1294 SLOG(Cellular, 2) << "Enabling modem after deferring";
1295 deferred_enable_modem_callback_.Run();
1296 deferred_enable_modem_callback_.Reset();
1297 }
Eric Shienbrood7fce52c2012-04-13 19:11:02 -04001298}
1299
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001300void CellularCapabilityUniversal::OnSignalQualityChanged(uint32 quality) {
1301 cellular()->HandleNewSignalQuality(quality);
1302}
1303
Jason Glasgowaf583282012-04-18 15:18:22 -04001304void CellularCapabilityUniversal::OnFacilityLocksChanged(uint32 locks) {
1305 if (sim_lock_status_.enabled != (locks & MM_MODEM_3GPP_FACILITY_SIM)) {
1306 sim_lock_status_.enabled = locks & MM_MODEM_3GPP_FACILITY_SIM;
1307 OnSimLockStatusChanged();
1308 }
1309}
Jason Glasgowef965562012-04-10 16:12:35 -04001310
Jason Glasgowaf583282012-04-18 15:18:22 -04001311void CellularCapabilityUniversal::OnSimPropertiesChanged(
1312 const DBusPropertiesMap &props,
1313 const vector<string> &/* invalidated_properties */) {
Ben Chan6d0d1e72012-11-06 21:19:28 -08001314 SLOG(Cellular, 2) << __func__;
Jason Glasgowaf583282012-04-18 15:18:22 -04001315 string value;
Jason Glasgow4380f0d2012-05-03 18:05:04 -04001316 bool must_update_home_provider = false;
Jason Glasgowaf583282012-04-18 15:18:22 -04001317 if (DBusProperties::GetString(props, MM_SIM_PROPERTY_SIMIDENTIFIER, &value))
1318 OnSimIdentifierChanged(value);
1319 if (DBusProperties::GetString(props, MM_SIM_PROPERTY_OPERATORIDENTIFIER,
1320 &value))
1321 OnOperatorIdChanged(value);
Jason Glasgow4380f0d2012-05-03 18:05:04 -04001322 if (DBusProperties::GetString(props, MM_SIM_PROPERTY_OPERATORNAME, &value)) {
1323 spn_ = value;
1324 must_update_home_provider = true;
1325 }
1326 if (DBusProperties::GetString(props, MM_SIM_PROPERTY_IMSI, &value)) {
1327 imsi_ = value;
1328 must_update_home_provider = true;
1329 }
Jason Glasgowaf583282012-04-18 15:18:22 -04001330 // TODO(jglasgow): May eventually want to get SPDI, etc
Jason Glasgowaf583282012-04-18 15:18:22 -04001331
Jason Glasgow4380f0d2012-05-03 18:05:04 -04001332 if (must_update_home_provider)
1333 SetHomeProvider();
Jason Glasgowaf583282012-04-18 15:18:22 -04001334}
1335
1336void CellularCapabilityUniversal::OnSimIdentifierChanged(const string &id) {
1337 sim_identifier_ = id;
1338}
1339
1340void CellularCapabilityUniversal::OnOperatorIdChanged(
1341 const string &operator_id) {
Ben Chan6d0d1e72012-11-06 21:19:28 -08001342 SLOG(Cellular, 2) << "Operator ID = '" << operator_id << "'";
Jason Glasgowaf583282012-04-18 15:18:22 -04001343 operator_id_ = operator_id;
1344}
1345
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001346} // namespace shill