blob: 23d6f87979c09df00b804a90da4b95c2ad53281d [file] [log] [blame]
Darin Petkovc64fe5e2012-01-11 12:46:13 +01001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Darin Petkovdaf43862011-10-27 11:37:28 +02002// 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_gsm.h"
6
Jason Glasgow4c0724a2012-04-17 15:47:40 -04007#include <string>
8#include <vector>
9
Eric Shienbrood3e20a232012-02-16 11:35:56 -050010#include <base/bind.h>
Eric Shienbrood3e20a232012-02-16 11:35:56 -050011#include <base/stl_util.h>
Ben Chana0ddf462014-02-06 11:32:42 -080012#include <base/strings/string_number_conversions.h>
13#include <base/strings/stringprintf.h>
Darin Petkov20c13ec2011-11-09 15:07:15 +010014#include <chromeos/dbus/service_constants.h>
15#include <mm/mm-modem.h>
Darin Petkovdaf43862011-10-27 11:37:28 +020016
Darin Petkov3cfbf212011-11-21 16:02:09 +010017#include "shill/adaptor_interfaces.h"
Darin Petkovae0c64e2011-11-15 15:50:27 +010018#include "shill/cellular_service.h"
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050019#include "shill/error.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070020#include "shill/logging.h"
Darin Petkov721ac932011-11-16 15:43:09 +010021#include "shill/property_accessor.h"
Darin Petkovdaf43862011-10-27 11:37:28 +020022#include "shill/proxy_factory.h"
23
Eric Shienbrood3e20a232012-02-16 11:35:56 -050024using base::Bind;
Darin Petkovb05315f2011-11-07 10:14:25 +010025using std::string;
Jason Glasgow4c0724a2012-04-17 15:47:40 -040026using std::vector;
Darin Petkovb05315f2011-11-07 10:14:25 +010027
Darin Petkovdaf43862011-10-27 11:37:28 +020028namespace shill {
29
Darin Petkovac635a82012-01-10 16:51:58 +010030// static
Darin Petkov1272a432011-11-10 15:53:37 +010031const char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] =
32 "access-tech";
33const char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num";
34const char CellularCapabilityGSM::kNetworkPropertyLongName[] = "operator-long";
35const char CellularCapabilityGSM::kNetworkPropertyShortName[] =
36 "operator-short";
37const char CellularCapabilityGSM::kNetworkPropertyStatus[] = "status";
Darin Petkovae0c64e2011-11-15 15:50:27 +010038const char CellularCapabilityGSM::kPhoneNumber[] = "*99#";
39const char CellularCapabilityGSM::kPropertyAccessTechnology[] =
40 "AccessTechnology";
Darin Petkov63138a92012-02-06 14:09:15 +010041const char CellularCapabilityGSM::kPropertyEnabledFacilityLocks[] =
42 "EnabledFacilityLocks";
Darin Petkov721ac932011-11-16 15:43:09 +010043const char CellularCapabilityGSM::kPropertyUnlockRequired[] = "UnlockRequired";
44const char CellularCapabilityGSM::kPropertyUnlockRetries[] = "UnlockRetries";
Darin Petkov1272a432011-11-10 15:53:37 +010045
Ben Chanc89b9282012-12-12 14:00:29 -080046const int CellularCapabilityGSM::kGetIMSIRetryLimit = 40;
Ben Chan7fab8972014-08-10 17:14:46 -070047const int64_t CellularCapabilityGSM::kGetIMSIRetryDelayMilliseconds = 500;
Gary Morain82a31a02012-08-02 18:03:32 -070048
49
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050050CellularCapabilityGSM::CellularCapabilityGSM(Cellular *cellular,
Thieu Lece4483e2013-01-23 15:12:03 -080051 ProxyFactory *proxy_factory,
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070052 ModemInfo *modem_info)
53 : CellularCapabilityClassic(cellular, proxy_factory, modem_info),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050054 weak_ptr_factory_(this),
Prathmesh Prabhuafe63662014-05-20 11:03:58 -070055 mobile_operator_info_(new MobileOperatorInfo(cellular->dispatcher(),
56 "ParseScanResult")),
Darin Petkov184c54e2011-11-15 12:44:39 +010057 registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
Darin Petkovae0c64e2011-11-15 15:50:27 +010058 access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN),
Prathmesh Prabhu99ec94d2013-11-22 10:43:37 -080059 home_provider_info_(NULL),
Gary Morain82a31a02012-08-02 18:03:32 -070060 get_imsi_retries_(0),
Prathmesh Prabhu49ffffd2014-01-09 18:28:55 -080061 get_imsi_retry_delay_milliseconds_(kGetIMSIRetryDelayMilliseconds) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070062 SLOG(Cellular, 2) << "Cellular capability constructed: GSM";
Prathmesh Prabhuafe63662014-05-20 11:03:58 -070063 mobile_operator_info_->Init();
mukesh agrawalbebf1b82013-04-23 15:06:33 -070064 HelpRegisterConstDerivedKeyValueStore(
Ben Chan7ea768e2013-09-20 15:08:40 -070065 kSIMLockStatusProperty, &CellularCapabilityGSM::SimLockStatusToProperty);
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -080066 this->cellular()->set_scanning_supported(true);
Ben Chan3ecdf822012-08-06 12:29:23 -070067
68 // TODO(benchan): This is a hack to initialize the GSM card proxy for GetIMSI
69 // before InitProxies is called. There are side-effects of calling InitProxies
70 // before the device is enabled. It's better to refactor InitProxies such that
71 // proxies can be created when the cellular device/capability is constructed,
72 // but callbacks for DBus signal updates are not set up until the device is
73 // enabled.
74 card_proxy_.reset(
75 proxy_factory->CreateModemGSMCardProxy(cellular->dbus_path(),
76 cellular->dbus_owner()));
77 // TODO(benchan): To allow unit testing using a mock proxy without further
78 // complicating the code, the test proxy factory is set up to return a NULL
79 // pointer when CellularCapabilityGSM is constructed. Refactor the code to
80 // avoid this hack.
81 if (card_proxy_.get())
82 InitProperties();
Darin Petkov1272a432011-11-10 15:53:37 +010083}
Darin Petkovdaf43862011-10-27 11:37:28 +020084
Ben Chanf98f00e2014-02-05 14:48:43 -080085CellularCapabilityGSM::~CellularCapabilityGSM() {}
86
87string CellularCapabilityGSM::GetTypeString() const {
88 return kTechnologyFamilyGsm;
89}
90
Darin Petkov63138a92012-02-06 14:09:15 +010091KeyValueStore CellularCapabilityGSM::SimLockStatusToProperty(Error */*error*/) {
92 KeyValueStore status;
Ben Chan7ea768e2013-09-20 15:08:40 -070093 status.SetBool(kSIMLockEnabledProperty, sim_lock_status_.enabled);
94 status.SetString(kSIMLockTypeProperty, sim_lock_status_.lock_type);
95 status.SetUint(kSIMLockRetriesLeftProperty, sim_lock_status_.retries_left);
Darin Petkov63138a92012-02-06 14:09:15 +010096 return status;
Darin Petkov721ac932011-11-16 15:43:09 +010097}
98
mukesh agrawalbebf1b82013-04-23 15:06:33 -070099void CellularCapabilityGSM::HelpRegisterConstDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +0100100 const string &name,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700101 KeyValueStore(CellularCapabilityGSM::*get)(Error *error)) {
Darin Petkov63138a92012-02-06 14:09:15 +0100102 cellular()->mutable_store()->RegisterDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +0100103 name,
Darin Petkov63138a92012-02-06 14:09:15 +0100104 KeyValueStoreAccessor(
105 new CustomAccessor<CellularCapabilityGSM, KeyValueStore>(
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700106 this, get, NULL)));
Darin Petkov721ac932011-11-16 15:43:09 +0100107}
108
Eric Shienbrood9a245532012-03-07 14:20:39 -0500109void CellularCapabilityGSM::InitProxies() {
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400110 CellularCapabilityClassic::InitProxies();
Ben Chan3ecdf822012-08-06 12:29:23 -0700111 // TODO(benchan): Remove this check after refactoring the proxy
112 // initialization.
113 if (!card_proxy_.get()) {
114 card_proxy_.reset(
115 proxy_factory()->CreateModemGSMCardProxy(cellular()->dbus_path(),
116 cellular()->dbus_owner()));
117 }
Darin Petkov184c54e2011-11-15 12:44:39 +0100118 network_proxy_.reset(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500119 proxy_factory()->CreateModemGSMNetworkProxy(cellular()->dbus_path(),
Darin Petkovdaf43862011-10-27 11:37:28 +0200120 cellular()->dbus_owner()));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500121 network_proxy_->set_signal_quality_callback(
122 Bind(&CellularCapabilityGSM::OnSignalQualitySignal,
123 weak_ptr_factory_.GetWeakPtr()));
124 network_proxy_->set_network_mode_callback(
125 Bind(&CellularCapabilityGSM::OnNetworkModeSignal,
126 weak_ptr_factory_.GetWeakPtr()));
127 network_proxy_->set_registration_info_callback(
128 Bind(&CellularCapabilityGSM::OnRegistrationInfoSignal,
129 weak_ptr_factory_.GetWeakPtr()));
Darin Petkovdaf43862011-10-27 11:37:28 +0200130}
131
Ben Chan3ecdf822012-08-06 12:29:23 -0700132void CellularCapabilityGSM::InitProperties() {
133 CellularTaskList *tasks = new CellularTaskList();
134 ResultCallback cb_ignore_error =
135 Bind(&CellularCapabilityGSM::StepCompletedCallback,
136 weak_ptr_factory_.GetWeakPtr(), ResultCallback(), true, tasks);
Ben Chanbd3aee82012-10-16 23:52:04 -0700137 // Chrome checks if a SIM is present before allowing the modem to be enabled,
138 // so shill needs to obtain IMSI, as an indicator of SIM presence, even
139 // before the device is enabled.
Ben Chan3ecdf822012-08-06 12:29:23 -0700140 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMSI,
141 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
142 RunNextStep(tasks);
143}
144
Eric Shienbrood9a245532012-03-07 14:20:39 -0500145void CellularCapabilityGSM::StartModem(Error *error,
146 const ResultCallback &callback) {
147 InitProxies();
148
149 CellularTaskList *tasks = new CellularTaskList();
150 ResultCallback cb =
151 Bind(&CellularCapabilityGSM::StepCompletedCallback,
Thieu Le923006b2012-04-05 16:32:58 -0700152 weak_ptr_factory_.GetWeakPtr(), callback, false, tasks);
153 ResultCallback cb_ignore_error =
154 Bind(&CellularCapabilityGSM::StepCompletedCallback,
155 weak_ptr_factory_.GetWeakPtr(), callback, true, tasks);
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400156 if (!cellular()->IsUnderlyingDeviceEnabled())
157 tasks->push_back(Bind(&CellularCapabilityGSM::EnableModem,
158 weak_ptr_factory_.GetWeakPtr(), cb));
159 // If we're within range of the home network, the modem will try to
160 // register once it's enabled, or may be already registered if we
161 // started out enabled.
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800162 if (!IsUnderlyingDeviceRegistered() &&
163 !cellular()->selected_network().empty())
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400164 tasks->push_back(Bind(&CellularCapabilityGSM::Register,
165 weak_ptr_factory_.GetWeakPtr(), cb));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500166 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMEI,
167 weak_ptr_factory_.GetWeakPtr(), cb));
Gary Morain82a31a02012-08-02 18:03:32 -0700168 get_imsi_retries_ = 0;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500169 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMSI,
170 weak_ptr_factory_.GetWeakPtr(), cb));
171 tasks->push_back(Bind(&CellularCapabilityGSM::GetSPN,
Thieu Le923006b2012-04-05 16:32:58 -0700172 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500173 tasks->push_back(Bind(&CellularCapabilityGSM::GetMSISDN,
Thieu Le923006b2012-04-05 16:32:58 -0700174 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500175 tasks->push_back(Bind(&CellularCapabilityGSM::GetProperties,
176 weak_ptr_factory_.GetWeakPtr(), cb));
177 tasks->push_back(Bind(&CellularCapabilityGSM::GetModemInfo,
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400178 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500179 tasks->push_back(Bind(&CellularCapabilityGSM::FinishEnable,
180 weak_ptr_factory_.GetWeakPtr(), cb));
181
182 RunNextStep(tasks);
183}
184
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400185bool CellularCapabilityGSM::IsUnderlyingDeviceRegistered() const {
186 switch (cellular()->modem_state()) {
Ben Chan7b7d63d2013-10-18 14:53:05 -0700187 case Cellular::kModemStateFailed:
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400188 case Cellular::kModemStateUnknown:
189 case Cellular::kModemStateDisabled:
190 case Cellular::kModemStateInitializing:
191 case Cellular::kModemStateLocked:
192 case Cellular::kModemStateDisabling:
193 case Cellular::kModemStateEnabling:
194 case Cellular::kModemStateEnabled:
195 return false;
196 case Cellular::kModemStateSearching:
197 case Cellular::kModemStateRegistered:
198 case Cellular::kModemStateDisconnecting:
199 case Cellular::kModemStateConnecting:
200 case Cellular::kModemStateConnected:
201 return true;
202 }
203 return false;
204}
205
Eric Shienbrood9a245532012-03-07 14:20:39 -0500206void CellularCapabilityGSM::ReleaseProxies() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700207 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400208 CellularCapabilityClassic::ReleaseProxies();
Darin Petkov721ac932011-11-16 15:43:09 +0100209 card_proxy_.reset();
210 network_proxy_.reset();
211}
212
Thieu Le63881a72014-07-28 17:28:36 -0700213bool CellularCapabilityGSM::AreProxiesInitialized() const {
214 return (CellularCapabilityClassic::AreProxiesInitialized() &&
215 card_proxy_.get() && network_proxy_.get());
216}
217
Darin Petkov5f316f62011-11-18 12:10:26 +0100218void CellularCapabilityGSM::OnServiceCreated() {
Ben Chan7ea768e2013-09-20 15:08:40 -0700219 cellular()->service()->SetActivationState(kActivationStateActivated);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100220}
221
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400222// Create the list of APNs to try, in the following order:
223// - last APN that resulted in a successful connection attempt on the
224// current network (if any)
225// - the APN, if any, that was set by the user
226// - the list of APNs found in the mobile broadband provider DB for the
227// home provider associated with the current SIM
228// - as a last resort, attempt to connect with no APN
229void CellularCapabilityGSM::SetupApnTryList() {
230 apn_try_list_.clear();
231
232 DCHECK(cellular()->service().get());
233 const Stringmap *apn_info = cellular()->service()->GetLastGoodApn();
234 if (apn_info)
235 apn_try_list_.push_back(*apn_info);
236
237 apn_info = cellular()->service()->GetUserSpecifiedApn();
238 if (apn_info)
239 apn_try_list_.push_back(*apn_info);
240
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800241 apn_try_list_.insert(apn_try_list_.end(),
242 cellular()->apn_list().begin(),
243 cellular()->apn_list().end());
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400244}
245
Darin Petkovae0c64e2011-11-15 15:50:27 +0100246void CellularCapabilityGSM::SetupConnectProperties(
247 DBusPropertiesMap *properties) {
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400248 SetupApnTryList();
249 FillConnectPropertyMap(properties);
250}
251
252void CellularCapabilityGSM::FillConnectPropertyMap(
253 DBusPropertiesMap *properties) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500254 (*properties)[kConnectPropertyPhoneNumber].writer().append_string(
Darin Petkovae0c64e2011-11-15 15:50:27 +0100255 kPhoneNumber);
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400256
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400257 if (!AllowRoaming())
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400258 (*properties)[kConnectPropertyHomeOnly].writer().append_bool(true);
259
260 if (!apn_try_list_.empty()) {
261 // Leave the APN at the front of the list, so that it can be recorded
262 // if the connect attempt succeeds.
263 Stringmap apn_info = apn_try_list_.front();
Ben Chan7ea768e2013-09-20 15:08:40 -0700264 SLOG(Cellular, 2) << __func__ << ": Using APN " << apn_info[kApnProperty];
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400265 (*properties)[kConnectPropertyApn].writer().append_string(
Ben Chan7ea768e2013-09-20 15:08:40 -0700266 apn_info[kApnProperty].c_str());
267 if (ContainsKey(apn_info, kApnUsernameProperty))
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400268 (*properties)[kConnectPropertyApnUsername].writer().append_string(
Ben Chan7ea768e2013-09-20 15:08:40 -0700269 apn_info[kApnUsernameProperty].c_str());
270 if (ContainsKey(apn_info, kApnPasswordProperty))
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400271 (*properties)[kConnectPropertyApnPassword].writer().append_string(
Ben Chan7ea768e2013-09-20 15:08:40 -0700272 apn_info[kApnPasswordProperty].c_str());
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400273 }
274}
275
Nathan Williamsb54974f2012-04-19 11:16:30 -0400276void CellularCapabilityGSM::Connect(const DBusPropertiesMap &properties,
277 Error *error,
278 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700279 SLOG(Cellular, 2) << __func__;
Nathan Williamsb54974f2012-04-19 11:16:30 -0400280 ResultCallback cb = Bind(&CellularCapabilityGSM::OnConnectReply,
281 weak_ptr_factory_.GetWeakPtr(),
282 callback);
283 simple_proxy_->Connect(properties, error, cb, kTimeoutConnect);
284}
285
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400286void CellularCapabilityGSM::OnConnectReply(const ResultCallback &callback,
287 const Error &error) {
Thieu Leb5954a22012-05-18 10:37:34 -0700288 CellularServiceRefPtr service = cellular()->service();
289 if (!service) {
290 // The service could have been deleted before our Connect() request
291 // completes if the modem was enabled and then quickly disabled.
292 apn_try_list_.clear();
293 } else if (error.IsFailure()) {
294 service->ClearLastGoodApn();
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400295 // The APN that was just tried (and failed) is still at the
296 // front of the list, about to be removed. If the list is empty
297 // after that, try one last time without an APN. This may succeed
298 // with some modems in some cases.
299 if (error.type() == Error::kInvalidApn && !apn_try_list_.empty()) {
300 apn_try_list_.pop_front();
Ben Chanfad4a0b2012-04-18 15:49:59 -0700301 SLOG(Cellular, 2) << "Connect failed with invalid APN, "
302 << apn_try_list_.size() << " remaining APNs to try";
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400303 DBusPropertiesMap props;
304 FillConnectPropertyMap(&props);
305 Error error;
306 Connect(props, &error, callback);
307 return;
308 }
309 } else if (!apn_try_list_.empty()) {
Thieu Leb5954a22012-05-18 10:37:34 -0700310 service->SetLastGoodApn(apn_try_list_.front());
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400311 apn_try_list_.clear();
312 }
Nathan Williamsb54974f2012-04-19 11:16:30 -0400313 if (!callback.is_null())
314 callback.Run(error);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400315}
316
317bool CellularCapabilityGSM::AllowRoaming() {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800318 return cellular()->provider_requires_roaming() || allow_roaming_property();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100319}
320
Eric Shienbrood9a245532012-03-07 14:20:39 -0500321// always called from an async context
322void CellularCapabilityGSM::GetIMEI(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700323 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500324 CHECK(!callback.is_null());
325 Error error;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800326 if (cellular()->imei().empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500327 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMEIReply,
328 weak_ptr_factory_.GetWeakPtr(), callback);
329 card_proxy_->GetIMEI(&error, cb, kTimeoutDefault);
330 if (error.IsFailure())
331 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500332 } else {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800333 SLOG(Cellular, 2) << "Already have IMEI " << cellular()->imei();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500334 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100335 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500336}
337
Eric Shienbrood9a245532012-03-07 14:20:39 -0500338// always called from an async context
339void CellularCapabilityGSM::GetIMSI(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700340 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500341 CHECK(!callback.is_null());
342 Error error;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800343 if (cellular()->imsi().empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500344 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMSIReply,
345 weak_ptr_factory_.GetWeakPtr(),
346 callback);
347 card_proxy_->GetIMSI(&error, cb, kTimeoutDefault);
Prathmesh Prabhu28b4a3b2014-03-28 11:52:09 -0700348 if (error.IsFailure()) {
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700349 cellular()->home_provider_info()->Reset();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500350 callback.Run(error);
Prathmesh Prabhu28b4a3b2014-03-28 11:52:09 -0700351 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500352 } else {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800353 SLOG(Cellular, 2) << "Already have IMSI " << cellular()->imsi();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500354 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100355 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500356}
357
Eric Shienbrood9a245532012-03-07 14:20:39 -0500358// always called from an async context
359void CellularCapabilityGSM::GetSPN(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700360 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500361 CHECK(!callback.is_null());
362 Error error;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100363 if (spn_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500364 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetSPNReply,
365 weak_ptr_factory_.GetWeakPtr(),
366 callback);
367 card_proxy_->GetSPN(&error, cb, kTimeoutDefault);
368 if (error.IsFailure())
369 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500370 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700371 SLOG(Cellular, 2) << "Already have SPN " << spn_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500372 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100373 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500374}
375
Eric Shienbrood9a245532012-03-07 14:20:39 -0500376// always called from an async context
377void CellularCapabilityGSM::GetMSISDN(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700378 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500379 CHECK(!callback.is_null());
380 Error error;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800381 string mdn = cellular()->mdn();
382 if (mdn.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500383 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetMSISDNReply,
384 weak_ptr_factory_.GetWeakPtr(),
385 callback);
386 card_proxy_->GetMSISDN(&error, cb, kTimeoutDefault);
387 if (error.IsFailure())
388 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500389 } else {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800390 SLOG(Cellular, 2) << "Already have MSISDN " << mdn;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500391 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100392 }
393}
394
Darin Petkov3e509242011-11-10 14:46:44 +0100395void CellularCapabilityGSM::GetSignalQuality() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700396 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500397 SignalQualityCallback callback =
398 Bind(&CellularCapabilityGSM::OnGetSignalQualityReply,
399 weak_ptr_factory_.GetWeakPtr());
400 network_proxy_->GetSignalQuality(NULL, callback, kTimeoutDefault);
Darin Petkov3e509242011-11-10 14:46:44 +0100401}
402
Eric Shienbrood9a245532012-03-07 14:20:39 -0500403void CellularCapabilityGSM::GetRegistrationState() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700404 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500405 RegistrationInfoCallback callback =
406 Bind(&CellularCapabilityGSM::OnGetRegistrationInfoReply,
407 weak_ptr_factory_.GetWeakPtr());
408 network_proxy_->GetRegistrationInfo(NULL, callback, kTimeoutDefault);
Darin Petkov184c54e2011-11-15 12:44:39 +0100409}
410
Eric Shienbrood9a245532012-03-07 14:20:39 -0500411void CellularCapabilityGSM::GetProperties(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700412 SLOG(Cellular, 2) << __func__;
Darin Petkov63138a92012-02-06 14:09:15 +0100413
Paul Stewartee6b3d72013-07-12 16:07:51 -0700414 // TODO(petkov): Switch to asynchronous calls (crbug.com/200687).
Ben Chan7fab8972014-08-10 17:14:46 -0700415 uint32_t tech = network_proxy_->AccessTechnology();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100416 SetAccessTechnology(tech);
Ben Chanfad4a0b2012-04-18 15:49:59 -0700417 SLOG(Cellular, 2) << "GSM AccessTechnology: " << tech;
Darin Petkov63138a92012-02-06 14:09:15 +0100418
Paul Stewartee6b3d72013-07-12 16:07:51 -0700419 // TODO(petkov): Switch to asynchronous calls (crbug.com/200687).
Ben Chan7fab8972014-08-10 17:14:46 -0700420 uint32_t locks = card_proxy_->EnabledFacilityLocks();
Darin Petkov63138a92012-02-06 14:09:15 +0100421 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
Ben Chanfad4a0b2012-04-18 15:49:59 -0700422 SLOG(Cellular, 2) << "GSM EnabledFacilityLocks: " << locks;
Darin Petkov63138a92012-02-06 14:09:15 +0100423
Eric Shienbrood9a245532012-03-07 14:20:39 -0500424 callback.Run(Error());
Darin Petkov184c54e2011-11-15 12:44:39 +0100425}
426
Eric Shienbrood9a245532012-03-07 14:20:39 -0500427// always called from an async context
428void CellularCapabilityGSM::Register(const ResultCallback &callback) {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800429 SLOG(Cellular, 2) << __func__ << " \"" << cellular()->selected_network()
430 << "\"";
Eric Shienbrood9a245532012-03-07 14:20:39 -0500431 CHECK(!callback.is_null());
432 Error error;
433 ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply,
434 weak_ptr_factory_.GetWeakPtr(), callback);
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800435 network_proxy_->Register(cellular()->selected_network(), &error, cb,
436 kTimeoutRegister);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500437 if (error.IsFailure())
438 callback.Run(error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100439}
440
441void CellularCapabilityGSM::RegisterOnNetwork(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500442 const string &network_id,
443 Error *error,
444 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700445 SLOG(Cellular, 2) << __func__ << "(" << network_id << ")";
Eric Shienbrood9a245532012-03-07 14:20:39 -0500446 CHECK(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500447 desired_network_ = network_id;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500448 ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply,
449 weak_ptr_factory_.GetWeakPtr(), callback);
450 network_proxy_->Register(network_id, error, cb, kTimeoutRegister);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500451}
452
Eric Shienbrood9a245532012-03-07 14:20:39 -0500453void CellularCapabilityGSM::OnRegisterReply(const ResultCallback &callback,
454 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700455 SLOG(Cellular, 2) << __func__ << "(" << error << ")";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500456
457 if (error.IsSuccess()) {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800458 cellular()->set_selected_network(desired_network_);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500459 desired_network_.clear();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500460 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500461 return;
462 }
463 // If registration on the desired network failed,
464 // try to register on the home network.
465 if (!desired_network_.empty()) {
466 desired_network_.clear();
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800467 cellular()->set_selected_network("");
Eric Shienbrood9a245532012-03-07 14:20:39 -0500468 LOG(INFO) << "Couldn't register on selected network, trying home network";
469 Register(callback);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500470 return;
471 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500472 callback.Run(error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100473}
474
Ben Chan31ce5642013-11-14 13:37:40 -0800475bool CellularCapabilityGSM::IsRegistered() const {
Darin Petkovb72cf402011-11-22 14:51:39 +0100476 return (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
477 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING);
478}
479
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400480void CellularCapabilityGSM::SetUnregistered(bool searching) {
481 // If we're already in some non-registered state, don't override that
482 if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
483 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
484 registration_state_ =
485 (searching ? MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING :
486 MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE);
487 }
488}
489
Darin Petkovb05315f2011-11-07 10:14:25 +0100490void CellularCapabilityGSM::RequirePIN(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500491 const std::string &pin, bool require,
492 Error *error, const ResultCallback &callback) {
493 CHECK(error);
494 card_proxy_->EnablePIN(pin, require, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100495}
496
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100497void CellularCapabilityGSM::EnterPIN(const string &pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500498 Error *error,
499 const ResultCallback &callback) {
500 CHECK(error);
501 card_proxy_->SendPIN(pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100502}
503
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100504void CellularCapabilityGSM::UnblockPIN(const string &unblock_code,
505 const string &pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500506 Error *error,
507 const ResultCallback &callback) {
508 CHECK(error);
509 card_proxy_->SendPUK(unblock_code, pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100510}
511
512void CellularCapabilityGSM::ChangePIN(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500513 const string &old_pin, const string &new_pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500514 Error *error, const ResultCallback &callback) {
515 CHECK(error);
516 card_proxy_->ChangePIN(old_pin, new_pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100517}
518
Prathmesh Prabhu49ffffd2014-01-09 18:28:55 -0800519void CellularCapabilityGSM::Scan(Error *error,
520 const ResultStringmapsCallback &callback) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500521 ScanResultsCallback cb = Bind(&CellularCapabilityGSM::OnScanReply,
522 weak_ptr_factory_.GetWeakPtr(), callback);
523 network_proxy_->Scan(error, cb, kTimeoutScan);
Darin Petkov1272a432011-11-10 15:53:37 +0100524}
525
Prathmesh Prabhu49ffffd2014-01-09 18:28:55 -0800526void CellularCapabilityGSM::OnScanReply(
527 const ResultStringmapsCallback &callback,
528 const GSMScanResults &results,
529 const Error &error) {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800530 Stringmaps found_networks;
Prathmesh Prabhu49ffffd2014-01-09 18:28:55 -0800531 for (const auto &result : results)
532 found_networks.push_back(ParseScanResult(result));
533 callback.Run(found_networks, error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500534}
535
536Stringmap CellularCapabilityGSM::ParseScanResult(const GSMScanResult &result) {
Darin Petkov1272a432011-11-10 15:53:37 +0100537 Stringmap parsed;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500538 for (GSMScanResult::const_iterator it = result.begin();
539 it != result.end(); ++it) {
Darin Petkov1272a432011-11-10 15:53:37 +0100540 // TODO(petkov): Define these in system_api/service_constants.h. The
541 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
542 static const char * const kStatusString[] = {
543 "unknown",
544 "available",
545 "current",
546 "forbidden",
547 };
548 static const char * const kTechnologyString[] = {
Ben Chan7ea768e2013-09-20 15:08:40 -0700549 kNetworkTechnologyGsm,
Darin Petkov1272a432011-11-10 15:53:37 +0100550 "GSM Compact",
Ben Chan7ea768e2013-09-20 15:08:40 -0700551 kNetworkTechnologyUmts,
552 kNetworkTechnologyEdge,
Darin Petkov1272a432011-11-10 15:53:37 +0100553 "HSDPA",
554 "HSUPA",
Ben Chan7ea768e2013-09-20 15:08:40 -0700555 kNetworkTechnologyHspa,
Darin Petkov1272a432011-11-10 15:53:37 +0100556 };
Ben Chanfad4a0b2012-04-18 15:49:59 -0700557 SLOG(Cellular, 2) << "Network property: " << it->first << " = "
558 << it->second;
Darin Petkov1272a432011-11-10 15:53:37 +0100559 if (it->first == kNetworkPropertyStatus) {
560 int status = 0;
561 if (base::StringToInt(it->second, &status) &&
562 status >= 0 &&
563 status < static_cast<int>(arraysize(kStatusString))) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700564 parsed[kStatusProperty] = kStatusString[status];
Darin Petkov1272a432011-11-10 15:53:37 +0100565 } else {
566 LOG(ERROR) << "Unexpected status value: " << it->second;
567 }
568 } else if (it->first == kNetworkPropertyID) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700569 parsed[kNetworkIdProperty] = it->second;
Darin Petkov1272a432011-11-10 15:53:37 +0100570 } else if (it->first == kNetworkPropertyLongName) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700571 parsed[kLongNameProperty] = it->second;
Darin Petkov1272a432011-11-10 15:53:37 +0100572 } else if (it->first == kNetworkPropertyShortName) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700573 parsed[kShortNameProperty] = it->second;
Darin Petkov1272a432011-11-10 15:53:37 +0100574 } else if (it->first == kNetworkPropertyAccessTechnology) {
575 int tech = 0;
576 if (base::StringToInt(it->second, &tech) &&
577 tech >= 0 &&
578 tech < static_cast<int>(arraysize(kTechnologyString))) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700579 parsed[kTechnologyProperty] = kTechnologyString[tech];
Darin Petkov1272a432011-11-10 15:53:37 +0100580 } else {
581 LOG(ERROR) << "Unexpected technology value: " << it->second;
582 }
583 } else {
584 LOG(WARNING) << "Unknown network property ignored: " << it->first;
585 }
586 }
587 // If the long name is not available but the network ID is, look up the long
588 // name in the mobile provider database.
Ben Chan7ea768e2013-09-20 15:08:40 -0700589 if ((!ContainsKey(parsed, kLongNameProperty) ||
590 parsed[kLongNameProperty].empty()) &&
591 ContainsKey(parsed, kNetworkIdProperty)) {
Prathmesh Prabhuafe63662014-05-20 11:03:58 -0700592 mobile_operator_info_->Reset();
593 mobile_operator_info_->UpdateMCCMNC(parsed[kNetworkIdProperty]);
594 if (mobile_operator_info_->IsMobileNetworkOperatorKnown() &&
595 !mobile_operator_info_->operator_name().empty()) {
596 parsed[kLongNameProperty] = mobile_operator_info_->operator_name();
Darin Petkov1272a432011-11-10 15:53:37 +0100597 }
598 }
599 return parsed;
600}
601
Ben Chan7fab8972014-08-10 17:14:46 -0700602void CellularCapabilityGSM::SetAccessTechnology(uint32_t access_technology) {
Darin Petkovae0c64e2011-11-15 15:50:27 +0100603 access_technology_ = access_technology;
604 if (cellular()->service().get()) {
Darin Petkovb72cf402011-11-22 14:51:39 +0100605 cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100606 }
607}
608
Darin Petkov20c13ec2011-11-09 15:07:15 +0100609string CellularCapabilityGSM::GetNetworkTechnologyString() const {
Darin Petkovb72cf402011-11-22 14:51:39 +0100610 switch (access_technology_) {
611 case MM_MODEM_GSM_ACCESS_TECH_GSM:
612 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
Ben Chan7ea768e2013-09-20 15:08:40 -0700613 return kNetworkTechnologyGsm;
Darin Petkovb72cf402011-11-22 14:51:39 +0100614 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
Ben Chan7ea768e2013-09-20 15:08:40 -0700615 return kNetworkTechnologyGprs;
Darin Petkovb72cf402011-11-22 14:51:39 +0100616 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
Ben Chan7ea768e2013-09-20 15:08:40 -0700617 return kNetworkTechnologyEdge;
Darin Petkovb72cf402011-11-22 14:51:39 +0100618 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
Ben Chan7ea768e2013-09-20 15:08:40 -0700619 return kNetworkTechnologyUmts;
Darin Petkovb72cf402011-11-22 14:51:39 +0100620 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
621 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
622 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
Ben Chan7ea768e2013-09-20 15:08:40 -0700623 return kNetworkTechnologyHspa;
Darin Petkovb72cf402011-11-22 14:51:39 +0100624 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
Ben Chan7ea768e2013-09-20 15:08:40 -0700625 return kNetworkTechnologyHspaPlus;
Darin Petkovb72cf402011-11-22 14:51:39 +0100626 default:
627 break;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100628 }
629 return "";
630}
631
632string CellularCapabilityGSM::GetRoamingStateString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100633 switch (registration_state_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100634 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
Ben Chan7ea768e2013-09-20 15:08:40 -0700635 return kRoamingStateHome;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100636 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
Ben Chan7ea768e2013-09-20 15:08:40 -0700637 return kRoamingStateRoaming;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100638 default:
639 break;
640 }
Ben Chan7ea768e2013-09-20 15:08:40 -0700641 return kRoamingStateUnknown;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100642}
643
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400644void CellularCapabilityGSM::OnDBusPropertiesChanged(
645 const string &interface,
646 const DBusPropertiesMap &properties,
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400647 const vector<string> &invalidated_properties) {
648 CellularCapabilityClassic::OnDBusPropertiesChanged(interface,
649 properties,
650 invalidated_properties);
651 if (interface == MM_MODEM_GSM_NETWORK_INTERFACE) {
Ben Chan7fab8972014-08-10 17:14:46 -0700652 uint32_t access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400653 if (DBusProperties::GetUint32(properties,
654 kPropertyAccessTechnology,
655 &access_technology)) {
656 SetAccessTechnology(access_technology);
657 }
Gary Morainbaeefdf2012-04-30 14:53:35 -0700658 } else {
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400659 bool emit = false;
Gary Morainbaeefdf2012-04-30 14:53:35 -0700660 if (interface == MM_MODEM_GSM_CARD_INTERFACE) {
Ben Chan7fab8972014-08-10 17:14:46 -0700661 uint32_t locks = 0;
Gary Morainbaeefdf2012-04-30 14:53:35 -0700662 if (DBusProperties::GetUint32(
663 properties, kPropertyEnabledFacilityLocks, &locks)) {
664 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
665 emit = true;
666 }
667 } else if (interface == MM_MODEM_INTERFACE) {
668 if (DBusProperties::GetString(properties, kPropertyUnlockRequired,
669 &sim_lock_status_.lock_type)) {
670 emit = true;
671 }
672 if (DBusProperties::GetUint32(properties, kPropertyUnlockRetries,
673 &sim_lock_status_.retries_left)) {
674 emit = true;
675 }
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400676 }
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800677 // TODO(pprabhu) Rename |emit| to |sim_present| after |sim_lock_status|
678 // moves to cellular.
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400679 if (emit) {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800680 cellular()->set_sim_present(true);
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400681 cellular()->adaptor()->EmitKeyValueStoreChanged(
Ben Chan7ea768e2013-09-20 15:08:40 -0700682 kSIMLockStatusProperty, SimLockStatusToProperty(NULL));
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400683 }
Darin Petkov63138a92012-02-06 14:09:15 +0100684 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100685}
686
Ben Chan7fab8972014-08-10 17:14:46 -0700687void CellularCapabilityGSM::OnNetworkModeSignal(uint32_t /*mode*/) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100688 // TODO(petkov): Implement this.
689 NOTIMPLEMENTED();
690}
691
Eric Shienbrood9a245532012-03-07 14:20:39 -0500692void CellularCapabilityGSM::OnRegistrationInfoSignal(
Ben Chan7fab8972014-08-10 17:14:46 -0700693 uint32_t status, const string &operator_code, const string &operator_name) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700694 SLOG(Cellular, 2) << __func__ << ": regstate=" << status
695 << ", opercode=" << operator_code
696 << ", opername=" << operator_name;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500697 registration_state_ = status;
698 serving_operator_.SetCode(operator_code);
699 serving_operator_.SetName(operator_name);
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700700 cellular()->serving_operator_info()->UpdateMCCMNC(operator_code);
701 cellular()->serving_operator_info()->UpdateOperatorName(operator_name);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500702 cellular()->HandleNewRegistrationState();
Darin Petkov184c54e2011-11-15 12:44:39 +0100703}
704
Ben Chan7fab8972014-08-10 17:14:46 -0700705void CellularCapabilityGSM::OnSignalQualitySignal(uint32_t quality) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100706 cellular()->HandleNewSignalQuality(quality);
707}
708
Eric Shienbrood9a245532012-03-07 14:20:39 -0500709void CellularCapabilityGSM::OnGetRegistrationInfoReply(
Ben Chan7fab8972014-08-10 17:14:46 -0700710 uint32_t status, const string &operator_code, const string &operator_name,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500711 const Error &error) {
712 if (error.IsSuccess())
713 OnRegistrationInfoSignal(status, operator_code, operator_name);
714}
715
Ben Chan7fab8972014-08-10 17:14:46 -0700716void CellularCapabilityGSM::OnGetSignalQualityReply(uint32_t quality,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500717 const Error &error) {
718 if (error.IsSuccess())
719 OnSignalQualitySignal(quality);
720}
721
722void CellularCapabilityGSM::OnGetIMEIReply(const ResultCallback &callback,
723 const string &imei,
724 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500725 if (error.IsSuccess()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700726 SLOG(Cellular, 2) << "IMEI: " << imei;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800727 cellular()->set_imei(imei);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500728 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700729 SLOG(Cellular, 2) << "GetIMEI failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500730 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500731 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500732}
733
Eric Shienbrood9a245532012-03-07 14:20:39 -0500734void CellularCapabilityGSM::OnGetIMSIReply(const ResultCallback &callback,
735 const string &imsi,
736 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500737 if (error.IsSuccess()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700738 SLOG(Cellular, 2) << "IMSI: " << imsi;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800739 cellular()->set_imsi(imsi);
740 cellular()->set_sim_present(true);
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700741 cellular()->home_provider_info()->UpdateIMSI(imsi);
Prathmesh Prabhuc93b6bc2014-07-28 15:20:11 -0700742 // We do not currently obtain the IMSI OTA at all. Provide the IMSI from the
743 // SIM to the serving operator as well to aid in MVNO identification.
744 cellular()->serving_operator_info()->UpdateIMSI(imsi);
Gary Morain82a31a02012-08-02 18:03:32 -0700745 callback.Run(error);
Arman Uguray29505ec2013-09-12 20:37:53 -0700746 } else if (!sim_lock_status_.lock_type.empty()) {
747 SLOG(Cellular, 2) << "GetIMSI failed - SIM lock in place.";
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800748 cellular()->set_sim_present(true);
Arman Uguray29505ec2013-09-12 20:37:53 -0700749 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500750 } else {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800751 cellular()->set_sim_present(false);
Gary Morain82a31a02012-08-02 18:03:32 -0700752 if (get_imsi_retries_++ < kGetIMSIRetryLimit) {
753 SLOG(Cellular, 2) << "GetIMSI failed - " << error << ". Retrying";
754 base::Callback<void(void)> retry_get_imsi_cb =
755 Bind(&CellularCapabilityGSM::GetIMSI,
756 weak_ptr_factory_.GetWeakPtr(), callback);
757 cellular()->dispatcher()->PostDelayedTask(
758 retry_get_imsi_cb,
759 get_imsi_retry_delay_milliseconds_);
760 } else {
761 LOG(INFO) << "GetIMSI failed - " << error;
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700762 cellular()->home_provider_info()->Reset();
Gary Morain82a31a02012-08-02 18:03:32 -0700763 callback.Run(error);
764 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500765 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500766}
767
Eric Shienbrood9a245532012-03-07 14:20:39 -0500768void CellularCapabilityGSM::OnGetSPNReply(const ResultCallback &callback,
769 const string &spn,
770 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500771 if (error.IsSuccess()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700772 SLOG(Cellular, 2) << "SPN: " << spn;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500773 spn_ = spn;
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700774 cellular()->home_provider_info()->UpdateOperatorName(spn);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500775 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700776 SLOG(Cellular, 2) << "GetSPN failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500777 }
Thieu Le923006b2012-04-05 16:32:58 -0700778 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500779}
780
Eric Shienbrood9a245532012-03-07 14:20:39 -0500781void CellularCapabilityGSM::OnGetMSISDNReply(const ResultCallback &callback,
782 const string &msisdn,
783 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500784 if (error.IsSuccess()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700785 SLOG(Cellular, 2) << "MSISDN: " << msisdn;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800786 cellular()->set_mdn(msisdn);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500787 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700788 SLOG(Cellular, 2) << "GetMSISDN failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500789 }
Thieu Le923006b2012-04-05 16:32:58 -0700790 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500791}
792
Darin Petkovdaf43862011-10-27 11:37:28 +0200793} // namespace shill