blob: 7bbd66c277176589ba7a4cb551695a1c4db27444 [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
Ben Chanc54afe52014-11-05 10:28:08 -08005#include "shill/cellular/cellular_capability_gsm.h"
Darin Petkovdaf43862011-10-27 11:37:28 +02006
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"
Ben Chanc54afe52014-11-05 10:28:08 -080018#include "shill/cellular/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
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070030namespace Logging {
31static auto kModuleLogScope = ScopeLogger::kCellular;
32static string ObjectID(CellularCapabilityGSM *c) {
33 return c->cellular()->GetRpcIdentifier();
34}
35}
36
Darin Petkovac635a82012-01-10 16:51:58 +010037// static
Darin Petkov1272a432011-11-10 15:53:37 +010038const char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] =
39 "access-tech";
40const char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num";
41const char CellularCapabilityGSM::kNetworkPropertyLongName[] = "operator-long";
42const char CellularCapabilityGSM::kNetworkPropertyShortName[] =
43 "operator-short";
44const char CellularCapabilityGSM::kNetworkPropertyStatus[] = "status";
Darin Petkovae0c64e2011-11-15 15:50:27 +010045const char CellularCapabilityGSM::kPhoneNumber[] = "*99#";
46const char CellularCapabilityGSM::kPropertyAccessTechnology[] =
47 "AccessTechnology";
Darin Petkov63138a92012-02-06 14:09:15 +010048const char CellularCapabilityGSM::kPropertyEnabledFacilityLocks[] =
49 "EnabledFacilityLocks";
Darin Petkov721ac932011-11-16 15:43:09 +010050const char CellularCapabilityGSM::kPropertyUnlockRequired[] = "UnlockRequired";
51const char CellularCapabilityGSM::kPropertyUnlockRetries[] = "UnlockRetries";
Darin Petkov1272a432011-11-10 15:53:37 +010052
Ben Chanc89b9282012-12-12 14:00:29 -080053const int CellularCapabilityGSM::kGetIMSIRetryLimit = 40;
Ben Chan7fab8972014-08-10 17:14:46 -070054const int64_t CellularCapabilityGSM::kGetIMSIRetryDelayMilliseconds = 500;
Gary Morain82a31a02012-08-02 18:03:32 -070055
56
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050057CellularCapabilityGSM::CellularCapabilityGSM(Cellular *cellular,
Thieu Lece4483e2013-01-23 15:12:03 -080058 ProxyFactory *proxy_factory,
Prathmesh Prabhu27526f12013-03-25 19:42:18 -070059 ModemInfo *modem_info)
60 : CellularCapabilityClassic(cellular, proxy_factory, modem_info),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050061 weak_ptr_factory_(this),
Prathmesh Prabhuafe63662014-05-20 11:03:58 -070062 mobile_operator_info_(new MobileOperatorInfo(cellular->dispatcher(),
63 "ParseScanResult")),
Darin Petkov184c54e2011-11-15 12:44:39 +010064 registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
Darin Petkovae0c64e2011-11-15 15:50:27 +010065 access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN),
Ben Chanea18c6c2014-09-30 13:08:26 -070066 home_provider_info_(nullptr),
Gary Morain82a31a02012-08-02 18:03:32 -070067 get_imsi_retries_(0),
Prathmesh Prabhu49ffffd2014-01-09 18:28:55 -080068 get_imsi_retry_delay_milliseconds_(kGetIMSIRetryDelayMilliseconds) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070069 SLOG(this, 2) << "Cellular capability constructed: GSM";
Prathmesh Prabhuafe63662014-05-20 11:03:58 -070070 mobile_operator_info_->Init();
mukesh agrawalbebf1b82013-04-23 15:06:33 -070071 HelpRegisterConstDerivedKeyValueStore(
Ben Chan7ea768e2013-09-20 15:08:40 -070072 kSIMLockStatusProperty, &CellularCapabilityGSM::SimLockStatusToProperty);
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -080073 this->cellular()->set_scanning_supported(true);
Ben Chan3ecdf822012-08-06 12:29:23 -070074
75 // TODO(benchan): This is a hack to initialize the GSM card proxy for GetIMSI
76 // before InitProxies is called. There are side-effects of calling InitProxies
77 // before the device is enabled. It's better to refactor InitProxies such that
78 // proxies can be created when the cellular device/capability is constructed,
79 // but callbacks for DBus signal updates are not set up until the device is
80 // enabled.
81 card_proxy_.reset(
82 proxy_factory->CreateModemGSMCardProxy(cellular->dbus_path(),
83 cellular->dbus_owner()));
84 // TODO(benchan): To allow unit testing using a mock proxy without further
Ben Chanea18c6c2014-09-30 13:08:26 -070085 // complicating the code, the test proxy factory is set up to return a nullptr
Ben Chan3ecdf822012-08-06 12:29:23 -070086 // pointer when CellularCapabilityGSM is constructed. Refactor the code to
87 // avoid this hack.
88 if (card_proxy_.get())
89 InitProperties();
Darin Petkov1272a432011-11-10 15:53:37 +010090}
Darin Petkovdaf43862011-10-27 11:37:28 +020091
Ben Chanf98f00e2014-02-05 14:48:43 -080092CellularCapabilityGSM::~CellularCapabilityGSM() {}
93
94string CellularCapabilityGSM::GetTypeString() const {
95 return kTechnologyFamilyGsm;
96}
97
Darin Petkov63138a92012-02-06 14:09:15 +010098KeyValueStore CellularCapabilityGSM::SimLockStatusToProperty(Error */*error*/) {
99 KeyValueStore status;
Ben Chan7ea768e2013-09-20 15:08:40 -0700100 status.SetBool(kSIMLockEnabledProperty, sim_lock_status_.enabled);
101 status.SetString(kSIMLockTypeProperty, sim_lock_status_.lock_type);
102 status.SetUint(kSIMLockRetriesLeftProperty, sim_lock_status_.retries_left);
Darin Petkov63138a92012-02-06 14:09:15 +0100103 return status;
Darin Petkov721ac932011-11-16 15:43:09 +0100104}
105
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700106void CellularCapabilityGSM::HelpRegisterConstDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +0100107 const string &name,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700108 KeyValueStore(CellularCapabilityGSM::*get)(Error *error)) {
Darin Petkov63138a92012-02-06 14:09:15 +0100109 cellular()->mutable_store()->RegisterDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +0100110 name,
Darin Petkov63138a92012-02-06 14:09:15 +0100111 KeyValueStoreAccessor(
112 new CustomAccessor<CellularCapabilityGSM, KeyValueStore>(
Ben Chanea18c6c2014-09-30 13:08:26 -0700113 this, get, nullptr)));
Darin Petkov721ac932011-11-16 15:43:09 +0100114}
115
Eric Shienbrood9a245532012-03-07 14:20:39 -0500116void CellularCapabilityGSM::InitProxies() {
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400117 CellularCapabilityClassic::InitProxies();
Ben Chan3ecdf822012-08-06 12:29:23 -0700118 // TODO(benchan): Remove this check after refactoring the proxy
119 // initialization.
120 if (!card_proxy_.get()) {
121 card_proxy_.reset(
122 proxy_factory()->CreateModemGSMCardProxy(cellular()->dbus_path(),
123 cellular()->dbus_owner()));
124 }
Darin Petkov184c54e2011-11-15 12:44:39 +0100125 network_proxy_.reset(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500126 proxy_factory()->CreateModemGSMNetworkProxy(cellular()->dbus_path(),
Darin Petkovdaf43862011-10-27 11:37:28 +0200127 cellular()->dbus_owner()));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500128 network_proxy_->set_signal_quality_callback(
129 Bind(&CellularCapabilityGSM::OnSignalQualitySignal,
130 weak_ptr_factory_.GetWeakPtr()));
131 network_proxy_->set_network_mode_callback(
132 Bind(&CellularCapabilityGSM::OnNetworkModeSignal,
133 weak_ptr_factory_.GetWeakPtr()));
134 network_proxy_->set_registration_info_callback(
135 Bind(&CellularCapabilityGSM::OnRegistrationInfoSignal,
136 weak_ptr_factory_.GetWeakPtr()));
Darin Petkovdaf43862011-10-27 11:37:28 +0200137}
138
Ben Chan3ecdf822012-08-06 12:29:23 -0700139void CellularCapabilityGSM::InitProperties() {
140 CellularTaskList *tasks = new CellularTaskList();
141 ResultCallback cb_ignore_error =
142 Bind(&CellularCapabilityGSM::StepCompletedCallback,
143 weak_ptr_factory_.GetWeakPtr(), ResultCallback(), true, tasks);
Ben Chanbd3aee82012-10-16 23:52:04 -0700144 // Chrome checks if a SIM is present before allowing the modem to be enabled,
145 // so shill needs to obtain IMSI, as an indicator of SIM presence, even
146 // before the device is enabled.
Ben Chan3ecdf822012-08-06 12:29:23 -0700147 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMSI,
148 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
149 RunNextStep(tasks);
150}
151
Eric Shienbrood9a245532012-03-07 14:20:39 -0500152void CellularCapabilityGSM::StartModem(Error *error,
153 const ResultCallback &callback) {
154 InitProxies();
155
156 CellularTaskList *tasks = new CellularTaskList();
157 ResultCallback cb =
158 Bind(&CellularCapabilityGSM::StepCompletedCallback,
Thieu Le923006b2012-04-05 16:32:58 -0700159 weak_ptr_factory_.GetWeakPtr(), callback, false, tasks);
160 ResultCallback cb_ignore_error =
161 Bind(&CellularCapabilityGSM::StepCompletedCallback,
162 weak_ptr_factory_.GetWeakPtr(), callback, true, tasks);
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400163 if (!cellular()->IsUnderlyingDeviceEnabled())
164 tasks->push_back(Bind(&CellularCapabilityGSM::EnableModem,
165 weak_ptr_factory_.GetWeakPtr(), cb));
166 // If we're within range of the home network, the modem will try to
167 // register once it's enabled, or may be already registered if we
168 // started out enabled.
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800169 if (!IsUnderlyingDeviceRegistered() &&
170 !cellular()->selected_network().empty())
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400171 tasks->push_back(Bind(&CellularCapabilityGSM::Register,
172 weak_ptr_factory_.GetWeakPtr(), cb));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500173 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMEI,
174 weak_ptr_factory_.GetWeakPtr(), cb));
Gary Morain82a31a02012-08-02 18:03:32 -0700175 get_imsi_retries_ = 0;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500176 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMSI,
177 weak_ptr_factory_.GetWeakPtr(), cb));
178 tasks->push_back(Bind(&CellularCapabilityGSM::GetSPN,
Thieu Le923006b2012-04-05 16:32:58 -0700179 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500180 tasks->push_back(Bind(&CellularCapabilityGSM::GetMSISDN,
Thieu Le923006b2012-04-05 16:32:58 -0700181 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500182 tasks->push_back(Bind(&CellularCapabilityGSM::GetProperties,
183 weak_ptr_factory_.GetWeakPtr(), cb));
184 tasks->push_back(Bind(&CellularCapabilityGSM::GetModemInfo,
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400185 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500186 tasks->push_back(Bind(&CellularCapabilityGSM::FinishEnable,
187 weak_ptr_factory_.GetWeakPtr(), cb));
188
189 RunNextStep(tasks);
190}
191
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400192bool CellularCapabilityGSM::IsUnderlyingDeviceRegistered() const {
193 switch (cellular()->modem_state()) {
Ben Chan7b7d63d2013-10-18 14:53:05 -0700194 case Cellular::kModemStateFailed:
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400195 case Cellular::kModemStateUnknown:
196 case Cellular::kModemStateDisabled:
197 case Cellular::kModemStateInitializing:
198 case Cellular::kModemStateLocked:
199 case Cellular::kModemStateDisabling:
200 case Cellular::kModemStateEnabling:
201 case Cellular::kModemStateEnabled:
202 return false;
203 case Cellular::kModemStateSearching:
204 case Cellular::kModemStateRegistered:
205 case Cellular::kModemStateDisconnecting:
206 case Cellular::kModemStateConnecting:
207 case Cellular::kModemStateConnected:
208 return true;
209 }
210 return false;
211}
212
Eric Shienbrood9a245532012-03-07 14:20:39 -0500213void CellularCapabilityGSM::ReleaseProxies() {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700214 SLOG(this, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400215 CellularCapabilityClassic::ReleaseProxies();
Darin Petkov721ac932011-11-16 15:43:09 +0100216 card_proxy_.reset();
217 network_proxy_.reset();
218}
219
Thieu Le63881a72014-07-28 17:28:36 -0700220bool CellularCapabilityGSM::AreProxiesInitialized() const {
221 return (CellularCapabilityClassic::AreProxiesInitialized() &&
222 card_proxy_.get() && network_proxy_.get());
223}
224
Darin Petkov5f316f62011-11-18 12:10:26 +0100225void CellularCapabilityGSM::OnServiceCreated() {
Ben Chan7ea768e2013-09-20 15:08:40 -0700226 cellular()->service()->SetActivationState(kActivationStateActivated);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100227}
228
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400229// Create the list of APNs to try, in the following order:
230// - last APN that resulted in a successful connection attempt on the
231// current network (if any)
232// - the APN, if any, that was set by the user
233// - the list of APNs found in the mobile broadband provider DB for the
234// home provider associated with the current SIM
235// - as a last resort, attempt to connect with no APN
236void CellularCapabilityGSM::SetupApnTryList() {
237 apn_try_list_.clear();
238
239 DCHECK(cellular()->service().get());
240 const Stringmap *apn_info = cellular()->service()->GetLastGoodApn();
241 if (apn_info)
242 apn_try_list_.push_back(*apn_info);
243
244 apn_info = cellular()->service()->GetUserSpecifiedApn();
245 if (apn_info)
246 apn_try_list_.push_back(*apn_info);
247
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800248 apn_try_list_.insert(apn_try_list_.end(),
249 cellular()->apn_list().begin(),
250 cellular()->apn_list().end());
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400251}
252
Darin Petkovae0c64e2011-11-15 15:50:27 +0100253void CellularCapabilityGSM::SetupConnectProperties(
254 DBusPropertiesMap *properties) {
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400255 SetupApnTryList();
256 FillConnectPropertyMap(properties);
257}
258
259void CellularCapabilityGSM::FillConnectPropertyMap(
260 DBusPropertiesMap *properties) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500261 (*properties)[kConnectPropertyPhoneNumber].writer().append_string(
Darin Petkovae0c64e2011-11-15 15:50:27 +0100262 kPhoneNumber);
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400263
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400264 if (!AllowRoaming())
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400265 (*properties)[kConnectPropertyHomeOnly].writer().append_bool(true);
266
267 if (!apn_try_list_.empty()) {
268 // Leave the APN at the front of the list, so that it can be recorded
269 // if the connect attempt succeeds.
270 Stringmap apn_info = apn_try_list_.front();
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700271 SLOG(this, 2) << __func__ << ": Using APN " << apn_info[kApnProperty];
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400272 (*properties)[kConnectPropertyApn].writer().append_string(
Ben Chan7ea768e2013-09-20 15:08:40 -0700273 apn_info[kApnProperty].c_str());
274 if (ContainsKey(apn_info, kApnUsernameProperty))
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400275 (*properties)[kConnectPropertyApnUsername].writer().append_string(
Ben Chan7ea768e2013-09-20 15:08:40 -0700276 apn_info[kApnUsernameProperty].c_str());
277 if (ContainsKey(apn_info, kApnPasswordProperty))
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400278 (*properties)[kConnectPropertyApnPassword].writer().append_string(
Ben Chan7ea768e2013-09-20 15:08:40 -0700279 apn_info[kApnPasswordProperty].c_str());
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400280 }
281}
282
Nathan Williamsb54974f2012-04-19 11:16:30 -0400283void CellularCapabilityGSM::Connect(const DBusPropertiesMap &properties,
284 Error *error,
285 const ResultCallback &callback) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700286 SLOG(this, 2) << __func__;
Nathan Williamsb54974f2012-04-19 11:16:30 -0400287 ResultCallback cb = Bind(&CellularCapabilityGSM::OnConnectReply,
288 weak_ptr_factory_.GetWeakPtr(),
289 callback);
290 simple_proxy_->Connect(properties, error, cb, kTimeoutConnect);
291}
292
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400293void CellularCapabilityGSM::OnConnectReply(const ResultCallback &callback,
294 const Error &error) {
Thieu Leb5954a22012-05-18 10:37:34 -0700295 CellularServiceRefPtr service = cellular()->service();
296 if (!service) {
297 // The service could have been deleted before our Connect() request
298 // completes if the modem was enabled and then quickly disabled.
299 apn_try_list_.clear();
300 } else if (error.IsFailure()) {
301 service->ClearLastGoodApn();
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400302 // The APN that was just tried (and failed) is still at the
303 // front of the list, about to be removed. If the list is empty
304 // after that, try one last time without an APN. This may succeed
305 // with some modems in some cases.
306 if (error.type() == Error::kInvalidApn && !apn_try_list_.empty()) {
307 apn_try_list_.pop_front();
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700308 SLOG(this, 2) << "Connect failed with invalid APN, "
309 << apn_try_list_.size() << " remaining APNs to try";
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400310 DBusPropertiesMap props;
311 FillConnectPropertyMap(&props);
312 Error error;
313 Connect(props, &error, callback);
314 return;
315 }
316 } else if (!apn_try_list_.empty()) {
Thieu Leb5954a22012-05-18 10:37:34 -0700317 service->SetLastGoodApn(apn_try_list_.front());
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400318 apn_try_list_.clear();
319 }
Nathan Williamsb54974f2012-04-19 11:16:30 -0400320 if (!callback.is_null())
321 callback.Run(error);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400322}
323
324bool CellularCapabilityGSM::AllowRoaming() {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800325 return cellular()->provider_requires_roaming() || allow_roaming_property();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100326}
327
Eric Shienbrood9a245532012-03-07 14:20:39 -0500328// always called from an async context
329void CellularCapabilityGSM::GetIMEI(const ResultCallback &callback) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700330 SLOG(this, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500331 CHECK(!callback.is_null());
332 Error error;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800333 if (cellular()->imei().empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500334 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMEIReply,
335 weak_ptr_factory_.GetWeakPtr(), callback);
336 card_proxy_->GetIMEI(&error, cb, kTimeoutDefault);
337 if (error.IsFailure())
338 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500339 } else {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700340 SLOG(this, 2) << "Already have IMEI " << cellular()->imei();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500341 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100342 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500343}
344
Eric Shienbrood9a245532012-03-07 14:20:39 -0500345// always called from an async context
346void CellularCapabilityGSM::GetIMSI(const ResultCallback &callback) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700347 SLOG(this, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500348 CHECK(!callback.is_null());
349 Error error;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800350 if (cellular()->imsi().empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500351 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMSIReply,
352 weak_ptr_factory_.GetWeakPtr(),
353 callback);
354 card_proxy_->GetIMSI(&error, cb, kTimeoutDefault);
Prathmesh Prabhu28b4a3b2014-03-28 11:52:09 -0700355 if (error.IsFailure()) {
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700356 cellular()->home_provider_info()->Reset();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500357 callback.Run(error);
Prathmesh Prabhu28b4a3b2014-03-28 11:52:09 -0700358 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500359 } else {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700360 SLOG(this, 2) << "Already have IMSI " << cellular()->imsi();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500361 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100362 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500363}
364
Eric Shienbrood9a245532012-03-07 14:20:39 -0500365// always called from an async context
366void CellularCapabilityGSM::GetSPN(const ResultCallback &callback) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700367 SLOG(this, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500368 CHECK(!callback.is_null());
369 Error error;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100370 if (spn_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500371 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetSPNReply,
372 weak_ptr_factory_.GetWeakPtr(),
373 callback);
374 card_proxy_->GetSPN(&error, cb, kTimeoutDefault);
375 if (error.IsFailure())
376 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500377 } else {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700378 SLOG(this, 2) << "Already have SPN " << spn_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500379 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100380 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500381}
382
Eric Shienbrood9a245532012-03-07 14:20:39 -0500383// always called from an async context
384void CellularCapabilityGSM::GetMSISDN(const ResultCallback &callback) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700385 SLOG(this, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500386 CHECK(!callback.is_null());
387 Error error;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800388 string mdn = cellular()->mdn();
389 if (mdn.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500390 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetMSISDNReply,
391 weak_ptr_factory_.GetWeakPtr(),
392 callback);
393 card_proxy_->GetMSISDN(&error, cb, kTimeoutDefault);
394 if (error.IsFailure())
395 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500396 } else {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700397 SLOG(this, 2) << "Already have MSISDN " << mdn;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500398 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100399 }
400}
401
Darin Petkov3e509242011-11-10 14:46:44 +0100402void CellularCapabilityGSM::GetSignalQuality() {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700403 SLOG(this, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500404 SignalQualityCallback callback =
405 Bind(&CellularCapabilityGSM::OnGetSignalQualityReply,
406 weak_ptr_factory_.GetWeakPtr());
Ben Chanea18c6c2014-09-30 13:08:26 -0700407 network_proxy_->GetSignalQuality(nullptr, callback, kTimeoutDefault);
Darin Petkov3e509242011-11-10 14:46:44 +0100408}
409
Eric Shienbrood9a245532012-03-07 14:20:39 -0500410void CellularCapabilityGSM::GetRegistrationState() {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700411 SLOG(this, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500412 RegistrationInfoCallback callback =
413 Bind(&CellularCapabilityGSM::OnGetRegistrationInfoReply,
414 weak_ptr_factory_.GetWeakPtr());
Ben Chanea18c6c2014-09-30 13:08:26 -0700415 network_proxy_->GetRegistrationInfo(nullptr, callback, kTimeoutDefault);
Darin Petkov184c54e2011-11-15 12:44:39 +0100416}
417
Eric Shienbrood9a245532012-03-07 14:20:39 -0500418void CellularCapabilityGSM::GetProperties(const ResultCallback &callback) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700419 SLOG(this, 2) << __func__;
Darin Petkov63138a92012-02-06 14:09:15 +0100420
Paul Stewartee6b3d72013-07-12 16:07:51 -0700421 // TODO(petkov): Switch to asynchronous calls (crbug.com/200687).
Ben Chan7fab8972014-08-10 17:14:46 -0700422 uint32_t tech = network_proxy_->AccessTechnology();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100423 SetAccessTechnology(tech);
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700424 SLOG(this, 2) << "GSM AccessTechnology: " << tech;
Darin Petkov63138a92012-02-06 14:09:15 +0100425
Paul Stewartee6b3d72013-07-12 16:07:51 -0700426 // TODO(petkov): Switch to asynchronous calls (crbug.com/200687).
Ben Chan7fab8972014-08-10 17:14:46 -0700427 uint32_t locks = card_proxy_->EnabledFacilityLocks();
Darin Petkov63138a92012-02-06 14:09:15 +0100428 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700429 SLOG(this, 2) << "GSM EnabledFacilityLocks: " << locks;
Darin Petkov63138a92012-02-06 14:09:15 +0100430
Eric Shienbrood9a245532012-03-07 14:20:39 -0500431 callback.Run(Error());
Darin Petkov184c54e2011-11-15 12:44:39 +0100432}
433
Eric Shienbrood9a245532012-03-07 14:20:39 -0500434// always called from an async context
435void CellularCapabilityGSM::Register(const ResultCallback &callback) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700436 SLOG(this, 2) << __func__ << " \"" << cellular()->selected_network()
437 << "\"";
Eric Shienbrood9a245532012-03-07 14:20:39 -0500438 CHECK(!callback.is_null());
439 Error error;
440 ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply,
441 weak_ptr_factory_.GetWeakPtr(), callback);
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800442 network_proxy_->Register(cellular()->selected_network(), &error, cb,
443 kTimeoutRegister);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500444 if (error.IsFailure())
445 callback.Run(error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100446}
447
448void CellularCapabilityGSM::RegisterOnNetwork(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500449 const string &network_id,
450 Error *error,
451 const ResultCallback &callback) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700452 SLOG(this, 2) << __func__ << "(" << network_id << ")";
Eric Shienbrood9a245532012-03-07 14:20:39 -0500453 CHECK(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500454 desired_network_ = network_id;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500455 ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply,
456 weak_ptr_factory_.GetWeakPtr(), callback);
457 network_proxy_->Register(network_id, error, cb, kTimeoutRegister);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500458}
459
Eric Shienbrood9a245532012-03-07 14:20:39 -0500460void CellularCapabilityGSM::OnRegisterReply(const ResultCallback &callback,
461 const Error &error) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700462 SLOG(this, 2) << __func__ << "(" << error << ")";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500463
464 if (error.IsSuccess()) {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800465 cellular()->set_selected_network(desired_network_);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500466 desired_network_.clear();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500467 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500468 return;
469 }
470 // If registration on the desired network failed,
471 // try to register on the home network.
472 if (!desired_network_.empty()) {
473 desired_network_.clear();
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800474 cellular()->set_selected_network("");
Eric Shienbrood9a245532012-03-07 14:20:39 -0500475 LOG(INFO) << "Couldn't register on selected network, trying home network";
476 Register(callback);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500477 return;
478 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500479 callback.Run(error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100480}
481
Ben Chan31ce5642013-11-14 13:37:40 -0800482bool CellularCapabilityGSM::IsRegistered() const {
Darin Petkovb72cf402011-11-22 14:51:39 +0100483 return (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
484 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING);
485}
486
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400487void CellularCapabilityGSM::SetUnregistered(bool searching) {
488 // If we're already in some non-registered state, don't override that
489 if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
490 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
491 registration_state_ =
492 (searching ? MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING :
493 MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE);
494 }
495}
496
Darin Petkovb05315f2011-11-07 10:14:25 +0100497void CellularCapabilityGSM::RequirePIN(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500498 const std::string &pin, bool require,
499 Error *error, const ResultCallback &callback) {
500 CHECK(error);
501 card_proxy_->EnablePIN(pin, require, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100502}
503
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100504void CellularCapabilityGSM::EnterPIN(const string &pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500505 Error *error,
506 const ResultCallback &callback) {
507 CHECK(error);
508 card_proxy_->SendPIN(pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100509}
510
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100511void CellularCapabilityGSM::UnblockPIN(const string &unblock_code,
512 const string &pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500513 Error *error,
514 const ResultCallback &callback) {
515 CHECK(error);
516 card_proxy_->SendPUK(unblock_code, pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100517}
518
519void CellularCapabilityGSM::ChangePIN(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500520 const string &old_pin, const string &new_pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500521 Error *error, const ResultCallback &callback) {
522 CHECK(error);
523 card_proxy_->ChangePIN(old_pin, new_pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100524}
525
Prathmesh Prabhu49ffffd2014-01-09 18:28:55 -0800526void CellularCapabilityGSM::Scan(Error *error,
527 const ResultStringmapsCallback &callback) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500528 ScanResultsCallback cb = Bind(&CellularCapabilityGSM::OnScanReply,
529 weak_ptr_factory_.GetWeakPtr(), callback);
530 network_proxy_->Scan(error, cb, kTimeoutScan);
Darin Petkov1272a432011-11-10 15:53:37 +0100531}
532
Prathmesh Prabhu49ffffd2014-01-09 18:28:55 -0800533void CellularCapabilityGSM::OnScanReply(
534 const ResultStringmapsCallback &callback,
535 const GSMScanResults &results,
536 const Error &error) {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800537 Stringmaps found_networks;
Prathmesh Prabhu49ffffd2014-01-09 18:28:55 -0800538 for (const auto &result : results)
539 found_networks.push_back(ParseScanResult(result));
540 callback.Run(found_networks, error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500541}
542
543Stringmap CellularCapabilityGSM::ParseScanResult(const GSMScanResult &result) {
Darin Petkov1272a432011-11-10 15:53:37 +0100544 Stringmap parsed;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500545 for (GSMScanResult::const_iterator it = result.begin();
546 it != result.end(); ++it) {
Darin Petkov1272a432011-11-10 15:53:37 +0100547 // TODO(petkov): Define these in system_api/service_constants.h. The
548 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
549 static const char * const kStatusString[] = {
550 "unknown",
551 "available",
552 "current",
553 "forbidden",
554 };
555 static const char * const kTechnologyString[] = {
Ben Chan7ea768e2013-09-20 15:08:40 -0700556 kNetworkTechnologyGsm,
Darin Petkov1272a432011-11-10 15:53:37 +0100557 "GSM Compact",
Ben Chan7ea768e2013-09-20 15:08:40 -0700558 kNetworkTechnologyUmts,
559 kNetworkTechnologyEdge,
Darin Petkov1272a432011-11-10 15:53:37 +0100560 "HSDPA",
561 "HSUPA",
Ben Chan7ea768e2013-09-20 15:08:40 -0700562 kNetworkTechnologyHspa,
Darin Petkov1272a432011-11-10 15:53:37 +0100563 };
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700564 SLOG(this, 2) << "Network property: " << it->first << " = "
565 << it->second;
Darin Petkov1272a432011-11-10 15:53:37 +0100566 if (it->first == kNetworkPropertyStatus) {
567 int status = 0;
568 if (base::StringToInt(it->second, &status) &&
569 status >= 0 &&
570 status < static_cast<int>(arraysize(kStatusString))) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700571 parsed[kStatusProperty] = kStatusString[status];
Darin Petkov1272a432011-11-10 15:53:37 +0100572 } else {
573 LOG(ERROR) << "Unexpected status value: " << it->second;
574 }
575 } else if (it->first == kNetworkPropertyID) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700576 parsed[kNetworkIdProperty] = it->second;
Darin Petkov1272a432011-11-10 15:53:37 +0100577 } else if (it->first == kNetworkPropertyLongName) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700578 parsed[kLongNameProperty] = it->second;
Darin Petkov1272a432011-11-10 15:53:37 +0100579 } else if (it->first == kNetworkPropertyShortName) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700580 parsed[kShortNameProperty] = it->second;
Darin Petkov1272a432011-11-10 15:53:37 +0100581 } else if (it->first == kNetworkPropertyAccessTechnology) {
582 int tech = 0;
583 if (base::StringToInt(it->second, &tech) &&
584 tech >= 0 &&
585 tech < static_cast<int>(arraysize(kTechnologyString))) {
Ben Chan7ea768e2013-09-20 15:08:40 -0700586 parsed[kTechnologyProperty] = kTechnologyString[tech];
Darin Petkov1272a432011-11-10 15:53:37 +0100587 } else {
588 LOG(ERROR) << "Unexpected technology value: " << it->second;
589 }
590 } else {
591 LOG(WARNING) << "Unknown network property ignored: " << it->first;
592 }
593 }
594 // If the long name is not available but the network ID is, look up the long
595 // name in the mobile provider database.
Ben Chan7ea768e2013-09-20 15:08:40 -0700596 if ((!ContainsKey(parsed, kLongNameProperty) ||
597 parsed[kLongNameProperty].empty()) &&
598 ContainsKey(parsed, kNetworkIdProperty)) {
Prathmesh Prabhuafe63662014-05-20 11:03:58 -0700599 mobile_operator_info_->Reset();
600 mobile_operator_info_->UpdateMCCMNC(parsed[kNetworkIdProperty]);
601 if (mobile_operator_info_->IsMobileNetworkOperatorKnown() &&
602 !mobile_operator_info_->operator_name().empty()) {
603 parsed[kLongNameProperty] = mobile_operator_info_->operator_name();
Darin Petkov1272a432011-11-10 15:53:37 +0100604 }
605 }
606 return parsed;
607}
608
Ben Chan7fab8972014-08-10 17:14:46 -0700609void CellularCapabilityGSM::SetAccessTechnology(uint32_t access_technology) {
Darin Petkovae0c64e2011-11-15 15:50:27 +0100610 access_technology_ = access_technology;
611 if (cellular()->service().get()) {
Darin Petkovb72cf402011-11-22 14:51:39 +0100612 cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100613 }
614}
615
Darin Petkov20c13ec2011-11-09 15:07:15 +0100616string CellularCapabilityGSM::GetNetworkTechnologyString() const {
Darin Petkovb72cf402011-11-22 14:51:39 +0100617 switch (access_technology_) {
618 case MM_MODEM_GSM_ACCESS_TECH_GSM:
619 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
Ben Chan7ea768e2013-09-20 15:08:40 -0700620 return kNetworkTechnologyGsm;
Darin Petkovb72cf402011-11-22 14:51:39 +0100621 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
Ben Chan7ea768e2013-09-20 15:08:40 -0700622 return kNetworkTechnologyGprs;
Darin Petkovb72cf402011-11-22 14:51:39 +0100623 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
Ben Chan7ea768e2013-09-20 15:08:40 -0700624 return kNetworkTechnologyEdge;
Darin Petkovb72cf402011-11-22 14:51:39 +0100625 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
Ben Chan7ea768e2013-09-20 15:08:40 -0700626 return kNetworkTechnologyUmts;
Darin Petkovb72cf402011-11-22 14:51:39 +0100627 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
628 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
629 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
Ben Chan7ea768e2013-09-20 15:08:40 -0700630 return kNetworkTechnologyHspa;
Darin Petkovb72cf402011-11-22 14:51:39 +0100631 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
Ben Chan7ea768e2013-09-20 15:08:40 -0700632 return kNetworkTechnologyHspaPlus;
Darin Petkovb72cf402011-11-22 14:51:39 +0100633 default:
634 break;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100635 }
636 return "";
637}
638
639string CellularCapabilityGSM::GetRoamingStateString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100640 switch (registration_state_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100641 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
Ben Chan7ea768e2013-09-20 15:08:40 -0700642 return kRoamingStateHome;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100643 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
Ben Chan7ea768e2013-09-20 15:08:40 -0700644 return kRoamingStateRoaming;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100645 default:
646 break;
647 }
Ben Chan7ea768e2013-09-20 15:08:40 -0700648 return kRoamingStateUnknown;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100649}
650
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400651void CellularCapabilityGSM::OnDBusPropertiesChanged(
652 const string &interface,
653 const DBusPropertiesMap &properties,
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400654 const vector<string> &invalidated_properties) {
655 CellularCapabilityClassic::OnDBusPropertiesChanged(interface,
656 properties,
657 invalidated_properties);
658 if (interface == MM_MODEM_GSM_NETWORK_INTERFACE) {
Ben Chan7fab8972014-08-10 17:14:46 -0700659 uint32_t access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400660 if (DBusProperties::GetUint32(properties,
661 kPropertyAccessTechnology,
662 &access_technology)) {
663 SetAccessTechnology(access_technology);
664 }
Gary Morainbaeefdf2012-04-30 14:53:35 -0700665 } else {
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400666 bool emit = false;
Gary Morainbaeefdf2012-04-30 14:53:35 -0700667 if (interface == MM_MODEM_GSM_CARD_INTERFACE) {
Ben Chan7fab8972014-08-10 17:14:46 -0700668 uint32_t locks = 0;
Gary Morainbaeefdf2012-04-30 14:53:35 -0700669 if (DBusProperties::GetUint32(
670 properties, kPropertyEnabledFacilityLocks, &locks)) {
671 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
672 emit = true;
673 }
674 } else if (interface == MM_MODEM_INTERFACE) {
675 if (DBusProperties::GetString(properties, kPropertyUnlockRequired,
676 &sim_lock_status_.lock_type)) {
677 emit = true;
678 }
679 if (DBusProperties::GetUint32(properties, kPropertyUnlockRetries,
680 &sim_lock_status_.retries_left)) {
681 emit = true;
682 }
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400683 }
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800684 // TODO(pprabhu) Rename |emit| to |sim_present| after |sim_lock_status|
685 // moves to cellular.
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400686 if (emit) {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800687 cellular()->set_sim_present(true);
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400688 cellular()->adaptor()->EmitKeyValueStoreChanged(
Ben Chanea18c6c2014-09-30 13:08:26 -0700689 kSIMLockStatusProperty, SimLockStatusToProperty(nullptr));
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400690 }
Darin Petkov63138a92012-02-06 14:09:15 +0100691 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100692}
693
Ben Chan7fab8972014-08-10 17:14:46 -0700694void CellularCapabilityGSM::OnNetworkModeSignal(uint32_t /*mode*/) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100695 // TODO(petkov): Implement this.
696 NOTIMPLEMENTED();
697}
698
Eric Shienbrood9a245532012-03-07 14:20:39 -0500699void CellularCapabilityGSM::OnRegistrationInfoSignal(
Ben Chan7fab8972014-08-10 17:14:46 -0700700 uint32_t status, const string &operator_code, const string &operator_name) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700701 SLOG(this, 2) << __func__ << ": regstate=" << status
702 << ", opercode=" << operator_code
703 << ", opername=" << operator_name;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500704 registration_state_ = status;
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700705 cellular()->serving_operator_info()->UpdateMCCMNC(operator_code);
706 cellular()->serving_operator_info()->UpdateOperatorName(operator_name);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500707 cellular()->HandleNewRegistrationState();
Darin Petkov184c54e2011-11-15 12:44:39 +0100708}
709
Ben Chan7fab8972014-08-10 17:14:46 -0700710void CellularCapabilityGSM::OnSignalQualitySignal(uint32_t quality) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100711 cellular()->HandleNewSignalQuality(quality);
712}
713
Eric Shienbrood9a245532012-03-07 14:20:39 -0500714void CellularCapabilityGSM::OnGetRegistrationInfoReply(
Ben Chan7fab8972014-08-10 17:14:46 -0700715 uint32_t status, const string &operator_code, const string &operator_name,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500716 const Error &error) {
717 if (error.IsSuccess())
718 OnRegistrationInfoSignal(status, operator_code, operator_name);
719}
720
Ben Chan7fab8972014-08-10 17:14:46 -0700721void CellularCapabilityGSM::OnGetSignalQualityReply(uint32_t quality,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500722 const Error &error) {
723 if (error.IsSuccess())
724 OnSignalQualitySignal(quality);
725}
726
727void CellularCapabilityGSM::OnGetIMEIReply(const ResultCallback &callback,
728 const string &imei,
729 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500730 if (error.IsSuccess()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700731 SLOG(this, 2) << "IMEI: " << imei;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800732 cellular()->set_imei(imei);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500733 } else {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700734 SLOG(this, 2) << "GetIMEI failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500735 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500736 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500737}
738
Eric Shienbrood9a245532012-03-07 14:20:39 -0500739void CellularCapabilityGSM::OnGetIMSIReply(const ResultCallback &callback,
740 const string &imsi,
741 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500742 if (error.IsSuccess()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700743 SLOG(this, 2) << "IMSI: " << imsi;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800744 cellular()->set_imsi(imsi);
745 cellular()->set_sim_present(true);
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700746 cellular()->home_provider_info()->UpdateIMSI(imsi);
Prathmesh Prabhuc93b6bc2014-07-28 15:20:11 -0700747 // We do not currently obtain the IMSI OTA at all. Provide the IMSI from the
748 // SIM to the serving operator as well to aid in MVNO identification.
749 cellular()->serving_operator_info()->UpdateIMSI(imsi);
Gary Morain82a31a02012-08-02 18:03:32 -0700750 callback.Run(error);
Arman Uguray29505ec2013-09-12 20:37:53 -0700751 } else if (!sim_lock_status_.lock_type.empty()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700752 SLOG(this, 2) << "GetIMSI failed - SIM lock in place.";
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800753 cellular()->set_sim_present(true);
Arman Uguray29505ec2013-09-12 20:37:53 -0700754 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500755 } else {
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800756 cellular()->set_sim_present(false);
Gary Morain82a31a02012-08-02 18:03:32 -0700757 if (get_imsi_retries_++ < kGetIMSIRetryLimit) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700758 SLOG(this, 2) << "GetIMSI failed - " << error << ". Retrying";
Gary Morain82a31a02012-08-02 18:03:32 -0700759 base::Callback<void(void)> retry_get_imsi_cb =
760 Bind(&CellularCapabilityGSM::GetIMSI,
761 weak_ptr_factory_.GetWeakPtr(), callback);
762 cellular()->dispatcher()->PostDelayedTask(
763 retry_get_imsi_cb,
764 get_imsi_retry_delay_milliseconds_);
765 } else {
766 LOG(INFO) << "GetIMSI failed - " << error;
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700767 cellular()->home_provider_info()->Reset();
Gary Morain82a31a02012-08-02 18:03:32 -0700768 callback.Run(error);
769 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500770 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500771}
772
Eric Shienbrood9a245532012-03-07 14:20:39 -0500773void CellularCapabilityGSM::OnGetSPNReply(const ResultCallback &callback,
774 const string &spn,
775 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500776 if (error.IsSuccess()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700777 SLOG(this, 2) << "SPN: " << spn;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500778 spn_ = spn;
Prathmesh Prabhu8599e052014-04-25 14:20:22 -0700779 cellular()->home_provider_info()->UpdateOperatorName(spn);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500780 } else {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700781 SLOG(this, 2) << "GetSPN failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500782 }
Thieu Le923006b2012-04-05 16:32:58 -0700783 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500784}
785
Eric Shienbrood9a245532012-03-07 14:20:39 -0500786void CellularCapabilityGSM::OnGetMSISDNReply(const ResultCallback &callback,
787 const string &msisdn,
788 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500789 if (error.IsSuccess()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700790 SLOG(this, 2) << "MSISDN: " << msisdn;
Prathmesh Prabhu9f06c872013-11-21 14:08:23 -0800791 cellular()->set_mdn(msisdn);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500792 } else {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700793 SLOG(this, 2) << "GetMSISDN failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500794 }
Thieu Le923006b2012-04-05 16:32:58 -0700795 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500796}
797
Darin Petkovdaf43862011-10-27 11:37:28 +0200798} // namespace shill