blob: 5492bed7352afe9ed83d1ac2568a8c9e687f6284 [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"
Ben Chanfad4a0b2012-04-18 15:49:59 -070024#include "shill/scope_logger.h"
Darin Petkovdaf43862011-10-27 11:37:28 +020025
Eric Shienbrood3e20a232012-02-16 11:35:56 -050026using base::Bind;
Darin Petkovb05315f2011-11-07 10:14:25 +010027using std::string;
Jason Glasgow4c0724a2012-04-17 15:47:40 -040028using std::vector;
Darin Petkovb05315f2011-11-07 10:14:25 +010029
Darin Petkovdaf43862011-10-27 11:37:28 +020030namespace shill {
31
Darin Petkovac635a82012-01-10 16:51:58 +010032// static
33unsigned int CellularCapabilityGSM::friendly_service_name_id_ = 0;
34
Darin Petkov1272a432011-11-10 15:53:37 +010035const char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] =
36 "access-tech";
37const char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num";
38const char CellularCapabilityGSM::kNetworkPropertyLongName[] = "operator-long";
39const char CellularCapabilityGSM::kNetworkPropertyShortName[] =
40 "operator-short";
41const char CellularCapabilityGSM::kNetworkPropertyStatus[] = "status";
Darin Petkovae0c64e2011-11-15 15:50:27 +010042const char CellularCapabilityGSM::kPhoneNumber[] = "*99#";
43const char CellularCapabilityGSM::kPropertyAccessTechnology[] =
44 "AccessTechnology";
Darin Petkov63138a92012-02-06 14:09:15 +010045const char CellularCapabilityGSM::kPropertyEnabledFacilityLocks[] =
46 "EnabledFacilityLocks";
Darin Petkov721ac932011-11-16 15:43:09 +010047const char CellularCapabilityGSM::kPropertyUnlockRequired[] = "UnlockRequired";
48const char CellularCapabilityGSM::kPropertyUnlockRetries[] = "UnlockRetries";
Darin Petkov1272a432011-11-10 15:53:37 +010049
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050050CellularCapabilityGSM::CellularCapabilityGSM(Cellular *cellular,
51 ProxyFactory *proxy_factory)
Jason Glasgow82f9ab32012-04-04 14:27:19 -040052 : CellularCapabilityClassic(cellular, proxy_factory),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050053 weak_ptr_factory_(this),
Darin Petkov184c54e2011-11-15 12:44:39 +010054 registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
Darin Petkovae0c64e2011-11-15 15:50:27 +010055 access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +010056 home_provider_(NULL),
Darin Petkov1272a432011-11-10 15:53:37 +010057 scanning_(false),
58 scan_interval_(0) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070059 SLOG(Cellular, 2) << "Cellular capability constructed: GSM";
Darin Petkov1272a432011-11-10 15:53:37 +010060 PropertyStore *store = cellular->mutable_store();
Darin Petkov184c54e2011-11-15 12:44:39 +010061 store->RegisterConstString(flimflam::kSelectedNetworkProperty,
62 &selected_network_);
Darin Petkov1272a432011-11-10 15:53:37 +010063 store->RegisterConstStringmaps(flimflam::kFoundNetworksProperty,
64 &found_networks_);
65 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
66 store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
Darin Petkov63138a92012-02-06 14:09:15 +010067 HelpRegisterDerivedKeyValueStore(
68 flimflam::kSIMLockStatusProperty,
69 &CellularCapabilityGSM::SimLockStatusToProperty,
70 NULL);
Darin Petkov3cfbf212011-11-21 16:02:09 +010071 store->RegisterConstStringmaps(flimflam::kCellularApnListProperty,
72 &apn_list_);
Darin Petkov0d06f7d2012-02-03 13:08:19 +010073 scanning_supported_ = true;
Darin Petkov1272a432011-11-10 15:53:37 +010074}
Darin Petkovdaf43862011-10-27 11:37:28 +020075
Darin Petkov63138a92012-02-06 14:09:15 +010076KeyValueStore CellularCapabilityGSM::SimLockStatusToProperty(Error */*error*/) {
77 KeyValueStore status;
78 status.SetBool(flimflam::kSIMLockEnabledProperty, sim_lock_status_.enabled);
79 status.SetString(flimflam::kSIMLockTypeProperty, sim_lock_status_.lock_type);
80 status.SetUint(flimflam::kSIMLockRetriesLeftProperty,
81 sim_lock_status_.retries_left);
82 return status;
Darin Petkov721ac932011-11-16 15:43:09 +010083}
84
Darin Petkov63138a92012-02-06 14:09:15 +010085void CellularCapabilityGSM::HelpRegisterDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +010086 const string &name,
Darin Petkov63138a92012-02-06 14:09:15 +010087 KeyValueStore(CellularCapabilityGSM::*get)(Error *error),
88 void(CellularCapabilityGSM::*set)(
89 const KeyValueStore &value, Error *error)) {
90 cellular()->mutable_store()->RegisterDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +010091 name,
Darin Petkov63138a92012-02-06 14:09:15 +010092 KeyValueStoreAccessor(
93 new CustomAccessor<CellularCapabilityGSM, KeyValueStore>(
Darin Petkov721ac932011-11-16 15:43:09 +010094 this, get, set)));
95}
96
Eric Shienbrood9a245532012-03-07 14:20:39 -050097void CellularCapabilityGSM::InitProxies() {
Jason Glasgow82f9ab32012-04-04 14:27:19 -040098 CellularCapabilityClassic::InitProxies();
Darin Petkovcb547732011-11-09 13:55:26 +010099 card_proxy_.reset(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500100 proxy_factory()->CreateModemGSMCardProxy(cellular()->dbus_path(),
Darin Petkovdaf43862011-10-27 11:37:28 +0200101 cellular()->dbus_owner()));
Darin Petkov184c54e2011-11-15 12:44:39 +0100102 network_proxy_.reset(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500103 proxy_factory()->CreateModemGSMNetworkProxy(cellular()->dbus_path(),
Darin Petkovdaf43862011-10-27 11:37:28 +0200104 cellular()->dbus_owner()));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500105 network_proxy_->set_signal_quality_callback(
106 Bind(&CellularCapabilityGSM::OnSignalQualitySignal,
107 weak_ptr_factory_.GetWeakPtr()));
108 network_proxy_->set_network_mode_callback(
109 Bind(&CellularCapabilityGSM::OnNetworkModeSignal,
110 weak_ptr_factory_.GetWeakPtr()));
111 network_proxy_->set_registration_info_callback(
112 Bind(&CellularCapabilityGSM::OnRegistrationInfoSignal,
113 weak_ptr_factory_.GetWeakPtr()));
Darin Petkovdaf43862011-10-27 11:37:28 +0200114}
115
Eric Shienbrood9a245532012-03-07 14:20:39 -0500116void CellularCapabilityGSM::StartModem(Error *error,
117 const ResultCallback &callback) {
118 InitProxies();
119
120 CellularTaskList *tasks = new CellularTaskList();
121 ResultCallback cb =
122 Bind(&CellularCapabilityGSM::StepCompletedCallback,
Thieu Le923006b2012-04-05 16:32:58 -0700123 weak_ptr_factory_.GetWeakPtr(), callback, false, tasks);
124 ResultCallback cb_ignore_error =
125 Bind(&CellularCapabilityGSM::StepCompletedCallback,
126 weak_ptr_factory_.GetWeakPtr(), callback, true, tasks);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500127 tasks->push_back(Bind(&CellularCapabilityGSM::EnableModem,
128 weak_ptr_factory_.GetWeakPtr(), cb));
129 tasks->push_back(Bind(&CellularCapabilityGSM::Register,
130 weak_ptr_factory_.GetWeakPtr(), cb));
131 tasks->push_back(Bind(&CellularCapabilityGSM::GetModemStatus,
132 weak_ptr_factory_.GetWeakPtr(), cb));
133 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMEI,
134 weak_ptr_factory_.GetWeakPtr(), cb));
135 tasks->push_back(Bind(&CellularCapabilityGSM::GetIMSI,
136 weak_ptr_factory_.GetWeakPtr(), cb));
137 tasks->push_back(Bind(&CellularCapabilityGSM::GetSPN,
Thieu Le923006b2012-04-05 16:32:58 -0700138 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500139 tasks->push_back(Bind(&CellularCapabilityGSM::GetMSISDN,
Thieu Le923006b2012-04-05 16:32:58 -0700140 weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500141 tasks->push_back(Bind(&CellularCapabilityGSM::GetProperties,
142 weak_ptr_factory_.GetWeakPtr(), cb));
143 tasks->push_back(Bind(&CellularCapabilityGSM::GetModemInfo,
144 weak_ptr_factory_.GetWeakPtr(), cb));
145 tasks->push_back(Bind(&CellularCapabilityGSM::FinishEnable,
146 weak_ptr_factory_.GetWeakPtr(), cb));
147
148 RunNextStep(tasks);
149}
150
Eric Shienbrood9a245532012-03-07 14:20:39 -0500151void CellularCapabilityGSM::ReleaseProxies() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700152 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400153 CellularCapabilityClassic::ReleaseProxies();
Darin Petkov721ac932011-11-16 15:43:09 +0100154 card_proxy_.reset();
155 network_proxy_.reset();
156}
157
Darin Petkov5f316f62011-11-18 12:10:26 +0100158void CellularCapabilityGSM::OnServiceCreated() {
Darin Petkov31332412012-01-28 01:50:02 +0100159 // If IMSI is available, base the service's storage identifier on it.
160 if (!imsi_.empty()) {
161 cellular()->service()->SetStorageIdentifier(
Darin Petkovdd3e8662012-02-03 13:16:20 +0100162 string(flimflam::kTypeCellular) + "_" +
163 cellular()->address() + "_" + imsi_);
Darin Petkov31332412012-01-28 01:50:02 +0100164 }
Darin Petkovb9c99332012-01-12 13:13:00 +0100165 cellular()->service()->SetActivationState(
Darin Petkov5f316f62011-11-18 12:10:26 +0100166 flimflam::kActivationStateActivated);
167 UpdateServingOperator();
168}
169
Darin Petkovae0c64e2011-11-15 15:50:27 +0100170void CellularCapabilityGSM::UpdateStatus(const DBusPropertiesMap &properties) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500171 if (ContainsKey(properties, kPropertyIMSI)) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100172 SetHomeProvider();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100173 }
174}
175
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400176// Create the list of APNs to try, in the following order:
177// - last APN that resulted in a successful connection attempt on the
178// current network (if any)
179// - the APN, if any, that was set by the user
180// - the list of APNs found in the mobile broadband provider DB for the
181// home provider associated with the current SIM
182// - as a last resort, attempt to connect with no APN
183void CellularCapabilityGSM::SetupApnTryList() {
184 apn_try_list_.clear();
185
186 DCHECK(cellular()->service().get());
187 const Stringmap *apn_info = cellular()->service()->GetLastGoodApn();
188 if (apn_info)
189 apn_try_list_.push_back(*apn_info);
190
191 apn_info = cellular()->service()->GetUserSpecifiedApn();
192 if (apn_info)
193 apn_try_list_.push_back(*apn_info);
194
195 apn_try_list_.insert(apn_try_list_.end(), apn_list_.begin(), apn_list_.end());
196}
197
Darin Petkovae0c64e2011-11-15 15:50:27 +0100198void CellularCapabilityGSM::SetupConnectProperties(
199 DBusPropertiesMap *properties) {
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400200 SetupApnTryList();
201 FillConnectPropertyMap(properties);
202}
203
204void CellularCapabilityGSM::FillConnectPropertyMap(
205 DBusPropertiesMap *properties) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500206 (*properties)[kConnectPropertyPhoneNumber].writer().append_string(
Darin Petkovae0c64e2011-11-15 15:50:27 +0100207 kPhoneNumber);
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400208
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400209 if (!AllowRoaming())
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400210 (*properties)[kConnectPropertyHomeOnly].writer().append_bool(true);
211
212 if (!apn_try_list_.empty()) {
213 // Leave the APN at the front of the list, so that it can be recorded
214 // if the connect attempt succeeds.
215 Stringmap apn_info = apn_try_list_.front();
Ben Chanfad4a0b2012-04-18 15:49:59 -0700216 SLOG(Cellular, 2) << __func__ << ": Using APN "
217 << apn_info[flimflam::kApnProperty];
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400218 (*properties)[kConnectPropertyApn].writer().append_string(
219 apn_info[flimflam::kApnProperty].c_str());
220 if (ContainsKey(apn_info, flimflam::kApnUsernameProperty))
221 (*properties)[kConnectPropertyApnUsername].writer().append_string(
222 apn_info[flimflam::kApnUsernameProperty].c_str());
223 if (ContainsKey(apn_info, flimflam::kApnPasswordProperty))
224 (*properties)[kConnectPropertyApnPassword].writer().append_string(
225 apn_info[flimflam::kApnPasswordProperty].c_str());
226 }
227}
228
Nathan Williamsb54974f2012-04-19 11:16:30 -0400229void CellularCapabilityGSM::Connect(const DBusPropertiesMap &properties,
230 Error *error,
231 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700232 SLOG(Cellular, 2) << __func__;
Nathan Williamsb54974f2012-04-19 11:16:30 -0400233 ResultCallback cb = Bind(&CellularCapabilityGSM::OnConnectReply,
234 weak_ptr_factory_.GetWeakPtr(),
235 callback);
236 simple_proxy_->Connect(properties, error, cb, kTimeoutConnect);
237}
238
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400239void CellularCapabilityGSM::OnConnectReply(const ResultCallback &callback,
240 const Error &error) {
241 if (error.IsFailure()) {
242 cellular()->service()->ClearLastGoodApn();
243 // The APN that was just tried (and failed) is still at the
244 // front of the list, about to be removed. If the list is empty
245 // after that, try one last time without an APN. This may succeed
246 // with some modems in some cases.
247 if (error.type() == Error::kInvalidApn && !apn_try_list_.empty()) {
248 apn_try_list_.pop_front();
Ben Chanfad4a0b2012-04-18 15:49:59 -0700249 SLOG(Cellular, 2) << "Connect failed with invalid APN, "
250 << apn_try_list_.size() << " remaining APNs to try";
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400251 DBusPropertiesMap props;
252 FillConnectPropertyMap(&props);
253 Error error;
254 Connect(props, &error, callback);
255 return;
256 }
257 } else if (!apn_try_list_.empty()) {
258 cellular()->service()->SetLastGoodApn(apn_try_list_.front());
259 apn_try_list_.clear();
260 }
Nathan Williamsb54974f2012-04-19 11:16:30 -0400261 if (!callback.is_null())
262 callback.Run(error);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400263}
264
265bool CellularCapabilityGSM::AllowRoaming() {
266 bool requires_roaming =
267 home_provider_ ? home_provider_->requires_roaming : false;
268 return requires_roaming || allow_roaming_property();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100269}
270
Eric Shienbrood9a245532012-03-07 14:20:39 -0500271// always called from an async context
272void CellularCapabilityGSM::GetIMEI(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700273 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500274 CHECK(!callback.is_null());
275 Error error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500276 if (imei_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500277 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMEIReply,
278 weak_ptr_factory_.GetWeakPtr(), callback);
279 card_proxy_->GetIMEI(&error, cb, kTimeoutDefault);
280 if (error.IsFailure())
281 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500282 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700283 SLOG(Cellular, 2) << "Already have IMEI " << imei_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500284 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100285 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500286}
287
Eric Shienbrood9a245532012-03-07 14:20:39 -0500288// always called from an async context
289void CellularCapabilityGSM::GetIMSI(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700290 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500291 CHECK(!callback.is_null());
292 Error error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500293 if (imsi_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500294 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMSIReply,
295 weak_ptr_factory_.GetWeakPtr(),
296 callback);
297 card_proxy_->GetIMSI(&error, cb, kTimeoutDefault);
298 if (error.IsFailure())
299 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500300 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700301 SLOG(Cellular, 2) << "Already have IMSI " << imsi_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500302 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100303 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500304}
305
Eric Shienbrood9a245532012-03-07 14:20:39 -0500306// always called from an async context
307void CellularCapabilityGSM::GetSPN(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700308 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500309 CHECK(!callback.is_null());
310 Error error;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100311 if (spn_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500312 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetSPNReply,
313 weak_ptr_factory_.GetWeakPtr(),
314 callback);
315 card_proxy_->GetSPN(&error, cb, kTimeoutDefault);
316 if (error.IsFailure())
317 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500318 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700319 SLOG(Cellular, 2) << "Already have SPN " << spn_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500320 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100321 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500322}
323
Eric Shienbrood9a245532012-03-07 14:20:39 -0500324// always called from an async context
325void CellularCapabilityGSM::GetMSISDN(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700326 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500327 CHECK(!callback.is_null());
328 Error error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500329 if (mdn_.empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500330 GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetMSISDNReply,
331 weak_ptr_factory_.GetWeakPtr(),
332 callback);
333 card_proxy_->GetMSISDN(&error, cb, kTimeoutDefault);
334 if (error.IsFailure())
335 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500336 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700337 SLOG(Cellular, 2) << "Already have MSISDN " << mdn_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500338 callback.Run(error);
Darin Petkovcb547732011-11-09 13:55:26 +0100339 }
340}
341
Darin Petkov3e509242011-11-10 14:46:44 +0100342void CellularCapabilityGSM::GetSignalQuality() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700343 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500344 SignalQualityCallback callback =
345 Bind(&CellularCapabilityGSM::OnGetSignalQualityReply,
346 weak_ptr_factory_.GetWeakPtr());
347 network_proxy_->GetSignalQuality(NULL, callback, kTimeoutDefault);
Darin Petkov3e509242011-11-10 14:46:44 +0100348}
349
Eric Shienbrood9a245532012-03-07 14:20:39 -0500350void CellularCapabilityGSM::GetRegistrationState() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700351 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500352 RegistrationInfoCallback callback =
353 Bind(&CellularCapabilityGSM::OnGetRegistrationInfoReply,
354 weak_ptr_factory_.GetWeakPtr());
355 network_proxy_->GetRegistrationInfo(NULL, callback, kTimeoutDefault);
Darin Petkov184c54e2011-11-15 12:44:39 +0100356}
357
Eric Shienbrood9a245532012-03-07 14:20:39 -0500358void CellularCapabilityGSM::GetProperties(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700359 SLOG(Cellular, 2) << __func__;
Darin Petkov63138a92012-02-06 14:09:15 +0100360
Darin Petkov184c54e2011-11-15 12:44:39 +0100361 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
362 uint32 tech = network_proxy_->AccessTechnology();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100363 SetAccessTechnology(tech);
Ben Chanfad4a0b2012-04-18 15:49:59 -0700364 SLOG(Cellular, 2) << "GSM AccessTechnology: " << tech;
Darin Petkov63138a92012-02-06 14:09:15 +0100365
366 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
367 uint32 locks = card_proxy_->EnabledFacilityLocks();
368 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
Ben Chanfad4a0b2012-04-18 15:49:59 -0700369 SLOG(Cellular, 2) << "GSM EnabledFacilityLocks: " << locks;
Darin Petkov63138a92012-02-06 14:09:15 +0100370
Eric Shienbrood9a245532012-03-07 14:20:39 -0500371 callback.Run(Error());
Darin Petkov184c54e2011-11-15 12:44:39 +0100372}
373
Darin Petkovac635a82012-01-10 16:51:58 +0100374string CellularCapabilityGSM::CreateFriendlyServiceName() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700375 SLOG(Cellular, 2) << __func__;
Darin Petkovac635a82012-01-10 16:51:58 +0100376 if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME &&
377 !cellular()->home_provider().GetName().empty()) {
378 return cellular()->home_provider().GetName();
379 }
380 if (!serving_operator_.GetName().empty()) {
381 return serving_operator_.GetName();
382 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500383 if (!carrier_.empty()) {
384 return carrier_;
Darin Petkovac635a82012-01-10 16:51:58 +0100385 }
386 if (!serving_operator_.GetCode().empty()) {
387 return "cellular_" + serving_operator_.GetCode();
388 }
389 return base::StringPrintf("GSMNetwork%u", friendly_service_name_id_++);
390}
391
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100392void CellularCapabilityGSM::SetHomeProvider() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700393 SLOG(Cellular, 2) << __func__ << "(IMSI: " << imsi_
394 << " SPN: " << spn_ << ")";
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100395 // TODO(petkov): The test for NULL provider_db should be done by
396 // mobile_provider_lookup_best_match.
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500397 if (imsi_.empty() || !cellular()->provider_db()) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100398 return;
399 }
400 mobile_provider *provider =
401 mobile_provider_lookup_best_match(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500402 cellular()->provider_db(), spn_.c_str(), imsi_.c_str());
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100403 if (!provider) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700404 SLOG(Cellular, 2) << "GSM provider not found.";
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100405 return;
406 }
407 home_provider_ = provider;
408 Cellular::Operator oper;
409 if (provider->networks) {
410 oper.SetCode(provider->networks[0]);
411 }
412 if (provider->country) {
413 oper.SetCountry(provider->country);
414 }
415 if (spn_.empty()) {
416 const char *name = mobile_provider_get_name(provider);
417 if (name) {
418 oper.SetName(name);
419 }
420 } else {
421 oper.SetName(spn_);
422 }
423 cellular()->set_home_provider(oper);
Darin Petkov3cfbf212011-11-21 16:02:09 +0100424 InitAPNList();
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100425}
426
Darin Petkovae0c64e2011-11-15 15:50:27 +0100427void CellularCapabilityGSM::UpdateOperatorInfo() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700428 SLOG(Cellular, 2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100429 const string &network_id = serving_operator_.GetCode();
430 if (!network_id.empty()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700431 SLOG(Cellular, 2) << "Looking up network id: " << network_id;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100432 mobile_provider *provider =
433 mobile_provider_lookup_by_network(cellular()->provider_db(),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100434 network_id.c_str());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100435 if (provider) {
436 const char *provider_name = mobile_provider_get_name(provider);
437 if (provider_name && *provider_name) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100438 serving_operator_.SetName(provider_name);
439 if (provider->country) {
440 serving_operator_.SetCountry(provider->country);
441 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700442 SLOG(Cellular, 2) << "Operator name: " << serving_operator_.GetName()
443 << ", country: " << serving_operator_.GetCountry();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100444 }
445 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700446 SLOG(Cellular, 2) << "GSM provider not found.";
Darin Petkovae0c64e2011-11-15 15:50:27 +0100447 }
448 }
449 UpdateServingOperator();
450}
451
452void CellularCapabilityGSM::UpdateServingOperator() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700453 SLOG(Cellular, 2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100454 if (cellular()->service().get()) {
Darin Petkov9cb02682012-01-28 00:17:38 +0100455 cellular()->service()->SetServingOperator(serving_operator_);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100456 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100457}
458
Darin Petkov3cfbf212011-11-21 16:02:09 +0100459void CellularCapabilityGSM::InitAPNList() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700460 SLOG(Cellular, 2) << __func__;
Darin Petkov3cfbf212011-11-21 16:02:09 +0100461 if (!home_provider_) {
462 return;
463 }
464 apn_list_.clear();
465 for (int i = 0; i < home_provider_->num_apns; ++i) {
466 Stringmap props;
467 mobile_apn *apn = home_provider_->apns[i];
468 if (apn->value) {
469 props[flimflam::kApnProperty] = apn->value;
470 }
471 if (apn->username) {
472 props[flimflam::kApnUsernameProperty] = apn->username;
473 }
474 if (apn->password) {
475 props[flimflam::kApnPasswordProperty] = apn->password;
476 }
477 // Find the first localized and non-localized name, if any.
478 const localized_name *lname = NULL;
479 const localized_name *name = NULL;
480 for (int j = 0; j < apn->num_names; ++j) {
481 if (apn->names[j]->lang) {
482 if (!lname) {
483 lname = apn->names[j];
484 }
485 } else if (!name) {
486 name = apn->names[j];
487 }
488 }
489 if (name) {
490 props[flimflam::kApnNameProperty] = name->name;
491 }
492 if (lname) {
493 props[flimflam::kApnLocalizedNameProperty] = lname->name;
494 props[flimflam::kApnLanguageProperty] = lname->lang;
495 }
496 apn_list_.push_back(props);
497 }
498 cellular()->adaptor()->EmitStringmapsChanged(
499 flimflam::kCellularApnListProperty, apn_list_);
500}
501
Eric Shienbrood9a245532012-03-07 14:20:39 -0500502// always called from an async context
503void CellularCapabilityGSM::Register(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700504 SLOG(Cellular, 2) << __func__ << " \"" << selected_network_ << "\"";
Eric Shienbrood9a245532012-03-07 14:20:39 -0500505 CHECK(!callback.is_null());
506 Error error;
507 ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply,
508 weak_ptr_factory_.GetWeakPtr(), callback);
509 network_proxy_->Register(selected_network_, &error, cb, kTimeoutRegister);
510 if (error.IsFailure())
511 callback.Run(error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100512}
513
514void CellularCapabilityGSM::RegisterOnNetwork(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500515 const string &network_id,
516 Error *error,
517 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700518 SLOG(Cellular, 2) << __func__ << "(" << network_id << ")";
Eric Shienbrood9a245532012-03-07 14:20:39 -0500519 CHECK(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500520 desired_network_ = network_id;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500521 ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply,
522 weak_ptr_factory_.GetWeakPtr(), callback);
523 network_proxy_->Register(network_id, error, cb, kTimeoutRegister);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500524}
525
Eric Shienbrood9a245532012-03-07 14:20:39 -0500526void CellularCapabilityGSM::OnRegisterReply(const ResultCallback &callback,
527 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700528 SLOG(Cellular, 2) << __func__ << "(" << error << ")";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500529
530 if (error.IsSuccess()) {
531 selected_network_ = desired_network_;
532 desired_network_.clear();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500533 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500534 return;
535 }
536 // If registration on the desired network failed,
537 // try to register on the home network.
538 if (!desired_network_.empty()) {
539 desired_network_.clear();
540 selected_network_.clear();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500541 LOG(INFO) << "Couldn't register on selected network, trying home network";
542 Register(callback);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500543 return;
544 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500545 callback.Run(error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100546}
547
Darin Petkovb72cf402011-11-22 14:51:39 +0100548bool CellularCapabilityGSM::IsRegistered() {
549 return (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
550 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING);
551}
552
Darin Petkovb05315f2011-11-07 10:14:25 +0100553void CellularCapabilityGSM::RequirePIN(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500554 const std::string &pin, bool require,
555 Error *error, const ResultCallback &callback) {
556 CHECK(error);
557 card_proxy_->EnablePIN(pin, require, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100558}
559
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100560void CellularCapabilityGSM::EnterPIN(const string &pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500561 Error *error,
562 const ResultCallback &callback) {
563 CHECK(error);
564 card_proxy_->SendPIN(pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100565}
566
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100567void CellularCapabilityGSM::UnblockPIN(const string &unblock_code,
568 const string &pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500569 Error *error,
570 const ResultCallback &callback) {
571 CHECK(error);
572 card_proxy_->SendPUK(unblock_code, pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100573}
574
575void CellularCapabilityGSM::ChangePIN(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500576 const string &old_pin, const string &new_pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500577 Error *error, const ResultCallback &callback) {
578 CHECK(error);
579 card_proxy_->ChangePIN(old_pin, new_pin, error, callback, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100580}
581
Eric Shienbrood9a245532012-03-07 14:20:39 -0500582void CellularCapabilityGSM::Scan(Error *error, const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700583 SLOG(Cellular, 2) << __func__;
Darin Petkov1272a432011-11-10 15:53:37 +0100584 // TODO(petkov): Defer scan requests if a scan is in progress already.
Eric Shienbrood9a245532012-03-07 14:20:39 -0500585 CHECK(error);
586 ScanResultsCallback cb = Bind(&CellularCapabilityGSM::OnScanReply,
587 weak_ptr_factory_.GetWeakPtr(), callback);
588 network_proxy_->Scan(error, cb, kTimeoutScan);
Darin Petkov1272a432011-11-10 15:53:37 +0100589}
590
Eric Shienbrood9a245532012-03-07 14:20:39 -0500591void CellularCapabilityGSM::OnScanReply(const ResultCallback &callback,
592 const GSMScanResults &results,
593 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700594 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400595
596 // Error handling is weak. The current expectation is that on any
597 // error, found_networks_ should be cleared and a property change
598 // notification sent out.
599 //
600 // TODO(jglasgow): fix error handling
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500601 found_networks_.clear();
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400602 if (!error.IsFailure()) {
603 for (GSMScanResults::const_iterator it = results.begin();
604 it != results.end(); ++it) {
605 found_networks_.push_back(ParseScanResult(*it));
606 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500607 }
Darin Petkovb7828b02012-02-03 12:34:30 +0100608 cellular()->adaptor()->EmitStringmapsChanged(flimflam::kFoundNetworksProperty,
609 found_networks_);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500610 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500611}
612
613Stringmap CellularCapabilityGSM::ParseScanResult(const GSMScanResult &result) {
Darin Petkov1272a432011-11-10 15:53:37 +0100614 Stringmap parsed;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500615 for (GSMScanResult::const_iterator it = result.begin();
616 it != result.end(); ++it) {
Darin Petkov1272a432011-11-10 15:53:37 +0100617 // TODO(petkov): Define these in system_api/service_constants.h. The
618 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
619 static const char * const kStatusString[] = {
620 "unknown",
621 "available",
622 "current",
623 "forbidden",
624 };
625 static const char * const kTechnologyString[] = {
626 flimflam::kNetworkTechnologyGsm,
627 "GSM Compact",
628 flimflam::kNetworkTechnologyUmts,
629 flimflam::kNetworkTechnologyEdge,
630 "HSDPA",
631 "HSUPA",
632 flimflam::kNetworkTechnologyHspa,
633 };
Ben Chanfad4a0b2012-04-18 15:49:59 -0700634 SLOG(Cellular, 2) << "Network property: " << it->first << " = "
635 << it->second;
Darin Petkov1272a432011-11-10 15:53:37 +0100636 if (it->first == kNetworkPropertyStatus) {
637 int status = 0;
638 if (base::StringToInt(it->second, &status) &&
639 status >= 0 &&
640 status < static_cast<int>(arraysize(kStatusString))) {
641 parsed[flimflam::kStatusProperty] = kStatusString[status];
642 } else {
643 LOG(ERROR) << "Unexpected status value: " << it->second;
644 }
645 } else if (it->first == kNetworkPropertyID) {
646 parsed[flimflam::kNetworkIdProperty] = it->second;
647 } else if (it->first == kNetworkPropertyLongName) {
648 parsed[flimflam::kLongNameProperty] = it->second;
649 } else if (it->first == kNetworkPropertyShortName) {
650 parsed[flimflam::kShortNameProperty] = it->second;
651 } else if (it->first == kNetworkPropertyAccessTechnology) {
652 int tech = 0;
653 if (base::StringToInt(it->second, &tech) &&
654 tech >= 0 &&
655 tech < static_cast<int>(arraysize(kTechnologyString))) {
656 parsed[flimflam::kTechnologyProperty] = kTechnologyString[tech];
657 } else {
658 LOG(ERROR) << "Unexpected technology value: " << it->second;
659 }
660 } else {
661 LOG(WARNING) << "Unknown network property ignored: " << it->first;
662 }
663 }
664 // If the long name is not available but the network ID is, look up the long
665 // name in the mobile provider database.
666 if ((!ContainsKey(parsed, flimflam::kLongNameProperty) ||
667 parsed[flimflam::kLongNameProperty].empty()) &&
668 ContainsKey(parsed, flimflam::kNetworkIdProperty)) {
669 mobile_provider *provider =
670 mobile_provider_lookup_by_network(
671 cellular()->provider_db(),
672 parsed[flimflam::kNetworkIdProperty].c_str());
673 if (provider) {
674 const char *long_name = mobile_provider_get_name(provider);
675 if (long_name && *long_name) {
676 parsed[flimflam::kLongNameProperty] = long_name;
677 }
678 }
679 }
680 return parsed;
681}
682
Darin Petkovae0c64e2011-11-15 15:50:27 +0100683void CellularCapabilityGSM::SetAccessTechnology(uint32 access_technology) {
684 access_technology_ = access_technology;
685 if (cellular()->service().get()) {
Darin Petkovb72cf402011-11-22 14:51:39 +0100686 cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100687 }
688}
689
Darin Petkov20c13ec2011-11-09 15:07:15 +0100690string CellularCapabilityGSM::GetNetworkTechnologyString() const {
Darin Petkovb72cf402011-11-22 14:51:39 +0100691 switch (access_technology_) {
692 case MM_MODEM_GSM_ACCESS_TECH_GSM:
693 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
694 return flimflam::kNetworkTechnologyGsm;
695 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
696 return flimflam::kNetworkTechnologyGprs;
697 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
698 return flimflam::kNetworkTechnologyEdge;
699 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
700 return flimflam::kNetworkTechnologyUmts;
701 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
702 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
703 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
704 return flimflam::kNetworkTechnologyHspa;
705 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
706 return flimflam::kNetworkTechnologyHspaPlus;
707 default:
708 break;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100709 }
710 return "";
711}
712
713string CellularCapabilityGSM::GetRoamingStateString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100714 switch (registration_state_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100715 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
716 return flimflam::kRoamingStateHome;
717 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
718 return flimflam::kRoamingStateRoaming;
719 default:
720 break;
721 }
722 return flimflam::kRoamingStateUnknown;
723}
724
Jason Glasgow4c0724a2012-04-17 15:47:40 -0400725void CellularCapabilityGSM::OnDBusPropertiesChanged(
726 const string &interface,
727 const DBusPropertiesMap &properties,
728 const vector<string> &/* invalidated_properties */) {
729 if (interface != MM_MODEM_INTERFACE)
730 return;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100731 uint32 access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
732 if (DBusProperties::GetUint32(properties,
733 kPropertyAccessTechnology,
734 &access_technology)) {
735 SetAccessTechnology(access_technology);
736 }
Darin Petkov63138a92012-02-06 14:09:15 +0100737 bool emit = false;
738 uint32 locks = 0;
739 if (DBusProperties::GetUint32(
740 properties, kPropertyEnabledFacilityLocks, &locks)) {
741 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
742 emit = true;
743 }
744 if (DBusProperties::GetString(
745 properties, kPropertyUnlockRequired, &sim_lock_status_.lock_type)) {
746 emit = true;
747 }
748 if (DBusProperties::GetUint32(
749 properties, kPropertyUnlockRetries, &sim_lock_status_.retries_left)) {
750 emit = true;
751 }
752 if (emit) {
753 cellular()->adaptor()->EmitKeyValueStoreChanged(
754 flimflam::kSIMLockStatusProperty, SimLockStatusToProperty(NULL));
755 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100756}
757
Eric Shienbrood9a245532012-03-07 14:20:39 -0500758void CellularCapabilityGSM::OnNetworkModeSignal(uint32 /*mode*/) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100759 // TODO(petkov): Implement this.
760 NOTIMPLEMENTED();
761}
762
Eric Shienbrood9a245532012-03-07 14:20:39 -0500763void CellularCapabilityGSM::OnRegistrationInfoSignal(
764 uint32 status, const string &operator_code, const string &operator_name) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700765 SLOG(Cellular, 2) << __func__ << ": regstate=" << status
766 << ", opercode=" << operator_code
767 << ", opername=" << operator_name;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500768 registration_state_ = status;
769 serving_operator_.SetCode(operator_code);
770 serving_operator_.SetName(operator_name);
771 UpdateOperatorInfo();
772 cellular()->HandleNewRegistrationState();
Darin Petkov184c54e2011-11-15 12:44:39 +0100773}
774
Eric Shienbrood9a245532012-03-07 14:20:39 -0500775void CellularCapabilityGSM::OnSignalQualitySignal(uint32 quality) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100776 cellular()->HandleNewSignalQuality(quality);
777}
778
Eric Shienbrood9a245532012-03-07 14:20:39 -0500779void CellularCapabilityGSM::OnGetRegistrationInfoReply(
780 uint32 status, const string &operator_code, const string &operator_name,
781 const Error &error) {
782 if (error.IsSuccess())
783 OnRegistrationInfoSignal(status, operator_code, operator_name);
784}
785
786void CellularCapabilityGSM::OnGetSignalQualityReply(uint32 quality,
787 const Error &error) {
788 if (error.IsSuccess())
789 OnSignalQualitySignal(quality);
790}
791
792void CellularCapabilityGSM::OnGetIMEIReply(const ResultCallback &callback,
793 const string &imei,
794 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500795 if (error.IsSuccess()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700796 SLOG(Cellular, 2) << "IMEI: " << imei;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500797 imei_ = imei;
798 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700799 SLOG(Cellular, 2) << "GetIMEI failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500800 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500801 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500802}
803
Eric Shienbrood9a245532012-03-07 14:20:39 -0500804void CellularCapabilityGSM::OnGetIMSIReply(const ResultCallback &callback,
805 const string &imsi,
806 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500807 if (error.IsSuccess()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700808 SLOG(Cellular, 2) << "IMSI: " << imsi;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500809 imsi_ = imsi;
810 SetHomeProvider();
811 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700812 SLOG(Cellular, 2) << "GetIMSI failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500813 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500814 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500815}
816
Eric Shienbrood9a245532012-03-07 14:20:39 -0500817void CellularCapabilityGSM::OnGetSPNReply(const ResultCallback &callback,
818 const string &spn,
819 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500820 if (error.IsSuccess()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700821 SLOG(Cellular, 2) << "SPN: " << spn;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500822 spn_ = spn;
823 SetHomeProvider();
824 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700825 SLOG(Cellular, 2) << "GetSPN failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500826 }
Thieu Le923006b2012-04-05 16:32:58 -0700827 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500828}
829
Eric Shienbrood9a245532012-03-07 14:20:39 -0500830void CellularCapabilityGSM::OnGetMSISDNReply(const ResultCallback &callback,
831 const string &msisdn,
832 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500833 if (error.IsSuccess()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700834 SLOG(Cellular, 2) << "MSISDN: " << msisdn;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500835 mdn_ = msisdn;
836 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700837 SLOG(Cellular, 2) << "GetMSISDN failed - " << error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500838 }
Thieu Le923006b2012-04-05 16:32:58 -0700839 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500840}
841
Darin Petkovdaf43862011-10-27 11:37:28 +0200842} // namespace shill