blob: 6c3067d83039bd83adf403769b4afce9eb11946d [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>
8#include <base/logging.h>
9#include <base/stl_util.h>
10#include <base/string_number_conversions.h>
11#include <base/stringprintf.h>
12#include <chromeos/dbus/service_constants.h>
13#include <mobile_provider.h>
14#include <mm/ModemManager-names.h>
15
16#include <string>
17#include <vector>
18
19#include "shill/adaptor_interfaces.h"
20#include "shill/cellular_service.h"
21#include "shill/error.h"
22#include "shill/property_accessor.h"
23#include "shill/proxy_factory.h"
Ben Chanfad4a0b2012-04-18 15:49:59 -070024#include "shill/scope_logger.h"
Jason Glasgow82f9ab32012-04-04 14:27:19 -040025
26#ifdef MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN
27#error "Do not include mm-modem.h"
28#endif
29
30// The following are constants that should be found in
31// mm/ModemManager-names.h The are reproduced here as #define because
32// that is how they will appear eventually in ModemManager-names.h
33#define MM_MODEM_SIMPLE_CONNECT_PIN "pin"
34#define MM_MODEM_SIMPLE_CONNECT_OPERATOR_ID "operator-id"
35#define MM_MODEM_SIMPLE_CONNECT_BANDS "bands"
36#define MM_MODEM_SIMPLE_CONNECT_ALLWOED_MODES "allowed-modes"
37#define MM_MODEM_SIMPLE_CONNECT_PREFERRED_MODE "preferred-mode"
38#define MM_MODEM_SIMPLE_CONNECT_APN "apn"
39#define MM_MODEM_SIMPLE_CONNECT_IP_TYPE "ip-type"
40#define MM_MODEM_SIMPLE_CONNECT_USER "user"
41#define MM_MODEM_SIMPLE_CONNECT_PASSWORD "password"
42#define MM_MODEM_SIMPLE_CONNECT_NUMBER "number"
43#define MM_MODEM_SIMPLE_CONNECT_ALLOW_ROAMING "allow-roaming"
44#define MM_MODEM_SIMPLE_CONNECT_RM_PROTOCOL "rm-protocol"
45
46using base::Bind;
Jason Glasgowef965562012-04-10 16:12:35 -040047using base::Callback;
48using base::Closure;
Jason Glasgow82f9ab32012-04-04 14:27:19 -040049using std::string;
50using std::vector;
51
52namespace shill {
53
54// static
55unsigned int CellularCapabilityUniversal::friendly_service_name_id_ = 0;
56
57static const char kPhoneNumber[] = "*99#";
58
59static string AccessTechnologyToString(uint32 access_technologies) {
60 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_LTE)
61 return flimflam::kNetworkTechnologyLte;
62 if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_EVDO0 |
63 MM_MODEM_ACCESS_TECHNOLOGY_EVDOA |
64 MM_MODEM_ACCESS_TECHNOLOGY_EVDOB))
65 return flimflam::kNetworkTechnologyEvdo;
66 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_1XRTT)
67 return flimflam::kNetworkTechnology1Xrtt;
68 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS)
69 return flimflam::kNetworkTechnologyHspaPlus;
70 if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_HSPA |
71 MM_MODEM_ACCESS_TECHNOLOGY_HSUPA |
72 MM_MODEM_ACCESS_TECHNOLOGY_HSDPA))
73 return flimflam::kNetworkTechnologyHspa;
74 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_UMTS)
75 return flimflam::kNetworkTechnologyUmts;
76 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_EDGE)
77 return flimflam::kNetworkTechnologyEdge;
78 if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_GPRS)
79 return flimflam::kNetworkTechnologyGprs;
80 if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT |
81 MM_MODEM_ACCESS_TECHNOLOGY_GSM))
82 return flimflam::kNetworkTechnologyGsm;
83 return "";
84}
85
86CellularCapabilityUniversal::CellularCapabilityUniversal(
87 Cellular *cellular,
88 ProxyFactory *proxy_factory)
89 : CellularCapability(cellular, proxy_factory),
90 weak_ptr_factory_(this),
91 registration_state_(MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN),
92 cdma_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
93 access_technologies_(MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN),
94 home_provider_(NULL),
95 scanning_supported_(true),
96 scanning_(false),
97 scan_interval_(0) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070098 SLOG(Cellular, 2) << "Cellular capability constructed: Universal";
Jason Glasgow82f9ab32012-04-04 14:27:19 -040099 PropertyStore *store = cellular->mutable_store();
100
101 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
102 store->RegisterConstBool(flimflam::kSupportNetworkScanProperty,
103 &scanning_supported_);
104 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
105 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
106 &firmware_revision_);
107 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
108 &hardware_revision_);
109 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
110 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
111 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
112 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
113 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
114 store->RegisterConstString(flimflam::kMinProperty, &min_);
115 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
116 store->RegisterConstString(flimflam::kSelectedNetworkProperty,
117 &selected_network_);
118 store->RegisterConstStringmaps(flimflam::kFoundNetworksProperty,
119 &found_networks_);
120 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
121 store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
122 HelpRegisterDerivedKeyValueStore(
123 flimflam::kSIMLockStatusProperty,
124 &CellularCapabilityUniversal::SimLockStatusToProperty,
125 NULL);
126 store->RegisterConstStringmaps(flimflam::kCellularApnListProperty,
127 &apn_list_);
128}
129
130KeyValueStore CellularCapabilityUniversal::SimLockStatusToProperty(
131 Error */*error*/) {
132 KeyValueStore status;
133 status.SetBool(flimflam::kSIMLockEnabledProperty, sim_lock_status_.enabled);
134 status.SetString(flimflam::kSIMLockTypeProperty, sim_lock_status_.lock_type);
135 status.SetUint(flimflam::kSIMLockRetriesLeftProperty,
136 sim_lock_status_.retries_left);
137 return status;
138}
139
140void CellularCapabilityUniversal::HelpRegisterDerivedKeyValueStore(
141 const string &name,
142 KeyValueStore(CellularCapabilityUniversal::*get)(Error *error),
143 void(CellularCapabilityUniversal::*set)(
144 const KeyValueStore &value, Error *error)) {
145 cellular()->mutable_store()->RegisterDerivedKeyValueStore(
146 name,
147 KeyValueStoreAccessor(
148 new CustomAccessor<CellularCapabilityUniversal, KeyValueStore>(
149 this, get, set)));
150}
151
152void CellularCapabilityUniversal::InitProxies() {
153 modem_3gpp_proxy_.reset(
154 proxy_factory()->CreateMM1ModemModem3gppProxy(cellular()->dbus_path(),
155 cellular()->dbus_owner()));
156 modem_cdma_proxy_.reset(
157 proxy_factory()->CreateMM1ModemModemCdmaProxy(cellular()->dbus_path(),
158 cellular()->dbus_owner()));
159 modem_proxy_.reset(
160 proxy_factory()->CreateMM1ModemProxy(cellular()->dbus_path(),
161 cellular()->dbus_owner()));
162 modem_simple_proxy_.reset(
163 proxy_factory()->CreateMM1ModemSimpleProxy(cellular()->dbus_path(),
164 cellular()->dbus_owner()));
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400165 modem_proxy_->set_state_changed_callback(
166 Bind(&CellularCapabilityUniversal::OnModemStateChangedSignal,
167 weak_ptr_factory_.GetWeakPtr()));
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400168 // Do not create a SIM proxy until the device is enabled because we
169 // do not yet know the object path of the sim object.
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400170 // TODO(jglasgow): register callbacks
171}
172
173void CellularCapabilityUniversal::StartModem(Error *error,
Jason Glasgowef965562012-04-10 16:12:35 -0400174 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700175 SLOG(Cellular, 2) << __func__;
Jason Glasgowef965562012-04-10 16:12:35 -0400176
177 InitProxies();
178
179 // Start by trying to enable the modem
180 CHECK(!callback.is_null());
181 modem_proxy_->Enable(
182 true,
183 error,
184 Bind(&CellularCapabilityUniversal::Start_EnableModemCompleted,
185 weak_ptr_factory_.GetWeakPtr(), callback),
186 kTimeoutEnable);
187 if (error->IsFailure())
188 callback.Run(*error);
189}
190
191void CellularCapabilityUniversal::Start_EnableModemCompleted(
192 const ResultCallback &callback, const Error &error) {
Eric Shienbrood9b1bd7b2012-04-20 16:42:26 -0400193 SLOG(Cellular, 2) << __func__ << ": " << error;
Jason Glasgowef965562012-04-10 16:12:35 -0400194 if (error.IsFailure()) {
195 callback.Run(error);
196 return;
197 }
198
199 // After modem is enabled, it should be possible to get properties
200 // TODO(jglasgow): handle errors from GetProperties
201 GetProperties();
202
203 // Try to register
204 Error local_error;
205 modem_3gpp_proxy_->Register(
206 selected_network_, &local_error,
207 Bind(&CellularCapabilityUniversal::Start_RegisterCompleted,
208 weak_ptr_factory_.GetWeakPtr(), callback),
209 kTimeoutRegister);
210 if (local_error.IsFailure()) {
211 callback.Run(local_error);
212 return;
213 }
214}
215
216void CellularCapabilityUniversal::Start_RegisterCompleted(
217 const ResultCallback &callback, const Error &error) {
Eric Shienbrood9b1bd7b2012-04-20 16:42:26 -0400218 SLOG(Cellular, 2) << __func__ << ": " << error;
Jason Glasgowef965562012-04-10 16:12:35 -0400219 if (error.IsSuccess()) {
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400220 // Normally, running the callback is the last thing done in a method.
221 // In this case, we do it first, because we want to make sure that
222 // the device is marked as Enabled before the registration state is
223 // handled. See comment in Cellular::HandleNewRegistrationState.
224 callback.Run(error);
Jason Glasgowef965562012-04-10 16:12:35 -0400225 // If registered, get the registration state and signal quality.
226 GetRegistrationState();
227 GetSignalQuality();
228 } else {
229 LOG(ERROR) << "registration failed: " << error;
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400230 // Ignore registration errors, because that just means there is no signal.
231 callback.Run(Error());
Jason Glasgowef965562012-04-10 16:12:35 -0400232 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400233}
234
235void CellularCapabilityUniversal::StopModem(Error *error,
236 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700237 SLOG(Cellular, 2) << __func__;
Jason Glasgowef965562012-04-10 16:12:35 -0400238 CHECK(!callback.is_null());
239 CHECK(error);
240 bool connected = false;
241 string all_bearers("/"); // Represents all bearers for disconnect operations
242
243 if (connected) {
244 modem_simple_proxy_->Disconnect(
245 all_bearers,
246 error,
247 Bind(&CellularCapabilityUniversal::Stop_DisconnectCompleted,
248 weak_ptr_factory_.GetWeakPtr(), callback),
249 kTimeoutDefault);
250 if (error->IsFailure())
251 callback.Run(*error);
252 } else {
253 Error error;
254 Closure task = Bind(&CellularCapabilityUniversal::Stop_Disable,
255 weak_ptr_factory_.GetWeakPtr(),
256 callback);
257 cellular()->dispatcher()->PostTask(task);
258 }
259}
260
261void CellularCapabilityUniversal::Stop_DisconnectCompleted(
262 const ResultCallback &callback, const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700263 SLOG(Cellular, 2) << __func__;
Jason Glasgowef965562012-04-10 16:12:35 -0400264
265 LOG_IF(ERROR, error.IsFailure()) << "Disconnect failed. Ignoring.";
266 Stop_Disable(callback);
267}
268
269void CellularCapabilityUniversal::Stop_Disable(const ResultCallback &callback) {
270 Error error;
271 modem_proxy_->Enable(
272 false, &error,
273 Bind(&CellularCapabilityUniversal::Stop_DisableCompleted,
274 weak_ptr_factory_.GetWeakPtr(), callback),
275 kTimeoutDefault);
276 if (error.IsFailure())
277 callback.Run(error);
278}
279
280void CellularCapabilityUniversal::Stop_DisableCompleted(
281 const ResultCallback &callback, const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700282 SLOG(Cellular, 2) << __func__;
Jason Glasgowef965562012-04-10 16:12:35 -0400283
284 if (error.IsSuccess())
285 ReleaseProxies();
286 callback.Run(error);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400287}
288
289void CellularCapabilityUniversal::Connect(const DBusPropertiesMap &properties,
290 Error *error,
291 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700292 SLOG(Cellular, 2) << __func__;
Nathan Williamsb54974f2012-04-19 11:16:30 -0400293 DBusPathCallback cb = Bind(&CellularCapabilityUniversal::OnConnectReply,
294 weak_ptr_factory_.GetWeakPtr(),
295 callback);
296 modem_simple_proxy_->Connect(properties, error, cb, kTimeoutConnect);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400297}
298
299void CellularCapabilityUniversal::Disconnect(Error *error,
300 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700301 SLOG(Cellular, 2) << __func__;
Nathan Williamsb54974f2012-04-19 11:16:30 -0400302 modem_simple_proxy_->Disconnect(bearer_path_,
303 error,
304 callback,
305 kTimeoutDefault);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400306}
307
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400308void CellularCapabilityUniversal::Activate(const string &carrier,
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400309 Error *error,
310 const ResultCallback &callback) {
311 OnUnsupportedOperation(__func__, error);
312}
313
314void CellularCapabilityUniversal::ReleaseProxies() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700315 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400316 modem_3gpp_proxy_.reset();
317 modem_cdma_proxy_.reset();
318 modem_proxy_.reset();
319 modem_simple_proxy_.reset();
320 sim_proxy_.reset();
321}
322
323void CellularCapabilityUniversal::OnServiceCreated() {
324 // If IMSI is available, base the service's storage identifier on it.
325 if (!imsi_.empty()) {
326 cellular()->service()->SetStorageIdentifier(
327 string(flimflam::kTypeCellular) + "_" +
328 cellular()->address() + "_" + imsi_);
329 }
330 cellular()->service()->SetActivationState(
331 flimflam::kActivationStateActivated);
332 UpdateServingOperator();
333}
334
335void CellularCapabilityUniversal::UpdateStatus(
336 const DBusPropertiesMap &properties) {
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400337 if (ContainsKey(properties, kModemPropertyIMSI)) {
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400338 SetHomeProvider();
339 }
340}
341
342// Create the list of APNs to try, in the following order:
343// - last APN that resulted in a successful connection attempt on the
344// current network (if any)
345// - the APN, if any, that was set by the user
346// - the list of APNs found in the mobile broadband provider DB for the
347// home provider associated with the current SIM
348// - as a last resort, attempt to connect with no APN
349void CellularCapabilityUniversal::SetupApnTryList() {
350 apn_try_list_.clear();
351
352 DCHECK(cellular()->service().get());
353 const Stringmap *apn_info = cellular()->service()->GetLastGoodApn();
354 if (apn_info)
355 apn_try_list_.push_back(*apn_info);
356
357 apn_info = cellular()->service()->GetUserSpecifiedApn();
358 if (apn_info)
359 apn_try_list_.push_back(*apn_info);
360
361 apn_try_list_.insert(apn_try_list_.end(), apn_list_.begin(), apn_list_.end());
362}
363
364void CellularCapabilityUniversal::SetupConnectProperties(
365 DBusPropertiesMap *properties) {
366 SetupApnTryList();
367 FillConnectPropertyMap(properties);
368}
369
370void CellularCapabilityUniversal::FillConnectPropertyMap(
371 DBusPropertiesMap *properties) {
372
373 // TODO(jglasgow): Is this really needed anymore?
374 (*properties)[MM_MODEM_SIMPLE_CONNECT_NUMBER].writer().append_string(
375 kPhoneNumber);
376
377 (*properties)[MM_MODEM_SIMPLE_CONNECT_ALLOW_ROAMING].writer().append_bool(
378 AllowRoaming());
379
380 if (!apn_try_list_.empty()) {
381 // Leave the APN at the front of the list, so that it can be recorded
382 // if the connect attempt succeeds.
383 Stringmap apn_info = apn_try_list_.front();
Ben Chanfad4a0b2012-04-18 15:49:59 -0700384 SLOG(Cellular, 2) << __func__ << ": Using APN "
385 << apn_info[flimflam::kApnProperty];
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400386 (*properties)[MM_MODEM_SIMPLE_CONNECT_APN].writer().append_string(
387 apn_info[flimflam::kApnProperty].c_str());
388 if (ContainsKey(apn_info, flimflam::kApnUsernameProperty))
389 (*properties)[MM_MODEM_SIMPLE_CONNECT_USER].writer().append_string(
390 apn_info[flimflam::kApnUsernameProperty].c_str());
391 if (ContainsKey(apn_info, flimflam::kApnPasswordProperty))
392 (*properties)[MM_MODEM_SIMPLE_CONNECT_PASSWORD].writer().append_string(
393 apn_info[flimflam::kApnPasswordProperty].c_str());
394 }
395}
396
397void CellularCapabilityUniversal::OnConnectReply(const ResultCallback &callback,
Nathan Williamsb54974f2012-04-19 11:16:30 -0400398 const DBus::Path &path,
399 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700400 SLOG(Cellular, 2) << __func__ << "(" << error << ")";
Nathan Williamsb54974f2012-04-19 11:16:30 -0400401
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400402 if (error.IsFailure()) {
403 cellular()->service()->ClearLastGoodApn();
404 // The APN that was just tried (and failed) is still at the
405 // front of the list, about to be removed. If the list is empty
406 // after that, try one last time without an APN. This may succeed
407 // with some modems in some cases.
408 if (error.type() == Error::kInvalidApn && !apn_try_list_.empty()) {
409 apn_try_list_.pop_front();
Ben Chanfad4a0b2012-04-18 15:49:59 -0700410 SLOG(Cellular, 2) << "Connect failed with invalid APN, "
411 << apn_try_list_.size() << " remaining APNs to try";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400412 DBusPropertiesMap props;
413 FillConnectPropertyMap(&props);
414 Error error;
415 Connect(props, &error, callback);
416 return;
417 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400418 } else {
419 if (!apn_try_list_.empty()) {
420 cellular()->service()->SetLastGoodApn(apn_try_list_.front());
421 apn_try_list_.clear();
422 }
Nathan Williamsb54974f2012-04-19 11:16:30 -0400423 bearer_path_ = path;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400424 }
425
426 if (!callback.is_null())
427 callback.Run(error);
428}
429
430bool CellularCapabilityUniversal::AllowRoaming() {
431 bool requires_roaming =
432 home_provider_ ? home_provider_->requires_roaming : false;
433 return requires_roaming || allow_roaming_property();
434}
435
436void CellularCapabilityUniversal::GetRegistrationState() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700437 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400438 string operator_code;
439 string operator_name;
440
441 const MMModem3gppRegistrationState state =
442 static_cast<MMModem3gppRegistrationState>(
443 modem_3gpp_proxy_->RegistrationState());
444 if (state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
445 state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
446 operator_code = modem_3gpp_proxy_->OperatorCode();
447 operator_name = modem_3gpp_proxy_->OperatorName();
448 }
449 On3GPPRegistrationChanged(state, operator_code, operator_name);
450}
451
Jason Glasgowef965562012-04-10 16:12:35 -0400452void CellularCapabilityUniversal::GetProperties() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700453 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400454
455 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
456 uint32 technologies = modem_proxy_->AccessTechnologies();
457 // TODO(jglasgow): figure out the most likely one that we are using....
458 SetAccessTechnologies(technologies);
Ben Chanfad4a0b2012-04-18 15:49:59 -0700459 SLOG(Cellular, 2) << "AccessTechnologies: " << technologies;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400460
461 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
462 uint32 locks = modem_3gpp_proxy_->EnabledFacilityLocks();
463 sim_lock_status_.enabled = locks & MM_MODEM_3GPP_FACILITY_SIM;
Ben Chanfad4a0b2012-04-18 15:49:59 -0700464 SLOG(Cellular, 2) << "GSM EnabledFacilityLocks: " << locks;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400465
466 // TODO(jglasgow): Switch to asynchronous calls (crosbug.com/17583).
467 const DBus::Struct<unsigned int, bool> quality =
468 modem_proxy_->SignalQuality();
469 OnSignalQualityChanged(quality._1);
470
471 // TODO(jglasgow): Switch to asynchronous calls (crosbug.com/17583).
472 if (imei_.empty()) {
473 imei_ = modem_3gpp_proxy_->Imei();
474 }
Jason Glasgowef965562012-04-10 16:12:35 -0400475
476 string sim_path = modem_proxy_->Sim();
477 OnSimPathChanged(sim_path);
478
479 if (sim_proxy_.get()) {
480 if (imsi_.empty()) {
481 imsi_ = sim_proxy_->Imsi();
482 }
483 if (spn_.empty()) {
484 spn_ = sim_proxy_->OperatorName();
485 // TODO(jglasgow): May eventually want to get SPDI, etc
486 }
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400487 }
Nathan Williamsb0b66df2012-04-17 13:29:07 -0400488
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400489 if (mdn_.empty()) {
Nathan Williams4b7c2a82012-04-13 15:19:47 -0400490 // TODO(njw): Switch to asynchronous calls (crosbug.com/17583).
491 vector<string> numbers = modem_proxy_->OwnNumbers();
492 if (numbers.size() > 0)
493 mdn_ = numbers[0];
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400494 }
Nathan Williamsb0b66df2012-04-17 13:29:07 -0400495
496 if (model_id_.empty()) {
497 // TODO(njw): Switch to asynchronous calls (crosbug.com/17583).
498 model_id_ = modem_proxy_->Model();
499 }
500
501 if (manufacturer_.empty()) {
502 // TODO(njw): Switch to asynchronous calls (crosbug.com/17583).
503 manufacturer_ = modem_proxy_->Manufacturer();
504 }
505
506 if (firmware_revision_.empty()) {
507 // TODO(njw): Switch to asynchronous calls (crosbug.com/17583).
508 firmware_revision_ = modem_proxy_->Revision();
509 }
510
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400511 GetRegistrationState();
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400512}
513
514string CellularCapabilityUniversal::CreateFriendlyServiceName() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700515 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400516 if (registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_HOME &&
517 !cellular()->home_provider().GetName().empty()) {
518 return cellular()->home_provider().GetName();
519 }
520 if (!serving_operator_.GetName().empty()) {
521 return serving_operator_.GetName();
522 }
523 if (!carrier_.empty()) {
524 return carrier_;
525 }
526 if (!serving_operator_.GetCode().empty()) {
527 return "cellular_" + serving_operator_.GetCode();
528 }
529 return base::StringPrintf("GSMNetwork%u", friendly_service_name_id_++);
530}
531
532void CellularCapabilityUniversal::SetHomeProvider() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700533 SLOG(Cellular, 2) << __func__ << "(IMSI: " << imsi_
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400534 << " SPN: " << spn_ << ")";
535 // TODO(petkov): The test for NULL provider_db should be done by
536 // mobile_provider_lookup_best_match.
537 if (imsi_.empty() || !cellular()->provider_db()) {
538 return;
539 }
540 mobile_provider *provider =
541 mobile_provider_lookup_best_match(
542 cellular()->provider_db(), spn_.c_str(), imsi_.c_str());
543 if (!provider) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700544 SLOG(Cellular, 2) << "GSM provider not found.";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400545 return;
546 }
547 home_provider_ = provider;
548 Cellular::Operator oper;
549 if (provider->networks) {
550 oper.SetCode(provider->networks[0]);
551 }
552 if (provider->country) {
553 oper.SetCountry(provider->country);
554 }
555 if (spn_.empty()) {
556 const char *name = mobile_provider_get_name(provider);
557 if (name) {
558 oper.SetName(name);
559 }
560 } else {
561 oper.SetName(spn_);
562 }
563 cellular()->set_home_provider(oper);
564 InitAPNList();
565}
566
567void CellularCapabilityUniversal::UpdateOperatorInfo() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700568 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400569 const string &network_id = serving_operator_.GetCode();
570 if (!network_id.empty()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700571 SLOG(Cellular, 2) << "Looking up network id: " << network_id;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400572 mobile_provider *provider =
573 mobile_provider_lookup_by_network(cellular()->provider_db(),
574 network_id.c_str());
575 if (provider) {
576 const char *provider_name = mobile_provider_get_name(provider);
577 if (provider_name && *provider_name) {
578 serving_operator_.SetName(provider_name);
579 if (provider->country) {
580 serving_operator_.SetCountry(provider->country);
581 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700582 SLOG(Cellular, 2) << "Operator name: " << serving_operator_.GetName()
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400583 << ", country: " << serving_operator_.GetCountry();
584 }
585 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700586 SLOG(Cellular, 2) << "GSM provider not found.";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400587 }
588 }
589 UpdateServingOperator();
590}
591
592void CellularCapabilityUniversal::UpdateServingOperator() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700593 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400594 if (cellular()->service().get()) {
595 cellular()->service()->SetServingOperator(serving_operator_);
596 }
597}
598
599void CellularCapabilityUniversal::InitAPNList() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700600 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400601 if (!home_provider_) {
602 return;
603 }
604 apn_list_.clear();
605 for (int i = 0; i < home_provider_->num_apns; ++i) {
606 Stringmap props;
607 mobile_apn *apn = home_provider_->apns[i];
608 if (apn->value) {
609 props[flimflam::kApnProperty] = apn->value;
610 }
611 if (apn->username) {
612 props[flimflam::kApnUsernameProperty] = apn->username;
613 }
614 if (apn->password) {
615 props[flimflam::kApnPasswordProperty] = apn->password;
616 }
617 // Find the first localized and non-localized name, if any.
618 const localized_name *lname = NULL;
619 const localized_name *name = NULL;
620 for (int j = 0; j < apn->num_names; ++j) {
621 if (apn->names[j]->lang) {
622 if (!lname) {
623 lname = apn->names[j];
624 }
625 } else if (!name) {
626 name = apn->names[j];
627 }
628 }
629 if (name) {
630 props[flimflam::kApnNameProperty] = name->name;
631 }
632 if (lname) {
633 props[flimflam::kApnLocalizedNameProperty] = lname->name;
634 props[flimflam::kApnLanguageProperty] = lname->lang;
635 }
636 apn_list_.push_back(props);
637 }
638 cellular()->adaptor()->EmitStringmapsChanged(
639 flimflam::kCellularApnListProperty, apn_list_);
640}
641
642// always called from an async context
643void CellularCapabilityUniversal::Register(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700644 SLOG(Cellular, 2) << __func__ << " \"" << selected_network_ << "\"";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400645 CHECK(!callback.is_null());
646 Error error;
647 ResultCallback cb = Bind(&CellularCapabilityUniversal::OnRegisterReply,
648 weak_ptr_factory_.GetWeakPtr(), callback);
649 modem_3gpp_proxy_->Register(selected_network_, &error, cb, kTimeoutRegister);
650 if (error.IsFailure())
651 callback.Run(error);
652}
653
654void CellularCapabilityUniversal::RegisterOnNetwork(
655 const string &network_id,
656 Error *error,
657 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700658 SLOG(Cellular, 2) << __func__ << "(" << network_id << ")";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400659 CHECK(error);
660 desired_network_ = network_id;
661 ResultCallback cb = Bind(&CellularCapabilityUniversal::OnRegisterReply,
662 weak_ptr_factory_.GetWeakPtr(), callback);
663 modem_3gpp_proxy_->Register(network_id, error, cb, kTimeoutRegister);
664}
665
666void CellularCapabilityUniversal::OnRegisterReply(
667 const ResultCallback &callback,
668 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700669 SLOG(Cellular, 2) << __func__ << "(" << error << ")";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400670
671 if (error.IsSuccess()) {
672 selected_network_ = desired_network_;
673 desired_network_.clear();
674 callback.Run(error);
675 return;
676 }
677 // If registration on the desired network failed,
678 // try to register on the home network.
679 if (!desired_network_.empty()) {
680 desired_network_.clear();
681 selected_network_.clear();
682 LOG(INFO) << "Couldn't register on selected network, trying home network";
683 Register(callback);
684 return;
685 }
686 callback.Run(error);
687}
688
689bool CellularCapabilityUniversal::IsRegistered() {
690 return (registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
691 registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING);
692}
693
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400694void CellularCapabilityUniversal::SetUnregistered(bool searching) {
695 // If we're already in some non-registered state, don't override that
696 if (registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
697 registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
698 registration_state_ =
699 (searching ? MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING :
700 MM_MODEM_3GPP_REGISTRATION_STATE_IDLE);
701 }
702}
703
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400704void CellularCapabilityUniversal::RequirePIN(
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400705 const string &pin, bool require,
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400706 Error *error, const ResultCallback &callback) {
707 CHECK(error);
708 sim_proxy_->EnablePin(pin, require, error, callback, kTimeoutDefault);
709}
710
711void CellularCapabilityUniversal::EnterPIN(const string &pin,
712 Error *error,
713 const ResultCallback &callback) {
714 CHECK(error);
715 sim_proxy_->SendPin(pin, error, callback, kTimeoutDefault);
716}
717
718void CellularCapabilityUniversal::UnblockPIN(const string &unblock_code,
719 const string &pin,
720 Error *error,
721 const ResultCallback &callback) {
722 CHECK(error);
723 sim_proxy_->SendPuk(unblock_code, pin, error, callback, kTimeoutDefault);
724}
725
726void CellularCapabilityUniversal::ChangePIN(
727 const string &old_pin, const string &new_pin,
728 Error *error, const ResultCallback &callback) {
729 CHECK(error);
730 sim_proxy_->ChangePin(old_pin, new_pin, error, callback, kTimeoutDefault);
731}
732
733void CellularCapabilityUniversal::Scan(Error *error,
734 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700735 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400736 // TODO(petkov): Defer scan requests if a scan is in progress already.
737 CHECK(error);
738 DBusPropertyMapsCallback cb = Bind(&CellularCapabilityUniversal::OnScanReply,
739 weak_ptr_factory_.GetWeakPtr(), callback);
740 modem_3gpp_proxy_->Scan(error, cb, kTimeoutScan);
741}
742
743void CellularCapabilityUniversal::OnScanReply(const ResultCallback &callback,
744 const ScanResults &results,
745 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700746 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400747
748 // Error handling is weak. The current expectation is that on any
749 // error, found_networks_ should be cleared and a property change
750 // notification sent out.
751 //
752 // TODO(jglasgow): fix error handling
753 found_networks_.clear();
754 if (!error.IsFailure()) {
755 for (ScanResults::const_iterator it = results.begin();
756 it != results.end(); ++it) {
757 found_networks_.push_back(ParseScanResult(*it));
758 }
759 }
760 cellular()->adaptor()->EmitStringmapsChanged(flimflam::kFoundNetworksProperty,
761 found_networks_);
762 callback.Run(error);
763}
764
765Stringmap CellularCapabilityUniversal::ParseScanResult(
766 const ScanResult &result) {
767
768 static const char kStatusProperty[] = "status";
769 static const char kOperatorLongProperty[] = "operator-long";
770 static const char kOperatorShortProperty[] = "operator-short";
771 static const char kOperatorCodeProperty[] = "operator-code";
772 static const char kOperatorAccessTechnologyProperty[] = "access-technology";
773
774 /* ScanResults contain the following keys:
775
776 "status"
777 A MMModem3gppNetworkAvailability value representing network
778 availability status, given as an unsigned integer (signature "u").
779 This key will always be present.
780
781 "operator-long"
782 Long-format name of operator, given as a string value (signature
783 "s"). If the name is unknown, this field should not be present.
784
785 "operator-short"
786 Short-format name of operator, given as a string value
787 (signature "s"). If the name is unknown, this field should not
788 be present.
789
790 "operator-code"
791 Mobile code of the operator, given as a string value (signature
792 "s"). Returned in the format "MCCMNC", where MCC is the
793 three-digit ITU E.212 Mobile Country Code and MNC is the two- or
794 three-digit GSM Mobile Network Code. e.g. "31026" or "310260".
795
796 "access-technology"
797 A MMModemAccessTechnology value representing the generic access
798 technology used by this mobile network, given as an unsigned
799 integer (signature "u").
800 */
801 Stringmap parsed;
802
803 uint32 status;
804 if (DBusProperties::GetUint32(result, kStatusProperty, &status)) {
805 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
806 static const char * const kStatusString[] = {
807 "unknown", // MM_MODEM_3GPP_NETWORK_AVAILABILITY_UNKNOWN
808 "available", // MM_MODEM_3GPP_NETWORK_AVAILABILITY_AVAILABLE
809 "current", // MM_MODEM_3GPP_NETWORK_AVAILABILITY_CURRENT
810 "forbidden", // MM_MODEM_3GPP_NETWORK_AVAILABILITY_FORBIDDEN
811 };
812 parsed[flimflam::kStatusProperty] = kStatusString[status];
813 }
814
815 uint32 tech; // MMModemAccessTechnology
816 if (DBusProperties::GetUint32(result, kOperatorAccessTechnologyProperty,
817 &tech)) {
818 parsed[flimflam::kTechnologyProperty] = AccessTechnologyToString(tech);
819 }
820
821 string operator_long, operator_short, operator_code;
822 if (DBusProperties::GetString(result, kOperatorLongProperty, &operator_long))
823 parsed[flimflam::kLongNameProperty] = operator_long;
824 if (DBusProperties::GetString(result, kOperatorShortProperty,
825 &operator_short))
826 parsed[flimflam::kShortNameProperty] = operator_short;
827 if (DBusProperties::GetString(result, kOperatorCodeProperty, &operator_code))
828 parsed[flimflam::kNetworkIdProperty] = operator_code;
829
830 // If the long name is not available but the network ID is, look up the long
831 // name in the mobile provider database.
832 if ((!ContainsKey(parsed, flimflam::kLongNameProperty) ||
833 parsed[flimflam::kLongNameProperty].empty()) &&
834 ContainsKey(parsed, flimflam::kNetworkIdProperty)) {
835 mobile_provider *provider =
836 mobile_provider_lookup_by_network(
837 cellular()->provider_db(),
838 parsed[flimflam::kNetworkIdProperty].c_str());
839 if (provider) {
840 const char *long_name = mobile_provider_get_name(provider);
841 if (long_name && *long_name) {
842 parsed[flimflam::kLongNameProperty] = long_name;
843 }
844 }
845 }
846 return parsed;
847}
848
849void CellularCapabilityUniversal::SetAccessTechnologies(
850 uint32 access_technologies) {
851 access_technologies_ = access_technologies;
852 if (cellular()->service().get()) {
853 cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString());
854 }
855}
856
857string CellularCapabilityUniversal::GetNetworkTechnologyString() const {
858 // Order is imnportant. Return the highest speed technology
859 // TODO(jglasgow): change shill interfaces to a capability model
860
861 return AccessTechnologyToString(access_technologies_);
862}
863
864string CellularCapabilityUniversal::GetRoamingStateString() const {
865 switch (registration_state_) {
866 case MM_MODEM_3GPP_REGISTRATION_STATE_HOME:
867 return flimflam::kRoamingStateHome;
868 case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING:
869 return flimflam::kRoamingStateRoaming;
870 default:
871 break;
872 }
873 return flimflam::kRoamingStateUnknown;
874}
875
876void CellularCapabilityUniversal::GetSignalQuality() {
Nathan Williams218cbcd2012-04-17 16:48:44 -0400877 // TODO(njw): Switch to asynchronous calls (crosbug.com/17583).
878 const DBus::Struct<unsigned int, bool> quality =
879 modem_proxy_->SignalQuality();
880 OnSignalQualityChanged(quality._1);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400881}
882
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400883void CellularCapabilityUniversal::OnModemPropertiesChanged(
884 const DBusPropertiesMap &properties,
885 const vector<string> &/* invalidated_properties */) {
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400886 // This solves a bootstrapping problem: If the modem is not yet
887 // enabled, there are no proxy objects associated with the capability
888 // object, so modem signals like StateChanged aren't seen. By monitoring
889 // changes to the State property via the ModemManager, we're able to
890 // get the initialization process started, which will result in the
891 // creation of the proxy objects.
892 //
893 // The first time we see the change to State (when the modem state
894 // is Unknown), we simply update the state, and rely on the Manager to
895 // enable the device when it is registered with the Manager. On subsequent
896 // changes to State, we need to explicitly enable the device ourselves.
897 int32 istate;
898 if (DBusProperties::GetInt32(properties, kModemPropertyState, &istate)) {
899 Cellular::ModemState state = static_cast<Cellular::ModemState>(istate);
900 Cellular::ModemState prev_modem_state = cellular()->modem_state();
901 bool was_enabled = cellular()->IsUnderlyingDeviceEnabled();
902 if (Cellular::IsEnabledModemState(state))
903 cellular()->set_modem_state(state);
904 if (prev_modem_state != Cellular::kModemStateUnknown &&
905 prev_modem_state != Cellular::kModemStateEnabling &&
906 !was_enabled &&
907 cellular()->state() == Cellular::kStateDisabled &&
908 cellular()->IsUnderlyingDeviceEnabled()) {
909 cellular()->SetEnabled(true);
910 }
911 }
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400912 string value;
Nathan Williamse9840802012-04-18 18:47:40 -0400913 if (DBusProperties::GetObjectPath(properties,
914 MM_MODEM_PROPERTY_SIM, &value))
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400915 OnSimPathChanged(value);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400916
917 uint32 access_technologies = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN;
918 if (DBusProperties::GetUint32(properties,
919 MM_MODEM_PROPERTY_ACCESSTECHNOLOGIES,
920 &access_technologies)) {
921 SetAccessTechnologies(access_technologies);
922 }
Nathan Williams218cbcd2012-04-17 16:48:44 -0400923
924 DBusPropertiesMap::const_iterator it =
925 properties.find(MM_MODEM_PROPERTY_SIGNALQUALITY);
926 if (it != properties.end()) {
927 DBus::Struct<unsigned int, bool> quality =
928 static_cast<DBus::Variant>(it->second);
929 OnSignalQualityChanged(quality._1);
930 }
931
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400932 // Unlockrequired and SimLock
933 bool emit = false;
934
935 uint32_t lock_required; // This is really of type MMModemLock
936 if (DBusProperties::GetUint32(properties,
937 MM_MODEM_PROPERTY_UNLOCKREQUIRED,
938 &lock_required)) {
939 // TODO(jglasgow): set sim_lock_status_.lock_type
940 emit = true;
941 }
942 // TODO(jglasgow): Update PIN retries which are a{uu} and require parsing
943 // Get the property MM_MODEM_PROPERTY_UNLOCKRETRIES
944 // Set sim_lock_status_.retries_left
945
946 if (emit) {
947 cellular()->adaptor()->EmitKeyValueStoreChanged(
948 flimflam::kSIMLockStatusProperty, SimLockStatusToProperty(NULL));
949 }
950}
951
952void CellularCapabilityUniversal::OnDBusPropertiesChanged(
953 const string &interface,
954 const DBusPropertiesMap &changed_properties,
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400955 const vector<string> &invalidated_properties) {
Jason Glasgowef965562012-04-10 16:12:35 -0400956 if (interface == MM_DBUS_INTERFACE_MODEM) {
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400957 OnModemPropertiesChanged(changed_properties, invalidated_properties);
Jason Glasgowef965562012-04-10 16:12:35 -0400958 }
959 // TODO(jglasgow): handle additional interfaces
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400960}
961
962void CellularCapabilityUniversal::OnModem3GPPPropertiesChanged(
963 const DBusPropertiesMap &properties) {
964 bool emit = false;
965 uint32 locks = 0;
966 if (DBusProperties::GetUint32(
967 properties, MM_MODEM_MODEM3GPP_PROPERTY_ENABLEDFACILITYLOCKS,
968 &locks)) {
969 sim_lock_status_.enabled = locks & MM_MODEM_3GPP_FACILITY_SIM;
970 emit = true;
971 }
972 // TODO(jglasgow): coordinate with changes to Modem properties
973 if (emit) {
974 cellular()->adaptor()->EmitKeyValueStoreChanged(
975 flimflam::kSIMLockStatusProperty, SimLockStatusToProperty(NULL));
976 }
977}
978
979void CellularCapabilityUniversal::OnNetworkModeSignal(uint32 /*mode*/) {
980 // TODO(petkov): Implement this.
981 NOTIMPLEMENTED();
982}
983
984void CellularCapabilityUniversal::On3GPPRegistrationChanged(
985 MMModem3gppRegistrationState state,
986 const string &operator_code,
987 const string &operator_name) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700988 SLOG(Cellular, 2) << __func__ << ": regstate=" << state
989 << ", opercode=" << operator_code
990 << ", opername=" << operator_name;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400991 registration_state_ = state;
992 serving_operator_.SetCode(operator_code);
993 serving_operator_.SetName(operator_name);
994 UpdateOperatorInfo();
995 cellular()->HandleNewRegistrationState();
996}
997
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400998void CellularCapabilityUniversal::OnModemStateChangedSignal(
999 int32 old_state, int32 new_state, uint32 reason) {
Eric Shienbrood9b1bd7b2012-04-20 16:42:26 -04001000 SLOG(Cellular, 2) << __func__ << "(" << old_state << ", " << new_state << ", "
1001 << reason << ")";
Eric Shienbrood7fce52c2012-04-13 19:11:02 -04001002 cellular()->OnModemStateChanged(static_cast<Cellular::ModemState>(old_state),
1003 static_cast<Cellular::ModemState>(new_state),
1004 reason);
1005}
1006
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001007void CellularCapabilityUniversal::OnSignalQualityChanged(uint32 quality) {
1008 cellular()->HandleNewSignalQuality(quality);
1009}
1010
Jason Glasgowef965562012-04-10 16:12:35 -04001011void CellularCapabilityUniversal::OnSimPathChanged(
1012 const string &sim_path) {
1013 if (sim_path == sim_path_)
1014 return;
1015
1016 mm1::SimProxyInterface *proxy = NULL;
1017 if (!sim_path.empty())
1018 proxy = proxy_factory()->CreateSimProxy(sim_path,
1019 cellular()->dbus_owner());
1020 sim_path_ = sim_path;
1021 sim_proxy_.reset(proxy);
1022}
1023
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001024} // namespace shill