blob: 3a5bc5a99b83ab6b778c9cee7bf7537cc99ddb7e [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>
Darin Petkovdaf43862011-10-27 11:37:28 +020011#include <base/logging.h>
Eric Shienbrood3e20a232012-02-16 11:35:56 -050012#include <base/stl_util.h>
Darin Petkov1272a432011-11-10 15:53:37 +010013#include <base/string_number_conversions.h>
Darin Petkovac635a82012-01-10 16:51:58 +010014#include <base/stringprintf.h>
Darin Petkov20c13ec2011-11-09 15:07:15 +010015#include <chromeos/dbus/service_constants.h>
16#include <mm/mm-modem.h>
Darin Petkov1272a432011-11-10 15:53:37 +010017#include <mobile_provider.h>
Darin Petkovdaf43862011-10-27 11:37:28 +020018
Darin Petkov3cfbf212011-11-21 16:02:09 +010019#include "shill/adaptor_interfaces.h"
Darin Petkovae0c64e2011-11-15 15:50:27 +010020#include "shill/cellular_service.h"
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050021#include "shill/error.h"
Darin Petkov721ac932011-11-16 15:43:09 +010022#include "shill/property_accessor.h"
Darin Petkovdaf43862011-10-27 11:37:28 +020023#include "shill/proxy_factory.h"
24
Eric Shienbrood3e20a232012-02-16 11:35:56 -050025using base::Bind;
Darin Petkovb05315f2011-11-07 10:14:25 +010026using std::string;
Jason Glasgow4c0724a2012-04-17 15:47:40 -040027using std::vector;
Darin Petkovb05315f2011-11-07 10:14:25 +010028
Darin Petkovdaf43862011-10-27 11:37:28 +020029namespace shill {
30
Darin Petkovac635a82012-01-10 16:51:58 +010031// static
32unsigned int CellularCapabilityGSM::friendly_service_name_id_ = 0;
33
Darin Petkov1272a432011-11-10 15:53:37 +010034const char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] =
35 "access-tech";
36const char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num";
37const char CellularCapabilityGSM::kNetworkPropertyLongName[] = "operator-long";
38const char CellularCapabilityGSM::kNetworkPropertyShortName[] =
39 "operator-short";
40const char CellularCapabilityGSM::kNetworkPropertyStatus[] = "status";
Darin Petkovae0c64e2011-11-15 15:50:27 +010041const char CellularCapabilityGSM::kPhoneNumber[] = "*99#";
42const char CellularCapabilityGSM::kPropertyAccessTechnology[] =
43 "AccessTechnology";
Darin Petkov63138a92012-02-06 14:09:15 +010044const char CellularCapabilityGSM::kPropertyEnabledFacilityLocks[] =
45 "EnabledFacilityLocks";
Darin Petkov721ac932011-11-16 15:43:09 +010046const char CellularCapabilityGSM::kPropertyUnlockRequired[] = "UnlockRequired";
47const char CellularCapabilityGSM::kPropertyUnlockRetries[] = "UnlockRetries";
Darin Petkov1272a432011-11-10 15:53:37 +010048
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050049CellularCapabilityGSM::CellularCapabilityGSM(Cellular *cellular,
50 ProxyFactory *proxy_factory)
Jason Glasgow82f9ab32012-04-04 14:27:19 -040051 : CellularCapabilityClassic(cellular, proxy_factory),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050052 weak_ptr_factory_(this),
Darin Petkov184c54e2011-11-15 12:44:39 +010053 registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
Darin Petkovae0c64e2011-11-15 15:50:27 +010054 access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +010055 home_provider_(NULL),
Darin Petkov1272a432011-11-10 15:53:37 +010056 scanning_(false),
57 scan_interval_(0) {
Darin Petkov5f316f62011-11-18 12:10:26 +010058 VLOG(2) << "Cellular capability constructed: GSM";
Darin Petkov1272a432011-11-10 15:53:37 +010059 PropertyStore *store = cellular->mutable_store();
Darin Petkov184c54e2011-11-15 12:44:39 +010060 store->RegisterConstString(flimflam::kSelectedNetworkProperty,
61 &selected_network_);
Darin Petkov1272a432011-11-10 15:53:37 +010062 store->RegisterConstStringmaps(flimflam::kFoundNetworksProperty,
63 &found_networks_);
64 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
65 store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
Darin Petkov63138a92012-02-06 14:09:15 +010066 HelpRegisterDerivedKeyValueStore(
67 flimflam::kSIMLockStatusProperty,
68 &CellularCapabilityGSM::SimLockStatusToProperty,
69 NULL);
Darin Petkov3cfbf212011-11-21 16:02:09 +010070 store->RegisterConstStringmaps(flimflam::kCellularApnListProperty,
71 &apn_list_);
Darin Petkov0d06f7d2012-02-03 13:08:19 +010072 scanning_supported_ = true;
Darin Petkov1272a432011-11-10 15:53:37 +010073}
Darin Petkovdaf43862011-10-27 11:37:28 +020074
Darin Petkov63138a92012-02-06 14:09:15 +010075KeyValueStore CellularCapabilityGSM::SimLockStatusToProperty(Error */*error*/) {
76 KeyValueStore status;
77 status.SetBool(flimflam::kSIMLockEnabledProperty, sim_lock_status_.enabled);
78 status.SetString(flimflam::kSIMLockTypeProperty, sim_lock_status_.lock_type);
79 status.SetUint(flimflam::kSIMLockRetriesLeftProperty,
80 sim_lock_status_.retries_left);
81 return status;
Darin Petkov721ac932011-11-16 15:43:09 +010082}
83
Darin Petkov63138a92012-02-06 14:09:15 +010084void CellularCapabilityGSM::HelpRegisterDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +010085 const string &name,
Darin Petkov63138a92012-02-06 14:09:15 +010086 KeyValueStore(CellularCapabilityGSM::*get)(Error *error),
87 void(CellularCapabilityGSM::*set)(
88 const KeyValueStore &value, Error *error)) {
89 cellular()->mutable_store()->RegisterDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +010090 name,
Darin Petkov63138a92012-02-06 14:09:15 +010091 KeyValueStoreAccessor(
92 new CustomAccessor<CellularCapabilityGSM, KeyValueStore>(
Darin Petkov721ac932011-11-16 15:43:09 +010093 this, get, set)));
94}
95
Eric Shienbrood9a245532012-03-07 14:20:39 -050096void CellularCapabilityGSM::InitProxies() {
Jason Glasgow82f9ab32012-04-04 14:27:19 -040097 CellularCapabilityClassic::InitProxies();
Darin Petkovcb547732011-11-09 13:55:26 +010098 card_proxy_.reset(
Eric Shienbrood9a245532012-03-07 14:20:39 -050099 proxy_factory()->CreateModemGSMCardProxy(cellular()->dbus_path(),
Darin Petkovdaf43862011-10-27 11:37:28 +0200100 cellular()->dbus_owner()));
Darin Petkov184c54e2011-11-15 12:44:39 +0100101 network_proxy_.reset(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500102 proxy_factory()->CreateModemGSMNetworkProxy(cellular()->dbus_path(),
Darin Petkovdaf43862011-10-27 11:37:28 +0200103 cellular()->dbus_owner()));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500104 network_proxy_->set_signal_quality_callback(
105 Bind(&CellularCapabilityGSM::OnSignalQualitySignal,
106 weak_ptr_factory_.GetWeakPtr()));
107 network_proxy_->set_network_mode_callback(
108 Bind(&CellularCapabilityGSM::OnNetworkModeSignal,
109 weak_ptr_factory_.GetWeakPtr()));
110 network_proxy_->set_registration_info_callback(
111 Bind(&CellularCapabilityGSM::OnRegistrationInfoSignal,
112 weak_ptr_factory_.GetWeakPtr()));
Darin Petkovdaf43862011-10-27 11:37:28 +0200113}
114
Eric Shienbrood9a245532012-03-07 14:20:39 -0500115void CellularCapabilityGSM::StartModem(Error *error,
116 const ResultCallback &callback) {
117 InitProxies();
118
119 CellularTaskList *tasks = new CellularTaskList();
120 ResultCallback cb =
121 Bind(&CellularCapabilityGSM::StepCompletedCallback,
Thieu Le923006b2012-04-05 16:32:58 -0700122 weak_ptr_factory_.GetWeakPtr(), callback, false, tasks);
123 ResultCallback cb_ignore_error =
124 Bind(&CellularCapabilityGSM::StepCompletedCallback,
125 weak_ptr_factory_.GetWeakPtr(), callback, true, tasks);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500126 tasks->push_back(Bind(&CellularCapabilityGSM::EnableModem,
127 weak_ptr_factory_.GetWeakPtr(), cb));
128 tasks->push_back(Bind(&CellularCapabilityGSM::Register,
129 weak_ptr_factory_.GetWeakPtr(), cb));
130 tasks->push_back(Bind(&CellularCapabilityGSM::GetModemStatus,
131 weak_ptr_factory_.GetWeakPtr(), cb));
132 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMEI,
133 weak_ptr_factory_.GetWeakPtr(), cb));
134 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMSI,
135 weak_ptr_factory_.GetWeakPtr(), cb));
136 tasks->push_back(Bind(&CellularCapabilityGSM::GetSPN,
Thieu Le923006b2012-04-05 16:32:58 -0700137 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500138 tasks->push_back(Bind(&CellularCapabilityGSM::GetMSISDN,
Thieu Le923006b2012-04-05 16:32:58 -0700139 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500140 tasks->push_back(Bind(&CellularCapabilityGSM::GetProperties,
141 weak_ptr_factory_.GetWeakPtr(), cb));
142 tasks->push_back(Bind(&CellularCapabilityGSM::GetModemInfo,
143 weak_ptr_factory_.GetWeakPtr(), cb));
144 tasks->push_back(Bind(&CellularCapabilityGSM::FinishEnable,
145 weak_ptr_factory_.GetWeakPtr(), cb));
146
147 RunNextStep(tasks);
148}
149
Eric Shienbrood9a245532012-03-07 14:20:39 -0500150void CellularCapabilityGSM::ReleaseProxies() {
151 VLOG(2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400152 CellularCapabilityClassic::ReleaseProxies();
Darin Petkov721ac932011-11-16 15:43:09 +0100153 card_proxy_.reset();
154 network_proxy_.reset();
155}
156
Darin Petkov5f316f62011-11-18 12:10:26 +0100157void CellularCapabilityGSM::OnServiceCreated() {
Darin Petkov31332412012-01-28 01:50:02 +0100158 // If IMSI is available, base the service's storage identifier on it.
159 if (!imsi_.empty()) {
160 cellular()->service()->SetStorageIdentifier(
Darin Petkovdd3e8662012-02-03 13:16:20 +0100161 string(flimflam::kTypeCellular) + "_" +
162 cellular()->address() + "_" + imsi_);
Darin Petkov31332412012-01-28 01:50:02 +0100163 }
Darin Petkovb9c99332012-01-12 13:13:00 +0100164 cellular()->service()->SetActivationState(
Darin Petkov5f316f62011-11-18 12:10:26 +0100165 flimflam::kActivationStateActivated);
166 UpdateServingOperator();
167}
168
Darin Petkovae0c64e2011-11-15 15:50:27 +0100169void CellularCapabilityGSM::UpdateStatus(const DBusPropertiesMap &properties) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500170 if (ContainsKey(properties, kPropertyIMSI)) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100171 SetHomeProvider();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100172 }
173}
174
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400175// Create the list of APNs to try, in the following order:
176// - last APN that resulted in a successful connection attempt on the
177// current network (if any)
178// - the APN, if any, that was set by the user
179// - the list of APNs found in the mobile broadband provider DB for the
180// home provider associated with the current SIM
181// - as a last resort, attempt to connect with no APN
182void CellularCapabilityGSM::SetupApnTryList() {
183 apn_try_list_.clear();
184
185 DCHECK(cellular()->service().get());
186 const Stringmap *apn_info = cellular()->service()->GetLastGoodApn();
187 if (apn_info)
188 apn_try_list_.push_back(*apn_info);
189
190 apn_info = cellular()->service()->GetUserSpecifiedApn();
191 if (apn_info)
192 apn_try_list_.push_back(*apn_info);
193
194 apn_try_list_.insert(apn_try_list_.end(), apn_list_.begin(), apn_list_.end());
195}
196
Darin Petkovae0c64e2011-11-15 15:50:27 +0100197void CellularCapabilityGSM::SetupConnectProperties(
198 DBusPropertiesMap *properties) {
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400199 SetupApnTryList();
200 FillConnectPropertyMap(properties);
201}
202
203void CellularCapabilityGSM::FillConnectPropertyMap(
204 DBusPropertiesMap *properties) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500205 (*properties)[kConnectPropertyPhoneNumber].writer().append_string(
Darin Petkovae0c64e2011-11-15 15:50:27 +0100206 kPhoneNumber);
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400207
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400208 if (!AllowRoaming())
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400209 (*properties)[kConnectPropertyHomeOnly].writer().append_bool(true);
210
211 if (!apn_try_list_.empty()) {
212 // Leave the APN at the front of the list, so that it can be recorded
213 // if the connect attempt succeeds.
214 Stringmap apn_info = apn_try_list_.front();
215 VLOG(2) << __func__ << ": Using APN " << apn_info[flimflam::kApnProperty];
216 (*properties)[kConnectPropertyApn].writer().append_string(
217 apn_info[flimflam::kApnProperty].c_str());
218 if (ContainsKey(apn_info, flimflam::kApnUsernameProperty))
219 (*properties)[kConnectPropertyApnUsername].writer().append_string(
220 apn_info[flimflam::kApnUsernameProperty].c_str());
221 if (ContainsKey(apn_info, flimflam::kApnPasswordProperty))
222 (*properties)[kConnectPropertyApnPassword].writer().append_string(
223 apn_info[flimflam::kApnPasswordProperty].c_str());
224 }
225}
226
Nathan Williamsb54974f2012-04-19 11:16:30 -0400227void CellularCapabilityGSM::Connect(const DBusPropertiesMap &properties,
228 Error *error,
229 const ResultCallback &callback) {
230 VLOG(2) << __func__;
231 ResultCallback cb = Bind(&CellularCapabilityGSM::OnConnectReply,
232 weak_ptr_factory_.GetWeakPtr(),
233 callback);
234 simple_proxy_->Connect(properties, error, cb, kTimeoutConnect);
235}
236
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400237void CellularCapabilityGSM::OnConnectReply(const ResultCallback &callback,
238 const Error &error) {
239 if (error.IsFailure()) {
240 cellular()->service()->ClearLastGoodApn();
241 // The APN that was just tried (and failed) is still at the
242 // front of the list, about to be removed. If the list is empty
243 // after that, try one last time without an APN. This may succeed
244 // with some modems in some cases.
245 if (error.type() == Error::kInvalidApn && !apn_try_list_.empty()) {
246 apn_try_list_.pop_front();
247 VLOG(2) << "Connect failed with invalid APN, " << apn_try_list_.size()
248 << " remaining APNs to try";
249 DBusPropertiesMap props;
250 FillConnectPropertyMap(&props);
251 Error error;
252 Connect(props, &error, callback);
253 return;
254 }
255 } else if (!apn_try_list_.empty()) {
256 cellular()->service()->SetLastGoodApn(apn_try_list_.front());
257 apn_try_list_.clear();
258 }
Nathan Williamsb54974f2012-04-19 11:16:30 -0400259 if (!callback.is_null())
260 callback.Run(error);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400261}
262
263bool CellularCapabilityGSM::AllowRoaming() {
264 bool requires_roaming =
265 home_provider_ ? home_provider_->requires_roaming : false;
266 return requires_roaming || allow_roaming_property();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100267}
268
Eric Shienbrood9a245532012-03-07 14:20:39 -0500269// always called from an async context
270void CellularCapabilityGSM::GetIMEI(const ResultCallback &callback) {
Darin Petkovcb547732011-11-09 13:55:26 +0100271 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500272 CHECK(!callback.is_null());
273 Error error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500274 if (imei_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500275 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMEIReply,
276 weak_ptr_factory_.GetWeakPtr(), callback);
277 card_proxy_->GetIMEI(&error, cb, kTimeoutDefault);
278 if (error.IsFailure())
279 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500280 } else {
281 VLOG(2) << "Already have IMEI " << imei_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500282 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100283 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500284}
285
Eric Shienbrood9a245532012-03-07 14:20:39 -0500286// always called from an async context
287void CellularCapabilityGSM::GetIMSI(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500288 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500289 CHECK(!callback.is_null());
290 Error error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500291 if (imsi_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500292 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMSIReply,
293 weak_ptr_factory_.GetWeakPtr(),
294 callback);
295 card_proxy_->GetIMSI(&error, cb, kTimeoutDefault);
296 if (error.IsFailure())
297 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500298 } else {
299 VLOG(2) << "Already have IMSI " << imsi_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500300 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100301 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500302}
303
Eric Shienbrood9a245532012-03-07 14:20:39 -0500304// always called from an async context
305void CellularCapabilityGSM::GetSPN(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500306 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500307 CHECK(!callback.is_null());
308 Error error;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100309 if (spn_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500310 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetSPNReply,
311 weak_ptr_factory_.GetWeakPtr(),
312 callback);
313 card_proxy_->GetSPN(&error, cb, kTimeoutDefault);
314 if (error.IsFailure())
315 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500316 } else {
317 VLOG(2) << "Already have SPN " << spn_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500318 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100319 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500320}
321
Eric Shienbrood9a245532012-03-07 14:20:39 -0500322// always called from an async context
323void CellularCapabilityGSM::GetMSISDN(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500324 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500325 CHECK(!callback.is_null());
326 Error error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500327 if (mdn_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500328 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetMSISDNReply,
329 weak_ptr_factory_.GetWeakPtr(),
330 callback);
331 card_proxy_->GetMSISDN(&error, cb, kTimeoutDefault);
332 if (error.IsFailure())
333 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500334 } else {
335 VLOG(2) << "Already have MSISDN " << mdn_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500336 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100337 }
338}
339
Darin Petkov3e509242011-11-10 14:46:44 +0100340void CellularCapabilityGSM::GetSignalQuality() {
341 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500342 SignalQualityCallback callback =
343 Bind(&CellularCapabilityGSM::OnGetSignalQualityReply,
344 weak_ptr_factory_.GetWeakPtr());
345 network_proxy_->GetSignalQuality(NULL, callback, kTimeoutDefault);
Darin Petkov3e509242011-11-10 14:46:44 +0100346}
347
Eric Shienbrood9a245532012-03-07 14:20:39 -0500348void CellularCapabilityGSM::GetRegistrationState() {
Darin Petkov184c54e2011-11-15 12:44:39 +0100349 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500350 RegistrationInfoCallback callback =
351 Bind(&CellularCapabilityGSM::OnGetRegistrationInfoReply,
352 weak_ptr_factory_.GetWeakPtr());
353 network_proxy_->GetRegistrationInfo(NULL, callback, kTimeoutDefault);
Darin Petkov184c54e2011-11-15 12:44:39 +0100354}
355
Eric Shienbrood9a245532012-03-07 14:20:39 -0500356void CellularCapabilityGSM::GetProperties(const ResultCallback &callback) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100357 VLOG(2) << __func__;
Darin Petkov63138a92012-02-06 14:09:15 +0100358
Darin Petkov184c54e2011-11-15 12:44:39 +0100359 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
360 uint32 tech = network_proxy_->AccessTechnology();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100361 SetAccessTechnology(tech);
Darin Petkov184c54e2011-11-15 12:44:39 +0100362 VLOG(2) << "GSM AccessTechnology: " << tech;
Darin Petkov63138a92012-02-06 14:09:15 +0100363
364 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
365 uint32 locks = card_proxy_->EnabledFacilityLocks();
366 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
367 VLOG(2) << "GSM EnabledFacilityLocks: " << locks;
368
Eric Shienbrood9a245532012-03-07 14:20:39 -0500369 callback.Run(Error());
Darin Petkov184c54e2011-11-15 12:44:39 +0100370}
371
Darin Petkovac635a82012-01-10 16:51:58 +0100372string CellularCapabilityGSM::CreateFriendlyServiceName() {
373 VLOG(2) << __func__;
374 if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME &&
375 !cellular()->home_provider().GetName().empty()) {
376 return cellular()->home_provider().GetName();
377 }
378 if (!serving_operator_.GetName().empty()) {
379 return serving_operator_.GetName();
380 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500381 if (!carrier_.empty()) {
382 return carrier_;
Darin Petkovac635a82012-01-10 16:51:58 +0100383 }
384 if (!serving_operator_.GetCode().empty()) {
385 return "cellular_" + serving_operator_.GetCode();
386 }
387 return base::StringPrintf("GSMNetwork%u", friendly_service_name_id_++);
388}
389
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100390void CellularCapabilityGSM::SetHomeProvider() {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500391 VLOG(2) << __func__ << "(IMSI: " << imsi_
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100392 << " SPN: " << spn_ << ")";
393 // TODO(petkov): The test for NULL provider_db should be done by
394 // mobile_provider_lookup_best_match.
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500395 if (imsi_.empty() || !cellular()->provider_db()) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100396 return;
397 }
398 mobile_provider *provider =
399 mobile_provider_lookup_best_match(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500400 cellular()->provider_db(), spn_.c_str(), imsi_.c_str());
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100401 if (!provider) {
402 VLOG(2) << "GSM provider not found.";
403 return;
404 }
405 home_provider_ = provider;
406 Cellular::Operator oper;
407 if (provider->networks) {
408 oper.SetCode(provider->networks[0]);
409 }
410 if (provider->country) {
411 oper.SetCountry(provider->country);
412 }
413 if (spn_.empty()) {
414 const char *name = mobile_provider_get_name(provider);
415 if (name) {
416 oper.SetName(name);
417 }
418 } else {
419 oper.SetName(spn_);
420 }
421 cellular()->set_home_provider(oper);
Darin Petkov3cfbf212011-11-21 16:02:09 +0100422 InitAPNList();
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100423}
424
Darin Petkovae0c64e2011-11-15 15:50:27 +0100425void CellularCapabilityGSM::UpdateOperatorInfo() {
426 VLOG(2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100427 const string &network_id = serving_operator_.GetCode();
428 if (!network_id.empty()) {
429 VLOG(2) << "Looking up network id: " << network_id;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100430 mobile_provider *provider =
431 mobile_provider_lookup_by_network(cellular()->provider_db(),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100432 network_id.c_str());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100433 if (provider) {
434 const char *provider_name = mobile_provider_get_name(provider);
435 if (provider_name && *provider_name) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100436 serving_operator_.SetName(provider_name);
437 if (provider->country) {
438 serving_operator_.SetCountry(provider->country);
439 }
440 VLOG(2) << "Operator name: " << serving_operator_.GetName()
441 << ", country: " << serving_operator_.GetCountry();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100442 }
443 } else {
444 VLOG(2) << "GSM provider not found.";
445 }
446 }
447 UpdateServingOperator();
448}
449
450void CellularCapabilityGSM::UpdateServingOperator() {
451 VLOG(2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100452 if (cellular()->service().get()) {
Darin Petkov9cb02682012-01-28 00:17:38 +0100453 cellular()->service()->SetServingOperator(serving_operator_);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100454 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100455}
456
Darin Petkov3cfbf212011-11-21 16:02:09 +0100457void CellularCapabilityGSM::InitAPNList() {
458 VLOG(2) << __func__;
459 if (!home_provider_) {
460 return;
461 }
462 apn_list_.clear();
463 for (int i = 0; i < home_provider_->num_apns; ++i) {
464 Stringmap props;
465 mobile_apn *apn = home_provider_->apns[i];
466 if (apn->value) {
467 props[flimflam::kApnProperty] = apn->value;
468 }
469 if (apn->username) {
470 props[flimflam::kApnUsernameProperty] = apn->username;
471 }
472 if (apn->password) {
473 props[flimflam::kApnPasswordProperty] = apn->password;
474 }
475 // Find the first localized and non-localized name, if any.
476 const localized_name *lname = NULL;
477 const localized_name *name = NULL;
478 for (int j = 0; j < apn->num_names; ++j) {
479 if (apn->names[j]->lang) {
480 if (!lname) {
481 lname = apn->names[j];
482 }
483 } else if (!name) {
484 name = apn->names[j];
485 }
486 }
487 if (name) {
488 props[flimflam::kApnNameProperty] = name->name;
489 }
490 if (lname) {
491 props[flimflam::kApnLocalizedNameProperty] = lname->name;
492 props[flimflam::kApnLanguageProperty] = lname->lang;
493 }
494 apn_list_.push_back(props);
495 }
496 cellular()->adaptor()->EmitStringmapsChanged(
497 flimflam::kCellularApnListProperty, apn_list_);
498}
499
Eric Shienbrood9a245532012-03-07 14:20:39 -0500500// always called from an async context
501void CellularCapabilityGSM::Register(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500502 VLOG(2) << __func__ << " \"" << selected_network_ << "\"";
Eric Shienbrood9a245532012-03-07 14:20:39 -0500503 CHECK(!callback.is_null());
504 Error error;
505 ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply,
506 weak_ptr_factory_.GetWeakPtr(), callback);
507 network_proxy_->Register(selected_network_, &error, cb, kTimeoutRegister);
508 if (error.IsFailure())
509 callback.Run(error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100510}
511
512void CellularCapabilityGSM::RegisterOnNetwork(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500513 const string &network_id,
514 Error *error,
515 const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500516 VLOG(2) << __func__ << "(" << network_id << ")";
Eric Shienbrood9a245532012-03-07 14:20:39 -0500517 CHECK(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500518 desired_network_ = network_id;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500519 ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply,
520 weak_ptr_factory_.GetWeakPtr(), callback);
521 network_proxy_->Register(network_id, error, cb, kTimeoutRegister);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500522}
523
Eric Shienbrood9a245532012-03-07 14:20:39 -0500524void CellularCapabilityGSM::OnRegisterReply(const ResultCallback &callback,
525 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500526 VLOG(2) << __func__ << "(" << error << ")";
527
528 if (error.IsSuccess()) {
529 selected_network_ = desired_network_;
530 desired_network_.clear();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500531 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500532 return;
533 }
534 // If registration on the desired network failed,
535 // try to register on the home network.
536 if (!desired_network_.empty()) {
537 desired_network_.clear();
538 selected_network_.clear();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500539 LOG(INFO) << "Couldn't register on selected network, trying home network";
540 Register(callback);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500541 return;
542 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500543 callback.Run(error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100544}
545
Darin Petkovb72cf402011-11-22 14:51:39 +0100546bool CellularCapabilityGSM::IsRegistered() {
547 return (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
548 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING);
549}
550
Darin Petkovb05315f2011-11-07 10:14:25 +0100551void CellularCapabilityGSM::RequirePIN(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500552 const std::string &pin, bool require,
553 Error *error, const ResultCallback &callback) {
554 CHECK(error);
555 card_proxy_->EnablePIN(pin, require, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100556}
557
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100558void CellularCapabilityGSM::EnterPIN(const string &pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500559 Error *error,
560 const ResultCallback &callback) {
561 CHECK(error);
562 card_proxy_->SendPIN(pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100563}
564
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100565void CellularCapabilityGSM::UnblockPIN(const string &unblock_code,
566 const string &pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500567 Error *error,
568 const ResultCallback &callback) {
569 CHECK(error);
570 card_proxy_->SendPUK(unblock_code, pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100571}
572
573void CellularCapabilityGSM::ChangePIN(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500574 const string &old_pin, const string &new_pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500575 Error *error, const ResultCallback &callback) {
576 CHECK(error);
577 card_proxy_->ChangePIN(old_pin, new_pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100578}
579
Eric Shienbrood9a245532012-03-07 14:20:39 -0500580void CellularCapabilityGSM::Scan(Error *error, const ResultCallback &callback) {
Darin Petkov1272a432011-11-10 15:53:37 +0100581 VLOG(2) << __func__;
582 // TODO(petkov): Defer scan requests if a scan is in progress already.
Eric Shienbrood9a245532012-03-07 14:20:39 -0500583 CHECK(error);
584 ScanResultsCallback cb = Bind(&CellularCapabilityGSM::OnScanReply,
585 weak_ptr_factory_.GetWeakPtr(), callback);
586 network_proxy_->Scan(error, cb, kTimeoutScan);
Darin Petkov1272a432011-11-10 15:53:37 +0100587}
588
Eric Shienbrood9a245532012-03-07 14:20:39 -0500589void CellularCapabilityGSM::OnScanReply(const ResultCallback &callback,
590 const GSMScanResults &results,
591 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500592 VLOG(2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400593
594 // Error handling is weak. The current expectation is that on any
595 // error, found_networks_ should be cleared and a property change
596 // notification sent out.
597 //
598 // TODO(jglasgow): fix error handling
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500599 found_networks_.clear();
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400600 if (!error.IsFailure()) {
601 for (GSMScanResults::const_iterator it = results.begin();
602 it != results.end(); ++it) {
603 found_networks_.push_back(ParseScanResult(*it));
604 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500605 }
Darin Petkovb7828b02012-02-03 12:34:30 +0100606 cellular()->adaptor()->EmitStringmapsChanged(flimflam::kFoundNetworksProperty,
607 found_networks_);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500608 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500609}
610
611Stringmap CellularCapabilityGSM::ParseScanResult(const GSMScanResult &result) {
Darin Petkov1272a432011-11-10 15:53:37 +0100612 Stringmap parsed;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500613 for (GSMScanResult::const_iterator it = result.begin();
614 it != result.end(); ++it) {
Darin Petkov1272a432011-11-10 15:53:37 +0100615 // TODO(petkov): Define these in system_api/service_constants.h. The
616 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
617 static const char * const kStatusString[] = {
618 "unknown",
619 "available",
620 "current",
621 "forbidden",
622 };
623 static const char * const kTechnologyString[] = {
624 flimflam::kNetworkTechnologyGsm,
625 "GSM Compact",
626 flimflam::kNetworkTechnologyUmts,
627 flimflam::kNetworkTechnologyEdge,
628 "HSDPA",
629 "HSUPA",
630 flimflam::kNetworkTechnologyHspa,
631 };
632 VLOG(2) << "Network property: " << it->first << " = " << it->second;
633 if (it->first == kNetworkPropertyStatus) {
634 int status = 0;
635 if (base::StringToInt(it->second, &status) &&
636 status >= 0 &&
637 status < static_cast<int>(arraysize(kStatusString))) {
638 parsed[flimflam::kStatusProperty] = kStatusString[status];
639 } else {
640 LOG(ERROR) << "Unexpected status value: " << it->second;
641 }
642 } else if (it->first == kNetworkPropertyID) {
643 parsed[flimflam::kNetworkIdProperty] = it->second;
644 } else if (it->first == kNetworkPropertyLongName) {
645 parsed[flimflam::kLongNameProperty] = it->second;
646 } else if (it->first == kNetworkPropertyShortName) {
647 parsed[flimflam::kShortNameProperty] = it->second;
648 } else if (it->first == kNetworkPropertyAccessTechnology) {
649 int tech = 0;
650 if (base::StringToInt(it->second, &tech) &&
651 tech >= 0 &&
652 tech < static_cast<int>(arraysize(kTechnologyString))) {
653 parsed[flimflam::kTechnologyProperty] = kTechnologyString[tech];
654 } else {
655 LOG(ERROR) << "Unexpected technology value: " << it->second;
656 }
657 } else {
658 LOG(WARNING) << "Unknown network property ignored: " << it->first;
659 }
660 }
661 // If the long name is not available but the network ID is, look up the long
662 // name in the mobile provider database.
663 if ((!ContainsKey(parsed, flimflam::kLongNameProperty) ||
664 parsed[flimflam::kLongNameProperty].empty()) &&
665 ContainsKey(parsed, flimflam::kNetworkIdProperty)) {
666 mobile_provider *provider =
667 mobile_provider_lookup_by_network(
668 cellular()->provider_db(),
669 parsed[flimflam::kNetworkIdProperty].c_str());
670 if (provider) {
671 const char *long_name = mobile_provider_get_name(provider);
672 if (long_name && *long_name) {
673 parsed[flimflam::kLongNameProperty] = long_name;
674 }
675 }
676 }
677 return parsed;
678}
679
Darin Petkovae0c64e2011-11-15 15:50:27 +0100680void CellularCapabilityGSM::SetAccessTechnology(uint32 access_technology) {
681 access_technology_ = access_technology;
682 if (cellular()->service().get()) {
Darin Petkovb72cf402011-11-22 14:51:39 +0100683 cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100684 }
685}
686
Darin Petkov20c13ec2011-11-09 15:07:15 +0100687string CellularCapabilityGSM::GetNetworkTechnologyString() const {
Darin Petkovb72cf402011-11-22 14:51:39 +0100688 switch (access_technology_) {
689 case MM_MODEM_GSM_ACCESS_TECH_GSM:
690 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
691 return flimflam::kNetworkTechnologyGsm;
692 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
693 return flimflam::kNetworkTechnologyGprs;
694 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
695 return flimflam::kNetworkTechnologyEdge;
696 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
697 return flimflam::kNetworkTechnologyUmts;
698 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
699 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
700 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
701 return flimflam::kNetworkTechnologyHspa;
702 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
703 return flimflam::kNetworkTechnologyHspaPlus;
704 default:
705 break;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100706 }
707 return "";
708}
709
710string CellularCapabilityGSM::GetRoamingStateString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100711 switch (registration_state_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100712 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
713 return flimflam::kRoamingStateHome;
714 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
715 return flimflam::kRoamingStateRoaming;
716 default:
717 break;
718 }
719 return flimflam::kRoamingStateUnknown;
720}
721
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400722void CellularCapabilityGSM::OnDBusPropertiesChanged(
723 const string &interface,
724 const DBusPropertiesMap &properties,
725 const vector<string> &/* invalidated_properties */) {
726 if (interface != MM_MODEM_INTERFACE)
727 return;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100728 uint32 access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
729 if (DBusProperties::GetUint32(properties,
730 kPropertyAccessTechnology,
731 &access_technology)) {
732 SetAccessTechnology(access_technology);
733 }
Darin Petkov63138a92012-02-06 14:09:15 +0100734 bool emit = false;
735 uint32 locks = 0;
736 if (DBusProperties::GetUint32(
737 properties, kPropertyEnabledFacilityLocks, &locks)) {
738 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
739 emit = true;
740 }
741 if (DBusProperties::GetString(
742 properties, kPropertyUnlockRequired, &sim_lock_status_.lock_type)) {
743 emit = true;
744 }
745 if (DBusProperties::GetUint32(
746 properties, kPropertyUnlockRetries, &sim_lock_status_.retries_left)) {
747 emit = true;
748 }
749 if (emit) {
750 cellular()->adaptor()->EmitKeyValueStoreChanged(
751 flimflam::kSIMLockStatusProperty, SimLockStatusToProperty(NULL));
752 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100753}
754
Eric Shienbrood9a245532012-03-07 14:20:39 -0500755void CellularCapabilityGSM::OnNetworkModeSignal(uint32 /*mode*/) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100756 // TODO(petkov): Implement this.
757 NOTIMPLEMENTED();
758}
759
Eric Shienbrood9a245532012-03-07 14:20:39 -0500760void CellularCapabilityGSM::OnRegistrationInfoSignal(
761 uint32 status, const string &operator_code, const string &operator_name) {
762 VLOG(2) << __func__ << ": regstate=" << status
763 << ", opercode=" << operator_code
764 << ", opername=" << operator_name;
765 registration_state_ = status;
766 serving_operator_.SetCode(operator_code);
767 serving_operator_.SetName(operator_name);
768 UpdateOperatorInfo();
769 cellular()->HandleNewRegistrationState();
Darin Petkov184c54e2011-11-15 12:44:39 +0100770}
771
Eric Shienbrood9a245532012-03-07 14:20:39 -0500772void CellularCapabilityGSM::OnSignalQualitySignal(uint32 quality) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100773 cellular()->HandleNewSignalQuality(quality);
774}
775
Eric Shienbrood9a245532012-03-07 14:20:39 -0500776void CellularCapabilityGSM::OnGetRegistrationInfoReply(
777 uint32 status, const string &operator_code, const string &operator_name,
778 const Error &error) {
779 if (error.IsSuccess())
780 OnRegistrationInfoSignal(status, operator_code, operator_name);
781}
782
783void CellularCapabilityGSM::OnGetSignalQualityReply(uint32 quality,
784 const Error &error) {
785 if (error.IsSuccess())
786 OnSignalQualitySignal(quality);
787}
788
789void CellularCapabilityGSM::OnGetIMEIReply(const ResultCallback &callback,
790 const string &imei,
791 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500792 if (error.IsSuccess()) {
793 VLOG(2) << "IMEI: " << imei;
794 imei_ = imei;
795 } else {
796 VLOG(2) << "GetIMEI failed - " << error;
797 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500798 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500799}
800
Eric Shienbrood9a245532012-03-07 14:20:39 -0500801void CellularCapabilityGSM::OnGetIMSIReply(const ResultCallback &callback,
802 const string &imsi,
803 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500804 if (error.IsSuccess()) {
805 VLOG(2) << "IMSI: " << imsi;
806 imsi_ = imsi;
807 SetHomeProvider();
808 } else {
809 VLOG(2) << "GetIMSI failed - " << error;
810 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500811 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500812}
813
Eric Shienbrood9a245532012-03-07 14:20:39 -0500814void CellularCapabilityGSM::OnGetSPNReply(const ResultCallback &callback,
815 const string &spn,
816 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500817 if (error.IsSuccess()) {
818 VLOG(2) << "SPN: " << spn;
819 spn_ = spn;
820 SetHomeProvider();
821 } else {
822 VLOG(2) << "GetSPN failed - " << error;
823 }
Thieu Le923006b2012-04-05 16:32:58 -0700824 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500825}
826
Eric Shienbrood9a245532012-03-07 14:20:39 -0500827void CellularCapabilityGSM::OnGetMSISDNReply(const ResultCallback &callback,
828 const string &msisdn,
829 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500830 if (error.IsSuccess()) {
831 VLOG(2) << "MSISDN: " << msisdn;
832 mdn_ = msisdn;
833 } else {
834 VLOG(2) << "GetMSISDN failed - " << error;
835 }
Thieu Le923006b2012-04-05 16:32:58 -0700836 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500837}
838
Darin Petkovdaf43862011-10-27 11:37:28 +0200839} // namespace shill